From 4eebc4b820da567d4d8aec014762204eab6642a5 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 12 Nov 2025 10:18:58 -0500 Subject: [PATCH] return domain-specific models from choreo-related repos, use future builders on async data when possbile --- .../choreographer/igc/igc_controller.dart | 8 +- lib/pangea/choreographer/igc/igc_repo.dart | 21 +-- lib/pangea/choreographer/igc/span_card.dart | 75 +++++------ .../choreographer/igc/span_data_repo.dart | 18 +-- .../it/contextual_definition_repo.dart | 17 ++- lib/pangea/choreographer/it/it_bar.dart | 5 +- .../choreographer/it/it_feedback_card.dart | 61 ++------- .../choreographer/it/word_data_card.dart | 121 +++++------------- lib/pangea/common/utils/async_state.dart | 55 ++++++++ lib/pangea/common/utils/feedback_model.dart | 29 ----- .../controllers/message_data_controller.dart | 6 +- .../full_text_translation_repo.dart | 16 +-- 12 files changed, 185 insertions(+), 247 deletions(-) create mode 100644 lib/pangea/common/utils/async_state.dart delete mode 100644 lib/pangea/common/utils/feedback_model.dart diff --git a/lib/pangea/choreographer/igc/igc_controller.dart b/lib/pangea/choreographer/igc/igc_controller.dart index a20129e55..e38aa8b67 100644 --- a/lib/pangea/choreographer/igc/igc_controller.dart +++ b/lib/pangea/choreographer/igc/igc_controller.dart @@ -108,11 +108,7 @@ class IgcController { } if (!_isFetching) return; - final response = res.result!; - _igcTextData = IGCTextData( - originalInput: response.originalInput, - matches: response.matches, - ); + _igcTextData = res.result!; _isFetching = false; } @@ -147,7 +143,7 @@ class IgcController { throw response.error!; } - _igcTextData?.setSpanData(match, response.result!.span); + _igcTextData?.setSpanData(match, response.result!); } Future fetchAllSpanDetails() async { diff --git a/lib/pangea/choreographer/igc/igc_repo.dart b/lib/pangea/choreographer/igc/igc_repo.dart index 3ffbc5d07..3dcf77205 100644 --- a/lib/pangea/choreographer/igc/igc_repo.dart +++ b/lib/pangea/choreographer/igc/igc_repo.dart @@ -7,6 +7,7 @@ import 'package:http/http.dart'; import 'package:fluffychat/pangea/choreographer/igc/igc_request_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/igc_response_model.dart'; +import 'package:fluffychat/pangea/choreographer/igc/igc_text_data_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_model.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; @@ -14,7 +15,7 @@ import '../../common/network/requests.dart'; import '../../common/network/urls.dart'; class _IgcCacheItem { - final Future data; + final Future data; final DateTime timestamp; const _IgcCacheItem({ @@ -52,7 +53,7 @@ class IgcRepo { static final Map _ignoredMatchCache = {}; static const Duration _cacheDuration = Duration(minutes: 10); - static Future> get( + static Future> get( String? accessToken, IGCRequestModel igcRequest, ) { @@ -69,7 +70,7 @@ class IgcRepo { return _getResult(igcRequest, future); } - static Future _fetch( + static Future _fetch( String? accessToken, { required IGCRequestModel igcRequest, }) async { @@ -91,12 +92,16 @@ class IgcRepo { final Map json = jsonDecode(utf8.decode(res.bodyBytes).toString()); - return IGCResponseModel.fromJson(json); + final respModel = IGCResponseModel.fromJson(json); + return IGCTextData( + originalInput: respModel.originalInput, + matches: respModel.matches, + ); } - static Future> _getResult( + static Future> _getResult( IGCRequestModel request, - Future future, + Future future, ) async { try { final res = await future; @@ -112,7 +117,7 @@ class IgcRepo { } } - static Future? _getCached( + static Future? _getCached( IGCRequestModel request, ) { final cacheKeys = [..._igcCache.keys]; @@ -129,7 +134,7 @@ class IgcRepo { static void _setCached( IGCRequestModel request, - Future response, + Future response, ) => _igcCache[request.hashCode.toString()] = _IgcCacheItem( data: response, diff --git a/lib/pangea/choreographer/igc/span_card.dart b/lib/pangea/choreographer/igc/span_card.dart index d4cb848d1..a1f0412a9 100644 --- a/lib/pangea/choreographer/igc/span_card.dart +++ b/lib/pangea/choreographer/igc/span_card.dart @@ -8,8 +8,8 @@ import 'package:fluffychat/pangea/choreographer/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_state_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_choice_type_enum.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_data_model.dart'; +import 'package:fluffychat/pangea/common/utils/async_state.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/common/utils/feedback_model.dart'; import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import '../../../widgets/matrix.dart'; import '../../common/widgets/choice_array.dart'; @@ -32,7 +32,8 @@ class SpanCard extends StatefulWidget { class SpanCardState extends State { bool _loadingChoices = true; - final _feedbackModel = FeedbackModel(); + final ValueNotifier> _feedbackState = + ValueNotifier>(const AsyncIdle()); final ScrollController scrollController = ScrollController(); @@ -44,7 +45,7 @@ class SpanCardState extends State { @override void dispose() { - _feedbackModel.dispose(); + _feedbackState.dispose(); scrollController.dispose(); super.dispose(); } @@ -62,19 +63,21 @@ class SpanCardState extends State { return; } + setState(() => _loadingChoices = true); + try { - setState(() => _loadingChoices = true); await widget.choreographer.igcController.fetchSpanDetails( match: widget.match, ); - } catch (e) { - widget.choreographer.clearMatches(e); - } finally { + if (_choices == null || _choices!.isEmpty) { widget.choreographer.clearMatches( 'No choices available for span ${widget.match.updatedMatch.match.message}', ); } + } catch (e) { + widget.choreographer.clearMatches(e); + } finally { if (mounted) { setState(() => _loadingChoices = false); } @@ -83,29 +86,28 @@ class SpanCardState extends State { Future _fetchFeedback() async { if (_selectedFeedback != null) { - _feedbackModel.setState(FeedbackLoaded(_selectedFeedback!)); + _feedbackState.value = AsyncLoaded(_selectedFeedback!); return; } try { - _feedbackModel.setState(FeedbackLoading()); + _feedbackState.value = const AsyncLoading(); await widget.choreographer.igcController.fetchSpanDetails( match: widget.match, force: true, ); - } finally { + + if (!mounted) return; + if (_selectedFeedback != null) { + _feedbackState.value = AsyncLoaded(_selectedFeedback!); + } else { + _feedbackState.value = AsyncError( + L10n.of(context).failedToLoadFeedback, + ); + } + } catch (e) { if (mounted) { - if (_selectedFeedback == null) { - _feedbackModel.setState( - FeedbackError( - L10n.of(context).failedToLoadFeedback, - ), - ); - } else { - _feedbackModel.setState( - FeedbackLoaded(_selectedFeedback!), - ); - } + _feedbackState.value = AsyncError(e); } } } @@ -113,11 +115,11 @@ class SpanCardState extends State { void _onChoiceSelect(int index) { final selected = _choices![index]; widget.match.selectChoice(index); - _feedbackModel.setState( - selected.feedback != null - ? FeedbackLoaded(selected.feedback!) - : FeedbackIdle(), - ); + + _feedbackState.value = selected.feedback != null + ? AsyncLoaded(selected.feedback!) + : const AsyncIdle(); + setState(() {}); } @@ -185,7 +187,7 @@ class SpanCardState extends State { _SpanCardFeedback( _selectedChoice != null, _fetchFeedback, - _feedbackModel, + _feedbackState, ), ], ), @@ -207,12 +209,12 @@ class SpanCardState extends State { class _SpanCardFeedback extends StatelessWidget { final bool hasSelectedChoice; final VoidCallback fetchFeedback; - final FeedbackModel feedbackModel; + final ValueNotifier> feedbackState; const _SpanCardFeedback( this.hasSelectedChoice, this.fetchFeedback, - this.feedbackModel, + this.feedbackState, ); @override @@ -224,12 +226,11 @@ class _SpanCardFeedback extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - ListenableBuilder( - listenable: feedbackModel, - builder: (context, _) { - final state = feedbackModel.state; + ValueListenableBuilder( + valueListenable: feedbackState, + builder: (context, state, __) { return switch (state) { - FeedbackIdle() => hasSelectedChoice + AsyncIdle() => hasSelectedChoice ? IconButton( onPressed: fetchFeedback, icon: const Icon(Icons.lightbulb_outline, size: 24), @@ -240,14 +241,14 @@ class _SpanCardFeedback extends StatelessWidget { fontStyle: FontStyle.italic, ), ), - FeedbackLoading() => const SizedBox( + AsyncLoading() => const SizedBox( width: 24, height: 24, child: CircularProgressIndicator(), ), - FeedbackError(:final error) => + AsyncError(:final error) => ErrorIndicator(message: error.toString()), - FeedbackLoaded(:final value) => + AsyncLoaded(:final value) => Text(value, style: BotStyle.text(context)), }; }, diff --git a/lib/pangea/choreographer/igc/span_data_repo.dart b/lib/pangea/choreographer/igc/span_data_repo.dart index 2f536d5a4..7c07825bc 100644 --- a/lib/pangea/choreographer/igc/span_data_repo.dart +++ b/lib/pangea/choreographer/igc/span_data_repo.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:async/async.dart'; import 'package:http/http.dart'; +import 'package:fluffychat/pangea/choreographer/igc/span_data_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_data_request.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_data_response.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; @@ -11,7 +12,7 @@ import '../../common/network/requests.dart'; import '../../common/network/urls.dart'; class _SpanDetailsCacheItem { - final Future data; + final Future data; final DateTime timestamp; const _SpanDetailsCacheItem({ @@ -24,7 +25,7 @@ class SpanDataRepo { static final Map _cache = {}; static const Duration _cacheDuration = Duration(minutes: 10); - static Future> get( + static Future> get( String? accessToken, { required SpanDetailsRequest request, }) async { @@ -41,7 +42,7 @@ class SpanDataRepo { return _getResult(request, future); } - static Future _fetch( + static Future _fetch( String? accessToken, { required SpanDetailsRequest request, }) async { @@ -59,14 +60,15 @@ class SpanDataRepo { throw Exception('Failed to load span details'); } - return SpanDetailsResponse.fromJson( + final respModel = SpanDetailsResponse.fromJson( jsonDecode(utf8.decode(res.bodyBytes)), ); + return respModel.span; } - static Future> _getResult( + static Future> _getResult( SpanDetailsRequest request, - Future future, + Future future, ) async { try { final res = await future; @@ -82,7 +84,7 @@ class SpanDataRepo { } } - static Future? _getCached( + static Future? _getCached( SpanDetailsRequest request, ) { final cacheKeys = [..._cache.keys]; @@ -96,7 +98,7 @@ class SpanDataRepo { static void _setCached( SpanDetailsRequest request, - Future response, + Future response, ) { _cache[request.hashCode.toString()] = _SpanDetailsCacheItem( data: response, diff --git a/lib/pangea/choreographer/it/contextual_definition_repo.dart b/lib/pangea/choreographer/it/contextual_definition_repo.dart index c1a7a67e7..8d6a5a616 100644 --- a/lib/pangea/choreographer/it/contextual_definition_repo.dart +++ b/lib/pangea/choreographer/it/contextual_definition_repo.dart @@ -11,10 +11,9 @@ import '../../common/network/requests.dart'; import '../../common/network/urls.dart'; class ContextualDefinitionRepo { - static final Map> _cache = - {}; + static final Map> _cache = {}; - static Future> get( + static Future> get( String accessToken, ContextualDefinitionRequestModel request, ) async { @@ -38,7 +37,7 @@ class ContextualDefinitionRepo { return _getResult(request, future); } - static Future _fetch( + static Future _fetch( String accessToken, ContextualDefinitionRequestModel request, ) async { @@ -77,12 +76,12 @@ class ContextualDefinitionRepo { ); } - return response; + return response.text; } - static Future> _getResult( + static Future> _getResult( ContextualDefinitionRequestModel request, - Future future, + Future future, ) async { try { final res = await future; @@ -98,14 +97,14 @@ class ContextualDefinitionRepo { } } - static Future? _getCached( + static Future? _getCached( ContextualDefinitionRequestModel request, ) => _cache[request.hashCode.toString()]; static void _setCached( ContextualDefinitionRequestModel request, - Future response, + Future response, ) => _cache[request.hashCode.toString()] = response; } diff --git a/lib/pangea/choreographer/it/it_bar.dart b/lib/pangea/choreographer/it/it_bar.dart index eaeb537b5..a65f42be9 100644 --- a/lib/pangea/choreographer/it/it_bar.dart +++ b/lib/pangea/choreographer/it/it_bar.dart @@ -113,9 +113,8 @@ class ITBarState extends State with SingleTickerProviderStateMixin { cardToShow: choiceFeedback == null ? WordDataCard( word: text, - wordLang: l2Code, + langCode: l2Code, fullText: _sourceText.value ?? widget.choreographer.currentText, - fullTextLang: l2Code, ) : ITFeedbackCard( FullTextTranslationRequestModel( @@ -129,7 +128,7 @@ class ITBarState extends State with SingleTickerProviderStateMixin { maxWidth: 300, borderColor: borderColor, transformTargetId: 'it_bar', - isScrollable: choiceFeedback == null, + isScrollable: false, overlayKey: "it_feedback_card", ignorePointer: true, ); diff --git a/lib/pangea/choreographer/it/it_feedback_card.dart b/lib/pangea/choreographer/it/it_feedback_card.dart index 6cb9ffecd..39ffbba8d 100644 --- a/lib/pangea/choreographer/it/it_feedback_card.dart +++ b/lib/pangea/choreographer/it/it_feedback_card.dart @@ -6,7 +6,6 @@ import 'package:async/async.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart'; -import 'package:fluffychat/pangea/common/utils/feedback_model.dart'; import 'package:fluffychat/pangea/translation/full_text_translation_repo.dart'; import 'package:fluffychat/pangea/translation/full_text_translation_request_model.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; @@ -14,7 +13,7 @@ import '../../../widgets/matrix.dart'; import '../../bot/utils/bot_style.dart'; import '../../common/widgets/card_error_widget.dart'; -class ITFeedbackCard extends StatefulWidget { +class ITFeedbackCard extends StatelessWidget { final FullTextTranslationRequestModel req; const ITFeedbackCard( @@ -22,56 +21,22 @@ class ITFeedbackCard extends StatefulWidget { super.key, }); - @override - State createState() => ITFeedbackCardController(); -} - -class ITFeedbackCardController extends State { - final FeedbackModel _feedbackModel = FeedbackModel(); - - @override - void initState() { - super.initState(); - _getFeedback(); - } - - @override - void dispose() { - _feedbackModel.dispose(); - super.dispose(); - } - - Future _getFeedback() async { - _feedbackModel.setState(FeedbackLoading()); - final result = await FullTextTranslationRepo.get( + Future> _getFeedback() { + return FullTextTranslationRepo.get( MatrixState.pangeaController.userController.accessToken, - widget.req, + req, ).timeout( const Duration(seconds: 10), - onTimeout: () { - return Result.error("Timeout getting translation"); - }, + onTimeout: () => Result.error("Timeout getting translation"), ); - - if (!mounted) return; - if (result.isError) { - _feedbackModel.setState( - FeedbackError(result.error.toString()), - ); - } else { - _feedbackModel.setState( - FeedbackLoaded(result.result!.bestTranslation), - ); - } } @override Widget build(BuildContext context) { - return ListenableBuilder( - listenable: _feedbackModel, - builder: (context, _) { - final state = _feedbackModel.state; - if (state is FeedbackError) { + return FutureBuilder>( + future: _getFeedback(), + builder: (context, snapshot) { + if (snapshot.hasError) { return CardErrorWidget(L10n.of(context).errorFetchingDefinition); } @@ -83,22 +48,22 @@ class ITFeedbackCardController extends State { alignment: WrapAlignment.center, children: [ Text( - widget.req.text, + req.text, style: BotStyle.text(context), ), Text( "≈", style: BotStyle.text(context), ), - _feedbackModel.state is FeedbackLoaded + snapshot.hasData ? Text( - (state as FeedbackLoaded).value, + snapshot.data!.result!, style: BotStyle.text(context), ) : TextLoadingShimmer( width: min( 140, - 10.0 * widget.req.text.length, + 10.0 * req.text.length, ), ), ], diff --git a/lib/pangea/choreographer/it/word_data_card.dart b/lib/pangea/choreographer/it/word_data_card.dart index 942aef97e..0399248bf 100644 --- a/lib/pangea/choreographer/it/word_data_card.dart +++ b/lib/pangea/choreographer/it/word_data_card.dart @@ -2,120 +2,65 @@ import 'package:flutter/material.dart'; import 'package:async/async.dart'; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/bot/utils/bot_style.dart'; import 'package:fluffychat/pangea/choreographer/it/contextual_definition_repo.dart'; import 'package:fluffychat/pangea/choreographer/it/contextual_definition_request_model.dart'; -import 'package:fluffychat/pangea/common/utils/feedback_model.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; import 'package:fluffychat/pangea/toolbar/widgets/toolbar_content_loading_indicator.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; -class WordDataCard extends StatefulWidget { +class WordDataCard extends StatelessWidget { final String word; final String fullText; - final String wordLang; - final String fullTextLang; + final String langCode; const WordDataCard({ super.key, required this.word, required this.fullText, - required this.wordLang, - required this.fullTextLang, + required this.langCode, }); - @override - State createState() => WordDataCardController(); -} - -class WordDataCardController extends State { - final FeedbackModel _feedbackModel = FeedbackModel(); - - @override - void initState() { - super.initState(); - _getContextualDefinition(); - } - - @override - void didUpdateWidget(covariant WordDataCard oldWidget) { - if (oldWidget.word != widget.word) { - _getContextualDefinition(); - } - super.didUpdateWidget(oldWidget); - } - - @override - void dispose() { - _feedbackModel.dispose(); - super.dispose(); - } - - ContextualDefinitionRequestModel get _request => - ContextualDefinitionRequestModel( - fullText: widget.fullText, - word: widget.word, - fullTextLang: widget.fullTextLang, - wordLang: widget.wordLang, - feedbackLang: - MatrixState.pangeaController.languageController.activeL1Code() ?? - LanguageKeys.defaultLanguage, - ); - - Future _getContextualDefinition() async { - _feedbackModel.setState(FeedbackLoading()); - final resp = await ContextualDefinitionRepo.get( + Future> _fetchDefinition() { + final request = ContextualDefinitionRequestModel( + fullText: fullText, + word: word, + fullTextLang: langCode, + wordLang: langCode, + feedbackLang: + MatrixState.pangeaController.languageController.activeL1Code() ?? + LanguageKeys.defaultLanguage, + ); + return ContextualDefinitionRepo.get( MatrixState.pangeaController.userController.accessToken, - _request, + request, ).timeout( const Duration(seconds: 10), - onTimeout: () { - return Result.error("Timeout getting definition"); - }, + onTimeout: () => Result.error("Timeout getting definition"), ); - - if (!mounted) return; - if (resp.isError) { - _feedbackModel.setState( - const FeedbackError("Error getting definition"), - ); - } else { - _feedbackModel.setState(FeedbackLoaded(resp.result!.text)); - } } @override Widget build(BuildContext context) { - return ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: AppConfig.toolbarMinWidth, - maxHeight: AppConfig.toolbarMaxHeight, - ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: ListenableBuilder( - listenable: _feedbackModel, - builder: (context, _) { - final state = _feedbackModel.state; - return switch (state) { - FeedbackIdle() => const SizedBox.shrink(), - FeedbackLoading() => - const ToolbarContentLoadingIndicator(), - FeedbackError() => Text( - L10n.of(context).sorryNoResults, - style: BotStyle.text(context), - textAlign: TextAlign.center, - ), - FeedbackLoaded(:final value) => - Text(value, style: BotStyle.text(context)), - }; - }, - ), - ), + return Center( + child: FutureBuilder>( + future: _fetchDefinition(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const ToolbarContentLoadingIndicator(); + } + final result = snapshot.data!; + if (result.isError) { + return Text( + L10n.of(context).sorryNoResults, + style: BotStyle.text(context), + textAlign: TextAlign.center, + ); + } + return Text(result.result!, style: BotStyle.text(context)); + }, ), ); } diff --git a/lib/pangea/common/utils/async_state.dart b/lib/pangea/common/utils/async_state.dart new file mode 100644 index 000000000..91c4e36db --- /dev/null +++ b/lib/pangea/common/utils/async_state.dart @@ -0,0 +1,55 @@ +/// A generic sealed class that represents the state of an asynchronous operation. +sealed class AsyncState { + /// Base constructor for all asynchronous state variants. + const AsyncState(); + + /// Represents an idle state before any asynchronous work has begun. + const factory AsyncState.idle() = AsyncIdle; + + /// Represents an in-progress loading state. + const factory AsyncState.loading() = AsyncLoading; + + /// Represents a completed asynchronous operation with a successful [value]. + const factory AsyncState.loaded(T value) = AsyncLoaded; + + /// Represents a failed asynchronous operation with an [error]. + const factory AsyncState.error(Object error) = AsyncError; +} + +/// The idle state of an [AsyncState], indicating no active or completed work. +/// +/// Use this as the initial state before triggering an async operation. +class AsyncIdle extends AsyncState { + /// Creates an idle [AsyncState]. + const AsyncIdle(); +} + +/// The loading state of an [AsyncState], indicating that work is in progress. +/// +/// This state is typically used to show a loading spinner or progress indicator. +class AsyncLoading extends AsyncState { + /// Creates a loading [AsyncState]. + const AsyncLoading(); +} + +/// The success state of an [AsyncState], containing a completed [value]. +/// +/// This state indicates that the asynchronous work finished successfully. +class AsyncLoaded extends AsyncState { + /// The result of the successful asynchronous operation. + final T value; + + /// Creates a loaded [AsyncState] with a [value]. + const AsyncLoaded(this.value); +} + +/// The error state of an [AsyncState], containing an [error]. +/// +/// This state indicates that the asynchronous work failed. +class AsyncError extends AsyncState { + /// The error produced during the asynchronous operation. + final Object error; + + /// Creates an error [AsyncState] with an [error]. + const AsyncError(this.error); +} diff --git a/lib/pangea/common/utils/feedback_model.dart b/lib/pangea/common/utils/feedback_model.dart deleted file mode 100644 index da5975335..000000000 --- a/lib/pangea/common/utils/feedback_model.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter/material.dart'; - -sealed class FeedbackState { - const FeedbackState(); -} - -class FeedbackIdle extends FeedbackState {} - -class FeedbackLoading extends FeedbackState {} - -class FeedbackLoaded extends FeedbackState { - final T value; - const FeedbackLoaded(this.value); -} - -class FeedbackError extends FeedbackState { - final Object error; - const FeedbackError(this.error); -} - -class FeedbackModel extends ChangeNotifier { - FeedbackState _state = FeedbackIdle(); - FeedbackState get state => _state; - - void setState(FeedbackState newState) { - _state = newState; - notifyListeners(); - } -} diff --git a/lib/pangea/events/controllers/message_data_controller.dart b/lib/pangea/events/controllers/message_data_controller.dart index ced9bb675..01a024a92 100644 --- a/lib/pangea/events/controllers/message_data_controller.dart +++ b/lib/pangea/events/controllers/message_data_controller.dart @@ -88,7 +88,7 @@ class MessageDataController extends BaseController { final rep = PangeaRepresentation( langCode: req.tgtLang, - text: res.result!.bestTranslation, + text: res.result!, originalSent: false, originalWritten: false, ); @@ -131,7 +131,7 @@ class MessageDataController extends BaseController { final rep = PangeaRepresentation( langCode: req.tgtLang, - text: res.result!.bestTranslation, + text: res.result!, originalSent: originalSent, originalWritten: false, ); @@ -180,7 +180,7 @@ class MessageDataController extends BaseController { } final translation = SttTranslationModel( - translation: res.result!.bestTranslation, + translation: res.result!, langCode: req.tgtLang, ); diff --git a/lib/pangea/translation/full_text_translation_repo.dart b/lib/pangea/translation/full_text_translation_repo.dart index 85109ef50..b1e621f11 100644 --- a/lib/pangea/translation/full_text_translation_repo.dart +++ b/lib/pangea/translation/full_text_translation_repo.dart @@ -14,7 +14,7 @@ import '../common/network/requests.dart'; import '../common/network/urls.dart'; class _TranslateCacheItem { - final Future response; + final Future response; final DateTime timestamp; const _TranslateCacheItem({ @@ -27,7 +27,7 @@ class FullTextTranslationRepo { static final Map _cache = {}; static const Duration _cacheDuration = Duration(minutes: 10); - static Future> get( + static Future> get( String accessToken, FullTextTranslationRequestModel request, ) { @@ -41,7 +41,7 @@ class FullTextTranslationRepo { return _getResult(request, future); } - static Future _fetch( + static Future _fetch( String accessToken, FullTextTranslationRequestModel request, ) async { @@ -63,12 +63,12 @@ class FullTextTranslationRepo { return FullTextTranslationResponseModel.fromJson( jsonDecode(utf8.decode(res.bodyBytes)), - ); + ).bestTranslation; } - static Future> _getResult( + static Future> _getResult( FullTextTranslationRequestModel request, - Future future, + Future future, ) async { try { final res = await future; @@ -84,7 +84,7 @@ class FullTextTranslationRepo { } } - static Future? _getCached( + static Future? _getCached( FullTextTranslationRequestModel request, ) { final cacheKeys = [..._cache.keys]; @@ -99,7 +99,7 @@ class FullTextTranslationRepo { static void _setCached( FullTextTranslationRequestModel request, - Future response, + Future response, ) => _cache[request.hashCode.toString()] = _TranslateCacheItem( response: response,