diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 652173db3..cbc5c8bf7 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -115,10 +115,17 @@ class ChatController extends State // #Pangea final PangeaController pangeaController = MatrixState.pangeaController; late Choreographer choreographer = Choreographer(pangeaController, this); - final List gameRounds = []; final GlobalKey roundTimerStateKey = GlobalKey(); RoundTimer? timer; + + final List gameRounds = []; + + List get completedRoundEventIds => gameRounds + .where((round) => round.isCompleted) + .map((round) => round.messageIDs) + .expand((x) => x) + .toList(); // Pangea# Room get room => sendingClient.getRoomById(roomId) ?? widget.room; @@ -414,7 +421,8 @@ class ChatController extends State List get visibleEvents => timeline?.events .where( - (x) => x.isVisibleInGui, + (x) => + x.isVisibleInGui && !completedRoundEventIds.contains(x.eventId), ) .toList() ?? []; @@ -552,7 +560,6 @@ class ChatController extends State //#Pangea choreographer.stateListener.close(); choreographer.dispose(); - roundTimerStateKey.currentState?.stopTimeout(); //Pangea# super.dispose(); } diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 9bca32169..7b9003379 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -27,7 +27,15 @@ class ChatEventList extends StatelessWidget { final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0; final events = controller.timeline!.events - .where((event) => event.isVisibleInGui) + .where( + (event) => + event.isVisibleInGui + // #Pangea + && + !controller.completedRoundEventIds.contains(event.eventId) + // Pangea# + , + ) .toList(); final animateInEventIndex = controller.animateInEventIndex; diff --git a/lib/pangea/extensions/sync_update_extension.dart b/lib/pangea/extensions/sync_update_extension.dart index 227e88c25..412ca2b8f 100644 --- a/lib/pangea/extensions/sync_update_extension.dart +++ b/lib/pangea/extensions/sync_update_extension.dart @@ -1,26 +1,18 @@ -import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:matrix/matrix.dart'; extension MembershipUpdate on SyncUpdate { - List botMessages(String roomID) { + List messages(Room chat) { if (rooms?.join == null || - !rooms!.join!.containsKey(roomID) || - rooms!.join![roomID]!.timeline?.events == null) { + !rooms!.join!.containsKey(chat.id) || + rooms!.join![chat.id]!.timeline?.events == null) { return []; } - final messageEvents = rooms!.join![roomID]!.timeline!.events! + return rooms!.join![chat.id]!.timeline!.events! .where( (event) => event.type == EventTypes.Message, ) - .toList(); - if (messageEvents.isEmpty) { - return []; - } - - return messageEvents - .where((event) => event.senderId == BotName.byEnvironment) - .map((event) => event.eventId) + .map((event) => Event.fromMatrixEvent(event, chat)) .toList(); } } diff --git a/lib/pangea/pages/games/story_game/round_model.dart b/lib/pangea/pages/games/story_game/round_model.dart index df99a52b7..ee54123f0 100644 --- a/lib/pangea/pages/games/story_game/round_model.dart +++ b/lib/pangea/pages/games/story_game/round_model.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pangea/extensions/sync_update_extension.dart'; +import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/widgets/chat/round_timer.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -13,25 +14,52 @@ class GameRoundModel { final ChatController controller; final Completer roundCompleter = Completer(); + late DateTime createdAt; RoundTimer timer; DateTime? startTime; DateTime? endTime; RoundState state = RoundState.notStarted; - + StreamSubscription? syncSubscription; final Set messageIDs = {}; GameRoundModel({ required this.controller, required this.timer, }) { - client.onSync.stream.firstWhere((update) { - final botEventIDs = update.botMessages(controller.roomId); - return botEventIDs.isNotEmpty; - }).then((_) => startRound()); + createdAt = DateTime.now(); + syncSubscription ??= client.onSync.stream.listen((update) { + final newMessages = update.messages(controller.room); + final botMessages = newMessages + .where((msg) => msg.senderId == BotName.byEnvironment) + .toList(); + + if (botMessages.isNotEmpty && + botMessages.any( + (msg) => + msg.originServerTs.isAfter(createdAt) && + !messageIDs.contains(msg.eventId), + )) { + if (state == RoundState.notStarted) { + startRound(); + } else if (state == RoundState.inProgress) { + endRound(); + } + } + + for (final message in newMessages) { + if (message.originServerTs.isAfter(createdAt) && + !messageIDs.contains(message.eventId) && + !message.eventId.startsWith("Pangea Chat")) { + messageIDs.add(message.eventId); + } + } + }); } Client get client => controller.pangeaController.matrixState.client; + bool get isCompleted => roundCompleter.isCompleted; + void startRound() { debugPrint("starting round"); state = RoundState.inProgress; @@ -42,12 +70,15 @@ class GameRoundModel { } void endRound() { - debugPrint("ending round"); + debugPrint("ending round, message IDs: $messageIDs"); endTime = DateTime.now(); state = RoundState.completed; controller.roundTimerStateKey.currentState?.stopTimeout(); + syncSubscription?.cancel(); roundCompleter.complete(); } - void dispose() {} + void dispose() { + syncSubscription?.cancel(); + } }