update UI on all analytics update types
This commit is contained in:
parent
811ba58c73
commit
dfbc1ab0b9
7 changed files with 138 additions and 38 deletions
|
|
@ -156,7 +156,7 @@ class AnalyticsDataService {
|
|||
} finally {
|
||||
Logs().i("Analytics database initialized.");
|
||||
initCompleter.complete();
|
||||
updateDispatcher.sendLocalAnalyticsUpdate(AnalyticsUpdate([]));
|
||||
updateDispatcher.sendEmptyAnalyticsUpdate();
|
||||
updateDispatcher.sendActivityAnalyticsUpdate(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -408,7 +408,7 @@ class AnalyticsDataService {
|
|||
final newConstructs = await getConstructUses(updateIds);
|
||||
|
||||
int points = 0;
|
||||
if (update.blockedConstruct == null || updateIds.isNotEmpty) {
|
||||
if (updateIds.isNotEmpty) {
|
||||
for (final id in updateIds) {
|
||||
final prevPoints = prevConstructs[id]?.points ?? 0;
|
||||
final newPoints = newConstructs[id]?.points ?? 0;
|
||||
|
|
@ -469,10 +469,6 @@ class AnalyticsDataService {
|
|||
}
|
||||
}
|
||||
|
||||
if (update.blockedConstruct != null) {
|
||||
events.add(ConstructBlockedEvent(update.blockedConstruct!));
|
||||
}
|
||||
|
||||
if (newUnusedConstructs.isNotEmpty) {
|
||||
events.add(NewConstructsEvent(newUnusedConstructs));
|
||||
}
|
||||
|
|
@ -518,11 +514,7 @@ class AnalyticsDataService {
|
|||
);
|
||||
|
||||
await _analyticsClientGetter.database.updateTotalXP(newXP);
|
||||
|
||||
_invalidateCaches();
|
||||
updateDispatcher.sendLocalAnalyticsUpdate(
|
||||
AnalyticsUpdate([], blockedConstruct: constructId),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> clearLocalAnalytics() async {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,34 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:fluffychat/pangea/analytics_data/analytics_data_service.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_event.dart';
|
||||
import 'package:fluffychat/pangea/analytics_settings/analytics_settings_model.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/lemmas/user_set_lemma_info.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
enum _AnalyticsUpdateEvent {
|
||||
constructAnalytics,
|
||||
activityAnalytics,
|
||||
lemmaInfo,
|
||||
blockedConstruct;
|
||||
|
||||
String get eventType {
|
||||
switch (this) {
|
||||
case _AnalyticsUpdateEvent.constructAnalytics:
|
||||
return PangeaEventTypes.construct;
|
||||
case _AnalyticsUpdateEvent.activityAnalytics:
|
||||
return PangeaEventTypes.activityRoomIds;
|
||||
case _AnalyticsUpdateEvent.lemmaInfo:
|
||||
return PangeaEventTypes.userSetLemmaInfo;
|
||||
case _AnalyticsUpdateEvent.blockedConstruct:
|
||||
return PangeaEventTypes.analyticsSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AnalyticsSyncController {
|
||||
final Client client;
|
||||
final AnalyticsDataService dataService;
|
||||
|
|
@ -30,15 +54,43 @@ class AnalyticsSyncController {
|
|||
final analyticsRoom = _getAnalyticsRoom();
|
||||
if (analyticsRoom == null) return;
|
||||
|
||||
final events = update.rooms?.join?[analyticsRoom.id]?.timeline?.events
|
||||
?.where(
|
||||
(e) =>
|
||||
e.type == PangeaEventTypes.construct &&
|
||||
e.senderId == client.userID,
|
||||
);
|
||||
final roomUpdates = update.rooms?.join?[analyticsRoom.id]?.timeline?.events;
|
||||
if (roomUpdates == null) return;
|
||||
|
||||
if (events == null || events.isEmpty) return;
|
||||
for (final type in _AnalyticsUpdateEvent.values) {
|
||||
await _dispatchSyncEvents(type, roomUpdates, analyticsRoom);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _dispatchSyncEvents(
|
||||
_AnalyticsUpdateEvent type,
|
||||
List<MatrixEvent> events,
|
||||
Room analyticsRoom,
|
||||
) async {
|
||||
final updates = events
|
||||
.where((e) => e.type == type.eventType && e.senderId == client.userID)
|
||||
.toList();
|
||||
|
||||
switch (type) {
|
||||
case _AnalyticsUpdateEvent.constructAnalytics:
|
||||
await _onConstructEvents(updates, analyticsRoom);
|
||||
break;
|
||||
case _AnalyticsUpdateEvent.activityAnalytics:
|
||||
_onActivityEvents(updates);
|
||||
break;
|
||||
case _AnalyticsUpdateEvent.lemmaInfo:
|
||||
_onLemmaInfoEvents(updates);
|
||||
break;
|
||||
case _AnalyticsUpdateEvent.blockedConstruct:
|
||||
await _onBlockedConstructEvents(updates);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onConstructEvents(
|
||||
List<MatrixEvent> events,
|
||||
Room analyticsRoom,
|
||||
) async {
|
||||
final constructEvents = events
|
||||
.map(
|
||||
(e) => ConstructAnalyticsEvent(
|
||||
|
|
@ -54,6 +106,60 @@ class AnalyticsSyncController {
|
|||
);
|
||||
}
|
||||
|
||||
void _onActivityEvents(List<MatrixEvent> events) {
|
||||
for (final event in events) {
|
||||
if (event.content[ModelKey.roomIds] is! List) continue;
|
||||
final roomIds = List<String>.from(
|
||||
event.content[ModelKey.roomIds]! as List,
|
||||
);
|
||||
final prevContent =
|
||||
event.unsigned?['prev_content'] as Map<String, Object?>?;
|
||||
final prevRoomIds =
|
||||
prevContent != null && prevContent[ModelKey.roomIds] is List
|
||||
? List<String>.from(prevContent[ModelKey.roomIds] as List)
|
||||
: [];
|
||||
final newRoomIds = roomIds
|
||||
.where((id) => !prevRoomIds.contains(id))
|
||||
.toList();
|
||||
|
||||
for (final roomId in newRoomIds) {
|
||||
dataService.updateDispatcher.sendActivityAnalyticsUpdate(roomId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _onLemmaInfoEvents(List<MatrixEvent> events) {
|
||||
for (final event in events) {
|
||||
if (event.stateKey == null) continue;
|
||||
final cID = ConstructIdentifier.fromString(event.stateKey!);
|
||||
if (cID == null) continue;
|
||||
|
||||
final update = UserSetLemmaInfo.fromJson(event.content);
|
||||
dataService.updateDispatcher.sendLemmaInfoUpdate(cID, update);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onBlockedConstructEvents(List<MatrixEvent> events) async {
|
||||
for (final event in events) {
|
||||
final current = AnalyticsSettingsModel.fromJson(event.content);
|
||||
final prevContent =
|
||||
event.unsigned?['prev_content'] as Map<String, Object?>?;
|
||||
final prev = prevContent != null
|
||||
? AnalyticsSettingsModel.fromJson(prevContent)
|
||||
: null;
|
||||
|
||||
final newBlocked = current.blockedConstructs;
|
||||
final prevBlocked = prev?.blockedConstructs ?? {};
|
||||
|
||||
final newlyBlocked = newBlocked.where((c) => !prevBlocked.contains(c));
|
||||
for (final constructId in newlyBlocked) {
|
||||
await dataService.updateDispatcher.sendBlockedConstructUpdate(
|
||||
constructId,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> waitForSync(String analyticsRoomId) async {
|
||||
await client.onSync.stream.firstWhere((update) {
|
||||
final roomUpdate = update.rooms?.join?[analyticsRoomId];
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@ class LevelUpdate {
|
|||
|
||||
class AnalyticsUpdate {
|
||||
final List<OneConstructUse> addedConstructs;
|
||||
final ConstructIdentifier? blockedConstruct;
|
||||
final String? targetID;
|
||||
|
||||
AnalyticsUpdate(this.addedConstructs, {this.blockedConstruct, this.targetID});
|
||||
AnalyticsUpdate(this.addedConstructs, {this.targetID});
|
||||
}
|
||||
|
||||
class ConstructLevelUpdate {
|
||||
|
|
@ -86,6 +85,18 @@ class AnalyticsUpdateDispatcher {
|
|||
UserSetLemmaInfo lemmaInfo,
|
||||
) => _lemmaInfoUpdateStream.add(MapEntry(constructId, lemmaInfo));
|
||||
|
||||
Future<void> sendBlockedConstructUpdate(
|
||||
ConstructIdentifier blockedConstruct,
|
||||
) async {
|
||||
await dataService.updateBlockedConstructs(blockedConstruct);
|
||||
final update = AnalyticsStreamUpdate(blockedConstruct: blockedConstruct);
|
||||
constructUpdateStream.add(update);
|
||||
}
|
||||
|
||||
void sendEmptyAnalyticsUpdate() {
|
||||
constructUpdateStream.add(AnalyticsStreamUpdate());
|
||||
}
|
||||
|
||||
Future<void> sendServerAnalyticsUpdate(
|
||||
List<ConstructAnalyticsEvent> events,
|
||||
) async {
|
||||
|
|
@ -113,9 +124,6 @@ class AnalyticsUpdateDispatcher {
|
|||
case final XPGainedEvent e:
|
||||
_onXPGained(e.points, e.targetID);
|
||||
break;
|
||||
case final ConstructBlockedEvent e:
|
||||
_onBlockedConstruct(e.blockedConstruct);
|
||||
break;
|
||||
case final ConstructLevelUpEvent e:
|
||||
_onConstructLevelUp(e.constructId, e.level, e.targetID);
|
||||
break;
|
||||
|
|
@ -163,11 +171,6 @@ class AnalyticsUpdateDispatcher {
|
|||
);
|
||||
}
|
||||
|
||||
void _onBlockedConstruct(ConstructIdentifier constructId) {
|
||||
final update = AnalyticsStreamUpdate(blockedConstruct: constructId);
|
||||
constructUpdateStream.add(update);
|
||||
}
|
||||
|
||||
void _onNewConstruct(Set<ConstructIdentifier> constructIds) {
|
||||
if (constructIds.isEmpty) return;
|
||||
newConstructsStream.add(constructIds);
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@ class XPGainedEvent extends AnalyticsUpdateEvent {
|
|||
XPGainedEvent(this.points, this.targetID);
|
||||
}
|
||||
|
||||
class ConstructBlockedEvent extends AnalyticsUpdateEvent {
|
||||
final ConstructIdentifier blockedConstruct;
|
||||
ConstructBlockedEvent(this.blockedConstruct);
|
||||
}
|
||||
|
||||
class NewConstructsEvent extends AnalyticsUpdateEvent {
|
||||
final Set<ConstructIdentifier> newConstructs;
|
||||
NewConstructsEvent(this.newConstructs);
|
||||
|
|
|
|||
|
|
@ -127,9 +127,6 @@ class AnalyticsUpdateService {
|
|||
if (analyticsRoom == null) return;
|
||||
|
||||
await analyticsRoom.addActivityRoomId(roomId);
|
||||
if (lang.langCodeShort == _l2?.langCodeShort) {
|
||||
dataService.updateDispatcher.sendActivityAnalyticsUpdate(roomId);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> blockConstruct(ConstructIdentifier constructId) async {
|
||||
|
|
@ -143,7 +140,6 @@ class AnalyticsUpdateService {
|
|||
);
|
||||
|
||||
await analyticsRoom.setAnalyticsSettings(updated);
|
||||
await dataService.updateBlockedConstructs(constructId);
|
||||
}
|
||||
|
||||
Future<void> setLemmaInfo(
|
||||
|
|
@ -160,7 +156,6 @@ class AnalyticsUpdateService {
|
|||
meaning: meaning,
|
||||
);
|
||||
if (userLemmaInfo == updated) return;
|
||||
dataService.updateDispatcher.sendLemmaInfoUpdate(constructId, updated);
|
||||
|
||||
try {
|
||||
await analyticsRoom.setUserSetLemmaInfo(constructId, updated);
|
||||
|
|
|
|||
|
|
@ -538,6 +538,13 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
fcm_shared_isolate:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
path: "pangea_packages/fcm_shared_isolate"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -170,4 +170,6 @@ flutter:
|
|||
# 1. Don't do it if you can avoid it or fix it upstream in a manageable time
|
||||
# 2. Always link an (upstream?) issue
|
||||
# 3. Explain how and when this can be removed (overrides must be temporarily)
|
||||
dependency_overrides:
|
||||
dependency_overrides:
|
||||
fcm_shared_isolate:
|
||||
path: pangea_packages/fcm_shared_isolate
|
||||
Loading…
Add table
Reference in a new issue