fix: always pass pos and morph when available on request TTS (#5716)

This commit is contained in:
ggurdin 2026-02-16 16:00:28 -05:00 committed by GitHub
parent dea49e3086
commit 58513051f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 65 additions and 18 deletions

View file

@ -228,6 +228,7 @@ class _WordCardWrapperState extends State<_WordCardWrapper> {
category: widget.v.pos,
),
langCode: widget.langCode,
pos: widget.v.pos,
onClose: () {
MatrixState.pAnyState.closeOverlay(widget.target);
widget.onClose();

View file

@ -55,7 +55,14 @@ class VocabDetailsView extends StatelessWidget {
? level.color(context)
: level.darkColor(context));
final forms = construct?.forms ?? [];
final forms =
construct?.uses
.where((u) => u.form != null)
.map((use) => _VocabForm(use.form!, use.category))
.toSet()
.toList() ??
[];
final tokenText = PangeaTokenText.fromString(constructId.lemma);
final token = PangeaToken(
text: tokenText,
@ -154,7 +161,7 @@ class VocabDetailsView extends StatelessWidget {
class _VocabForms extends StatelessWidget {
final String lemma;
final List<String> forms;
final List<_VocabForm> forms;
final Color textColor;
const _VocabForms({
@ -184,11 +191,12 @@ class _VocabForms extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
WordTextWithAudioButton(
text: form,
text: form.form,
pos: form.pos,
style: Theme.of(
context,
).textTheme.bodyLarge?.copyWith(color: textColor),
uniqueID: "$form-$lemma-$i",
uniqueID: "${form.form}-$lemma-$i",
langCode:
MatrixState.pangeaController.userController.userL2Code!,
),
@ -201,3 +209,21 @@ class _VocabForms extends StatelessWidget {
);
}
}
class _VocabForm {
final String form;
final String pos;
const _VocabForm(this.form, this.pos);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is _VocabForm &&
runtimeType == other.runtimeType &&
form.toLowerCase() == other.form.toLowerCase() &&
pos == other.pos;
@override
int get hashCode => form.toLowerCase().hashCode ^ pos.hashCode;
}

View file

@ -4,6 +4,9 @@ import 'package:fluffychat/pangea/common/widgets/word_audio_button.dart';
class WordTextWithAudioButton extends StatelessWidget {
final String text;
final String pos;
final Map<String, String>? morph;
final String uniqueID;
final TextStyle? style;
final double? iconSize;
@ -14,6 +17,8 @@ class WordTextWithAudioButton extends StatelessWidget {
required this.text,
required this.uniqueID,
required this.langCode,
required this.pos,
this.morph,
this.style,
this.iconSize,
});
@ -39,6 +44,8 @@ class WordTextWithAudioButton extends StatelessWidget {
baseOpacity: 1,
langCode: langCode,
padding: const EdgeInsets.only(left: 8.0),
pos: pos,
morph: morph,
),
],
);

View file

@ -84,9 +84,6 @@ class ConstructUses {
_ => ConstructLevelEnum.flowers,
};
List<String> get forms =>
_uses.map((e) => e.form).whereType<String>().toSet().toList();
List<OneConstructUse> get cappedUses {
final result = <OneConstructUse>[];
var totalXp = 0;

View file

@ -253,9 +253,13 @@ class AnalyticsPracticeState extends State<AnalyticsPractice>
} else {
return;
}
final token = activityTarget.value!.target.tokens.first;
TtsController.tryToSpeak(
activityTarget.value!.target.tokens.first.vocabConstructID.lemma,
token.vocabConstructID.lemma,
langCode: _l2!.langCode,
pos: token.pos,
morph: token.morph.map((k, v) => MapEntry(k.name, v)),
);
}

View file

@ -149,6 +149,8 @@ class _AnalyticsActivityView extends StatelessWidget {
final isVocabType =
controller.widget.type == ConstructTypeEnum.vocab;
final token = target.target.tokens.first;
return Column(
children: [
Text(
@ -162,12 +164,11 @@ class _AnalyticsActivityView extends StatelessWidget {
),
if (isVocabType && !isAudioActivity)
PhoneticTranscriptionWidget(
text: target
.target
.tokens
.first
.vocabConstructID
.lemma,
text: token.vocabConstructID.lemma,
pos: token.pos,
morph: token.morph.map(
(k, v) => MapEntry(k.name, v),
),
textLanguage: MatrixState
.pangeaController
.userController

View file

@ -8,6 +8,9 @@ import 'package:fluffychat/widgets/matrix.dart';
class WordAudioButton extends StatefulWidget {
final String text;
final String pos;
final Map<String, String>? morph;
final bool isSelected;
final double baseOpacity;
final String uniqueID;
@ -23,6 +26,8 @@ class WordAudioButton extends StatefulWidget {
required this.text,
required this.uniqueID,
required this.langCode,
required this.pos,
this.morph,
this.isSelected = false,
this.baseOpacity = 1,
this.callbackOverride,
@ -94,6 +99,8 @@ class WordAudioButtonState extends State<WordAudioButton> {
context: context,
targetID: 'word-audio-button-${widget.uniqueID}',
langCode: widget.langCode,
pos: widget.pos,
morph: widget.morph,
onStart: () {
if (mounted) {
setState(() => _isPlaying = true);

View file

@ -18,7 +18,7 @@ class PhoneticTranscriptionWidget extends StatefulWidget {
final LanguageModel textLanguage;
/// POS tag for disambiguation (from PangeaToken, e.g. "VERB").
final String? pos;
final String pos;
/// Morph features for disambiguation (from PangeaToken).
final Map<String, String>? morph;
@ -35,7 +35,7 @@ class PhoneticTranscriptionWidget extends StatefulWidget {
super.key,
required this.text,
required this.textLanguage,
this.pos,
required this.pos,
this.morph,
this.style,
this.iconSize,

View file

@ -241,6 +241,8 @@ class PracticeController with ChangeNotifier {
TtsController.tryToSpeak(
token.text.content,
langCode: MatrixState.pangeaController.userController.userL2!.langCode,
pos: token.pos,
morph: token.morph.map((k, v) => MapEntry(k.name, v)),
);
}

View file

@ -29,7 +29,7 @@ class WordZoomWidget extends StatelessWidget {
final Event? event;
/// POS tag for PT v2 disambiguation (e.g. "VERB").
final String? pos;
final String pos;
/// Morph features for PT v2 disambiguation (e.g. {"Tense": "Past"}).
final Map<String, String>? morph;
@ -45,9 +45,9 @@ class WordZoomWidget extends StatelessWidget {
required this.token,
required this.construct,
required this.langCode,
required this.pos,
this.onClose,
this.event,
this.pos,
this.morph,
this.enableEmojiSelection = true,
this.onDismissNewWordOverlay,
@ -153,6 +153,8 @@ class WordZoomWidget extends StatelessWidget {
)
: WordAudioButton(
text: token.content,
pos: pos,
morph: morph,
uniqueID: "lemma-content-${token.content}",
langCode: langCode,
iconSize: 24.0,