using queue and simplifying selected token for activity flow

pull/1490/head
William Jordan-Cooley 1 year ago
parent 1a4dc0ba95
commit c82ce34124

@ -127,15 +127,28 @@ class MessageAnalyticsEntry {
return queue.take(3).toList(); return queue.take(3).toList();
} }
/// Removes the last activity from the queue /// Adds a word focus listening activity to the front of the queue
/// This should only used when there is a startingToken in practice flow /// And limits to 3 activities
/// and we want to go down to 2 activities + the activity with the startingToken void addForWordMeaning(PangeaToken selectedToken) {
void goDownTo2Activities() { _activityQueue.insert(
if (_activityQueue.isNotEmpty && _activityQueue.length > 2) { 0,
_activityQueue.removeLast(); TargetTokensAndActivityType(
tokens: [selectedToken],
activityType: ActivityTypeEnum.wordMeaning,
),
);
// remove down to three activities
if (_activityQueue.length > 3) {
_activityQueue.removeRange(3, _activityQueue.length);
} }
} }
int get numActivities => _activityQueue.length;
void clearActivityQueue() {
_activityQueue.clear();
}
/// Returns a hidden word activity if there is a sequence of tokens that have hiddenWordListening in their eligibleActivityTypes /// Returns a hidden word activity if there is a sequence of tokens that have hiddenWordListening in their eligibleActivityTypes
TargetTokensAndActivityType? getHiddenWordActivity(int numOtherActivities) { TargetTokensAndActivityType? getHiddenWordActivity(int numOtherActivities) {
// don't do hidden word listening on own messages // don't do hidden word listening on own messages

@ -65,7 +65,6 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
/// The number of activities that need to be completed before the toolbar is unlocked /// The number of activities that need to be completed before the toolbar is unlocked
/// If we don't have any good activities for them, we'll decrease this number /// If we don't have any good activities for them, we'll decrease this number
static const int neededActivities = 3; static const int neededActivities = 3;
int activitiesLeftToComplete = neededActivities;
bool get messageInUserL2 => bool get messageInUserL2 =>
pangeaMessageEvent.messageDisplayLangCode == pangeaMessageEvent.messageDisplayLangCode ==
@ -121,9 +120,6 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
_getTokens(); _getTokens();
activitiesLeftToComplete = activitiesLeftToComplete -
widget._pangeaMessageEvent.numberOfActivitiesCompleted;
_reactionSubscription = _reactionSubscription =
widget.chatController.room.client.onSync.stream.where( widget.chatController.room.client.onSync.stream.where(
(update) { (update) {
@ -146,7 +142,12 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
tts.setupTTS(); tts.setupTTS();
_setInitialToolbarModeAndSelectedSpan(); if (selectedTargetTokenForWordMeaning != null) {
messageAnalyticsEntry
?.addForWordMeaning(selectedTargetTokenForWordMeaning!);
}
_setInitialToolbarMode();
} }
MessageAnalyticsEntry? get messageAnalyticsEntry => tokens != null MessageAnalyticsEntry? get messageAnalyticsEntry => tokens != null
@ -171,7 +172,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
.then((tokens) { .then((tokens) {
// this isn't currently working because originalSent's _event is null // this isn't currently working because originalSent's _event is null
this.tokens = tokens; this.tokens = tokens;
_setInitialToolbarModeAndSelectedSpan(); _setInitialToolbarMode();
}); });
} }
} }
@ -209,13 +210,13 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
} }
} }
int get activitiesLeftToComplete => messageAnalyticsEntry?.numActivities ?? 0;
bool get isPracticeComplete => activitiesLeftToComplete <= 0; bool get isPracticeComplete => activitiesLeftToComplete <= 0;
/// When an activity is completed, we need to update the state /// When an activity is completed, we need to update the state
/// and check if the toolbar should be unlocked /// and check if the toolbar should be unlocked
void onActivityFinish() { void onActivityFinish() {
if (!mounted) return; if (!mounted) return;
activitiesLeftToComplete -= 1;
clearSelection(); clearSelection();
setState(() {}); setState(() {});
} }
@ -223,29 +224,25 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
/// In some cases, we need to exit the practice flow and let the user /// In some cases, we need to exit the practice flow and let the user
/// interact with the toolbar without completing activities /// interact with the toolbar without completing activities
void exitPracticeFlow() { void exitPracticeFlow() {
messageAnalyticsEntry?.clearActivityQueue();
clearSelection(); clearSelection();
activitiesLeftToComplete = 0;
setState(() {}); setState(() {});
} }
Future<void> _setInitialToolbarModeAndSelectedSpan() async { Future<void> _setInitialToolbarMode() async {
if (widget._pangeaMessageEvent.isAudioMessage) { if (widget._pangeaMessageEvent.isAudioMessage) {
toolbarMode = MessageMode.speechToText; toolbarMode = MessageMode.speechToText;
return setState(() => toolbarMode = MessageMode.practiceActivity); return setState(() => toolbarMode = MessageMode.practiceActivity);
} }
// we're only going to do activities if we have tokens for the message // 1) we're only going to do activities if we have tokens for the message
if (tokens != null) { // 2) if the user selects a span on initialization, then we want to give
// if the user selects a span on initialization, then we want to give // them a practice activity on that word
// them a practice activity on that word // 3) if the user has activities left to complete, then we want to give them
if (selectedTargetTokenForWordMeaning != null) { if (tokens != null &&
_selectedSpan = selectedTargetTokenForWordMeaning?.text; (selectedTargetTokenForWordMeaning != null ||
return setState(() => toolbarMode = MessageMode.practiceActivity); activitiesLeftToComplete > 0)) {
} return setState(() => toolbarMode = MessageMode.practiceActivity);
if (activitiesLeftToComplete > 0) {
return setState(() => toolbarMode = MessageMode.practiceActivity);
}
} }
// Note: this setting is now hidden so this will always be false // Note: this setting is now hidden so this will always be false

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/controllers/message_analytics_controller.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/controllers/practice_activity_generation_controller.dart'; import 'package:fluffychat/pangea/controllers/practice_activity_generation_controller.dart';
import 'package:fluffychat/pangea/controllers/put_analytics_controller.dart'; import 'package:fluffychat/pangea/controllers/put_analytics_controller.dart';
@ -10,7 +9,6 @@ import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart';
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/message_activity_request.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/message_activity_request.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_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/models/practice_activities.dart/practice_activity_record_model.dart';
@ -55,9 +53,6 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
List<PracticeActivityEvent> get practiceActivities => List<PracticeActivityEvent> get practiceActivities =>
widget.pangeaMessageEvent.practiceActivities; widget.pangeaMessageEvent.practiceActivities;
// if the user has selected a token, we're going to give them an activity on that token first
late PangeaToken? startingToken;
// Used to show an animation when the user completes an activity // Used to show an animation when the user completes an activity
// while simultaneously fetching a new activity and not showing the loading spinner // while simultaneously fetching a new activity and not showing the loading spinner
// until the appropriate time has passed to 'savor the joy' // until the appropriate time has passed to 'savor the joy'
@ -97,7 +92,6 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
/// Get an existing activity if there is one. /// Get an existing activity if there is one.
/// If not, get a new activity from the server. /// If not, get a new activity from the server.
Future<void> initialize() async { Future<void> initialize() async {
startingToken = widget.overlayController.selectedTargetTokenForWordMeaning;
_setPracticeActivity( _setPracticeActivity(
await _fetchActivity(), await _fetchActivity(),
); );
@ -120,26 +114,8 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
return null; return null;
} }
// if the user selected a token which is not already in a hidden word activity, final nextActivitySpecs =
// we're going to give them an activity on that token first widget.overlayController.messageAnalyticsEntry?.nextActivity;
// otherwise, we're going to give them an activity on the next token in the queue
TargetTokensAndActivityType? nextActivitySpecs;
if (startingToken != null) {
// if the user selected a token, we're going to give them an activity on that token first
nextActivitySpecs = TargetTokensAndActivityType(
tokens: [startingToken!],
activityType: ActivityTypeEnum.wordMeaning,
);
// clear the starting token so that the next activity is not based on it
startingToken = null;
// we want to go down to 2 activities + the activity with the startingToken
// so we remove the last activity from the queue if there's more than 2
widget.overlayController.messageAnalyticsEntry?.goDownTo2Activities();
} else {
nextActivitySpecs =
widget.overlayController.messageAnalyticsEntry?.nextActivity;
}
// the client is going to be choosing the next activity now // the client is going to be choosing the next activity now
// if nothing is set then it must be done with practice // if nothing is set then it must be done with practice
if (nextActivitySpecs == null) { if (nextActivitySpecs == null) {
@ -151,7 +127,7 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
// check if we already have an activity matching the specs // check if we already have an activity matching the specs
final existingActivity = practiceActivities.firstWhereOrNull( final existingActivity = practiceActivities.firstWhereOrNull(
(activity) => (activity) =>
nextActivitySpecs!.matchesActivity(activity.practiceActivity), nextActivitySpecs.matchesActivity(activity.practiceActivity),
); );
if (existingActivity != null) { if (existingActivity != null) {
debugPrint('found existing activity'); debugPrint('found existing activity');
@ -160,7 +136,7 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
} }
debugPrint( debugPrint(
"client requesting ${nextActivitySpecs.activityType.string} for ${nextActivitySpecs.tokens.map((t) => t.text).join(' ')}", "client requesting ${nextActivitySpecs.activityType.string} for: ${nextActivitySpecs.tokens.map((t) => t.text.content).join(' ')}",
); );
final PracticeActivityModelResponse? activityResponse = final PracticeActivityModelResponse? activityResponse =

Loading…
Cancel
Save