From 3da1f79863e8d646a271a912e036f9c875206787 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Mon, 15 Jul 2024 16:07:21 -0400 Subject: [PATCH 01/20] Scroll to make space for toolbar --- lib/pages/chat/chat_event_list.dart | 1 + lib/pages/chat/events/message.dart | 18 ++++++++++---- lib/pages/chat/events/message_content.dart | 8 +++++- lib/pangea/widgets/chat/message_buttons.dart | 3 +++ lib/pangea/widgets/chat/message_toolbar.dart | 26 +++++++++++++++++--- lib/pangea/widgets/chat/overlay_message.dart | 3 +++ lib/pangea/widgets/igc/pangea_rich_text.dart | 7 +++++- 7 files changed, 56 insertions(+), 10 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 24508bb62..963a2c230 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -168,6 +168,7 @@ class ChatEventList extends StatelessWidget { onSelect: controller.onSelectMessage, scrollToEventId: (String eventId) => controller.scrollToEventId(eventId), + scrollController: controller.scrollController, longPressSelect: controller.selectedEvents.isNotEmpty, // #Pangea selectedDisplayLang: diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 3b2c1b2fb..a1d04cb5c 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -43,6 +43,7 @@ class Message extends StatelessWidget { final bool immersionMode; final bool definitions; final ChatController controller; + final ScrollController scrollController; // Pangea# final Color? avatarPresenceBackgroundColor; @@ -68,6 +69,7 @@ class Message extends StatelessWidget { required this.immersionMode, required this.definitions, required this.controller, + required this.scrollController, // Pangea# super.key, }); @@ -317,10 +319,12 @@ class Message extends StatelessWidget { padding: const EdgeInsets.only(left: 8), child: GestureDetector( // #Pangea - onTap: () => - toolbarController?.showToolbar(context), - onDoubleTap: () => - toolbarController?.showToolbar(context), + onTap: () => toolbarController?.showToolbar( + context, + scrollController, + ), + onDoubleTap: () => toolbarController + ?.showToolbar(context, scrollController), // Pangea# onLongPress: longPressSelect ? null @@ -443,6 +447,8 @@ class Message extends StatelessWidget { immersionMode: immersionMode, toolbarController: toolbarController, + scrollController: + scrollController, // Pangea# ), if (event.hasAggregatedEvents( @@ -588,7 +594,9 @@ class Message extends StatelessWidget { : MainAxisAlignment.start, children: [ if (pangeaMessageEvent?.showMessageButtons ?? false) - MessageButtons(toolbarController: toolbarController), + MessageButtons( + toolbarController: toolbarController, + scrollController: scrollController), MessageReactions(event, timeline), ], ), diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 01ae471f8..ab6c60193 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -39,6 +39,7 @@ class MessageContent extends StatelessWidget { final bool immersionMode; final ToolbarDisplayController? toolbarController; final bool isOverlay; + final ScrollController scrollController; // Pangea# const MessageContent( @@ -52,6 +53,7 @@ class MessageContent extends StatelessWidget { required this.immersionMode, required this.toolbarController, this.isOverlay = false, + required this.scrollController, // Pangea# required this.borderRadius, }); @@ -299,6 +301,7 @@ class MessageContent extends StatelessWidget { style: messageTextStyle, pangeaMessageEvent: pangeaMessageEvent!, immersionMode: immersionMode, + scrollController: scrollController, toolbarController: toolbarController, ); } else if (pangeaMessageEvent != null) { @@ -322,7 +325,8 @@ class MessageContent extends StatelessWidget { toolbarController?.toolbar?.textSelection .onTextSelection(selection); }, - onTap: () => toolbarController?.showToolbar(context), + onTap: () => + toolbarController?.showToolbar(context, scrollController), contextMenuBuilder: (context, state) => (toolbarController?.highlighted ?? false) ? const SizedBox.shrink() @@ -331,10 +335,12 @@ class MessageContent extends StatelessWidget { textSelection: state, onDefine: () => toolbarController?.showToolbar( context, + scrollController, mode: MessageMode.definition, ), onListen: () => toolbarController?.showToolbar( context, + scrollController, mode: MessageMode.textToSpeech, ), ), diff --git a/lib/pangea/widgets/chat/message_buttons.dart b/lib/pangea/widgets/chat/message_buttons.dart index f7748675f..7d3539298 100644 --- a/lib/pangea/widgets/chat/message_buttons.dart +++ b/lib/pangea/widgets/chat/message_buttons.dart @@ -4,15 +4,18 @@ import 'package:flutter/material.dart'; class MessageButtons extends StatelessWidget { final ToolbarDisplayController? toolbarController; + final ScrollController scrollController; const MessageButtons({ super.key, + required this.scrollController, this.toolbarController, }); void showActivity(BuildContext context) { toolbarController?.showToolbar( context, + scrollController, mode: MessageMode.practiceActivity, ); } diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 8d2d66b7d..57c814bca 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -59,7 +59,11 @@ class ToolbarDisplayController { ); } - void showToolbar(BuildContext context, {MessageMode? mode}) { + void showToolbar( + BuildContext context, + ScrollController scrollController, { + MessageMode? mode, + }) { bool toolbarUp = true; if (highlighted) return; if (controller.selectMode) { @@ -79,8 +83,23 @@ class ToolbarDisplayController { final Size transformTargetSize = (targetRenderBox as RenderBox).size; messageWidth = transformTargetSize.width; final Offset targetOffset = (targetRenderBox).localToGlobal(Offset.zero); - final double screenHeight = MediaQuery.of(context).size.height; - toolbarUp = targetOffset.dy >= screenHeight / 2; + // final double screenHeight = MediaQuery.of(context).size.height; + // If message is too close to top, make space for toolbar + if (targetOffset.dy < 360) { + // If chat can scroll up, do so + final scrollTo = scrollController.offset - targetOffset.dy + 360 + 118; + if (scrollTo >= 0) { + scrollController.animateTo( + scrollTo, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + ); + } + // If cannot scroll up enough, show toolbar underneath instead + else { + toolbarUp = false; + } + } } final Widget overlayMessage = OverlayMessage( @@ -89,6 +108,7 @@ class ToolbarDisplayController { immersionMode: immersionMode, ownMessage: pangeaMessageEvent.ownMessage, toolbarController: this, + scrollController: scrollController, width: messageWidth, nextEvent: nextEvent, previousEvent: previousEvent, diff --git a/lib/pangea/widgets/chat/overlay_message.dart b/lib/pangea/widgets/chat/overlay_message.dart index 5f3d46c7e..86ad9cfb8 100644 --- a/lib/pangea/widgets/chat/overlay_message.dart +++ b/lib/pangea/widgets/chat/overlay_message.dart @@ -21,6 +21,7 @@ class OverlayMessage extends StatelessWidget { final bool ownMessage; final ToolbarDisplayController toolbarController; final double? width; + final ScrollController scrollController; const OverlayMessage( this.event, { @@ -31,6 +32,7 @@ class OverlayMessage extends StatelessWidget { required this.immersionMode, required this.ownMessage, required this.toolbarController, + required this.scrollController, this.width, super.key, }); @@ -151,6 +153,7 @@ class OverlayMessage extends StatelessWidget { pangeaMessageEvent: pangeaMessageEvent, immersionMode: immersionMode, toolbarController: toolbarController, + scrollController: scrollController, isOverlay: true, ), if (event.hasAggregatedEvents( diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index abf583b3b..4302807e6 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -21,12 +21,14 @@ class PangeaRichText extends StatefulWidget { final bool immersionMode; final ToolbarDisplayController? toolbarController; final TextStyle? style; + final ScrollController scrollController; const PangeaRichText({ super.key, required this.pangeaMessageEvent, required this.immersionMode, required this.toolbarController, + required this.scrollController, this.style, }); @@ -151,7 +153,8 @@ class PangeaRichTextState extends State { widget.toolbarController?.toolbar?.textSelection .onTextSelection(selection); }, - onTap: () => widget.toolbarController?.showToolbar(context), + onTap: () => widget.toolbarController + ?.showToolbar(context, widget.scrollController), enableInteractiveSelection: widget.toolbarController?.highlighted ?? false, contextMenuBuilder: (context, state) => @@ -162,10 +165,12 @@ class PangeaRichTextState extends State { textSelection: state, onDefine: () => widget.toolbarController?.showToolbar( context, + widget.scrollController, mode: MessageMode.definition, ), onListen: () => widget.toolbarController?.showToolbar( context, + widget.scrollController, mode: MessageMode.textToSpeech, ), ), From 6424f95855c4db2ab9f7f22159cac10b7f0dcfc8 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 16 Jul 2024 11:25:54 -0400 Subject: [PATCH 02/20] Fix some incorrect calculations --- lib/pangea/widgets/chat/message_toolbar.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 7794f46cf..5f378657d 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -86,8 +86,9 @@ class ToolbarDisplayController { // If message is too close to top, make space for toolbar if (targetOffset.dy < 360) { // If chat can scroll up, do so - final scrollTo = scrollController.offset - targetOffset.dy + 360 + 118; - if (scrollTo >= 0) { + final scrollTo = scrollController.offset - targetOffset.dy + 300; + if (scrollTo >= scrollController.position.minScrollExtent && + scrollTo <= scrollController.position.maxScrollExtent) { scrollController.animateTo( scrollTo, duration: FluffyThemes.animationDuration, From 9aa1c7725b6a945c2875ad0eed6cb00797456ed7 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 16 Jul 2024 11:53:09 -0400 Subject: [PATCH 03/20] Address some more edge cases --- lib/pangea/widgets/chat/message_toolbar.dart | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 5f378657d..f99758a43 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -86,7 +86,7 @@ class ToolbarDisplayController { // If message is too close to top, make space for toolbar if (targetOffset.dy < 360) { // If chat can scroll up, do so - final scrollTo = scrollController.offset - targetOffset.dy + 300; + var scrollTo = scrollController.offset - targetOffset.dy + 320; if (scrollTo >= scrollController.position.minScrollExtent && scrollTo <= scrollController.position.maxScrollExtent) { scrollController.animateTo( @@ -98,6 +98,30 @@ class ToolbarDisplayController { // If cannot scroll up enough, show toolbar underneath instead else { toolbarUp = false; + // Scroll down if need more space beneath message + final spaceBeneath = MediaQuery.of(context).size.height - + targetOffset.dy - + transformTargetSize.height; + if (spaceBeneath < 360) { + scrollTo = scrollController.offset + spaceBeneath - 320; + if (scrollTo >= scrollController.position.minScrollExtent && + scrollTo <= scrollController.position.maxScrollExtent) { + scrollController.animateTo( + scrollTo, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + ); + } + // If can't scroll down enough, scroll up as much as possible and show toolbar above + else { + scrollController.animateTo( + scrollController.position.minScrollExtent, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + ); + toolbarUp = true; + } + } } } } From e7167631d0f9ca62f90d5a305f14a35581084948 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 16 Jul 2024 12:02:31 -0400 Subject: [PATCH 04/20] More math corrections --- lib/pangea/widgets/chat/message_toolbar.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index f99758a43..41ae358d3 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -84,7 +84,7 @@ class ToolbarDisplayController { final Offset targetOffset = (targetRenderBox).localToGlobal(Offset.zero); // final double screenHeight = MediaQuery.of(context).size.height; // If message is too close to top, make space for toolbar - if (targetOffset.dy < 360) { + if (targetOffset.dy < 320) { // If chat can scroll up, do so var scrollTo = scrollController.offset - targetOffset.dy + 320; if (scrollTo >= scrollController.position.minScrollExtent && @@ -102,7 +102,7 @@ class ToolbarDisplayController { final spaceBeneath = MediaQuery.of(context).size.height - targetOffset.dy - transformTargetSize.height; - if (spaceBeneath < 360) { + if (spaceBeneath < 320) { scrollTo = scrollController.offset + spaceBeneath - 320; if (scrollTo >= scrollController.position.minScrollExtent && scrollTo <= scrollController.position.maxScrollExtent) { From 19987c75a7c76b930d712ded9b71a57852585800 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 16 Jul 2024 16:07:42 -0400 Subject: [PATCH 05/20] Get rid of scrollcontroller chain --- lib/pages/chat/chat_event_list.dart | 1 - lib/pages/chat/events/message.dart | 13 ++-- lib/pages/chat/events/message_content.dart | 8 +-- lib/pangea/widgets/chat/message_buttons.dart | 3 - lib/pangea/widgets/chat/message_toolbar.dart | 75 ++++++++++---------- lib/pangea/widgets/chat/overlay_message.dart | 3 - lib/pangea/widgets/igc/pangea_rich_text.dart | 7 +- 7 files changed, 44 insertions(+), 66 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 963a2c230..24508bb62 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -168,7 +168,6 @@ class ChatEventList extends StatelessWidget { onSelect: controller.onSelectMessage, scrollToEventId: (String eventId) => controller.scrollToEventId(eventId), - scrollController: controller.scrollController, longPressSelect: controller.selectedEvents.isNotEmpty, // #Pangea selectedDisplayLang: diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index a1d04cb5c..45b60abd1 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -43,7 +43,6 @@ class Message extends StatelessWidget { final bool immersionMode; final bool definitions; final ChatController controller; - final ScrollController scrollController; // Pangea# final Color? avatarPresenceBackgroundColor; @@ -69,7 +68,6 @@ class Message extends StatelessWidget { required this.immersionMode, required this.definitions, required this.controller, - required this.scrollController, // Pangea# super.key, }); @@ -321,10 +319,9 @@ class Message extends StatelessWidget { // #Pangea onTap: () => toolbarController?.showToolbar( context, - scrollController, ), - onDoubleTap: () => toolbarController - ?.showToolbar(context, scrollController), + onDoubleTap: () => + toolbarController?.showToolbar(context), // Pangea# onLongPress: longPressSelect ? null @@ -447,8 +444,6 @@ class Message extends StatelessWidget { immersionMode: immersionMode, toolbarController: toolbarController, - scrollController: - scrollController, // Pangea# ), if (event.hasAggregatedEvents( @@ -595,8 +590,8 @@ class Message extends StatelessWidget { children: [ if (pangeaMessageEvent?.showMessageButtons ?? false) MessageButtons( - toolbarController: toolbarController, - scrollController: scrollController), + toolbarController: toolbarController, + ), MessageReactions(event, timeline), ], ), diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index ab6c60193..01ae471f8 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -39,7 +39,6 @@ class MessageContent extends StatelessWidget { final bool immersionMode; final ToolbarDisplayController? toolbarController; final bool isOverlay; - final ScrollController scrollController; // Pangea# const MessageContent( @@ -53,7 +52,6 @@ class MessageContent extends StatelessWidget { required this.immersionMode, required this.toolbarController, this.isOverlay = false, - required this.scrollController, // Pangea# required this.borderRadius, }); @@ -301,7 +299,6 @@ class MessageContent extends StatelessWidget { style: messageTextStyle, pangeaMessageEvent: pangeaMessageEvent!, immersionMode: immersionMode, - scrollController: scrollController, toolbarController: toolbarController, ); } else if (pangeaMessageEvent != null) { @@ -325,8 +322,7 @@ class MessageContent extends StatelessWidget { toolbarController?.toolbar?.textSelection .onTextSelection(selection); }, - onTap: () => - toolbarController?.showToolbar(context, scrollController), + onTap: () => toolbarController?.showToolbar(context), contextMenuBuilder: (context, state) => (toolbarController?.highlighted ?? false) ? const SizedBox.shrink() @@ -335,12 +331,10 @@ class MessageContent extends StatelessWidget { textSelection: state, onDefine: () => toolbarController?.showToolbar( context, - scrollController, mode: MessageMode.definition, ), onListen: () => toolbarController?.showToolbar( context, - scrollController, mode: MessageMode.textToSpeech, ), ), diff --git a/lib/pangea/widgets/chat/message_buttons.dart b/lib/pangea/widgets/chat/message_buttons.dart index 7d3539298..f7748675f 100644 --- a/lib/pangea/widgets/chat/message_buttons.dart +++ b/lib/pangea/widgets/chat/message_buttons.dart @@ -4,18 +4,15 @@ import 'package:flutter/material.dart'; class MessageButtons extends StatelessWidget { final ToolbarDisplayController? toolbarController; - final ScrollController scrollController; const MessageButtons({ super.key, - required this.scrollController, this.toolbarController, }); void showActivity(BuildContext context) { toolbarController?.showToolbar( context, - scrollController, mode: MessageMode.practiceActivity, ); } diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 41ae358d3..477c64e5f 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -59,8 +59,7 @@ class ToolbarDisplayController { } void showToolbar( - BuildContext context, - ScrollController scrollController, { + BuildContext context, { MessageMode? mode, }) { bool toolbarUp = true; @@ -82,46 +81,49 @@ class ToolbarDisplayController { final Size transformTargetSize = (targetRenderBox as RenderBox).size; messageWidth = transformTargetSize.width; final Offset targetOffset = (targetRenderBox).localToGlobal(Offset.zero); - // final double screenHeight = MediaQuery.of(context).size.height; - // If message is too close to top, make space for toolbar + + // If there is enough space above, procede as normal + // Else if there is enough space below, show toolbar underneath if (targetOffset.dy < 320) { - // If chat can scroll up, do so - var scrollTo = scrollController.offset - targetOffset.dy + 320; - if (scrollTo >= scrollController.position.minScrollExtent && - scrollTo <= scrollController.position.maxScrollExtent) { - scrollController.animateTo( - scrollTo, + final spaceBeneath = MediaQuery.of(context).size.height - + (targetOffset.dy + transformTargetSize.height); + if (spaceBeneath >= 320) { + toolbarUp = false; + } + + // See if it's possible to scroll up to make space + else if (controller.scrollController.offset - targetOffset.dy + 320 >= + controller.scrollController.position.minScrollExtent && + controller.scrollController.offset - targetOffset.dy + 320 <= + controller.scrollController.position.maxScrollExtent) { + controller.scrollController.animateTo( + controller.scrollController.offset - targetOffset.dy + 320, duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, ); } - // If cannot scroll up enough, show toolbar underneath instead - else { + + // See if it's possible to scroll down to make space + else if (controller.scrollController.offset + spaceBeneath - 320 >= + controller.scrollController.position.minScrollExtent && + controller.scrollController.offset + spaceBeneath - 320 <= + controller.scrollController.position.maxScrollExtent) { + controller.scrollController.animateTo( + controller.scrollController.offset + spaceBeneath - 320, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + ); toolbarUp = false; - // Scroll down if need more space beneath message - final spaceBeneath = MediaQuery.of(context).size.height - - targetOffset.dy - - transformTargetSize.height; - if (spaceBeneath < 320) { - scrollTo = scrollController.offset + spaceBeneath - 320; - if (scrollTo >= scrollController.position.minScrollExtent && - scrollTo <= scrollController.position.maxScrollExtent) { - scrollController.animateTo( - scrollTo, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - ); - } - // If can't scroll down enough, scroll up as much as possible and show toolbar above - else { - scrollController.animateTo( - scrollController.position.minScrollExtent, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - ); - toolbarUp = true; - } - } + } + + // If message is too big and can't scroll either way + // Scroll up as much as possible, and show toolbar above + else { + controller.scrollController.animateTo( + controller.scrollController.position.minScrollExtent, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + ); } } } @@ -132,7 +134,6 @@ class ToolbarDisplayController { immersionMode: immersionMode, ownMessage: pangeaMessageEvent.ownMessage, toolbarController: this, - scrollController: scrollController, width: messageWidth, nextEvent: nextEvent, previousEvent: previousEvent, diff --git a/lib/pangea/widgets/chat/overlay_message.dart b/lib/pangea/widgets/chat/overlay_message.dart index 86ad9cfb8..5f3d46c7e 100644 --- a/lib/pangea/widgets/chat/overlay_message.dart +++ b/lib/pangea/widgets/chat/overlay_message.dart @@ -21,7 +21,6 @@ class OverlayMessage extends StatelessWidget { final bool ownMessage; final ToolbarDisplayController toolbarController; final double? width; - final ScrollController scrollController; const OverlayMessage( this.event, { @@ -32,7 +31,6 @@ class OverlayMessage extends StatelessWidget { required this.immersionMode, required this.ownMessage, required this.toolbarController, - required this.scrollController, this.width, super.key, }); @@ -153,7 +151,6 @@ class OverlayMessage extends StatelessWidget { pangeaMessageEvent: pangeaMessageEvent, immersionMode: immersionMode, toolbarController: toolbarController, - scrollController: scrollController, isOverlay: true, ), if (event.hasAggregatedEvents( diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 4302807e6..abf583b3b 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -21,14 +21,12 @@ class PangeaRichText extends StatefulWidget { final bool immersionMode; final ToolbarDisplayController? toolbarController; final TextStyle? style; - final ScrollController scrollController; const PangeaRichText({ super.key, required this.pangeaMessageEvent, required this.immersionMode, required this.toolbarController, - required this.scrollController, this.style, }); @@ -153,8 +151,7 @@ class PangeaRichTextState extends State { widget.toolbarController?.toolbar?.textSelection .onTextSelection(selection); }, - onTap: () => widget.toolbarController - ?.showToolbar(context, widget.scrollController), + onTap: () => widget.toolbarController?.showToolbar(context), enableInteractiveSelection: widget.toolbarController?.highlighted ?? false, contextMenuBuilder: (context, state) => @@ -165,12 +162,10 @@ class PangeaRichTextState extends State { textSelection: state, onDefine: () => widget.toolbarController?.showToolbar( context, - widget.scrollController, mode: MessageMode.definition, ), onListen: () => widget.toolbarController?.showToolbar( context, - widget.scrollController, mode: MessageMode.textToSpeech, ), ), From 6a02db73bbc44d6a4097ab1fd81f797c9000143c Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Wed, 17 Jul 2024 12:14:07 -0400 Subject: [PATCH 06/20] integrate forked matrix sdk, addressing breaking changes of newer versions of matrix sdk --- lib/pages/chat/events/video_player.dart | 19 +++++++++---------- lib/utils/localized_exception_extension.dart | 5 +---- pubspec.lock | 9 ++++----- pubspec.yaml | 5 ++++- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index 1b0983bd4..d76d49576 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -1,21 +1,20 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:chewie/chewie.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:universal_html/html.dart' as html; -import 'package:video_player/video_player.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat/events/image_bubble.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/blur_hash.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:universal_html/html.dart' as html; +import 'package:video_player/video_player.dart'; + import '../../../utils/error_reporter.dart'; class EventVideoPlayer extends StatefulWidget { @@ -71,7 +70,7 @@ class EventVideoPlayerState extends State { autoInitialize: true, ); } - } on MatrixConnectionException catch (e) { + } on Exception catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toLocalizedString(context)), diff --git a/lib/utils/localized_exception_extension.dart b/lib/utils/localized_exception_extension.dart index 65be02a1f..5b2df02fd 100644 --- a/lib/utils/localized_exception_extension.dart +++ b/lib/utils/localized_exception_extension.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/encryption.dart'; import 'package:matrix/matrix.dart'; @@ -67,9 +66,7 @@ extension LocalizedExceptionExtension on Object { supportedVersions, ); } - if (this is MatrixConnectionException || - this is SocketException || - this is SyncConnectionException) { + if (this is SocketException || this is SyncConnectionException) { return L10n.of(context)!.noConnectionToTheServer; } if (this is String) return toString(); diff --git a/pubspec.lock b/pubspec.lock index 7a4059d66..bc213b7c6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1432,11 +1432,10 @@ packages: matrix: dependency: "direct main" description: - name: matrix - sha256: bb6de59d0f69e10bb6893130a967f1ffcbfa3d3ffed3864f0736ce3d968e669c - url: "https://pub.dev" - source: hosted - version: "0.29.12" + path: "../matrix-dart-sdk" + relative: true + source: path + version: "0.30.0" meta: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a24dfdff3..1e75fc4b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,7 +70,10 @@ dependencies: keyboard_shortcuts: ^0.1.4 latlong2: ^0.9.1 linkify: ^5.0.0 - matrix: ^0.29.12 + matrix: + git: + url: https://github.com/pangeachat/matrix-dart-sdk.git # repo + ref: main # branch native_imaging: ^0.1.1 package_info_plus: ^6.0.0 pasteboard: ^0.2.0 From 56de4ce2bc60c2f638a1f8add3c879ee89f529b2 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Thu, 18 Jul 2024 10:45:41 -0400 Subject: [PATCH 07/20] Minimize long message toolbar weirdness --- lib/pangea/widgets/chat/message_toolbar.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 477c64e5f..16fb4571e 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -152,9 +152,17 @@ class ToolbarDisplayController { ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ - toolbarUp ? toolbar! : overlayMessage, + toolbarUp + // Column is limited to screen height + // If message portion is too tall, decrease toolbar height + // as necessary to prevent toolbar from acting strange + // Problems may still occur if toolbar height is decreased too much + ? Flexible( + child: toolbar!, + ) + : overlayMessage, const SizedBox(height: 6), - toolbarUp ? overlayMessage : toolbar!, + toolbarUp ? overlayMessage : Flexible(child: toolbar!), ], ); } catch (err) { From 8cdd9c3b2d8f235784d904ec10dd593c57206e2b Mon Sep 17 00:00:00 2001 From: Kelrap Date: Thu, 18 Jul 2024 17:17:28 -0400 Subject: [PATCH 08/20] Lets students add subrooms to spaces --- lib/pages/chat_list/chat_list.dart | 7 +------ .../pangea_room_extension.dart | 2 ++ .../user_permissions_extension.dart | 16 ++-------------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 803b773e1..9abe76a91 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -819,8 +819,7 @@ class ChatListController extends State label: space.nameIncludingParents(context), // If user is not admin of space, button is grayed out textStyle: TextStyle( - color: (firstSelectedRoom == null || - (firstSelectedRoom.isSpace && !space.isRoomAdmin)) + color: (firstSelectedRoom == null) ? Theme.of(context).colorScheme.outline : Theme.of(context).colorScheme.surfaceTint, ), @@ -838,10 +837,6 @@ class ChatListController extends State if (firstSelectedRoom == null) { throw L10n.of(context)!.nonexistentSelection; } - // If user is not admin of the would-be parent space, does not allow - if (firstSelectedRoom.isSpace && !space.isRoomAdmin) { - throw L10n.of(context)!.cantAddSpaceChild; - } if (space.canSendDefaultStates) { for (final roomId in selectedRoomIds) { diff --git a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart index fbec662a7..f0094f994 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -291,6 +291,8 @@ extension PangeaRoom on Room { bool get canDelete => _canDelete; + /// Determines whether user has permission to add child room to this + /// Can add child if, and only if, is admin of child bool canIAddSpaceChild(Room? room, {bool spaceMode = false}) { return _canIAddSpaceChild(room, spaceMode: spaceMode); } diff --git a/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart b/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart index b94db5c57..a61b459c6 100644 --- a/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart @@ -88,20 +88,8 @@ extension UserPermissionsRoomExtension on Room { return false; } - final isSpaceAdmin = isRoomAdmin; - final isChildRoomAdmin = room?.isRoomAdmin ?? true; - - // if user is not admin of child room, return false - if (!isChildRoomAdmin) return false; - - // if the child room is a space, or will be a space, - // then the user must be an admin of the parent space - if (room?.isSpace ?? spaceMode) return isSpaceAdmin; - - // otherwise, the user can add the child room to the parent - // if they're the admin of the parent or if the parent creation - // of group chats - return isSpaceAdmin || (pangeaRoomRules?.isCreateRooms ?? false); + // Can add child if, and only if, admin of child + return room?.isRoomAdmin ?? true; } bool get _canIAddSpaceParents => From 328ce621af91c37d56258fe75c0118511843c405 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Fri, 19 Jul 2024 09:30:05 -0400 Subject: [PATCH 09/20] Get rid of Flexible redundancy --- lib/pangea/widgets/chat/message_toolbar.dart | 148 +++++++++---------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 16fb4571e..5698b45c1 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -157,12 +157,10 @@ class ToolbarDisplayController { // If message portion is too tall, decrease toolbar height // as necessary to prevent toolbar from acting strange // Problems may still occur if toolbar height is decreased too much - ? Flexible( - child: toolbar!, - ) + ? toolbar! : overlayMessage, const SizedBox(height: 6), - toolbarUp ? overlayMessage : Flexible(child: toolbar!), + toolbarUp ? overlayMessage : toolbar!, ], ); } catch (err) { @@ -421,83 +419,85 @@ class MessageToolbarState extends State { @override Widget build(BuildContext context) { - return Material( - type: MaterialType.transparency, - child: Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - border: Border.all( - width: 2, - color: Theme.of(context).colorScheme.primary, + return Flexible( + child: Material( + type: MaterialType.transparency, + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + border: Border.all( + width: 2, + color: Theme.of(context).colorScheme.primary, + ), + borderRadius: const BorderRadius.all( + Radius.circular(25), + ), ), - borderRadius: const BorderRadius.all( - Radius.circular(25), + constraints: const BoxConstraints( + maxWidth: 300, + minWidth: 300, + maxHeight: 300, ), - ), - constraints: const BoxConstraints( - maxWidth: 300, - minWidth: 300, - maxHeight: 300, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: AnimatedSize( - duration: FluffyThemes.animationDuration, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: toolbarContent ?? const SizedBox(), - ), - SizedBox(height: toolbarContent == null ? 0 : 20), - ], + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: SingleChildScrollView( + child: AnimatedSize( + duration: FluffyThemes.animationDuration, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: toolbarContent ?? const SizedBox(), + ), + SizedBox(height: toolbarContent == null ? 0 : 20), + ], + ), ), ), ), - ), - Row( - mainAxisSize: MainAxisSize.min, - children: MessageMode.values.map((mode) { - if ([ - MessageMode.definition, - MessageMode.textToSpeech, - MessageMode.translation, - ].contains(mode) && - widget.pangeaMessageEvent.isAudioMessage) { - return const SizedBox.shrink(); - } - if (mode == MessageMode.speechToText && - !widget.pangeaMessageEvent.isAudioMessage) { - return const SizedBox.shrink(); - } - return Tooltip( - message: mode.tooltip(context), - child: IconButton( - icon: Icon(mode.icon), - color: mode.iconColor( - widget.pangeaMessageEvent, - currentMode, - context, + Row( + mainAxisSize: MainAxisSize.min, + children: MessageMode.values.map((mode) { + if ([ + MessageMode.definition, + MessageMode.textToSpeech, + MessageMode.translation, + ].contains(mode) && + widget.pangeaMessageEvent.isAudioMessage) { + return const SizedBox.shrink(); + } + if (mode == MessageMode.speechToText && + !widget.pangeaMessageEvent.isAudioMessage) { + return const SizedBox.shrink(); + } + return Tooltip( + message: mode.tooltip(context), + child: IconButton( + icon: Icon(mode.icon), + color: mode.iconColor( + widget.pangeaMessageEvent, + currentMode, + context, + ), + onPressed: () => updateMode(mode), + ), + ); + }).toList() + + [ + Tooltip( + message: L10n.of(context)!.more, + child: IconButton( + icon: const Icon(Icons.add_reaction_outlined), + onPressed: showMore, ), - onPressed: () => updateMode(mode), ), - ); - }).toList() + - [ - Tooltip( - message: L10n.of(context)!.more, - child: IconButton( - icon: const Icon(Icons.add_reaction_outlined), - onPressed: showMore, - ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ); From 65c4f4472dfa71c7fd7e35379972390be14ef8d7 Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Fri, 19 Jul 2024 14:30:19 -0400 Subject: [PATCH 10/20] add extra class method to prevent breaking changes --- lib/utils/matrix_sdk_extensions/matrix_locals.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/utils/matrix_sdk_extensions/matrix_locals.dart b/lib/utils/matrix_sdk_extensions/matrix_locals.dart index 5714baa22..b4536b6db 100644 --- a/lib/utils/matrix_sdk_extensions/matrix_locals.dart +++ b/lib/utils/matrix_sdk_extensions/matrix_locals.dart @@ -344,4 +344,10 @@ class MatrixLocals extends MatrixLocalizations { @override String startedKeyVerification(String senderName) => l10n.startedKeyVerification(senderName); + + @override + String invitedBy(String senderName) { + // TODO: implement invitedBy + throw UnimplementedError(); + } } From d8b3187dc50845c89db33765b0441b9124ead425 Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Fri, 19 Jul 2024 14:31:19 -0400 Subject: [PATCH 11/20] update pubspec.lock to point to latest sdk --- pubspec.lock | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index bc213b7c6..ae95fb892 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1432,9 +1432,11 @@ packages: matrix: dependency: "direct main" description: - path: "../matrix-dart-sdk" - relative: true - source: path + path: "." + ref: main + resolved-ref: "0a95cd8f3cfac8c9b0b59d6ee7fdbdb159949ca3" + url: "https://github.com/pangeachat/matrix-dart-sdk.git" + source: git version: "0.30.0" meta: dependency: transitive From e18eb6f104924a5cc5083099854b79aa0e8a4cef Mon Sep 17 00:00:00 2001 From: Kelrap Date: Fri, 19 Jul 2024 15:41:01 -0400 Subject: [PATCH 12/20] Adds speech to text error --- assets/l10n/intl_en.arb | 4 +++- lib/pangea/utils/error_handler.dart | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index be109614e..385009ff6 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4111,5 +4111,7 @@ "deleteSubscriptionWarningBody": "Deleting your account will not automatically cancel your subscription.", "manageSubscription": "Manage Subscription", "createSpace": "Create space", - "createChat": "Create chat" + "createChat": "Create chat", + "error520Title": "Please try again.", + "error520Desc": "Sorry, we could not understand your message..." } \ No newline at end of file diff --git a/lib/pangea/utils/error_handler.dart b/lib/pangea/utils/error_handler.dart index 65f73c15b..4b7330d6c 100644 --- a/lib/pangea/utils/error_handler.dart +++ b/lib/pangea/utils/error_handler.dart @@ -122,6 +122,10 @@ class ErrorCopy { title = l10n.error502504Title; body = l10n.error502504Desc; break; + case 520: + title = l10n.error520Title; + body = l10n.error520Desc; + break; case 404: title = l10n.error404Title; body = l10n.error404Desc; From 9ed7507353b0c15ab79c826e54e0dc7c53d61032 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Mon, 22 Jul 2024 10:39:46 -0400 Subject: [PATCH 13/20] Remove canIAddSpaceChild --- .../children_and_parents_extension.dart | 2 +- .../pangea_room_extension.dart | 6 ----- .../room_analytics_extension.dart | 24 +++++++++---------- .../user_permissions_extension.dart | 16 +------------ .../widgets/class/add_space_toggles.dart | 2 +- 5 files changed, 14 insertions(+), 36 deletions(-) diff --git a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart index 2f0596908..f5a2bf8de 100644 --- a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart @@ -131,7 +131,7 @@ extension ChildrenAndParentsRoomExtension on Room { spaceMode = child?.isSpace ?? spaceMode; // get the bool for adding chats to spaces - final bool canAddChild = _canIAddSpaceChild(child, spaceMode: spaceMode); + final bool canAddChild = child?.isRoomAdmin ?? true; if (!spaceMode) return canAddChild; // if adding space to a space, check if the child is an ancestor diff --git a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart index f0094f994..edd32d96d 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -291,12 +291,6 @@ extension PangeaRoom on Room { bool get canDelete => _canDelete; - /// Determines whether user has permission to add child room to this - /// Can add child if, and only if, is admin of child - bool canIAddSpaceChild(Room? room, {bool spaceMode = false}) { - return _canIAddSpaceChild(room, spaceMode: spaceMode); - } - bool get canIAddSpaceParents => _canIAddSpaceParents; bool pangeaCanSendEvent(String eventType) => _pangeaCanSendEvent(eventType); diff --git a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart index a27526a2b..97ccc24ac 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -68,19 +68,17 @@ extension AnalyticsRoomExtension on Room { } if (spaceChildren.any((sc) => sc.roomId == analyticsRoom.id)) return; - if (canIAddSpaceChild(null)) { - try { - await setSpaceChild(analyticsRoom.id); - } catch (err) { - debugPrint( - "Failed to add analytics room ${analyticsRoom.id} for student to space $id", - ); - Sentry.addBreadcrumb( - Breadcrumb( - message: "Failed to add analytics room to space $id", - ), - ); - } + try { + await setSpaceChild(analyticsRoom.id); + } catch (err) { + debugPrint( + "Failed to add analytics room ${analyticsRoom.id} for student to space $id", + ); + Sentry.addBreadcrumb( + Breadcrumb( + message: "Failed to add analytics room to space $id", + ), + ); } } diff --git a/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart b/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart index a61b459c6..d066bf84f 100644 --- a/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart @@ -78,24 +78,10 @@ extension UserPermissionsRoomExtension on Room { bool get _canDelete => isSpaceAdmin; - bool _canIAddSpaceChild(Room? room, {bool spaceMode = false}) { - if (!isSpace) { - ErrorHandler.logError( - m: "should not call canIAddSpaceChildren on non-space room. Room id: $id", - data: toJson(), - s: StackTrace.current, - ); - return false; - } - - // Can add child if, and only if, admin of child - return room?.isRoomAdmin ?? true; - } - bool get _canIAddSpaceParents => _isRoomAdmin || pangeaCanSendEvent(EventTypes.SpaceParent); - //overriding the default canSendEvent to check power levels + // Overriding the default canSendEvent to check power levels bool _pangeaCanSendEvent(String eventType) { final powerLevelsMap = getState(EventTypes.RoomPowerLevels)?.content; if (powerLevelsMap == null) return 0 <= ownPowerLevel; diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index c7d4fba71..b8cd622a2 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -79,7 +79,7 @@ class AddToSpaceState extends State { if (widget.activeSpaceId != null) { final activeSpace = Matrix.of(context).client.getRoomById(widget.activeSpaceId!); - if (activeSpace != null && activeSpace.canIAddSpaceChild(null)) { + if (activeSpace != null) { parent = activeSpace; } else { ErrorHandler.logError( From 5ce1d556b64111477090c2ae710e82b9f60c0b1f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 22 Jul 2024 11:44:53 -0400 Subject: [PATCH 14/20] account for matrix space child permissions --- .../children_and_parents_extension.dart | 3 ++- .../room_analytics_extension.dart | 2 ++ .../widgets/class/add_space_toggles.dart | 26 ++++++++++--------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart index f5a2bf8de..371af1768 100644 --- a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart @@ -131,7 +131,8 @@ extension ChildrenAndParentsRoomExtension on Room { spaceMode = child?.isSpace ?? spaceMode; // get the bool for adding chats to spaces - final bool canAddChild = child?.isRoomAdmin ?? true; + final bool canAddChild = + (child?.isRoomAdmin ?? true) && canSendEvent(EventTypes.SpaceChild); if (!spaceMode) return canAddChild; // if adding space to a space, check if the child is an ancestor diff --git a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart index 97ccc24ac..225e8be61 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -67,7 +67,9 @@ extension AnalyticsRoomExtension on Room { return Future.value(); } + if (!canSendEvent(EventTypes.SpaceChild)) return; if (spaceChildren.any((sc) => sc.roomId == analyticsRoom.id)) return; + try { await setSpaceChild(analyticsRoom.id); } catch (err) { diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index b8cd622a2..fd7843955 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -76,18 +76,6 @@ class AddToSpaceState extends State { ) : null; - if (widget.activeSpaceId != null) { - final activeSpace = - Matrix.of(context).client.getRoomById(widget.activeSpaceId!); - if (activeSpace != null) { - parent = activeSpace; - } else { - ErrorHandler.logError( - e: Exception('activeSpaceId ${widget.activeSpaceId} not found'), - ); - } - } - //sort possibleParents //if possibleParent in parents, put first //use sort but use any instead of contains because contains uses == and we want to compare by id @@ -102,6 +90,20 @@ class AddToSpaceState extends State { }); isOpen = widget.startOpen; + + if (widget.activeSpaceId != null) { + final activeSpace = + Matrix.of(context).client.getRoomById(widget.activeSpaceId!); + if (activeSpace == null) { + ErrorHandler.logError( + e: Exception('activeSpaceId ${widget.activeSpaceId} not found'), + ); + return; + } + if (activeSpace.canSendEvent(EventTypes.SpaceChild)) { + parent = activeSpace; + } + } } Future _addSingleSpace(String roomToAddId, Room newParent) async { From a7c329905b825b1b200b898624c0b8559ffa30bc Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 22 Jul 2024 12:18:06 -0400 Subject: [PATCH 15/20] don't rebuild the whole chat list on selection change --- lib/pages/chat_list/chat_list.dart | 38 +++++++--- lib/pages/chat_list/chat_list_body.dart | 32 +++++---- lib/pages/chat_list/space_view.dart | 23 ++++-- .../chat_list/chat_list_header_wrapper.dart | 47 ++++++++++++ .../chat_list/chat_list_item_wrapper.dart | 71 +++++++++++++++++++ 5 files changed, 185 insertions(+), 26 deletions(-) create mode 100644 lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart create mode 100644 lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index a9ef24e89..0897a28eb 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -599,12 +599,23 @@ class ChatListController extends State super.dispose(); } + // #Pangea + final StreamController selectionsStream = + StreamController.broadcast(); + // Pangea# + void toggleSelection(String roomId) { - setState( - () => selectedRoomIds.contains(roomId) - ? selectedRoomIds.remove(roomId) - : selectedRoomIds.add(roomId), - ); + // #Pangea + // setState( + // () => selectedRoomIds.contains(roomId) + // ? selectedRoomIds.remove(roomId) + // : selectedRoomIds.add(roomId), + // ); + selectedRoomIds.contains(roomId) + ? selectedRoomIds.remove(roomId) + : selectedRoomIds.add(roomId); + selectionsStream.add(roomId); + // Pangea# } Future toggleUnread() async { @@ -676,8 +687,8 @@ class ChatListController extends State context: context, future: () => _archiveSelectedRooms(), ); - setState(() {}); // #Pangea + // setState(() {}); if (archivedActiveRoom) { context.go('/rooms'); } @@ -709,7 +720,6 @@ class ChatListController extends State context: context, future: () => _leaveSelectedRooms(onlyAdmin), ); - setState(() {}); if (leftActiveRoom) { context.go('/rooms'); } @@ -871,7 +881,12 @@ class ChatListController extends State ); } - setState(() => selectedRoomIds.clear()); + // #Pangea + // setState(() => selectedRoomIds.clear()); + if (firstSelectedRoom != null) { + toggleSelection(firstSelectedRoom.id); + } + // Pangea# } bool get anySelectedRoomNotMarkedUnread => selectedRoomIds.any( @@ -941,7 +956,12 @@ class ChatListController extends State if (selectMode == SelectMode.share) { setState(() => Matrix.of(context).shareContent = null); } else { - setState(() => selectedRoomIds.clear()); + // #Pangea + // setState(() => selectedRoomIds.clear()); + for (final roomId in selectedRoomIds.toList()) { + toggleSelection(roomId); + } + // Pangea# } } diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index 2866e3260..b9b388da9 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -1,11 +1,11 @@ import 'package:animations/animations.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; -import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; import 'package:fluffychat/pages/chat_list/space_view.dart'; -import 'package:fluffychat/pages/chat_list/utils/on_chat_tap.dart'; import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart'; import 'package:fluffychat/pangea/widgets/chat_list/chat_list_body_text.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/chat_list_header_wrapper.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/chat_list_item_wrapper.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -17,7 +17,6 @@ import 'package:matrix/matrix.dart'; import '../../config/themes.dart'; import '../../widgets/connection_status_header.dart'; import '../../widgets/matrix.dart'; -import 'chat_list_header.dart'; class ChatListViewBody extends StatelessWidget { final ChatListController controller; @@ -76,7 +75,10 @@ class ChatListViewBody extends StatelessWidget { child: CustomScrollView( controller: controller.scrollController, slivers: [ - ChatListHeader(controller: controller), + // #Pangea + // ChatListHeader(controller: controller), + ChatListHeaderWrapper(controller: controller), + // Pangea# SliverList( delegate: SliverChildListDelegate( [ @@ -247,17 +249,23 @@ class ChatListViewBody extends StatelessWidget { SliverList.builder( itemCount: rooms.length, itemBuilder: (BuildContext context, int i) { - return ChatListItem( + // #Pangea + // return ChatListItem( + return ChatListItemWrapper( + controller: controller, + // Pangea# rooms[i], key: Key('chat_list_item_${rooms[i].id}'), filter: filter, - selected: - controller.selectedRoomIds.contains(rooms[i].id), - onTap: controller.selectMode == SelectMode.select - ? () => controller.toggleSelection(rooms[i].id) - : () => onChatTap(rooms[i], context), - onLongPress: () => - controller.toggleSelection(rooms[i].id), + // #Pangea + // selected: + // controller.selectedRoomIds.contains(rooms[i].id), + // onTap: controller.selectMode == SelectMode.select + // ? () => controller.toggleSelection(rooms[i].id) + // : () => onChatTap(rooms[i], context), + // onLongPress: () => + // controller.toggleSelection(rooms[i].id), + // Pangea# activeChat: controller.activeChat == rooms[i].id, ); }, diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index bdd19338d..d0ff8cdf5 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -4,7 +4,6 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; -import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; import 'package:fluffychat/pages/chat_list/utils/on_chat_tap.dart'; import 'package:fluffychat/pangea/constants/class_default_values.dart'; @@ -12,6 +11,8 @@ import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/utils/chat_list_handle_space_tap.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/chat_list_header_wrapper.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/chat_list_item_wrapper.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:flutter/material.dart'; @@ -23,7 +24,6 @@ import 'package:matrix/matrix.dart'; import '../../utils/localized_exception_extension.dart'; import '../../widgets/matrix.dart'; -import 'chat_list_header.dart'; class SpaceView extends StatefulWidget { final ChatListController controller; @@ -709,7 +709,10 @@ class _SpaceViewState extends State { child: CustomScrollView( controller: widget.scrollController, slivers: [ - ChatListHeader(controller: widget.controller), + // #Pangea + // ChatListHeader(controller: widget.controller), + ChatListHeaderWrapper(controller: widget.controller), + // Pangea# SliverList( delegate: SliverChildBuilderDelegate( (context, i) { @@ -789,7 +792,13 @@ class _SpaceViewState extends State { child: CustomScrollView( controller: widget.scrollController, slivers: [ - ChatListHeader(controller: widget.controller, globalSearch: false), + // #Pangea + // ChatListHeader(controller: widget.controller, globalSearch: false), + ChatListHeaderWrapper( + controller: widget.controller, + globalSearch: false, + ), + // Pangea# SliverAppBar( automaticallyImplyLeading: false, primary: false, @@ -911,7 +920,11 @@ class _SpaceViewState extends State { room.membership != Membership.leave // Pangea# ) { - return ChatListItem( + // #Pangea + // return ChatListItem( + return ChatListItemWrapper( + controller: widget.controller, + // Pangea# room, onLongPress: () => _onSpaceChildContextMenu(spaceChild, room), diff --git a/lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart b/lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart new file mode 100644 index 000000000..7944f37ab --- /dev/null +++ b/lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart @@ -0,0 +1,47 @@ +import 'dart:async'; + +import 'package:fluffychat/pages/chat_list/chat_list.dart'; +import 'package:fluffychat/pages/chat_list/chat_list_header.dart'; +import 'package:flutter/material.dart'; + +/// A wrapper around ChatListHeader to allow rebuilding on state changes. +/// Prevents having to rebuild the entire ChatList when a single item changes. +class ChatListHeaderWrapper extends StatefulWidget { + final ChatListController controller; + final bool globalSearch; + + const ChatListHeaderWrapper({ + super.key, + required this.controller, + this.globalSearch = true, + }); + + @override + ChatListHeaderWrapperState createState() => ChatListHeaderWrapperState(); +} + +class ChatListHeaderWrapperState extends State { + StreamSubscription? stateSub; + + @override + void initState() { + super.initState(); + stateSub = widget.controller.selectionsStream.stream.listen((roomID) { + setState(() {}); + }); + } + + @override + void dispose() { + stateSub?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ChatListHeader( + controller: widget.controller, + globalSearch: widget.globalSearch, + ); + } +} diff --git a/lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart b/lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart new file mode 100644 index 000000000..2d500bf93 --- /dev/null +++ b/lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart @@ -0,0 +1,71 @@ +import 'dart:async'; + +import 'package:fluffychat/pages/chat_list/chat_list.dart'; +import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; +import 'package:fluffychat/pages/chat_list/utils/on_chat_tap.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; + +/// A wrapper around ChatListItem to allow rebuilding on state changes. +/// Prevents having to rebuild the entire ChatList when a single item changes. +class ChatListItemWrapper extends StatefulWidget { + final Room room; + final bool activeChat; + final void Function()? onForget; + final String? filter; + final ChatListController controller; + + final void Function()? onLongPress; + final void Function()? onTap; + + const ChatListItemWrapper( + this.room, { + this.activeChat = false, + this.onForget, + this.filter, + required this.controller, + this.onLongPress, + this.onTap, + super.key, + }); + + @override + ChatListItemWrapperState createState() => ChatListItemWrapperState(); +} + +class ChatListItemWrapperState extends State { + StreamSubscription? stateSub; + + @override + void initState() { + super.initState(); + stateSub = widget.controller.selectionsStream.stream.listen((roomID) { + if (roomID == widget.room.id) { + setState(() {}); + } + }); + } + + @override + void dispose() { + stateSub?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ChatListItem( + widget.room, + activeChat: widget.activeChat, + selected: widget.controller.selectedRoomIds.contains(widget.room.id), + onTap: widget.onTap ?? + (widget.controller.selectMode == SelectMode.select + ? () => widget.controller.toggleSelection(widget.room.id) + : () => onChatTap(widget.room, context)), + onLongPress: widget.onLongPress ?? + () => widget.controller.toggleSelection(widget.room.id), + onForget: widget.onForget, + filter: widget.filter, + ); + } +} From acef3778f7405df5989624ce593ba53cc27f0e39 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 22 Jul 2024 13:53:46 -0400 Subject: [PATCH 16/20] made logic for determining if warning should show in translated card more readable and moved out of build function --- .../chat/message_translation_card.dart | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/pangea/widgets/chat/message_translation_card.dart b/lib/pangea/widgets/chat/message_translation_card.dart index 8ea66094d..68d3a6e95 100644 --- a/lib/pangea/widgets/chat/message_translation_card.dart +++ b/lib/pangea/widgets/chat/message_translation_card.dart @@ -10,7 +10,6 @@ import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; class MessageTranslationCard extends StatefulWidget { final PangeaMessageEvent messageEvent; @@ -133,6 +132,22 @@ class MessageTranslationCardState extends State { setState(() {}); } + /// Show warning if message's language code is user's L1 + /// or if translated text is same as original text. + /// Warning does not show if was previously closed + bool get showWarning { + if (MatrixState.pangeaController.instructions.wereInstructionsTurnedOff( + InlineInstructions.l1Translation.toString(), + )) return false; + + final bool isWrittenInL1 = + l1Code != null && widget.messageEvent.originalSent?.langCode == l1Code; + final bool isTextIdentical = selectionTranslation != null && + widget.messageEvent.originalSent?.text == selectionTranslation; + + return isWrittenInL1 || isTextIdentical; + } + @override Widget build(BuildContext context) { if (!_fetchingRepresentation && @@ -141,19 +156,6 @@ class MessageTranslationCardState extends State { return const CardErrorWidget(); } - // Show warning if message's language code is user's L1 - // or if translated text is same as original text - // Warning does not show if was previously closed - final bool showWarning = widget.messageEvent.originalSent != null && - ((!widget.immersionMode && - widget.messageEvent.originalSent!.langCode.equals(l1Code)) || - (selectionTranslation == null || - widget.messageEvent.originalSent!.text - .equals(selectionTranslation))) && - !MatrixState.pangeaController.instructions.wereInstructionsTurnedOff( - InlineInstructions.l1Translation.toString(), - ); - return Container( child: _fetchingRepresentation ? const ToolbarContentLoadingIndicator() From ed1070dbe334885b758eb9da794f39d89c262d5a Mon Sep 17 00:00:00 2001 From: Kelrap Date: Mon, 22 Jul 2024 17:05:36 -0400 Subject: [PATCH 17/20] Decrease audio toolbar padding --- lib/pages/chat/events/audio_player.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 82a06ba79..2055544f3 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -298,7 +298,7 @@ class AudioPlayerState extends State { final statusText = this.statusText ??= _durationString ?? '00:00'; final audioPlayer = this.audioPlayer; return Padding( - padding: const EdgeInsets.all(12.0), + padding: const EdgeInsets.all(5.0), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -332,7 +332,7 @@ class AudioPlayerState extends State { }, ), ), - const SizedBox(width: 8), + const SizedBox(width: 5), Row( mainAxisSize: MainAxisSize.min, children: [ @@ -368,7 +368,7 @@ class AudioPlayerState extends State { ), ], ), - const SizedBox(width: 8), + const SizedBox(width: 5), SizedBox( width: 36, child: Text( From a3a75262c955812214024ce455ac82977a0e832c Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 23 Jul 2024 10:49:46 -0400 Subject: [PATCH 18/20] Add #Pangea comments --- lib/pages/chat/events/audio_player.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 2055544f3..8ab4d067a 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -298,7 +298,10 @@ class AudioPlayerState extends State { final statusText = this.statusText ??= _durationString ?? '00:00'; final audioPlayer = this.audioPlayer; return Padding( + // #Pangea + // padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(5.0), + // Pangea# child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -332,7 +335,10 @@ class AudioPlayerState extends State { }, ), ), + // #Pangea + // const SizedBox(width: 8), const SizedBox(width: 5), + // Pangea# Row( mainAxisSize: MainAxisSize.min, children: [ @@ -368,7 +374,10 @@ class AudioPlayerState extends State { ), ], ), + // #Pangea + // const SizedBox(width: 8), const SizedBox(width: 5), + // Pangea# SizedBox( width: 36, child: Text( From bed27abe510ab6add55ae029ab42f747df577bce Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 24 Jul 2024 12:59:52 -0400 Subject: [PATCH 19/20] added sentry breadcrumbs to help track down ios logout issue --- lib/pangea/utils/p_store.dart | 4 ++++ .../flutter_matrix_dart_sdk_database/builder.dart | 10 ++++++++++ .../flutter_matrix_dart_sdk_database/cipher.dart | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/lib/pangea/utils/p_store.dart b/lib/pangea/utils/p_store.dart index 0dfe0d5cd..233975fc5 100644 --- a/lib/pangea/utils/p_store.dart +++ b/lib/pangea/utils/p_store.dart @@ -1,5 +1,6 @@ import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:get_storage/get_storage.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; /// Utility to save and read data both in the matrix profile (this is the default /// behavior) and in the local storage (local needs to be specificied). An @@ -66,6 +67,9 @@ class PStore { /// Clears the storage by erasing all data in the box. void clearStorage() { + // this could potenitally be interfering with openning database + // at the start of the session, which is causing auto log outs on iOS + Sentry.addBreadcrumb(Breadcrumb(message: 'Clearing local storage')); _box.erase(); } } diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart index 655fea198..b5665c635 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart @@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:universal_html/html.dart' as html; @@ -80,6 +81,9 @@ Future _constructDatabase(Client client) async { } final cipher = await getDatabaseCipher(); + // #Pangea + Sentry.addBreadcrumb(Breadcrumb(message: 'Database cipher: $cipher')); + // Pangea# Directory? fileStorageLocation; try { @@ -97,6 +101,9 @@ Future _constructDatabase(Client client) async { // import the SQLite / SQLCipher shared objects / dynamic libraries final factory = createDatabaseFactoryFfi(ffiInit: SQfLiteEncryptionHelper.ffiInit); + // #Pangea + Sentry.addBreadcrumb(Breadcrumb(message: 'Database path: $path')); + // Pangea# // migrate from potential previous SQLite database path to current one await _migrateLegacyLocation(path, client.clientName); @@ -113,6 +120,9 @@ Future _constructDatabase(Client client) async { path: path, cipher: cipher, ); + // #Pangea + Sentry.addBreadcrumb(Breadcrumb(message: 'Database cipher helper: $helper')); + // Pangea# // check whether the DB is already encrypted and otherwise do so await helper?.ensureDatabaseFileEncrypted(); diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart index 612f74395..bfe1251dc 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart @@ -5,6 +5,7 @@ import 'package:fluffychat/config/setting_keys.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:matrix/matrix.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; const _passwordStorageKey = 'database_password'; @@ -58,6 +59,12 @@ void _sendNoEncryptionWarning(Object exception) async { // l10n.noDatabaseEncryption, // exception.toString(), // ); + Sentry.addBreadcrumb( + Breadcrumb( + message: 'No database encryption', + data: {'exception': exception}, + ), + ); // Pangea# await store.setBool(SettingKeys.noEncryptionWarningShown, true); From 9f6cd047aa4d75cc2313c8b1396ac4ebef00a85d Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 24 Jul 2024 13:25:16 -0400 Subject: [PATCH 20/20] auto reload space hierarchy view after it's invalidated in the matrix SDK --- lib/pages/chat_list/space_view.dart | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index d0ff8cdf5..ccc9aa9c4 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -53,6 +53,25 @@ class _SpaceViewState extends State { widget.controller.pangeaController.pStoreService.read(_chatCountsKey) ?? {}, ); + + /// Used to filter out sync updates with hierarchy updates for the active + /// space so that the view can be auto-reloaded in the room subscription + bool hasHierarchyUpdate(SyncUpdate update) { + final joinTimeline = + update.rooms?.join?[widget.controller.activeSpaceId]?.timeline; + final leaveTimeline = + update.rooms?.leave?[widget.controller.activeSpaceId]?.timeline; + if (joinTimeline == null && leaveTimeline == null) return false; + final bool hasJoinUpdate = joinTimeline?.events?.any( + (event) => event.type == EventTypes.SpaceChild, + ) ?? + false; + final bool hasLeaveUpdate = leaveTimeline?.events?.any( + (event) => event.type == EventTypes.SpaceChild, + ) ?? + false; + return hasJoinUpdate || hasLeaveUpdate; + } // Pangea# @override @@ -78,12 +97,9 @@ class _SpaceViewState extends State { // Listen for changes to the activeSpace's hierarchy, // and reload the hierarchy when they come through final client = Matrix.of(context).client; - _roomSubscription ??= client.onRoomState.stream.where((u) { - return u.state.type == EventTypes.SpaceChild && - u.roomId == widget.controller.activeSpaceId; - }).listen((update) { - loadHierarchy(hasUpdate: true); - }); + _roomSubscription ??= client.onSync.stream + .where(hasHierarchyUpdate) + .listen((update) => loadHierarchy(hasUpdate: true)); // Pangea# super.initState(); }