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/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# ], ), ), 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/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/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/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), - ); + 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; - }); + 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 (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/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/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/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 15b52bd41..804c9b991 100644 --- a/lib/pangea/widgets/class/join_with_link.dart +++ b/lib/pangea/widgets/class/join_with_link.dart @@ -1,14 +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: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'; +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 @@ -28,49 +25,31 @@ 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]; 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", + ), ); + return; } - 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"); - }); - } - - _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"); }); } @override - Widget build(BuildContext context) => const EmptyPage(); + Widget build(BuildContext context) => const SizedBox(); } 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;