From 78cb3afe0b04ac75c19fbc7d91e3f4e6598aacd8 Mon Sep 17 00:00:00 2001 From: wcjord <32568597+wcjord@users.noreply.github.com> Date: Fri, 29 Nov 2024 17:47:00 -0500 Subject: [PATCH] word focus turned off and tts on Choice click (#1118) * word focus turned off and tts on Choice click * play audio on word selection --- lib/pages/chat/chat.dart | 1 + .../controllers/choreographer.dart | 6 + .../choreographer/widgets/choice_array.dart | 12 +- lib/pangea/choreographer/widgets/it_bar.dart | 1 + .../widgets/translation_finished_flow.dart | 3 +- lib/pangea/enum/activity_type_enum.dart | 10 ++ lib/pangea/models/pangea_token_model.dart | 1 + .../practice_activity_model.dart | 14 ++ .../widgets/chat/message_audio_card.dart | 10 +- .../chat/message_selection_overlay.dart | 15 +- lib/pangea/widgets/chat/message_toolbar.dart | 6 +- lib/pangea/widgets/chat/tts_controller.dart | 7 +- lib/pangea/widgets/igc/span_card.dart | 1 + .../multiple_choice_activity.dart | 57 ++++++- .../practice_activity_card.dart | 144 ++++++++++-------- 15 files changed, 196 insertions(+), 92 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 1f3521273..800957d52 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -140,6 +140,7 @@ class ChatController extends State Timer? typingTimeout; bool currentlyTyping = false; // #Pangea + // bool dragging = false; // void onDragEntered(_) => setState(() => dragging = true); diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 33a5a6974..395628bbb 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -17,6 +17,7 @@ import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/any_state_holder.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/overlay.dart'; +import 'package:fluffychat/pangea/widgets/chat/tts_controller.dart'; import 'package:fluffychat/pangea/widgets/igc/paywall_card.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -40,6 +41,7 @@ class Choreographer { late IgcController igc; late AlternativeTranslator altTranslator; late ErrorService errorService; + final tts = TtsController(); bool isFetching = false; int _timesClicked = 0; @@ -66,6 +68,8 @@ class Choreographer { .subscriptionController.trialActivationStream.stream .listen((_) => _onChangeListener); + tts.setupTTS(); + clear(); } @@ -454,6 +458,7 @@ class Choreographer { choreoRecord = ChoreoRecord.newRecord; itController.clear(); igc.clear(); + //@ggurdin - why is this commented out? // errorService.clear(); _resetDebounceTimer(); } @@ -477,6 +482,7 @@ class Choreographer { dispose() { _textController.dispose(); trialStream?.cancel(); + tts.dispose(); } LanguageModel? get l2Lang { diff --git a/lib/pangea/choreographer/widgets/choice_array.dart b/lib/pangea/choreographer/widgets/choice_array.dart index 9aa74afac..ffae01e85 100644 --- a/lib/pangea/choreographer/widgets/choice_array.dart +++ b/lib/pangea/choreographer/widgets/choice_array.dart @@ -2,6 +2,7 @@ import 'dart:developer'; import 'dart:math'; import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/widgets/chat/tts_controller.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -20,6 +21,10 @@ class ChoicesArray extends StatefulWidget { final String originalSpan; final String Function(int) uniqueKeyForLayerLink; + /// If null then should not be used + /// We don't want tts in the case of L1 options + final TtsController? tts; + /// Used to unqiuely identify the keys for choices, in cases where multiple /// choices could have identical text, like in back-to-back practice activities final String? id; @@ -35,6 +40,7 @@ class ChoicesArray extends StatefulWidget { required this.originalSpan, required this.uniqueKeyForLayerLink, required this.selectedChoiceIndex, + required this.tts, this.isActive = true, this.onLongPress, this.id, @@ -73,7 +79,11 @@ class ChoicesArrayState extends State { theme: theme, onLongPress: widget.isActive ? widget.onLongPress : null, onPressed: widget.isActive - ? widget.onPressed + ? (String value, int index) { + widget.onPressed(value, index); + // TODO - what to pass here as eventID? + widget.tts?.tryToSpeak(value, context, null); + } : (String value, int index) { debugger(when: kDebugMode); }, diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index 30cc7c007..13bdb6c2b 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -418,6 +418,7 @@ class ITChoices extends StatelessWidget { onLongPress: (value, index) => showCard(context, index), uniqueKeyForLayerLink: (int index) => "itChoices$index", selectedChoiceIndex: null, + tts: controller.choreographer.tts, ); } catch (e) { debugger(when: kDebugMode); diff --git a/lib/pangea/choreographer/widgets/translation_finished_flow.dart b/lib/pangea/choreographer/widgets/translation_finished_flow.dart index fe6630af5..f3a26b0c7 100644 --- a/lib/pangea/choreographer/widgets/translation_finished_flow.dart +++ b/lib/pangea/choreographer/widgets/translation_finished_flow.dart @@ -67,7 +67,7 @@ class AlternativeTranslations extends StatelessWidget { @override Widget build(BuildContext context) { return ChoicesArray( - originalSpan: controller.choreographer.itController.sourceText ?? "dummy", + originalSpan: controller.sourceText ?? "dummy", isLoading: controller.choreographer.altTranslator.loadingAlternativeTranslations, // choices: controller.choreographer.altTranslator.similarityResponse.scores @@ -82,6 +82,7 @@ class AlternativeTranslations extends StatelessWidget { }, uniqueKeyForLayerLink: (int index) => "altTranslation$index", selectedChoiceIndex: null, + tts: controller.choreographer.tts, ); } } diff --git a/lib/pangea/enum/activity_type_enum.dart b/lib/pangea/enum/activity_type_enum.dart index 8da783867..d7f7d9df5 100644 --- a/lib/pangea/enum/activity_type_enum.dart +++ b/lib/pangea/enum/activity_type_enum.dart @@ -26,6 +26,16 @@ extension ActivityTypeExtension on ActivityTypeEnum { } } + bool get includeTTSOnClick { + switch (this) { + case ActivityTypeEnum.wordMeaning: + return false; + case ActivityTypeEnum.wordFocusListening: + case ActivityTypeEnum.hiddenWordListening: + return true; + } + } + ActivityTypeEnum fromString(String value) { final split = value.split('.').last; switch (split) { diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index 2edbd4a8f..ade520102 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -197,6 +197,7 @@ class PangeaToken { case ActivityTypeEnum.wordMeaning: return canBeDefined; case ActivityTypeEnum.wordFocusListening: + return false; case ActivityTypeEnum.hiddenWordListening: return canBeHeard; } diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index 2ae1f667a..a36f75d97 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -4,6 +4,7 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/enum/activity_display_instructions_enum.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; @@ -200,13 +201,20 @@ class PracticeActivityRequest { } class PracticeActivityModel { + // deprecated in favor of targetTokens final List tgtConstructs; + + // being added after creation from request info + // TODO - replace tgtConstructs with targetTokens in server return + List? targetTokens; + final String langCode; final ActivityTypeEnum activityType; final ActivityContent content; PracticeActivityModel({ required this.tgtConstructs, + required this.targetTokens, required this.langCode, required this.activityType, required this.content, @@ -244,6 +252,11 @@ class PracticeActivityModel { activityType: ActivityTypeEnum.wordMeaning.fromString(json['activity_type']), content: ActivityContent.fromJson(contentMap), + targetTokens: json['target_tokens'] is List + ? (json['target_tokens'] as List) + .map((e) => PangeaToken.fromJson(e as Map)) + .toList() + : null, ); } @@ -256,6 +269,7 @@ class PracticeActivityModel { 'lang_code': langCode, 'activity_type': activityType.string, 'content': content.toJson(), + 'target_tokens': targetTokens?.map((e) => e.toJson()).toList(), }; } diff --git a/lib/pangea/widgets/chat/message_audio_card.dart b/lib/pangea/widgets/chat/message_audio_card.dart index 242d2ca9b..08a9e9adf 100644 --- a/lib/pangea/widgets/chat/message_audio_card.dart +++ b/lib/pangea/widgets/chat/message_audio_card.dart @@ -59,11 +59,11 @@ class MessageAudioCardState extends State { @override void didUpdateWidget(covariant oldWidget) { - if (oldWidget.selection != widget.selection && widget.selection != null) { - debugPrint('selection changed'); - setSectionStartAndEndFromSelection(); - playSelectionAudio(); - } + // if (oldWidget.selection != widget.selection && widget.selection != null) { + // debugPrint('selection changed'); + // setSectionStartAndEndFromSelection(); + // playSelectionAudio(); + // } super.didUpdateWidget(oldWidget); } diff --git a/lib/pangea/widgets/chat/message_selection_overlay.dart b/lib/pangea/widgets/chat/message_selection_overlay.dart index 80363e7d0..7bef4225b 100644 --- a/lib/pangea/widgets/chat/message_selection_overlay.dart +++ b/lib/pangea/widgets/chat/message_selection_overlay.dart @@ -18,7 +18,6 @@ import 'package:fluffychat/pangea/widgets/chat/message_toolbar_buttons.dart'; import 'package:fluffychat/pangea/widgets/chat/overlay_footer.dart'; import 'package:fluffychat/pangea/widgets/chat/overlay_header.dart'; import 'package:fluffychat/pangea/widgets/chat/overlay_message.dart'; -import 'package:fluffychat/pangea/widgets/chat/tts_controller.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; @@ -67,7 +66,6 @@ class MessageOverlayController extends State PangeaMessageEvent? get pangeaMessageEvent => widget._pangeaMessageEvent; - final TtsController tts = TtsController(); bool _isPlayingAudio = false; bool get showToolbarButtons => @@ -139,8 +137,6 @@ class MessageOverlayController extends State ); }, ).listen((_) => setState(() {})); - - tts.setupTTS(); } MessageAnalyticsEntry? get messageAnalyticsEntry => @@ -297,6 +293,14 @@ class MessageOverlayController extends State } } + if (_selectedSpan != null) { + widget.chatController.choreographer.tts.tryToSpeak( + token.text.content, + context, + pangeaMessageEvent!.eventId, + ); + } + setState(() {}); } @@ -450,7 +454,7 @@ class MessageOverlayController extends State void dispose() { _animationController.dispose(); _reactionSubscription?.cancel(); - tts.dispose(); + super.dispose(); } @@ -562,7 +566,6 @@ class MessageOverlayController extends State MessageToolbar( pangeaMessageEvent: pangeaMessageEvent!, overLayController: this, - ttsController: tts, ), const SizedBox(height: 8), SizedBox( diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index cb88bbf5e..849fc18a0 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -27,15 +27,16 @@ const double minCardHeight = 70; class MessageToolbar extends StatelessWidget { final PangeaMessageEvent pangeaMessageEvent; final MessageOverlayController overLayController; - final TtsController ttsController; const MessageToolbar({ super.key, required this.pangeaMessageEvent, required this.overLayController, - required this.ttsController, }); + TtsController get ttsController => + overLayController.widget.chatController.choreographer.tts; + Widget toolbarContent(BuildContext context) { final bool subscribed = MatrixState.pangeaController.subscriptionController.isSubscribed; @@ -135,7 +136,6 @@ class MessageToolbar extends StatelessWidget { return PracticeActivityCard( pangeaMessageEvent: pangeaMessageEvent, overlayController: overLayController, - ttsController: ttsController, ); default: debugger(when: kDebugMode); diff --git a/lib/pangea/widgets/chat/tts_controller.dart b/lib/pangea/widgets/chat/tts_controller.dart index 6eb762ef0..5a7bbc3e8 100644 --- a/lib/pangea/widgets/chat/tts_controller.dart +++ b/lib/pangea/widgets/chat/tts_controller.dart @@ -145,7 +145,8 @@ class TtsController { Future tryToSpeak( String text, BuildContext context, - String eventID, + // TODO - make non-nullable again + String? eventID, ) async { if (_isLanguageFullySupported) { await _speak(text); @@ -157,7 +158,9 @@ class TtsController { 'availableLangCodes': _availableLangCodes, }, ); - await _showMissingVoicePopup(context, eventID); + if (eventID != null) { + await _showMissingVoicePopup(context, eventID); + } } } diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 9454a2517..a9075a976 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -280,6 +280,7 @@ class WordMatchContent extends StatelessWidget { uniqueKeyForLayerLink: (int index) => "wordMatch$index", selectedChoiceIndex: controller.selectedChoiceIndex, + tts: controller.widget.scm.choreographer.tts, ), const SizedBox(height: 12), PromptAndFeedback(controller: controller), diff --git a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart index 2127b11ce..33e9d99d9 100644 --- a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart +++ b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart @@ -5,6 +5,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; import 'package:fluffychat/pangea/controllers/put_analytics_controller.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -21,7 +22,6 @@ import 'package:matrix/matrix.dart'; class MultipleChoiceActivity extends StatefulWidget { final PracticeActivityCardState practiceCardController; final PracticeActivityModel currentActivity; - final TtsController tts; final Event event; final VoidCallback? onError; @@ -29,7 +29,6 @@ class MultipleChoiceActivity extends StatefulWidget { super.key, required this.practiceCardController, required this.currentActivity, - required this.tts, required this.event, this.onError, }); @@ -46,6 +45,8 @@ class MultipleChoiceActivityState extends State { @override void initState() { + speakTargetTokens(); + super.initState(); } @@ -55,18 +56,59 @@ class MultipleChoiceActivityState extends State { if (widget.practiceCardController.currentCompletionRecord?.responses .isEmpty ?? false) { + speakTargetTokens(); + setState(() => selectedChoiceIndex = null); } } - void updateChoice(String value, int index) { - if (currentRecordModel?.hasTextResponse(value) ?? false) { - return; + void speakTargetTokens() { + if (widget.practiceCardController.currentActivity?.targetTokens != null) { + widget.practiceCardController.tts.tryToSpeak( + PangeaToken.reconstructText( + widget.practiceCardController.currentActivity!.targetTokens!, + ), + context, + null, + ); } + } + + TtsController get tts => widget.practiceCardController.tts; + void updateChoice(String value, int index) { final bool isCorrect = widget.currentActivity.content.isCorrect(value, index); + // If the activity is not set to include TTS on click, and the choice is correct, speak the target tokens + // We have to check if tokens + if (!widget.currentActivity.activityType.includeTTSOnClick && + isCorrect && + mounted) { + // should be set by now but just in case we make a mistake + if (widget.practiceCardController.currentActivity?.targetTokens == null) { + debugger(when: kDebugMode); + ErrorHandler.logError( + e: "Missing target tokens in multiple choice activity", + data: { + "currentActivity": widget.practiceCardController.currentActivity, + }, + ); + } else { + tts.tryToSpeak( + PangeaToken.reconstructText( + widget.practiceCardController.currentActivity!.targetTokens!, + ), + context, + null, + ); + } + } + + if (currentRecordModel?.hasTextResponse(value) ?? false) { + return; + } + currentRecordModel?.addResponse( text: value, score: isCorrect ? 1 : 0, @@ -136,7 +178,7 @@ class MultipleChoiceActivityState extends State { ActivityTypeEnum.wordFocusListening) WordAudioButton( text: practiceActivity.content.answer, - ttsController: widget.tts, + ttsController: tts, eventID: widget.event.eventId, ), if (practiceActivity.activityType == @@ -146,7 +188,7 @@ class MultipleChoiceActivityState extends State { widget.practiceCardController.widget.pangeaMessageEvent, overlayController: widget.practiceCardController.widget.overlayController, - tts: widget.practiceCardController.widget.overlayController.tts, + tts: tts, setIsPlayingAudio: widget.practiceCardController.widget .overlayController.setIsPlayingAudio, onError: widget.onError, @@ -170,6 +212,7 @@ class MultipleChoiceActivityState extends State { .toList(), isActive: true, id: currentRecordModel?.hashCode.toString(), + tts: practiceActivity.activityType.includeTTSOnClick ? tts : null, ), ], ); diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index ca1cd5f4a..0898b8b74 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -30,13 +30,11 @@ import 'package:flutter/material.dart'; class PracticeActivityCard extends StatefulWidget { final PangeaMessageEvent pangeaMessageEvent; final MessageOverlayController overlayController; - final TtsController ttsController; const PracticeActivityCard({ super.key, required this.pangeaMessageEvent, required this.overlayController, - required this.ttsController, }); @override @@ -59,6 +57,9 @@ class PracticeActivityCardState extends State { Duration appropriateTimeForJoy = const Duration(milliseconds: 1500); bool savoringTheJoy = false; + TtsController get tts => + widget.overlayController.widget.chatController.choreographer.tts; + @override void initState() { super.initState(); @@ -100,76 +101,86 @@ class PracticeActivityCardState extends State { Future _fetchActivity({ ActivityQualityFeedback? activityFeedback, }) async { - // try { - debugPrint('Fetching activity'); - _updateFetchingActivity(true); - - // target tokens can be empty if activities have been completed for each - // it's set on initialization and then removed when each activity is completed - if (!mounted || - !pangeaController.languageController.languagesSet || - widget.overlayController.messageAnalyticsEntry == null) { - debugger(when: kDebugMode); - _updateFetchingActivity(false); - return null; - } + try { + debugPrint('Fetching activity'); + _updateFetchingActivity(true); + + // target tokens can be empty if activities have been completed for each + // it's set on initialization and then removed when each activity is completed + if (!mounted || + !pangeaController.languageController.languagesSet || + widget.overlayController.messageAnalyticsEntry == null) { + debugger(when: kDebugMode); + _updateFetchingActivity(false); + return null; + } - final nextActivitySpecs = - widget.overlayController.messageAnalyticsEntry?.nextActivity; - // the client is going to be choosing the next activity now - // if nothing is set then it must be done with practice - if (nextActivitySpecs == null) { - debugPrint("No next activity set, exiting practice flow"); - _updateFetchingActivity(false); - return null; - } + final nextActivitySpecs = + widget.overlayController.messageAnalyticsEntry?.nextActivity; + // the client is going to be choosing the next activity now + // if nothing is set then it must be done with practice + if (nextActivitySpecs == null) { + debugPrint("No next activity set, exiting practice flow"); + _updateFetchingActivity(false); + return null; + } - // check if we already have an activity matching the specs - final existingActivity = practiceActivities.firstWhereOrNull( - (activity) => - nextActivitySpecs.matchesActivity(activity.practiceActivity), - ); - if (existingActivity != null) { - debugPrint('found existing activity'); + // check if we already have an activity matching the specs + final existingActivity = practiceActivities.firstWhereOrNull( + (activity) => + nextActivitySpecs.matchesActivity(activity.practiceActivity), + ); + if (existingActivity != null) { + debugPrint('found existing activity'); + _updateFetchingActivity(false); + existingActivity.practiceActivity.targetTokens = + nextActivitySpecs.tokens; + return existingActivity.practiceActivity; + } + + debugPrint( + "client requesting ${nextActivitySpecs.activityType.string} for: ${nextActivitySpecs.tokens.map((t) => "word: ${t.text.content} xp: ${t.xp}").join(' ')}", + ); + + final PracticeActivityModelResponse? activityResponse = + await pangeaController.practiceGenerationController + .getPracticeActivity( + MessageActivityRequest( + userL1: pangeaController.languageController.userL1!.langCode, + userL2: pangeaController.languageController.userL2!.langCode, + messageText: widget.pangeaMessageEvent.messageDisplayText, + messageTokens: widget.overlayController.tokens!, + activityQualityFeedback: activityFeedback, + targetTokens: nextActivitySpecs.tokens, + targetType: nextActivitySpecs.activityType, + ), + widget.pangeaMessageEvent, + ); + + currentActivityCompleter = activityResponse?.eventCompleter; _updateFetchingActivity(false); - return existingActivity.practiceActivity; - } - debugPrint( - "client requesting ${nextActivitySpecs.activityType.string} for: ${nextActivitySpecs.tokens.map((t) => "word: ${t.text.content} xp: ${t.xp}").join(' ')}", - ); + if (activityResponse == null || activityResponse.activity == null) { + debugPrint('No activity found'); + return null; + } - final PracticeActivityModelResponse? activityResponse = - await pangeaController.practiceGenerationController.getPracticeActivity( - MessageActivityRequest( - userL1: pangeaController.languageController.userL1!.langCode, - userL2: pangeaController.languageController.userL2!.langCode, - messageText: widget.pangeaMessageEvent.messageDisplayText, - messageTokens: widget.overlayController.tokens!, - activityQualityFeedback: activityFeedback, - targetTokens: nextActivitySpecs.tokens, - targetType: nextActivitySpecs.activityType, - ), - widget.pangeaMessageEvent, - ); + activityResponse.activity!.targetTokens = nextActivitySpecs.tokens; - currentActivityCompleter = activityResponse?.eventCompleter; - _updateFetchingActivity(false); - - return activityResponse?.activity; - // } catch (e, s) { - // debugger(when: kDebugMode); - // ErrorHandler.logError( - // e: e, - // s: s, - // m: 'Failed to get new activity', - // data: { - // 'activity': currentActivity, - // 'record': currentCompletionRecord, - // }, - // ); - // return null; - // } + return activityResponse.activity; + } catch (e, s) { + debugger(when: kDebugMode); + ErrorHandler.logError( + e: e, + s: s, + m: 'Failed to get new activity', + data: { + 'activity': currentActivity, + 'record': currentCompletionRecord, + }, + ); + return null; + } } ConstructUseMetaData get metadata => ConstructUseMetaData( @@ -313,7 +324,6 @@ class PracticeActivityCardState extends State { return MultipleChoiceActivity( practiceCardController: this, currentActivity: currentActivity!, - tts: widget.ttsController, event: widget.pangeaMessageEvent.event, onError: _onError, );