resolve merge conflicts
This commit is contained in:
commit
abab3923d9
20 changed files with 348 additions and 389 deletions
|
|
@ -4990,5 +4990,6 @@
|
|||
}
|
||||
},
|
||||
"pickDifferentActivity": "Pick a different activity",
|
||||
"messageLanguageMismatchMessage": "Your target language doesn't match this message. Update your target language?"
|
||||
"messageLanguageMismatchMessage": "Your target language doesn't match this message. Update your target language?",
|
||||
"blockLemmaConfirmation": "This vocab word will be permanently removed from your analytics"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
|||
import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/level_up/level_up_banner.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/message_analytics_feedback.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/bot/utils/bot_name.dart';
|
||||
import 'package:fluffychat/pangea/chat/utils/unlocked_morphs_snackbar.dart';
|
||||
import 'package:fluffychat/pangea/chat/widgets/event_too_large_dialog.dart';
|
||||
|
|
@ -471,7 +470,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
|
||||
void _onAnalyticsUpdate(AnalyticsStreamUpdate update) {
|
||||
if (update.targetID != null) {
|
||||
OverlayUtil.showPointsGained(update.targetID!, context);
|
||||
OverlayUtil.showPointsGained(update.targetID!, update.points, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2107,14 +2106,11 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
];
|
||||
|
||||
_showAnalyticsFeedback(constructs, eventId);
|
||||
|
||||
pangeaController.putAnalytics.setState(
|
||||
AnalyticsStream(
|
||||
eventId: eventId,
|
||||
targetID: eventId,
|
||||
roomId: room.id,
|
||||
constructs: constructs,
|
||||
),
|
||||
pangeaController.putAnalytics.addAnalytics(
|
||||
constructs,
|
||||
eventId: eventId,
|
||||
targetId: eventId,
|
||||
roomId: room.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2161,13 +2157,11 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
if (constructs.isEmpty) return;
|
||||
|
||||
_showAnalyticsFeedback(constructs, eventId);
|
||||
MatrixState.pangeaController.putAnalytics.setState(
|
||||
AnalyticsStream(
|
||||
eventId: eventId,
|
||||
targetID: eventId,
|
||||
roomId: room.id,
|
||||
constructs: constructs,
|
||||
),
|
||||
MatrixState.pangeaController.putAnalytics.addAnalytics(
|
||||
constructs,
|
||||
eventId: eventId,
|
||||
targetId: eventId,
|
||||
roomId: room.id,
|
||||
);
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -2312,6 +2306,36 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onLeave() async {
|
||||
final parentSpaceId = room.courseParent?.id;
|
||||
final confirmed = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).areYouSure,
|
||||
message: L10n.of(context).leaveRoomDescription,
|
||||
okLabel: L10n.of(context).leave,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
isDestructive: true,
|
||||
);
|
||||
if (confirmed != OkCancelResult.ok) return;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: widget.room.leave,
|
||||
);
|
||||
|
||||
if (result.isError) return;
|
||||
final r = Matrix.of(context).client.getRoomById(widget.room.id);
|
||||
if (r != null && r.membership != Membership.leave) {
|
||||
await Matrix.of(context).client.waitForRoomInSync(
|
||||
widget.room.id,
|
||||
leave: true,
|
||||
);
|
||||
}
|
||||
|
||||
context.go(
|
||||
parentSpaceId != null ? '/rooms/spaces/$parentSpaceId' : '/rooms',
|
||||
);
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
late final ValueNotifier<bool> _displayChatDetailsColumn;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,10 @@ class ChatView extends StatelessWidget {
|
|||
if (controller.room.showActivityChatUI) {
|
||||
return [
|
||||
ActivityMenuButton(controller: controller),
|
||||
ActivitySessionPopupMenu(controller.room),
|
||||
ActivitySessionPopupMenu(
|
||||
controller.room,
|
||||
onLeave: controller.onLeave,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,14 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pages/chat_details/chat_download_provider.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
|
||||
enum ActivityPopupMenuActions { invite, leave, download }
|
||||
|
||||
class ActivitySessionPopupMenu extends StatefulWidget {
|
||||
final Room room;
|
||||
final VoidCallback onLeave;
|
||||
|
||||
const ActivitySessionPopupMenu(this.room, {super.key});
|
||||
const ActivitySessionPopupMenu(this.room, {required this.onLeave, super.key});
|
||||
|
||||
@override
|
||||
ActivitySessionPopupMenuState createState() =>
|
||||
|
|
@ -30,28 +29,7 @@ class ActivitySessionPopupMenuState extends State<ActivitySessionPopupMenu>
|
|||
onSelected: (choice) async {
|
||||
switch (choice) {
|
||||
case ActivityPopupMenuActions.leave:
|
||||
final parentSpaceId = widget.room.courseParent?.id;
|
||||
final router = GoRouter.of(context);
|
||||
final confirmed = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).areYouSure,
|
||||
message: L10n.of(context).leaveRoomDescription,
|
||||
okLabel: L10n.of(context).leave,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
isDestructive: true,
|
||||
);
|
||||
if (confirmed != OkCancelResult.ok) return;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => widget.room.leave(),
|
||||
);
|
||||
if (result.error == null) {
|
||||
router.go(
|
||||
parentSpaceId != null
|
||||
? '/rooms/spaces/$parentSpaceId'
|
||||
: '/rooms',
|
||||
);
|
||||
}
|
||||
widget.onLeave();
|
||||
break;
|
||||
case ActivityPopupMenuActions.invite:
|
||||
context.go(
|
||||
|
|
|
|||
|
|
@ -135,6 +135,14 @@ class ConstructListModel {
|
|||
level = calculateLevelWithXp(totalXP);
|
||||
}
|
||||
|
||||
void deleteConstruct(ConstructIdentifier constructId, int offset) {
|
||||
_uses.removeWhere((use) => use.identifier == constructId);
|
||||
_constructMap.removeWhere(
|
||||
(key, value) => value.id == constructId,
|
||||
);
|
||||
updateConstructs([], offset);
|
||||
}
|
||||
|
||||
List<ConstructUses> constructList({ConstructTypeEnum? type}) => _constructList
|
||||
.where(
|
||||
(constructUse) => type == null || constructUse.constructType == type,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
|||
import 'package:fluffychat/pangea/analytics_misc/constructs_event.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/analytics_settings/analytics_settings_extension.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/local.key.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/base_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
|
|
@ -84,6 +85,12 @@ class GetAnalyticsController extends BaseController {
|
|||
.putAnalytics.analyticsUpdateStream.stream
|
||||
.listen(_onAnalyticsUpdate);
|
||||
|
||||
_pangeaController.putAnalytics.savedActivitiesNotifier
|
||||
.addListener(_onActivityAnalyticsUpdate);
|
||||
|
||||
_pangeaController.putAnalytics.blockedConstructsNotifier
|
||||
.addListener(_onBlockedConstructsUpdate);
|
||||
|
||||
// When a newly-joined space comes through in a sync
|
||||
// update, add the analytics rooms to the space
|
||||
_joinSpaceSubscription ??= _client.onSync.stream
|
||||
|
|
@ -95,6 +102,20 @@ class GetAnalyticsController extends BaseController {
|
|||
|
||||
final offset =
|
||||
_pangeaController.userController.analyticsProfile?.xpOffset ?? 0;
|
||||
|
||||
final allUses = [
|
||||
...(_getConstructsLocal() ?? []),
|
||||
..._locallyCachedConstructs,
|
||||
];
|
||||
|
||||
final Room? analyticsRoom = _client.analyticsRoomLocal(_l2!);
|
||||
final blockedLemmas = analyticsRoom?.analyticsSettings?.blockedConstructs;
|
||||
if (blockedLemmas != null && blockedLemmas.isNotEmpty) {
|
||||
allUses.removeWhere(
|
||||
(use) => blockedLemmas.contains(use.identifier),
|
||||
);
|
||||
}
|
||||
|
||||
constructListModel.updateConstructs(
|
||||
[
|
||||
...(_getConstructsLocal() ?? []),
|
||||
|
|
@ -109,11 +130,7 @@ class GetAnalyticsController extends BaseController {
|
|||
data: {},
|
||||
);
|
||||
} finally {
|
||||
_updateAnalyticsStream(
|
||||
type: AnalyticsUpdateType.init,
|
||||
points: 0,
|
||||
newConstructs: [],
|
||||
);
|
||||
_updateAnalyticsStream(AnalyticsStreamUpdate());
|
||||
if (!initCompleter.isCompleted) initCompleter.complete();
|
||||
_initializing = false;
|
||||
}
|
||||
|
|
@ -128,23 +145,16 @@ class GetAnalyticsController extends BaseController {
|
|||
_joinSpaceSubscription?.cancel();
|
||||
_joinSpaceSubscription = null;
|
||||
initCompleter = Completer<void>();
|
||||
_pangeaController.putAnalytics.savedActivitiesNotifier
|
||||
.removeListener(_onActivityAnalyticsUpdate);
|
||||
_pangeaController.putAnalytics.blockedConstructsNotifier
|
||||
.removeListener(_onBlockedConstructsUpdate);
|
||||
_cache.clear();
|
||||
// perMessage.dispose();
|
||||
}
|
||||
|
||||
Future<void> _onAnalyticsUpdate(
|
||||
AnalyticsUpdate analyticsUpdate,
|
||||
) async {
|
||||
final validTypes = [AnalyticsUpdateType.local, AnalyticsUpdateType.server];
|
||||
if (!validTypes.contains(analyticsUpdate.type)) {
|
||||
_updateAnalyticsStream(
|
||||
type: analyticsUpdate.type,
|
||||
points: 0,
|
||||
newConstructs: [],
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (analyticsUpdate.isLogout) return;
|
||||
|
||||
final oldLevel = constructListModel.level;
|
||||
|
|
@ -159,9 +169,6 @@ class GetAnalyticsController extends BaseController {
|
|||
)
|
||||
.toSet();
|
||||
|
||||
final prevUnlockedVocab =
|
||||
constructListModel.unlockedLemmas(ConstructTypeEnum.vocab).toSet();
|
||||
|
||||
constructListModel.updateConstructs(analyticsUpdate.newConstructs, offset);
|
||||
|
||||
final newUnlockedMorphs = constructListModel
|
||||
|
|
@ -172,11 +179,6 @@ class GetAnalyticsController extends BaseController {
|
|||
.toSet()
|
||||
.difference(prevUnlockedMorphs);
|
||||
|
||||
final newUnlockedVocab = constructListModel
|
||||
.unlockedLemmas(ConstructTypeEnum.vocab)
|
||||
.toSet()
|
||||
.difference(prevUnlockedVocab);
|
||||
|
||||
if (analyticsUpdate.type == AnalyticsUpdateType.server) {
|
||||
await _getConstructs(forceUpdate: true);
|
||||
}
|
||||
|
|
@ -192,13 +194,13 @@ class GetAnalyticsController extends BaseController {
|
|||
_onUnlockMorphLemmas(newUnlockedMorphs);
|
||||
}
|
||||
_updateAnalyticsStream(
|
||||
type: analyticsUpdate.type,
|
||||
points: analyticsUpdate.newConstructs.fold<int>(
|
||||
0,
|
||||
(previousValue, element) => previousValue + element.xp,
|
||||
AnalyticsStreamUpdate(
|
||||
points: analyticsUpdate.newConstructs.fold<int>(
|
||||
0,
|
||||
(previousValue, element) => previousValue + element.xp,
|
||||
),
|
||||
targetID: analyticsUpdate.targetID,
|
||||
),
|
||||
targetID: analyticsUpdate.targetID,
|
||||
newConstructs: [...newUnlockedMorphs, ...newUnlockedVocab],
|
||||
);
|
||||
// Update public profile each time that new analytics are added.
|
||||
// If the level hasn't changed, this will not send an update to the server.
|
||||
|
|
@ -209,20 +211,8 @@ class GetAnalyticsController extends BaseController {
|
|||
);
|
||||
}
|
||||
|
||||
void _updateAnalyticsStream({
|
||||
required AnalyticsUpdateType type,
|
||||
required int points,
|
||||
required List<ConstructIdentifier> newConstructs,
|
||||
String? targetID,
|
||||
}) =>
|
||||
analyticsStream.add(
|
||||
AnalyticsStreamUpdate(
|
||||
type: type,
|
||||
points: points,
|
||||
newConstructs: newConstructs,
|
||||
targetID: targetID,
|
||||
),
|
||||
);
|
||||
void _updateAnalyticsStream(AnalyticsStreamUpdate update) =>
|
||||
analyticsStream.add(update);
|
||||
|
||||
void _onLevelUp(final int lowerLevel, final int upperLevel) {
|
||||
setState({
|
||||
|
|
@ -253,6 +243,21 @@ class GetAnalyticsController extends BaseController {
|
|||
setState({'unlocked_constructs': filtered});
|
||||
}
|
||||
|
||||
void _onActivityAnalyticsUpdate() =>
|
||||
_updateAnalyticsStream(AnalyticsStreamUpdate());
|
||||
|
||||
void _onBlockedConstructsUpdate() {
|
||||
final constructId =
|
||||
_pangeaController.putAnalytics.blockedConstructsNotifier.value;
|
||||
if (constructId == null) return;
|
||||
|
||||
constructListModel.deleteConstruct(
|
||||
constructId,
|
||||
_pangeaController.userController.analyticsProfile?.xpOffset ?? 0,
|
||||
);
|
||||
_updateAnalyticsStream(AnalyticsStreamUpdate());
|
||||
}
|
||||
|
||||
/// A local cache of eventIds and construct uses for messages sent since the last update.
|
||||
/// It's a map of eventIDs to a list of OneConstructUses. Not just a list of OneConstructUses
|
||||
/// because, with practice activity constructs, we might need to add to the list for a given
|
||||
|
|
@ -286,8 +291,7 @@ class GetAnalyticsController extends BaseController {
|
|||
return formattedCache;
|
||||
} catch (err) {
|
||||
// if something goes wrong while trying to format the local data, clear it
|
||||
_pangeaController.putAnalytics
|
||||
.clearMessagesSinceUpdate(clearDrafts: true);
|
||||
clearMessagesCache();
|
||||
return {};
|
||||
}
|
||||
} catch (exception, stackTrace) {
|
||||
|
|
@ -471,19 +475,6 @@ class GetAnalyticsController extends BaseController {
|
|||
return newConstructCount;
|
||||
}
|
||||
|
||||
// Future<GenerateConstructSummaryResult?>
|
||||
// _generateLevelUpAnalyticsAndSaveToStateEvent(
|
||||
// final int lowerLevel,
|
||||
// final int upperLevel,
|
||||
// ) async {
|
||||
// // generate level up analytics as a construct summary
|
||||
// ConstructSummary summary;
|
||||
// try {
|
||||
// final int maxXP = constructListModel.calculateXpWithLevel(upperLevel);
|
||||
// final int minXP = constructListModel.calculateXpWithLevel(lowerLevel);
|
||||
// int diffXP = maxXP - minXP;
|
||||
// if (diffXP < 0) diffXP = 0;
|
||||
|
||||
ConstructSummary? getConstructSummaryFromStateEvent() {
|
||||
try {
|
||||
final Room? analyticsRoom = _client.analyticsRoomLocal(_l2!);
|
||||
|
|
@ -649,15 +640,11 @@ class AnalyticsCacheEntry {
|
|||
}
|
||||
|
||||
class AnalyticsStreamUpdate {
|
||||
final AnalyticsUpdateType type;
|
||||
final int points;
|
||||
final List<ConstructIdentifier> newConstructs;
|
||||
final String? targetID;
|
||||
|
||||
AnalyticsStreamUpdate({
|
||||
required this.type,
|
||||
required this.points,
|
||||
required this.newConstructs,
|
||||
this.points = 0,
|
||||
this.targetID,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
|
|
@ -28,27 +27,27 @@ mixin LemmaEmojiSetter {
|
|||
String? roomId,
|
||||
String? targetId,
|
||||
}) {
|
||||
MatrixState.pangeaController.putAnalytics.setState(
|
||||
AnalyticsStream(
|
||||
eventId: eventId,
|
||||
roomId: roomId,
|
||||
targetID: targetId,
|
||||
constructs: [
|
||||
OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.em,
|
||||
lemma: constructId.lemma,
|
||||
constructType: constructId.type,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: roomId,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: eventId,
|
||||
),
|
||||
category: constructId.category,
|
||||
form: constructId.lemma,
|
||||
xp: ConstructUseTypeEnum.em.pointValue,
|
||||
),
|
||||
],
|
||||
final constructs = [
|
||||
OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.em,
|
||||
lemma: constructId.lemma,
|
||||
constructType: constructId.type,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: roomId,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: eventId,
|
||||
),
|
||||
category: constructId.category,
|
||||
form: constructId.lemma,
|
||||
xp: ConstructUseTypeEnum.em.pointValue,
|
||||
),
|
||||
];
|
||||
|
||||
MatrixState.pangeaController.putAnalytics.addAnalytics(
|
||||
constructs,
|
||||
eventId: eventId,
|
||||
roomId: roomId,
|
||||
targetId: targetId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,27 +5,31 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/base_controller.dart';
|
||||
import 'package:fluffychat/pangea/analytics_settings/analytics_settings_extension.dart';
|
||||
import 'package:fluffychat/pangea/analytics_settings/analytics_settings_model.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/languages/language_model.dart';
|
||||
import 'package:fluffychat/pangea/user/user_controller.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
enum AnalyticsUpdateType { server, local, activities, init }
|
||||
enum AnalyticsUpdateType { server, local }
|
||||
|
||||
/// handles the processing of analytics for
|
||||
/// 1) messages sent by the user and
|
||||
/// 2) constructs used by the user, both in sending messages and doing practice activities
|
||||
class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
||||
class PutAnalyticsController {
|
||||
late PangeaController _pangeaController;
|
||||
StreamController<AnalyticsUpdate> analyticsUpdateStream =
|
||||
StreamController.broadcast();
|
||||
|
||||
StreamSubscription<AnalyticsStream>? _analyticsStream;
|
||||
ValueNotifier<List<String>> savedActivitiesNotifier = ValueNotifier([]);
|
||||
ValueNotifier<ConstructIdentifier?> blockedConstructsNotifier =
|
||||
ValueNotifier(null);
|
||||
|
||||
StreamSubscription? _languageStream;
|
||||
Timer? _updateTimer;
|
||||
|
||||
|
|
@ -53,31 +57,19 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
}
|
||||
|
||||
void initialize() {
|
||||
// Listen for calls to setState on the analytics stream
|
||||
// and update the analytics room if necessary
|
||||
_analyticsStream ??=
|
||||
stateStream.listen((data) => _onNewAnalyticsData(data));
|
||||
|
||||
// Listen for changes to the user's language settings
|
||||
_languageStream ??=
|
||||
_pangeaController.userController.languageStream.stream.listen((update) {
|
||||
_onUpdateLanguages(update.prevTargetLang);
|
||||
});
|
||||
|
||||
_languageStream ??= _pangeaController.userController.languageStream.stream
|
||||
.listen(_onUpdateLanguages);
|
||||
_refreshAnalyticsIfOutdated();
|
||||
}
|
||||
|
||||
/// Reset analytics last updated time to null.
|
||||
@override
|
||||
void dispose() {
|
||||
_updateTimer?.cancel();
|
||||
lastUpdated = null;
|
||||
lastUpdatedCompleter = Completer<DateTime?>();
|
||||
_analyticsStream?.cancel();
|
||||
_analyticsStream = null;
|
||||
_languageStream?.cancel();
|
||||
_languageStream = null;
|
||||
clearMessagesSinceUpdate();
|
||||
MatrixState.pangeaController.getAnalytics.clearMessagesCache();
|
||||
}
|
||||
|
||||
/// If analytics haven't been updated in the last day, update them
|
||||
|
|
@ -112,137 +104,18 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
/// Given new construct uses, format and cache
|
||||
/// the data locally and reset the update timer
|
||||
/// Decide whether to update the analytics room
|
||||
void _onNewAnalyticsData(AnalyticsStream data) {
|
||||
final String? eventID = data.eventId;
|
||||
final String? roomID = data.roomId;
|
||||
|
||||
final List<OneConstructUse> constructs = [];
|
||||
// if (roomID != null) {
|
||||
// constructs = _getDraftUses(roomID);
|
||||
// }
|
||||
|
||||
constructs.addAll(data.constructs);
|
||||
|
||||
if (kDebugMode) {
|
||||
for (final use in constructs) {
|
||||
debugPrint(
|
||||
"_onNewAnalyticsData filtered use: ${use.constructType.string} ${use.useType.string} ${use.lemma} ${use.xp}",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void addAnalytics(
|
||||
List<OneConstructUse> constructs, {
|
||||
String? eventId,
|
||||
String? roomId,
|
||||
String? targetId,
|
||||
}) {
|
||||
final level = _pangeaController.getAnalytics.constructListModel.level;
|
||||
|
||||
_addLocalMessage(eventID, constructs).then(
|
||||
(_) {
|
||||
if (roomID != null) _clearDraftUses(roomID);
|
||||
_decideWhetherToUpdateAnalyticsRoom(
|
||||
level,
|
||||
data.targetID,
|
||||
data.constructs,
|
||||
);
|
||||
},
|
||||
_addLocalMessage(eventId, constructs).then(
|
||||
(_) => _sendAnalytics(level, targetId, constructs),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onUpdateLanguages(LanguageModel? previousL2) async {
|
||||
await sendLocalAnalyticsToAnalyticsRoom(
|
||||
l2Override: previousL2,
|
||||
);
|
||||
_pangeaController.resetAnalytics().then((_) {
|
||||
final level = _pangeaController.getAnalytics.constructListModel.level;
|
||||
_pangeaController.userController.updateAnalyticsProfile(level: level);
|
||||
});
|
||||
}
|
||||
|
||||
// void addDraftUses(
|
||||
// List<PangeaToken> tokens,
|
||||
// String roomID,
|
||||
// ConstructUseTypeEnum useType, {
|
||||
// String? targetID,
|
||||
// }) {
|
||||
// final metadata = ConstructUseMetaData(
|
||||
// roomId: roomID,
|
||||
// timeStamp: DateTime.now(),
|
||||
// );
|
||||
|
||||
// // we only save those with saveVocab == true
|
||||
// final tokensToSave =
|
||||
// tokens.where((token) => token.lemma.saveVocab).toList();
|
||||
|
||||
// // get all our vocab constructs
|
||||
// final uses = tokensToSave
|
||||
// .map(
|
||||
// (token) => OneConstructUse(
|
||||
// useType: useType,
|
||||
// lemma: token.lemma.text,
|
||||
// form: token.text.content,
|
||||
// constructType: ConstructTypeEnum.vocab,
|
||||
// metadata: metadata,
|
||||
// category: token.pos,
|
||||
// ),
|
||||
// )
|
||||
// .toList();
|
||||
|
||||
// // get all our grammar constructs
|
||||
// for (final token in tokensToSave) {
|
||||
// uses.add(
|
||||
// OneConstructUse(
|
||||
// useType: useType,
|
||||
// lemma: token.pos,
|
||||
// form: token.text.content,
|
||||
// category: "POS",
|
||||
// constructType: ConstructTypeEnum.morph,
|
||||
// metadata: metadata,
|
||||
// ),
|
||||
// );
|
||||
// for (final entry in token.morph.entries) {
|
||||
// uses.add(
|
||||
// OneConstructUse(
|
||||
// useType: useType,
|
||||
// lemma: entry.value,
|
||||
// form: token.text.content,
|
||||
// category: entry.key,
|
||||
// constructType: ConstructTypeEnum.morph,
|
||||
// metadata: metadata,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (kDebugMode) {
|
||||
// for (final use in uses) {
|
||||
// debugPrint(
|
||||
// "Draft use: ${use.constructType.string} ${use.useType.string} ${use.lemma} ${use.useType.pointValue}",
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// final level = _pangeaController.getAnalytics.constructListModel.level;
|
||||
|
||||
// // the list 'uses' gets altered in the _addLocalMessage method,
|
||||
// // so copy it here to that the list of new uses is accurate
|
||||
// final List<OneConstructUse> newUses = List.from(uses);
|
||||
// _addLocalMessage('draft$roomID', uses).then(
|
||||
// (_) => _decideWhetherToUpdateAnalyticsRoom(
|
||||
// level,
|
||||
// targetID,
|
||||
// newUses,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
// List<OneConstructUse> _getDraftUses(String roomID) {
|
||||
// final currentCache = _pangeaController.getAnalytics.messagesSinceUpdate;
|
||||
// return currentCache['draft$roomID'] ?? [];
|
||||
// }
|
||||
|
||||
void _clearDraftUses(String roomID) {
|
||||
final currentCache = _pangeaController.getAnalytics.messagesSinceUpdate;
|
||||
currentCache.remove('draft$roomID');
|
||||
_setMessagesSinceUpdate(currentCache);
|
||||
}
|
||||
|
||||
/// Add a list of construct uses for a new message to the local
|
||||
/// cache of recently sent messages
|
||||
Future<void> _addLocalMessage(
|
||||
|
|
@ -255,7 +128,7 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
|
||||
// if this is not a draft message, add the eventId to the metadata
|
||||
// if it's missing (it will be missing for draft constructs)
|
||||
if (cacheKey != null && !cacheKey.startsWith('draft')) {
|
||||
if (cacheKey != null) {
|
||||
constructs = constructs.map((construct) {
|
||||
if (construct.metadata.eventId != null) return construct;
|
||||
construct.metadata.eventId = cacheKey;
|
||||
|
|
@ -283,7 +156,7 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
/// If the addition brought the total number of messages in the cache
|
||||
/// to the max, or if the addition triggered a level-up, update the analytics.
|
||||
/// Otherwise, add a local update to the alert stream.
|
||||
void _decideWhetherToUpdateAnalyticsRoom(
|
||||
void _sendAnalytics(
|
||||
int prevLevel,
|
||||
String? targetID,
|
||||
List<OneConstructUse> newConstructs,
|
||||
|
|
@ -311,25 +184,14 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
);
|
||||
}
|
||||
|
||||
/// Clears the local cache of recently sent constructs. Called before updating analytics
|
||||
void clearMessagesSinceUpdate({clearDrafts = false}) {
|
||||
if (clearDrafts) {
|
||||
MatrixState.pangeaController.getAnalytics.clearMessagesCache();
|
||||
return;
|
||||
}
|
||||
|
||||
final localCache = _pangeaController.getAnalytics.messagesSinceUpdate;
|
||||
final draftKeys = localCache.keys.where((key) => key.startsWith('draft'));
|
||||
if (draftKeys.isEmpty) {
|
||||
MatrixState.pangeaController.getAnalytics.clearMessagesCache();
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, List<OneConstructUse>> newCache = {};
|
||||
for (final key in draftKeys) {
|
||||
newCache[key] = localCache[key]!;
|
||||
}
|
||||
_setMessagesSinceUpdate(newCache);
|
||||
Future<void> _onUpdateLanguages(LanguageUpdate update) async {
|
||||
await sendLocalAnalyticsToAnalyticsRoom(
|
||||
l2Override: update.prevTargetLang,
|
||||
);
|
||||
_pangeaController.resetAnalytics().then((_) {
|
||||
final level = _pangeaController.getAnalytics.constructListModel.level;
|
||||
_pangeaController.userController.updateAnalyticsProfile(level: level);
|
||||
});
|
||||
}
|
||||
|
||||
/// Save the local cache of recently sent constructs to the local storage
|
||||
|
|
@ -369,7 +231,7 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
_updateCompleter = Completer<void>();
|
||||
try {
|
||||
await _updateAnalytics(l2Override: l2Override);
|
||||
clearMessagesSinceUpdate();
|
||||
MatrixState.pangeaController.getAnalytics.clearMessagesCache();
|
||||
|
||||
lastUpdated = DateTime.now();
|
||||
analyticsUpdateStream.add(
|
||||
|
|
@ -425,48 +287,34 @@ class PutAnalyticsController extends BaseController<AnalyticsStream> {
|
|||
);
|
||||
if (analyticsRoom == null) return;
|
||||
await analyticsRoom.addActivityRoomId(roomId);
|
||||
|
||||
analyticsUpdateStream.add(
|
||||
AnalyticsUpdate(
|
||||
AnalyticsUpdateType.activities,
|
||||
[],
|
||||
),
|
||||
);
|
||||
savedActivitiesNotifier.value = analyticsRoom.activityRoomIds;
|
||||
}
|
||||
|
||||
Future<void> removeActivityAnalytics(String roomId) async {
|
||||
if (_client.userID == null) return;
|
||||
Future<void> blockConstruct(ConstructIdentifier constructId) async {
|
||||
if (_pangeaController.matrixState.client.userID == null) return;
|
||||
if (_pangeaController.userController.userL2 == null) return;
|
||||
|
||||
final Room? analyticsRoom = await _client.getMyAnalyticsRoom(
|
||||
_pangeaController.userController.userL2!,
|
||||
);
|
||||
if (analyticsRoom == null) return;
|
||||
await analyticsRoom.removeActivityRoomId(roomId);
|
||||
analyticsUpdateStream.add(
|
||||
AnalyticsUpdate(
|
||||
AnalyticsUpdateType.activities,
|
||||
[],
|
||||
),
|
||||
|
||||
final current = analyticsRoom.analyticsSettings ??
|
||||
const AnalyticsSettingsModel(blockedConstructs: {});
|
||||
|
||||
final blockedConstructs = current.blockedConstructs;
|
||||
final updated = current.copyWith(
|
||||
blockedConstructs: {
|
||||
...blockedConstructs,
|
||||
constructId,
|
||||
},
|
||||
);
|
||||
|
||||
await analyticsRoom.setAnalyticsSettings(updated);
|
||||
blockedConstructsNotifier.value = constructId;
|
||||
}
|
||||
}
|
||||
|
||||
class AnalyticsStream {
|
||||
final String? eventId;
|
||||
final String? roomId;
|
||||
final String? targetID;
|
||||
|
||||
final List<OneConstructUse> constructs;
|
||||
|
||||
AnalyticsStream({
|
||||
required this.eventId,
|
||||
required this.roomId,
|
||||
required this.constructs,
|
||||
this.targetID,
|
||||
});
|
||||
}
|
||||
|
||||
class AnalyticsUpdate {
|
||||
final AnalyticsUpdateType type;
|
||||
final List<OneConstructUse> newConstructs;
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@ import 'package:go_router/go_router.dart';
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/activity_archive.dart';
|
||||
import 'package:fluffychat/pangea/analytics_page/analytics_page_constants.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/level_dialog_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class AnalyticsPage extends StatelessWidget {
|
||||
|
|
@ -28,18 +30,48 @@ class AnalyticsPage extends StatelessWidget {
|
|||
this.isSidebar = false,
|
||||
});
|
||||
|
||||
Future<void> _blockLemma(BuildContext context) async {
|
||||
final resp = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).areYouSure,
|
||||
message: L10n.of(context).blockLemmaConfirmation,
|
||||
isDestructive: true,
|
||||
);
|
||||
|
||||
if (resp != OkCancelResult.ok) return;
|
||||
final res = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () =>
|
||||
MatrixState.pangeaController.putAnalytics.blockConstruct(construct!),
|
||||
);
|
||||
|
||||
if (!res.isError) {
|
||||
context.go("/rooms/analytics/${ConstructTypeEnum.vocab.name}");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final analyticsRoomId = GoRouterState.of(context).pathParameters['roomid'];
|
||||
return Scaffold(
|
||||
appBar: construct != null ? AppBar() : null,
|
||||
appBar: construct != null
|
||||
? AppBar(
|
||||
actions: indicator == ProgressIndicatorEnum.wordsUsed
|
||||
? [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_forever_outlined),
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
tooltip: L10n.of(context).delete,
|
||||
onPressed: () => _blockLemma(context),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
)
|
||||
: null,
|
||||
body: SafeArea(
|
||||
child: StreamBuilder(
|
||||
stream: MatrixState
|
||||
.pangeaController.getAnalytics.analyticsStream.stream
|
||||
.where(
|
||||
(u) => u.type == AnalyticsUpdateType.init,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future:
|
||||
MatrixState.pangeaController.getAnalytics.initCompleter.future,
|
||||
builder: (context, snapshot) {
|
||||
return Padding(
|
||||
padding: const EdgeInsetsGeometry.all(16.0),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_settings/analytics_settings_model.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
|
||||
extension AnalyticsSettingsRoomExtension on Room {
|
||||
AnalyticsSettingsModel? get analyticsSettings {
|
||||
final event = getState(PangeaEventTypes.analyticsSettings);
|
||||
if (event == null) return null;
|
||||
return AnalyticsSettingsModel.fromJson(event.content);
|
||||
}
|
||||
|
||||
Future<void> setAnalyticsSettings(
|
||||
AnalyticsSettingsModel settings,
|
||||
) async {
|
||||
await client.setRoomStateWithKey(
|
||||
id,
|
||||
PangeaEventTypes.analyticsSettings,
|
||||
"",
|
||||
settings.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
36
lib/pangea/analytics_settings/analytics_settings_model.dart
Normal file
36
lib/pangea/analytics_settings/analytics_settings_model.dart
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
|
||||
class AnalyticsSettingsModel {
|
||||
final Set<ConstructIdentifier> blockedConstructs;
|
||||
|
||||
const AnalyticsSettingsModel({
|
||||
required this.blockedConstructs,
|
||||
});
|
||||
|
||||
AnalyticsSettingsModel copyWith({
|
||||
Set<ConstructIdentifier>? blockedConstructs,
|
||||
}) {
|
||||
return AnalyticsSettingsModel(
|
||||
blockedConstructs: blockedConstructs ?? this.blockedConstructs,
|
||||
);
|
||||
}
|
||||
|
||||
factory AnalyticsSettingsModel.fromJson(Map<String, dynamic> json) {
|
||||
final blockedConstructs = <ConstructIdentifier>{};
|
||||
if (json['blocked_constructs'] != null) {
|
||||
final lemmas = json['blocked_constructs'] as List<dynamic>;
|
||||
for (final lemma in lemmas) {
|
||||
blockedConstructs.add(ConstructIdentifier.fromJson(lemma));
|
||||
}
|
||||
}
|
||||
return AnalyticsSettingsModel(
|
||||
blockedConstructs: blockedConstructs,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'blocked_constructs': blockedConstructs.map((c) => c.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -51,11 +51,11 @@ class LearningProgressIndicatorsState
|
|||
// if getAnalytics has already finished initializing,
|
||||
// the data is loaded and should be displayed.
|
||||
if (MatrixState.pangeaController.getAnalytics.initCompleter.isCompleted) {
|
||||
updateData(null);
|
||||
updateData();
|
||||
}
|
||||
_analyticsSubscription = MatrixState
|
||||
.pangeaController.getAnalytics.analyticsStream.stream
|
||||
.listen(updateData);
|
||||
.listen((_) => updateData());
|
||||
|
||||
// rebuild when target language changes
|
||||
_languageSubscription = MatrixState
|
||||
|
|
@ -71,10 +71,11 @@ class LearningProgressIndicatorsState
|
|||
_analyticsSubscription = null;
|
||||
_languageSubscription?.cancel();
|
||||
_languageSubscription = null;
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void updateData(AnalyticsStreamUpdate? _) {
|
||||
void updateData() {
|
||||
if (_loading) _loading = false;
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ import 'package:get_storage/get_storage.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/utils/bot_client_extension.dart';
|
||||
|
|
@ -127,6 +130,19 @@ class PangeaController {
|
|||
if (exclude.contains(key)) continue;
|
||||
futures.add(GetStorage(key).erase());
|
||||
}
|
||||
|
||||
if (AppConfig.showedActivityMenu) {
|
||||
futures.add(
|
||||
SharedPreferences.getInstance().then((prefs) async {
|
||||
AppConfig.showedActivityMenu = false;
|
||||
prefs.setBool(
|
||||
SettingKeys.showedActivityMenu,
|
||||
AppConfig.showedActivityMenu,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await Future.wait(futures);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -289,6 +289,7 @@ class OverlayUtil {
|
|||
|
||||
static void showPointsGained(
|
||||
String targetId,
|
||||
int points,
|
||||
BuildContext context,
|
||||
) {
|
||||
showOverlay(
|
||||
|
|
@ -297,7 +298,7 @@ class OverlayUtil {
|
|||
targetAnchor: Alignment.bottomCenter,
|
||||
context: context,
|
||||
child: PointsGainedAnimation(
|
||||
points: 2,
|
||||
points: points,
|
||||
targetID: targetId,
|
||||
),
|
||||
transformTargetId: targetId,
|
||||
|
|
|
|||
|
|
@ -54,4 +54,6 @@ class PangeaEventTypes {
|
|||
static const courseUser = "p.course_user";
|
||||
static const teacherMode = "pangea.teacher_mode";
|
||||
static const courseChatList = "pangea.course_chat_list";
|
||||
|
||||
static const analyticsSettings = "pangea.analytics_settings";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class LemmaHighlightEmojiRowState extends State<LemmaHighlightEmojiRow>
|
|||
|
||||
void _onAnalyticsUpdate(AnalyticsStreamUpdate update) {
|
||||
if (update.targetID != null) {
|
||||
OverlayUtil.showPointsGained(update.targetID!, context);
|
||||
OverlayUtil.showPointsGained(update.targetID!, update.points, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,17 +77,19 @@ class PracticeSelectionRepo {
|
|||
static PracticeSelection? _getCached(
|
||||
String eventId,
|
||||
) {
|
||||
for (final String key in _storage.getKeys()) {
|
||||
try {
|
||||
try {
|
||||
final keys = List.from(_storage.getKeys());
|
||||
for (final String key in keys) {
|
||||
final cacheEntry = _PracticeSelectionCacheEntry.fromJson(
|
||||
_storage.read(key),
|
||||
);
|
||||
if (cacheEntry.isExpired) {
|
||||
_storage.remove(key);
|
||||
}
|
||||
} catch (e) {
|
||||
_storage.remove(key);
|
||||
}
|
||||
} catch (e) {
|
||||
_storage.erase();
|
||||
return null;
|
||||
}
|
||||
|
||||
final entry = _storage.read(eventId);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import 'package:fluffychat/pages/chat/chat.dart';
|
|||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_representation_event.dart';
|
||||
|
|
@ -193,27 +192,26 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
setState(() {});
|
||||
if (selectedToken != null && isNewToken(selectedToken!)) {
|
||||
final token = selectedToken!;
|
||||
MatrixState.pangeaController.putAnalytics.setState(
|
||||
AnalyticsStream(
|
||||
eventId: event.eventId,
|
||||
roomId: event.room.id,
|
||||
constructs: [
|
||||
OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.click,
|
||||
lemma: token.lemma.text,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: event.room.id,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: event.eventId,
|
||||
),
|
||||
category: token.pos,
|
||||
form: token.text.content,
|
||||
xp: ConstructUseTypeEnum.click.pointValue,
|
||||
),
|
||||
],
|
||||
targetID: "word-zoom-card-${token.text.uniqueKey}",
|
||||
final constructs = [
|
||||
OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.click,
|
||||
lemma: token.lemma.text,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: event.room.id,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: event.eventId,
|
||||
),
|
||||
category: token.pos,
|
||||
form: token.text.content,
|
||||
xp: ConstructUseTypeEnum.click.pointValue,
|
||||
),
|
||||
];
|
||||
MatrixState.pangeaController.putAnalytics.addAnalytics(
|
||||
constructs,
|
||||
eventId: event.eventId,
|
||||
roomId: event.room.id,
|
||||
targetId: "word-zoom-card-${token.text.uniqueKey}",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import 'package:collection/collection.dart';
|
|||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
||||
|
|
@ -125,28 +124,28 @@ class PracticeController with ChangeNotifier {
|
|||
final constructUseType = _activity!.practiceTarget.record.responses.last
|
||||
.useType(_activity!.activityType);
|
||||
|
||||
MatrixState.pangeaController.putAnalytics.setState(
|
||||
AnalyticsStream(
|
||||
eventId: pangeaMessageEvent.eventId,
|
||||
roomId: pangeaMessageEvent.room.id,
|
||||
constructs: [
|
||||
OneConstructUse(
|
||||
useType: constructUseType,
|
||||
lemma: token.lemma.text,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: pangeaMessageEvent.room.id,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: pangeaMessageEvent.eventId,
|
||||
),
|
||||
category: token.pos,
|
||||
// in the case of a wrong answer, the cId doesn't match the token
|
||||
form: token.text.content,
|
||||
xp: constructUseType.pointValue,
|
||||
),
|
||||
],
|
||||
targetID: targetId,
|
||||
final constructs = [
|
||||
OneConstructUse(
|
||||
useType: constructUseType,
|
||||
lemma: token.lemma.text,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: pangeaMessageEvent.room.id,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: pangeaMessageEvent.eventId,
|
||||
),
|
||||
category: token.pos,
|
||||
// in the case of a wrong answer, the cId doesn't match the token
|
||||
form: token.text.content,
|
||||
xp: constructUseType.pointValue,
|
||||
),
|
||||
];
|
||||
|
||||
MatrixState.pangeaController.putAnalytics.addAnalytics(
|
||||
constructs,
|
||||
eventId: pangeaMessageEvent.eventId,
|
||||
roomId: pangeaMessageEvent.room.id,
|
||||
targetId: targetId,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ abstract class ClientManager {
|
|||
PangeaEventTypes.courseUser,
|
||||
PangeaEventTypes.teacherMode,
|
||||
PangeaEventTypes.courseChatList,
|
||||
PangeaEventTypes.analyticsSettings,
|
||||
// Pangea#
|
||||
},
|
||||
logLevel: kReleaseMode ? Level.warning : Level.verbose,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue