Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use-queue #1025

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions lib/pangea/controllers/message_analytics_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,28 @@ class MessageAnalyticsEntry {
return queue.take(3).toList();
}

/// Removes the last activity from the queue
/// This should only used when there is a startingToken in practice flow
/// and we want to go down to 2 activities + the activity with the startingToken
void goDownTo2Activities() {
if (_activityQueue.isNotEmpty && _activityQueue.length > 2) {
_activityQueue.removeLast();
/// Adds a word focus listening activity to the front of the queue
/// And limits to 3 activities
void addForWordMeaning(PangeaToken selectedToken) {
_activityQueue.insert(
0,
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
TargetTokensAndActivityType? getHiddenWordActivity(int numOtherActivities) {
// don't do hidden word listening on own messages
Expand Down
39 changes: 18 additions & 21 deletions lib/pangea/widgets/chat/message_selection_overlay.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
/// 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
static const int neededActivities = 3;
int activitiesLeftToComplete = neededActivities;

bool get messageInUserL2 =>
pangeaMessageEvent.messageDisplayLangCode ==
Expand Down Expand Up @@ -121,9 +120,6 @@ class MessageOverlayController extends State<MessageSelectionOverlay>

_getTokens();

activitiesLeftToComplete = activitiesLeftToComplete -
widget._pangeaMessageEvent.numberOfActivitiesCompleted;

_reactionSubscription =
widget.chatController.room.client.onSync.stream.where(
(update) {
Expand All @@ -146,7 +142,12 @@ class MessageOverlayController extends State<MessageSelectionOverlay>

tts.setupTTS();

_setInitialToolbarModeAndSelectedSpan();
if (selectedTargetTokenForWordMeaning != null) {
messageAnalyticsEntry
?.addForWordMeaning(selectedTargetTokenForWordMeaning!);
}

_setInitialToolbarMode();
}

MessageAnalyticsEntry? get messageAnalyticsEntry => tokens != null
Expand All @@ -171,7 +172,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
.then((tokens) {
// this isn't currently working because originalSent's _event is null
this.tokens = tokens;
_setInitialToolbarModeAndSelectedSpan();
_setInitialToolbarMode();
});
}
}
Expand Down Expand Up @@ -209,43 +210,39 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
}
}

int get activitiesLeftToComplete => messageAnalyticsEntry?.numActivities ?? 0;
bool get isPracticeComplete => activitiesLeftToComplete <= 0;

/// When an activity is completed, we need to update the state
/// and check if the toolbar should be unlocked
void onActivityFinish() {
if (!mounted) return;
activitiesLeftToComplete -= 1;
clearSelection();
setState(() {});
}

/// In some cases, we need to exit the practice flow and let the user
/// interact with the toolbar without completing activities
void exitPracticeFlow() {
messageAnalyticsEntry?.clearActivityQueue();
clearSelection();
activitiesLeftToComplete = 0;
setState(() {});
}

Future<void> _setInitialToolbarModeAndSelectedSpan() async {
Future<void> _setInitialToolbarMode() async {
if (widget._pangeaMessageEvent.isAudioMessage) {
toolbarMode = MessageMode.speechToText;
return setState(() => toolbarMode = MessageMode.practiceActivity);
}

// we're only going to do activities if we have tokens for the message
if (tokens != null) {
// if the user selects a span on initialization, then we want to give
// them a practice activity on that word
if (selectedTargetTokenForWordMeaning != null) {
_selectedSpan = selectedTargetTokenForWordMeaning?.text;
return setState(() => toolbarMode = MessageMode.practiceActivity);
}

if (activitiesLeftToComplete > 0) {
return setState(() => toolbarMode = MessageMode.practiceActivity);
}
// 1) we're only going to do activities if we have tokens for the message
// 2) if the user selects a span on initialization, then we want to give
// them a practice activity on that word
// 3) if the user has activities left to complete, then we want to give them
if (tokens != null &&
(selectedTargetTokenForWordMeaning != null ||
activitiesLeftToComplete > 0)) {
return setState(() => toolbarMode = MessageMode.practiceActivity);
}

// Note: this setting is now hidden so this will always be false
Expand Down
32 changes: 4 additions & 28 deletions lib/pangea/widgets/practice_activity/practice_activity_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import 'dart:async';
import 'dart:developer';

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/practice_activity_generation_controller.dart';
import 'package:fluffychat/pangea/controllers/put_analytics_controller.dart';
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/practice_activity_event.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/practice_activity_model.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
Expand Down Expand Up @@ -55,9 +53,6 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
List<PracticeActivityEvent> get 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
// while simultaneously fetching a new activity and not showing the loading spinner
// until the appropriate time has passed to 'savor the joy'
Expand Down Expand Up @@ -97,7 +92,6 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
/// Get an existing activity if there is one.
/// If not, get a new activity from the server.
Future<void> initialize() async {
startingToken = widget.overlayController.selectedTargetTokenForWordMeaning;
_setPracticeActivity(
await _fetchActivity(),
);
Expand All @@ -120,26 +114,8 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
return null;
}

// if the user selected a token which is not already in a hidden word activity,
// we're going to give them an activity on that token first
// 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;
}

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) {
Expand All @@ -151,7 +127,7 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
// check if we already have an activity matching the specs
final existingActivity = practiceActivities.firstWhereOrNull(
(activity) =>
nextActivitySpecs!.matchesActivity(activity.practiceActivity),
nextActivitySpecs.matchesActivity(activity.practiceActivity),
);
if (existingActivity != null) {
debugPrint('found existing activity');
Expand All @@ -160,7 +136,7 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
}

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 =
Expand Down
Loading