From 392b3e31c6063e1159b2eb148e37ebd53fbebafc Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 17 Dec 2025 15:32:59 -0500 Subject: [PATCH] add space between rows of tokens in practice mode --- lib/pages/chat/events/html_message.dart | 21 ++++++++++++++++ .../message_practice/practice_controller.dart | 24 ++++++++++++++++++ .../token_practice_button.dart | 25 +++++++------------ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index f0e1f2838..e186e2304 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -14,6 +14,7 @@ import 'package:fluffychat/pages/chat/chat.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/toolbar/layout/reading_assistance_mode_enum.dart'; +import 'package:fluffychat/pangea/toolbar/message_practice/message_practice_mode_enum.dart'; import 'package:fluffychat/pangea/toolbar/message_practice/token_practice_button.dart'; import 'package:fluffychat/pangea/toolbar/message_selection_overlay.dart'; import 'package:fluffychat/pangea/toolbar/reading_assistance/token_emoji_button.dart'; @@ -513,6 +514,26 @@ class HtmlMessage extends StatelessWidget { ), ), ), + if (renderer.showCenterStyling && + token != null && + overlayController != null) + ListenableBuilder( + listenable: overlayController!.practiceController, + builder: (context, _) => AnimatedSize( + duration: const Duration( + milliseconds: AppConfig.overlayAnimationDuration, + ), + curve: Curves.easeOut, + child: SizedBox( + height: overlayController! + .practiceController.practiceMode != + MessagePracticeMode.noneSelected + ? 16.0 + : 0.0, + width: tokenWidth, + ), + ), + ), ], // ), ), diff --git a/lib/pangea/toolbar/message_practice/practice_controller.dart b/lib/pangea/toolbar/message_practice/practice_controller.dart index 00fee09d3..0e388d57e 100644 --- a/lib/pangea/toolbar/message_practice/practice_controller.dart +++ b/lib/pangea/toolbar/message_practice/practice_controller.dart @@ -54,6 +54,30 @@ class PracticeController with ChangeNotifier { practiceSelection?.activities(activityType).every((a) => a.isComplete) == true; + bool isPracticeButtonEmpty(PangeaToken token) { + final target = practiceTargetForToken(token); + + if (MessagePracticeMode.wordEmoji == practiceMode) { + if (token.vocabConstructID.userSetEmoji.firstOrNull != null) { + return false; + } + // Keep open even when completed to show emoji + return target == null; + } + + if (MessagePracticeMode.wordMorph == practiceMode) { + // Keep open even when completed to show morph icon + return target == null; + } + + return target == null || + target.isCompleteByToken( + token, + _activity?.morphFeature, + ) == + true; + } + Future> fetchActivityModel( PracticeTarget target, ) async { diff --git a/lib/pangea/toolbar/message_practice/token_practice_button.dart b/lib/pangea/toolbar/message_practice/token_practice_button.dart index 33f8d5130..44e675b9e 100644 --- a/lib/pangea/toolbar/message_practice/token_practice_button.dart +++ b/lib/pangea/toolbar/message_practice/token_practice_button.dart @@ -55,20 +55,7 @@ class TokenPracticeButton extends StatelessWidget { true; } - bool get _isEmpty { - final mode = controller.practiceMode; - if (MessagePracticeMode.wordEmoji == mode && - token.vocabConstructID.userSetEmoji.firstOrNull != null) { - return false; - } - - return _activity == null || - (isActivityCompleteOrNullForToken && - ![MessagePracticeMode.wordEmoji, MessagePracticeMode.wordMorph] - .contains(mode)) || - (MessagePracticeMode.wordMorph == mode && - _activity?.morphFeature == null); - } + bool get _isEmpty => controller.isPracticeButtonEmpty(token); bool get _isSelected => controller.selectedMorph?.token == token && @@ -124,8 +111,14 @@ class TokenPracticeButton extends StatelessWidget { curve: Curves.easeOut, alignment: Alignment.bottomCenter, child: _isEmpty - ? const SizedBox(height: 0) - : SizedBox(height: tokenButtonHeight, child: child), + ? const SizedBox() + : Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 16.0), + SizedBox(height: tokenButtonHeight, child: child), + ], + ), ); }, );