chore: started adding widget to show phonetic transcription

This commit is contained in:
ggurdin 2025-06-16 13:52:32 -04:00
parent 68b1382ba2
commit 40a6e5a10b
No known key found for this signature in database
GPG key ID: A01CB41737CBB478
5 changed files with 131 additions and 8 deletions

View file

@ -5016,5 +5016,6 @@
"directMessage": "Direct Message",
"newDirectMessage": "New direct message",
"speakingExercisesTooltip": "Speaking practice",
"noChatsFoundHereYet": "No chats found here yet"
"noChatsFoundHereYet": "No chats found here yet",
"phoneticTranscriptionError": "Phonetic transcription failed"
}

View file

@ -11,6 +11,7 @@ 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/phonetic_transcription/phonetic_transcription_widget.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';
@ -26,6 +27,9 @@ class VocabDetailsView extends StatelessWidget {
ConstructUses get _construct => constructId.constructUses;
String? get _userL1 =>
MatrixState.pangeaController.languageController.userL1?.langCode;
/// Get the language code for the current lemma
String? get _userL2 =>
MatrixState.pangeaController.languageController.userL2?.langCode;
@ -60,6 +64,12 @@ class VocabDetailsView extends StatelessWidget {
),
subtitle: Column(
children: [
if (_userL1 != null && _userL2 != null)
PhoneticTranscription(
text: _construct.lemma,
l1: _userL1!,
l2: _userL2!,
),
Row(
mainAxisSize: MainAxisSize.min,
spacing: 8.0,

View file

@ -1,6 +1,11 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:get_storage/get_storage.dart';
import 'package:http/http.dart';
import 'package:fluffychat/pangea/common/config/environment.dart';
import 'package:fluffychat/pangea/common/network/requests.dart';
import 'package:fluffychat/pangea/common/network/urls.dart';
@ -8,22 +13,22 @@ import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_request.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_response.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/foundation.dart';
import 'package:get_storage/get_storage.dart';
import 'package:http/http.dart';
class PhoneticTranscriptionRepo {
static final GetStorage _storage =
GetStorage('phonetic_transcription_storage');
static void set(PhoneticTranscriptionRequest request,
PhoneticTranscriptionResponse response) {
static void set(
PhoneticTranscriptionRequest request,
PhoneticTranscriptionResponse response,
) {
response.expireAt ??= DateTime.now().add(const Duration(days: 100));
_storage.write(request.storageKey, response.toJson());
}
static Future<PhoneticTranscriptionResponse> _fetch(
PhoneticTranscriptionRequest request) async {
PhoneticTranscriptionRequest request,
) async {
final cachedJson = _storage.read(request.storageKey);
final cached = cachedJson == null
? null
@ -54,7 +59,8 @@ class PhoneticTranscriptionRepo {
}
static Future<PhoneticTranscriptionResponse> get(
PhoneticTranscriptionRequest request) async {
PhoneticTranscriptionRequest request,
) async {
try {
return await _fetch(request);
} catch (e) {

View file

@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_repo.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_request.dart';
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_response.dart';
class PhoneticTranscription extends StatefulWidget {
final String text;
final String l1;
final String l2;
const PhoneticTranscription({
super.key,
required this.text,
required this.l1,
required this.l2,
});
@override
State<PhoneticTranscription> createState() => PhoneticTranscriptionState();
}
class PhoneticTranscriptionState extends State<PhoneticTranscription> {
bool _loading = false;
String? error;
PhoneticTranscriptionResponse? _response;
@override
void initState() {
super.initState();
_fetchPhoneticTranscription();
}
@override
void didUpdateWidget(covariant PhoneticTranscription oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.text != widget.text ||
oldWidget.l1 != widget.l1 ||
oldWidget.l2 != widget.l2) {
_fetchPhoneticTranscription();
}
}
Future<void> _fetchPhoneticTranscription() async {
final PhoneticTranscriptionRequest request = PhoneticTranscriptionRequest(
l1: widget.l1,
l2: widget.l2,
content: widget.text,
);
try {
setState(() {
_loading = true;
error = null;
});
_response = await PhoneticTranscriptionRepo.get(request);
} catch (e, s) {
ErrorHandler.logError(
e: e,
s: s,
data: request.toJson(),
);
error = e.toString();
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
@override
Widget build(BuildContext context) {
if (error != null) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.error_outline,
color: Theme.of(context).colorScheme.error,
size: 16.0,
),
const SizedBox(width: 8),
Text(
L10n.of(context).phoneticTranscriptionError,
style: Theme.of(context).textTheme.bodyLarge,
),
],
);
}
if (_loading || _response == null) {
return const Center(child: CircularProgressIndicator.adaptive());
}
return Text(
'Phonetic transcription for "${widget.text}" in ${widget.l2}',
style: Theme.of(context).textTheme.bodyLarge,
);
}
}