| 1 | import 'dart:convert'; |
| 2 | |
| 3 | import 'package:cake_wallet/core/secure_storage.dart'; |
| 4 | import 'package:flutter/material.dart'; |
| 5 | import 'package:flutter_inappwebview/flutter_inappwebview.dart'; |
| 6 | |
| 7 | const COOKIE_KEY = 'chatwootCookie'; |
| 8 | |
| 9 | class ChatwootWidget extends StatefulWidget { |
| 10 | const ChatwootWidget( |
| 11 | this.secureStorage, { |
| 12 | required this.supportUrl, |
| 13 | required this.appVersion, |
| 14 | required this.fiatApiMode, |
| 15 | required this.walletType, |
| 16 | required this.walletSyncState, |
| 17 | required this.builtInTorState, |
| 18 | }); |
| 19 | |
| 20 | final SecureStorage secureStorage; |
| 21 | final String supportUrl; |
| 22 | final String appVersion; |
| 23 | final String fiatApiMode; |
| 24 | final String walletType; |
| 25 | final String walletSyncState; |
| 26 | final String builtInTorState; |
| 27 | |
| 28 | @override |
| 29 | ChatwootWidgetState createState() => ChatwootWidgetState(); |
| 30 | } |
| 31 | |
| 32 | class ChatwootWidgetState extends State<ChatwootWidget> { |
| 33 | final GlobalKey _webViewKey = GlobalKey(); |
| 34 | |
| 35 | @override |
| 36 | Widget build(BuildContext context) => InAppWebView( |
| 37 | key: _webViewKey, |
| 38 | initialSettings: InAppWebViewSettings(transparentBackground: true), |
| 39 | initialUrlRequest: URLRequest(url: WebUri(widget.supportUrl)), |
| 40 | onWebViewCreated: (InAppWebViewController controller) { |
| 41 | controller.addWebMessageListener( |
| 42 | WebMessageListener( |
| 43 | jsObjectName: 'ReactNativeWebView', |
| 44 | onPostMessage: (WebMessage? message, WebUri? sourceOrigin, bool isMainFrame, |
| 45 | PlatformJavaScriptReplyProxy replyProxy) { |
| 46 | final shortenedMessage = message?.data.toString().substring(16); |
| 47 | if (shortenedMessage != null && _isJsonString(shortenedMessage)) { |
| 48 | final parsedMessage = jsonDecode(shortenedMessage); |
| 49 | final eventType = parsedMessage["event"]; |
| 50 | if (eventType == 'loaded') { |
| 51 | final authToken = parsedMessage["config"]["authToken"]; |
| 52 | _storeCookie(authToken as String); |
| 53 | _setCustomAttributes(controller, { |
| 54 | "app_version": widget.appVersion, |
| 55 | "fiat_api_mode": widget.fiatApiMode, |
| 56 | "wallet_type": widget.walletType, |
| 57 | "wallet_sync_state": widget.walletSyncState, |
| 58 | "built_in_tor": widget.builtInTorState, |
| 59 | }); |
| 60 | } |
| 61 | } |
| 62 | }, |
| 63 | ), |
| 64 | ); |
| 65 | }, |
| 66 | ); |
| 67 | |
| 68 | bool _isJsonString(String str) { |
| 69 | try { |
| 70 | jsonDecode(str); |
| 71 | } catch (e) { |
| 72 | return false; |
| 73 | } |
| 74 | return true; |
| 75 | } |
| 76 | |
| 77 | /// Add additional contact attributes to the chatwoot chat. |
| 78 | /// IMPORTANT: You have to add the attribute key in the chatwoot settings |
| 79 | /// under: settings/custom-attributes |
| 80 | Future<void> _setCustomAttributes( |
| 81 | InAppWebViewController controller, |
| 82 | Map<String, dynamic> customAttributes, |
| 83 | ) { |
| 84 | final attributeObject = { |
| 85 | "event": "set-custom-attributes", |
| 86 | "customAttributes": customAttributes, |
| 87 | }; |
| 88 | return controller.postWebMessage( |
| 89 | message: WebMessage( |
| 90 | data: "chatwoot-widget:${jsonEncode(attributeObject)}", |
| 91 | ), |
| 92 | ); |
| 93 | } |
| 94 | |
| 95 | Future<void> _storeCookie(String value) => |
| 96 | widget.secureStorage.write(key: COOKIE_KEY, value: value); |
| 97 | } |