diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 0897a28eb..8f5515fc4 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -863,7 +863,7 @@ class ChatListController extends State if (space.canSendDefaultStates) { for (final roomId in selectedRoomIds) { - await space.pangeaSetSpaceChild(roomId); + await space.pangeaSetSpaceChild(roomId, suggested: true); } } // Pangea# diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index ccc9aa9c4..a90c0d094 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -579,7 +579,12 @@ class _SpaceViewState extends State { : null, ); } - await activeSpace.setSpaceChild(roomId); + await activeSpace.setSpaceChild( + roomId, + // #Pangea + suggested: true, + // Pangea# + ); }, ); if (result.error != null) return; diff --git a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart index f76ebff42..c22ba9a23 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:developer'; import 'package:adaptive_dialog/adaptive_dialog.dart'; diff --git a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart index 3a2e62c86..7bdd13743 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -203,30 +203,66 @@ extension AnalyticsRoomExtension on Room { creationContent?.tryGet(ModelKey.oldLangCode) == langCode; } - Future sendSummaryAnalyticsEvent( + Future sendSummaryAnalyticsEvent( List records, ) async { final SummaryAnalyticsModel analyticsModel = SummaryAnalyticsModel( messages: records, ); - final String? eventId = await sendEvent( + await sendEvent( analyticsModel.toJson(), type: PangeaEventTypes.summaryAnalytics, ); - return eventId; } - Future sendConstructsEvent( + /// Sends construct events to the server. + /// + /// The [uses] parameter is a list of [OneConstructUse] objects representing the + /// constructs to be sent. To prevent hitting the maximum event size, the events + /// are chunked into smaller lists. Each chunk is sent as a separate event. + Future sendConstructsEvent( List uses, ) async { - final ConstructAnalyticsModel constructsModel = ConstructAnalyticsModel( - uses: uses, - ); + // these events can get big, so we chunk them to prevent hitting the max event size. + // go through each of the uses being sent and add them to the current chunk until + // the size (in bytes) of the current chunk is greater than the max event size, then + // start a new chunk until all uses have been added. + final List> useChunks = []; + List currentChunk = []; + int currentChunkSize = 0; - final String? eventId = await sendEvent( - constructsModel.toJson(), - type: PangeaEventTypes.construct, - ); - return eventId; + for (final use in uses) { + // get the size, in bytes, of the json representation of the use + final json = use.toJson(); + final jsonString = jsonEncode(json); + final jsonSizeInBytes = utf8.encode(jsonString).length; + + // If this use would tip this chunk over the size limit, + // add it to the list of all chunks and start a new chunk. + // + // I tested with using the maxPDUSize constant, but the events + // were still too large. 50000 seems to be a safe number of bytes. + if (currentChunkSize + jsonSizeInBytes > (maxPDUSize - 10000)) { + useChunks.add(currentChunk); + currentChunk = []; + currentChunkSize = 0; + } + + // add this use to the current chunk + currentChunk.add(use); + currentChunkSize += jsonSizeInBytes; + } + + if (currentChunk.isNotEmpty) { + useChunks.add(currentChunk); + } + + for (final chunk in useChunks) { + final constructsModel = ConstructAnalyticsModel(uses: chunk); + await sendEvent( + constructsModel.toJson(), + type: PangeaEventTypes.construct, + ); + } } }