Re add chatwoot (#1044)

* Revert "Revert "Cw 397 chatwoot live support (#1011)""

This reverts commit ecdc7baa2e3c8f46c3c5013f56c8b864f088ec9f.

* Re-add chatwoot
Change chatwoot base url
This commit is contained in:
Omar Hatem
2023-08-15 03:47:25 +03:00
committed by GitHub
parent ad6edd9a05
commit 5ec930cbc6
63 changed files with 762 additions and 260 deletions
@@ -2,12 +2,10 @@ import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/utils/language_list.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart';
import 'package:flutter/cupertino.dart';
@@ -1,12 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class RestoreButton extends StatelessWidget {
const RestoreButton({
required this.onPressed,
required this.image,
required this.title,
required this.description});
const RestoreButton(
{required this.onPressed,
required this.image,
required this.title,
required this.description});
final VoidCallback onPressed;
final Image image;
@@ -24,10 +23,7 @@ class RestoreButton extends StatelessWidget {
alignment: Alignment.topLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(12)),
color: Theme.of(context)
.accentTextTheme!
.bodySmall!
.color!,
color: Theme.of(context).accentTextTheme.bodySmall!.color!,
),
child: Row(
mainAxisSize: MainAxisSize.max,
@@ -49,7 +45,7 @@ class RestoreButton extends StatelessWidget {
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.primaryTextTheme!
.primaryTextTheme
.titleLarge!
.color!),
),
@@ -61,7 +57,7 @@ class RestoreButton extends StatelessWidget {
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context)
.primaryTextTheme!
.primaryTextTheme
.labelSmall!
.color!),
),
@@ -6,7 +6,6 @@ class SettingsCellWithArrow extends StandardListRow {
: super(title: title, isSelected: false, onTap: handler);
@override
Widget buildTrailing(BuildContext context) =>
Image.asset('assets/images/select_arrow.png',
color: Theme.of(context).primaryTextTheme!.labelSmall!.color!);
}
Widget buildTrailing(BuildContext context) => Image.asset('assets/images/select_arrow.png',
color: Theme.of(context).primaryTextTheme.labelSmall!.color!);
}
+61 -38
View File
@@ -1,55 +1,78 @@
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/settings/link_list_item.dart';
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/support/widgets/support_tiles.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/view_model/support_view_model.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:url_launcher/url_launcher.dart';
class SupportPage extends BasePage {
SupportPage(this.supportViewModel);
final SupportViewModel supportViewModel;
final imageLiveSupport = Image.asset('assets/images/live_support.png');
final imageWalletGuides = Image.asset('assets/images/wallet_guides.png');
final imageMoreLinks = Image.asset('assets/images/more_links.png');
@override
String get title => S.current.settings_support;
@override
AppBarStyle get appBarStyle => AppBarStyle.regular;
@override
Widget body(BuildContext context) {
final iconColor = Theme.of(context)
.accentTextTheme!
.displayLarge!
.backgroundColor!;
// FIX-ME: Added `context` it was not used here before, maby bug ?
return Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: SectionStandardList(
context: context,
sectionCount: 1,
itemCounter: (int _) => supportViewModel.items.length,
itemBuilder: (_, __, index) {
final item = supportViewModel.items[index];
if (item is RegularListItem) {
return SettingsCellWithArrow(title: item.title, handler: item.handler);
}
if (item is LinkListItem) {
return SettingsLinkProviderCell(
title: item.title,
icon: item.icon,
iconColor: item.hasIconColor ? iconColor : null,
link: item.link,
linkTitle: item.linkTitle);
}
return Container();
}),
return Container(
child: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 330),
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 24),
child: SupportTile(
image: imageLiveSupport,
title: S.of(context).support_title_live_chat,
description: S.of(context).support_description_live_chat,
onPressed: () {
if (DeviceInfo.instance.isDesktop) {
_launchUrl(supportViewModel.fetchUrl());
} else {
Navigator.pushNamed(context, Routes.supportLiveChat);
}
},
),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: SupportTile(
image: imageWalletGuides,
title: S.of(context).support_title_guides,
description: S.of(context).support_description_guides,
onPressed: () => _launchUrl(supportViewModel.guidesUrl),
),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: SupportTile(
image: imageMoreLinks,
title: S.of(context).support_title_other_links,
description: S.of(context).support_description_other_links,
onPressed: () => Navigator.pushNamed(context, Routes.supportOtherLinks),
),
),
],
),
),
),
);
}
void _launchUrl(String url) async {
try {
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
} catch (e) {}
}
}
@@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
class SupportTile extends StatelessWidget {
const SupportTile(
{required this.onPressed,
required this.image,
required this.title,
required this.description});
final VoidCallback onPressed;
final Image image;
final String title;
final String description;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onPressed,
child: Container(
width: double.infinity,
padding: EdgeInsets.all(24),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(12)),
color: Theme.of(context).accentTextTheme.bodySmall!.color!,
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
image,
Expanded(
child: Padding(
padding: EdgeInsets.only(left: 16),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
description,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Theme.of(context).primaryTextTheme.labelSmall!.color!,
),
),
)
],
),
),
)
],
),
),
);
}
}
@@ -0,0 +1,38 @@
import 'package:cake_wallet/generated/i18n.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/view_model/support_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class SupportChatPage extends BasePage {
SupportChatPage(this.supportViewModel, {required this.secureStorage});
final SupportViewModel supportViewModel;
final FlutterSecureStorage secureStorage;
@override
String get title => S.current.settings_support;
@override
AppBarStyle get appBarStyle => AppBarStyle.regular;
@override
Widget body(BuildContext context) => FutureBuilder<String>(
future: getCookie(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
print(snapshot.data);
if (snapshot.hasData)
return ChatwootWidget(
secureStorage,
supportUrl: supportViewModel.fetchUrl(authToken: snapshot.data!)
);
return Container();
},
);
Future<String> getCookie() async {
return await secureStorage.read(key: COOKIE_KEY) ?? "";
}
}
@@ -0,0 +1,62 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
const COOKIE_KEY = 'chatwootCookie';
class ChatwootWidget extends StatefulWidget {
ChatwootWidget(this.secureStorage, {required this.supportUrl});
final FlutterSecureStorage secureStorage;
final String supportUrl;
@override
ChatwootWidgetState createState() => ChatwootWidgetState();
}
class ChatwootWidgetState extends State<ChatwootWidget> {
final GlobalKey _webViewkey = GlobalKey();
@override
Widget build(BuildContext context) => InAppWebView(
key: _webViewkey,
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(transparentBackground: true),
),
initialUrlRequest: URLRequest(url: Uri.tryParse(widget.supportUrl)),
onWebViewCreated: (InAppWebViewController controller) {
controller.addWebMessageListener(
WebMessageListener(
jsObjectName: 'ReactNativeWebView',
onPostMessage: (String? message, Uri? sourceOrigin, bool isMainFrame,
JavaScriptReplyProxy replyProxy) {
final shortenedMessage = message?.substring(16);
if (shortenedMessage != null && isJsonString(shortenedMessage)) {
final parsedMessage = jsonDecode(shortenedMessage);
final eventType = parsedMessage["event"];
if (eventType == 'loaded') {
final authToken = parsedMessage["config"]["authToken"];
print(authToken);
storeCookie(authToken as String);
}
}
},
),
);
},
);
bool isJsonString(String str) {
try {
jsonDecode(str);
} catch (e) {
return false;
}
return true;
}
Future<void> storeCookie(String value) async =>
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
}
@@ -0,0 +1,58 @@
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:cake_wallet/view_model/settings/link_list_item.dart';
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
import 'package:cake_wallet/view_model/support_view_model.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/generated/i18n.dart';
class SupportOtherLinksPage extends BasePage {
SupportOtherLinksPage(this.supportViewModel);
final SupportViewModel supportViewModel;
@override
String get title => S.current.settings_support;
@override
AppBarStyle get appBarStyle => AppBarStyle.transparent;
@override
Widget body(BuildContext context) {
final iconColor =
Theme.of(context).accentTextTheme.displayLarge!.backgroundColor!;
return Container(
child: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: SectionStandardList(
context: context,
sectionCount: 1,
itemCounter: (int _) => supportViewModel.items.length,
itemBuilder: (_, __, index) {
final item = supportViewModel.items[index];
if (item is RegularListItem) {
return SettingsCellWithArrow(
title: item.title, handler: item.handler);
}
if (item is LinkListItem) {
return SettingsLinkProviderCell(
title: item.title,
icon: item.icon,
iconColor: item.hasIconColor ? iconColor : null,
link: item.link,
linkTitle: item.linkTitle);
}
return Container();
}),
),
),
);
}
}