chore: reload info in word card in vocab details after submitting token feedback

This commit is contained in:
ggurdin 2026-01-19 12:18:27 -05:00
parent 6e3c6bcb2f
commit 257fb465be
No known key found for this signature in database
GPG key ID: A01CB41737CBB478
10 changed files with 236 additions and 301 deletions

View file

@ -18,9 +18,13 @@ import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart';
import 'package:fluffychat/pangea/morphs/default_morph_mapping.dart';
import 'package:fluffychat/pangea/morphs/morph_models.dart';
import 'package:fluffychat/pangea/morphs/morph_repo.dart';
import 'package:fluffychat/pangea/token_info_feedback/show_token_feedback_dialog.dart';
import 'package:fluffychat/pangea/token_info_feedback/token_info_feedback_request.dart';
import 'package:fluffychat/widgets/matrix.dart';
class ConstructAnalyticsView extends StatefulWidget {
@ -49,6 +53,7 @@ class ConstructAnalyticsViewState extends State<ConstructAnalyticsView> {
FocusNode searchFocusNode = FocusNode();
ConstructLevelEnum? selectedConstructLevel;
StreamSubscription<AnalyticsStreamUpdate>? _constructUpdateSub;
final ValueNotifier<int> reloadNotifier = ValueNotifier<int>(0);
@override
void initState() {
@ -72,6 +77,7 @@ class ConstructAnalyticsViewState extends State<ConstructAnalyticsView> {
searchController.dispose();
_constructUpdateSub?.cancel();
searchFocusNode.dispose();
reloadNotifier.dispose();
super.dispose();
}
@ -162,6 +168,29 @@ class ConstructAnalyticsViewState extends State<ConstructAnalyticsView> {
});
}
Future<void> onFlagTokenInfo(
PangeaToken token,
LemmaInfoResponse lemmaInfo,
String phonetics,
) async {
final requestData = TokenInfoFeedbackRequestData(
userId: Matrix.of(context).client.userID!,
detectedLanguage: MatrixState.pangeaController.userController.userL2Code!,
tokens: [token],
selectedToken: 0,
wordCardL1: MatrixState.pangeaController.userController.userL1Code!,
lemmaInfo: lemmaInfo,
phonetics: phonetics,
);
await TokenFeedbackUtil.showTokenFeedbackDialog(
context,
requestData: requestData,
langCode: MatrixState.pangeaController.userController.userL2Code!,
onUpdated: () => reloadNotifier.value++,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -182,7 +211,10 @@ class ConstructAnalyticsViewState extends State<ConstructAnalyticsView> {
: MorphDetailsView(constructId: widget.construct!)
: widget.construct == null
? VocabAnalyticsListView(controller: this)
: VocabDetailsView(constructId: widget.construct!),
: VocabDetailsView(
constructId: widget.construct!,
controller: this,
),
),
],
),

View file

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_usage_content.dart';
import 'package:fluffychat/pangea/analytics_details_popup/construct_xp_progress_bar.dart';
import 'package:fluffychat/pangea/analytics_details_popup/word_text_with_audio_button.dart';
@ -12,8 +13,6 @@ import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart';
import 'package:fluffychat/pangea/lemmas/lemma.dart';
import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart';
import 'package:fluffychat/pangea/token_info_feedback/show_token_feedback_dialog.dart';
import 'package:fluffychat/pangea/token_info_feedback/token_info_feedback_request.dart';
import 'package:fluffychat/pangea/toolbar/word_card/word_zoom_widget.dart';
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
import 'package:fluffychat/widgets/future_loading_dialog.dart';
@ -23,10 +22,12 @@ import 'package:fluffychat/widgets/matrix.dart';
/// Displays information about selected lemma, and its usage
class VocabDetailsView extends StatelessWidget {
final ConstructIdentifier constructId;
final ConstructAnalyticsViewState controller;
const VocabDetailsView({
super.key,
required this.constructId,
required this.controller,
});
Future<void> _blockLemma(BuildContext context) async {
@ -93,27 +94,12 @@ class VocabDetailsView extends StatelessWidget {
MatrixState.pangeaController.userController.userL2Code!,
construct: constructId,
onClose: Navigator.of(context).pop,
onFlagTokenInfo:
(LemmaInfoResponse lemmaInfo, String phonetics) {
final requestData = TokenInfoFeedbackRequestData(
userId: Matrix.of(context).client.userID!,
detectedLanguage: MatrixState
.pangeaController.userController.userL2Code!,
tokens: [token],
selectedToken: 0,
wordCardL1: MatrixState
.pangeaController.userController.userL1Code!,
lemmaInfo: lemmaInfo,
phonetics: phonetics,
);
TokenFeedbackUtil.showTokenFeedbackDialog(
context,
requestData: requestData,
langCode: MatrixState
.pangeaController.userController.userL2Code!,
);
},
onFlagTokenInfo: (
LemmaInfoResponse lemmaInfo,
String phonetics,
) =>
controller.onFlagTokenInfo(token, lemmaInfo, phonetics),
reloadNotifier: controller.reloadNotifier,
maxWidth: double.infinity,
),
),

View file

@ -6,6 +6,7 @@ import 'package:shimmer/shimmer.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/analytics_data/analytics_updater_mixin.dart';
import 'package:fluffychat/pangea/common/utils/async_state.dart';
import 'package:fluffychat/pangea/common/widgets/shimmer_background.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/lemmas/lemma_meaning_builder.dart';
@ -49,35 +50,15 @@ class LemmaHighlightEmojiRowState extends State<LemmaHighlightEmojiRow>
constructId: widget.cId,
messageInfo: widget.messageInfo,
builder: (context, controller) {
if (controller.error != null) {
return const SizedBox.shrink();
}
final emojis = controller.lemmaInfo?.emoji;
return SizedBox(
height: 70.0,
child: Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: emojis == null || emojis.isEmpty
? List.generate(
3,
(_) => Shimmer.fromColors(
baseColor: Colors.transparent,
highlightColor:
Theme.of(context).colorScheme.primary.withAlpha(70),
child: Container(
height: 55.0,
width: 55.0,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary,
borderRadius:
BorderRadius.circular(AppConfig.borderRadius),
),
),
),
)
: emojis.map(
return switch (controller.state) {
AsyncError() => const SizedBox.shrink(),
AsyncLoaded(value: final lemmaInfo) => SizedBox(
height: 70.0,
child: Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: [
...lemmaInfo.emoji.map(
(emoji) {
final targetId = "${widget.targetId}-$emoji";
return EmojiChoiceItem(
@ -94,9 +75,35 @@ class LemmaHighlightEmojiRowState extends State<LemmaHighlightEmojiRow>
enabled: widget.enabled,
);
},
).toList(),
),
);
),
],
),
),
_ => SizedBox(
height: 70.0,
child: Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: List.generate(
3,
(_) => Shimmer.fromColors(
baseColor: Colors.transparent,
highlightColor:
Theme.of(context).colorScheme.primary.withAlpha(70),
child: Container(
height: 55.0,
width: 55.0,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary,
borderRadius:
BorderRadius.circular(AppConfig.borderRadius),
),
),
),
),
),
),
};
},
);
}

