diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 74c88ae06..ee9fb9f3a 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4507,7 +4507,7 @@ }, "botModeValidation": "Please select a chat mode", "clickBestOption": "Choose the best options to translate your message!", - "completeActivitiesToUnlock": "Complete one of the activities (emoji, meaning, listening OR grammar) to unlock the translation!", + "completeActivitiesToUnlock": "Complete at least one activity to unlock the translation!", "botSettingsSubtitle": "Invite bot to moderate chat activity", "invitePeople": "Invite users", "noCapacityLimit": "No capacity limit", @@ -4866,4 +4866,4 @@ "shareSpaceLink": "Share link to space", "byUsingPangeaChat": "By using Pangea Chat, I agree to the ", "details": "Details" -} +} \ No newline at end of file diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index 581e6de77..2ce131c3f 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -316,7 +316,7 @@ class HtmlMessage extends StatelessWidget { ), width: tokenWidth, animateIn: isTransitionAnimation, - practiceTarget: + practiceTargetForToken: overlayController?.toolbarMode.associatedActivityType != null ? overlayController?.practiceSelection diff --git a/lib/pangea/analytics_details_popup/morph_meaning_widget.dart b/lib/pangea/analytics_details_popup/morph_meaning_widget.dart index b4b1bb423..de13dfac0 100644 --- a/lib/pangea/analytics_details_popup/morph_meaning_widget.dart +++ b/lib/pangea/analytics_details_popup/morph_meaning_widget.dart @@ -1,28 +1,24 @@ import 'dart:developer'; import 'dart:math'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; - import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart'; import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_repo.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class MorphMeaningWidget extends StatefulWidget { final MorphFeaturesEnum feature; final String tag; final TextStyle? style; - final InlineSpan? leading; const MorphMeaningWidget({ super.key, required this.feature, required this.tag, this.style, - this.leading, }); @override @@ -136,36 +132,18 @@ class MorphMeaningWidgetState extends State { ); } - return Row( - mainAxisAlignment: widget.leading != null - ? MainAxisAlignment.start - : MainAxisAlignment.center, - children: [ - Flexible( - child: Tooltip( - triggerMode: TooltipTriggerMode.tap, - message: L10n.of(context).doubleClickToEdit, - child: GestureDetector( - onLongPress: () => _toggleEditMode(true), - onDoubleTap: () => _toggleEditMode(true), - child: RichText( - textAlign: - widget.leading == null ? TextAlign.center : TextAlign.start, - text: TextSpan( - style: widget.style, - children: [ - if (widget.leading != null) widget.leading!, - if (widget.leading != null) const TextSpan(text: ' '), - TextSpan( - text: _cachedResponse ?? L10n.of(context).meaningNotFound, - ), - ], - ), - ), - ), - ), + return Tooltip( + triggerMode: TooltipTriggerMode.tap, + message: L10n.of(context).doubleClickToEdit, + child: GestureDetector( + onLongPress: () => _toggleEditMode(true), + onDoubleTap: () => _toggleEditMode(true), + child: Text( + textAlign: TextAlign.center, + _cachedResponse ?? L10n.of(context).meaningNotFound, + style: widget.style, ), - ], + ), ); } } diff --git a/lib/pangea/message_token_text/message_token_button.dart b/lib/pangea/message_token_text/message_token_button.dart index 7b393c6b6..8058ae4f0 100644 --- a/lib/pangea/message_token_text/message_token_button.dart +++ b/lib/pangea/message_token_text/message_token_button.dart @@ -32,7 +32,7 @@ class MessageTokenButton extends StatefulWidget { final TextStyle textStyle; final double width; final bool animateIn; - final PracticeTarget? practiceTarget; + final PracticeTarget? practiceTargetForToken; const MessageTokenButton({ super.key, @@ -40,7 +40,7 @@ class MessageTokenButton extends StatefulWidget { required this.token, required this.textStyle, required this.width, - required this.practiceTarget, + required this.practiceTargetForToken, this.animateIn = false, }); @@ -127,9 +127,9 @@ class MessageTokenButtonState extends State bool get _animate => widget.animateIn || _finishedInitialAnimation; - PracticeTarget? get _activity => widget.practiceTarget; + PracticeTarget? get _activity => widget.practiceTargetForToken; - bool get _isActivityCompleteForToken => + bool get _isActivityCompleteOrNullForToken => _activity?.isCompleteByToken( widget.token, _activity!.morphFeature, @@ -189,8 +189,13 @@ class MessageTokenButtonState extends State bool get _isEmpty { final mode = widget.overlayController?.toolbarMode; + if (MessageMode.wordEmoji == mode && + widget.token.vocabConstructID.userSetEmoji.firstOrNull != null) { + return false; + } + return _activity == null || - (_isActivityCompleteForToken && + (_isActivityCompleteOrNullForToken && ![MessageMode.wordEmoji, MessageMode.wordMorph].contains(mode)) || (MessageMode.wordMorph == mode && _activity?.morphFeature == null); } @@ -207,7 +212,7 @@ class MessageTokenButtonState extends State messageMode: widget.overlayController!.toolbarMode, token: widget.token, selectedChoice: widget.overlayController?.selectedChoice, - isComplete: _isActivityCompleteForToken, + isActivityCompleteOrNullForToken: _isActivityCompleteOrNullForToken, isSelected: _isSelected, height: tokenButtonHeight, width: widget.width, @@ -229,7 +234,7 @@ class MessageTokenButtonState extends State messageMode: widget.overlayController!.toolbarMode, token: widget.token, selectedChoice: widget.overlayController?.selectedChoice, - isComplete: _isActivityCompleteForToken, + isActivityCompleteOrNullForToken: _isActivityCompleteOrNullForToken, isSelected: _isSelected, height: _heightAnimation.value, width: widget.width, @@ -252,7 +257,7 @@ class MessageTokenButtonContent extends StatelessWidget { final PangeaToken token; final PracticeChoice? selectedChoice; - final bool isComplete; + final bool isActivityCompleteOrNullForToken; final bool isSelected; final double height; final double width; @@ -269,7 +274,7 @@ class MessageTokenButtonContent extends StatelessWidget { required this.messageMode, required this.token, required this.selectedChoice, - required this.isComplete, + required this.isActivityCompleteOrNullForToken, required this.isSelected, required this.height, required this.width, @@ -291,7 +296,7 @@ class MessageTokenButtonContent extends StatelessWidget { if (activity == null) { return Theme.of(context).colorScheme.primary; } - if (isComplete) { + if (isActivityCompleteOrNullForToken) { return AppConfig.gold; } return Theme.of(context).colorScheme.primary; @@ -299,11 +304,7 @@ class MessageTokenButtonContent extends StatelessWidget { @override Widget build(BuildContext context) { - if (activity == null) { - return SizedBox(height: height); - } - - if (isComplete) { + if (isActivityCompleteOrNullForToken || activity == null) { if (MessageMode.wordEmoji == messageMode) { return SizedBox( height: height, @@ -314,7 +315,7 @@ class MessageTokenButtonContent extends StatelessWidget { ), ); } - if (MessageMode.wordMorph == messageMode) { + if (MessageMode.wordMorph == messageMode && activity != null) { final morphFeature = activity!.morphFeature!; final morphTag = token.morphIdByFeature(morphFeature); if (morphTag != null) { @@ -337,8 +338,9 @@ class MessageTokenButtonContent extends StatelessWidget { ), ); } + } else { + return SizedBox(height: height); } - return SizedBox(height: height); } if (MessageMode.wordMorph == messageMode) { diff --git a/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice.dart b/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice.dart index b11b048ff..e3d4320d0 100644 --- a/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice.dart +++ b/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice.dart @@ -1,8 +1,5 @@ -import 'package:flutter/material.dart'; - import 'package:collection/collection.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - +import 'package:fluffychat/pangea/analytics_details_popup/morph_meaning_widget.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_animation.dart'; import 'package:fluffychat/pangea/constructs/construct_form.dart'; @@ -15,6 +12,8 @@ import 'package:fluffychat/pangea/practice_activities/practice_activity_model.da import 'package:fluffychat/pangea/practice_activities/practice_choice.dart'; import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/message_morph_choice_item.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; // this widget will handle the content of the input bar when mode == MessageMode.wordMorph @@ -62,19 +61,41 @@ class MessageMorphInputBarContentState void didUpdateWidget(covariant MessageMorphInputBarContent oldWidget) { if (morph != oldWidget.overlayController.selectedMorph?.morph || token != oldWidget.overlayController.selectedToken) { - selectedTag = null; setState(() {}); } super.didUpdateWidget(oldWidget); } + String? get _correctChoice { + return widget.activity.multipleChoiceContent?.choices + .firstWhereOrNull((choice) { + return widget.activity.practiceTarget.wasCorrectChoice(choice) == true; + }); + } + + TextStyle? textStyle(BuildContext context) => overlay.maxWidth > 600 + ? Theme.of(context).textTheme.bodyLarge?.copyWith( + fontWeight: FontWeight.bold, + ) + : Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.bold, + ); + @override Widget build(BuildContext context) { - final iconSize = overlay.maxWidth > 600 ? 30.0 : 24.0; - final spacing = overlay.maxWidth > 600 ? 16.0 : 8.0; + final iconSize = overlay.maxWidth > 600 + ? 28.0 + : overlay.maxWidth > 600 + ? 24.0 + : 16.0; + final spacing = overlay.maxWidth > 600 + ? 16.0 + : overlay.maxWidth > 600 + ? 8.0 + : 4.0; return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.max, spacing: spacing, children: [ @@ -94,13 +115,7 @@ class MessageMorphInputBarContentState morph.getDisplayCopy(context), token.text.content, ), - style: overlay.maxWidth > 600 - ? Theme.of(context).textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.bold, - ) - : Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.bold, - ), + style: textStyle(context), textAlign: TextAlign.center, ), ), @@ -151,12 +166,21 @@ class MessageMorphInputBarContentState }, ).toList(), ), - // SizedBox( - // height: 50, - // child: selectedTag != null - // ? MorphMeaningWidget(feature: morph, tag: selectedTag!) - // : null, - // ), + Container( + constraints: BoxConstraints( + minHeight: overlay.maxWidth > 600 ? 20 : 34, + ), + alignment: Alignment.center, + child: selectedTag != null + ? MorphMeaningWidget( + feature: morph, + tag: selectedTag!, + style: overlay.maxWidth > 600 + ? Theme.of(context).textTheme.bodyLarge + : Theme.of(context).textTheme.bodySmall, + ) + : const SizedBox.shrink(), + ), ], ); } diff --git a/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice_item.dart b/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice_item.dart index 9ce498b25..043e92622 100644 --- a/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice_item.dart +++ b/lib/pangea/toolbar/reading_assistance_input_row/message_morph_choice_item.dart @@ -1,11 +1,10 @@ -import 'package:flutter/material.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; import 'package:fluffychat/pangea/morphs/morph_icon.dart'; +import 'package:flutter/material.dart'; class MessageMorphChoiceItem extends StatefulWidget { const MessageMorphChoiceItem({ @@ -61,7 +60,7 @@ class MessageMorphChoiceItemState extends State { @override Widget build(BuildContext context) { final color = _color; - final iconSize = FluffyThemes.isColumnMode(context) ? 32.0 : 24.0; + final iconSize = FluffyThemes.isColumnMode(context) ? 24.0 : 16.0; final style = FluffyThemes.isColumnMode(context) ? Theme.of(context).textTheme.bodyLarge : Theme.of(context).textTheme.bodySmall; @@ -76,8 +75,9 @@ class MessageMorphChoiceItemState extends State { color: color, borderRadius: BorderRadius.circular(AppConfig.borderRadius), border: Border.all( - color: - widget.isSelected || _isHovered ? color : Colors.transparent, + color: widget.isSelected || _isHovered + ? color.withAlpha(255) + : Colors.transparent, width: 2.0, ), ), diff --git a/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart b/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart index c547e0c3c..c3d1dbb33 100644 --- a/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart +++ b/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart @@ -1,14 +1,13 @@ import 'dart:developer'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/practice_activities/practice_choice.dart'; import 'package:fluffychat/pangea/toolbar/controllers/tts_controller.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; class PracticeMatchItem extends StatefulWidget { const PracticeMatchItem({ @@ -129,7 +128,7 @@ class PracticeMatchItemState extends State { borderRadius: BorderRadius.circular(AppConfig.borderRadius), border: isSelected ? Border.all( - color: color(context), + color: color(context).withAlpha(255), width: 2, ) : Border.all( diff --git a/lib/pangea/toolbar/widgets/message_selection_overlay.dart b/lib/pangea/toolbar/widgets/message_selection_overlay.dart index 13b7185aa..e0598b1f4 100644 --- a/lib/pangea/toolbar/widgets/message_selection_overlay.dart +++ b/lib/pangea/toolbar/widgets/message_selection_overlay.dart @@ -538,10 +538,11 @@ class MessageOverlayController extends State /// we don't want to associate the audio with the text in this mode if (practiceSelection?.hasActiveActivityByToken( - ActivityTypeEnum.wordFocusListening, - token, - ) == - false) { + ActivityTypeEnum.wordFocusListening, + token, + ) == + false || + !hideWordCardContent) { widget.chatController.choreographer.tts.tryToSpeak( token.text.content, context, diff --git a/lib/pangea/toolbar/widgets/message_token_text.dart b/lib/pangea/toolbar/widgets/message_token_text.dart index e9d1843ec..f917b897a 100644 --- a/lib/pangea/toolbar/widgets/message_token_text.dart +++ b/lib/pangea/toolbar/widgets/message_token_text.dart @@ -226,7 +226,7 @@ class MessageTextWidget extends StatelessWidget { textStyle: renderer.style(context), width: tokenWidth, animateIn: isTransitionAnimation, - practiceTarget: overlayController + practiceTargetForToken: overlayController ?.toolbarMode.associatedActivityType != null ? overlayController?.practiceSelection diff --git a/lib/pangea/toolbar/widgets/toolbar_button_column.dart b/lib/pangea/toolbar/widgets/toolbar_button_column.dart index b1cf8907d..005616be1 100644 --- a/lib/pangea/toolbar/widgets/toolbar_button_column.dart +++ b/lib/pangea/toolbar/widgets/toolbar_button_column.dart @@ -1,8 +1,7 @@ -import 'package:flutter/material.dart'; - import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; import 'package:fluffychat/pangea/toolbar/widgets/toolbar_button.dart'; +import 'package:flutter/material.dart'; class ToolbarButtonRow extends StatelessWidget { final MessageOverlayController overlayController; @@ -14,8 +13,6 @@ class ToolbarButtonRow extends StatelessWidget { static const double iconWidth = 36.0; static const double buttonSize = 40.0; - static const barMargin = - EdgeInsets.symmetric(horizontal: iconWidth / 2, vertical: buttonSize / 2); @override Widget build(BuildContext context) { @@ -85,6 +82,7 @@ class ToolbarButtonRow extends StatelessWidget { ), ], ), + const SizedBox(height: 4.0), ], ); }