merge github-issues into auto-pr
This commit is contained in:
commit
70e085e4f0
22 changed files with 287 additions and 72 deletions
|
|
@ -3988,5 +3988,6 @@
|
|||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"messageAnalytics": "Message Analytics"
|
||||
}
|
||||
|
|
@ -549,6 +549,12 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
});
|
||||
|
||||
// #Pangea
|
||||
final List<String> edittingEvents = [];
|
||||
void clearEdittingEvent(String eventId) {
|
||||
edittingEvents.remove(eventId);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
// Future<void> send() async {
|
||||
// Original send function gets the tx id within the matrix lib,
|
||||
// but for choero, the tx id is generated before the message send.
|
||||
|
|
@ -591,6 +597,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
// editEventId: editEvent?.eventId,
|
||||
// parseCommands: parseCommands,
|
||||
// );
|
||||
final previousEdit = editEvent;
|
||||
room
|
||||
.pangeaSendTextEvent(
|
||||
sendController.text,
|
||||
|
|
@ -606,6 +613,13 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
)
|
||||
.then(
|
||||
(String? msgEventId) {
|
||||
// #Pangea
|
||||
setState(() {
|
||||
if (previousEdit != null) {
|
||||
edittingEvents.add(previousEdit.eventId);
|
||||
}
|
||||
});
|
||||
// Pangea#
|
||||
GoogleAnalytics.sendMessage(
|
||||
room.id,
|
||||
room.classCode,
|
||||
|
|
@ -628,6 +642,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
useType: useType ?? UseType.un,
|
||||
time: DateTime.now(),
|
||||
),
|
||||
isEdit: previousEdit != null,
|
||||
);
|
||||
|
||||
if (choreo != null &&
|
||||
|
|
@ -641,6 +656,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
...choreo.toGrammarConstructUse(msgEventId, room.id),
|
||||
],
|
||||
originalSent!.langCode,
|
||||
isEdit: previousEdit != null,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ class AudioPlayerWidget extends StatefulWidget {
|
|||
this.color = Colors.black,
|
||||
// #Pangea
|
||||
this.matrixFile,
|
||||
super.key,
|
||||
this.autoplay = false,
|
||||
// Pangea#
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -236,17 +236,6 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
|
|||
|
||||
late final List<int> waveform;
|
||||
|
||||
// #Pangea
|
||||
Future<void> _downloadMatrixFile() async {
|
||||
if (kIsWeb) return;
|
||||
final temp = await getTemporaryDirectory();
|
||||
final tempDir = temp;
|
||||
final file = File('${tempDir.path}/${widget.matrixFile!.name}');
|
||||
await file.writeAsBytes(widget.matrixFile!.bytes);
|
||||
audioFile = file;
|
||||
}
|
||||
|
||||
// Pangea#
|
||||
void _toggleSpeed() async {
|
||||
final audioPlayer = this.audioPlayer;
|
||||
if (audioPlayer == null) return;
|
||||
|
|
@ -268,6 +257,17 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
|
|||
setState(() {});
|
||||
}
|
||||
|
||||
// #Pangea
|
||||
Future<void> _downloadMatrixFile() async {
|
||||
if (kIsWeb) return;
|
||||
final temp = await getTemporaryDirectory();
|
||||
final tempDir = temp;
|
||||
final file = File('${tempDir.path}/${widget.matrixFile!.name}');
|
||||
await file.writeAsBytes(widget.matrixFile!.bytes);
|
||||
audioFile = file;
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:fluffychat/config/themes.dart';
|
|||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pangea/enum/use_type.dart';
|
||||
import 'package:fluffychat/pangea/models/language_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||
import 'package:fluffychat/utils/string_color.dart';
|
||||
|
|
@ -71,10 +72,21 @@ class Message extends StatelessWidget {
|
|||
super.key,
|
||||
});
|
||||
|
||||
// #Pangea
|
||||
PangeaMessageEvent? get pangeaMessageEvent =>
|
||||
controller.getPangeaMessageEvent(event.eventId);
|
||||
// Pangea#
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// #Pangea
|
||||
debugPrint('Message.build()');
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (controller.edittingEvents.contains(event.eventId)) {
|
||||
pangeaMessageEvent?.updateLatestEdit();
|
||||
controller.clearEdittingEvent(event.eventId);
|
||||
}
|
||||
});
|
||||
// Pangea#
|
||||
if (!{
|
||||
EventTypes.Message,
|
||||
|
|
|
|||
|
|
@ -27,10 +27,7 @@ class RecordingDialogState extends State<RecordingDialog> {
|
|||
|
||||
bool error = false;
|
||||
String? _recordedPath;
|
||||
// #Pangea
|
||||
// final _audioRecorder = Record();
|
||||
final _audioRecorder = AudioRecorder();
|
||||
// Pangea#
|
||||
final _audioRecorder = Record();
|
||||
final List<double> amplitudeTimeline = [];
|
||||
|
||||
static const int bitRate = 64000;
|
||||
|
|
@ -48,28 +45,11 @@ class RecordingDialogState extends State<RecordingDialog> {
|
|||
return;
|
||||
}
|
||||
await WakelockPlus.enable();
|
||||
|
||||
// We try to pick Opus where supported, since that is a codec optimized
|
||||
// for speech as well as what the voice messages MSC uses.
|
||||
final audioCodec =
|
||||
(await _audioRecorder.isEncoderSupported(AudioEncoder.opus))
|
||||
? AudioEncoder.opus
|
||||
: AudioEncoder.aacLc;
|
||||
// #Pangea
|
||||
// await _audioRecorder.start(
|
||||
// path: _recordedPath,
|
||||
// bitRate: bitRate,
|
||||
// samplingRate: samplingRate,
|
||||
// );
|
||||
await _audioRecorder.start(
|
||||
RecordConfig(
|
||||
encoder: audioCodec,
|
||||
bitRate: bitRate,
|
||||
// samplingRate: samplingRate,
|
||||
),
|
||||
path: _recordedPath!,
|
||||
path: _recordedPath,
|
||||
bitRate: bitRate,
|
||||
samplingRate: samplingRate,
|
||||
);
|
||||
// Pangea#
|
||||
setState(() => _duration = Duration.zero);
|
||||
_recorderSubscription?.cancel();
|
||||
_recorderSubscription =
|
||||
|
|
|
|||
|
|
@ -818,6 +818,7 @@ class ChatListController extends State<ChatList>
|
|||
await pangeaController.subscriptionController.initialize();
|
||||
pangeaController.afterSyncAndFirstLoginInitialization(context);
|
||||
await pangeaController.inviteBotToExistingSpaces();
|
||||
await pangeaController.setPangeaPushRules();
|
||||
} else {
|
||||
ErrorHandler.logError(
|
||||
m: "didn't run afterSyncAndFirstLoginInitialization because not mounted",
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ class PangeaEventTypes {
|
|||
static const botOptions = "pangea.bot_options";
|
||||
|
||||
static const userAge = "pangea.user_age";
|
||||
static const textToSpeechRule = "p.rule.text_to_speech";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ class MessageDataController extends BaseController {
|
|||
late PangeaController _pangeaController;
|
||||
|
||||
final List<CacheItem> _cache = [];
|
||||
|
||||
final Map<String, MessageDataQueueItem> _messageDataToSave = {};
|
||||
final List<RepresentationCacheItem> _representationCache = [];
|
||||
|
||||
MessageDataController(PangeaController pangeaController) {
|
||||
_pangeaController = pangeaController;
|
||||
|
|
@ -31,6 +30,14 @@ class MessageDataController extends BaseController {
|
|||
e.parentId == parentId && e.type == type && e.langCode == langCode,
|
||||
);
|
||||
|
||||
RepresentationCacheItem? getRepresentationCacheItem(
|
||||
String parentId,
|
||||
String langCode,
|
||||
) =>
|
||||
_representationCache.firstWhereOrNull(
|
||||
(e) => e.parentId == parentId && e.langCode == langCode,
|
||||
);
|
||||
|
||||
Future<PangeaMessageTokens?> _getTokens(
|
||||
TokensRequestModel req,
|
||||
) async {
|
||||
|
|
@ -141,6 +148,32 @@ class MessageDataController extends BaseController {
|
|||
required String? source,
|
||||
required String target,
|
||||
required Room room,
|
||||
}) async {
|
||||
final RepresentationCacheItem? item =
|
||||
getRepresentationCacheItem(text, target);
|
||||
if (item != null) return item.data;
|
||||
|
||||
_representationCache.add(
|
||||
RepresentationCacheItem(
|
||||
text,
|
||||
target,
|
||||
_getPangeaRepresentation(
|
||||
text: text,
|
||||
source: source,
|
||||
target: target,
|
||||
room: room,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return _representationCache.last.data;
|
||||
}
|
||||
|
||||
Future<PangeaRepresentation?> _getPangeaRepresentation({
|
||||
required String text,
|
||||
required String? source,
|
||||
required String target,
|
||||
required Room room,
|
||||
}) async {
|
||||
final req = FullTextTranslationRequestModel(
|
||||
text: text,
|
||||
|
|
@ -235,3 +268,11 @@ class CacheItem {
|
|||
|
||||
CacheItem(this.parentId, this.type, this.langCode, this.data);
|
||||
}
|
||||
|
||||
class RepresentationCacheItem {
|
||||
String parentId;
|
||||
String langCode;
|
||||
Future<PangeaRepresentation?> data;
|
||||
|
||||
RepresentationCacheItem(this.parentId, this.langCode, this.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/student_analytics_summary_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -24,8 +25,9 @@ class MyAnalyticsController {
|
|||
//PTODO - locally cache and update periodically
|
||||
Future<void> handleMessage(
|
||||
Room room,
|
||||
RecentMessageRecord messageRecord,
|
||||
) async {
|
||||
RecentMessageRecord messageRecord, {
|
||||
bool isEdit = false,
|
||||
}) async {
|
||||
try {
|
||||
debugPrint("in handle message with type ${messageRecord.useType}");
|
||||
if (_userId == null) {
|
||||
|
|
@ -48,7 +50,7 @@ class MyAnalyticsController {
|
|||
|
||||
for (final event in events) {
|
||||
if (event != null) {
|
||||
event.handleNewMessage(messageRecord);
|
||||
event.handleNewMessage(messageRecord, isEdit: isEdit);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
@ -76,8 +78,9 @@ class MyAnalyticsController {
|
|||
|
||||
Future<void> saveConstructsMixed(
|
||||
List<OneConstructUse> allUses,
|
||||
String langCode,
|
||||
) async {
|
||||
String langCode, {
|
||||
bool isEdit = false,
|
||||
}) async {
|
||||
try {
|
||||
final Map<String, List<OneConstructUse>> aggregatedVocabUse = {};
|
||||
for (final use in allUses) {
|
||||
|
|
@ -94,8 +97,9 @@ class MyAnalyticsController {
|
|||
saveFutures.add(
|
||||
analyticsRoom.saveConstructUsesSameLemma(
|
||||
uses.key,
|
||||
uses.value.first.constructType!,
|
||||
uses.value.first.constructType ?? ConstructType.grammar,
|
||||
uses.value,
|
||||
isEdit: isEdit,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:developer';
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:fluffychat/pangea/constants/class_default_values.dart';
|
||||
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/controllers/class_controller.dart';
|
||||
import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart';
|
||||
import 'package:fluffychat/pangea/controllers/language_controller.dart';
|
||||
|
|
@ -235,6 +236,7 @@ class PangeaController {
|
|||
if (!userIds.contains(BotName.byEnvironment)) {
|
||||
try {
|
||||
await space.invite(BotName.byEnvironment);
|
||||
await space.postLoad();
|
||||
await space.setPower(
|
||||
BotName.byEnvironment,
|
||||
ClassDefaultValues.powerLevelOfAdmin,
|
||||
|
|
@ -259,4 +261,35 @@ class PangeaController {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setPangeaPushRules() async {
|
||||
if (!(matrixState.client.globalPushRules?.override?.any(
|
||||
(element) => element.ruleId == PangeaEventTypes.textToSpeechRule,
|
||||
) ??
|
||||
false)) {
|
||||
await matrixState.client.setPushRule(
|
||||
'global',
|
||||
PushRuleKind.override,
|
||||
PangeaEventTypes.textToSpeechRule,
|
||||
[PushRuleAction.dontNotify],
|
||||
conditions: [
|
||||
PushCondition(
|
||||
kind: 'event_match',
|
||||
key: 'content.msgtype',
|
||||
pattern: MessageTypes.Audio,
|
||||
),
|
||||
PushCondition(
|
||||
kind: 'event_match',
|
||||
key: 'content.transcription.lang_code',
|
||||
pattern: '*',
|
||||
),
|
||||
PushCondition(
|
||||
kind: 'event_match',
|
||||
key: 'content.transcription.text',
|
||||
pattern: '*',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,4 +217,31 @@ extension PangeaClient on Client {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<List<String>> getEditHistory(
|
||||
String roomId,
|
||||
String eventId,
|
||||
) async {
|
||||
final Room? room = getRoomById(roomId);
|
||||
final Event? editEvent = await room?.getEventById(eventId);
|
||||
final String? edittedEventId =
|
||||
editEvent?.content.tryGetMap('m.relates_to')?['event_id'];
|
||||
if (edittedEventId == null) return [];
|
||||
|
||||
final Event? originalEvent = await room!.getEventById(edittedEventId);
|
||||
if (originalEvent == null) return [];
|
||||
|
||||
final Timeline timeline = await room.getTimeline();
|
||||
final List<Event> editEvents = originalEvent
|
||||
.aggregatedEvents(
|
||||
timeline,
|
||||
RelationshipTypes.edit,
|
||||
)
|
||||
.sorted(
|
||||
(a, b) => b.originServerTs.compareTo(a.originServerTs),
|
||||
)
|
||||
.toList();
|
||||
editEvents.add(originalEvent);
|
||||
return editEvents.slice(1).map((e) => e.eventId).toList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -698,16 +698,39 @@ extension PangeaRoom on Room {
|
|||
}
|
||||
}
|
||||
|
||||
Future<List<OneConstructUse>> removeEdittedLemmas(
|
||||
List<OneConstructUse> lemmaUses,
|
||||
) async {
|
||||
final List<String> removeUses = [];
|
||||
for (final use in lemmaUses) {
|
||||
if (use.msgId == null) continue;
|
||||
final List<String> removeIds = await client.getEditHistory(
|
||||
use.chatId,
|
||||
use.msgId!,
|
||||
);
|
||||
removeUses.addAll(removeIds);
|
||||
}
|
||||
lemmaUses.removeWhere((use) => removeUses.contains(use.msgId));
|
||||
final allEvents = await allConstructEvents;
|
||||
for (final constructEvent in allEvents) {
|
||||
await constructEvent.removeEdittedUses(removeUses, client);
|
||||
}
|
||||
return lemmaUses;
|
||||
}
|
||||
|
||||
Future<void> saveConstructUsesSameLemma(
|
||||
String lemma,
|
||||
ConstructType type,
|
||||
List<OneConstructUse> lemmaUses,
|
||||
) async {
|
||||
List<OneConstructUse> lemmaUses, {
|
||||
bool isEdit = false,
|
||||
}) async {
|
||||
final ConstructEvent? localEvent = _vocabEventLocal(lemma);
|
||||
|
||||
if (isEdit) {
|
||||
lemmaUses = await removeEdittedLemmas(lemmaUses);
|
||||
}
|
||||
|
||||
if (localEvent == null) {
|
||||
final json =
|
||||
ConstructUses(lemma: lemma, type: type, uses: lemmaUses).toJson();
|
||||
await client.setRoomStateWithKey(
|
||||
id,
|
||||
PangeaEventTypes.vocab,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:fluffychat/pangea/models/constructs_analytics_model.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/models/constructs_analytics_model.dart';
|
||||
import '../constants/pangea_event_types.dart';
|
||||
|
||||
class ConstructEvent {
|
||||
|
|
@ -30,4 +30,24 @@ class ConstructEvent {
|
|||
content.uses.addAll(uses);
|
||||
event.content = content.toJson();
|
||||
}
|
||||
|
||||
Future<void> removeEdittedUses(
|
||||
List<String> removeIds,
|
||||
Client client,
|
||||
) async {
|
||||
_contentCache ??= ConstructUses.fromJson(event.content);
|
||||
if (_contentCache == null || _event.stateKey == null) return;
|
||||
final previousLength = _contentCache!.uses.length;
|
||||
_contentCache!.uses.removeWhere(
|
||||
(element) => removeIds.contains(element.msgId),
|
||||
);
|
||||
if (previousLength > _contentCache!.uses.length) {
|
||||
await client.setRoomStateWithKey(
|
||||
_event.room.id,
|
||||
_event.type,
|
||||
_event.stateKey!,
|
||||
_contentCache!.toJson(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
|||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/constants/pangea_message_types.dart';
|
||||
import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/choreo_record.dart';
|
||||
|
|
@ -70,6 +69,12 @@ class PangeaMessageEvent {
|
|||
.firstOrNull ??
|
||||
_event;
|
||||
|
||||
Event updateLatestEdit() {
|
||||
_latestEditCache = null;
|
||||
_representations = null;
|
||||
return _latestEdit;
|
||||
}
|
||||
|
||||
bool showRichText(bool selected, bool highlighted) {
|
||||
if (!_isValidPangeaMessageEvent) {
|
||||
return false;
|
||||
|
|
@ -466,7 +471,7 @@ class PangeaMessageEvent {
|
|||
_event.room.isSpaceAdmin &&
|
||||
_event.senderId != BotName.byEnvironment &&
|
||||
!room.isUserSpaceAdmin(_event.senderId) &&
|
||||
_event.messageType != PangeaMessageTypes.report;
|
||||
_event.messageType == MessageTypes.Text;
|
||||
|
||||
String get messageDisplayLangCode {
|
||||
final bool immersionMode = MatrixState
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/constants/class_default_values.dart';
|
||||
import 'package:fluffychat/pangea/extensions/client_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/student_analytics_summary_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../constants/pangea_event_types.dart';
|
||||
import 'chart_analytics_model.dart';
|
||||
|
||||
|
|
@ -41,8 +41,27 @@ class StudentAnalyticsEvent {
|
|||
return _contentCache!;
|
||||
}
|
||||
|
||||
Future<void> handleNewMessage(RecentMessageRecord message) async {
|
||||
debugPrint("handle new message");
|
||||
Future<void> removeEdittedMessages(
|
||||
RecentMessageRecord message,
|
||||
) async {
|
||||
final List<String> removeIds = await classRoom.client.getEditHistory(
|
||||
message.chatId,
|
||||
message.eventId,
|
||||
);
|
||||
if (removeIds.isEmpty) return;
|
||||
_messagesToSave.removeWhere(
|
||||
(msg) => removeIds.any((e) => e == msg.eventId),
|
||||
);
|
||||
content.removeEdittedMessages(
|
||||
classRoom.client,
|
||||
removeIds,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> handleNewMessage(
|
||||
RecentMessageRecord message, {
|
||||
isEdit = false,
|
||||
}) async {
|
||||
if (classRoom.client.userID != _event.stateKey) {
|
||||
debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -50,6 +69,10 @@ class StudentAnalyticsEvent {
|
|||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEdit) {
|
||||
await removeEdittedMessages(message);
|
||||
}
|
||||
_addMessage(message);
|
||||
|
||||
if (DateTime.now().difference(content.lastUpdated).inMinutes >
|
||||
|
|
@ -66,6 +89,10 @@ class StudentAnalyticsEvent {
|
|||
);
|
||||
return;
|
||||
}
|
||||
for (final message in messages) {
|
||||
await removeEdittedMessages(message);
|
||||
}
|
||||
|
||||
_messagesToSave.addAll(messages);
|
||||
_updateStudentAnalytics();
|
||||
}
|
||||
|
|
@ -75,6 +102,7 @@ class StudentAnalyticsEvent {
|
|||
content.addAll(_messagesToSave);
|
||||
debugPrint("updating student analytics");
|
||||
_clearMessages();
|
||||
|
||||
await classRoom.client.setRoomStateWithKey(
|
||||
classRoom.id,
|
||||
_event.type,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../enum/use_type.dart';
|
||||
|
||||
class RecentMessageRecord {
|
||||
|
|
@ -78,6 +79,12 @@ class StudentAnalyticsSummary {
|
|||
}
|
||||
}
|
||||
|
||||
void removeEdittedMessages(Client client, List<String> removeEventIds) {
|
||||
_messages.removeWhere(
|
||||
(element) => removeEventIds.contains(element.eventId),
|
||||
);
|
||||
}
|
||||
|
||||
List<RecentMessageRecord> get messages => _messages;
|
||||
|
||||
static const _messagesKey = "msgs";
|
||||
|
|
|
|||
|
|
@ -49,10 +49,6 @@ class StudentAnalyticsController extends State<StudentAnalyticsPage> {
|
|||
}
|
||||
|
||||
Future<void> initialize() async {
|
||||
await _pangeaController.matrixState.client
|
||||
.updateMyLearningAnalyticsForAllClassesImIn(
|
||||
_pangeaController.pStoreService,
|
||||
);
|
||||
await getClassAndChatAnalytics(context);
|
||||
stateSub = _pangeaController.matrixState.client.onRoomState.stream
|
||||
.where(
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class GetChatListItemSubtitle {
|
|||
}
|
||||
|
||||
if (event.type != EventTypes.Message ||
|
||||
event.messageType != MessageTypes.Text ||
|
||||
!pangeaController.permissionsController
|
||||
.isToolEnabled(ToolSetting.immersionMode, event.room)) {
|
||||
return event.calcLocalizedBody(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
|
|
@ -134,6 +135,13 @@ class AddToSpaceState extends State<AddToSpaceToggles> {
|
|||
future: () => add
|
||||
? _addSingleSpace(room!.id, possibleParent)
|
||||
: possibleParent.removeSpaceChild(room!.id),
|
||||
onError: (e) {
|
||||
// if error occurs, do not change value of toggle
|
||||
add = !add;
|
||||
return (e as Object?)?.toLocalizedString(context) ??
|
||||
e?.toString() ??
|
||||
L10n.of(context)!.oopsSomethingWentWrong;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'dart:convert';
|
|||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:desktop_notifications/desktop_notifications.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/utils/client_manager.dart';
|
||||
|
|
@ -249,8 +250,14 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
LoadingDialog.defaultTitle = L10n.of(context)!.loadingPleaseWait;
|
||||
LoadingDialog.defaultBackLabel = L10n.of(context)!.close;
|
||||
LoadingDialog.defaultOnError =
|
||||
(e) => (e as Object?)!.toLocalizedString(context);
|
||||
// #Pangea
|
||||
// LoadingDialog.defaultOnError =
|
||||
// (e) => (e as Object?)!.toLocalizedString(context);
|
||||
LoadingDialog.defaultOnError = (e) =>
|
||||
(e as Object?)?.toLocalizedString(context) ??
|
||||
e?.toString() ??
|
||||
L10n.of(context)!.oopsSomethingWentWrong;
|
||||
// Pangea#
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -354,7 +361,11 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
e.type == EventUpdateType.timeline &&
|
||||
[EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted]
|
||||
.contains(e.content['type']) &&
|
||||
e.content['sender'] != c.userID,
|
||||
e.content['sender'] != c.userID
|
||||
// #Pangea
|
||||
&&
|
||||
!e.content['content']?.containsKey(ModelKey.transcription),
|
||||
// Pangea#,
|
||||
)
|
||||
.listen(showLocalNotification);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -83,10 +83,7 @@ dependencies:
|
|||
punycode: ^1.0.0
|
||||
qr_code_scanner: ^1.0.1
|
||||
receive_sharing_intent: ^1.4.5
|
||||
# #Pangea
|
||||
# record: 4.4.4 # Upgrade to 5 currently breaks playing on iOS
|
||||
record: ^5.0.4
|
||||
# Pangea#
|
||||
record: 4.4.4 # Upgrade to 5 currently breaks playing on iOS
|
||||
scroll_to_index: ^3.0.1
|
||||
share_plus: ^8.0.2
|
||||
shared_preferences: ^2.2.0 # Pinned because https://github.com/flutter/flutter/issues/118401
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@
|
|||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="The cutest messenger in the Matrix network.">
|
||||
<!-- #Pangea -->
|
||||
<!-- <meta name="description" content="The cutest messenger in the Matrix network."> -->
|
||||
<meta name="description" content="Learn a language while texting your friends.">
|
||||
<!-- Pangea# -->
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue