From 5e3e1604d4cb51854b340aa7b437029cb067cce7 Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Fri, 28 Mar 2025 15:06:03 -0400 Subject: [PATCH] chore: updates to sizing and spacing in vocab details popup (#2258) --- .../morph_details_view.dart | 22 +-- .../vocab_analytics_details_view.dart | 132 ++++++++++-------- lib/pangea/lemmas/lemma_emoji_row.dart | 7 +- .../word_text_with_audio_button.dart | 82 ++++------- .../word_zoom/lemma_meaning_widget.dart | 3 +- 5 files changed, 120 insertions(+), 126 deletions(-) diff --git a/lib/pangea/analytics_details_popup/morph_details_view.dart b/lib/pangea/analytics_details_popup/morph_details_view.dart index c0294f0f6..1cd243d6f 100644 --- a/lib/pangea/analytics_details_popup/morph_details_view.dart +++ b/lib/pangea/analytics_details_popup/morph_details_view.dart @@ -40,16 +40,18 @@ class MorphDetailsView extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - MorphMeaningWidget( - feature: _morphFeature, - tag: _morphTag, - style: Theme.of(context).textTheme.bodyLarge, - // leading: TextSpan( - // text: L10n.of(context).meaningSectionHeader, - // style: const TextStyle( - // fontWeight: FontWeight.bold, - // ), - // ), + Expanded( + child: MorphMeaningWidget( + feature: _morphFeature, + tag: _morphTag, + style: Theme.of(context).textTheme.bodyLarge, + // leading: TextSpan( + // text: L10n.of(context).meaningSectionHeader, + // style: const TextStyle( + // fontWeight: FontWeight.bold, + // ), + // ), + ), ), ], ), diff --git a/lib/pangea/analytics_details_popup/vocab_analytics_details_view.dart b/lib/pangea/analytics_details_popup/vocab_analytics_details_view.dart index b2e6b018e..37b6e766b 100644 --- a/lib/pangea/analytics_details_popup/vocab_analytics_details_view.dart +++ b/lib/pangea/analytics_details_popup/vocab_analytics_details_view.dart @@ -1,5 +1,6 @@ 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/analytics_details_popup_content.dart'; @@ -7,9 +8,9 @@ import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/pangea/constructs/construct_level_enum.dart'; import 'package:fluffychat/pangea/lemmas/lemma_emoji_row.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:fluffychat/pangea/toolbar/widgets/practice_activity/word_audio_button.dart'; import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/word_text_with_audio_button.dart'; import 'package:fluffychat/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -29,6 +30,18 @@ class VocabDetailsView extends StatelessWidget { String? get _userL2 => MatrixState.pangeaController.languageController.userL2?.langCode; + List get forms => + MatrixState.pangeaController.getAnalytics.constructListModel + .getConstructUsesByLemma(_construct.lemma) + .map((e) => e.uses) + .expand((element) => element) + .map((e) => e.form?.toLowerCase()) + .toSet() + .whereType() + .toList(); + + final double _iconSize = 24.0; + @override Widget build(BuildContext context) { final Color textColor = (Theme.of(context).brightness != Brightness.light @@ -36,36 +49,50 @@ class VocabDetailsView extends StatelessWidget { : _construct.lemmaCategory.darkColor(context)); return AnalyticsDetailsViewContent( - title: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - WordAudioButton( - text: _construct.lemma, - size: 24, - ), - const SizedBox(width: 4.0), - Text( - _construct.lemma, - style: Theme.of(context).textTheme.headlineLarge?.copyWith( - color: textColor, - ), - ), - ], + title: WordTextWithAudioButton( + text: _construct.lemma, + style: Theme.of(context).textTheme.headlineLarge?.copyWith( + color: textColor, + ), + iconSize: _iconSize, ), - subtitle: Row( - mainAxisAlignment: MainAxisAlignment.center, + subtitle: Column( children: [ - MorphIcon( - morphFeature: MorphFeaturesEnum.Pos, - morphTag: _construct.category, - ), - const SizedBox(width: 4.0), - Text( - MorphFeaturesEnum.Pos.getDisplayCopy(context), - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - color: textColor, + Row( + mainAxisSize: MainAxisSize.min, + spacing: 8.0, + children: [ + Text( + getGrammarCopy( + category: "POS", + lemma: _construct.category, + context: context, + ) ?? + _construct.lemma, + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + color: textColor, + ), + ), + SizedBox( + width: _iconSize, + height: _iconSize, + child: MorphIcon( + morphFeature: MorphFeaturesEnum.Pos, + morphTag: _construct.category, ), + ), + ], + ), + const SizedBox(height: 16.0), + LemmaEmojiRow( + isSelected: false, + shouldShowEmojis: true, + cId: constructId, + onTapOverride: null, + emojiSetCallback: () { + debugPrint('Emoji set callback'); + }, + iconSize: _iconSize, ), ], ), @@ -74,20 +101,6 @@ class VocabDetailsView extends StatelessWidget { child: Column( spacing: 8.0, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - LemmaEmojiRow( - isSelected: false, - shouldShowEmojis: true, - cId: constructId, - onTapOverride: null, - emojiSetCallback: () { - debugPrint('Emoji set callback'); - }, - ), - ], - ), Align( alignment: Alignment.topLeft, child: _userL2 == null @@ -100,9 +113,9 @@ class VocabDetailsView extends StatelessWidget { style: Theme.of(context).textTheme.bodyLarge, leading: TextSpan( text: L10n.of(context).meaningSectionHeader, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + fontWeight: FontWeight.bold, + ), ), ), ), @@ -119,31 +132,26 @@ class VocabDetailsView extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - ...MatrixState - .pangeaController.getAnalytics.constructListModel - .getConstructUsesByLemma(_construct.lemma) - .map((e) => e.uses) - .expand((element) => element) - .map((e) => e.form?.toLowerCase()) - .toSet() - .whereType() - .map( - (form) => WordTextWithAudioButton( + const SizedBox(width: 6.0), + ...forms.mapIndexed( + (i, form) => Row( + mainAxisSize: MainAxisSize.min, + children: [ + WordTextWithAudioButton( text: form, - textSize: Theme.of(context) - .textTheme - .bodyMedium - ?.fontSize ?? - 16, + style: Theme.of(context).textTheme.bodyLarge, ), - ), + if (i != forms.length - 1) const Text(", "), + ], + ), + ), ], ), ), ], ), ), - xpIcon: _construct.lemmaCategory.icon(12), + xpIcon: _construct.lemmaCategory.icon(_iconSize + 6.0), constructId: constructId, ); } diff --git a/lib/pangea/lemmas/lemma_emoji_row.dart b/lib/pangea/lemmas/lemma_emoji_row.dart index 913f1dc9b..cb88ed663 100644 --- a/lib/pangea/lemmas/lemma_emoji_row.dart +++ b/lib/pangea/lemmas/lemma_emoji_row.dart @@ -19,6 +19,7 @@ class LemmaEmojiRow extends StatefulWidget { final VoidCallback? onTapOverride; final bool isSelected; final bool shouldShowEmojis; + final double? iconSize; /// if a setState is defined then we're in a context where /// we allow removing an emoji @@ -32,6 +33,7 @@ class LemmaEmojiRow extends StatefulWidget { required this.isSelected, required this.shouldShowEmojis, this.emojiSetCallback, + this.iconSize, }); @override @@ -89,7 +91,8 @@ class LemmaEmojiRowState extends State { blurBackground: false, borderColor: Theme.of(context).colorScheme.primary, closePrevOverlay: false, - offset: const Offset(0, 60), + followerAnchor: Alignment.topCenter, + targetAnchor: Alignment.bottomCenter, ); } catch (e, s) { debugger(when: kDebugMode); @@ -156,7 +159,7 @@ class LemmaEmojiRowState extends State { padding: const EdgeInsets.all(8.0), child: Text( displayEmoji!, - style: Theme.of(context).textTheme.headlineSmall, + style: TextStyle(fontSize: widget.iconSize ?? 20), ), ), ) diff --git a/lib/pangea/toolbar/widgets/practice_activity/word_text_with_audio_button.dart b/lib/pangea/toolbar/widgets/practice_activity/word_text_with_audio_button.dart index 7b9c50d1d..bd3cd1019 100644 --- a/lib/pangea/toolbar/widgets/practice_activity/word_text_with_audio_button.dart +++ b/lib/pangea/toolbar/widgets/practice_activity/word_text_with_audio_button.dart @@ -8,12 +8,14 @@ import 'package:fluffychat/widgets/matrix.dart'; class WordTextWithAudioButton extends StatefulWidget { final String text; - final double? textSize; + final TextStyle? style; + final double? iconSize; const WordTextWithAudioButton({ super.key, required this.text, - this.textSize, + this.style, + this.iconSize, }); @override @@ -46,9 +48,6 @@ class WordAudioButtonState extends State { super.dispose(); } - double get textSize => - widget.textSize ?? Theme.of(context).textTheme.titleLarge?.fontSize ?? 16; - @override Widget build(BuildContext context) { return CompositedTransformTarget( @@ -80,7 +79,7 @@ class WordAudioButtonState extends State { await tts.tryToSpeak( widget.text, context, - targetID: 'text-audio-button', + targetID: 'text-audio-button ${widget.text}', ); } catch (e, s) { ErrorHandler.logError( @@ -97,53 +96,34 @@ class WordAudioButtonState extends State { } } }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular(4), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 180), - child: Text( - widget.text, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: _isPlaying - ? Theme.of(context).colorScheme.primary - : null, - fontSize: textSize, - ), - overflow: TextOverflow.ellipsis, - ), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 8.0, + children: [ + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 180), + child: Text( + widget.text, + style: widget.style ?? Theme.of(context).textTheme.bodyMedium, + overflow: TextOverflow.ellipsis, ), - const SizedBox(width: 4), - if (_isLoading) - const Padding( - padding: EdgeInsets.only( - left: 4, - ), // Adds 20 pixels of left padding - child: SizedBox( - width: 16, - height: 16, - child: CircularProgressIndicator( - strokeWidth: 3, - ), - ), - ) - else - Icon( - _isPlaying ? Icons.volume_up : Icons.pause_outlined, - size: textSize, - color: _isPlaying - ? Theme.of(context).colorScheme.primary - : null, + ), + if (_isLoading) + const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 3, ), - ], - ), + ) + else + Icon( + _isPlaying ? Icons.pause_outlined : Icons.volume_up, + color: + _isPlaying ? Theme.of(context).colorScheme.primary : null, + size: widget.iconSize, + ), + ], ), ), ), diff --git a/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart index c169f4d4b..b93c37562 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart @@ -225,7 +225,8 @@ class LemmaMeaningWidgetState extends State { ), children: [ if (widget.leading != null) widget.leading!, - if (widget.leading != null) const TextSpan(text: ' '), + if (widget.leading != null) + const WidgetSpan(child: SizedBox(width: 6.0)), TextSpan( text: _lemmaInfo?.meaning, ),