From 774432ef495c39f08594b7b36fc98ed00c353873 Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:09:45 -0500 Subject: [PATCH] 5825 remove unreferenced writing assistance code (#5826) * chore: delete span details * remove IT * fix null check error * more cleanup --- lib/pages/chat/chat.dart | 13 - lib/pages/chat/chat_view.dart | 21 +- lib/pages/chat/input_bar.dart | 6 +- .../activity_role_tooltip.dart | 43 -- .../widgets/chat_floating_action_button.dart | 4 +- lib/pangea/chat/widgets/chat_input_bar.dart | 56 +-- .../chat/widgets/chat_view_background.dart | 38 -- .../chat/widgets/pangea_chat_input_row.dart | 17 +- .../choreographer/choreo_constants.dart | 9 - .../choreographer/choreo_mode_enum.dart | 1 - .../choreographer/choreo_record_model.dart | 2 +- lib/pangea/choreographer/choreographer.dart | 123 +----- .../choreographer_send_button.dart | 7 +- .../choreographer_state_extension.dart | 10 +- .../{it => }/completed_it_step_model.dart | 57 --- .../choreographer/igc/span_data_repo.dart | 96 ---- .../choreographer/igc/span_data_request.dart | 47 -- .../choreographer/igc/span_data_response.dart | 26 -- .../it/contextual_definition_repo.dart | 92 ---- .../contextual_definition_request_model.dart | 44 -- .../contextual_definition_response_model.dart | 9 - .../it/gold_route_tracker_model.dart | 37 -- lib/pangea/choreographer/it/it_bar.dart | 410 ------------------ .../choreographer/it/it_controller.dart | 239 ---------- .../choreographer/it/it_feedback_card.dart | 58 --- lib/pangea/choreographer/it/it_repo.dart | 87 ---- .../choreographer/it/it_request_model.dart | 69 --- .../choreographer/it/it_response_model.dart | 74 ---- lib/pangea/choreographer/it/it_shimmer.dart | 38 -- .../choreographer/it/it_step_model.dart | 61 --- .../choreographer/it/word_data_card.dart | 69 --- lib/pangea/common/network/urls.dart | 16 - lib/pangea/common/widgets/choice_array.dart | 31 +- 33 files changed, 68 insertions(+), 1842 deletions(-) delete mode 100644 lib/pangea/activity_sessions/activity_session_chat/activity_role_tooltip.dart delete mode 100644 lib/pangea/chat/widgets/chat_view_background.dart delete mode 100644 lib/pangea/choreographer/choreo_mode_enum.dart rename lib/pangea/choreographer/{it => }/completed_it_step_model.dart (66%) delete mode 100644 lib/pangea/choreographer/igc/span_data_repo.dart delete mode 100644 lib/pangea/choreographer/igc/span_data_request.dart delete mode 100644 lib/pangea/choreographer/igc/span_data_response.dart delete mode 100644 lib/pangea/choreographer/it/contextual_definition_repo.dart delete mode 100644 lib/pangea/choreographer/it/contextual_definition_request_model.dart delete mode 100644 lib/pangea/choreographer/it/contextual_definition_response_model.dart delete mode 100644 lib/pangea/choreographer/it/gold_route_tracker_model.dart delete mode 100644 lib/pangea/choreographer/it/it_bar.dart delete mode 100644 lib/pangea/choreographer/it/it_controller.dart delete mode 100644 lib/pangea/choreographer/it/it_feedback_card.dart delete mode 100644 lib/pangea/choreographer/it/it_repo.dart delete mode 100644 lib/pangea/choreographer/it/it_request_model.dart delete mode 100644 lib/pangea/choreographer/it/it_response_model.dart delete mode 100644 lib/pangea/choreographer/it/it_shimmer.dart delete mode 100644 lib/pangea/choreographer/it/it_step_model.dart delete mode 100644 lib/pangea/choreographer/it/word_data_card.dart diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index a43942e80..00bb1f6dc 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -572,7 +572,6 @@ class ChatController extends State void _pangeaInit() { choreographer = Choreographer(inputFocus); - choreographer.timesDismissedIT.addListener(_onCloseIT); final updater = Matrix.of(context).analyticsDataService.updateDispatcher; _levelSubscription = updater.levelUpdateStream.stream.listen(_onLevelUp); @@ -861,7 +860,6 @@ class ChatController extends State _constructsSubscription?.cancel(); _tokensSubscription?.cancel(); _router.routeInformationProvider.removeListener(_onRouteChanged); - choreographer.timesDismissedIT.removeListener(_onCloseIT); scrollController.dispose(); inputFocus.dispose(); depressMessageButton.dispose(); @@ -2287,11 +2285,6 @@ class ChatController extends State return; } - if (matchToShow.updatedMatch.isITStart) { - choreographer.itController.openIT(sendController.text); - return; - } - final isSpanCardOpen = MatrixState.pAnyState.isOverlayOpen( overlayKey: 'span-card-overlay', ); @@ -2397,12 +2390,6 @@ class ChatController extends State } } - void _onCloseIT() { - if (choreographer.timesDismissedIT.value >= 3) { - showDisableLanguageToolsPopup(); - } - } - void showDisableLanguageToolsPopup() { if (InstructionsEnum.disableLanguageTools.isToggledOff) { return; diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index f9665e0aa..ebd52e578 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -24,7 +24,6 @@ import 'package:fluffychat/pangea/activity_sessions/activity_session_start/activ import 'package:fluffychat/pangea/analytics_misc/level_up/star_rain_widget.dart'; import 'package:fluffychat/pangea/chat/widgets/chat_floating_action_button.dart'; import 'package:fluffychat/pangea/chat/widgets/chat_input_bar.dart'; -import 'package:fluffychat/pangea/chat/widgets/chat_view_background.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; import 'package:fluffychat/pangea/navigation/navigation_util.dart'; import 'package:fluffychat/utils/account_config.dart'; @@ -474,21 +473,11 @@ class ChatView extends StatelessWidget { // #Pangea // onTap: controller.clearSingleSelectedEvent, // child: ChatEventList(controller: controller), - child: Stack( - children: [ - ListenableBuilder( - listenable: - controller.timelineUpdateNotifier, - builder: (context, _) { - return ChatEventList( - controller: controller, - ); - }, - ), - ChatViewBackground( - controller.choreographer.itController.open, - ), - ], + child: ListenableBuilder( + listenable: controller.timelineUpdateNotifier, + builder: (context, _) { + return ChatEventList(controller: controller); + }, ), // Pangea# ), diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 775d3da91..7ea6094a3 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -8,7 +8,6 @@ import 'package:slugify/slugify.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/choreographer/choreo_constants.dart'; -import 'package:fluffychat/pangea/choreographer/choreo_mode_enum.dart'; import 'package:fluffychat/pangea/choreographer/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_state_model.dart'; import 'package:fluffychat/pangea/choreographer/text_editing/pangea_text_controller.dart'; @@ -484,7 +483,6 @@ class InputBar extends StatelessWidget { contextMenuBuilder: (c, e) => markdownContextBuilder(c, e, controller!), onTap: () => _onInputTap(context), - readOnly: choreographer.choreoMode == ChoreoModeEnum.it, autocorrect: MatrixState.pangeaController.userController .isToolEnabled(ToolSetting.enableAutocorrect), // Pangea# @@ -532,9 +530,7 @@ class InputBar extends StatelessWidget { builder: (context, _) => SizedBox( height: 24, child: ShrinkableText( - text: choreographer.itController.open.value - ? L10n.of(context).buildTranslation - : _defaultHintText(context), + text: _defaultHintText(context), maxWidth: double.infinity, style: Theme.of(context).textTheme.bodyLarge?.copyWith( color: Theme.of(context).disabledColor, diff --git a/lib/pangea/activity_sessions/activity_session_chat/activity_role_tooltip.dart b/lib/pangea/activity_sessions/activity_session_chat/activity_role_tooltip.dart deleted file mode 100644 index 18e1819f2..000000000 --- a/lib/pangea/activity_sessions/activity_session_chat/activity_role_tooltip.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; -import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; - -class ActivityRoleTooltip extends StatelessWidget { - final Room room; - final ValueNotifier hide; - - const ActivityRoleTooltip({ - required this.room, - required this.hide, - super.key, - }); - - @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: hide, - builder: (context, hide, _) { - if (!room.showActivityChatUI || room.ownRole?.goal == null || hide) { - return const SizedBox(); - } - - return InlineTooltip( - message: room.ownRole!.goal!, - isClosed: room.hasDismissedGoalTooltip, - onClose: () async { - await room.dismissGoalTooltip(); - }, - padding: EdgeInsets.only( - left: 16.0, - right: 16.0, - top: FluffyThemes.isColumnMode(context) ? 16.0 : 8.0, - ), - ); - }, - ); - } -} diff --git a/lib/pangea/chat/widgets/chat_floating_action_button.dart b/lib/pangea/chat/widgets/chat_floating_action_button.dart index b29f5ee59..05f657885 100644 --- a/lib/pangea/chat/widgets/chat_floating_action_button.dart +++ b/lib/pangea/chat/widgets/chat_floating_action_button.dart @@ -16,7 +16,6 @@ class ChatFloatingActionButton extends StatelessWidget { return ListenableBuilder( listenable: Listenable.merge([ controller.choreographer.errorService, - controller.choreographer.itController.open, controller.scrollController, controller.scrollableNotifier, ]), @@ -31,8 +30,7 @@ class ChatFloatingActionButton extends StatelessWidget { ); } - if (controller.choreographer.errorService.error != null && - !controller.choreographer.itController.open.value) { + if (controller.choreographer.errorService.error != null) { return ChoreographerHasErrorButton( controller.choreographer.errorService.error!, controller.choreographer, diff --git a/lib/pangea/chat/widgets/chat_input_bar.dart b/lib/pangea/chat/widgets/chat_input_bar.dart index 1938ffbd7..abdeeedd4 100644 --- a/lib/pangea/chat/widgets/chat_input_bar.dart +++ b/lib/pangea/chat/widgets/chat_input_bar.dart @@ -5,10 +5,8 @@ import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pages/chat/chat_emoji_picker.dart'; import 'package:fluffychat/pages/chat/reply_display.dart'; -import 'package:fluffychat/pangea/activity_sessions/activity_session_chat/activity_role_tooltip.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; import 'package:fluffychat/pangea/chat/widgets/pangea_chat_input_row.dart'; -import 'package:fluffychat/pangea/choreographer/it/it_bar.dart'; -import 'package:fluffychat/pangea/instructions/instructions_enum.dart'; import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; class ChatInputBar extends StatelessWidget { @@ -27,36 +25,27 @@ class ChatInputBar extends StatelessWidget { return Column( mainAxisSize: MainAxisSize.min, children: [ - ValueListenableBuilder( - valueListenable: controller.choreographer.itController.open, - builder: (context, open, _) { - return open - ? Container( - constraints: const BoxConstraints( - maxWidth: FluffyThemes.maxTimelineWidth, - ), - alignment: Alignment.center, - child: InstructionsInlineTooltip( - instructionsEnum: InstructionsEnum.clickBestOption, - animate: false, - padding: EdgeInsets.only( - left: 16.0, - right: 16.0, - top: FluffyThemes.isColumnMode(context) ? 16.0 : 8.0, - ), - ), - ) - : Container( - constraints: const BoxConstraints( - maxWidth: FluffyThemes.maxTimelineWidth, - ), - alignment: Alignment.center, - child: ActivityRoleTooltip( - room: controller.room, - hide: controller.choreographer.itController.open, - ), - ); - }, + Container( + constraints: const BoxConstraints( + maxWidth: FluffyThemes.maxTimelineWidth, + ), + alignment: Alignment.center, + child: + controller.room.showActivityChatUI && + controller.room.ownRole?.goal != null + ? InlineTooltip( + message: controller.room.ownRole!.goal!, + isClosed: controller.room.hasDismissedGoalTooltip, + onClose: () async { + await controller.room.dismissGoalTooltip(); + }, + padding: EdgeInsets.only( + left: 16.0, + right: 16.0, + top: FluffyThemes.isColumnMode(context) ? 16.0 : 8.0, + ), + ) + : SizedBox(), ), Container( margin: EdgeInsets.all( @@ -75,7 +64,6 @@ class ChatInputBar extends StatelessWidget { : Column( mainAxisSize: MainAxisSize.min, children: [ - ITBar(choreographer: controller.choreographer), ReplyDisplay(controller), PangeaChatInputRow(controller: controller), ChatEmojiPicker(controller), diff --git a/lib/pangea/chat/widgets/chat_view_background.dart b/lib/pangea/chat/widgets/chat_view_background.dart deleted file mode 100644 index f74c79278..000000000 --- a/lib/pangea/chat/widgets/chat_view_background.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/material.dart'; - -class ChatViewBackground extends StatelessWidget { - final ValueNotifier visible; - const ChatViewBackground(this.visible, {super.key}); - - @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: visible, - builder: (context, value, _) { - return value - ? Positioned( - left: 0, - right: 0, - top: 0, - bottom: 0, - child: Material( - borderOnForeground: false, - color: const Color.fromRGBO(0, 0, 0, 1).withAlpha(150), - clipBehavior: Clip.antiAlias, - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 2.5, sigmaY: 2.5), - child: Container( - height: double.infinity, - width: double.infinity, - color: Colors.transparent, - ), - ), - ), - ) - : const SizedBox.shrink(); - }, - ); - } -} diff --git a/lib/pangea/chat/widgets/pangea_chat_input_row.dart b/lib/pangea/chat/widgets/pangea_chat_input_row.dart index f54ac14db..5c8a619d3 100644 --- a/lib/pangea/chat/widgets/pangea_chat_input_row.dart +++ b/lib/pangea/chat/widgets/pangea_chat_input_row.dart @@ -69,15 +69,7 @@ class PangeaChatInputRow extends StatelessWidget { duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, height: height, - width: - text.text.isEmpty && - !controller - .choreographer - .itController - .open - .value - ? height - : 0, + width: text.text.isEmpty ? height : 0, alignment: Alignment.center, clipBehavior: Clip.hardEdge, decoration: const BoxDecoration(), @@ -298,12 +290,7 @@ class PangeaChatInputRow extends StatelessWidget { alignment: Alignment.center, child: PlatformInfos.platformCanRecord && - text.text.isEmpty && - !controller - .choreographer - .itController - .open - .value + text.text.isEmpty ? IconButton( tooltip: L10n.of(context).voiceMessage, onPressed: () => recordingViewModel diff --git a/lib/pangea/choreographer/choreo_constants.dart b/lib/pangea/choreographer/choreo_constants.dart index a303266ce..66a0298b0 100644 --- a/lib/pangea/choreographer/choreo_constants.dart +++ b/lib/pangea/choreographer/choreo_constants.dart @@ -1,13 +1,4 @@ -import 'package:flutter/material.dart'; - class ChoreoConstants { - static const numberOfITChoices = 4; - static const levelThresholdForGreen = 1; - static const levelThresholdForYellow = 2; - static const levelThresholdForRed = 3; - static const green = Colors.green; - static const yellow = Color.fromARGB(255, 206, 152, 2); - static const red = Colors.red; static const int msBeforeIGCStart = 10000; static const int maxLength = 1000; static const String inputTransformTargetKey = 'input_text_field'; diff --git a/lib/pangea/choreographer/choreo_mode_enum.dart b/lib/pangea/choreographer/choreo_mode_enum.dart deleted file mode 100644 index 5d382dff3..000000000 --- a/lib/pangea/choreographer/choreo_mode_enum.dart +++ /dev/null @@ -1 +0,0 @@ -enum ChoreoModeEnum { igc, it } diff --git a/lib/pangea/choreographer/choreo_record_model.dart b/lib/pangea/choreographer/choreo_record_model.dart index cc02fd108..47241c905 100644 --- a/lib/pangea/choreographer/choreo_record_model.dart +++ b/lib/pangea/choreographer/choreo_record_model.dart @@ -4,7 +4,7 @@ import 'package:fluffychat/pangea/choreographer/choreo_edit_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_status_enum.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_data_model.dart'; -import 'it/completed_it_step_model.dart'; +import 'completed_it_step_model.dart'; /// this class lives within a [PangeaIGCEvent] /// it always has a [RepresentationEvent] parent diff --git a/lib/pangea/choreographer/choreographer.dart b/lib/pangea/choreographer/choreographer.dart index e4e43b1ad..03fb71039 100644 --- a/lib/pangea/choreographer/choreographer.dart +++ b/lib/pangea/choreographer/choreographer.dart @@ -6,46 +6,37 @@ import 'package:async/async.dart'; import 'package:fluffychat/pangea/choreographer/assistance_state_enum.dart'; import 'package:fluffychat/pangea/choreographer/choreo_constants.dart'; -import 'package:fluffychat/pangea/choreographer/choreo_mode_enum.dart'; import 'package:fluffychat/pangea/choreographer/choreo_record_model.dart'; import 'package:fluffychat/pangea/choreographer/choreographer_state_extension.dart'; import 'package:fluffychat/pangea/choreographer/igc/igc_controller.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_state_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_status_enum.dart'; -import 'package:fluffychat/pangea/choreographer/it/completed_it_step_model.dart'; import 'package:fluffychat/pangea/choreographer/pangea_message_content_model.dart'; import 'package:fluffychat/pangea/choreographer/text_editing/edit_type_enum.dart'; import 'package:fluffychat/pangea/choreographer/text_editing/pangea_text_controller.dart'; -import 'package:fluffychat/pangea/events/models/representation_content_model.dart'; import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/events/repo/token_api_models.dart'; import 'package:fluffychat/pangea/events/repo/tokens_repo.dart'; -import 'package:fluffychat/pangea/languages/language_constants.dart'; import 'package:fluffychat/pangea/learning_settings/tool_settings_enum.dart'; import 'package:fluffychat/pangea/subscription/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/text_to_speech/tts_controller.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import '../../widgets/matrix.dart'; import 'choreographer_error_controller.dart'; -import 'it/it_controller.dart'; class Choreographer extends ChangeNotifier { final FocusNode inputFocus; late final PangeaTextController textController; - late final ITController itController; late final IgcController igcController; late final ChoreographerErrorController errorService; ChoreoRecordModel? _choreoRecord; final ValueNotifier _isFetching = ValueNotifier(false); - final ValueNotifier _timesDismissedIT = ValueNotifier(0); - int _timesClicked = 0; Timer? _debounceTimer; String? _lastChecked; - ChoreoModeEnum _choreoMode = ChoreoModeEnum.igc; DateTime? _lastIgcError; DateTime? _lastTokensError; @@ -54,17 +45,13 @@ class Choreographer extends ChangeNotifier { StreamSubscription? _languageSub; StreamSubscription? _settingsUpdateSub; - StreamSubscription? _acceptedContinuanceSub; StreamSubscription? _updatedMatchSub; Choreographer(this.inputFocus) { _initialize(); } - int get timesClicked => _timesClicked; ValueNotifier get isFetching => _isFetching; - ValueNotifier get timesDismissedIT => _timesDismissedIT; - ChoreoModeEnum get choreoMode => _choreoMode; String get currentText => textController.text; ChoreoRecordModel get _record => _choreoRecord ??= ChoreoRecordModel( @@ -86,12 +73,6 @@ class Choreographer extends ChangeNotifier { errorService = ChoreographerErrorController(); errorService.addListener(notifyListeners); - itController = ITController( - (e) => errorService.setErrorAndLock(ChoreoError(raw: e)), - ); - itController.open.addListener(_onUpdateITOpenStatus); - itController.editing.addListener(_onSubmitSourceTextEdits); - igcController = IgcController( (e) { errorService.setErrorAndLock(ChoreoError(raw: e)); @@ -121,9 +102,6 @@ class Choreographer extends ChangeNotifier { notifyListeners(); }); - _acceptedContinuanceSub ??= itController.acceptedContinuanceStream.stream - .listen(_onAcceptContinuance); - _updatedMatchSub ??= igcController.matchUpdateStream.stream.listen( _onUpdateMatch, ); @@ -131,36 +109,27 @@ class Choreographer extends ChangeNotifier { void clear() { _lastChecked = null; - _timesClicked = 0; _isFetching.value = false; _choreoRecord = null; - itController.closeIT(); - itController.clearSourceText(); - itController.clearSession(); igcController.clear(); _resetDebounceTimer(); - _setChoreoMode(ChoreoModeEnum.igc); + notifyListeners(); } @override void dispose() { errorService.removeListener(notifyListeners); - itController.open.removeListener(_onCloseIT); - itController.editing.removeListener(_onSubmitSourceTextEdits); textController.removeListener(_onChange); _languageSub?.cancel(); _settingsUpdateSub?.cancel(); - _acceptedContinuanceSub?.cancel(); _updatedMatchSub?.cancel(); _debounceTimer?.cancel(); igcController.dispose(); - itController.dispose(); errorService.dispose(); textController.dispose(); _isFetching.dispose(); - _timesDismissedIT.dispose(); TtsController.stop(); super.dispose(); @@ -168,23 +137,6 @@ class Choreographer extends ChangeNotifier { void onPaste(String value) => _record.pastedStrings.add(value); - void onClickSend() { - if (assistanceState == AssistanceStateEnum.fetched) { - _timesClicked++; - - // if user is doing IT, call closeIT here to - // ensure source text is replaced when needed - if (itController.open.value && _timesClicked > 1) { - itController.closeIT(dismiss: true); - } - } - } - - void _setChoreoMode(ChoreoModeEnum mode) { - _choreoMode = mode; - notifyListeners(); - } - void _resetDebounceTimer() { if (_debounceTimer != null) { _debounceTimer?.cancel(); @@ -228,10 +180,8 @@ class Choreographer extends ChangeNotifier { _lastChecked = textController.text; if (errorService.isError) return; if (textController.editType == EditTypeEnum.keyboard) { - if (igcController.currentText != null || - itController.sourceText.value != null) { + if (igcController.currentText != null) { igcController.clear(); - itController.clearSourceText(); notifyListeners(); } @@ -254,9 +204,7 @@ class Choreographer extends ChangeNotifier { MatrixState.pangeaController.userController.userL1 == null || (!ToolSetting.interactiveGrammar.enabled && !ToolSetting.interactiveTranslator.enabled) || - (!ToolSetting.autoIGC.enabled && - !manual && - _choreoMode != ChoreoModeEnum.it) || + (!ToolSetting.autoIGC.enabled && !manual) || _backoffRequest(_lastIgcError, _igcErrorBackoff)) { return; } @@ -334,20 +282,9 @@ class Choreographer extends ChangeNotifier { tokensResp = res.isValue ? res.result : null; } - final hasOriginalWritten = - _record.includedIT && itController.sourceText.value != null; - return PangeaMessageContentModel( message: message, choreo: _record, - originalWritten: hasOriginalWritten - ? PangeaRepresentation( - langCode: l1LangCode ?? LanguageKeys.unknownLanguage, - text: itController.sourceText.value!, - originalWritten: true, - originalSent: false, - ) - : null, tokensSent: tokensResp != null ? PangeaMessageTokens( tokens: tokensResp.tokens, @@ -357,60 +294,6 @@ class Choreographer extends ChangeNotifier { ); } - void _onUpdateITOpenStatus() { - itController.open.value ? _onOpenIT() : _onCloseIT(); - notifyListeners(); - } - - void _onOpenIT() { - inputFocus.unfocus(); - final itMatch = igcController.openMatches.firstWhere( - (match) => match.updatedMatch.isITStart, - orElse: () => - throw Exception("Attempted to open IT without an ITStart match"), - ); - - igcController.clear(); - itMatch.setStatus(PangeaMatchStatusEnum.accepted); - _record.addRecord("", match: itMatch.updatedMatch); - - _setChoreoMode(ChoreoModeEnum.it); - textController.setSystemText("", EditTypeEnum.it); - } - - void _onCloseIT() { - if (itController.dismissed && - currentText.isEmpty && - itController.sourceText.value != null) { - textController.setSystemText( - itController.sourceText.value!, - EditTypeEnum.itDismissed, - ); - } - - if (itController.dismissed) { - _timesDismissedIT.value = _timesDismissedIT.value + 1; - } - _setChoreoMode(ChoreoModeEnum.igc); - errorService.resetError(); - } - - void _onSubmitSourceTextEdits() { - if (itController.editing.value) return; - textController.setSystemText("", EditTypeEnum.it); - } - - void _onAcceptContinuance(CompletedITStepModel step) { - textController.setSystemText( - textController.text + step.continuances[step.chosen].text, - EditTypeEnum.it, - ); - - _record.addRecord(textController.text, step: step); - inputFocus.requestFocus(); - notifyListeners(); - } - void clearMatches(Object error) { MatrixState.pAnyState.closeAllOverlays(); igcController.clearMatches(); diff --git a/lib/pangea/choreographer/choreographer_send_button.dart b/lib/pangea/choreographer/choreographer_send_button.dart index 69a6c6a15..af498d49d 100644 --- a/lib/pangea/choreographer/choreographer_send_button.dart +++ b/lib/pangea/choreographer/choreographer_send_button.dart @@ -8,11 +8,6 @@ class ChoreographerSendButton extends StatelessWidget { final ChatController controller; const ChoreographerSendButton({super.key, required this.controller}); - Future _onPressed(BuildContext context) async { - controller.choreographer.onClickSend(); - controller.onInputBarSubmitted(); - } - @override Widget build(BuildContext context) { return ValueListenableBuilder( @@ -26,7 +21,7 @@ class ChoreographerSendButton extends StatelessWidget { color: controller.choreographer.assistanceState.sendButtonColor( context, ), - onPressed: fetching ? null : () => _onPressed(context), + onPressed: fetching ? null : controller.onInputBarSubmitted, tooltip: L10n.of(context).send, ), ); diff --git a/lib/pangea/choreographer/choreographer_state_extension.dart b/lib/pangea/choreographer/choreographer_state_extension.dart index e02801089..064a62aab 100644 --- a/lib/pangea/choreographer/choreographer_state_extension.dart +++ b/lib/pangea/choreographer/choreographer_state_extension.dart @@ -1,5 +1,4 @@ import 'package:fluffychat/pangea/choreographer/assistance_state_enum.dart'; -import 'package:fluffychat/pangea/choreographer/choreo_mode_enum.dart'; import 'package:fluffychat/pangea/choreographer/choreographer.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -8,7 +7,7 @@ extension ChoregrapherStateExtension on Choreographer { final isSubscribed = MatrixState.pangeaController.subscriptionController.isSubscribed; if (isSubscribed == false) return AssistanceStateEnum.noSub; - if (currentText.trim().isEmpty && itController.sourceText.value == null) { + if (currentText.trim().isEmpty) { return AssistanceStateEnum.noMessage; } @@ -16,15 +15,12 @@ extension ChoregrapherStateExtension on Choreographer { return AssistanceStateEnum.error; } - if (igcController.openMatches.isNotEmpty || - (choreoMode == ChoreoModeEnum.it && - itController.currentITStep.value?.isFinal != true)) { + if (igcController.openMatches.isNotEmpty) { return AssistanceStateEnum.fetched; } if (isFetching.value) return AssistanceStateEnum.fetching; - if (igcController.currentText == null && - itController.sourceText.value == null) { + if (igcController.currentText == null) { return AssistanceStateEnum.notFetched; } return AssistanceStateEnum.complete; diff --git a/lib/pangea/choreographer/it/completed_it_step_model.dart b/lib/pangea/choreographer/completed_it_step_model.dart similarity index 66% rename from lib/pangea/choreographer/it/completed_it_step_model.dart rename to lib/pangea/choreographer/completed_it_step_model.dart index 5eafc6f05..3c8b34d08 100644 --- a/lib/pangea/choreographer/it/completed_it_step_model.dart +++ b/lib/pangea/choreographer/completed_it_step_model.dart @@ -1,8 +1,3 @@ -import 'package:flutter/material.dart'; - -import 'package:fluffychat/l10n/l10n.dart'; -import '../choreo_constants.dart'; - class CompletedITStepModel { final List continuances; final int chosen; @@ -84,58 +79,6 @@ class ContinuanceModel { return data; } - ContinuanceModel copyWith({ - double? probability, - int? level, - String? text, - String? description, - int? indexSavedByServer, - bool? wasClicked, - bool? inDictionary, - bool? hasInfo, - bool? gold, - }) { - return ContinuanceModel( - probability: probability ?? this.probability, - level: level ?? this.level, - text: text ?? this.text, - description: description ?? this.description, - indexSavedByServer: indexSavedByServer ?? this.indexSavedByServer, - wasClicked: wasClicked ?? this.wasClicked, - inDictionary: inDictionary ?? this.inDictionary, - hasInfo: hasInfo ?? this.hasInfo, - gold: gold ?? this.gold, - ); - } - - Color? get color { - if (!wasClicked) return null; - switch (level) { - case ChoreoConstants.levelThresholdForGreen: - return ChoreoConstants.green; - case ChoreoConstants.levelThresholdForYellow: - return ChoreoConstants.yellow; - case ChoreoConstants.levelThresholdForRed: - return ChoreoConstants.red; - default: - return null; - } - } - - String? feedbackText(BuildContext context) { - final L10n l10n = L10n.of(context); - switch (level) { - case ChoreoConstants.levelThresholdForGreen: - return l10n.greenFeedback; - case ChoreoConstants.levelThresholdForYellow: - return l10n.yellowFeedback; - case ChoreoConstants.levelThresholdForRed: - return l10n.redFeedback; - default: - return null; - } - } - @override bool operator ==(Object other) => identical(this, other) || diff --git a/lib/pangea/choreographer/igc/span_data_repo.dart b/lib/pangea/choreographer/igc/span_data_repo.dart deleted file mode 100644 index c19a9aafe..000000000 --- a/lib/pangea/choreographer/igc/span_data_repo.dart +++ /dev/null @@ -1,96 +0,0 @@ -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'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import '../../common/network/requests.dart'; -import '../../common/network/urls.dart'; - -class _SpanDetailsCacheItem { - final Future data; - final DateTime timestamp; - - const _SpanDetailsCacheItem({required this.data, required this.timestamp}); -} - -class SpanDataRepo { - static final Map _cache = {}; - static const Duration _cacheDuration = Duration(minutes: 10); - - static Future> get( - String? accessToken, { - required SpanDetailsRequest request, - }) async { - final cached = _getCached(request); - if (cached != null) { - return _getResult(request, cached); - } - - final future = _fetch(accessToken, request: request); - _setCached(request, future); - return _getResult(request, future); - } - - static Future _fetch( - String? accessToken, { - required SpanDetailsRequest request, - }) async { - final Requests req = Requests( - accessToken: accessToken, - choreoApiKey: Environment.choreoApiKey, - ); - - final Response res = await req.post( - url: PApiUrls.spanDetails, - body: request.toJson(), - ); - - if (res.statusCode != 200) { - throw Exception('Failed to load span details'); - } - - final respModel = SpanDetailsResponse.fromJson( - jsonDecode(utf8.decode(res.bodyBytes)), - ); - return respModel.span; - } - - static Future> _getResult( - SpanDetailsRequest request, - Future future, - ) async { - try { - final res = await future; - return Result.value(res); - } catch (e, s) { - _cache.remove(request.hashCode.toString()); - ErrorHandler.logError(e: e, s: s, data: request.toJson()); - return Result.error(e); - } - } - - static Future? _getCached(SpanDetailsRequest request) { - final cacheKeys = [..._cache.keys]; - for (final key in cacheKeys) { - if (DateTime.now().difference(_cache[key]!.timestamp) >= _cacheDuration) { - _cache.remove(key); - } - } - return _cache[request.hashCode.toString()]?.data; - } - - static void _setCached( - SpanDetailsRequest request, - Future response, - ) { - _cache[request.hashCode.toString()] = _SpanDetailsCacheItem( - data: response, - timestamp: DateTime.now(), - ); - } -} diff --git a/lib/pangea/choreographer/igc/span_data_request.dart b/lib/pangea/choreographer/igc/span_data_request.dart deleted file mode 100644 index 88b80f139..000000000 --- a/lib/pangea/choreographer/igc/span_data_request.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:fluffychat/pangea/choreographer/igc/span_data_model.dart'; -import 'package:fluffychat/pangea/common/constants/model_keys.dart'; - -class SpanDetailsRequest { - final String userL1; - final String userL2; - final bool enableIT; - final bool enableIGC; - final SpanData span; - - const SpanDetailsRequest({ - required this.userL1, - required this.userL2, - required this.enableIGC, - required this.enableIT, - required this.span, - }); - - Map toJson() => { - ModelKey.userL1: userL1, - ModelKey.userL2: userL2, - ModelKey.enableIT: enableIT, - ModelKey.enableIGC: enableIGC, - 'span': span.toJson(), - }; - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other is! SpanDetailsRequest) return false; - if (other.userL1 != userL1) return false; - if (other.userL2 != userL2) return false; - if (other.enableIT != enableIT) return false; - if (other.enableIGC != enableIGC) return false; - if (other.span != span) return false; - return true; - } - - @override - int get hashCode { - return userL1.hashCode ^ - userL2.hashCode ^ - enableIT.hashCode ^ - enableIGC.hashCode ^ - span.hashCode; - } -} diff --git a/lib/pangea/choreographer/igc/span_data_response.dart b/lib/pangea/choreographer/igc/span_data_response.dart deleted file mode 100644 index 331a673ce..000000000 --- a/lib/pangea/choreographer/igc/span_data_response.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:fluffychat/pangea/choreographer/igc/span_data_model.dart'; - -class SpanDetailsResponse { - final String userL1; - final String userL2; - final bool enableIT; - final bool enableIGC; - final SpanData span; - - const SpanDetailsResponse({ - required this.userL1, - required this.userL2, - required this.enableIGC, - required this.enableIT, - required this.span, - }); - - factory SpanDetailsResponse.fromJson(Map json) => - SpanDetailsResponse( - userL1: json['user_l1'] as String, - userL2: json['user_l2'] as String, - enableIT: json['enable_it'] as bool, - enableIGC: json['enable_igc'] as bool, - span: SpanData.fromJson(json['span']), - ); -} diff --git a/lib/pangea/choreographer/it/contextual_definition_repo.dart b/lib/pangea/choreographer/it/contextual_definition_repo.dart deleted file mode 100644 index 3050d28b2..000000000 --- a/lib/pangea/choreographer/it/contextual_definition_repo.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'dart:convert'; - -import 'package:async/async.dart'; -import 'package:http/http.dart'; - -import 'package:fluffychat/pangea/choreographer/it/contextual_definition_request_model.dart'; -import 'package:fluffychat/pangea/choreographer/it/contextual_definition_response_model.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import '../../common/network/requests.dart'; -import '../../common/network/urls.dart'; - -class ContextualDefinitionRepo { - static final Map> _cache = {}; - - static Future> get( - String accessToken, - ContextualDefinitionRequestModel request, - ) async { - final cached = _getCached(request); - if (cached != null) { - try { - return Result.value(await cached); - } catch (e, s) { - _cache.remove(request.hashCode.toString()); - ErrorHandler.logError(e: e, s: s, data: request.toJson()); - return Result.error(e); - } - } - - final future = _fetch(accessToken, request); - _setCached(request, future); - return _getResult(request, future); - } - - static Future _fetch( - String accessToken, - ContextualDefinitionRequestModel request, - ) async { - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: accessToken, - ); - - final Response res = await req.post( - url: PApiUrls.contextualDefinition, - body: request.toJson(), - ); - - if (res.statusCode != 200) { - throw Exception( - "Contextual definition request failed with status code ${res.statusCode}", - ); - } - - final ContextualDefinitionResponseModel response = - ContextualDefinitionResponseModel.fromJson( - jsonDecode(utf8.decode(res.bodyBytes).toString()), - ); - - if (response.text.isEmpty) { - ErrorHandler.logError( - e: Exception("empty text in contextual definition response"), - data: {"request": request.toJson(), "accessToken": accessToken}, - ); - } - - return response.text; - } - - static Future> _getResult( - ContextualDefinitionRequestModel request, - Future future, - ) async { - try { - final res = await future; - return Result.value(res); - } catch (e, s) { - _cache.remove(request.hashCode.toString()); - ErrorHandler.logError(e: e, s: s, data: request.toJson()); - return Result.error(e); - } - } - - static Future? _getCached(ContextualDefinitionRequestModel request) => - _cache[request.hashCode.toString()]; - - static void _setCached( - ContextualDefinitionRequestModel request, - Future response, - ) => _cache[request.hashCode.toString()] = response; -} diff --git a/lib/pangea/choreographer/it/contextual_definition_request_model.dart b/lib/pangea/choreographer/it/contextual_definition_request_model.dart deleted file mode 100644 index a160d5ec3..000000000 --- a/lib/pangea/choreographer/it/contextual_definition_request_model.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:fluffychat/pangea/common/constants/model_keys.dart'; - -class ContextualDefinitionRequestModel { - final String fullText; - final String word; - final String feedbackLang; - final String fullTextLang; - final String wordLang; - - const ContextualDefinitionRequestModel({ - required this.fullText, - required this.word, - required this.feedbackLang, - required this.fullTextLang, - required this.wordLang, - }); - - Map toJson() => { - ModelKey.fullText: fullText, - ModelKey.word: word, - ModelKey.lang: feedbackLang, - ModelKey.fullTextLang: fullTextLang, - ModelKey.wordLang: wordLang, - }; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is ContextualDefinitionRequestModel && - runtimeType == other.runtimeType && - fullText == other.fullText && - word == other.word && - feedbackLang == other.feedbackLang && - fullTextLang == other.fullTextLang && - wordLang == other.wordLang; - - @override - int get hashCode => - fullText.hashCode ^ - word.hashCode ^ - feedbackLang.hashCode ^ - fullTextLang.hashCode ^ - wordLang.hashCode; -} diff --git a/lib/pangea/choreographer/it/contextual_definition_response_model.dart b/lib/pangea/choreographer/it/contextual_definition_response_model.dart deleted file mode 100644 index fb6e2a032..000000000 --- a/lib/pangea/choreographer/it/contextual_definition_response_model.dart +++ /dev/null @@ -1,9 +0,0 @@ -class ContextualDefinitionResponseModel { - final String text; - - const ContextualDefinitionResponseModel({required this.text}); - - factory ContextualDefinitionResponseModel.fromJson( - Map json, - ) => ContextualDefinitionResponseModel(text: json["response"]); -} diff --git a/lib/pangea/choreographer/it/gold_route_tracker_model.dart b/lib/pangea/choreographer/it/gold_route_tracker_model.dart deleted file mode 100644 index 47a7a9be4..000000000 --- a/lib/pangea/choreographer/it/gold_route_tracker_model.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:fluffychat/pangea/choreographer/it/completed_it_step_model.dart'; - -class GoldRouteTrackerModel { - final String _originalText; - final List continuances; - - const GoldRouteTrackerModel(this.continuances, String originalText) - : _originalText = originalText; - - ContinuanceModel? currentContinuance({ - required String currentText, - required String sourceText, - }) { - if (_originalText != sourceText) { - return null; - } - - String stack = ""; - for (final cont in continuances) { - if (stack == currentText) { - return cont; - } - stack += cont.text; - } - - return null; - } - - String? get fullTranslation { - if (continuances.isEmpty) return null; - String full = ""; - for (final cont in continuances) { - full += cont.text; - } - return full; - } -} diff --git a/lib/pangea/choreographer/it/it_bar.dart b/lib/pangea/choreographer/it/it_bar.dart deleted file mode 100644 index d9d1915bf..000000000 --- a/lib/pangea/choreographer/it/it_bar.dart +++ /dev/null @@ -1,410 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; - -import 'package:sentry_flutter/sentry_flutter.dart'; - -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics_summary/animated_progress_bar.dart'; -import 'package:fluffychat/pangea/choreographer/choreo_constants.dart'; -import 'package:fluffychat/pangea/choreographer/choreographer.dart'; -import 'package:fluffychat/pangea/choreographer/it/completed_it_step_model.dart'; -import 'package:fluffychat/pangea/choreographer/it/it_feedback_card.dart'; -import 'package:fluffychat/pangea/choreographer/it/word_data_card.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; -import 'package:fluffychat/pangea/learning_settings/settings_learning.dart'; -import 'package:fluffychat/pangea/translation/full_text_translation_request_model.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../../common/utils/overlay.dart'; -import '../../common/widgets/choice_array.dart'; - -class ITBar extends StatefulWidget { - final Choreographer choreographer; - const ITBar({super.key, required this.choreographer}); - - @override - ITBarState createState() => ITBarState(); -} - -class ITBarState extends State with SingleTickerProviderStateMixin { - late AnimationController _controller; - late Animation _animation; - final TextEditingController _sourceTextController = TextEditingController(); - - Timer? _successTimer; - bool _visible = false; - - @override - void initState() { - super.initState(); - - _controller = AnimationController( - duration: const Duration(milliseconds: 300), - vsync: this, - ); - _animation = CurvedAnimation(parent: _controller, curve: Curves.easeInOut); - _openListener(); - _open.addListener(_openListener); - } - - @override - void dispose() { - _controller.dispose(); - _sourceTextController.dispose(); - _successTimer?.cancel(); - _open.removeListener(_openListener); - super.dispose(); - } - - FullTextTranslationRequestModel _translationRequest(String text) => - FullTextTranslationRequestModel( - text: text, - tgtLang: MatrixState.pangeaController.userController.userL1!.langCode, - userL1: MatrixState.pangeaController.userController.userL1!.langCode, - userL2: MatrixState.pangeaController.userController.userL2!.langCode, - ); - - void _openListener() { - if (!mounted) return; - - final nextText = _sourceText.value ?? widget.choreographer.currentText; - if (_sourceTextController.text != nextText) { - _sourceTextController.text = nextText; - } - - if (_open.value) { - setState(() => _visible = true); - _controller.forward(); - } else { - _controller.reverse().then((value) { - if (!mounted) return; - setState(() => _visible = false); - }); - } - } - - ValueNotifier get _sourceText => - widget.choreographer.itController.sourceText; - ValueNotifier get _open => widget.choreographer.itController.open; - - void _showFeedbackCard( - ContinuanceModel continuance, [ - Color? borderColor, - bool selected = false, - ]) { - final text = continuance.text; - MatrixState.pAnyState.closeOverlay("it_feedback_card"); - OverlayUtil.showPositionedCard( - context: context, - cardToShow: selected - ? WordDataCard( - word: text, - langCode: - MatrixState.pangeaController.userController.userL2!.langCode, - fullText: _sourceText.value ?? widget.choreographer.currentText, - ) - : ITFeedbackCard(_translationRequest(text)), - maxHeight: 300, - maxWidth: 300, - borderColor: borderColor, - transformTargetId: 'it_bar', - isScrollable: false, - overlayKey: "it_feedback_card", - ignorePointer: true, - ); - } - - void _selectContinuance(int index) { - MatrixState.pAnyState.closeOverlay("it_feedback_card"); - ContinuanceModel continuance; - try { - continuance = widget.choreographer.itController.selectContinuance(index); - } catch (e, s) { - ErrorHandler.logError( - e: e, - s: s, - level: SentryLevel.warning, - data: {"index": index}, - ); - widget.choreographer.itController.closeIT(); - return; - } - - if (continuance.level == 1) { - _onCorrectSelection(index); - } else { - _showFeedbackCard( - continuance, - continuance.level == 2 ? ChoreoConstants.yellow : ChoreoConstants.red, - true, - ); - } - } - - void _onCorrectSelection(int index) { - _successTimer?.cancel(); - _successTimer = Timer(const Duration(milliseconds: 500), () { - if (!mounted) return; - try { - widget.choreographer.itController.acceptContinuance(index); - } catch (e, s) { - ErrorHandler.logError( - e: e, - s: s, - level: SentryLevel.warning, - data: {"index": index}, - ); - widget.choreographer.itController.closeIT(); - } - }); - } - - @override - Widget build(BuildContext context) { - if (!_visible) { - return const SizedBox.shrink(); - } - - return AnimatedBuilder( - animation: _animation, - builder: (context, child) => SizeTransition( - sizeFactor: _animation, - axisAlignment: -1.0, - child: child, - ), - child: CompositedTransformTarget( - link: MatrixState.pAnyState.layerLinkAndKey('it_bar').link, - child: Container( - key: MatrixState.pAnyState.layerLinkAndKey('it_bar').key, - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(24), - topRight: Radius.circular(24), - ), - color: Theme.of(context).colorScheme.surfaceContainer, - ), - padding: const EdgeInsets.all(12.0), - child: Column( - spacing: 12.0, - children: [ - _ITBarHeader( - onClose: () => - widget.choreographer.itController.closeIT(dismiss: true), - setEditing: - widget.choreographer.itController.setEditingSourceText, - editing: widget.choreographer.itController.editing, - progress: widget.choreographer.itController.progress, - sourceTextController: _sourceTextController, - sourceText: _sourceText, - onSubmitEdits: (_) { - widget.choreographer.itController.submitSourceTextEdits( - _sourceTextController.text, - ); - }, - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - constraints: const BoxConstraints(minHeight: 80), - child: Center( - child: widget.choreographer.errorService.isError - ? Row( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - ErrorIndicator( - message: L10n.of(context).translationError, - style: TextStyle( - fontStyle: FontStyle.italic, - color: Theme.of(context).colorScheme.error, - ), - ), - IconButton( - onPressed: - widget.choreographer.itController.closeIT, - icon: const Icon(Icons.close, size: 20), - ), - ], - ) - : ValueListenableBuilder( - valueListenable: - widget.choreographer.itController.currentITStep, - builder: (context, step, _) { - return step == null - ? CircularProgressIndicator( - strokeWidth: 2.0, - color: Theme.of( - context, - ).colorScheme.primary, - ) - : _ITChoices( - continuances: step.continuances, - onPressed: _selectContinuance, - onLongPressed: _showFeedbackCard, - ); - }, - ), - ), - ), - ], - ), - ), - ), - ); - } -} - -class _ITBarHeader extends StatelessWidget { - final VoidCallback onClose; - final Function(String) onSubmitEdits; - final Function(bool) setEditing; - - final ValueNotifier editing; - final ValueNotifier progress; - final TextEditingController sourceTextController; - final ValueNotifier sourceText; - - const _ITBarHeader({ - required this.onClose, - required this.setEditing, - required this.editing, - required this.progress, - required this.onSubmitEdits, - required this.sourceTextController, - required this.sourceText, - }); - - @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: editing, - builder: (context, isEditing, _) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - AnimatedCrossFade( - duration: const Duration(milliseconds: 200), - crossFadeState: isEditing - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - firstChild: Row( - spacing: 12.0, - children: [ - Expanded( - child: TextField( - controller: sourceTextController, - autofocus: true, - enableSuggestions: false, - maxLines: null, - textInputAction: TextInputAction.send, - onSubmitted: onSubmitEdits, - decoration: const InputDecoration( - border: OutlineInputBorder(), - ), - ), - ), - IconButton( - color: Theme.of(context).colorScheme.primary, - icon: const Icon(Icons.close_outlined), - onPressed: () => setEditing(false), - ), - ], - ), - secondChild: Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: ValueListenableBuilder( - valueListenable: progress, - builder: (context, value, _) => AnimatedProgressBar( - height: 20.0, - widthPercent: value, - backgroundColor: Theme.of( - context, - ).colorScheme.surfaceContainerHighest, - barColor: Theme.of( - context, - ).colorScheme.primary.withAlpha(180), - ), - ), - ), - ), - IconButton( - color: Theme.of(context).colorScheme.primary, - onPressed: () => setEditing(true), - icon: const Icon(Icons.edit_outlined), - ), - IconButton( - color: Theme.of(context).colorScheme.primary, - icon: const Icon(Icons.settings_outlined), - onPressed: () => showDialog( - context: context, - builder: (c) => const SettingsLearning(), - barrierDismissible: false, - ), - ), - IconButton( - color: Theme.of(context).colorScheme.primary, - icon: const Icon(Icons.close_outlined), - onPressed: onClose, - ), - ], - ), - ), - isEditing - ? const SizedBox(height: 24.0) - : ValueListenableBuilder( - valueListenable: sourceText, - builder: (context, text, _) { - return Container( - padding: const EdgeInsets.only(top: 8.0), - constraints: const BoxConstraints(minHeight: 24.0), - child: sourceText.value != null - ? Text( - sourceText.value!, - textAlign: TextAlign.center, - ) - : const SizedBox(), - ); - }, - ), - ], - ); - }, - ); - } -} - -class _ITChoices extends StatelessWidget { - final List continuances; - final Function(int) onPressed; - final Function(ContinuanceModel) onLongPressed; - - const _ITChoices({ - required this.continuances, - required this.onPressed, - required this.onLongPressed, - }); - - @override - Widget build(BuildContext context) { - return ChoicesArray( - id: Object.hashAll(continuances).toString(), - isLoading: false, - choices: [ - ...continuances.map( - (e) => Choice( - text: e.text.trim(), - color: e.color, - isGold: e.description == "best", - ), - ), - ], - onPressed: (value, index) => onPressed(index), - onLongPress: (value, index) => onLongPressed(continuances[index]), - selectedChoiceIndex: null, - langCode: MatrixState.pangeaController.userController.userL2Code!, - ); - } -} diff --git a/lib/pangea/choreographer/it/it_controller.dart b/lib/pangea/choreographer/it/it_controller.dart deleted file mode 100644 index d8f51dc50..000000000 --- a/lib/pangea/choreographer/it/it_controller.dart +++ /dev/null @@ -1,239 +0,0 @@ -import 'dart:async'; -import 'dart:collection'; - -import 'package:flutter/foundation.dart'; - -import 'package:async/async.dart'; - -import 'package:fluffychat/pangea/choreographer/it/gold_route_tracker_model.dart'; -import 'package:fluffychat/pangea/choreographer/it/it_repo.dart'; -import 'package:fluffychat/pangea/choreographer/it/it_response_model.dart'; -import 'package:fluffychat/pangea/choreographer/it/it_step_model.dart'; -import 'package:fluffychat/widgets/future_loading_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import 'completed_it_step_model.dart'; -import 'it_request_model.dart'; - -class ITController { - final Function(Object) onError; - - final Queue> _queue = Queue(); - GoldRouteTrackerModel? _goldRouteTracker; - - final ValueNotifier _sourceText = ValueNotifier(null); - final ValueNotifier _currentITStep = ValueNotifier(null); - final ValueNotifier _open = ValueNotifier(false); - final ValueNotifier _editing = ValueNotifier(false); - final ValueNotifier _progress = ValueNotifier(0.0); - - ITController(this.onError); - - ValueNotifier get open => _open; - ValueNotifier get editing => _editing; - ValueNotifier get progress => _progress; - - ValueNotifier get currentITStep => _currentITStep; - ValueNotifier get sourceText => _sourceText; - StreamController acceptedContinuanceStream = - StreamController.broadcast(); - - bool _continuing = false; - bool dismissed = false; - - ITRequestModel _request(String textInput) { - assert(_sourceText.value != null); - return ITRequestModel( - text: _sourceText.value!, - customInput: textInput, - sourceLangCode: MatrixState.pangeaController.userController.userL1Code!, - targetLangCode: MatrixState.pangeaController.userController.userL2Code!, - goldTranslation: _goldRouteTracker?.fullTranslation, - goldContinuances: _goldRouteTracker?.continuances, - ); - } - - Future> _safeRequest(String text) { - return ITRepo.get(_request(text)).timeout( - const Duration(seconds: 10), - onTimeout: () => Result.error( - TimeoutException("ITRepo.get timed out after 10 seconds"), - ), - ); - } - - void clearSourceText() { - _sourceText.value = null; - } - - void clearSession() { - dismissed = false; - _progress.value = 0.0; - } - - void dispose() { - acceptedContinuanceStream.close(); - _open.dispose(); - _editing.dispose(); - _currentITStep.dispose(); - _sourceText.dispose(); - } - - void openIT(String text) { - _sourceText.value = text; - _open.value = true; - _continueIT(); - } - - void closeIT({bool dismiss = false}) { - MatrixState.pAnyState.closeOverlay("it_feedback_card"); - - setEditingSourceText(false); - if (dismiss) { - dismissed = true; - } - - _open.value = false; - _queue.clear(); - _currentITStep.value = null; - _goldRouteTracker = null; - } - - void setEditingSourceText(bool value) { - _editing.value = value; - } - - void submitSourceTextEdits(String text) { - _queue.clear(); - _currentITStep.value = null; - _goldRouteTracker = null; - _progress.value = 0.0; - _sourceText.value = text; - setEditingSourceText(false); - _continueIT(); - } - - ContinuanceModel selectContinuance(int index) { - if (_currentITStep.value == null) { - throw "onSelectContinuance called when _currentITStep is null"; - } - - if (index < 0 || index >= _currentITStep.value!.continuances.length) { - throw "onSelectContinuance called with invalid index $index"; - } - - final currentStep = _currentITStep.value!; - currentStep.continuances[index] = currentStep.continuances[index].copyWith( - wasClicked: true, - ); - _currentITStep.value = _currentITStep.value!.copyWith( - continuances: currentStep.continuances, - ); - return _currentITStep.value!.continuances[index]; - } - - void acceptContinuance(int chosenIndex) { - if (_currentITStep.value == null) { - throw "onAcceptContinuance called when _currentITStep is null"; - } - - if (chosenIndex < 0 || - chosenIndex >= _currentITStep.value!.continuances.length) { - throw "onAcceptContinuance called with invalid index $chosenIndex"; - } - - acceptedContinuanceStream.add( - CompletedITStepModel( - _currentITStep.value!.continuances, - chosen: chosenIndex, - ), - ); - final progress = - (_goldRouteTracker!.continuances.indexWhere( - (c) => - c.text == - _currentITStep.value!.continuances[chosenIndex].text, - ) + - 1) / - _goldRouteTracker!.continuances.length; - _progress.value = progress; - _continueIT(); - } - - Future _continueIT() async { - if (_continuing) return; - _continuing = true; - - try { - if (_currentITStep.value == null) { - await _initTranslationData(); - } else if (_queue.isEmpty) { - closeIT(); - } else { - final nextStepCompleter = _queue.removeFirst(); - _currentITStep.value = await nextStepCompleter.future; - } - } catch (e) { - onError(e); - } finally { - _continuing = false; - } - } - - Future _initTranslationData() async { - final res = await _safeRequest(""); - if (_sourceText.value == null || !_open.value) return; - if (res.isError || res.result?.goldContinuances == null) { - onError(res.asError!); - return; - } - - final result = res.result!; - _goldRouteTracker = GoldRouteTrackerModel( - result.goldContinuances!, - _sourceText.value!, - ); - - _currentITStep.value = ITStepModel.fromResponse( - sourceText: _sourceText.value!, - currentText: "", - responseModel: res.result!, - storedGoldContinuances: _goldRouteTracker!.continuances, - ); - - _fillITStepQueue(); - } - - Future _fillITStepQueue() async { - if (_sourceText.value == null || - _goldRouteTracker!.continuances.length < 2) { - return; - } - - final sourceText = _sourceText.value!; - final goldContinuances = _goldRouteTracker!.continuances; - String currentText = goldContinuances[0].text; - for (int i = 1; i < goldContinuances.length; i++) { - if (_sourceText.value == null || !_open.value) { - return; - } - - final completer = Completer(); - _queue.add(completer); - final resp = await _safeRequest(currentText); - if (resp.isError) { - completer.completeError(resp.asError!); - break; - } else { - final step = ITStepModel.fromResponse( - sourceText: sourceText, - currentText: currentText, - responseModel: resp.result!, - storedGoldContinuances: goldContinuances, - ); - completer.complete(step); - } - - currentText += goldContinuances[i].text; - } - } -} diff --git a/lib/pangea/choreographer/it/it_feedback_card.dart b/lib/pangea/choreographer/it/it_feedback_card.dart deleted file mode 100644 index 75df42b79..000000000 --- a/lib/pangea/choreographer/it/it_feedback_card.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; - -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/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'; -import '../../../widgets/matrix.dart'; -import '../../bot/utils/bot_style.dart'; -import '../../common/widgets/card_error_widget.dart'; - -class ITFeedbackCard extends StatelessWidget { - final FullTextTranslationRequestModel req; - - const ITFeedbackCard(this.req, {super.key}); - - Future> _getFeedback() { - return FullTextTranslationRepo.get( - MatrixState.pangeaController.userController.accessToken, - req, - ).timeout( - const Duration(seconds: 10), - onTimeout: () => Result.error("Timeout getting translation"), - ); - } - - @override - Widget build(BuildContext context) { - return FutureBuilder>( - future: _getFeedback(), - builder: (context, snapshot) { - if (snapshot.hasError) { - return CardErrorWidget(L10n.of(context).errorFetchingDefinition); - } - - return Container( - constraints: const BoxConstraints(maxWidth: 300), - alignment: Alignment.center, - child: Wrap( - spacing: 10, - alignment: WrapAlignment.center, - children: [ - Text(req.text, style: BotStyle.text(context)), - Text("≈", style: BotStyle.text(context)), - snapshot.hasData - ? Text(snapshot.data!.result!, style: BotStyle.text(context)) - : TextLoadingShimmer(width: min(140, 10.0 * req.text.length)), - ], - ), - ); - }, - ); - } -} diff --git a/lib/pangea/choreographer/it/it_repo.dart b/lib/pangea/choreographer/it/it_repo.dart deleted file mode 100644 index 04ccb5c77..000000000 --- a/lib/pangea/choreographer/it/it_repo.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'dart:convert'; - -import 'package:async/async.dart'; -import 'package:http/http.dart'; - -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../../common/network/requests.dart'; -import '../../common/network/urls.dart'; -import 'it_request_model.dart'; -import 'it_response_model.dart'; - -class _ITCacheItem { - final Future response; - final DateTime timestamp; - - const _ITCacheItem({required this.response, required this.timestamp}); -} - -class ITRepo { - static final Map _cache = {}; - static const Duration _cacheDuration = Duration(minutes: 10); - - static Future> get(ITRequestModel request) { - final cached = _getCached(request); - if (cached != null) { - return _getResult(request, cached); - } - - final future = _fetch(request); - _setCached(request, future); - return _getResult(request, future); - } - - static Future _fetch(ITRequestModel request) async { - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); - final Response res = await req.post( - url: PApiUrls.firstStep, - body: request.toJson(), - ); - - if (res.statusCode != 200) { - throw Exception('Failed to load interactive translation'); - } - - final json = jsonDecode(utf8.decode(res.bodyBytes).toString()); - return ITResponseModel.fromJson(json); - } - - static Future> _getResult( - ITRequestModel request, - Future future, - ) async { - try { - final res = await future; - return Result.value(res); - } catch (e, s) { - _cache.remove(request.hashCode.toString()); - ErrorHandler.logError(e: e, s: s, data: request.toJson()); - return Result.error(e); - } - } - - static Future? _getCached(ITRequestModel request) { - final cacheKeys = [..._cache.keys]; - for (final key in cacheKeys) { - if (DateTime.now().difference(_cache[key]!.timestamp) >= _cacheDuration) { - _cache.remove(key); - } - } - return _cache[request.hashCode.toString()]?.response; - } - - static void _setCached( - ITRequestModel request, - Future response, - ) { - _cache[request.hashCode.toString()] = _ITCacheItem( - response: response, - timestamp: DateTime.now(), - ); - } -} diff --git a/lib/pangea/choreographer/it/it_request_model.dart b/lib/pangea/choreographer/it/it_request_model.dart deleted file mode 100644 index 5e70a65b4..000000000 --- a/lib/pangea/choreographer/it/it_request_model.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:flutter/foundation.dart'; - -import 'package:fluffychat/pangea/choreographer/it/completed_it_step_model.dart'; -import 'package:fluffychat/pangea/common/constants/model_keys.dart'; - -class ITRequestModel { - final String text; - final String customInput; - final String sourceLangCode; - final String targetLangCode; - - final String? goldTranslation; - final List? goldContinuances; - - const ITRequestModel({ - required this.text, - required this.customInput, - required this.sourceLangCode, - required this.targetLangCode, - required this.goldTranslation, - required this.goldContinuances, - }); - - factory ITRequestModel.fromJson(Map json) => ITRequestModel( - text: json[ModelKey.text], - customInput: json['custom_input'], - sourceLangCode: json[ModelKey.srcLang], - targetLangCode: json[ModelKey.tgtLang], - goldTranslation: json[ModelKey.goldTranslation], - goldContinuances: json['gold_continuances'] != null - ? (json['gold_continuances']) - .map((e) => ContinuanceModel.fromJson(e)) - .toList() - : null, - ); - - Map toJson() => { - ModelKey.text: text, - 'custom_input': customInput, - ModelKey.srcLang: sourceLangCode, - ModelKey.tgtLang: targetLangCode, - ModelKey.goldTranslation: goldTranslation, - 'gold_continuances': goldContinuances != null - ? List.from(goldContinuances!.map((e) => e.toJson())) - : null, - }; - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - - return other is ITRequestModel && - other.text == text && - other.customInput == customInput && - other.sourceLangCode == sourceLangCode && - other.targetLangCode == targetLangCode && - other.goldTranslation == goldTranslation && - listEquals(other.goldContinuances, goldContinuances); - } - - @override - int get hashCode => - text.hashCode ^ - customInput.hashCode ^ - sourceLangCode.hashCode ^ - targetLangCode.hashCode ^ - goldTranslation.hashCode ^ - Object.hashAll(goldContinuances ?? []); -} diff --git a/lib/pangea/choreographer/it/it_response_model.dart b/lib/pangea/choreographer/it/it_response_model.dart deleted file mode 100644 index 3c68802a8..000000000 --- a/lib/pangea/choreographer/it/it_response_model.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:collection/collection.dart'; - -import 'package:fluffychat/pangea/choreographer/choreo_constants.dart'; -import 'package:fluffychat/pangea/choreographer/it/completed_it_step_model.dart'; - -class ITResponseModel { - final String fullTextTranslation; - final List continuances; - final List? goldContinuances; - final bool isFinal; - final String? translationId; - final int payloadId; - - const ITResponseModel({ - required this.fullTextTranslation, - required this.continuances, - required this.translationId, - required this.goldContinuances, - required this.isFinal, - required this.payloadId, - }); - - factory ITResponseModel.fromJson(Map json) { - //PTODO - is continuances a variable type? can we change that? - if (json['continuances'].runtimeType == String) { - debugPrint("continuances was string - ${json['continuances']}"); - json['continuances'] = []; - json['finished'] = true; - } - - final List interimCont = (json['continuances'] as List) - .mapIndexed((index, e) { - e["index"] = index; - return ContinuanceModel.fromJson(e); - }) - .toList() - .take(ChoreoConstants.numberOfITChoices) - .toList() - .cast() - //can't do this on the backend because step translation can't filter them out - .where((element) => element.inDictionary) - .toList(); - - interimCont.shuffle(); - - return ITResponseModel( - fullTextTranslation: json["full_text_translation"] ?? json["translation"], - continuances: interimCont, - translationId: json['translation_id'], - payloadId: json['payload_id'] ?? 0, - isFinal: json['finished'] ?? false, - goldContinuances: json['gold_continuances'] != null - ? (json['gold_continuances'] as Iterable).map((e) { - e["gold"] = true; - return ContinuanceModel.fromJson(e); - }).toList() - : null, - ); - } - - Map toJson() { - final Map data = {}; - data['full_text_translation'] = fullTextTranslation; - data['continuances'] = continuances.map((v) => v.toJson()).toList(); - if (translationId != null) { - data['translation_id'] = translationId; - } - data['payload_id'] = payloadId; - data["finished"] = isFinal; - return data; - } -} diff --git a/lib/pangea/choreographer/it/it_shimmer.dart b/lib/pangea/choreographer/it/it_shimmer.dart deleted file mode 100644 index 06912b0ed..000000000 --- a/lib/pangea/choreographer/it/it_shimmer.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/material.dart'; - -class ItShimmer extends StatelessWidget { - const ItShimmer({super.key}); - - @override - Widget build(BuildContext context) { - final color = Theme.of(context).colorScheme.primary.withAlpha(50); - - return Wrap( - alignment: WrapAlignment.center, - spacing: 4, - runSpacing: 4, - children: List.generate(3, (_) { - return ImageFiltered( - imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), - child: TextButton( - style: TextButton.styleFrom( - minimumSize: const Size(50, 36), - backgroundColor: color, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - padding: const EdgeInsets.symmetric(horizontal: 7), - ), - onPressed: null, - child: const Text( - " ", // 10 spaces - style: TextStyle(color: Colors.transparent, fontSize: 16), - ), - ), - ); - }), - ); - } -} diff --git a/lib/pangea/choreographer/it/it_step_model.dart b/lib/pangea/choreographer/it/it_step_model.dart deleted file mode 100644 index 34f98b42c..000000000 --- a/lib/pangea/choreographer/it/it_step_model.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:fluffychat/pangea/choreographer/choreo_constants.dart'; -import 'package:fluffychat/pangea/choreographer/it/completed_it_step_model.dart'; -import 'package:fluffychat/pangea/choreographer/it/gold_route_tracker_model.dart'; -import 'package:fluffychat/pangea/choreographer/it/it_response_model.dart'; - -class ITStepModel { - late List continuances; - late bool isFinal; - - ITStepModel({this.continuances = const [], this.isFinal = false}); - - factory ITStepModel.fromResponse({ - required String sourceText, - required String currentText, - required ITResponseModel responseModel, - required List? storedGoldContinuances, - }) { - final List gold = - storedGoldContinuances ?? responseModel.goldContinuances ?? []; - final goldTracker = GoldRouteTrackerModel(gold, sourceText); - - final isFinal = responseModel.isFinal; - List continuances; - if (responseModel.continuances.isEmpty) { - continuances = []; - } else { - final ContinuanceModel? goldCont = goldTracker.currentContinuance( - currentText: currentText, - sourceText: sourceText, - ); - if (goldCont != null) { - continuances = [ - ...responseModel.continuances - .where((c) => c.text.toLowerCase() != goldCont.text.toLowerCase()) - .map((e) { - //we only want one green choice and for that to be our gold - if (e.level == ChoreoConstants.levelThresholdForGreen) { - return e.copyWith( - level: ChoreoConstants.levelThresholdForYellow, - ); - } - return e; - }), - goldCont, - ]; - continuances.shuffle(); - } else { - continuances = List.from(responseModel.continuances); - } - } - - return ITStepModel(continuances: continuances, isFinal: isFinal); - } - - ITStepModel copyWith({List? continuances, bool? isFinal}) { - return ITStepModel( - continuances: continuances ?? this.continuances, - isFinal: isFinal ?? this.isFinal, - ); - } -} diff --git a/lib/pangea/choreographer/it/word_data_card.dart b/lib/pangea/choreographer/it/word_data_card.dart deleted file mode 100644 index a4359c657..000000000 --- a/lib/pangea/choreographer/it/word_data_card.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:async/async.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/widgets/content_loading_indicator.dart'; -import 'package:fluffychat/pangea/languages/language_constants.dart'; -import 'package:fluffychat/widgets/future_loading_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; - -class WordDataCard extends StatelessWidget { - final String word; - final String fullText; - final String langCode; - - const WordDataCard({ - super.key, - required this.word, - required this.fullText, - required this.langCode, - }); - - ContextualDefinitionRequestModel get _request => - ContextualDefinitionRequestModel( - fullText: fullText, - word: word, - fullTextLang: langCode, - wordLang: langCode, - feedbackLang: - MatrixState.pangeaController.userController.userL1Code ?? - LanguageKeys.defaultLanguage, - ); - - Future> _fetchDefinition() { - return ContextualDefinitionRepo.get( - MatrixState.pangeaController.userController.accessToken, - _request, - ).timeout( - const Duration(seconds: 10), - onTimeout: () => Result.error("Timeout getting definition"), - ); - } - - @override - Widget build(BuildContext context) { - return Center( - child: FutureBuilder>( - future: _fetchDefinition(), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const ContentLoadingIndicator(); - } - 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/network/urls.dart b/lib/pangea/common/network/urls.dart index 21ab7cd65..d691accea 100644 --- a/lib/pangea/common/network/urls.dart +++ b/lib/pangea/common/network/urls.dart @@ -31,20 +31,13 @@ class PApiUrls { "${PApiUrls._choreoEndpoint}/language_detection"; static String igcLite = "${PApiUrls._choreoEndpoint}/grammar_v2"; - static String spanDetails = "${PApiUrls._choreoEndpoint}/span_details"; static String simpleTranslation = "${PApiUrls._choreoEndpoint}/translation/direct"; static String tokenize = "${PApiUrls._choreoEndpoint}/tokenize"; - static String contextualDefinition = - "${PApiUrls._choreoEndpoint}/contextual_definition"; - - static String firstStep = "${PApiUrls._choreoEndpoint}/it_initialstep"; static String textToSpeech = "${PApiUrls._choreoEndpoint}/text_to_speech"; static String speechToText = "${PApiUrls._choreoEndpoint}/speech_to_text"; - static String phoneticTranscription = - "${PApiUrls._choreoEndpoint}/phonetic_transcription"; static String phoneticTranscriptionV2 = "${PApiUrls._choreoEndpoint}/phonetic_transcription_v2"; @@ -55,15 +48,6 @@ class PApiUrls { "${PApiUrls._choreoEndpoint}/lemma_definition"; static String morphDictionary = "${PApiUrls._choreoEndpoint}/morph_meaning"; - // static String activityPlan = "${PApiUrls._choreoEndpoint}/activity_plan"; - // static String activityPlanGeneration = - // "${PApiUrls._choreoEndpoint}/activity_plan/generate"; - // static String activityPlanSearch = - // "${PApiUrls._choreoEndpoint}/activity_plan/search"; - // static String activityModeList = "${PApiUrls._choreoEndpoint}/modes"; - // static String objectiveList = "${PApiUrls._choreoEndpoint}/objectives"; - // static String topicList = "${PApiUrls._choreoEndpoint}/topics"; - static String activitySummary = "${PApiUrls._choreoEndpoint}/activity_summary"; diff --git a/lib/pangea/common/widgets/choice_array.dart b/lib/pangea/common/widgets/choice_array.dart index 660b87e5a..36f767988 100644 --- a/lib/pangea/common/widgets/choice_array.dart +++ b/lib/pangea/common/widgets/choice_array.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; @@ -8,7 +10,6 @@ import 'package:fluffychat/pangea/common/widgets/choice_animation.dart'; import 'package:fluffychat/pangea/text_to_speech/tts_controller.dart'; import 'package:fluffychat/widgets/matrix.dart'; import '../../bot/utils/bot_style.dart'; -import '../../choreographer/it/it_shimmer.dart'; typedef ChoiceCallback = void Function(String value, int index); @@ -46,7 +47,33 @@ class ChoicesArray extends StatelessWidget { @override Widget build(BuildContext context) { return isLoading && (choices == null || choices!.length <= 1) - ? const ItShimmer() + ? Wrap( + alignment: WrapAlignment.center, + spacing: 4, + runSpacing: 4, + children: List.generate(3, (_) { + return ImageFiltered( + imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), + child: TextButton( + style: TextButton.styleFrom( + minimumSize: const Size(50, 36), + backgroundColor: Theme.of( + context, + ).colorScheme.primary.withAlpha(50), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.symmetric(horizontal: 7), + ), + onPressed: null, + child: const Text( + " ", // 10 spaces + style: TextStyle(color: Colors.transparent, fontSize: 16), + ), + ), + ); + }), + ) : Wrap( alignment: WrapAlignment.center, spacing: 4.0,