From 08da254bae57872471fa3a221832e14b2bf5f7d9 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Thu, 18 Jul 2024 16:33:54 -0400 Subject: [PATCH 01/13] Input text turns red when hit limit --- lib/pages/chat/input_bar.dart | 3 +++ lib/pangea/widgets/chat/input_bar_wrapper.dart | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 9337b488a..0d2251203 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -504,6 +504,9 @@ class InputBar extends StatelessWidget { onSubmitted!(text); }, // #Pangea + style: controller?.text.length == 1000 + ? const TextStyle(color: Colors.red) + : null, onTap: () { controller!.onInputTap( context, diff --git a/lib/pangea/widgets/chat/input_bar_wrapper.dart b/lib/pangea/widgets/chat/input_bar_wrapper.dart index 374f60a80..5f6c1b49b 100644 --- a/lib/pangea/widgets/chat/input_bar_wrapper.dart +++ b/lib/pangea/widgets/chat/input_bar_wrapper.dart @@ -61,6 +61,11 @@ class InputBarWrapperState extends State { super.dispose(); } + void refreshOnChange(String text) { + widget.onChanged!(text); + setState(() {}); + } + @override Widget build(BuildContext context) { return InputBar( @@ -73,7 +78,7 @@ class InputBarWrapperState extends State { focusNode: widget.focusNode, controller: widget.controller, decoration: widget.decoration, - onChanged: widget.onChanged, + onChanged: widget.onChanged != null ? refreshOnChange : null, autofocus: widget.autofocus, textInputAction: widget.textInputAction, readOnly: widget.readOnly, From 828b406286926f622cac999e70d345687d24c95c Mon Sep 17 00:00:00 2001 From: Kelrap Date: Mon, 22 Jul 2024 10:04:18 -0400 Subject: [PATCH 02/13] Only rebuild when maxLength changes --- lib/pages/chat/input_bar.dart | 14 +++++++++++--- lib/pangea/widgets/chat/input_bar_wrapper.dart | 6 +++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 0d2251203..4ffde1f42 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -21,6 +21,7 @@ class InputBar extends StatelessWidget { final ValueChanged? onSubmitImage; final FocusNode? focusNode; // #Pangea + final Function? updateBar; // final TextEditingController? controller; final PangeaTextController? controller; // Pangea# @@ -38,6 +39,7 @@ class InputBar extends StatelessWidget { this.onSubmitImage, this.focusNode, this.controller, + this.updateBar, this.decoration, this.onChanged, this.autofocus, @@ -401,6 +403,9 @@ class InputBar extends StatelessWidget { @override Widget build(BuildContext context) { final useShortCuts = (AppConfig.sendOnEnter ?? !PlatformInfos.isMobile); + // #Pangea + final bool maxLength = controller?.text.length == 1000; + // Pangea# return Shortcuts( shortcuts: !useShortCuts ? {} @@ -504,9 +509,7 @@ class InputBar extends StatelessWidget { onSubmitted!(text); }, // #Pangea - style: controller?.text.length == 1000 - ? const TextStyle(color: Colors.red) - : null, + style: maxLength ? const TextStyle(color: Colors.red) : null, onTap: () { controller!.onInputTap( context, @@ -519,6 +522,11 @@ class InputBar extends StatelessWidget { // fix for the library for now // it sets the types for the callback incorrectly onChanged!(text); + // #Pangea + if (maxLength != (controller?.text.length == 1000)) { + updateBar!(); + } + // Pangea# }, textCapitalization: TextCapitalization.sentences, ), diff --git a/lib/pangea/widgets/chat/input_bar_wrapper.dart b/lib/pangea/widgets/chat/input_bar_wrapper.dart index 5f6c1b49b..5aa813bbe 100644 --- a/lib/pangea/widgets/chat/input_bar_wrapper.dart +++ b/lib/pangea/widgets/chat/input_bar_wrapper.dart @@ -61,8 +61,7 @@ class InputBarWrapperState extends State { super.dispose(); } - void refreshOnChange(String text) { - widget.onChanged!(text); + void refreshOnChange() { setState(() {}); } @@ -78,7 +77,8 @@ class InputBarWrapperState extends State { focusNode: widget.focusNode, controller: widget.controller, decoration: widget.decoration, - onChanged: widget.onChanged != null ? refreshOnChange : null, + updateBar: refreshOnChange, + onChanged: widget.onChanged, autofocus: widget.autofocus, textInputAction: widget.textInputAction, readOnly: widget.readOnly, From f2e112789d33f479c7226d23173e9ee8e290f71f Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 23 Jul 2024 10:17:40 -0400 Subject: [PATCH 03/13] Permissions default to yes/student choice --- .../controllers/permissions_controller.dart | 105 ++++++++++-------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/lib/pangea/controllers/permissions_controller.dart b/lib/pangea/controllers/permissions_controller.dart index ed84e13c3..175e048f3 100644 --- a/lib/pangea/controllers/permissions_controller.dart +++ b/lib/pangea/controllers/permissions_controller.dart @@ -1,5 +1,4 @@ import 'package:fluffychat/pangea/constants/age_limits.dart'; -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/controllers/base_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; @@ -36,63 +35,73 @@ class PermissionsController extends BaseController { return dob?.isAtLeastYearsOld(AgeLimits.toAccessFeatures) ?? false; } - /// A user can private chat if - /// 1) they are 18 and outside a class context or - /// 2) they are in a class context and the class rules permit it - /// If no class is passed, uses classController.activeClass + /// A user can private chat if they are 18+ bool canUserPrivateChat({String? roomID}) { - final Room? classContext = - firstRoomWithState(roomID: roomID, type: PangeaEventTypes.rules); - return classContext?.pangeaRoomRules == null - ? isUser18() - : classContext!.pangeaRoomRules!.oneToOneChatClass || - classContext.isRoomAdmin; + return isUser18(); + // Rules can't be edited; default to true + // final Room? classContext = + // firstRoomWithState(roomID: roomID, type: PangeaEventTypes.rules); + // return classContext?.pangeaRoomRules == null + // ? isUser18() + // : classContext!.pangeaRoomRules!.oneToOneChatClass || + // classContext.isRoomAdmin; } bool canUserGroupChat({String? roomID}) { - final Room? classContext = - firstRoomWithState(roomID: roomID, type: PangeaEventTypes.rules); - - return classContext?.pangeaRoomRules == null - ? isUser18() - : classContext!.pangeaRoomRules!.isCreateRooms || - classContext.isRoomAdmin; + return isUser18(); + // Rules can't be edited; default to true + // final Room? classContext = + // firstRoomWithState(roomID: roomID, type: PangeaEventTypes.rules); + + // return classContext?.pangeaRoomRules == null + // ? isUser18() + // : classContext!.pangeaRoomRules!.isCreateRooms || + // classContext.isRoomAdmin; } bool showChatInputAddButton(String roomId) { final PangeaRoomRules? perms = _getRoomRules(roomId); if (perms == null) return isUser18(); - return perms.isShareFiles || - perms.isShareLocation || - perms.isSharePhoto || - perms.isShareVideo; + // Rules can't be edited; default to true + // return perms.isShareFiles || + // perms.isShareLocation || + // perms.isSharePhoto || + // perms.isShareVideo; + return true; } /// works for both roomID of chat and class - bool canShareVideo(String? roomID) => - _getRoomRules(roomID)?.isShareVideo ?? isUser18(); + bool canShareVideo(String? roomID) => isUser18(); + // Rules can't be edited; default to true + // _getRoomRules(roomID)?.isShareVideo ?? isUser18(); /// works for both roomID of chat and class - bool canSharePhoto(String? roomID) => - _getRoomRules(roomID)?.isSharePhoto ?? isUser18(); + bool canSharePhoto(String? roomID) => isUser18(); + // Rules can't be edited; default to true + // _getRoomRules(roomID)?.isSharePhoto ?? isUser18(); /// works for both roomID of chat and class - bool canShareFile(String? roomID) => - _getRoomRules(roomID)?.isShareFiles ?? isUser18(); + bool canShareFile(String? roomID) => isUser18(); + // Rules can't be edited; default to true + // _getRoomRules(roomID)?.isShareFiles ?? isUser18(); /// works for both roomID of chat and class - bool canShareLocation(String? roomID) => - _getRoomRules(roomID)?.isShareLocation ?? isUser18(); + bool canShareLocation(String? roomID) => isUser18(); + // Rules can't be edited; default to true + // _getRoomRules(roomID)?.isShareLocation ?? isUser18(); - int? classLanguageToolPermission(Room room, ToolSetting setting) => - room.firstRules?.getToolSettings(setting); + int? classLanguageToolPermission(Room room, ToolSetting setting) => 1; + // Rules can't be edited; default to student choice + // room.firstRules?.getToolSettings(setting); - //what happens if a room isn't in a class? + // what happens if a room isn't in a class? bool isToolDisabledByClass(ToolSetting setting, Room? room) { - if (room?.isSpaceAdmin ?? false) return false; - final int? classPermission = - room != null ? classLanguageToolPermission(room, setting) : 1; - return classPermission == 0; + return false; + // Rules can't be edited; default to false + // if (room?.isSpaceAdmin ?? false) return false; + // final int? classPermission = + // room != null ? classLanguageToolPermission(room, setting) : 1; + // return classPermission == 0; } bool userToolSetting(ToolSetting setting) { @@ -117,18 +126,22 @@ class PermissionsController extends BaseController { } bool isToolEnabled(ToolSetting setting, Room? room) { - if (room?.isSpaceAdmin ?? false) { - return userToolSetting(setting); - } - final int? classPermission = - room != null ? classLanguageToolPermission(room, setting) : 1; - if (classPermission == 0) return false; - if (classPermission == 2) return true; + // Rules can't be edited; default to true return userToolSetting(setting); + // if (room?.isSpaceAdmin ?? false) { + // return userToolSetting(setting); + // } + // final int? classPermission = + // room != null ? classLanguageToolPermission(room, setting) : 1; + // if (classPermission == 0) return false; + // if (classPermission == 2) return true; + // return userToolSetting(setting); } bool isWritingAssistanceEnabled(Room? room) { - return isToolEnabled(ToolSetting.interactiveTranslator, room) && - isToolEnabled(ToolSetting.interactiveGrammar, room); + // Rules can't be edited; default to true + return true; + // return isToolEnabled(ToolSetting.interactiveTranslator, room) && + // isToolEnabled(ToolSetting.interactiveGrammar, room); } } From 8c1df0eb88c85c663e0e0f4f28c015b297ff4533 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 23 Jul 2024 12:35:53 -0400 Subject: [PATCH 04/13] Move calculations to state --- lib/pages/chat/input_bar.dart | 13 ++++--------- lib/pangea/widgets/chat/input_bar_wrapper.dart | 13 +++++++++---- lib/pangea/widgets/igc/pangea_text_controller.dart | 5 +++++ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 4ffde1f42..54dba8674 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -21,7 +21,6 @@ class InputBar extends StatelessWidget { final ValueChanged? onSubmitImage; final FocusNode? focusNode; // #Pangea - final Function? updateBar; // final TextEditingController? controller; final PangeaTextController? controller; // Pangea# @@ -39,7 +38,6 @@ class InputBar extends StatelessWidget { this.onSubmitImage, this.focusNode, this.controller, - this.updateBar, this.decoration, this.onChanged, this.autofocus, @@ -404,7 +402,7 @@ class InputBar extends StatelessWidget { Widget build(BuildContext context) { final useShortCuts = (AppConfig.sendOnEnter ?? !PlatformInfos.isMobile); // #Pangea - final bool maxLength = controller?.text.length == 1000; + controller?.currentlyMaxLength = controller?.isMaxLength ?? false; // Pangea# return Shortcuts( shortcuts: !useShortCuts @@ -509,7 +507,9 @@ class InputBar extends StatelessWidget { onSubmitted!(text); }, // #Pangea - style: maxLength ? const TextStyle(color: Colors.red) : null, + style: controller?.isMaxLength ?? false + ? const TextStyle(color: Colors.red) + : null, onTap: () { controller!.onInputTap( context, @@ -522,11 +522,6 @@ class InputBar extends StatelessWidget { // fix for the library for now // it sets the types for the callback incorrectly onChanged!(text); - // #Pangea - if (maxLength != (controller?.text.length == 1000)) { - updateBar!(); - } - // Pangea# }, textCapitalization: TextCapitalization.sentences, ), diff --git a/lib/pangea/widgets/chat/input_bar_wrapper.dart b/lib/pangea/widgets/chat/input_bar_wrapper.dart index 5aa813bbe..1e8cd4727 100644 --- a/lib/pangea/widgets/chat/input_bar_wrapper.dart +++ b/lib/pangea/widgets/chat/input_bar_wrapper.dart @@ -61,8 +61,14 @@ class InputBarWrapperState extends State { super.dispose(); } - void refreshOnChange() { - setState(() {}); + void refreshOnChange(String text) { + if (widget.onChanged != null) { + widget.onChanged!(text); + } + if (widget.controller?.currentlyMaxLength != + widget.controller?.isMaxLength) { + setState(() {}); + } } @override @@ -77,8 +83,7 @@ class InputBarWrapperState extends State { focusNode: widget.focusNode, controller: widget.controller, decoration: widget.decoration, - updateBar: refreshOnChange, - onChanged: widget.onChanged, + onChanged: refreshOnChange, autofocus: widget.autofocus, textInputAction: widget.textInputAction, readOnly: widget.readOnly, diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index b91186c22..d7f24a7e2 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -25,6 +25,11 @@ class PangeaTextController extends TextEditingController { text ??= ''; this.text = text; } + + bool get isMaxLength => text.length == 1000; + + bool currentlyMaxLength = false; + bool forceKeepOpen = false; setSystemText(String text, EditType type) { From a87c296c1366298e75f2c96ba2893c2244620891 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 23 Jul 2024 12:41:39 -0400 Subject: [PATCH 05/13] Fix difference in function --- lib/pangea/controllers/permissions_controller.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pangea/controllers/permissions_controller.dart b/lib/pangea/controllers/permissions_controller.dart index 175e048f3..3a8eca775 100644 --- a/lib/pangea/controllers/permissions_controller.dart +++ b/lib/pangea/controllers/permissions_controller.dart @@ -60,14 +60,14 @@ class PermissionsController extends BaseController { } bool showChatInputAddButton(String roomId) { - final PangeaRoomRules? perms = _getRoomRules(roomId); - if (perms == null) return isUser18(); // Rules can't be edited; default to true + // final PangeaRoomRules? perms = _getRoomRules(roomId); + // if (perms == null) return isUser18(); // return perms.isShareFiles || // perms.isShareLocation || // perms.isSharePhoto || // perms.isShareVideo; - return true; + return isUser18(); } /// works for both roomID of chat and class From a7e6e7a4c9ffbbb876d954883260898f7044bce9 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 23 Jul 2024 15:16:34 -0400 Subject: [PATCH 06/13] Shorten overlay instead of toolbar --- lib/pages/chat/events/message_content.dart | 13 +- lib/pangea/widgets/chat/message_toolbar.dart | 151 ++++++++++--------- lib/pangea/widgets/chat/overlay_message.dart | 140 ++++++++--------- 3 files changed, 159 insertions(+), 145 deletions(-) diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 01ae471f8..5468b59e8 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -289,17 +289,20 @@ class MessageContent extends StatelessWidget { // #Pangea // return Linkify( final messageTextStyle = TextStyle( + overflow: TextOverflow.ellipsis, color: textColor, fontSize: bigEmotes ? fontSize * 3 : fontSize, decoration: event.redacted ? TextDecoration.lineThrough : null, height: 1.3, ); if (immersionMode && pangeaMessageEvent != null) { - return PangeaRichText( - style: messageTextStyle, - pangeaMessageEvent: pangeaMessageEvent!, - immersionMode: immersionMode, - toolbarController: toolbarController, + return Flexible( + child: PangeaRichText( + style: messageTextStyle, + pangeaMessageEvent: pangeaMessageEvent!, + immersionMode: immersionMode, + toolbarController: toolbarController, + ), ); } else if (pangeaMessageEvent != null) { toolbarController?.toolbar?.textSelection.setMessageText( diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 5698b45c1..d4270fe5a 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -63,6 +63,7 @@ class ToolbarDisplayController { MessageMode? mode, }) { bool toolbarUp = true; + bool messageTooLong = false; if (highlighted) return; if (controller.selectMode) { controller.clearSelectedEvents(); @@ -82,6 +83,10 @@ class ToolbarDisplayController { messageWidth = transformTargetSize.width; final Offset targetOffset = (targetRenderBox).localToGlobal(Offset.zero); + // If the message is too long, will need to anchor by toolbar + messageTooLong = + transformTargetSize.height > MediaQuery.of(context).size.height - 320; + // If there is enough space above, procede as normal // Else if there is enough space below, show toolbar underneath if (targetOffset.dy < 320) { @@ -419,85 +424,87 @@ class MessageToolbarState extends State { @override Widget build(BuildContext context) { - 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), - ), + 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, ), - constraints: const BoxConstraints( - maxWidth: 300, - minWidth: 300, - maxHeight: 300, + borderRadius: const BorderRadius.all( + Radius.circular(25), ), - 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), - ], - ), + ), + 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), + ], ), ), ), - 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, + ), + 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, + ), + ), + ], + ), + ], + // ), ), ), ); diff --git a/lib/pangea/widgets/chat/overlay_message.dart b/lib/pangea/widgets/chat/overlay_message.dart index 5f3d46c7e..31e2b10b1 100644 --- a/lib/pangea/widgets/chat/overlay_message.dart +++ b/lib/pangea/widgets/chat/overlay_message.dart @@ -118,81 +118,85 @@ class OverlayMessage extends StatelessWidget { ownMessage: ownMessage, ); - return Material( - color: noBubble ? Colors.transparent : color, - clipBehavior: Clip.antiAlias, - shape: RoundedRectangleBorder( - borderRadius: borderRadius, - ), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - ), - padding: noBubble || noPadding - ? EdgeInsets.zero - : const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - constraints: BoxConstraints( - maxWidth: width ?? FluffyThemes.columnWidth * 1.25, + return Flexible( + child: Material( + color: noBubble ? Colors.transparent : color, + clipBehavior: Clip.antiAlias, + shape: RoundedRectangleBorder( + borderRadius: borderRadius, ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - MessageContent( - event.getDisplayEvent(timeline), - textColor: textColor, - borderRadius: borderRadius, - selected: selected, - pangeaMessageEvent: pangeaMessageEvent, - immersionMode: immersionMode, - toolbarController: toolbarController, - isOverlay: true, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, ), - if (event.hasAggregatedEvents( - timeline, - RelationshipTypes.edit, - ) || - (pangeaMessageEvent.showUseType)) - Padding( - padding: const EdgeInsets.only( - top: 4.0, + ), + padding: noBubble || noPadding + ? EdgeInsets.zero + : const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (pangeaMessageEvent.showUseType) ...[ - pangeaMessageEvent.msgUseType.iconView( - context, - textColor.withAlpha(164), - ), - const SizedBox(width: 4), - ], - if (event.hasAggregatedEvents( - timeline, - RelationshipTypes.edit, - )) ...[ - Icon( - Icons.edit_outlined, - color: textColor.withAlpha(164), - size: 14, - ), - Text( - ' - ${event.getDisplayEvent(timeline).originServerTs.localizedTimeShort(context)}', - style: TextStyle( + constraints: BoxConstraints( + maxWidth: width ?? FluffyThemes.columnWidth * 1.25, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: MessageContent( + event.getDisplayEvent(timeline), + textColor: textColor, + borderRadius: borderRadius, + selected: selected, + pangeaMessageEvent: pangeaMessageEvent, + immersionMode: immersionMode, + toolbarController: toolbarController, + isOverlay: true, + ), + ), + if (event.hasAggregatedEvents( + timeline, + RelationshipTypes.edit, + ) || + (pangeaMessageEvent.showUseType)) + Padding( + padding: const EdgeInsets.only( + top: 4.0, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (pangeaMessageEvent.showUseType) ...[ + pangeaMessageEvent.msgUseType.iconView( + context, + textColor.withAlpha(164), + ), + const SizedBox(width: 4), + ], + if (event.hasAggregatedEvents( + timeline, + RelationshipTypes.edit, + )) ...[ + Icon( + Icons.edit_outlined, color: textColor.withAlpha(164), - fontSize: 12, + size: 14, ), - ), + Text( + ' - ${event.getDisplayEvent(timeline).originServerTs.localizedTimeShort(context)}', + style: TextStyle( + color: textColor.withAlpha(164), + fontSize: 12, + ), + ), + ], ], - ], + ), ), - ), - ], + ], + ), ), ), ); From 51bf91d8e5f7301e31659a7dec1a2b77194195e0 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 23 Jul 2024 15:22:39 -0400 Subject: [PATCH 07/13] Edits I forgot to save earlier --- lib/pangea/widgets/chat/message_toolbar.dart | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index d4270fe5a..74fd4b7a6 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -63,7 +63,6 @@ class ToolbarDisplayController { MessageMode? mode, }) { bool toolbarUp = true; - bool messageTooLong = false; if (highlighted) return; if (controller.selectMode) { controller.clearSelectedEvents(); @@ -83,10 +82,6 @@ class ToolbarDisplayController { messageWidth = transformTargetSize.width; final Offset targetOffset = (targetRenderBox).localToGlobal(Offset.zero); - // If the message is too long, will need to anchor by toolbar - messageTooLong = - transformTargetSize.height > MediaQuery.of(context).size.height - 320; - // If there is enough space above, procede as normal // Else if there is enough space below, show toolbar underneath if (targetOffset.dy < 320) { @@ -424,10 +419,7 @@ class MessageToolbarState extends State { @override Widget build(BuildContext context) { - return - // Flexible( - // child: - Material( + return Material( type: MaterialType.transparency, child: Container( padding: const EdgeInsets.all(10), @@ -504,7 +496,6 @@ class MessageToolbarState extends State { ], ), ], - // ), ), ), ); From cc58771de0a0eca5998fcccda707ad6a8da1a9fa Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 24 Jul 2024 08:50:47 -0400 Subject: [PATCH 08/13] Silences web focus error --- lib/pages/chat/chat.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index e1af6a2c0..3ebe2dd98 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -475,10 +475,10 @@ class ChatController extends State if (kIsWeb && !Matrix.of(context).webHasFocus) return; // #Pangea } catch (err, s) { - ErrorHandler.logError( - e: PangeaWarningError("Web focus error: $err"), - s: s, - ); + // ErrorHandler.logError( + // e: PangeaWarningError("Web focus error: $err"), + // s: s, + // ); return; } // Pangea# From cfdeb40732e7398604937b03d1fbb1acf838a945 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 24 Jul 2024 08:57:19 -0400 Subject: [PATCH 09/13] Add #Pangea comments --- lib/pages/chat/chat.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 3ebe2dd98..1f32bcc64 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -475,10 +475,12 @@ class ChatController extends State if (kIsWeb && !Matrix.of(context).webHasFocus) return; // #Pangea } catch (err, s) { + // #Pangea // ErrorHandler.logError( // e: PangeaWarningError("Web focus error: $err"), // s: s, // ); + // Pangea# return; } // Pangea# From 859510be99a267b9bf7fe9ed18fcdcb5c2420ab8 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 24 Jul 2024 12:05:49 -0400 Subject: [PATCH 10/13] Prevents invite error --- .../room_analytics_extension.dart | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) 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 a0d6c21c9..b053fc409 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -103,17 +103,19 @@ extension AnalyticsRoomExtension on Room { .where((teacher) => !participants.contains(teacher)) .toList(); - Future.wait( - uninvitedTeachers.map( - (teacher) => analyticsRoom.invite(teacher.id).catchError((err, s) { - ErrorHandler.logError( - e: err, - m: "Failed to invite teacher ${teacher.id} to analytics room ${analyticsRoom.id}", - s: s, - ); - }), - ), - ); + if (!canSendEvent(EventTypes.SpaceChild)) { + Future.wait( + uninvitedTeachers.map( + (teacher) => analyticsRoom.invite(teacher.id).catchError((err, s) { + ErrorHandler.logError( + e: err, + m: "Failed to invite teacher ${teacher.id} to analytics room ${analyticsRoom.id}", + s: s, + ); + }), + ), + ); + } } /// Invite all the user's teachers to 1 analytics room. From b510a09c9053e58e305c100928896a82757d5da3 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 24 Jul 2024 13:45:16 -0400 Subject: [PATCH 11/13] Fix logic error --- .../pangea_room_extension/room_analytics_extension.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 b053fc409..3a2e62c86 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -54,6 +54,7 @@ extension AnalyticsRoomExtension on Room { return Future.value(); } + // Checks that user has permission to add child to space if (!canSendEvent(EventTypes.SpaceChild)) return; if (spaceChildren.any((sc) => sc.roomId == analyticsRoom.id)) return; @@ -103,7 +104,7 @@ extension AnalyticsRoomExtension on Room { .where((teacher) => !participants.contains(teacher)) .toList(); - if (!canSendEvent(EventTypes.SpaceChild)) { + if (analyticsRoom.canSendEvent(EventTypes.RoomMember)) { Future.wait( uninvitedTeachers.map( (teacher) => analyticsRoom.invite(teacher.id).catchError((err, s) { From d37aae9cbf43978b6537d5fb6dcf387ecac082fc Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 24 Jul 2024 13:47:32 -0400 Subject: [PATCH 12/13] Delete commented code --- lib/pages/chat/chat.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 1f32bcc64..c61beafd2 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -475,12 +475,6 @@ class ChatController extends State if (kIsWeb && !Matrix.of(context).webHasFocus) return; // #Pangea } catch (err, s) { - // #Pangea - // ErrorHandler.logError( - // e: PangeaWarningError("Web focus error: $err"), - // s: s, - // ); - // Pangea# return; } // Pangea# From 6311df08756d919cf50fd9707e83133b7db5492b Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 25 Jul 2024 11:25:59 -0400 Subject: [PATCH 13/13] moved stateful variable from text controller to input bar wrapper widget --- lib/pages/chat/input_bar.dart | 3 --- lib/pangea/widgets/chat/input_bar_wrapper.dart | 13 +++++++++++-- lib/pangea/widgets/igc/pangea_text_controller.dart | 3 +-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 54dba8674..84a802e54 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -401,9 +401,6 @@ class InputBar extends StatelessWidget { @override Widget build(BuildContext context) { final useShortCuts = (AppConfig.sendOnEnter ?? !PlatformInfos.isMobile); - // #Pangea - controller?.currentlyMaxLength = controller?.isMaxLength ?? false; - // Pangea# return Shortcuts( shortcuts: !useShortCuts ? {} diff --git a/lib/pangea/widgets/chat/input_bar_wrapper.dart b/lib/pangea/widgets/chat/input_bar_wrapper.dart index 1e8cd4727..9441312bd 100644 --- a/lib/pangea/widgets/chat/input_bar_wrapper.dart +++ b/lib/pangea/widgets/chat/input_bar_wrapper.dart @@ -44,6 +44,7 @@ class InputBarWrapper extends StatefulWidget { class InputBarWrapperState extends State { StreamSubscription? _choreoSub; + String _currentText = ''; @override void initState() { @@ -65,10 +66,18 @@ class InputBarWrapperState extends State { if (widget.onChanged != null) { widget.onChanged!(text); } - if (widget.controller?.currentlyMaxLength != - widget.controller?.isMaxLength) { + + final bool decreasedFromMaxLength = + _currentText.length >= PangeaTextController.maxLength && + text.length < PangeaTextController.maxLength; + final bool reachedMaxLength = + _currentText.length < PangeaTextController.maxLength && + text.length < PangeaTextController.maxLength; + + if (decreasedFromMaxLength || reachedMaxLength) { setState(() {}); } + _currentText = text; } @override diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index d7f24a7e2..8fc136edd 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -26,10 +26,9 @@ class PangeaTextController extends TextEditingController { this.text = text; } + static const int maxLength = 1000; bool get isMaxLength => text.length == 1000; - bool currentlyMaxLength = false; - bool forceKeepOpen = false; setSystemText(String text, EditType type) {