Flutter
Il pacchetto kavchat_flutter aggiunge alla tua app Flutter una chat di assistenza basata su script: pulsanti, riconoscimento del testo libero, un modulo che apre un ticket, una copia del bot che funziona anche offline e un layout da destra a sinistra per ebraico e arabo.
Installazione
dependencies:
kavchat_flutter: ^0.0.11Il pacchetto include http, shared_preferences (cache della versione e conversazione salvata) e url_launcher (link negli script). Per aprire i link tel: su Android 11 e versioni successive, aggiungi a AndroidManifest.xml una voce <queries> per lo schema tel e un'altra per https per i link ai siti web (vedi il README di url_launcher). Su iOS, LSApplicationQueriesSchemes serve solo se chiami direttamente canLaunchUrl.
Utilizzo
final kavchat = KavchatController(
publicKey: 'pk_live_...',
// apiBase: 'https://api.kavchat.com', // default
// locale: 'he', // default: device language if translated, else the bot language
onScreen: (screen, targetId) => navigatorKey.currentState?.pushNamed('/$screen', arguments: targetId),
);
Scaffold(
floatingActionButton: KavchatLauncher(controller: kavchat), // hidden while the bot is off
);
// or open it yourself
showKavchat(context, kavchat);
// or embed the screen in your own route
KavchatChat(controller: kavchat, onClose: () => Navigator.pop(context));Crea il controller una sola volta (per esempio in uno State o in un provider) e chiama dispose() quando viene eliminato il componente che lo contiene.
KavchatLauncher è un FloatingActionButton: posizionalo con Scaffold.floatingActionButtonLocation. L'impostazione kavchat.settings?.position (start o end) indica il lato scelto nel pannello di controllo.
Se nel pannello di gestione è configurato un messaggio accanto al pulsante della chat (un fumetto, un testo curvo sopra il pulsante, il pulsante stesso che si allunga a forma di capsula e parla oppure una linea che sale dal pulsante e mostra le prime opzioni del bot), KavchatLauncher lo mostra dopo il ritardo impostato, al massimo una volta al giorno. Toccando un'opzione sulla linea, la chat si apre con quell'opzione selezionata, come se fosse stata scelta nella chat. Chiudere il messaggio o aprire la chat nasconde il messaggio fino al giorno successivo. Il messaggio non viene mostrato mentre la chat è aperta. Se sul dispositivo è attiva la riduzione del movimento, il messaggio viene mostrato senza animazioni. Quando è attiva l'opzione "Non mostrare sui telefoni", il messaggio appare solo sui tablet (con il lato più corto dello schermo di almeno 600 punti). Sui telefoni, la linea mostra fino a due opzioni. KavchatLauncher(controller: kavchat, attention: false) disattiva il messaggio.
Quando l'icona del pulsante nel tema è un volto, ogni tanto sbatte le palpebre mentre il pulsante è inattivo. Il volto non sbatte le palpebre se la chat è aperta, se l'app è in background o se è attiva la riduzione del movimento.
Il bot non viene mostrato (il pulsante flottante non appare e KavchatChat mostra "Non disponibile") quando la versione ha enabled: false: il bot è disattivato, è disponibile solo per gli utenti di test e l'utente non è tra questi, oppure la quota è esaurita (reason: 'quota').
Token di identità
Per gli utenti che hanno effettuato l'accesso, firma un JWT di breve durata sul tuo server con la chiave segreta (mai nell'app, vedi Identificazione degli utenti) e passalo così:
KavchatController(publicKey: 'pk_live_...', userToken: jwt, userName: 'Dana');
await kavchat.setUser(token: newJwt, name: 'Dana'); // after login
await kavchat.setUser(token: null); // after logoutIl token viene inviato nell'header Authorization: Bearer <token> a ogni chiamata. Con un token, il modulo di contatto non richiede email o telefono e il gruppo degli utenti di test riconosce l'utente. setUser ricarica la versione e un utente diverso avvia una nuova conversazione: una conversazione salvata sul dispositivo non passa mai a un altro account.
Link, schermate e modulo di contatto
- I pulsanti di tipo
linksi aprono conurl_launcher, solo per gli indirizzihttps:etel:. Nei messaggi del bot sono ammessi solo linkhttps:. - I pulsanti di tipo
screenchiamanoonScreen(screen, targetId). Senza questa funzione non fanno nulla. - Il pulsante "Contatta il team" apre il modulo integrato (nome, email, telefono, oggetto e messaggio, con la conversazione allegata) e dopo l'invio mostra il numero del ticket.
Elenco delle schermate nell'editor
Dichiara una sola volta le schermate che l'app può aprire in KavchatController(screens: ...). L'SDK invia automaticamente l'elenco a Kavchat e l'editor degli script propone queste schermate in un menu a discesa con i loro nomi, al posto di un campo di testo libero. L'editor richiede anche l'identificativo dell'elemento quando una schermata ne ha bisogno e segnala i pulsanti che rimandano a schermate non dichiarate. Non serve inserire manualmente l'elenco delle schermate nel pannello di controllo.
final kavchat = KavchatController(
publicKey: 'pk_live_...',
screens: const [
KavchatScreen(id: 'orders', label: 'My orders'),
KavchatScreen(id: 'product', label: 'Product page', needsTarget: true), // the button carries a targetId
],
onScreen: (screen, targetId) => navigatorKey.currentState?.pushNamed('/$screen', arguments: targetId),
);
// later, to replace the list: await kavchat.registerScreens([...]);idè il valore ricevuto daonScreen: lettere latine, cifre,_,.e-, fino a 40 caratteri.labelè il nome visualizzato dall'amministratore, fino a 60 caratteri. Sono consentite fino a 100 schermate. Le voci non valide e gli identificativi duplicati vengono scartati.needsTarget: il pulsante contiene anche un identificativo dell'elemento (per esempio l'ID di un prodotto), che viene passato aonScreencometargetId.- L'elenco viene inviato in background dopo il caricamento della versione, solo quando è cambiato o una volta alla settimana. Un eventuale errore non viene mostrato e l'invio viene ritentato al prossimo avvio. L'utente non vede nulla.
- Le schermate registrate appaiono nel pannello di controllo sotto Bot, Impostazioni, "Schermate dell'app", insieme alle piattaforme che hanno segnalato ciascuna schermata. Da lì puoi eliminare una schermata rimossa dall'app.
RTL
La chat imposta la propria Directionality in base alla lingua dell'interfaccia: da destra a sinistra per he e ar, da sinistra a destra per tutte le altre. Non cambia la direzione della tua app. Anche ogni fumetto sceglie la propria direzione in base alla prima lettera con direzionalità forte, così i contenuti misti si leggono correttamente. La lingua dell'interfaccia e quella dello script sono separate: un bot in inglese può mostrare pulsanti in arabo, come "Indietro", quando è impostato locale: 'ar'.
Colori e branding
I colori derivano dall'impostazione del bot primaryColor. Il testo su questo colore è nero o bianco in base al contrasto WCAG; un colore troppo chiaro viene sostituito con uno scuro dove viene usato per il testo. Per modificare i colori:
KavchatLauncher(controller: kavchat, theme: KavchatThemeData.fromColor(const Color(0xFF0F766E)));
KavchatChat(controller: kavchat, theme: KavchatThemeData.fromHex('#0f766e').copyWith(background: Colors.white));Il badge "Powered by Kavchat by maxsave" appare in tutti i piani, con un link a kavchat.com. Con Premium puoi nasconderlo nelle impostazioni del bot.
Chat con un operatore
Non serve alcuna configurazione per iniziare. Quando attivi la chat con gli operatori nel pannello di gestione, l'opzione compare nella chat dell'app esattamente come nel widget per il sito.
- L'opzione: "Parla con un operatore" compare prima di "Contatta il team", solo dopo che il server ha confermato la disponibilità di un operatore. La disponibilità viene verificata di nuovo quando si tocca il pulsante. Fuori dall'orario di servizio o quando tutti gli operatori sono occupati, viene mostrato solo il modulo di contatto, con una breve spiegazione e, se noto, l'orario in cui il team tornerà disponibile. Quando la quota mensile è esaurita, il modulo viene mostrato senza spiegazioni.
- La richiesta: gli ospiti lasciano un'email o un numero di telefono, nel caso in cui nessun operatore si liberi in tempo. Possono aggiungere anche un nome e un primo messaggio. Se è disponibile più di un reparto, ne scelgono uno. Gli utenti identificati (
userToken) non devono inserire i recapiti. Se nessun operatore può accettare la chat, si apre il modulo di contatto con i dati già inseriti. - L'attesa: viene mostrato "In attesa di un operatore" con un conto alla rovescia fino alla fine del tempo di attesa che hai impostato, insieme ai pulsanti "Lascia un messaggio" e "Termina la chat". È possibile scrivere già durante l'attesa. Allo scadere del tempo, la conversazione diventa automaticamente un ticket. Vengono mostrati il numero del ticket e una spiegazione che indica che nessun operatore si è liberato in tempo.
- La conversazione: nome dell'operatore, messaggi, indicatore di digitazione, trasferimento a un altro operatore e chiusura della chat. Tutto ciò che arriva dal server viene mostrato come testo semplice, senza link.
- In tempo reale: una connessione Server-Sent Events tramite una risposta
httpin streaming. Se la connessione si interrompe, la chat si riconnette a intervalli crescenti e recupera tutto ciò che ha perso. In questo modo nessun messaggio va perso o compare due volte. Sulle reti che bloccano questa connessione e su Flutter Web, la chat usa richieste ripetute (long-poll). Ogni messaggio ha un identificativo, quindi un nuovo tentativo non crea duplicati. Un messaggio non inviato viene segnalato e puoi inviarlo di nuovo con un tocco. - Background e riavvio: quando l'app passa in background (
paused,hidden), la connessione viene chiusa. Quando torna in primo piano (resumed), la chat recupera ciò che ha perso. La credenziale di accesso alla chat è valida per un massimo di 12 ore o fino al termine della conversazione e viene salvata nello spazio di archiviazione che scegli. Così, dopo il riavvio dell'app, una conversazione ancora aperta torna sullo schermo. La credenziale non viene salvata nell'URL né scritta nei log. - Nessuna notifica push in questa versione: i messaggi dell'operatore arrivano solo mentre l'app è aperta.
Ti consigliamo di salvare la credenziale di accesso in un archivio sicuro (Keychain su iOS, Keystore su Android), per esempio con flutter_secure_storage. Se non configuri secureStorage, la credenziale viene salvata nello stesso archivio della conversazione. Un tuo pulsante per parlare con un operatore apre il modulo di richiesta quando un operatore è disponibile. Se non ce ne sono, si apre il modulo di contatto con la spiegazione:
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class SecureKavchatStorage implements KavchatStorage {
final _s = const FlutterSecureStorage();
@override
Future<String?> read(String key) => _s.read(key: key);
@override
Future<void> write(String key, String value) => _s.write(key: key, value: value);
@override
Future<void> remove(String key) => _s.delete(key: key);
}
final kavchat = KavchatController(
publicKey: 'pk_live_...',
secureStorage: SecureKavchatStorage(),
livePage: 'checkout',
onLivePhase: (phase) => debugPrint('live chat: $phase'),
);
// your own button
FilledButton(onPressed: kavchat.openLive, child: const Text('Chat with us'));La stessa logica, senza Flutter, si trova in kavchat_engine (KavchatClient, LiveSession e la macchina a stati condivisa liveApplyEvent, liveLines e liveStatus, che supera gli stessi vettori di test del widget per il sito).
Domande, condizioni e lead
Non serve configurare nulla nell'app. Uno script può chiedere dati (nome, telefono, email, un numero o un testo), decidere come proseguire in base a condizioni (Premium) e inviare un lead. Tutto viene eseguito sul dispositivo.
- La tastiera giusta: quando il bot attende una risposta, il campo di testo mostra una tastiera per telefono, email o numeri, con completamento automatico. Se la risposta non è valida, il bot spiega cosa manca e il campo viene evidenziato. Per le domande facoltative compare il pulsante "Salta".
- Lead: quando è presente un testo per il consenso, compaiono i pulsanti "Invia" e "No, grazie". Se manca la connessione di rete, il lead viene salvato sul dispositivo e inviato quando la connessione torna disponibile, senza duplicati.
- Precompilazione: le risposte già fornite dall'utente compilano il modulo di contatto e il modulo di richiesta per parlare con un operatore e vengono allegate al ticket e alla chat con l'operatore. Nome, email e telefono presenti nel token di identità sono considerati risposte già note e il bot non li chiede di nuovo.
- Schermata corrente:
livePageindica anche la schermata verificata dalle condizioni e inviata insieme ai lead. Quando l'utente passa a un'altra schermata, chiamasetPage('checkout').
Risposte AI (Premium)
Non serve configurare nulla nell'app. Quando attivi le risposte AI nel pannello di gestione (con la tua chiave di un fornitore AI), una domanda a cui nessuno script risponde viene inviata a Kavchat. Durante l'attesa, fino a 20 secondi, la chat mostra che il bot sta scrivendo. La risposta appare come testo semplice con una piccola etichetta "Risposta AI" nella lingua dell'interfaccia, seguita da un pulsante per un argomento correlato, se presente, e dal pulsante "Contatta il team".
Se non c'è una risposta o se la richiesta fallisce, impiega troppo tempo o supera il limite (10 risposte per conversazione ogni 15 minuti), la chat mostra il consueto messaggio "Non ho trovato una risposta". La domanda compare comunque nel report delle domande senza risposta e le risposte AI vengono conservate nella conversazione salvata come qualsiasi altro messaggio.
Funzionamento offline e cache
La versione viene salvata nella cache con il suo ETag (If-None-Match, 304). In assenza di rete o in caso di errore del server, viene usata la copia salvata e un messaggio lo segnala. La conversazione viene salvata per ciascun bot e ripristinata per 24 ore, purché la versione non sia cambiata. Il percorso della conversazione viene comunicato al server 2 secondi dopo l'ultima azione e anche quando l'app passa in background.