From aca6f62eac074b39cafdf6e6a4a5a65fa0b5c768 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 6 May 2024 09:37:11 -0400 Subject: [PATCH 1/8] pass l10n to getSubtitle directly rather than passing context to prevent null check error --- lib/pages/chat_list/chat_list_item.dart | 2 +- lib/pangea/models/pangea_message_event.dart | 2 -- lib/pangea/utils/get_chat_list_item_subtitle.dart | 15 +++++++-------- .../widgets/chat/message_translation_card.dart | 1 - lib/pangea/widgets/igc/pangea_rich_text.dart | 1 - 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 680fe8dcf..447b5f6c3 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -205,7 +205,7 @@ class ChatListItem extends StatelessWidget { // Future.value(L10n.of(context)!.emptyChat), future: room.lastEvent != null ? GetChatListItemSubtitle().getSubtitle( - context, + L10n.of(context)!, room.lastEvent, MatrixState.pangeaController, ) diff --git a/lib/pangea/models/pangea_message_event.dart b/lib/pangea/models/pangea_message_event.dart index 61bcceb4e..8dab042ab 100644 --- a/lib/pangea/models/pangea_message_event.dart +++ b/lib/pangea/models/pangea_message_event.dart @@ -95,7 +95,6 @@ class PangeaMessageEvent { BuildContext context, ) async { final String text = (await representationByLanguageGlobal( - context: context, langCode: langCode, )) ?.text ?? @@ -399,7 +398,6 @@ class PangeaMessageEvent { } Future representationByLanguageGlobal({ - required BuildContext context, required String langCode, }) async { // try { diff --git a/lib/pangea/utils/get_chat_list_item_subtitle.dart b/lib/pangea/utils/get_chat_list_item_subtitle.dart index e5b1388a9..f9616cc7c 100644 --- a/lib/pangea/utils/get_chat_list_item_subtitle.dart +++ b/lib/pangea/utils/get_chat_list_item_subtitle.dart @@ -4,7 +4,6 @@ import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/pangea_message_event.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; @@ -12,16 +11,17 @@ import '../../utils/matrix_sdk_extensions/matrix_locals.dart'; class GetChatListItemSubtitle { Future getSubtitle( - BuildContext context, + L10n l10n, Event? event, PangeaController pangeaController, ) async { - if (event == null) return L10n.of(context)!.emptyChat; + if (event == null) return l10n.emptyChat; try { String? eventContextId = event.eventId; if (!event.eventId.isValidMatrixId || event.eventId.sigil != '\$') { eventContextId = null; } + final Timeline timeline = await event.room.getTimeline(eventContextId: eventContextId); @@ -47,7 +47,7 @@ class GetChatListItemSubtitle { !pangeaController.permissionsController .isToolEnabled(ToolSetting.immersionMode, event.room)) { return event.calcLocalizedBody( - MatrixLocals(L10n.of(context)!), + MatrixLocals(l10n), hideReply: true, hideEdit: true, plaintextBody: true, @@ -71,14 +71,13 @@ class GetChatListItemSubtitle { final String? text = (await pangeaMessageEvent.representationByLanguageGlobal( - context: context, langCode: l2Code, )) ?.text; - final i18n = MatrixLocals(L10n.of(context)!); + final i18n = MatrixLocals(l10n); - if (text == null) return L10n.of(context)!.emptyChat; + if (text == null) return l10n.emptyChat; if (!event.room.isDirectChat || event.room.directChatMatrixID != event.room.lastEvent?.senderId) { @@ -95,7 +94,7 @@ class GetChatListItemSubtitle { } catch (e, s) { // debugger(when: kDebugMode); ErrorHandler.logError(e: e, s: s); - return event?.body ?? L10n.of(context)!.emptyChat; + return event?.body ?? l10n.emptyChat; } } } diff --git a/lib/pangea/widgets/chat/message_translation_card.dart b/lib/pangea/widgets/chat/message_translation_card.dart index 5014d83f3..ae1a26c4c 100644 --- a/lib/pangea/widgets/chat/message_translation_card.dart +++ b/lib/pangea/widgets/chat/message_translation_card.dart @@ -51,7 +51,6 @@ class MessageTranslationCardState extends State { if (repEvent == null && mounted) { repEvent = await widget.messageEvent.representationByLanguageGlobal( - context: context, langCode: langCode, ); } diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index fb0fcef1c..38e79706e 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -83,7 +83,6 @@ class PangeaRichTextState extends State { widget.pangeaMessageEvent .representationByLanguageGlobal( - context: context, langCode: widget.pangeaMessageEvent.messageDisplayLangCode, ) .onError((error, stackTrace) => ErrorHandler.logError()) From 31b90eab0c290bd0054697eb5cc552b6d0925f6d Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 6 May 2024 11:45:00 -0400 Subject: [PATCH 2/8] ensure that subscription initalization finishes before running customer update --- .../controllers/subscription_controller.dart | 32 +++++++++++++++---- lib/pangea/models/mobile_subscriptions.dart | 12 +++---- .../settings_subscription.dart | 2 +- lib/widgets/matrix.dart | 1 + 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/lib/pangea/controllers/subscription_controller.dart b/lib/pangea/controllers/subscription_controller.dart index 828fd5365..3cf40f8f5 100644 --- a/lib/pangea/controllers/subscription_controller.dart +++ b/lib/pangea/controllers/subscription_controller.dart @@ -32,8 +32,6 @@ enum CanSendStatus { class SubscriptionController extends BaseController { late PangeaController _pangeaController; SubscriptionInfo? subscription; - - bool initialized = false; final StreamController subscriptionStream = StreamController.broadcast(); SubscriptionController(PangeaController pangeaController) : super() { @@ -45,7 +43,28 @@ class SubscriptionController extends BaseController { (subscription!.currentSubscriptionId != null || subscription!.currentSubscription != null); + bool _isInitializing = false; + Completer initialized = Completer(); + Future initialize() async { + if (initialized.isCompleted) return; + if (_isInitializing) { + await initialized.future; + return; + } + _isInitializing = true; + await _initialize(); + _isInitializing = false; + initialized.complete(); + } + + Future reinitialize() async { + initialized = Completer(); + _isInitializing = false; + await initialize(); + } + + Future _initialize() async { try { if (_pangeaController.matrixState.client.userID == null) { debugPrint( @@ -63,8 +82,6 @@ class SubscriptionController extends BaseController { setNewUserTrial(); } - initialized = true; - if (!kIsWeb) { Purchases.addCustomerInfoUpdateListener( (CustomerInfo info) async { @@ -186,6 +203,9 @@ class SubscriptionController extends BaseController { } Future updateCustomerInfo() async { + if (!initialized.isCompleted) { + await initialize(); + } if (subscription == null) { ErrorHandler.logError( m: "Null subscription info in subscription settings", @@ -220,7 +240,7 @@ class SubscriptionController extends BaseController { } bool get _shouldShowPaywall { - return initialized && + return initialized.isCompleted && !isSubscribed && (_lastDismissedPaywall == null || DateTime.now().difference(_lastDismissedPaywall!).inHours > @@ -245,7 +265,7 @@ class SubscriptionController extends BaseController { Future showPaywall(BuildContext context) async { try { - if (!initialized) { + if (!initialized.isCompleted) { await initialize(); } if (subscription?.availableSubscriptions.isEmpty ?? true) { diff --git a/lib/pangea/models/mobile_subscriptions.dart b/lib/pangea/models/mobile_subscriptions.dart index 4a57d6200..00fc6e3fd 100644 --- a/lib/pangea/models/mobile_subscriptions.dart +++ b/lib/pangea/models/mobile_subscriptions.dart @@ -1,15 +1,13 @@ import 'dart:io'; -import 'package:flutter/material.dart'; - import 'package:collection/collection.dart'; -import 'package:purchases_flutter/purchases_flutter.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; - import 'package:fluffychat/pangea/config/environment.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/models/base_subscription_info.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:flutter/material.dart'; +import 'package:purchases_flutter/purchases_flutter.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; class MobileSubscriptionInfo extends SubscriptionInfo { MobileSubscriptionInfo({required super.pangeaController}) : super(); @@ -119,11 +117,11 @@ class MobileSubscriptionInfo extends SubscriptionInfo { Future setCustomerInfo() async { if (allProducts == null) { ErrorHandler.logError( - m: "Null appProducts in setCustomerInfo", + m: "Null allProducts in setCustomerInfo", s: StackTrace.current, ); debugPrint( - "Null appProducts in setCustomerInfo", + "Null allProducts in setCustomerInfo", ); return; } diff --git a/lib/pangea/pages/settings_subscription/settings_subscription.dart b/lib/pangea/pages/settings_subscription/settings_subscription.dart index 86c43ff47..374abedb3 100644 --- a/lib/pangea/pages/settings_subscription/settings_subscription.dart +++ b/lib/pangea/pages/settings_subscription/settings_subscription.dart @@ -30,7 +30,7 @@ class SubscriptionManagementController extends State { @override void initState() { - if (!subscriptionController.initialized) { + if (!subscriptionController.initialized.isCompleted) { subscriptionController.initialize().then((_) => setState(() {})); } diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index 5aae2398b..634695a18 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -335,6 +335,7 @@ class MatrixState extends State with WidgetsBindingObserver { // #Pangea if (state == LoginState.loggedIn) { await (await pangeaController.userController.completer).future; + await pangeaController.subscriptionController.reinitialize(); } String routeDestination; if (state == LoginState.loggedIn) { From 7d3a7103c5e36267ecdf270ef637c1470f5c82c0 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 8 May 2024 09:28:20 -0400 Subject: [PATCH 3/8] =?UTF-8?q?If=20the=20user=20highlights=20a=20word=20a?= =?UTF-8?q?nd=20they=E2=80=99re=20not=20actively=20defining,=20then=20it?= =?UTF-8?q?=20should=20automatically=20switch=20to=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pangea/widgets/chat/message_toolbar.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 8e88d3a51..bb42bd667 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -301,8 +301,13 @@ class MessageToolbarState extends State { widget.textSelection.selectionStream.stream.listen((value) { timer?.cancel(); timer = Timer(const Duration(milliseconds: 500), () { - if (currentMode != null || value != null && value.isNotEmpty) { - updateMode(currentMode ?? MessageMode.translation); + if (value != null && value.isNotEmpty) { + final MessageMode newMode = currentMode == MessageMode.definition + ? MessageMode.definition + : MessageMode.translation; + updateMode(newMode); + } else if (currentMode != null) { + updateMode(currentMode!); } }); }); From f6a45323e03188496a64020e67bcc5411e923bbc Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 8 May 2024 14:26:34 -0400 Subject: [PATCH 4/8] make join_with_link work for users who are logged in or logged out --- lib/config/routes.dart | 17 +++--- lib/pages/chat_list/space_view.dart | 16 ++++-- lib/pangea/controllers/class_controller.dart | 60 +++++++++++--------- lib/pangea/utils/class_code.dart | 17 ++---- lib/pangea/widgets/class/join_with_link.dart | 46 +++++++-------- 5 files changed, 79 insertions(+), 77 deletions(-) diff --git a/lib/config/routes.dart b/lib/config/routes.dart index bf3f0fe7e..8b69aca1e 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -113,6 +113,14 @@ abstract class AppRoutes { ), ), // #Pangea + GoRoute( + path: '/join_with_link', + pageBuilder: (context, state) => defaultPageBuilder( + context, + state, + const JoinClassWithLink(), + ), + ), GoRoute( path: '/user_age', pageBuilder: (context, state) => defaultPageBuilder( @@ -154,15 +162,6 @@ abstract class AppRoutes { ), redirect: loggedOutRedirect, ), - GoRoute( - path: '/join_with_link', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const JoinClassWithLink(), - ), - redirect: loggedOutRedirect, - ), // Pangea# GoRoute( path: '/rooms', diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index c82838f12..e7d793e3d 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -81,17 +81,25 @@ class _SpaceViewState extends State { nextBatch: null, ); } + + setState(() { + error = null; + loading = true; + }); // Pangea# + final activeSpaceId = widget.controller.activeSpaceId!; final client = Matrix.of(context).client; final activeSpace = client.getRoomById(activeSpaceId); await activeSpace?.postLoad(); - setState(() { - error = null; - loading = true; - }); + // #Pangea + // setState(() { + // error = null; + // loading = true; + // }); + // Pangea# try { final response = await client.getSpaceHierarchy( diff --git a/lib/pangea/controllers/class_controller.dart b/lib/pangea/controllers/class_controller.dart index 2c684b459..7706d2194 100644 --- a/lib/pangea/controllers/class_controller.dart +++ b/lib/pangea/controllers/class_controller.dart @@ -105,36 +105,44 @@ class ClassController extends BaseController { } Future joinClasswithCode(BuildContext context, String classCode) async { - final QueryPublicRoomsResponse queryPublicRoomsResponse = - await Matrix.of(context).client.queryPublicRooms( - limit: 1, - filter: PublicRoomQueryFilter(genericSearchTerm: classCode), - ); - - final PublicRoomsChunk? classChunk = - queryPublicRoomsResponse.chunk.firstWhereOrNull((element) { - return element.canonicalAlias?.replaceAll("#", "").split(":")[0] == - classCode; - }); - - if (classChunk == null) { - ClassCodeUtil.messageSnack(context, L10n.of(context)!.unableToFindClass); - return; - } + try { + final QueryPublicRoomsResponse queryPublicRoomsResponse = + await Matrix.of(context).client.queryPublicRooms( + limit: 1, + filter: PublicRoomQueryFilter(genericSearchTerm: classCode), + ); + + final PublicRoomsChunk? classChunk = + queryPublicRoomsResponse.chunk.firstWhereOrNull((element) { + return element.canonicalAlias?.replaceAll("#", "").split(":")[0] == + classCode; + }); + + if (classChunk == null) { + ClassCodeUtil.messageSnack( + context, L10n.of(context)!.unableToFindClass); + return; + } + + if (Matrix.of(context) + .client + .rooms + .any((room) => room.id == classChunk.roomId)) { + setActiveSpaceIdInChatListController(classChunk.roomId); + ClassCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass); + return; + } + await _pangeaController.matrixState.client.joinRoom(classChunk.roomId); - if (Matrix.of(context) - .client - .rooms - .any((room) => room.id == classChunk.roomId)) { setActiveSpaceIdInChatListController(classChunk.roomId); - ClassCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass); + GoogleAnalytics.joinClass(classCode); return; + } catch (err) { + ClassCodeUtil.messageSnack( + context, + ErrorCopy(context, err).body, + ); } - await _pangeaController.matrixState.client.joinRoom(classChunk.roomId); - - setActiveSpaceIdInChatListController(classChunk.roomId); - GoogleAnalytics.joinClass(classCode); - return; // P-EPIC // prereq - server needs ability to invite to private room. how? // does server api have ability with admin token? diff --git a/lib/pangea/utils/class_code.dart b/lib/pangea/utils/class_code.dart index b4e0671d6..ca783f755 100644 --- a/lib/pangea/utils/class_code.dart +++ b/lib/pangea/utils/class_code.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -35,18 +34,10 @@ class ClassCodeUtil { ], ); if (classCode == null || classCode.single.isEmpty) return; - - try { - await pangeaController.classController.joinClasswithCode( - context, - classCode.first, - ); - } catch (err) { - messageSnack( - context, - ErrorCopy(context, err).body, - ); - } + await pangeaController.classController.joinClasswithCode( + context, + classCode.first, + ); } static messageDialog( diff --git a/lib/pangea/widgets/class/join_with_link.dart b/lib/pangea/widgets/class/join_with_link.dart index 15b52bd41..00020e78d 100644 --- a/lib/pangea/widgets/class/join_with_link.dart +++ b/lib/pangea/widgets/class/join_with_link.dart @@ -1,7 +1,6 @@ import 'package:fluffychat/pangea/constants/url_query_parameter_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/utils/class_code.dart'; -import 'package:fluffychat/widgets/layouts/empty_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; @@ -28,7 +27,7 @@ class _JoinClassWithLinkState extends State { void initState() { super.initState(); - Future.delayed(Duration.zero, () { + Future.delayed(Duration.zero, () async { classCode = GoRouterState.of(context) .uri .queryParameters[UrlQueryParameterKeys.classCode]; @@ -42,35 +41,32 @@ class _JoinClassWithLinkState extends State { } if (!Matrix.of(context).client.isLogged()) { - return ClassCodeUtil.messageDialog( - context, L10n.of(context)!.pleaseLoginFirst, () async { - await _pangeaController.pStoreService.save( - PLocalKey.cachedClassCodeToJoin, - classCode, - addClientIdToKey: false, - local: true, - ); - context.go("/home"); - }); + await _pangeaController.pStoreService.save( + PLocalKey.cachedClassCodeToJoin, + classCode, + addClientIdToKey: false, + local: true, + ); + context.go("/home"); + return; } _pangeaController.classController .joinClasswithCode( - context, - classCode!, - ) - .onError( - (error, stackTrace) => ClassCodeUtil.messageSnack( - context, - ErrorCopy(context, error).body, - ), - ) - .whenComplete( - () => context.go("/rooms"), - ); + context, + classCode!, + ) + .onError((error, stackTrace) { + ClassCodeUtil.messageSnack( + context, + ErrorCopy(context, error).body, + ); + }).whenComplete( + () => context.go("/rooms"), + ); }); } @override - Widget build(BuildContext context) => const EmptyPage(); + Widget build(BuildContext context) => const SizedBox(); } From b0490034e3659b732517d90aa4f6f20ba5857b29 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 8 May 2024 14:30:54 -0400 Subject: [PATCH 5/8] remove hover menu from messages on web --- lib/pages/chat/events/message.dart | 130 +++++++++++++++-------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index ff206d2b0..568fe0997 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -574,70 +574,72 @@ class Message extends StatelessWidget { ), child: container, ), - Positioned( - left: ownMessage ? null : 48, - right: ownMessage ? 4 : null, - top: displayTime ? 38 : 0, - child: AnimatedScale( - duration: Duration( - milliseconds: - (FluffyThemes.animationDuration.inMilliseconds / 2) - .floor(), - ), - curve: FluffyThemes.animationCurve, - scale: !longPressSelect && hovered ? 1 : 0, - alignment: Alignment.center, - child: Material( - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.9), - elevation: - Theme.of(context).appBarTheme.scrolledUnderElevation ?? - 4, - borderRadius: BorderRadius.circular(AppConfig.borderRadius), - shadowColor: Theme.of(context).appBarTheme.shadowColor, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (event.room.canSendDefaultMessages) - SizedBox( - width: 32, - height: 32, - child: IconButton( - icon: Icon( - Icons.reply_outlined, - size: 16, - color: Theme.of(context) - .colorScheme - .onTertiaryContainer, - ), - tooltip: L10n.of(context)!.reply, - onPressed: event.room.canSendDefaultMessages - ? () => onSwipe() - : null, - ), - ), - SizedBox( - width: 32, - height: 32, - child: IconButton( - icon: Icon( - Icons.more_vert, - size: 16, - color: Theme.of(context) - .colorScheme - .onTertiaryContainer, - ), - tooltip: L10n.of(context)!.select, - onPressed: () => onSelect(event), - ), - ), - ], - ), - ), - ), - ), + // #Pangea + // Positioned( + // left: ownMessage ? null : 48, + // right: ownMessage ? 4 : null, + // top: displayTime ? 38 : 0, + // child: AnimatedScale( + // duration: Duration( + // milliseconds: + // (FluffyThemes.animationDuration.inMilliseconds / 2) + // .floor(), + // ), + // curve: FluffyThemes.animationCurve, + // scale: !longPressSelect && hovered ? 1 : 0, + // alignment: Alignment.center, + // child: Material( + // color: Theme.of(context) + // .colorScheme + // .secondaryContainer + // .withOpacity(0.9), + // elevation: + // Theme.of(context).appBarTheme.scrolledUnderElevation ?? + // 4, + // borderRadius: BorderRadius.circular(AppConfig.borderRadius), + // shadowColor: Theme.of(context).appBarTheme.shadowColor, + // child: Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // if (event.room.canSendDefaultMessages) + // SizedBox( + // width: 32, + // height: 32, + // child: IconButton( + // icon: Icon( + // Icons.reply_outlined, + // size: 16, + // color: Theme.of(context) + // .colorScheme + // .onTertiaryContainer, + // ), + // tooltip: L10n.of(context)!.reply, + // onPressed: event.room.canSendDefaultMessages + // ? () => onSwipe() + // : null, + // ), + // ), + // SizedBox( + // width: 32, + // height: 32, + // child: IconButton( + // icon: Icon( + // Icons.more_vert, + // size: 16, + // color: Theme.of(context) + // .colorScheme + // .onTertiaryContainer, + // ), + // tooltip: L10n.of(context)!.select, + // onPressed: () => onSelect(event), + // ), + // ), + // ], + // ), + // ), + // ), + // ), + // Pangea# ], ), ), From c2f785795e918e81068d012de39eda48cb3bf8d1 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 8 May 2024 14:53:41 -0400 Subject: [PATCH 6/8] refresh toolbar / input bar after activating free trial --- lib/pages/chat/input_bar.dart | 10 ++--- .../controllers/choreographer.dart | 7 +++- .../controllers/subscription_controller.dart | 12 ++++-- .../chat/message_unsubscribed_card.dart | 1 - lib/pangea/widgets/class/join_with_link.dart | 41 ++++++------------- lib/pangea/widgets/igc/span_card.dart | 4 +- 6 files changed, 33 insertions(+), 42 deletions(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 8d4bfe617..373b88c10 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -50,11 +50,11 @@ class InputBar extends StatelessWidget { List> getSuggestions(String text) { // #Pangea final List> ret = >[]; - // if (controller!.selection.baseOffset != - // controller!.selection.extentOffset || - // controller!.selection.baseOffset < 0) { - // return []; // no entries if there is selected text - // } + if (controller!.selection.baseOffset != + controller!.selection.extentOffset || + controller!.selection.baseOffset < 0) { + return []; // no entries if there is selected text + } // Pangea# final searchText = controller!.text.substring(0, controller!.selection.baseOffset); diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index e5be2d194..556eaaff8 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -51,6 +51,7 @@ class Choreographer { String? _lastChecked; ChoreoMode choreoMode = ChoreoMode.igc; final StreamController stateListener = StreamController(); + StreamSubscription? trialStream; Choreographer(this.pangeaController, this.chatController) { _initialize(); @@ -63,6 +64,9 @@ class Choreographer { errorService = ErrorService(this); altTranslator = AlternativeTranslator(this); _textController.addListener(_onChangeListener); + trialStream = pangeaController + .subscriptionController.trialActivationStream.stream + .listen((_) => _onChangeListener); clear(); } @@ -214,7 +218,7 @@ class Choreographer { if (choreoMode == ChoreoMode.it && itController.isTranslationDone && !tokensOnly) { - debugger(when: kDebugMode); + // debugger(when: kDebugMode); } await (choreoMode == ChoreoMode.it && !itController.isTranslationDone @@ -413,6 +417,7 @@ class Choreographer { dispose() { _textController.dispose(); + trialStream?.cancel(); } LanguageModel? get l2Lang { diff --git a/lib/pangea/controllers/subscription_controller.dart b/lib/pangea/controllers/subscription_controller.dart index eed1cb371..36e965137 100644 --- a/lib/pangea/controllers/subscription_controller.dart +++ b/lib/pangea/controllers/subscription_controller.dart @@ -34,6 +34,7 @@ class SubscriptionController extends BaseController { late PangeaController _pangeaController; SubscriptionInfo? subscription; final StreamController subscriptionStream = StreamController.broadcast(); + final StreamController trialActivationStream = StreamController.broadcast(); SubscriptionController(PangeaController pangeaController) : super() { _pangeaController = pangeaController; @@ -191,10 +192,13 @@ class SubscriptionController extends BaseController { void activateNewUserTrial() { _pangeaController.pStoreService .save( - MatrixProfile.activatedFreeTrial.title, - true, - ) - .then((_) => setNewUserTrial()); + MatrixProfile.activatedFreeTrial.title, + true, + ) + .then((_) { + setNewUserTrial(); + trialActivationStream.add(true); + }); } void setNewUserTrial() { diff --git a/lib/pangea/widgets/chat/message_unsubscribed_card.dart b/lib/pangea/widgets/chat/message_unsubscribed_card.dart index 2d37328ec..8219e2355 100644 --- a/lib/pangea/widgets/chat/message_unsubscribed_card.dart +++ b/lib/pangea/widgets/chat/message_unsubscribed_card.dart @@ -33,7 +33,6 @@ class MessageUnsubscribedCard extends StatelessWidget { MatrixState.pangeaController.subscriptionController .showPaywall(context); } - MatrixState.pAnyState.closeOverlay(); } return Padding( diff --git a/lib/pangea/widgets/class/join_with_link.dart b/lib/pangea/widgets/class/join_with_link.dart index 00020e78d..804c9b991 100644 --- a/lib/pangea/widgets/class/join_with_link.dart +++ b/lib/pangea/widgets/class/join_with_link.dart @@ -1,13 +1,11 @@ import 'package:fluffychat/pangea/constants/url_query_parameter_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/utils/class_code.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import '../../../widgets/matrix.dart'; import '../../constants/local.key.dart'; -import '../../utils/error_handler.dart'; //if on home with classcode in url and not logged in, then save it soemhow and after llogin, join class automatically //if on home with classcode in url and logged in, then join class automatically @@ -33,37 +31,22 @@ class _JoinClassWithLinkState extends State { .queryParameters[UrlQueryParameterKeys.classCode]; if (classCode == null) { - return ClassCodeUtil.messageDialog( - context, - L10n.of(context)!.unableToFindClassCode, - () => context.go("/rooms"), + Sentry.addBreadcrumb( + Breadcrumb( + message: + "Navigated to join_with_link without class code query parameter", + ), ); - } - - if (!Matrix.of(context).client.isLogged()) { - await _pangeaController.pStoreService.save( - PLocalKey.cachedClassCodeToJoin, - classCode, - addClientIdToKey: false, - local: true, - ); - context.go("/home"); return; } - _pangeaController.classController - .joinClasswithCode( - context, - classCode!, - ) - .onError((error, stackTrace) { - ClassCodeUtil.messageSnack( - context, - ErrorCopy(context, error).body, - ); - }).whenComplete( - () => context.go("/rooms"), + await _pangeaController.pStoreService.save( + PLocalKey.cachedClassCodeToJoin, + classCode, + addClientIdToKey: false, + local: true, ); + context.go("/home"); }); } diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index eb167da3b..7185d726c 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -77,9 +77,9 @@ class SpanCardState extends State { if (mounted) { setState(() => fetchingData = false); } - } catch (e) { + } catch (e, s) { // debugger(when: kDebugMode); - ErrorHandler.logError(e: e, s: StackTrace.current); + ErrorHandler.logError(e: e, s: s); if (mounted) { setState(() { error = e; From 5ad48def7c85841559689e79d28641e4881c189f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 8 May 2024 15:23:35 -0400 Subject: [PATCH 7/8] When adding a chat to a class, default to 'suggested' set to true --- lib/pangea/widgets/class/add_space_toggles.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index 307db42ef..cd875cd95 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -72,7 +72,7 @@ class AddToSpaceState extends State { final activeSpace = Matrix.of(context).client.getRoomById(widget.activeSpaceId!); if (activeSpace != null && activeSpace.canIAddSpaceChild(null)) { - parents.add(SuggestionStatus(false, activeSpace)); + parents.add(SuggestionStatus(true, activeSpace)); } else { ErrorHandler.logError( e: Exception('activeSpaceId ${widget.activeSpaceId} not found'), @@ -111,12 +111,13 @@ class AddToSpaceState extends State { } } - Future _addSingleSpace(String roomToAddId, Room newParent) { + Future _addSingleSpace(String roomToAddId, Room newParent) async { GoogleAnalytics.addParent(roomToAddId, newParent.classCode); - return newParent.setSpaceChild( + await newParent.setSpaceChild( roomToAddId, suggested: isSuggestedInSpace(newParent), ); + await setSuggested(true, newParent); } Future addSpaces(String roomToAddId) async { @@ -147,7 +148,7 @@ class AddToSpaceState extends State { setState( () => add - ? parents.add(SuggestionStatus(false, possibleParent)) + ? parents.add(SuggestionStatus(true, possibleParent)) : parents.removeWhere( (suggestionStatus) => suggestionStatus.room.id == possibleParent.id, From 8c108f670864901c808c7d398468f83e87ca3490 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 8 May 2024 15:36:11 -0400 Subject: [PATCH 8/8] When enabling the bot, the Language level of the bot should default to that of the class --- lib/pages/new_group/new_group_view.dart | 1 + .../conversation_bot/conversation_bot_settings.dart | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/pages/new_group/new_group_view.dart b/lib/pages/new_group/new_group_view.dart index eb0fa605d..822b89214 100644 --- a/lib/pages/new_group/new_group_view.dart +++ b/lib/pages/new_group/new_group_view.dart @@ -86,6 +86,7 @@ class NewGroupView extends StatelessWidget { // ), ConversationBotSettings( key: controller.addConversationBotKey, + activeSpaceId: controller.activeSpaceId, ), const Divider(height: 1), AddToSpaceToggles( diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index 94214c8d2..0227c243a 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -20,12 +20,14 @@ import '../../utils/error_handler.dart'; class ConversationBotSettings extends StatefulWidget { final Room? room; final bool startOpen; + final String? activeSpaceId; // final ClassSettingsModel? initialSettings; const ConversationBotSettings({ super.key, this.room, this.startOpen = false, + this.activeSpaceId, // this.initialSettings, }); @@ -37,6 +39,7 @@ class ConversationBotSettingsState extends State { late BotOptionsModel botOptions; late bool isOpen; bool addBot = false; + Room? parentSpace; ConversationBotSettingsState({Key? key}); @@ -50,6 +53,12 @@ class ConversationBotSettingsState extends State { addBot = isBotRoom; }); }); + parentSpace = widget.activeSpaceId != null + ? Matrix.of(context).client.getRoomById(widget.activeSpaceId!) + : null; + if (parentSpace != null && botOptions.languageLevel == null) { + botOptions.languageLevel = parentSpace?.classSettings?.languageLevel; + } } Future updateBotOption(void Function() makeLocalChange) async {