View file

@ -8,29 +8,11 @@ import 'package:fluffychat/pangea/lemmas/lemma_info_request.dart';
import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart';
import 'package:fluffychat/widgets/matrix.dart';
class _LemmaMeaningLoader extends AsyncLoader<LemmaInfoResponse> {
final LemmaInfoRequest request;
_LemmaMeaningLoader(this.request) : super();
@override
Future<LemmaInfoResponse> fetch() async {
final result = await LemmaInfoRepo.get(
MatrixState.pangeaController.userController.accessToken,
request,
);
if (result.isError) {
throw result.asError!.error;
}
return result.asValue!.value;
}
}
class LemmaMeaningBuilder extends StatefulWidget {
final String langCode;
final ConstructIdentifier constructId;
final Map<String, dynamic> messageInfo;
final ValueNotifier<int>? reloadNotifier;
final Widget Function(
BuildContext context,
@ -43,6 +25,7 @@ class LemmaMeaningBuilder extends StatefulWidget {
required this.constructId,
required this.builder,
required this.messageInfo,
this.reloadNotifier,
});
@override
@ -50,12 +33,14 @@ class LemmaMeaningBuilder extends StatefulWidget {
}
class LemmaMeaningBuilderState extends State<LemmaMeaningBuilder> {
late _LemmaMeaningLoader _loader;
final ValueNotifier<AsyncState<LemmaInfoResponse>> _loader =
ValueNotifier(const AsyncState.idle());
@override
void initState() {
super.initState();
_reload();
_load();
widget.reloadNotifier?.addListener(_load);
}
@override
@ -63,24 +48,22 @@ class LemmaMeaningBuilderState extends State<LemmaMeaningBuilder> {
super.didUpdateWidget(oldWidget);
if (oldWidget.constructId != widget.constructId ||
oldWidget.langCode != widget.langCode) {
_loader.dispose();
_reload();
_load();
}
}
@override
void dispose() {
widget.reloadNotifier?.removeListener(_load);
_loader.dispose();
super.dispose();
}
bool get isLoading => _loader.isLoading;
bool get isError => _loader.isError;
Object? get error =>
isError ? (_loader.state.value as AsyncError).error : null;
LemmaInfoResponse? get lemmaInfo => _loader.value;
AsyncState<LemmaInfoResponse> get state => _loader.value;
bool get isError => _loader.value is AsyncError;
bool get isLoaded => _loader.value is AsyncLoaded;
LemmaInfoResponse? get lemmaInfo =>
isLoaded ? (_loader.value as AsyncLoaded<LemmaInfoResponse>).value : null;
LemmaInfoRequest get _request => LemmaInfoRequest(
lemma: widget.constructId.lemma,
@ -91,15 +74,23 @@ class LemmaMeaningBuilderState extends State<LemmaMeaningBuilder> {
messageInfo: widget.messageInfo,
);
void _reload() {
_loader = _LemmaMeaningLoader(_request);
_loader.load();
Future<void> _load() async {
_loader.value = const AsyncState.loading();
final result = await LemmaInfoRepo.get(
MatrixState.pangeaController.userController.accessToken,
_request,
);
if (!mounted) return;
result.isError
? _loader.value = AsyncState.error(result.asError!.error)
: _loader.value = AsyncState.loaded(result.asValue!.value);
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: _loader.state,
valueListenable: _loader,
builder: (context, _, __) => widget.builder(
context,
this,

View file

@ -1,77 +0,0 @@
import 'package:flutter/material.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart';
import 'package:fluffychat/pangea/common/network/requests.dart';
import 'package:fluffychat/pangea/common/widgets/error_indicator.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/lemmas/lemma_meaning_builder.dart';
import 'package:fluffychat/widgets/matrix.dart';
class LemmaMeaningWidget extends StatelessWidget {
final ConstructIdentifier constructId;
final TextStyle? style;
final InlineSpan? leading;
final Map<String, dynamic> messageInfo;
const LemmaMeaningWidget({
super.key,
required this.constructId,
required this.messageInfo,
this.style,
this.leading,
});
@override
Widget build(BuildContext context) {
return LemmaMeaningBuilder(
langCode: MatrixState.pangeaController.userController.userL2!.langCode,
constructId: constructId,
messageInfo: messageInfo,
builder: (context, controller) {
if (controller.isLoading) {
return const TextLoadingShimmer();
}
if (controller.error != null) {
if (controller.error is UnsubscribedException) {
return ErrorIndicator(
message: L10n.of(context).subscribeToUnlockDefinitions,
style: style,
onTap: () {
MatrixState.pangeaController.subscriptionController
.showPaywall(context);
},
);
}
return ErrorIndicator(
message: L10n.of(context).errorFetchingDefinition,
style: style,
);
}
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: RichText(
textAlign: leading == null ? TextAlign.center : TextAlign.start,
text: TextSpan(
style: style,
children: [
if (leading != null) leading!,
if (leading != null)
const WidgetSpan(child: SizedBox(width: 6.0)),
TextSpan(
text: controller.lemmaInfo?.meaning,
),
],
),
),
),
],
);
},
);
}
}

View file

@ -8,29 +8,10 @@ import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_
import 'package:fluffychat/widgets/matrix.dart';
import 'phonetic_transcription_repo.dart';
class _TranscriptLoader extends AsyncLoader<String> {
final PhoneticTranscriptionRequest request;
_TranscriptLoader(this.request) : super();
@override
Future<String> fetch() async {
final resp = await PhoneticTranscriptionRepo.get(
MatrixState.pangeaController.userController.accessToken,
request,
);
if (resp.isError) {
throw resp.asError!.error;
}
return resp.asValue!.value.phoneticTranscriptionResult.phoneticTranscription
.first.phoneticL1Transcription.content;
}
}
class PhoneticTranscriptionBuilder extends StatefulWidget {
final LanguageModel textLanguage;
final String text;
final ValueNotifier<int>? reloadNotifier;
final Widget Function(
BuildContext context,
@ -42,6 +23,7 @@ class PhoneticTranscriptionBuilder extends StatefulWidget {
required this.textLanguage,
required this.text,
required this.builder,
this.reloadNotifier,
});
@override
@ -51,12 +33,14 @@ class PhoneticTranscriptionBuilder extends StatefulWidget {
class PhoneticTranscriptionBuilderState
extends State<PhoneticTranscriptionBuilder> {
late _TranscriptLoader _loader;
final ValueNotifier<AsyncState<String>> _loader =
ValueNotifier(const AsyncState.idle());
@override
void initState() {
super.initState();
_reload();
_load();
widget.reloadNotifier?.addListener(_load);
}
@override
@ -64,27 +48,24 @@ class PhoneticTranscriptionBuilderState
super.didUpdateWidget(oldWidget);
if (oldWidget.text != widget.text ||
oldWidget.textLanguage != widget.textLanguage) {
_loader.dispose();
_reload();
_load();
}
}
@override
void dispose() {
widget.reloadNotifier?.removeListener(_load);
_loader.dispose();
super.dispose();
}
bool get isLoading => _loader.isLoading;
bool get isError => _loader.isError;
AsyncState<String> get state => _loader.value;
bool get isError => _loader.value is AsyncError;
bool get isLoaded => _loader.value is AsyncLoaded;
String? get transcription =>
isLoaded ? (_loader.value as AsyncLoaded<String>).value : null;
Object? get error =>
isError ? (_loader.state.value as AsyncError).error : null;
String? get transcription => _loader.value;
PhoneticTranscriptionRequest get _transcriptRequest =>
PhoneticTranscriptionRequest(
PhoneticTranscriptionRequest get _request => PhoneticTranscriptionRequest(
arc: LanguageArc(
l1: MatrixState.pangeaController.userController.userL1!,
l2: widget.textLanguage,
@ -92,15 +73,26 @@ class PhoneticTranscriptionBuilderState
content: PangeaTokenText.fromString(widget.text),
);
void _reload() {
_loader = _TranscriptLoader(_transcriptRequest);
_loader.load();
Future<void> _load() async {
_loader.value = const AsyncState.loading();
final resp = await PhoneticTranscriptionRepo.get(
MatrixState.pangeaController.userController.accessToken,
_request,
);
if (!mounted) return;
resp.isError
? _loader.value = AsyncState.error(resp.asError!.error)
: _loader.value = AsyncState.loaded(
resp.asValue!.value.phoneticTranscriptionResult
.phoneticTranscription.first.phoneticL1Transcription.content,
);
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: _loader.state,
valueListenable: _loader,
builder: (context, _, __) => widget.builder(
context,
this,

View file

@ -1,10 +1,9 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart';
import 'package:fluffychat/pangea/common/network/requests.dart';
import 'package:fluffychat/pangea/common/utils/async_state.dart';
import 'package:fluffychat/pangea/common/widgets/error_indicator.dart';
import 'package:fluffychat/pangea/languages/language_model.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_builder.dart';
@ -22,6 +21,7 @@ class PhoneticTranscriptionWidget extends StatefulWidget {
final int? maxLines;
final VoidCallback? onTranscriptionFetched;
final ValueNotifier<int>? reloadNotifier;
const PhoneticTranscriptionWidget({
super.key,
@ -32,6 +32,7 @@ class PhoneticTranscriptionWidget extends StatefulWidget {
this.iconColor,
this.maxLines,
this.onTranscriptionFetched,
this.reloadNotifier,
});
@override
@ -85,59 +86,58 @@ class _PhoneticTranscriptionWidgetState
key: MatrixState.pAnyState.layerLinkAndKey(targetId).key,
textLanguage: widget.textLanguage,
text: widget.text,
reloadNotifier: widget.reloadNotifier,
builder: (context, controller) {
if (controller.isError) {
return controller.error is UnsubscribedException
? ErrorIndicator(
message: L10n.of(context)
.subscribeToUnlockTranscriptions,
onTap: () {
MatrixState
.pangeaController.subscriptionController
.showPaywall(context);
},
)
: ErrorIndicator(
message:
L10n.of(context).failedToFetchTranscription,
);
}
if (controller.isLoading ||
controller.transcription == null) {
return const TextLoadingShimmer(
width: 125.0,
height: 20.0,
);
}
return Row(
spacing: 8.0,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
controller.transcription!,
textScaler: TextScaler.noScaling,
style: widget.style ??
Theme.of(context).textTheme.bodyMedium,
maxLines: widget.maxLines,
overflow: TextOverflow.ellipsis,
),
return switch (controller.state) {
AsyncError(error: final error) =>
error is UnsubscribedException
? ErrorIndicator(
message: L10n.of(context)
.subscribeToUnlockTranscriptions,
onTap: () {
MatrixState
.pangeaController.subscriptionController
.showPaywall(context);
},
)
: ErrorIndicator(
message:
L10n.of(context).failedToFetchTranscription,
),
AsyncLoaded<String>(value: final transcription) => Row(
spacing: 8.0,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
transcription,
textScaler: TextScaler.noScaling,
style: widget.style ??
Theme.of(context).textTheme.bodyMedium,
maxLines: widget.maxLines,
overflow: TextOverflow.ellipsis,
),
),
Tooltip(
message: _isPlaying
? L10n.of(context).stop
: L10n.of(context).playAudio,
child: Icon(
_isPlaying
? Icons.pause_outlined
: Icons.volume_up,
size: widget.iconSize ?? 24,
color: widget.iconColor ??
Theme.of(context).iconTheme.color,
),
),
],
),
Tooltip(
message: _isPlaying
? L10n.of(context).stop
: L10n.of(context).playAudio,
child: Icon(
_isPlaying ? Icons.pause_outlined : Icons.volume_up,
size: widget.iconSize ?? 24,
color: widget.iconColor ??
Theme.of(context).iconTheme.color,
),
_ => const TextLoadingShimmer(
width: 125.0,
height: 20.0,
),
],
);
};
},
),
),

View file

@ -12,6 +12,7 @@ class TokenFeedbackUtil {
required TokenInfoFeedbackRequestData requestData,
required String langCode,
PangeaMessageEvent? event,
VoidCallback? onUpdated,
}) async {
final resp = await showDialog(
context: context,
@ -23,6 +24,8 @@ class TokenFeedbackUtil {
);
if (resp == null) return;
onUpdated?.call();
await showDialog(
context: context,
builder: (context) {

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart';
import 'package:fluffychat/pangea/common/utils/async_state.dart';
import 'package:fluffychat/pangea/common/widgets/error_indicator.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/lemmas/lemma_meaning_builder.dart';
@ -12,6 +13,7 @@ class LemmaMeaningDisplay extends StatelessWidget {
final ConstructIdentifier constructId;
final String text;
final Map<String, dynamic> messageInfo;
final ValueNotifier<int>? reloadNotifier;
const LemmaMeaningDisplay({
super.key,
@ -19,6 +21,7 @@ class LemmaMeaningDisplay extends StatelessWidget {
required this.constructId,
required this.text,
required this.messageInfo,
this.reloadNotifier,
});
@override
@ -27,53 +30,47 @@ class LemmaMeaningDisplay extends StatelessWidget {
langCode: langCode,
constructId: constructId,
messageInfo: messageInfo,
reloadNotifier: reloadNotifier,
builder: (context, controller) {
if (controller.isError) {
return ErrorIndicator(
message: L10n.of(context).errorFetchingDefinition,
style: const TextStyle(fontSize: 14.0),
);
}
if (controller.isLoading || controller.lemmaInfo == null) {
return const TextLoadingShimmer(
width: 125.0,
height: 20.0,
);
}
final pos = getGrammarCopy(
category: "POS",
lemma: constructId.category,
context: context,
) ??
L10n.of(context).other;
return RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style.copyWith(
fontSize: 14.0,
),
children: [
TextSpan(
text: "${constructId.lemma} ($pos)",
return switch (controller.state) {
AsyncError() => ErrorIndicator(
message: L10n.of(context).errorFetchingDefinition,
style: const TextStyle(fontSize: 14.0),
),
AsyncLoaded(value: final lemmaInfo) => RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style.copyWith(
fontSize: 14.0,
),
children: [
TextSpan(
text: "${constructId.lemma} (${getGrammarCopy(
category: "POS",
lemma: constructId.category,
context: context,
) ?? L10n.of(context).other})",
),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
const TextSpan(text: ":"),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
TextSpan(
text: lemmaInfo.meaning,
),
],
),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
const TextSpan(text: ":"),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
TextSpan(
text: controller.lemmaInfo!.meaning,
),
],
),
);
),
_ => const TextLoadingShimmer(
width: 125.0,
height: 20.0,
),
};
},
);
}

View file

@ -30,6 +30,7 @@ class WordZoomWidget extends StatelessWidget {
final bool enableEmojiSelection;
final VoidCallback? onDismissNewWordOverlay;
final Function(LemmaInfoResponse, String)? onFlagTokenInfo;
final ValueNotifier<int>? reloadNotifier;
final double? maxWidth;
const WordZoomWidget({
@ -42,6 +43,7 @@ class WordZoomWidget extends StatelessWidget {
this.enableEmojiSelection = true,
this.onDismissNewWordOverlay,
this.onFlagTokenInfo,
this.reloadNotifier,
this.maxWidth,
});
@ -143,6 +145,7 @@ class WordZoomWidget extends StatelessWidget {
style: const TextStyle(fontSize: 14.0),
iconSize: 24.0,
maxLines: 2,
reloadNotifier: reloadNotifier,
)
: WordAudioButton(
text: token.content,
@ -161,6 +164,7 @@ class WordZoomWidget extends StatelessWidget {
constructId: construct,
text: token.content,
messageInfo: event?.content ?? {},
reloadNotifier: reloadNotifier,
),
],
),