feat: Add app-version to Chatwoot Contact Attributes (#2049)

This commit is contained in:
Konstantin Ullrich 2025-02-24 23:01:58 +01:00 committed by GitHub
parent d1de481558
commit 465ff7e78c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 26 deletions

View file

@ -1256,7 +1256,7 @@ Future<void> setup({
getIt.registerFactoryParam<OrderDetailsPage, Order, void>( getIt.registerFactoryParam<OrderDetailsPage, Order, void>(
(Order order, _) => OrderDetailsPage(getIt.get<OrderDetailsViewModel>(param1: order))); (Order order, _) => OrderDetailsPage(getIt.get<OrderDetailsViewModel>(param1: order)));
getIt.registerFactory(() => SupportViewModel()); getIt.registerFactory(() => SupportViewModel(getIt.get<SettingsStore>()));
getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>())); getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>()));
@ -1418,4 +1418,4 @@ Future<void> setup({
getIt.registerFactory(() => SeedVerificationPage(getIt.get<WalletSeedViewModel>())); getIt.registerFactory(() => SeedVerificationPage(getIt.get<WalletSeedViewModel>()));
_isSetupFinished = true; _isSetupFinished = true;
} }

View file

@ -3,10 +3,8 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart'; import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart';
import 'package:cake_wallet/view_model/support_view_model.dart'; import 'package:cake_wallet/view_model/support_view_model.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SupportChatPage extends BasePage { class SupportChatPage extends BasePage {
SupportChatPage(this.supportViewModel, {required this.secureStorage}); SupportChatPage(this.supportViewModel, {required this.secureStorage});
@ -23,17 +21,16 @@ class SupportChatPage extends BasePage {
Widget body(BuildContext context) => FutureBuilder<String>( Widget body(BuildContext context) => FutureBuilder<String>(
future: getCookie(), future: getCookie(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) { builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
printV(snapshot.data);
if (snapshot.hasData) if (snapshot.hasData)
return ChatwootWidget( return ChatwootWidget(
secureStorage, secureStorage,
supportUrl: supportViewModel.fetchUrl(authToken: snapshot.data!) supportUrl: supportViewModel.fetchUrl(authToken: snapshot.data!),
appVersion: supportViewModel.appVersion,
); );
return Container(); return Container();
}, },
); );
Future<String> getCookie() async { Future<String> getCookie() async =>
return await secureStorage.read(key: COOKIE_KEY) ?? ""; await secureStorage.read(key: COOKIE_KEY) ?? "";
}
} }

View file

@ -1,46 +1,50 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
const COOKIE_KEY = 'chatwootCookie'; const COOKIE_KEY = 'chatwootCookie';
class ChatwootWidget extends StatefulWidget { class ChatwootWidget extends StatefulWidget {
ChatwootWidget(this.secureStorage, {required this.supportUrl}); const ChatwootWidget(
this.secureStorage, {
required this.supportUrl,
required this.appVersion,
});
final SecureStorage secureStorage; final SecureStorage secureStorage;
final String supportUrl; final String supportUrl;
final String appVersion;
@override @override
ChatwootWidgetState createState() => ChatwootWidgetState(); ChatwootWidgetState createState() => ChatwootWidgetState();
} }
class ChatwootWidgetState extends State<ChatwootWidget> { class ChatwootWidgetState extends State<ChatwootWidget> {
final GlobalKey _webViewkey = GlobalKey(); final GlobalKey _webViewKey = GlobalKey();
@override @override
Widget build(BuildContext context) => InAppWebView( Widget build(BuildContext context) => InAppWebView(
key: _webViewkey, key: _webViewKey,
initialSettings: InAppWebViewSettings( initialSettings: InAppWebViewSettings(transparentBackground: true),
transparentBackground: true,
),
initialUrlRequest: URLRequest(url: WebUri(widget.supportUrl)), initialUrlRequest: URLRequest(url: WebUri(widget.supportUrl)),
onWebViewCreated: (InAppWebViewController controller) { onWebViewCreated: (InAppWebViewController controller) {
controller.addWebMessageListener( controller.addWebMessageListener(
WebMessageListener( WebMessageListener(
jsObjectName: 'ReactNativeWebView', jsObjectName: 'ReactNativeWebView',
onPostMessage: (WebMessage? message, WebUri? sourceOrigin, bool isMainFrame, onPostMessage: (WebMessage? message, WebUri? sourceOrigin,
PlatformJavaScriptReplyProxy replyProxy) { bool isMainFrame, PlatformJavaScriptReplyProxy replyProxy) {
final shortenedMessage = message?.data.toString().substring(16); final shortenedMessage = message?.data.toString().substring(16);
if (shortenedMessage != null && isJsonString(shortenedMessage)) { if (shortenedMessage != null &&
_isJsonString(shortenedMessage)) {
final parsedMessage = jsonDecode(shortenedMessage); final parsedMessage = jsonDecode(shortenedMessage);
final eventType = parsedMessage["event"]; final eventType = parsedMessage["event"];
if (eventType == 'loaded') { if (eventType == 'loaded') {
final authToken = parsedMessage["config"]["authToken"]; final authToken = parsedMessage["config"]["authToken"];
printV(authToken); _storeCookie(authToken as String);
storeCookie(authToken as String); _setCustomAttributes(
controller, {"app_version": widget.appVersion});
} }
} }
}, },
@ -49,7 +53,7 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
}, },
); );
bool isJsonString(String str) { bool _isJsonString(String str) {
try { try {
jsonDecode(str); jsonDecode(str);
} catch (e) { } catch (e) {
@ -58,7 +62,24 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
return true; return true;
} }
Future<void> storeCookie(String value) async { /// Add additional contact attributes to the chatwoot chat.
await widget.secureStorage.write(key: COOKIE_KEY, value: value); /// IMPORTANT: You have to add the attribute key in the chatwoot settings
/// under: settings/custom-attributes
Future<void> _setCustomAttributes(
InAppWebViewController controller,
Map<String, dynamic> customAttributes,
) {
final attributeObject = {
"event": "set-custom-attributes",
"customAttributes": customAttributes,
};
return controller.postWebMessage(
message: WebMessage(
data: "chatwoot-widget:${jsonEncode(attributeObject)}",
),
);
} }
Future<void> _storeCookie(String value) =>
widget.secureStorage.write(key: COOKIE_KEY, value: value);
} }

View file

@ -1,16 +1,19 @@
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/view_model/settings/link_list_item.dart'; import 'package:cake_wallet/view_model/settings/link_list_item.dart';
import 'package:cake_wallet/view_model/settings/settings_list_item.dart'; import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
part 'support_view_model.g.dart'; part 'support_view_model.g.dart';
class SupportViewModel = SupportViewModelBase with _$SupportViewModel; class SupportViewModel = SupportViewModelBase with _$SupportViewModel;
abstract class SupportViewModelBase with Store { abstract class SupportViewModelBase with Store {
SupportViewModelBase() final SettingsStore settingsStore;
SupportViewModelBase(this.settingsStore)
: items = [ : items = [
LinkListItem( LinkListItem(
title: 'Email', title: 'Email',
@ -116,5 +119,8 @@ abstract class SupportViewModelBase with Store {
return supportUrl; return supportUrl;
} }
String get appVersion =>
"${isMoneroOnly ? "Monero.com" : "Cake Wallet"} - ${settingsStore.appVersion}";
List<SettingsListItem> items; List<SettingsListItem> items;
} }