diff --git a/lib/pangea/toolbar/layout/message_selection_positioner.dart b/lib/pangea/toolbar/layout/message_selection_positioner.dart index 0f0440b2b..8ae896346 100644 --- a/lib/pangea/toolbar/layout/message_selection_positioner.dart +++ b/lib/pangea/toolbar/layout/message_selection_positioner.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; +import 'package:provider/provider.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/setting_keys.dart'; @@ -13,6 +14,8 @@ import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; +import 'package:fluffychat/pangea/languages/language_constants.dart'; +import 'package:fluffychat/pangea/languages/locale_provider.dart'; import 'package:fluffychat/pangea/toolbar/layout/over_message_overlay.dart'; import 'package:fluffychat/pangea/toolbar/layout/practice_mode_transition_animation.dart'; import 'package:fluffychat/pangea/toolbar/layout/reading_assistance_mode_enum.dart'; @@ -259,19 +262,53 @@ class MessageSelectionPositionerState extends State ); } + bool get isRtl { + final locale = Provider.of(context, listen: false) + .locale + ?.languageCode; + return locale != null && + LanguageConstants.rtlLanguageCodes.contains(locale); + } + double? get messageLeftOffset { + if (ownMessage) return null; + + if (isRtl) { + return _originalMessageOffset.dx - + (showDetails ? FluffyThemes.columnWidth : 0); + } + if (ownMessage) return null; return max(_originalMessageOffset.dx - columnWidth, 0); } double? get messageRightOffset { if (mediaQuery == null || !ownMessage) return null; + + if (isRtl) { + return mediaQuery!.size.width - + columnWidth - + _originalMessageOffset.dx - + originalMessageSize.width; + } + return mediaQuery!.size.width - _originalMessageOffset.dx - originalMessageSize.width - (showDetails ? FluffyThemes.columnWidth : 0); } + Alignment get messageAlignment { + return ownMessage ? Alignment.bottomRight : Alignment.bottomLeft; + } + + CrossAxisAlignment get messageColumnAlignment { + if (isRtl) { + return ownMessage ? CrossAxisAlignment.start : CrossAxisAlignment.end; + } + return ownMessage ? CrossAxisAlignment.end : CrossAxisAlignment.start; + } + double get _contentHeight { final messageHeight = _overlayMessageSize?.height ?? originalMessageSize.height; diff --git a/lib/pangea/toolbar/layout/over_message_overlay.dart b/lib/pangea/toolbar/layout/over_message_overlay.dart index b32f9a0d8..8fa6eeda8 100644 --- a/lib/pangea/toolbar/layout/over_message_overlay.dart +++ b/lib/pangea/toolbar/layout/over_message_overlay.dart @@ -17,77 +17,77 @@ class OverMessageOverlay extends StatelessWidget { @override Widget build(BuildContext context) { return Align( - alignment: - controller.ownMessage ? Alignment.bottomRight : Alignment.bottomLeft, + alignment: controller.messageAlignment, child: Padding( padding: EdgeInsets.only( left: controller.messageLeftOffset ?? 0.0, right: controller.messageRightOffset ?? 0.0, ), - child: SingleChildScrollView( - controller: controller.scrollController, - child: Column( - crossAxisAlignment: controller.ownMessage - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - if (!controller.shouldScroll) ...[ - WordCardSwitcher(controller: controller), + child: GestureDetector( + onTap: controller.widget.chatController.clearSelectedEvents, + child: SingleChildScrollView( + controller: controller.scrollController, + child: Column( + crossAxisAlignment: controller.messageColumnAlignment, + mainAxisSize: MainAxisSize.min, + children: [ + if (!controller.shouldScroll) ...[ + WordCardSwitcher(controller: controller), + const SizedBox(height: 4.0), + ] else + AnimatedContainer( + duration: FluffyThemes.animationDuration, + height: controller.overheadContentHeight, + ), + CompositedTransformTarget( + link: MatrixState.pAnyState + .layerLinkAndKey( + 'overlay_message_${controller.widget.event.eventId}', + ) + .link, + child: ValueListenableBuilder( + valueListenable: + controller.widget.overlayController.selectedMode, + builder: (context, mode, __) { + return OverlayCenterContent( + event: controller.widget.event, + messageHeight: mode != SelectMode.emoji + ? controller.originalMessageSize.height + : null, + messageWidth: controller.widget.overlayController + .selectModeController.isShowingExtraContent + ? max(controller.originalMessageSize.width, 150) + : controller.originalMessageSize.width, + overlayController: controller.widget.overlayController, + chatController: controller.widget.chatController, + nextEvent: controller.widget.nextEvent, + prevEvent: controller.widget.prevEvent, + hasReactions: controller.hasReactions, + isTransitionAnimation: true, + readingAssistanceMode: controller.readingAssistanceMode, + overlayKey: + 'overlay_message_${controller.widget.event.eventId}', + ); + }, + ), + ), const SizedBox(height: 4.0), - ] else + SelectModeButtons( + controller: controller.widget.chatController, + overlayController: controller.widget.overlayController, + launchPractice: () => controller.launchPractice( + ReadingAssistanceMode.practiceMode, + ), + ), AnimatedContainer( duration: FluffyThemes.animationDuration, - height: controller.overheadContentHeight, + height: max(0, controller.spaceBelowContent), + width: controller.mediaQuery!.size.width - + controller.columnWidth - + (controller.showDetails ? FluffyThemes.columnWidth : 0), ), - CompositedTransformTarget( - link: MatrixState.pAnyState - .layerLinkAndKey( - 'overlay_message_${controller.widget.event.eventId}', - ) - .link, - child: ValueListenableBuilder( - valueListenable: - controller.widget.overlayController.selectedMode, - builder: (context, mode, __) { - return OverlayCenterContent( - event: controller.widget.event, - messageHeight: mode != SelectMode.emoji - ? controller.originalMessageSize.height - : null, - messageWidth: controller.widget.overlayController - .selectModeController.isShowingExtraContent - ? max(controller.originalMessageSize.width, 150) - : controller.originalMessageSize.width, - overlayController: controller.widget.overlayController, - chatController: controller.widget.chatController, - nextEvent: controller.widget.nextEvent, - prevEvent: controller.widget.prevEvent, - hasReactions: controller.hasReactions, - isTransitionAnimation: true, - readingAssistanceMode: controller.readingAssistanceMode, - overlayKey: - 'overlay_message_${controller.widget.event.eventId}', - ); - }, - ), - ), - const SizedBox(height: 4.0), - SelectModeButtons( - controller: controller.widget.chatController, - overlayController: controller.widget.overlayController, - launchPractice: () => controller.launchPractice( - ReadingAssistanceMode.practiceMode, - ), - ), - AnimatedContainer( - duration: FluffyThemes.animationDuration, - height: max(0, controller.spaceBelowContent), - width: controller.mediaQuery!.size.width - - controller.columnWidth - - (controller.showDetails ? FluffyThemes.columnWidth : 0), - ), - ], + ], + ), ), ), ), diff --git a/lib/pangea/toolbar/layout/practice_mode_transition_animation.dart b/lib/pangea/toolbar/layout/practice_mode_transition_animation.dart index c10fbf13b..72dc5321e 100644 --- a/lib/pangea/toolbar/layout/practice_mode_transition_animation.dart +++ b/lib/pangea/toolbar/layout/practice_mode_transition_animation.dart @@ -55,6 +55,9 @@ class PracticeModeTransitionAnimationState void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { + final isRtl = widget.controller.isRtl; + final columnWidth = isRtl ? 0 : widget.controller.columnWidth; + final startOffset = Offset( widget.controller.ownMessage ? widget.controller.messageRightOffset! @@ -63,7 +66,7 @@ class PracticeModeTransitionAnimationState ); final endOffset = Offset( - _centerMessageOffset!.dx - widget.controller.columnWidth, + _centerMessageOffset!.dx - columnWidth, _centerMessageOffset!.dy, ); diff --git a/lib/pangea/toolbar/word_card/word_zoom_widget.dart b/lib/pangea/toolbar/word_card/word_zoom_widget.dart index 98d957cb5..1841da14b 100644 --- a/lib/pangea/toolbar/word_card/word_zoom_widget.dart +++ b/lib/pangea/toolbar/word_card/word_zoom_widget.dart @@ -174,27 +174,33 @@ class WordZoomWidget extends StatelessWidget { ], ); - return Material( - type: MaterialType.transparency, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - border: Border.all( - color: Theme.of(context).colorScheme.primary, - width: 4.0, + return GestureDetector( + onTap: () { + // Absorb taps to prevent them from propagating + // to widgets below and closing the overlay. + }, + child: Material( + type: MaterialType.transparency, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + border: Border.all( + color: Theme.of(context).colorScheme.primary, + width: 4.0, + ), + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), ), - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), + height: AppConfig.toolbarMaxHeight, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + content, + ], ), ), - height: AppConfig.toolbarMaxHeight, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - content, - ], - ), ), ); }