feat: add local cache for activity session analytics (#3878)

pull/2245/head
ggurdin 2 months ago committed by GitHub
parent 85ac0317b8
commit 6bf699c190
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -8,6 +8,7 @@ import 'package:matrix/matrix.dart';
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart';
import 'package:fluffychat/pangea/activity_sessions/activity_roles_model.dart';
import 'package:fluffychat/pangea/activity_sessions/activity_session_analytics_repo.dart';
import 'package:fluffychat/pangea/activity_summary/activity_summary_analytics_model.dart';
import 'package:fluffychat/pangea/activity_summary/activity_summary_model.dart';
import 'package:fluffychat/pangea/activity_summary/activity_summary_request_model.dart';
@ -19,6 +20,7 @@ import 'package:fluffychat/pangea/course_plans/course_plan_room_extension.dart';
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
import 'package:fluffychat/widgets/matrix.dart';
import '../activity_summary/activity_summary_repo.dart';
extension ActivityRoomExtension on Room {
@ -326,4 +328,41 @@ extension ActivityRoomExtension on Room {
roomType?.startsWith(PangeaRoomTypes.activitySession) == true;
bool get isActivitySession => isActivityRoomType || activityPlan != null;
Future<ActivitySummaryAnalyticsModel> getActivityAnalytics() async {
// wait for local storage box to init in getAnalytics initialization
if (!MatrixState.pangeaController.getAnalytics.initCompleter.isCompleted) {
await MatrixState.pangeaController.getAnalytics.initCompleter.future;
}
final cached = ActivitySessionAnalyticsRepo.get(id);
final analytics = cached?.analytics ?? ActivitySummaryAnalyticsModel();
final eventsSince = await getAllEvents(since: cached?.lastEventId);
final timeline = this.timeline ?? await getTimeline();
final messageEvents = getPangeaMessageEvents(
eventsSince,
timeline,
msgtypes: [
MessageTypes.Text,
MessageTypes.Audio,
],
);
if (messageEvents.isEmpty) {
return analytics;
}
for (final pangeaMessage in messageEvents) {
analytics.addConstructs(pangeaMessage);
}
await ActivitySessionAnalyticsRepo.set(
id,
messageEvents.last.eventId,
analytics,
);
return analytics;
}
}

@ -0,0 +1,56 @@
import 'package:get_storage/get_storage.dart';
import 'package:fluffychat/pangea/activity_summary/activity_summary_analytics_model.dart';
class CachedActivityAnalytics {
final DateTime timestamp;
final String lastEventId;
final ActivitySummaryAnalyticsModel analytics;
CachedActivityAnalytics(
this.timestamp,
this.lastEventId,
this.analytics,
);
}
class ActivitySessionAnalyticsRepo {
static final GetStorage _activityAnalyticsStorage =
GetStorage('activity_analytics_storage');
static Duration cacheDuration = const Duration(minutes: 30);
static CachedActivityAnalytics? get(String roomId) {
final json = _activityAnalyticsStorage.read(roomId);
if (json == null) return null;
try {
final timestamp = DateTime.parse(json['timestamp'] as String);
if (DateTime.now().difference(timestamp) > cacheDuration) {
_activityAnalyticsStorage.remove(roomId);
return null;
}
final lastEventId = json['last_event_id'] as String;
final analyticsJson = json['analytics'] as Map<String, dynamic>;
final analytics = ActivitySummaryAnalyticsModel.fromJson(analyticsJson);
return CachedActivityAnalytics(timestamp, lastEventId, analytics);
} catch (e) {
_activityAnalyticsStorage.remove(roomId);
return null;
}
}
static Future<void> set(
String roomId,
String lastEventId,
ActivitySummaryAnalyticsModel analytics,
) async {
final json = {
'timestamp': DateTime.now().toIso8601String(),
'last_event_id': lastEventId,
'analytics': analytics.toJson(),
};
await _activityAnalyticsStorage.write(roomId, json);
}
}

@ -76,6 +76,7 @@ class GetAnalyticsController extends BaseController {
try {
await GetStorage.init("analytics_storage");
await GetStorage.init("activity_analytics_storage");
_client.updateAnalyticsRoomJoinRules();
_client.addAnalyticsRoomsToSpaces();

@ -129,6 +129,7 @@ class PangeaController {
'vocab_storage',
'onboarding_storage',
'analytics_request_storage',
'activity_analytics_storage',
];
Future<void> clearCache({List<String> exclude = const []}) async {

@ -322,7 +322,7 @@ extension EventsRoomExtension on Room {
return resp.chunk.map((e) => Event.fromMatrixEvent(e, this)).toList();
}
Future<List<Event>> getAllEvents() async {
Future<List<Event>> getAllEvents({String? since}) async {
final GetRoomEventsResponse initalResp =
await client.getRoomEvents(id, Direction.b);
@ -340,9 +340,20 @@ extension EventsRoomExtension on Room {
resp.end != nextStartToken
? nextStartToken = resp.end
: nextStartToken = null;
if (since != null && chunkMessages.any((e) => e.eventId == since)) {
break;
}
}
allMatrixEvents = allMatrixEvents.reversed.toList();
if (since != null) {
final index = allMatrixEvents.indexWhere((e) => e.eventId == since);
if (index != -1) {
allMatrixEvents = allMatrixEvents.sublist(index + 1);
}
}
final List<Event> allEvents = allMatrixEvents
.map((MatrixEvent message) => Event.fromMatrixEvent(message, this))
.toList();
@ -352,13 +363,14 @@ extension EventsRoomExtension on Room {
List<PangeaMessageEvent> getPangeaMessageEvents(
List<Event> events,
Timeline timeline,
) {
Timeline timeline, {
List<String> msgtypes = const [MessageTypes.Text],
}) {
final List<PangeaMessageEvent> allPangeaMessages = events
.where(
(Event event) =>
event.type == EventTypes.Message &&
event.content['msgtype'] == MessageTypes.Text,
msgtypes.contains(event.content['msgtype']),
)
.map(
(Event message) => PangeaMessageEvent(

Loading…
Cancel
Save