From 9321e024e77ac1657a516780cf1d285170c1c1b6 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 9 Oct 2024 14:56:05 -0400 Subject: [PATCH] cache number of completed activities --- lib/pangea/constants/local.key.dart | 1 + .../practice_activity_record_controller.dart | 46 +++++++++++++++++++ .../pangea_message_event.dart | 12 +++-- .../practice_activity_event.dart | 32 ++++++------- .../practice_activity_card.dart | 3 ++ 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/lib/pangea/constants/local.key.dart b/lib/pangea/constants/local.key.dart index 08446ace4..1c6f1f37b 100644 --- a/lib/pangea/constants/local.key.dart +++ b/lib/pangea/constants/local.key.dart @@ -5,4 +5,5 @@ class PLocalKey { static const String dismissedPaywall = 'dismissedPaywall'; static const String paywallBackoff = 'paywallBackoff'; static const String messagesSinceUpdate = 'messagesSinceLastUpdate'; + static const String completedActivities = 'completedActivities'; } diff --git a/lib/pangea/controllers/practice_activity_record_controller.dart b/lib/pangea/controllers/practice_activity_record_controller.dart index b075fa553..45b036611 100644 --- a/lib/pangea/controllers/practice_activity_record_controller.dart +++ b/lib/pangea/controllers/practice_activity_record_controller.dart @@ -1,6 +1,8 @@ import 'dart:async'; +import 'dart:collection'; import 'dart:developer'; +import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; @@ -21,6 +23,7 @@ class _RecordCacheItem { /// Controller for handling activity completions. class PracticeActivityRecordController { + static const int maxStoredEvents = 100; static final Map _cache = {}; late final PangeaController _pangeaController; Timer? _cacheClearTimer; @@ -29,6 +32,49 @@ class PracticeActivityRecordController { _initializeCacheClearing(); } + LinkedHashMap get completedActivities { + try { + final dynamic locallySaved = _pangeaController.pStoreService.read( + PLocalKey.completedActivities, + ); + if (locallySaved == null) return LinkedHashMap(); + try { + final LinkedHashMap cache = + LinkedHashMap.from(locallySaved); + return cache; + } catch (err) { + _pangeaController.pStoreService.delete( + PLocalKey.completedActivities, + ); + return LinkedHashMap(); + } + } catch (exception, stackTrace) { + ErrorHandler.logError( + e: PangeaWarningError( + "Failed to get completed activities from cache: $exception", + ), + s: stackTrace, + m: 'Failed to get completed activities from cache', + ); + return LinkedHashMap(); + } + } + + Future completeActivity(String messageID) async { + final LinkedHashMap currentCache = completedActivities; + final numCompleted = currentCache[messageID] ?? 0; + currentCache[messageID] = numCompleted + 1; + + if (currentCache.length > maxStoredEvents) { + currentCache.remove(currentCache.keys.first); + } + + await _pangeaController.pStoreService.save( + PLocalKey.completedActivities, + currentCache, + ); + } + void _initializeCacheClearing() { const duration = Duration(minutes: 2); _cacheClearTimer = Timer.periodic(duration, (Timer t) => _clearCache()); diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 86fae48e3..5e5a4a059 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -583,13 +583,15 @@ class PangeaMessageEvent { /// Otherwise, it checks if every activity in the list is complete using the [isComplete] property. /// If any activity is not complete, it returns true, indicating that the activity icon should be shown. /// Otherwise, it returns false. - bool get hasUncompletedActivity { - if (practiceActivities.isEmpty) return false; - return practiceActivities.any((activity) => !(activity.isComplete)); - } + // bool get hasUncompletedActivity { + // if (practiceActivities.isEmpty) return false; + // return practiceActivities.any((activity) => !(activity.isComplete)); + // } int get numberOfActivitiesCompleted { - return practiceActivities.where((activity) => activity.isComplete).length; + return MatrixState.pangeaController.activityRecordController + .completedActivities[eventId] ?? + 0; } String? get l2Code => diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart index 2dab65618..f8ac678dd 100644 --- a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart +++ b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart @@ -63,30 +63,26 @@ class PracticeActivityEvent { /// Completion record assosiated with this activity /// for the logged in user, null if there is none - List get allUserRecords => allRecords - .where( - (recordEvent) => - recordEvent.event.senderId == recordEvent.event.room.client.userID, - ) - .toList(); + // List get allUserRecords => allRecords + // .where( + // (recordEvent) => + // recordEvent.event.senderId == recordEvent.event.room.client.userID, + // ) + // .toList(); /// Get the most recent user record for this activity - PracticeActivityRecordEvent? get latestUserRecord { - final List userRecords = allUserRecords; - if (userRecords.isEmpty) return null; - return userRecords.reduce( - (a, b) => a.event.originServerTs.isAfter(b.event.originServerTs) ? a : b, - ); - } + // PracticeActivityRecordEvent? get latestUserRecord { + // final List userRecords = allUserRecords; + // if (userRecords.isEmpty) return null; + // return userRecords.reduce( + // (a, b) => a.event.originServerTs.isAfter(b.event.originServerTs) ? a : b, + // ); + // } - DateTime? get lastCompletedAt => latestUserRecord?.event.originServerTs; + // DateTime? get lastCompletedAt => latestUserRecord?.event.originServerTs; String get parentMessageId => event.relationshipEventId!; - /// Checks if there are any user records in the list for this activity, - /// and, if so, then the activity is complete - bool get isComplete => latestUserRecord != null; - ExistingActivityMetaData get activityRequestMetaData => ExistingActivityMetaData( activityEventId: event.eventId, diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 9e0ee3b01..ab4f59451 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -197,6 +197,9 @@ class MessagePracticeActivityCardState extends State { ); widget.overlayController.onActivityFinish(); + pangeaController.activityRecordController.completeActivity( + widget.pangeaMessageEvent.eventId, + ); // final Iterable result = await Future.wait([