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),
+ ],
+ ),
);
},
);