diff --git a/commet/lib/client/alert.dart b/commet/lib/client/alert.dart index 50ab51659..c0547e27d 100644 --- a/commet/lib/client/alert.dart +++ b/commet/lib/client/alert.dart @@ -24,9 +24,9 @@ class Alert { class AlertManager { final NotifyingList _alerts = NotifyingList.empty(growable: true); - Stream get onAlertAdded => _alerts.onAdd; + Stream get onAlertAdded => _alerts.onAdd; - Stream get onAlertRemoved => _alerts.onRemove; + Stream get onAlertRemoved => _alerts.onRemove; List get alerts => _alerts; diff --git a/commet/lib/client/call_manager.dart b/commet/lib/client/call_manager.dart index bd006b1bf..a0407f7d5 100644 --- a/commet/lib/client/call_manager.dart +++ b/commet/lib/client/call_manager.dart @@ -7,7 +7,6 @@ import 'package:commet/client/components/push_notification/notification_content. import 'package:commet/client/components/push_notification/notification_manager.dart'; import 'package:commet/client/components/voip/voip_component.dart'; import 'package:commet/client/components/voip/voip_session.dart'; -import 'package:commet/client/stale_info.dart'; import 'package:commet/config/platform_utils.dart'; import 'package:commet/utils/notifying_list.dart'; import 'package:intl/intl.dart'; @@ -37,17 +36,14 @@ class CallManager { NotifyingList.empty(growable: true); CallManager(this.clientManager) { - clientManager.onClientAdded.stream.listen(_onClientAdded); - clientManager.onClientRemoved.stream.listen(_onClientRemoved); + clientManager.onClientAdded.listen(_onClientAdded); } Player? player; Player? muteSoundPlayer; Player? unmuteSoundPlayer; - void _onClientAdded(int index) { - var client = clientManager.clients[index]; - + void _onClientAdded(Client client) { var voip = client.getComponent(); if (voip == null) { return; @@ -57,8 +53,6 @@ class CallManager { voip.onSessionEnded.listen(onSessionEnded); } - void _onClientRemoved(StalePeerInfo event) {} - void onClientSessionStarted(VoipSession event) { var room = event.client.getRoom(event.roomId); currentSessions.add(event); diff --git a/commet/lib/client/client.dart b/commet/lib/client/client.dart index e504ddec4..ca982f5a1 100644 --- a/commet/lib/client/client.dart +++ b/commet/lib/client/client.dart @@ -97,28 +97,28 @@ abstract class Client { List get singleRooms; /// Gets list of all rooms - List get rooms; + Iterable get rooms; /// Gets list of all spaces - List get spaces; + Iterable get spaces; /// Gets list of all currently known users - List get peers; + Iterable get peers; /// When a room is added, this will be called with the index of the new room - Stream get onRoomAdded; + Stream get onRoomAdded; /// When a space is added, this will be called with the index of the new space - Stream get onSpaceAdded; + Stream get onSpaceAdded; /// When a room is removed, this will be called with the index of the room which was removed - Stream get onRoomRemoved; + Stream get onRoomRemoved; /// When a space is removed, this will be called with the index of the space which was removed - Stream get onSpaceRemoved; + Stream get onSpaceRemoved; /// When a new peer is found, this will be called with the index of the new peer - Stream get onPeerAdded; + Stream get onPeerAdded; /// When the client receives an update from the server, this will be called Stream get onSync; diff --git a/commet/lib/client/client_manager.dart b/commet/lib/client/client_manager.dart index 454ebd719..4df550ea4 100644 --- a/commet/lib/client/client_manager.dart +++ b/commet/lib/client/client_manager.dart @@ -9,26 +9,36 @@ import 'package:commet/client/matrix/matrix_client.dart'; import 'package:commet/client/stale_info.dart'; import 'package:commet/client/tasks/client_connection_status_task.dart'; import 'package:commet/main.dart'; -import 'package:commet/utils/notifying_list.dart'; +import 'package:commet/utils/notifying_map.dart'; +import 'package:commet/utils/notifying_sub_map.dart'; class ClientManager { - final Map _clients = {}; + final NotifyingMap _all_rooms = NotifyingMap(); - final NotifyingList _rooms = NotifyingList.empty(growable: true); + final NotifyingMap _clients = NotifyingMap(); - final NotifyingList _spaces = NotifyingList.empty(growable: true); + late final NotifyingMap _rooms = + NotifyingSubMap(_all_rooms, null); + + late final NotifyingMap _spaces = + NotifyingSubMap(_all_rooms, null); + + NotifyingMap get motifyingMapRoom => _rooms; + NotifyingMap get motifyingMapSpace => _spaces; final AlertManager alertManager = AlertManager(); late CallManager callManager; late final DirectMessagesAggregator directMessages; - ClientManager() { + static final ClientManager instance = ClientManager._(); + + ClientManager._() { directMessages = DirectMessagesAggregator(this); callManager = CallManager(this); } - List get rooms => _rooms; + Iterable get rooms => _rooms.values; List singleRooms({Client? filterClient}) { var result = List.empty(growable: true); @@ -46,7 +56,7 @@ class ClientManager { } } - if (client.spaces.any((space) => space.containsRoom(room.identifier))) { + if (client.spaces.any((space) => space.containsRoom(room.roomId))) { continue; } @@ -57,7 +67,7 @@ class ClientManager { return result; } - List get spaces => _spaces; + Iterable get spaces => _spaces.values; final List _clientsList = List.empty(growable: true); final Map> _clientSubscriptions = {}; @@ -66,18 +76,17 @@ class ClientManager { late StreamController onSync = StreamController.broadcast(); - Stream get onRoomAdded => _rooms.onAdd; + Stream get onRoomAdded => _rooms.onAdd.map((e) => e.value); - Stream get onRoomRemoved => _rooms.onRemove; + Stream get onRoomRemoved => _rooms.onRemove.map((e) => e.value); - Stream get onSpaceAdded => _spaces.onAdd; + Stream get onSpaceAdded => _spaces.onAdd.map((e) => e.value); - Stream get onSpaceRemoved => _spaces.onRemove; + Stream get onSpaceRemoved => _spaces.onRemove.map((e) => e.value); - late StreamController onClientAdded = StreamController.broadcast(); + Stream get onClientAdded => _clients.onAdd.map((e) => e.value); - late StreamController onClientRemoved = - StreamController.broadcast(); + Stream get onClientRemoved => _clients.onRemove.map((e) => e.value); late StreamController onSpaceUpdated = StreamController.broadcast(); late StreamController onSpaceChildUpdated = @@ -92,14 +101,12 @@ class ClientManager { // previousValue + element.displayNotificationCount); static Future init({bool isBackgroundService = false}) async { - final newClientManager = ClientManager(); - await Future.wait([ - MatrixClient.loadFromDB(newClientManager, + MatrixClient.loadFromDB(instance, isBackgroundService: isBackgroundService), ]); - return newClientManager; + return instance; } void addClient(Client client) { @@ -108,27 +115,16 @@ class ClientManager { _clientsList.add(client); - for (int i = 0; i < client.rooms.length; i++) { - _onClientAddedRoom(client, i); - } - - for (int i = 0; i < client.spaces.length; i++) { - _addSpace(client, i); + for (final e in client.spaces) { + _addSpace(client, e); } _clientSubscriptions[client] = [ client.onSync.listen((_) => _synced()), - client.onRoomAdded.listen((index) => _onClientAddedRoom(client, index)), - client.onRoomRemoved - .listen((index) => _onClientRemovedRoom(client, index)), - client.onSpaceAdded.listen((index) => _addSpace(client, index)), - client.onSpaceRemoved - .listen((index) => _onClientRemovedSpace(client, index)), + client.onSpaceAdded.listen((space) => _addSpace(client, space)), client.connectionStatusChanged.stream .listen((event) => _onClientConnectionStatusChanged(client, event)), ]; - - onClientAdded.add(_clients.length - 1); } catch (error) {} } @@ -146,25 +142,9 @@ class ClientManager { } } - void _onClientAddedRoom(Client client, int index) { - rooms.add(client.rooms[index]); - } - - void _onClientRemovedRoom(Client client, int index) { - var room = client.rooms[index]; - _rooms.remove(room); - } - - void _onClientRemovedSpace(Client client, int index) { - var space = client.spaces[index]; - _spaces.remove(space); - } - - void _addSpace(Client client, int index) { - var space = client.spaces[index]; + void _addSpace(Client client, Space space) { space.onUpdate.listen((_) => spaceUpdated(space)); space.onChildRoomUpdated.listen((_) => spaceChildUpdated(space)); - spaces.add(client.spaces[index]); } void spaceUpdated(Space space) { @@ -196,20 +176,19 @@ class ClientManager { identifier: client.self!.identifier, avatar: client.self!.avatar); - for (int i = rooms.length - 1; i >= 0; i--) { - if (rooms[i].client == client) { - rooms.removeAt(i); + for (final room in rooms) { + if (room.client == client) { + _rooms.remove(room.localId); } } - for (int i = spaces.length - 1; i >= 0; i--) { - if (spaces[i].client == client) { - spaces.removeAt(i); + for (final space in spaces) { + if (space.client == client) { + _spaces.remove(space.localId); } } await client.logout(); - onClientRemoved.add(clientInfo); _clients.remove(client.identifier); _clientsList.removeAt(clientIndex); } diff --git a/commet/lib/client/components/calendar_room/calendar_sync.dart b/commet/lib/client/components/calendar_room/calendar_sync.dart index dad3fe407..47acec4f2 100644 --- a/commet/lib/client/components/calendar_room/calendar_sync.dart +++ b/commet/lib/client/components/calendar_room/calendar_sync.dart @@ -21,15 +21,11 @@ class CalendarSync { Future syncAllClients() async { Log.i("Client Manager: ${clientManager}"); - if (clientManager == null) { - Timer(Duration(seconds: 30), () => syncAllClients()); - } else { - await Future.wait([ - for (var client in clientManager!.clients) syncClient(client), - ]); + await Future.wait([ + for (var client in clientManager.clients) syncClient(client), + ]); - Timer(Duration(minutes: 30), () => syncAllClients()); - } + Timer(Duration(minutes: 30), () => syncAllClients()); } Future syncClient(Client client) async { @@ -53,7 +49,7 @@ class CalendarSync { if (calendar?.syncedCalendars.value?.isNotEmpty == true) { Log.i( - "Syncing room calendar from external sources: ${room.identifier}", + "Syncing room calendar from external sources: ${room.roomId}", ); await calendar!.runCalendarSync(); diff --git a/commet/lib/client/components/component.dart b/commet/lib/client/components/component.dart index 3a8c8bd5b..3e5efec92 100644 --- a/commet/lib/client/components/component.dart +++ b/commet/lib/client/components/component.dart @@ -21,7 +21,7 @@ abstract class NeedsPostLoginInit { void postLoginInit(); static void doPostLoginInit() { - for (var client in clientManager!.clients) { + for (var client in clientManager.clients) { if (!client.isLoggedIn()) continue; var components = client.getAllComponents()!; diff --git a/commet/lib/client/components/direct_messages/direct_message_aggregator.dart b/commet/lib/client/components/direct_messages/direct_message_aggregator.dart index e199fddad..10787ebcf 100644 --- a/commet/lib/client/components/direct_messages/direct_message_aggregator.dart +++ b/commet/lib/client/components/direct_messages/direct_message_aggregator.dart @@ -1,9 +1,8 @@ import 'dart:async'; +import 'package:commet/client/client.dart'; import 'package:commet/client/client_manager.dart'; import 'package:commet/client/components/direct_messages/direct_message_component.dart'; -import 'package:commet/client/room.dart'; -import 'package:commet/client/stale_info.dart'; class DirectMessagesAggregator implements DirectMessagesInterface { ClientManager clientManager; @@ -34,8 +33,8 @@ class DirectMessagesAggregator implements DirectMessagesInterface { comp?.onHighlightedRoomsListUpdated.listen(onHighlightedListUpdated); } - clientManager.onClientAdded.stream.listen(onClientAdded); - clientManager.onClientRemoved.stream.listen(onClientRemoved); + clientManager.onClientAdded.listen(onClientAdded); + clientManager.onClientRemoved.listen(onClientRemoved); } void updateDirectMessageRooms() { @@ -61,8 +60,7 @@ class DirectMessagesAggregator implements DirectMessagesInterface { updateDirectMessageRooms(); } - void onClientAdded(int index) { - var client = clientManager.clients[index]; + void onClientAdded(Client client) { final comp = client.getComponent(); if (comp != null) { comp.onRoomsListUpdated.listen(onClientUpdatedList); @@ -71,7 +69,7 @@ class DirectMessagesAggregator implements DirectMessagesInterface { } } - void onClientRemoved(StalePeerInfo event) { + void onClientRemoved(Client client) { updateDirectMessageRooms(); } diff --git a/commet/lib/client/components/photo_album_room/photo_album_timeline.dart b/commet/lib/client/components/photo_album_room/photo_album_timeline.dart index ba34200e0..0b6e5a929 100644 --- a/commet/lib/client/components/photo_album_room/photo_album_timeline.dart +++ b/commet/lib/client/components/photo_album_room/photo_album_timeline.dart @@ -1,9 +1,9 @@ import 'package:commet/client/components/photo_album_room/photo.dart'; abstract class PhotoAlbumTimeline { - Stream get onAdded; - Stream get onChanged; - Stream get onRemoved; + Stream get onAdded; + Stream get onChanged; + Stream get onRemoved; List get photos; diff --git a/commet/lib/client/components/push_notification/android/android_notifier.dart b/commet/lib/client/components/push_notification/android/android_notifier.dart index 73fc4fba0..c98b9720e 100644 --- a/commet/lib/client/components/push_notification/android/android_notifier.dart +++ b/commet/lib/client/components/push_notification/android/android_notifier.dart @@ -65,18 +65,18 @@ class AndroidNotifier implements Notifier { return; } - var client = clientManager!.clients + var client = clientManager.clients .firstWhereOrNull((element) => element.hasRoom(roomId)); if (client == null) { - client = clientManager!.clients.firstWhereOrNull((client) => + client = clientManager.clients.firstWhereOrNull((client) => client .getComponent() ?.invitations .any((i) => i.roomId == roomId) == true); - for (client in clientManager!.clients) { + for (client in clientManager.clients) { final comp = client.getComponent(); var invite = @@ -116,7 +116,7 @@ class AndroidNotifier implements Notifier { eventId: eventId, senderImageId: user.avatarId, roomImageId: room.avatarId, - roomId: room.identifier, + roomId: room.roomId, clientId: client.identifier, senderImage: user.avatar, roomImage: await room.getShortcutImage(), @@ -149,7 +149,7 @@ class AndroidNotifier implements Notifier { Future displayMessageNotification( MessageNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); + var client = clientManager.getClient(content.clientId); var room = client?.getRoom(content.roomId); if (room == null) { @@ -187,14 +187,14 @@ class AndroidNotifier implements Notifier { placeholderText: content.roomName, imageId: content.roomImageId, format: ShortcutIconFormat.png, - identifier: room.identifier, + identifier: room.roomId, imageProvider: await room.getShortcutImage()); await Future.wait([ shortcutsManager.createShortcutForRoom(room), ]); - var id = room.identifier.hashCode; + var id = room.roomId.hashCode; var activeStyleInfo = await AndroidFlutterLocalNotificationsPlugin() .getActiveNotificationMessagingStyle(id); @@ -254,7 +254,7 @@ class AndroidNotifier implements Notifier { } Future displayCallNotification(CallNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); + var client = clientManager.getClient(content.clientId); var room = client?.getRoom(content.roomId); if (room == null) { @@ -280,10 +280,10 @@ class AndroidNotifier implements Notifier { placeholderText: content.roomName, imageId: content.roomImageId, format: ShortcutIconFormat.png, - identifier: room.identifier, + identifier: room.roomId, imageProvider: await room.getShortcutImage()); - var id = room.identifier.hashCode; + var id = room.roomId.hashCode; var payload = OpenRoomURI(roomId: content.roomId, clientId: content.clientId) @@ -355,7 +355,7 @@ class AndroidNotifier implements Notifier { var uri = CustomURI.parse(details.actionId!); Log.d("Parsed action uri: $uri"); if (uri case AcceptCallUri _) { - final session = clientManager?.callManager.currentSessions + final session = clientManager.callManager.currentSessions .where((e) => e.sessionId == uri.callId && e.client.identifier == uri.clientId) @@ -367,7 +367,7 @@ class AndroidNotifier implements Notifier { } if (uri case DeclineCallUri _) { - final session = clientManager?.callManager.currentSessions + final session = clientManager.callManager.currentSessions .where((e) => e.sessionId == uri.callId && e.client.identifier == uri.clientId) @@ -407,7 +407,7 @@ class AndroidNotifier implements Notifier { if (notifications == null) return; for (var noti in notifications) { - if (noti.groupKey == room.identifier) { + if (noti.groupKey == room.roomId) { flutterLocalNotificationsPlugin?.cancel(noti.id!); } } diff --git a/commet/lib/client/components/push_notification/linux/linux_notifier.dart b/commet/lib/client/components/push_notification/linux/linux_notifier.dart index f15927a96..11b974e3d 100644 --- a/commet/lib/client/components/push_notification/linux/linux_notifier.dart +++ b/commet/lib/client/components/push_notification/linux/linux_notifier.dart @@ -60,7 +60,7 @@ class LinuxNotifier implements Notifier { if (eventId == null) return; if (message == null) return; - var client = clientManager!.getClient(clientId); + var client = clientManager.getClient(clientId); if (client == null) return; @@ -80,13 +80,13 @@ class LinuxNotifier implements Notifier { if ([callAccept, callDecline].contains(action)) { final callId = payload['call_id']; final clientId = payload['client_id']; - final session = clientManager?.callManager.currentSessions + final session = clientManager.callManager.currentSessions .where( (e) => e.sessionId == callId && e.client.identifier == clientId) .firstOrNull; if (action == callDecline) { - clientManager?.callManager.stopRingtone(); + clientManager.callManager.stopRingtone(); } if (session != null) { @@ -96,7 +96,7 @@ class LinuxNotifier implements Notifier { if (action == callDecline) { session.declineCall(); - clientManager?.callManager.stopRingtone(); + clientManager.callManager.stopRingtone(); } } else { Log.d("Could not find call session"); @@ -131,7 +131,7 @@ class LinuxNotifier implements Notifier { Future displayMessageNotification( MessageNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); + var client = clientManager.getClient(content.clientId); var room = client?.getRoom(content.roomId); if (room == null) { @@ -201,7 +201,7 @@ class LinuxNotifier implements Notifier { } Future displayCallNotification(CallNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); + var client = clientManager.getClient(content.clientId); var room = client?.getRoom(content.roomId); if (room == null) { diff --git a/commet/lib/client/components/push_notification/modifiers/linux_notification_formatting.dart b/commet/lib/client/components/push_notification/modifiers/linux_notification_formatting.dart index 93561b26d..0c7cb5b2f 100644 --- a/commet/lib/client/components/push_notification/modifiers/linux_notification_formatting.dart +++ b/commet/lib/client/components/push_notification/modifiers/linux_notification_formatting.dart @@ -34,7 +34,7 @@ class NotificationModifierLinuxFormatting implements NotificationModifier { if (content is MessageNotificationContent && content.formattedContent != null && content.formatType != null) { - final client = clientManager!.getClient(content.clientId); + final client = clientManager.getClient(content.clientId); final room = client!.getRoom(content.roomId)!; var formattedContent = await convertFormattedContent( diff --git a/commet/lib/client/components/push_notification/modifiers/suppress_active_room.dart b/commet/lib/client/components/push_notification/modifiers/suppress_active_room.dart index edabe4b12..1ccc51e44 100644 --- a/commet/lib/client/components/push_notification/modifiers/suppress_active_room.dart +++ b/commet/lib/client/components/push_notification/modifiers/suppress_active_room.dart @@ -11,7 +11,7 @@ class NotificationModifierSuppressActiveRoom implements NotificationModifier { NotificationModifierSuppressActiveRoom() { EventBus.onSelectedRoomChanged.stream.listen((event) { - roomId = event?.identifier; + roomId = event?.roomId; }); } diff --git a/commet/lib/client/components/push_notification/modifiers/suppress_other_device_active.dart b/commet/lib/client/components/push_notification/modifiers/suppress_other_device_active.dart index 3102517f1..808410c3d 100644 --- a/commet/lib/client/components/push_notification/modifiers/suppress_other_device_active.dart +++ b/commet/lib/client/components/push_notification/modifiers/suppress_other_device_active.dart @@ -18,13 +18,7 @@ class NotificationModifierSuppressOtherActiveDevice return content; } - if (clientManager == null) { - Log.w( - "Suppressing notifications for background client is not currently supported"); - return content; - } - - var clients = clientManager!.clients + var clients = clientManager.clients .where((element) => element.hasRoom(content.roomId)); for (var client in clients) { diff --git a/commet/lib/client/components/push_notification/notification_content.dart b/commet/lib/client/components/push_notification/notification_content.dart index 81ee760b2..51ce8104d 100644 --- a/commet/lib/client/components/push_notification/notification_content.dart +++ b/commet/lib/client/components/push_notification/notification_content.dart @@ -72,7 +72,7 @@ class MessageNotificationContent extends NotificationContent { senderImage: user.avatar, senderId: user.identifier, roomName: room.displayName, - roomId: room.identifier, + roomId: room.roomId, roomImage: await room.getShortcutImage(), content: msg.body ?? "Sent a message", clientId: room.client.identifier, @@ -98,7 +98,7 @@ class MessageNotificationContent extends NotificationContent { senderImage: user.avatar, senderId: user.identifier, roomName: room.displayName, - roomId: room.identifier, + roomId: room.roomId, roomImage: await room.getShortcutImage(), content: msg.stickerName, clientId: room.client.identifier, diff --git a/commet/lib/client/components/push_notification/notification_manager.dart b/commet/lib/client/components/push_notification/notification_manager.dart index 8e7543a2d..eb526d665 100644 --- a/commet/lib/client/components/push_notification/notification_manager.dart +++ b/commet/lib/client/components/push_notification/notification_manager.dart @@ -50,7 +50,7 @@ class NotificationManager { "https://commet.chat/troubleshoot/android-background-service-failed/")), ); - clientManager?.alertManager.addAlert(alert); + clientManager.alertManager.addAlert(alert); preferences.setLastForegroundServiceRunSucceeded(null); } } diff --git a/commet/lib/client/components/push_notification/push_notification_component.dart b/commet/lib/client/components/push_notification/push_notification_component.dart index ceb268c92..446d02cf7 100644 --- a/commet/lib/client/components/push_notification/push_notification_component.dart +++ b/commet/lib/client/components/push_notification/push_notification_component.dart @@ -11,11 +11,7 @@ abstract class PushNotificationComponent Future updatePushers(); static Future updateAllPushers() async { - if (clientManager == null) { - return; - } - - for (var client in clientManager!.clients) { + for (var client in clientManager.clients) { var notifier = client.getComponent(); await notifier?.updatePushers(); } diff --git a/commet/lib/client/components/push_notification/windows/windows_notifier.dart b/commet/lib/client/components/push_notification/windows/windows_notifier.dart index 4cd16f120..901535497 100644 --- a/commet/lib/client/components/push_notification/windows/windows_notifier.dart +++ b/commet/lib/client/components/push_notification/windows/windows_notifier.dart @@ -69,7 +69,7 @@ class WindowsNotifier implements Notifier { if (eventId == null) return; if (message == null) return; - var client = clientManager!.getClient(clientId); + var client = clientManager.getClient(clientId); if (client == null) return; @@ -90,7 +90,7 @@ class WindowsNotifier implements Notifier { print("Handling call response"); final callId = args['call_id']; final clientId = args['client_id']; - final session = clientManager?.callManager.currentSessions + final session = clientManager.callManager.currentSessions .where( (e) => e.sessionId == callId && e.client.identifier == clientId) .firstOrNull; @@ -133,7 +133,7 @@ class WindowsNotifier implements Notifier { CallNotificationContent content) async { String? avatarFilePath; - var client = clientManager?.getClient(content.clientId); + var client = clientManager.getClient(content.clientId); var room = client?.getRoom(content.roomId); if (room == null) { @@ -193,7 +193,7 @@ class WindowsNotifier implements Notifier { MessageNotificationContent content) async { String? avatarFilePath; - var client = clientManager?.getClient(content.clientId); + var client = clientManager.getClient(content.clientId); var room = client?.getRoom(content.roomId); if (room == null) { diff --git a/commet/lib/client/components/user_presence/user_presence_lifecycle_watcher.dart b/commet/lib/client/components/user_presence/user_presence_lifecycle_watcher.dart index a02fc8499..5e9ef31c1 100644 --- a/commet/lib/client/components/user_presence/user_presence_lifecycle_watcher.dart +++ b/commet/lib/client/components/user_presence/user_presence_lifecycle_watcher.dart @@ -46,12 +46,10 @@ class UserPresenceLifecycleWatcher { } } - if (clientManager != null) { - for (var client in clientManager!.clients) { - final component = client.getComponent(); - if (component != null) { - component.setStatus(state); - } + for (var client in clientManager.clients) { + final component = client.getComponent(); + if (component != null) { + component.setStatus(state); } } diff --git a/commet/lib/client/matrix/components/account_switch_prefix/matrix_account_switch_prefix.dart b/commet/lib/client/matrix/components/account_switch_prefix/matrix_account_switch_prefix.dart index 813949c3f..cbe642bbc 100644 --- a/commet/lib/client/matrix/components/account_switch_prefix/matrix_account_switch_prefix.dart +++ b/commet/lib/client/matrix/components/account_switch_prefix/matrix_account_switch_prefix.dart @@ -26,7 +26,7 @@ class MatrixAccountSwitchComponent extends AccountSwitchPrefix { @override (Client, String)? getPrefixedAccount(String string, Room currentRoom) { - for (var otherClient in clientManager!.clients) { + for (var otherClient in clientManager.clients) { if (otherClient is! MatrixClient) continue; var component = otherClient.getComponent(); @@ -37,7 +37,7 @@ class MatrixAccountSwitchComponent extends AccountSwitchPrefix { if (string.startsWith(component.clientPrefix!)) { print("Found prefixed client!, $otherClient"); - if (otherClient.hasRoom(currentRoom.identifier)) { + if (otherClient.hasRoom(currentRoom.roomId)) { return (otherClient, component.clientPrefix!); } else { print("Client is not a member of the room!"); @@ -84,7 +84,7 @@ class MatrixAccountSwitchComponent extends AccountSwitchPrefix { @override bool isPossiblyUsingPrefix(String currentText) { - for (var otherClient in clientManager!.clients) { + for (var otherClient in clientManager.clients) { if (otherClient is! MatrixClient) continue; var component = otherClient.getComponent(); diff --git a/commet/lib/client/matrix/components/calendar_room_component/matrix_calendar_room_component.dart b/commet/lib/client/matrix/components/calendar_room_component/matrix_calendar_room_component.dart index bf705fe39..da14eb73e 100644 --- a/commet/lib/client/matrix/components/calendar_room_component/matrix_calendar_room_component.dart +++ b/commet/lib/client/matrix/components/calendar_room_component/matrix_calendar_room_component.dart @@ -157,14 +157,14 @@ class MatrixCalendarRoomComponent room.matrixRoom.client.setAccountDataPerRoom( client.matrixClient.userID!, - room.identifier, + room.roomId, syncedCalendarsEventType, {}); } } if (room.isE2EE) { data = BasicEvent(type: syncedCalendarsEventType, content: { - "remote_calendars": preferences.getCalendarSources(room.identifier) + "remote_calendars": preferences.getCalendarSources(room.roomId) }); } diff --git a/commet/lib/client/matrix/components/direct_messages/matrix_direct_messages_component.dart b/commet/lib/client/matrix/components/direct_messages/matrix_direct_messages_component.dart index 777ee5d88..3741c55c7 100644 --- a/commet/lib/client/matrix/components/direct_messages/matrix_direct_messages_component.dart +++ b/commet/lib/client/matrix/components/direct_messages/matrix_direct_messages_component.dart @@ -36,7 +36,7 @@ class MatrixDirectMessagesComponent MatrixDirectMessagesComponent(this.client) { client.getMatrixClient().onSync.stream.listen(onMatrixSync); EventBus.onSelectedRoomChanged.stream - .listen((value) => currentRoomId = value?.identifier ?? ""); + .listen((value) => currentRoomId = value?.roomId ?? ""); } @override @@ -81,8 +81,7 @@ class MatrixDirectMessagesComponent return client.getRoom(roomId); } - void onRoomAdded(int index) { - var room = client.rooms[index]; + void onRoomAdded(Room room) { if (isRoomDirectMessage(room)) { updateRoomsList(); } @@ -107,16 +106,15 @@ class MatrixDirectMessagesComponent } } - void onRoomRemoved(int index) { - var room = client.rooms[index]; + void onRoomRemoved(Room room) { directMessageRooms.remove(room); listUpdated.add(null); } void updateNotificationsList() { highlightedRoomsList = directMessageRooms - .where((e) => - e.displayNotificationCount > 0 && e.identifier != currentRoomId) + .where( + (e) => e.displayNotificationCount > 0 && e.roomId != currentRoomId) .toList(); highlightedListUpdated.add(null); diff --git a/commet/lib/client/matrix/components/emoticon/matrix_room_emoticon_component.dart b/commet/lib/client/matrix/components/emoticon/matrix_room_emoticon_component.dart index 8a70b6011..4962f009c 100644 --- a/commet/lib/client/matrix/components/emoticon/matrix_room_emoticon_component.dart +++ b/commet/lib/client/matrix/components/emoticon/matrix_room_emoticon_component.dart @@ -42,7 +42,7 @@ class MatrixRoomEmoticonComponent extends MatrixEmoticonComponent bool get canCreatePack => room.permissions.canEditRoomEmoticons; @override - String get ownerId => room.identifier; + String get ownerId => room.roomId; @override String get ownerDisplayName => room.displayName; @@ -52,7 +52,7 @@ class MatrixRoomEmoticonComponent extends MatrixEmoticonComponent List packs = List.from(ownedPacks, growable: true); for (var space in room.client.spaces - .where((element) => element.containsRoom(room.identifier))) { + .where((element) => element.containsRoom(room.roomId))) { var component = space.getComponent(); if (component == null) continue; packs.addAll(component.ownedPacks); @@ -135,7 +135,7 @@ class MatrixRoomEmoticonComponent extends MatrixEmoticonComponent var result = List.of(ownedPacks); for (var space in room.client.spaces - .where((element) => element.containsRoom(room.identifier))) { + .where((element) => element.containsRoom(room.roomId))) { var component = space.getComponent(); if (component != null) { result.addAll(component.ownedPacks.where((e) => !result.contains(e))); diff --git a/commet/lib/client/matrix/components/emoticon/matrix_space_emoticon_component.dart b/commet/lib/client/matrix/components/emoticon/matrix_space_emoticon_component.dart index acbbc63b8..38e568d1b 100644 --- a/commet/lib/client/matrix/components/emoticon/matrix_space_emoticon_component.dart +++ b/commet/lib/client/matrix/components/emoticon/matrix_space_emoticon_component.dart @@ -14,7 +14,7 @@ class MatrixSpaceEmoticonComponent extends MatrixEmoticonComponent bool get canCreatePack => space.permissions.canEditRoomEmoticons; @override - String get ownerId => space.identifier; + String get ownerId => space.roomId; @override String get ownerDisplayName => space.displayName; diff --git a/commet/lib/client/matrix/components/photo_album_room/matrix_photo_album_timeline.dart b/commet/lib/client/matrix/components/photo_album_room/matrix_photo_album_timeline.dart index 97c3e2151..1ee11e104 100644 --- a/commet/lib/client/matrix/components/photo_album_room/matrix_photo_album_timeline.dart +++ b/commet/lib/client/matrix/components/photo_album_room/matrix_photo_album_timeline.dart @@ -19,13 +19,13 @@ class MatrixPhotoAlbumTimeline implements PhotoAlbumTimeline { MatrixPhotoAlbumTimeline(this.room); @override - Stream get onAdded => _photos.onAdd; + Stream get onAdded => _photos.onAdd; @override - Stream get onChanged => _photos.onItemUpdated; + Stream get onChanged => _photos.onItemUpdated; @override - Stream get onRemoved => _photos.onRemove; + Stream get onRemoved => _photos.onRemove; Future initTimeline() async { matrixTimeline = await room.getTimeline(); diff --git a/commet/lib/client/matrix/components/threads/matrix_thread_timeline.dart b/commet/lib/client/matrix/components/threads/matrix_thread_timeline.dart index 32b4184ea..70e8fbf15 100644 --- a/commet/lib/client/matrix/components/threads/matrix_thread_timeline.dart +++ b/commet/lib/client/matrix/components/threads/matrix_thread_timeline.dart @@ -85,7 +85,7 @@ class MatrixThreadTimeline implements Timeline { var mx = client.getMatrixClient(); var data = await mx.request(matrix.RequestType.GET, - "/client/unstable/rooms/${room.identifier}/relations/$threadRootId/m.thread", + "/client/unstable/rooms/${room.roomId}/relations/$threadRootId/m.thread", query: { "limit": limit.toString(), if (nextBatch != null) "from": nextBatch diff --git a/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart b/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart index f7580ee8c..ac4ddf92b 100644 --- a/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart +++ b/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart @@ -89,7 +89,7 @@ class MatrixLivekitBackend { for (var item in fociPreferred) { final map = item as Map; if (map['type'] != "livekit") continue; - if (map['livekit_alias'] != room.identifier) continue; + if (map['livekit_alias'] != room.roomId) continue; return Uri.parse(map['livekit_service_url']); } } @@ -159,7 +159,7 @@ class MatrixLivekitBackend { "foci_preferred": fociUrl .map((e) => { "type": "livekit", - "livekit_alias": room.identifier, + "livekit_alias": room.roomId, "livekit_service_url": e.toString() }) .toList(), diff --git a/commet/lib/client/matrix/components/voip_room/matrix_livekit_voip_session.dart b/commet/lib/client/matrix/components/voip_room/matrix_livekit_voip_session.dart index 07ea4a513..3b0d73a10 100644 --- a/commet/lib/client/matrix/components/voip_room/matrix_livekit_voip_session.dart +++ b/commet/lib/client/matrix/components/voip_room/matrix_livekit_voip_session.dart @@ -28,7 +28,7 @@ class MatrixLivekitVoipSession implements VoipSession { final StreamController _onVolumeChanged = StreamController.broadcast(); MatrixLivekitVoipSession(this.room, this.livekitRoom) { - clientManager?.callManager.onClientSessionStarted(this); + clientManager.callManager.onClientSessionStarted(this); addInitialStreams(); final listener = livekitRoom.createListener(); @@ -147,11 +147,11 @@ class MatrixLivekitVoipSession implements VoipSession { } void onParticipantConnected(lk.ParticipantConnectedEvent event) { - clientManager?.callManager.joinCallSound(); + clientManager.callManager.joinCallSound(); } void onParticipantDisconnected(lk.ParticipantDisconnectedEvent event) { - clientManager?.callManager.endCallSound(); + clientManager.callManager.endCallSound(); } void onLocalTrackPublished(lk.LocalTrackPublishedEvent event) { @@ -203,7 +203,7 @@ class MatrixLivekitVoipSession implements VoipSession { _stateChanged.add(()); _onConnectionChanged.add(state); - clientManager?.callManager.onSessionEnded(this); + clientManager.callManager.onSessionEnded(this); } @override @@ -230,7 +230,7 @@ class MatrixLivekitVoipSession implements VoipSession { String? get remoteUserName => null; @override - String get roomId => room.identifier; + String get roomId => room.roomId; @override String get roomName => room.displayName; diff --git a/commet/lib/client/matrix/components/voip_room/matrix_voip_room_component.dart b/commet/lib/client/matrix/components/voip_room/matrix_voip_room_component.dart index 502b1cf44..acdfa9357 100644 --- a/commet/lib/client/matrix/components/voip_room/matrix_voip_room_component.dart +++ b/commet/lib/client/matrix/components/voip_room/matrix_voip_room_component.dart @@ -113,7 +113,7 @@ class MatrixVoipRoomComponent for (var entry in state.entries) if (entry.value.senderId == client.matrixClient.userID) client.matrixClient.setRoomStateWithKey( - room.identifier, + room.roomId, MatrixVoipRoomComponent.callMemberStateEvent, entry.key, {}, diff --git a/commet/lib/client/matrix/extensions/matrix_client_extensions.dart b/commet/lib/client/matrix/extensions/matrix_client_extensions.dart index 7af9dffd9..7e2a1d283 100644 --- a/commet/lib/client/matrix/extensions/matrix_client_extensions.dart +++ b/commet/lib/client/matrix/extensions/matrix_client_extensions.dart @@ -62,7 +62,8 @@ extension MatrixExtensions on Client { avatar: image, numMembers: numMembers, visibility: visibility, - topic: topic); + topic: topic, + clientId: this.clientName); } return null; diff --git a/commet/lib/client/matrix/matrix_client.dart b/commet/lib/client/matrix/matrix_client.dart index 64c06e94b..346d58fd4 100644 --- a/commet/lib/client/matrix/matrix_client.dart +++ b/commet/lib/client/matrix/matrix_client.dart @@ -21,8 +21,8 @@ import 'package:commet/config/global_config.dart'; import 'package:commet/debug/log.dart'; import 'package:commet/diagnostic/diagnostics.dart'; import 'package:commet/main.dart'; -import 'package:commet/utils/list_extension.dart'; -import 'package:commet/utils/notifying_list.dart'; +import 'package:commet/utils/notifying_map.dart'; +import 'package:commet/utils/notifying_sub_map.dart'; import 'package:commet/utils/stored_stream_controller.dart'; import 'package:flutter/foundation.dart'; import 'package:crypto/crypto.dart'; @@ -53,12 +53,16 @@ class MatrixClient extends Client { late String _id; - final NotifyingList _rooms = NotifyingList.empty(growable: true); - final NotifyingList _spaces = NotifyingList.empty(growable: true); + late final NotifyingMap _rooms = NotifyingSubMap( + clientManager.motifyingMapRoom, (e) => e?.clientId == _id); - final NotifyingList _peers = NotifyingList.empty(growable: true); + late final NotifyingMap _spaces = NotifyingSubMap( + clientManager.motifyingMapSpace, (e) => e?.clientId == _id); - final Map _peersMap = {}; + late final NotifyingMap _peers = NotifyingMap(); + + NotifyingMap get motifyingMapRoom => _rooms; + NotifyingMap get motifyingMapSpace => _spaces; final StreamController _onSync = StreamController.broadcast(); @@ -106,34 +110,34 @@ class MatrixClient extends Client { String get identifier => _id; @override - Stream get onPeerAdded => _peers.onAdd; + Stream get onPeerAdded => _peers.onAdd.map((e) => e.value); @override - Stream get onRoomAdded => _rooms.onAdd; + Stream get onRoomAdded => _rooms.onAdd.map((e) => e.value); @override - Stream get onSpaceAdded => _spaces.onAdd; + Stream get onSpaceAdded => _spaces.onAdd.map((e) => e.value); @override - Stream get onRoomRemoved => _rooms.onRemove; + Stream get onRoomRemoved => _rooms.onRemove.map((e) => e.value); @override - Stream get onSpaceRemoved => _spaces.onRemove; + Stream get onSpaceRemoved => _spaces.onRemove.map((e) => e.value); @override Stream get onSync => _onSync.stream; @override - List get peers => _peers; + Iterable get peers => _peers.values; @override - List get rooms => _rooms; + Iterable get rooms => _rooms.values; @override List get singleRooms => throw UnimplementedError(); @override - List get spaces => _spaces; + Iterable get spaces => _spaces.values; @override StoredStreamController connectionStatusChanged = @@ -393,10 +397,11 @@ class MatrixClient extends Client { for (var room in joinedRooms) { if (hasRoom(room.id)) continue; - rooms.add(MatrixRoom(this, room, _matrixClient)); + var newRoom = MatrixRoom(this, room, _matrixClient); + _rooms[newRoom.localId] = newRoom; } - rooms.removeWhere((e) => !joinedRooms.any((r) => r.id == e.identifier)); + _rooms.removeWhere((k, v) => !joinedRooms.any((r) => r.id == v.roomId)); } void _updateSpacesList() { @@ -408,7 +413,8 @@ class MatrixClient extends Client { bool didChange = false; for (var space in allSpaces) { if (hasSpace(space.id)) continue; - spaces.add(MatrixSpace(this, space, _matrixClient)); + var matrixSpace = MatrixSpace(this, space, _matrixClient); + _spaces[matrixSpace.localId] = matrixSpace; didChange = true; } @@ -483,7 +489,7 @@ class MatrixClient extends Client { if (hasRoom(id)) return getRoom(id)!; var room = MatrixRoom(this, matrixRoom, _matrixClient); - rooms.add(room); + _rooms[room.localId] = room; return room; } @@ -503,7 +509,7 @@ class MatrixClient extends Client { _matrixClient.getRoomById(id)!, _matrixClient, ); - spaces.add(space); + _spaces[space.localId] = space; return space; } @@ -522,7 +528,7 @@ class MatrixClient extends Client { _matrixClient.getRoomById(id)!, _matrixClient, ); - spaces.add(space); + _spaces[space.localId] = space; return space; } @@ -538,7 +544,7 @@ class MatrixClient extends Client { if (hasRoom(id)) return getRoom(id)!; var room = MatrixRoom(this, _matrixClient.getRoomById(id)!, _matrixClient); - rooms.add(room); + _rooms[room.localId] = room; return room; } @@ -566,7 +572,7 @@ class MatrixClient extends Client { @override Iterable getEligibleRoomsForSpace(Space space) { - return rooms.where((room) => !space.containsRoom(room.identifier)); + return rooms.where((room) => !space.containsRoom(room.roomId)); } @override @@ -583,27 +589,29 @@ class MatrixClient extends Client { @override Room? getRoom(String identifier) { - return _rooms.tryFirstWhere((element) => element.identifier == identifier); + return _rooms[BaseRoom.get_localId(identifier, this.identifier)]; } @override Space? getSpace(String identifier) { - return _spaces.tryFirstWhere((element) => element.identifier == identifier); + return _spaces[BaseRoom.get_localId(identifier, this.identifier)]; } @override bool hasPeer(String identifier) { - return _peersMap.containsKey(identifier); + return _peers.containsKey(identifier); } @override bool hasRoom(String identifier) { - return _rooms.any((element) => element.identifier == identifier); + return _rooms + .containsKey(BaseRoom.get_localId(identifier, this.identifier)); } @override bool hasSpace(String identifier) { - return _spaces.any((element) => element.identifier == identifier); + return _spaces + .containsKey(BaseRoom.get_localId(identifier, this.identifier)); } (String, List?)? parseAddressToIdAndVia(String address) { @@ -680,16 +688,16 @@ class MatrixClient extends Client { @override Future leaveRoom(Room room) async { - _rooms.remove(room); + _rooms.remove(room.localId); await room.close(); - return _matrixClient.leaveRoom(room.identifier); + return _matrixClient.leaveRoom(room.roomId); } @override Future leaveSpace(Space space) async { - _spaces.remove(space); + _spaces.remove(space.localId); space.close(); - return _matrixClient.leaveRoom(space.identifier); + return _matrixClient.leaveRoom(space.roomId); } void onSyncStatusChanged(matrix.SyncStatusUpdate event) { diff --git a/commet/lib/client/matrix/matrix_room.dart b/commet/lib/client/matrix/matrix_room.dart index 7bf012dec..ac3fcf675 100644 --- a/commet/lib/client/matrix/matrix_room.dart +++ b/commet/lib/client/matrix/matrix_room.dart @@ -133,7 +133,7 @@ class MatrixRoom extends Room { if (hashColor != null) return hashColor!; - hashColor = MatrixPeer.hashColor(identifier); + hashColor = MatrixPeer.hashColor(roomId); return hashColor!; } @@ -199,7 +199,7 @@ class MatrixRoom extends Room { Client get client => _client; @override - String get identifier => _matrixRoom.id; + String get roomId => _matrixRoom.id; @override Timeline? get timeline => _timeline; @@ -262,7 +262,7 @@ class MatrixRoom extends Room { } void onEvent(matrix.EventUpdate eventUpdate) async { - if (eventUpdate.roomID != identifier) { + if (eventUpdate.roomID != roomId) { return; } @@ -322,7 +322,7 @@ class MatrixRoom extends Room { } // never notify for a message that came from an account we are logged in to! - if (clientManager?.clients + if (clientManager.clients .any((element) => element.self?.identifier == event.senderId) == true) { return false; @@ -633,7 +633,7 @@ class MatrixRoom extends Room { } return client.spaces - .where((space) => space.containsRoom(identifier)) + .where((space) => space.containsRoom(roomId)) .firstOrNull ?.avatar; } @@ -847,4 +847,7 @@ class MatrixRoom extends Room { await tl.setReadMarker(); } + + @override + String get clientId => client.identifier; } diff --git a/commet/lib/client/matrix/matrix_room_preview.dart b/commet/lib/client/matrix/matrix_room_preview.dart index 74e783542..fc90fd41b 100644 --- a/commet/lib/client/matrix/matrix_room_preview.dart +++ b/commet/lib/client/matrix/matrix_room_preview.dart @@ -6,7 +6,7 @@ import 'package:commet/client/room_preview.dart'; import 'package:flutter/widgets.dart'; import 'package:matrix/matrix.dart'; -class MatrixSpaceRoomChunkPreview implements RoomPreview { +class MatrixSpaceRoomChunkPreview extends RoomPreview { SpaceRoomsChunk chunk; Client matrixClient; @override @@ -48,4 +48,7 @@ class MatrixSpaceRoomChunkPreview implements RoomPreview { @override RoomVisibility? get visibility => null; + + @override + String get clientId => matrixClient.clientName; } diff --git a/commet/lib/client/matrix/matrix_space.dart b/commet/lib/client/matrix/matrix_space.dart index 0d5b1e72d..d019126c1 100644 --- a/commet/lib/client/matrix/matrix_space.dart +++ b/commet/lib/client/matrix/matrix_space.dart @@ -125,13 +125,13 @@ class MatrixSpace extends Space { String get displayName => _displayName; @override - String get identifier => _matrixRoom.id; + String get roomId => _matrixRoom.id; @override - Stream get onChildRoomPreviewAdded => _previews.onAdd; + Stream get onChildRoomPreviewAdded => _previews.onAdd; @override - Stream get onChildRoomPreviewRemoved => _previews.onRemove; + Stream get onChildRoomPreviewRemoved => _previews.onRemove; @override Stream get onChildRoomPreviewsUpdated => _previews.onListUpdated; @@ -146,16 +146,16 @@ class MatrixSpace extends Space { List get subspaces => _subspaces; @override - Stream get onChildSpaceAdded => _subspaces.onAdd; + Stream get onChildSpaceAdded => _subspaces.onAdd; @override - Stream get onChildSpaceRemoved => _subspaces.onRemove; + Stream get onChildSpaceRemoved => _subspaces.onRemove; @override - Stream get onRoomAdded => _rooms.onAdd; + Stream get onRoomAdded => _rooms.onAdd; @override - Stream get onRoomRemoved => _rooms.onRemove; + Stream get onRoomRemoved => _rooms.onRemove; @override Stream get onUpdate => _onUpdate.stream; @@ -261,9 +261,8 @@ class MatrixSpace extends Space { _avatar = avatar; } - void onClientRoomRemoved(int index) { - var leftRoom = client.rooms[index]; - if (containsRoom(leftRoom.identifier)) { + void onClientRoomRemoved(Room leftRoom) { + if (containsRoom(leftRoom.roomId)) { _rooms.remove(leftRoom); } } @@ -273,11 +272,11 @@ class MatrixSpace extends Space { var space = client.getSpace(child.roomId!); if (space == null) { - subspaces.removeWhere((e) => e.identifier == child.roomId); + subspaces.removeWhere((e) => e.roomId == child.roomId); } if (space != null) { - if (!subspaces.any((s) => s.identifier == child.roomId)) { + if (!subspaces.any((s) => s.roomId == child.roomId)) { subspaces.add(space); _previews.removeWhere((p) => p.roomId == child.roomId); @@ -286,15 +285,13 @@ class MatrixSpace extends Space { var room = client.getRoom(child.roomId!); if (room == null) { - _rooms.removeWhere((e) => e.identifier == child.roomId); + _rooms.removeWhere((e) => e.roomId == child.roomId); } if (room != null) { - if (!containsRoom(room.identifier) && - !client.hasSpace(room.identifier)) { + if (!containsRoom(room.roomId) && !client.hasSpace(room.roomId)) { _rooms.add(room); - _previews - .removeWhere((element) => element.roomId == room.identifier); + _previews.removeWhere((element) => element.roomId == room.roomId); } } } @@ -308,15 +305,14 @@ class MatrixSpace extends Space { } _rooms.sort((a, b) { - var orderA = orders[a.identifier] ?? ""; - var orderB = orders[b.identifier] ?? ""; + var orderA = orders[a.roomId] ?? ""; + var orderB = orders[b.roomId] ?? ""; return orderA.compareTo(orderB); }); } - void _onRoomAdded(int index) { - var room = _rooms[index]; + void _onRoomAdded(Room room) { _subscriptions.add(room.onUpdate.listen((event) { _onChildUpdated.add(room); })); @@ -325,17 +321,16 @@ class MatrixSpace extends Space { @override Future createRoom(String name, CreateRoomArgs args) async { var room = await client.createRoom(args); - _matrixRoom.setSpaceChild(room.identifier); + _matrixRoom.setSpaceChild(room.roomId); return room; } @override Future> fetchChildren() async { - var response = - await _matrixClient.getSpaceHierarchy(identifier, maxDepth: 5); + var response = await _matrixClient.getSpaceHierarchy(roomId, maxDepth: 5); return response.rooms - .where((element) => element.roomId != identifier) + .where((element) => element.roomId != roomId) .where((element) => !containsRoom(element.roomId)) .map((e) => MatrixSpaceRoomChunkPreview(e, _matrixClient)) .toList(); @@ -356,12 +351,11 @@ class MatrixSpace extends Space { @override Future loadExtra() async { - var response = - await _matrixClient.getSpaceHierarchy(identifier, maxDepth: 1); + var response = await _matrixClient.getSpaceHierarchy(roomId, maxDepth: 1); // read child rooms response.rooms - .where((element) => element.roomId != identifier) + .where((element) => element.roomId != roomId) .where((element) => _matrixClient.getRoomById(element.roomId)?.membership != matrix.Membership.join) @@ -394,21 +388,21 @@ class MatrixSpace extends Space { @override Future setSpaceChildRoom(Room room) async { - await _matrixRoom.setSpaceChild(room.identifier); + await _matrixRoom.setSpaceChild(room.roomId); children.add(SpaceChildRoom(room)); _onUpdate.add(null); } @override Future setSpaceChildSpace(Space room) async { - await _matrixRoom.setSpaceChild(room.identifier); + await _matrixRoom.setSpaceChild(room.roomId); children.add(SpaceChildSpace(room)); _onUpdate.add(null); } @override bool containsRoom(String identifier) { - return _rooms.any((element) => element.identifier == identifier); + return _rooms.any((element) => element.roomId == identifier); } @override @@ -425,7 +419,7 @@ class MatrixSpace extends Space { if (update == null) return; for (var id in update.keys) { - if (roomsWithChildren.any((i) => i.identifier == id)) { + if (roomsWithChildren.any((i) => i.roomId == id)) { _updateTopLevelStatus(); _onUpdate.add(null); } @@ -501,4 +495,7 @@ class MatrixSpace extends Space { Future removeChild(SpaceChild child) async { await matrixRoom.removeSpaceChild(child.id); } + + @override + String get clientId => client.identifier; } diff --git a/commet/lib/client/matrix_background/matrix_background_client.dart b/commet/lib/client/matrix_background/matrix_background_client.dart index a1a894c75..477ab0799 100644 --- a/commet/lib/client/matrix_background/matrix_background_client.dart +++ b/commet/lib/client/matrix_background/matrix_background_client.dart @@ -51,19 +51,19 @@ class MatrixBackgroundClient implements Client { int? get maxFileSize => 0; @override - Stream get onPeerAdded => Stream.empty(); + Stream get onPeerAdded => Stream.empty(); @override - Stream get onRoomAdded => Stream.empty(); + Stream get onRoomAdded => Stream.empty(); @override - Stream get onRoomRemoved => Stream.empty(); + Stream get onRoomRemoved => Stream.empty(); @override - Stream get onSpaceAdded => Stream.empty(); + Stream get onSpaceAdded => Stream.empty(); @override - Stream get onSpaceRemoved => Stream.empty(); + Stream get onSpaceRemoved => Stream.empty(); @override Stream get onSync => Stream.empty(); diff --git a/commet/lib/client/matrix_background/matrix_background_direct_messages_component.dart b/commet/lib/client/matrix_background/matrix_background_direct_messages_component.dart index 87313db69..1909b064f 100644 --- a/commet/lib/client/matrix_background/matrix_background_direct_messages_component.dart +++ b/commet/lib/client/matrix_background/matrix_background_direct_messages_component.dart @@ -33,7 +33,7 @@ class MatrixBackgroundClientDirectMessagesComponent var item = pair.value; Log.i(item); var list = item as List; - if (list.contains(room.identifier)) { + if (list.contains(room.roomId)) { return key; } } @@ -58,7 +58,7 @@ class MatrixBackgroundClientDirectMessagesComponent for (var item in content.values) { Log.i(item); var list = item as List; - if (list.contains(room.identifier)) { + if (list.contains(room.roomId)) { Log.i("Found room id in account info, this is a direct message"); return true; } diff --git a/commet/lib/client/matrix_background/matrix_background_room.dart b/commet/lib/client/matrix_background/matrix_background_room.dart index 26a4342f5..2806202c9 100644 --- a/commet/lib/client/matrix_background/matrix_background_room.dart +++ b/commet/lib/client/matrix_background/matrix_background_room.dart @@ -69,7 +69,7 @@ class MatrixBackgroundRoom implements Room { } if (displayName == "") { - displayName = identifier; + displayName = roomId; } if (avatarId != null) { @@ -105,7 +105,7 @@ class MatrixBackgroundRoom implements Room { } @override - Color get defaultColor => getColorOfUser(identifier); + Color get defaultColor => getColorOfUser(roomId); @override String get developerInfo => throw UnimplementedError(); @@ -128,8 +128,7 @@ class MatrixBackgroundRoom implements Room { Future fetchMember(String id) async { var db = backgroundClient.database.db; var data = await (db.select(db.roomMembers) - ..where( - (tbl) => tbl.roomId.equals(identifier) & tbl.userId.equals(id))) + ..where((tbl) => tbl.roomId.equals(roomId) & tbl.userId.equals(id))) .getSingleOrNull(); MatrixBackgroundMember result = MatrixBackgroundMember(id); @@ -163,8 +162,7 @@ class MatrixBackgroundRoom implements Room { @override Future?> getEvent(String eventId) async { - var result = - await backgroundClient.api.getOneRoomEvent(identifier, eventId); + var result = await backgroundClient.api.getOneRoomEvent(roomId, eventId); Log.i("Received event: ${result}"); if ([ @@ -203,9 +201,6 @@ class MatrixBackgroundRoom implements Room { @override IconData get icon => throw UnimplementedError(); - @override - String get identifier => roomId; - @override List<(Member, Role)> importantMembers() { throw UnimplementedError(); @@ -349,4 +344,8 @@ class MatrixBackgroundRoom implements Room { // TODO: implement markAsRead throw UnimplementedError(); } + + @override + // TODO: implement clientId + String get clientId => client.identifier; } diff --git a/commet/lib/client/room.dart b/commet/lib/client/room.dart index 1778926af..14670f608 100644 --- a/commet/lib/client/room.dart +++ b/commet/lib/client/room.dart @@ -18,10 +18,31 @@ enum RoomVisibility { public, private, invite, knock } enum PushRule { notify, mentionsOnly, dontNotify } +abstract class BaseRoom { + String get roomId; + String get clientId; + + /// A locally unique identifier, to distinguish between rooms when two or more accounts in this app are in the same room + String get localId => get_localId(roomId, clientId); + + static get_localId(String roomId, String clientId) { + return "${clientId}:${roomId}"; + } + + @override + bool operator ==(Object other) { + if (other is! BaseRoom) return false; + if (identical(this, other)) return true; + return localId == other.localId; + } + + @override + int get hashCode => localId.hashCode; +} + /// The Room object should only be used for rooms which the user is a member of. /// Rooms which the user has not joined should be represented with a RoomPreview -abstract class Room { - String get identifier; +abstract class Room extends BaseRoom { Client get client; final Key key = UniqueKey(); @@ -140,9 +161,6 @@ abstract class Room { bool get isMembersListComplete; - /// A locally unique identifier, to distinguish between rooms when two or more accounts in this app are in the same room - String get localId => "${client.identifier}:$identifier"; - /// Update the display name of this room Future setDisplayName(String newName); @@ -193,15 +211,4 @@ abstract class Room { Future setTopic(String topic); Future markAsRead(); - - @override - bool operator ==(Object other) { - if (other is! Room) return false; - if (other.client != client) return false; - if (identical(this, other)) return true; - return identifier == other.identifier; - } - - @override - int get hashCode => identifier.hashCode; } diff --git a/commet/lib/client/room_preview.dart b/commet/lib/client/room_preview.dart index a58d72cab..4cfe48c22 100644 --- a/commet/lib/client/room_preview.dart +++ b/commet/lib/client/room_preview.dart @@ -1,11 +1,9 @@ import 'package:commet/client/client.dart'; -import 'package:commet/client/room.dart'; import 'package:flutter/material.dart'; enum RoomPreviewType { room, space, inaccessible } -abstract class RoomPreview { - String get roomId; +abstract class RoomPreview extends BaseRoom { ImageProvider? get avatar; String get displayName; String? get topic; @@ -15,7 +13,7 @@ abstract class RoomPreview { RoomVisibility? get visibility; } -class GenericRoomPreview implements RoomPreview { +class GenericRoomPreview extends RoomPreview { @override String roomId; @@ -39,11 +37,15 @@ class GenericRoomPreview implements RoomPreview { required this.type, this.numMembers, this.visibility, - this.topic}); + this.topic, + required this.clientId}); @override Color get color => Colors.grey; @override RoomVisibility? visibility; + + @override + final String clientId; } diff --git a/commet/lib/client/space.dart b/commet/lib/client/space.dart index 851670da1..36a33eedb 100644 --- a/commet/lib/client/space.dart +++ b/commet/lib/client/space.dart @@ -8,11 +8,9 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:commet/debug/log.dart'; -abstract class Space { +abstract class Space extends BaseRoom { late Key key = UniqueKey(); - String get identifier; - Client get client; Permissions get permissions; @@ -78,19 +76,19 @@ abstract class Space { Stream get onChildRoomUpdated; - Stream get onRoomAdded; + Stream get onRoomAdded; - Stream get onRoomRemoved; + Stream get onRoomRemoved; Stream get onChildRoomsUpdated; - Stream get onChildRoomPreviewAdded; + Stream get onChildRoomPreviewAdded; - Stream get onChildRoomPreviewRemoved; + Stream get onChildRoomPreviewRemoved; - Stream get onChildSpaceAdded; + Stream get onChildSpaceAdded; - Stream get onChildSpaceRemoved; + Stream get onChildSpaceRemoved; Stream get onChildRoomPreviewsUpdated; @@ -98,7 +96,7 @@ abstract class Space { bool get fullyLoaded; - String get localId => "${client.identifier}:$identifier"; + String get localId => "${client.identifier}:$roomId"; int get notificationCount => roomsWithChildren .where((element) => element.pushRule == PushRule.notify) @@ -153,9 +151,9 @@ abstract class Space { if (other is! Space) return false; if (other.client != client) return false; if (identical(this, other)) return true; - return identifier == other.identifier; + return roomId == other.roomId; } @override - int get hashCode => identifier.hashCode; + int get hashCode => roomId.hashCode; } diff --git a/commet/lib/client/space_child.dart b/commet/lib/client/space_child.dart index bf2dc8d21..501b56ab7 100644 --- a/commet/lib/client/space_child.dart +++ b/commet/lib/client/space_child.dart @@ -12,7 +12,7 @@ class SpaceChildRoom implements SpaceChild { final T child; @override - String get id => child.identifier; + String get id => child.roomId; SpaceChildRoom(this.child); } @@ -22,7 +22,7 @@ class SpaceChildSpace implements SpaceChild { final T child; @override - String get id => child.identifier; + String get id => child.roomId; SpaceChildSpace(this.child); } diff --git a/commet/lib/main.dart b/commet/lib/main.dart index 18eb080a9..6b7717fd9 100644 --- a/commet/lib/main.dart +++ b/commet/lib/main.dart @@ -53,7 +53,7 @@ FileCache? fileCache; Preferences preferences = Preferences(); ShortcutsManager shortcutsManager = ShortcutsManager(); BackgroundTaskManager backgroundTaskManager = BackgroundTaskManager(); -ClientManager? clientManager; +ClientManager get clientManager => ClientManager.instance; bool isHeadless = false; @@ -111,11 +111,11 @@ void bubble() async { GlobalCupertinoLocalizations.delegate, ], builder: (context, child) => Provider( - create: (context) => clientManager!, + create: (context) => ClientManager.instance, child: child, ), home: BubblePage( - clientManager!, + clientManager, initialClientId: initialClientId, initialRoom: initialRoomId, ))); @@ -202,7 +202,7 @@ Future initNecessary() async { GlobalConfig.init(), ]); - clientManager = await ClientManager.init(); + await ClientManager.init(); Diagnostics.setPostInit(); shortcutsManager.init(); @@ -272,7 +272,7 @@ Future startGui() async { } runApp(App( - clientManager: clientManager!, + clientManager: clientManager, initialTheme: initialTheme, initialClientId: initialClientId, initialRoom: initialRoomId, diff --git a/commet/lib/service/background_service_notifications/background_service_task_notification.dart b/commet/lib/service/background_service_notifications/background_service_task_notification.dart index 516a277d4..257e29a47 100644 --- a/commet/lib/service/background_service_notifications/background_service_task_notification.dart +++ b/commet/lib/service/background_service_notifications/background_service_task_notification.dart @@ -47,7 +47,7 @@ class BackgroundNotificationsManager { shortcutsManager.init(); - clientManager = await ClientManager.init(isBackgroundService: true); + await ClientManager.init(isBackgroundService: true); } void onReceived(Map? data) async { @@ -94,7 +94,7 @@ class BackgroundNotificationsManager { var eventId = data["event_id"] as String; var client = - clientManager!.clients.firstWhere((element) => element.hasRoom(roomId)); + clientManager.clients.firstWhere((element) => element.hasRoom(roomId)); Log.i("Found client: ${client.identifier}"); var room = client.getRoom(roomId); @@ -124,7 +124,7 @@ class BackgroundNotificationsManager { roomName: room.displayName, content: event.plainTextBody, eventId: eventId, - roomId: room.identifier, + roomId: room.roomId, clientId: client.identifier, senderImage: user.avatar, roomImage: room.avatar, diff --git a/commet/lib/service/background_service_notifications/background_service_task_notification2.dart b/commet/lib/service/background_service_notifications/background_service_task_notification2.dart index c981791f0..76a7d5884 100644 --- a/commet/lib/service/background_service_notifications/background_service_task_notification2.dart +++ b/commet/lib/service/background_service_notifications/background_service_task_notification2.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:commet/cache/file_cache.dart'; -import 'package:commet/client/client_manager.dart'; import 'package:commet/client/components/direct_messages/direct_message_component.dart'; import 'package:commet/client/components/push_notification/notification_content.dart'; import 'package:commet/client/components/push_notification/notification_manager.dart'; @@ -22,7 +21,7 @@ class BackgroundNotificationsManager2 { List> queue = List.empty(growable: true); Future init() async { - if (fileCache == null || clientManager == null) { + if (fileCache == null) { await initDatabaseServer(); } @@ -34,17 +33,13 @@ class BackgroundNotificationsManager2 { } } - if (clientManager == null) { - clientManager = ClientManager(); - - final clients = preferences.getRegisteredMatrixClients(); - if (clients != null) { - for (var id in clients) { - var client = MatrixBackgroundClient(databaseId: id); - Log.i("Adding background matrix client: ${id}"); - await client.init(true, isBackgroundService: true); - clientManager!.addClient(client); - } + final clients = preferences.getRegisteredMatrixClients(); + if (clients != null) { + for (var id in clients) { + var client = MatrixBackgroundClient(databaseId: id); + Log.i("Adding background matrix client: ${id}"); + await client.init(true, isBackgroundService: true); + clientManager.addClient(client); } } @@ -109,7 +104,7 @@ class BackgroundNotificationsManager2 { return; } - var client = clientManager!.clients + var client = clientManager.clients .firstWhereOrNull((element) => element.hasRoom(roomId)); // If the room does not already belong to any of our clients, it must be an invite diff --git a/commet/lib/ui/atoms/rich_text/matrix_html_parser.dart b/commet/lib/ui/atoms/rich_text/matrix_html_parser.dart index a9aee7f3c..147ec9829 100644 --- a/commet/lib/ui/atoms/rich_text/matrix_html_parser.dart +++ b/commet/lib/ui/atoms/rich_text/matrix_html_parser.dart @@ -194,7 +194,7 @@ class _MatrixHtmlStateState extends State { LinkUtils.open(uri, clientId: widget.client.identifier, context: context, - contextRoomId: widget.room?.identifier); + contextRoomId: widget.room?.roomId); } } @@ -438,7 +438,7 @@ class LinkifyHtmlExtension extends HtmlExtension { mentionedRoom?.defaultColor ?? MatrixPeer.hashColor(mxid), avatar: mentionedRoom?.avatar, onTap: () => LinkUtils.open(href, - clientId: client.identifier, contextRoomId: room?.identifier), + clientId: client.identifier, contextRoomId: room?.roomId), ); } diff --git a/commet/lib/ui/atoms/rich_text_field.dart b/commet/lib/ui/atoms/rich_text_field.dart index 22f637e42..306ef1a3a 100644 --- a/commet/lib/ui/atoms/rich_text_field.dart +++ b/commet/lib/ui/atoms/rich_text_field.dart @@ -6,7 +6,6 @@ import 'package:commet/client/matrix/components/emoticon/matrix_emoticon.dart'; import 'package:commet/client/matrix/components/emoticon/matrix_emoticon_component.dart'; import 'package:commet/client/matrix/components/emoticon/matrix_room_emoticon_component.dart'; import 'package:commet/client/matrix/matrix_client.dart'; -import 'package:commet/client/room.dart'; import 'package:commet/main.dart'; import 'package:commet/ui/atoms/emoji_widget.dart'; import 'package:commet/ui/atoms/mention.dart'; diff --git a/commet/lib/ui/atoms/room_header.dart b/commet/lib/ui/atoms/room_header.dart index eee6f9d2c..0422169ad 100644 --- a/commet/lib/ui/atoms/room_header.dart +++ b/commet/lib/ui/atoms/room_header.dart @@ -274,9 +274,9 @@ class _HeaderBurgerState extends State { super.initState(); color = widget.notificationColor; subs = [ - clientManager!.directMessages.onHighlightedRoomsListUpdated + clientManager.directMessages.onHighlightedRoomsListUpdated .listen((_) => updateState()), - clientManager!.onSpaceUpdated.stream.listen((_) => updateState()), + clientManager.onSpaceUpdated.stream.listen((_) => updateState()), ]; updateNotificationCount(); @@ -299,14 +299,14 @@ class _HeaderBurgerState extends State { notificationCount = 0; var topLevelSpaces = - clientManager!.spaces.where((e) => e.isTopLevel).toList(); + clientManager.spaces.where((e) => e.isTopLevel).toList(); for (var i in topLevelSpaces) { highlightedNotificationCount += i.displayHighlightedNotificationCount; notificationCount += i.displayNotificationCount; } - for (var dm in clientManager!.directMessages.highlightedRoomsList) { + for (var dm in clientManager.directMessages.highlightedRoomsList) { highlightedNotificationCount += dm.displayNotificationCount; notificationCount += dm.displayNotificationCount; } diff --git a/commet/lib/ui/atoms/room_preview.dart b/commet/lib/ui/atoms/room_preview.dart index 839d3326f..e3c690cfb 100644 --- a/commet/lib/ui/atoms/room_preview.dart +++ b/commet/lib/ui/atoms/room_preview.dart @@ -1,5 +1,4 @@ import 'package:commet/client/client.dart'; -import 'package:commet/client/room.dart'; import 'package:commet/client/room_preview.dart'; import 'package:flutter/material.dart'; import 'package:tiamat/tiamat.dart'; diff --git a/commet/lib/ui/atoms/space_icon.dart b/commet/lib/ui/atoms/space_icon.dart index 7ff2aa844..e3c37d0c0 100644 --- a/commet/lib/ui/atoms/space_icon.dart +++ b/commet/lib/ui/atoms/space_icon.dart @@ -60,7 +60,7 @@ class _SpaceIconState extends State { void onSelectedSpaceChanged(Space? event) { setState(() { - selected = event?.identifier == widget.spaceId; + selected = event?.roomId == widget.spaceId; }); } diff --git a/commet/lib/ui/molecules/space_selector.dart b/commet/lib/ui/molecules/space_selector.dart index 852387284..6226c2e8a 100644 --- a/commet/lib/ui/molecules/space_selector.dart +++ b/commet/lib/ui/molecules/space_selector.dart @@ -128,7 +128,7 @@ class _SpaceSelectorState extends State { onUpdate: onUpdate, avatar: avatar, userAvatar: userAvatar, - spaceId: space.identifier, + spaceId: space.roomId, userColor: userColor, userDisplayName: userDisplayName, highlightedNotificationCount: highlightedNotificationCount, diff --git a/commet/lib/ui/molecules/timeline_events/events/timeline_event_view_thread.dart b/commet/lib/ui/molecules/timeline_events/events/timeline_event_view_thread.dart index f7a5d4180..6d91e81a3 100644 --- a/commet/lib/ui/molecules/timeline_events/events/timeline_event_view_thread.dart +++ b/commet/lib/ui/molecules/timeline_events/events/timeline_event_view_thread.dart @@ -67,7 +67,7 @@ class _TimelineEventViewThreadState extends State { senderColor: senderColor, onTap: () => EventBus.openThread.add(( widget.timeline.client.identifier, - widget.timeline.room.identifier, + widget.timeline.room.roomId, threadEventId )), ); diff --git a/commet/lib/ui/molecules/timeline_events/timeline_event_menu.dart b/commet/lib/ui/molecules/timeline_events/timeline_event_menu.dart index eb1ced059..8e762ebb5 100644 --- a/commet/lib/ui/molecules/timeline_events/timeline_event_menu.dart +++ b/commet/lib/ui/molecules/timeline_events/timeline_event_menu.dart @@ -287,7 +287,7 @@ class TimelineEventMenu { action: (context) { EventBus.openThread.add(( timeline.client.identifier, - timeline.room.identifier, + timeline.room.roomId, event.eventId, )); onActionFinished?.call(); diff --git a/commet/lib/ui/navigation/adaptive_dialog.dart b/commet/lib/ui/navigation/adaptive_dialog.dart index 6042828c7..f44260dd2 100644 --- a/commet/lib/ui/navigation/adaptive_dialog.dart +++ b/commet/lib/ui/navigation/adaptive_dialog.dart @@ -78,14 +78,14 @@ class AdaptiveDialog { bool dismissible = true, double initialHeightMobile = 0.5, }) async { - if (clientManager?.clients.length == 1) { - return clientManager!.clients.first; + if (clientManager.clients.length == 1) { + return clientManager.clients.first; } return AdaptiveDialog.pickOne( context, title: "Pick Account", - items: clientManager!.clients, + items: clientManager.clients, itemBuilder: (context, item, callback) { return SizedBox( child: UserPanelView( diff --git a/commet/lib/ui/organisms/call_view/call.dart b/commet/lib/ui/organisms/call_view/call.dart index e783b5081..4a93f3335 100644 --- a/commet/lib/ui/organisms/call_view/call.dart +++ b/commet/lib/ui/organisms/call_view/call.dart @@ -42,9 +42,9 @@ class _CallWidgetState extends State { Future setMicrophoneMute(bool isMuted) { if (isMuted) { - clientManager?.callManager.playMuteSound(); + clientManager.callManager.playMuteSound(); } else { - clientManager?.callManager.playUnmuteSound(); + clientManager.callManager.playUnmuteSound(); } return widget.session.setMicrophoneMute(isMuted); diff --git a/commet/lib/ui/organisms/chat/chat.dart b/commet/lib/ui/organisms/chat/chat.dart index f949bdbc9..4f7bc4075 100644 --- a/commet/lib/ui/organisms/chat/chat.dart +++ b/commet/lib/ui/organisms/chat/chat.dart @@ -207,7 +207,7 @@ class ChatState extends State { var targetThread = threadsComponent; if (overrideClient != null) { - var newRoom = overrideClient.getRoom(targetRoom.identifier); + var newRoom = overrideClient.getRoom(targetRoom.roomId); if (newRoom != null) { targetRoom = newRoom; targetThread = targetRoom.client.getComponent(); diff --git a/commet/lib/ui/organisms/chat/chat_view.dart b/commet/lib/ui/organisms/chat/chat_view.dart index 9de511cd7..93260cac8 100644 --- a/commet/lib/ui/organisms/chat/chat_view.dart +++ b/commet/lib/ui/organisms/chat/chat_view.dart @@ -60,7 +60,7 @@ class ChatView extends StatelessWidget { child: CircularProgressIndicator(), ) : RoomTimelineWidget( - key: ValueKey("${state.room.identifier}-timeline"), + key: ValueKey("${state.room.roomId}-timeline"), timeline: state.timeline!, setReplyingEvent: (event) => state.setInteractingEvent(event, type: EventInteractionType.reply), @@ -140,14 +140,13 @@ class ChatView extends StatelessWidget { ?.getPrefixedAccount(input, state.room) ?.$1, onTapOverrideClient: (overrideClient) { - EventBus.openRoom - .add((state.room.identifier, overrideClient.identifier)); + EventBus.openRoom.add((state.room.roomId, overrideClient.identifier)); if (state.isThread) { WidgetsBinding.instance.addPostFrameCallback((_) { EventBus.openThread.add(( overrideClient.identifier, - state.room.identifier, + state.room.roomId, state.threadId! )); }); @@ -165,8 +164,8 @@ class ChatView extends StatelessWidget { typingIndicatorWidget: state.typingIndicators != null ? TypingIndicatorsWidget( component: state.typingIndicators!, - key: ValueKey( - "room_typing_indicators_key_${state.room.identifier}"), + key: + ValueKey("room_typing_indicators_key_${state.room.roomId}"), ) : null, processAutofill: (text) => diff --git a/commet/lib/ui/organisms/home_screen/home_screen.dart b/commet/lib/ui/organisms/home_screen/home_screen.dart index d0d930e5d..c17195b3f 100644 --- a/commet/lib/ui/organisms/home_screen/home_screen.dart +++ b/commet/lib/ui/organisms/home_screen/home_screen.dart @@ -71,10 +71,8 @@ class _HomeScreenState extends State { } void onSync(void event) { - Future.delayed(Duration(seconds: 1)).then((_) { - setState(() { - updateRecent(); - }); + setState(() { + updateRecent(); }); } @@ -131,7 +129,7 @@ class _HomeScreenState extends State { .singleRooms(filterClient: filterClient), recentActivity: recentActivity, onRoomClicked: (room) => EventBus.openRoom - .add((room.identifier, room.client.identifier)), + .add((room.roomId, room.client.identifier)), joinRoom: joinRoom, createRoom: createRoom, ), diff --git a/commet/lib/ui/organisms/home_screen/home_screen_view.dart b/commet/lib/ui/organisms/home_screen/home_screen_view.dart index f6def7809..bda3a502c 100644 --- a/commet/lib/ui/organisms/home_screen/home_screen_view.dart +++ b/commet/lib/ui/organisms/home_screen/home_screen_view.dart @@ -118,7 +118,7 @@ class HomeScreenView extends StatelessWidget { : null, onTap: () => onRoomClicked?.call(room), showUserAvatar: clientManager.rooms - .where((element) => element.identifier == room.identifier) + .where((element) => element.roomId == room.roomId) .length > 1, userAvatar: room.client.self!.avatar, @@ -158,8 +158,7 @@ class HomeScreenView extends StatelessWidget { : null, onTap: () => onRoomClicked?.call(room), showUserAvatar: clientManager.rooms - .where((element) => - element.identifier == room.identifier) + .where((element) => element.roomId == room.roomId) .length > 1, userAvatar: room.client.self!.avatar, diff --git a/commet/lib/ui/organisms/photo_albums/photo_album_view.dart b/commet/lib/ui/organisms/photo_albums/photo_album_view.dart index 39c6293d1..21b5e88b8 100644 --- a/commet/lib/ui/organisms/photo_albums/photo_album_view.dart +++ b/commet/lib/ui/organisms/photo_albums/photo_album_view.dart @@ -43,7 +43,7 @@ class _PhotoAlbumViewState extends State { late List subs; - void onAdded(int event) { + void onAdded(Photo event) { setState(() { numItems = timeline!.photos.length; }); @@ -397,13 +397,13 @@ class _PhotoAlbumViewState extends State { builder: (_) => PhotosAlbumUploadView(f, widget.component)); } - void onChanged(int event) { + void onChanged(Photo event) { setState(() { numItems = timeline!.photos.length; }); } - void onRemoved(int event) { + void onRemoved(Photo event) { setState(() { numItems = timeline!.photos.length; }); diff --git a/commet/lib/ui/organisms/room_quick_access_menu/room_quick_access_menu.dart b/commet/lib/ui/organisms/room_quick_access_menu/room_quick_access_menu.dart index 0a70a6105..1347b606f 100644 --- a/commet/lib/ui/organisms/room_quick_access_menu/room_quick_access_menu.dart +++ b/commet/lib/ui/organisms/room_quick_access_menu/room_quick_access_menu.dart @@ -39,7 +39,7 @@ class RoomQuickAccessMenu { builder: (context) => SendInvitationWidget( room.client, invitation, - roomId: room.identifier, + roomId: room.roomId, displayName: room.displayName, existingMembers: room.memberIds, ), @@ -48,8 +48,7 @@ class RoomQuickAccessMenu { if (canCall) RoomQuickAccessMenuEntry( name: "Call", - action: (context) => - calls.startCall(room.identifier, CallType.voice), + action: (context) => calls.startCall(room.roomId, CallType.voice), icon: Icons.call), if (!preferences.hideRoomSidePanel) ...[ if (calendar?.hasCalendar == true && calendar?.isCalendarRoom == false) diff --git a/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar.dart b/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar.dart index 35f9a2e33..1a55b0c18 100644 --- a/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar.dart +++ b/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar.dart @@ -207,7 +207,7 @@ class _SideNavigationBarState extends State { bool shouldShowAvatarForSpace(Space space) { var spaces = _clientManager.spaces - .where((element) => element.identifier == space.identifier); + .where((element) => element.roomId == space.roomId); return spaces.length > 1; } } diff --git a/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar_direct_messages.dart b/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar_direct_messages.dart index 540ba67c4..bd07a198a 100644 --- a/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar_direct_messages.dart +++ b/commet/lib/ui/organisms/side_navigation_bar/side_navigation_bar_direct_messages.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:commet/client/client.dart'; import 'package:commet/client/components/direct_messages/direct_message_component.dart'; -import 'package:commet/client/room.dart'; import 'package:commet/ui/atoms/space_icon.dart'; import 'package:commet/utils/event_bus.dart'; import 'package:flutter/material.dart'; @@ -82,7 +81,7 @@ class _SideNavigationBarDirectMessagesState return SpaceIcon( displayName: data.displayName, placeholderColor: data.defaultColor, - spaceId: data.identifier, + spaceId: data.roomId, avatar: data.avatar, width: 70, highlightedNotificationCount: data.notificationCount, diff --git a/commet/lib/ui/organisms/sidebar_call_icon/sidebar_calls_list.dart b/commet/lib/ui/organisms/sidebar_call_icon/sidebar_calls_list.dart index 0cf197ae4..056e63f0d 100644 --- a/commet/lib/ui/organisms/sidebar_call_icon/sidebar_calls_list.dart +++ b/commet/lib/ui/organisms/sidebar_call_icon/sidebar_calls_list.dart @@ -44,7 +44,7 @@ class _SidebarCallsListState extends State { }); sessions.onRemove.listen((event) { - if (sessions[event] == selectedSession) { + if (event == selectedSession) { setState(() { selectedSession = null; link = null; diff --git a/commet/lib/ui/organisms/space_summary/space_summary.dart b/commet/lib/ui/organisms/space_summary/space_summary.dart index 3cf09925f..a7c35c168 100644 --- a/commet/lib/ui/organisms/space_summary/space_summary.dart +++ b/commet/lib/ui/organisms/space_summary/space_summary.dart @@ -123,7 +123,7 @@ class _SpaceSummaryState extends State { AdaptiveDialog.show(context, builder: (context) => SendInvitationWidget( widget.space.client, invitation, - roomId: widget.space.identifier, + roomId: widget.space.roomId, displayName: widget.space.displayName), title: "Invite"); } diff --git a/commet/lib/ui/organisms/space_summary/space_summary_view.dart b/commet/lib/ui/organisms/space_summary/space_summary_view.dart index a993d345f..4d61e28ab 100644 --- a/commet/lib/ui/organisms/space_summary/space_summary_view.dart +++ b/commet/lib/ui/organisms/space_summary/space_summary_view.dart @@ -372,7 +372,7 @@ class SpaceSummaryViewState extends State { ImplicitlyAnimatedList( padding: EdgeInsets.all(0), key: ValueKey( - "animated-list-child-previews-${widget.space.identifier}"), + "animated-list-child-previews-${widget.space.roomId}"), initialAnimation: false, physics: NeverScrollableScrollPhysics(), itemData: previews, diff --git a/commet/lib/ui/organisms/user_profile/user_profile.dart b/commet/lib/ui/organisms/user_profile/user_profile.dart index da39092ff..f39ef7a6f 100644 --- a/commet/lib/ui/organisms/user_profile/user_profile.dart +++ b/commet/lib/ui/organisms/user_profile/user_profile.dart @@ -257,11 +257,11 @@ class _UserProfileState extends State { if (existingRooms.isNotEmpty == true) { EventBus.openRoom - .add((existingRooms.first.identifier, widget.client.identifier)); + .add((existingRooms.first.roomId, widget.client.identifier)); } else { var room = await component.createDirectMessage(profile!.identifier); if (room != null) { - EventBus.openRoom.add((room.identifier, widget.client.identifier)); + EventBus.openRoom.add((room.roomId, widget.client.identifier)); } } diff --git a/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart b/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart index d6d19e925..856dffb70 100644 --- a/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart +++ b/commet/lib/ui/pages/developer/benchmarks/benchmark_utils.dart @@ -34,7 +34,7 @@ extension BenchmarkUtils on MatrixClient { }, mxRoom)); var room = MatrixRoom(this, mxRoom, getMatrixClient()); - rooms.add(room); + motifyingMapRoom[room.localId] = room; return room; } } diff --git a/commet/lib/ui/pages/login/login_page.dart b/commet/lib/ui/pages/login/login_page.dart index 7b98c36ad..6ac320af2 100644 --- a/commet/lib/ui/pages/login/login_page.dart +++ b/commet/lib/ui/pages/login/login_page.dart @@ -125,7 +125,7 @@ class LoginPageState extends State { } if (result == LoginResult.success) { - clientManager?.addClient(loginClient!); + clientManager.addClient(loginClient!); widget.onSuccess?.call(loginClient!); } } diff --git a/commet/lib/ui/pages/main/main_page.dart b/commet/lib/ui/pages/main/main_page.dart index caa982af2..3dc60a8fe 100644 --- a/commet/lib/ui/pages/main/main_page.dart +++ b/commet/lib/ui/pages/main/main_page.dart @@ -67,7 +67,7 @@ class MainPageState extends State { VoipSession? get currentCall => currentRoom == null ? null : widget.clientManager.callManager - .getCallInRoom(currentRoom!.client, currentRoom!.identifier); + .getCallInRoom(currentRoom!.client, currentRoom!.roomId); @override void initState() { @@ -269,7 +269,7 @@ class MainPageState extends State { var partner = direct.getDirectMessagePartnerId(room); - component.startCall(room.identifier, CallType.voice, userId: partner); + component.startCall(room.roomId, CallType.voice, userId: partner); } void selectHome() { diff --git a/commet/lib/ui/pages/main/main_page_view_desktop.dart b/commet/lib/ui/pages/main/main_page_view_desktop.dart index c3b4546a1..b34f74f98 100644 --- a/commet/lib/ui/pages/main/main_page_view_desktop.dart +++ b/commet/lib/ui/pages/main/main_page_view_desktop.dart @@ -139,8 +139,8 @@ class MainPageViewDesktop extends StatelessWidget { {double height = 50, double avatarRadius = 12}) { Profile? current = state.currentUser; - if (clientManager!.clients.length == 1) { - current = clientManager!.clients.first.self; + if (clientManager.clients.length == 1) { + current = clientManager.clients.first.self; } return Material( @@ -154,15 +154,15 @@ class MainPageViewDesktop extends StatelessWidget { child: AdaptiveContextMenu( modal: true, items: [ - if (clientManager!.clients.length > 1) + if (clientManager.clients.length > 1) tiamat.ContextMenuItem( text: "Mix Accounts", onPressed: () { EventBus.setFilterClient.add(null); preferences.setFilterClient(null); }), - if (clientManager!.clients.length > 1) - ...clientManager!.clients + if (clientManager.clients.length > 1) + ...clientManager.clients .map((i) => tiamat.ContextMenuItem( text: i.self!.identifier, onPressed: () { @@ -203,7 +203,7 @@ class MainPageViewDesktop extends StatelessWidget { ), ), if (current == null) - ...clientManager!.clients + ...clientManager.clients .where((i) => i.self != null) .map((i) => Padding( padding: const EdgeInsets.fromLTRB(0, 4, 0, 4), diff --git a/commet/lib/ui/pages/main/room_primary_view.dart b/commet/lib/ui/pages/main/room_primary_view.dart index 7734ce053..673b8ec4c 100644 --- a/commet/lib/ui/pages/main/room_primary_view.dart +++ b/commet/lib/ui/pages/main/room_primary_view.dart @@ -52,9 +52,9 @@ class RoomPrimaryView extends StatelessWidget { } } - final call = clientManager?.callManager.getCallInRoom( + final call = clientManager.callManager.getCallInRoom( room.client, - room.identifier, + room.roomId, ); return Column( diff --git a/commet/lib/ui/pages/settings/app_settings_page.dart b/commet/lib/ui/pages/settings/app_settings_page.dart index f9b861ad7..28c462e6b 100644 --- a/commet/lib/ui/pages/settings/app_settings_page.dart +++ b/commet/lib/ui/pages/settings/app_settings_page.dart @@ -12,7 +12,7 @@ class AppSettingsPage extends StatelessWidget { @override Widget build(BuildContext context) { return SettingsPage(showDonateButton: true, settings: [ - if (clientManager!.clients.isNotEmpty) SettingsCategoryAccount(), + if (clientManager.clients.isNotEmpty) SettingsCategoryAccount(), SettingsCategoryApp(), SettingsCategoryAbout(), ]); diff --git a/commet/lib/ui/pages/settings/categories/account/account_management/account_management_tab.dart b/commet/lib/ui/pages/settings/categories/account/account_management/account_management_tab.dart index a4a2cb2e2..34e37cd6d 100644 --- a/commet/lib/ui/pages/settings/categories/account/account_management/account_management_tab.dart +++ b/commet/lib/ui/pages/settings/categories/account/account_management/account_management_tab.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:commet/client/client.dart'; import 'package:commet/client/client_manager.dart'; import 'package:commet/client/components/account_switch_prefix/account_switch_prefix.dart'; -import 'package:commet/client/stale_info.dart'; import 'package:commet/main.dart'; import 'package:commet/ui/molecules/user_panel.dart'; import 'package:commet/ui/navigation/adaptive_text_dialog.dart'; @@ -27,10 +26,12 @@ class AccountManagementSettingsTab extends StatefulWidget { class _AccountManagementSettingsTabState extends State { - StreamSubscription? onClientAddedListener; - StreamSubscription? onClientRemovedListener; + StreamSubscription? onClientAddedListener; + StreamSubscription? onClientRemovedListener; final GlobalKey _listKey = GlobalKey(); - late int _numClients; + final List _clientList = List.empty(growable: true); + + int get _numClients => _clientList.length; String get promptAddAccount => Intl.message("Add Account", desc: "Label for button in settings to add another account", @@ -51,29 +52,26 @@ class _AccountManagementSettingsTabState @override void initState() { - onClientAddedListener = - widget.clientManager.onClientAdded.stream.listen((index) { - _listKey.currentState?.insertItem(index); - setState(() { - _numClients++; - }); + onClientAddedListener = widget.clientManager.onClientAdded.listen((client) { + _clientList.add(client); + _listKey.currentState?.insertItem(_clientList.length - 1); + setState(() {}); }); onClientRemovedListener = - widget.clientManager.onClientRemoved.stream.listen((info) { + widget.clientManager.onClientRemoved.listen((client) { + int index = _clientList.indexOf(client); _listKey.currentState?.removeItem( - info.index, + index, (context, animation) => SizeTransition( sizeFactor: animation, child: accountListItem( - displayName: info.displayName!, - avatar: info.avatar, - detail: info.identifier), + displayName: client.self!.displayName, + avatar: client.self!.avatar, + detail: client.self!.identifier), )); }); - _numClients = widget.clientManager.clients.length; - super.initState(); } diff --git a/commet/lib/ui/pages/settings/categories/app/notification_settings/notifier_debug_view.dart b/commet/lib/ui/pages/settings/categories/app/notification_settings/notifier_debug_view.dart index 28cc6702d..e9f5250b5 100644 --- a/commet/lib/ui/pages/settings/categories/app/notification_settings/notifier_debug_view.dart +++ b/commet/lib/ui/pages/settings/categories/app/notification_settings/notifier_debug_view.dart @@ -16,7 +16,7 @@ class _NotifierDebugViewState extends State { @override void initState() { - component = clientManager!.clients.firstOrNull + component = clientManager.clients.firstOrNull ?.getComponent(); super.initState(); } @@ -25,9 +25,9 @@ class _NotifierDebugViewState extends State { Widget build(BuildContext context) { return Column( children: [ - if (clientManager!.clients.length > 1) + if (clientManager.clients.length > 1) AccountSelector( - clientManager!.clients, + clientManager.clients, onClientSelected: (client) { setState(() { component = client.getComponent(); diff --git a/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart b/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart index 67c4d8c1b..1a85e0782 100644 --- a/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart +++ b/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart @@ -68,7 +68,7 @@ class SettingsCategoryApp implements SettingsCategory { pageBuilder: (context) { return const AppearanceSettingsPage(); }), - if (clientManager?.clients + if (clientManager.clients .any((e) => e.getComponent() != null) == true) SettingsTab( diff --git a/commet/lib/ui/pages/settings/categories/app/voip_settings/voip_debug_settings.dart b/commet/lib/ui/pages/settings/categories/app/voip_settings/voip_debug_settings.dart index 7931d7252..ccbc55ffa 100644 --- a/commet/lib/ui/pages/settings/categories/app/voip_settings/voip_debug_settings.dart +++ b/commet/lib/ui/pages/settings/categories/app/voip_settings/voip_debug_settings.dart @@ -17,7 +17,7 @@ class _VoipDebugSettingsState extends State { @override void initState() { - selectedClient = clientManager!.clients.first; + selectedClient = clientManager.clients.first; super.initState(); } @@ -25,9 +25,9 @@ class _VoipDebugSettingsState extends State { Widget build(BuildContext context) { return Column( children: [ - if (clientManager!.clients.length > 1) + if (clientManager.clients.length > 1) AccountSelector( - clientManager!.clients, + clientManager.clients, onClientSelected: (client) { setState(() { selectedClient = client; diff --git a/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart b/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart index 5cf786d92..922f98296 100644 --- a/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart +++ b/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart @@ -203,7 +203,7 @@ class _DeveloperSettingsPageState extends State { tiamat.Button( text: "Message Notification", onTap: () async { - var client = clientManager!.clients.first; + var client = clientManager.clients.first; var room = client.rooms.first; var user = client.self!; NotificationManager.notify(MessageNotificationContent( @@ -211,7 +211,7 @@ class _DeveloperSettingsPageState extends State { senderImage: user.avatar, senderId: user.identifier, roomName: room.displayName, - roomId: room.identifier, + roomId: room.roomId, roomImage: await room.getShortcutImage(), content: "Test Message!", clientId: client.identifier, @@ -224,10 +224,10 @@ class _DeveloperSettingsPageState extends State { text: "Call Notification", onTap: () async { if (!BuildConfig.ANDROID) { - clientManager?.callManager.startRingtone(); + clientManager.callManager.startRingtone(); } - var client = clientManager!.clients.first; + var client = clientManager.clients.first; var room = client.rooms.first; var user = client.self!; NotificationManager.notify(CallNotificationContent( @@ -235,7 +235,7 @@ class _DeveloperSettingsPageState extends State { senderImage: user.avatar, senderId: user.identifier, roomName: room.displayName, - roomId: room.identifier, + roomId: room.roomId, senderName: user.displayName, senderImageId: "fake_call_avatar_id", roomImage: await room.getShortcutImage(), diff --git a/commet/lib/ui/pages/settings/categories/room/appearance/room_appearance_settings_page.dart b/commet/lib/ui/pages/settings/categories/room/appearance/room_appearance_settings_page.dart index 266448be9..8a0f88ac8 100644 --- a/commet/lib/ui/pages/settings/categories/room/appearance/room_appearance_settings_page.dart +++ b/commet/lib/ui/pages/settings/categories/room/appearance/room_appearance_settings_page.dart @@ -37,7 +37,7 @@ class _RoomAppearanceSettingsPageState client: widget.room.client, avatar: widget.room.avatar, displayName: widget.room.displayName, - identifier: widget.room.identifier, + identifier: widget.room.roomId, color: widget.room.defaultColor, canEditName: widget.room.permissions.canEditName, canEditAvatar: widget.room.permissions.canEditAvatar, diff --git a/commet/lib/ui/pages/settings/categories/space/space_appearance_settings_page.dart b/commet/lib/ui/pages/settings/categories/space/space_appearance_settings_page.dart index 935c6043e..1f28de340 100644 --- a/commet/lib/ui/pages/settings/categories/space/space_appearance_settings_page.dart +++ b/commet/lib/ui/pages/settings/categories/space/space_appearance_settings_page.dart @@ -48,7 +48,7 @@ class _SpaceAppearanceSettingsPageState RoomAppearanceSettingsView( avatar: widget.space.avatar, displayName: widget.space.displayName, - identifier: widget.space.identifier, + identifier: widget.space.roomId, onImagePicked: onAvatarPicked, onNameChanged: setName, setTopic: widget.space.setTopic, diff --git a/commet/lib/ui/pages/settings/settings_page.dart b/commet/lib/ui/pages/settings/settings_page.dart index e80764225..fb6ff88f8 100644 --- a/commet/lib/ui/pages/settings/settings_page.dart +++ b/commet/lib/ui/pages/settings/settings_page.dart @@ -56,7 +56,7 @@ class SettingsPage extends StatelessWidget { title: "Pick an account to donate with", context, items: [ - ...clientManager!.clients, + ...clientManager.clients, "anonymous", ], itemBuilder: (context, item, callback) { diff --git a/commet/lib/utils/autofill_utils.dart b/commet/lib/utils/autofill_utils.dart index 7d8b73995..6cbc68f2d 100644 --- a/commet/lib/utils/autofill_utils.dart +++ b/commet/lib/utils/autofill_utils.dart @@ -74,7 +74,7 @@ class AutofillUtils { static List searchRooms(String string, Room room) { var rooms = List.empty(growable: true); var spaces = room.client.spaces - .where((element) => element.containsRoom(room.identifier)); + .where((element) => element.containsRoom(room.roomId)); for (var space in spaces) { for (var room in space.rooms) { if (!rooms.contains(room)) { @@ -93,7 +93,7 @@ class AutofillUtils { ])); return fuzzy.search(string, 20).map((e) { - return AutofillSearchResult(e.item.displayName, e.item.identifier); + return AutofillSearchResult(e.item.displayName, e.item.roomId); }).toList(); } diff --git a/commet/lib/utils/background_tasks/background_task_manager.dart b/commet/lib/utils/background_tasks/background_task_manager.dart index fe4043ad3..5be02867d 100644 --- a/commet/lib/utils/background_tasks/background_task_manager.dart +++ b/commet/lib/utils/background_tasks/background_task_manager.dart @@ -6,9 +6,9 @@ import 'package:commet/utils/notifying_list.dart'; class BackgroundTaskManager { NotifyingList tasks = NotifyingList.empty(growable: true); - Stream get onTaskAdded => tasks.onAdd; + Stream get onTaskAdded => tasks.onAdd; - Stream get onTaskRemoved => tasks.onRemove; + Stream get onTaskRemoved => tasks.onRemove; Stream get onListUpdate => tasks.onListUpdated; diff --git a/commet/lib/utils/event_bus.dart b/commet/lib/utils/event_bus.dart index 13727d899..0b17c8f76 100644 --- a/commet/lib/utils/event_bus.dart +++ b/commet/lib/utils/event_bus.dart @@ -1,8 +1,6 @@ import 'dart:async'; import 'package:commet/client/client.dart'; import 'package:commet/client/components/message_effects/message_effect_particles.dart'; -import 'package:commet/client/room.dart'; -import 'package:commet/client/space.dart'; import 'package:commet/ui/molecules/overlapping_panels.dart'; import 'package:desktop_drop/desktop_drop.dart'; import 'package:flutter/material.dart'; diff --git a/commet/lib/utils/notifying_list.dart b/commet/lib/utils/notifying_list.dart index 77978ddca..6bf8d37bf 100644 --- a/commet/lib/utils/notifying_list.dart +++ b/commet/lib/utils/notifying_list.dart @@ -4,24 +4,24 @@ import 'dart:math'; class NotifyingList implements List { List _internalList; - late StreamController _onAdd = StreamController.broadcast(); + late StreamController _onAdd = StreamController.broadcast(); - late StreamController _onRemove = StreamController.broadcast(); + late StreamController _onRemove = StreamController.broadcast(); late StreamController _onListUpdated = StreamController.broadcast(); - late StreamController _onItemUpdated = StreamController.broadcast(); + late StreamController _onItemUpdated = StreamController.broadcast(); // This stream is called after an item is added to the list - Stream get onAdd => _onAdd.stream; + Stream get onAdd => _onAdd.stream; // This stream is called just before an item is removed from the list, the item will still be accessible at this index until the stream is completed - Stream get onRemove => _onRemove.stream; + Stream get onRemove => _onRemove.stream; // This stream is called whenever the items in the list are changed Stream get onListUpdated => _onListUpdated.stream; - Stream get onItemUpdated => _onItemUpdated.stream; + Stream get onItemUpdated => _onItemUpdated.stream; @override T get first => _internalList.first; @@ -42,13 +42,13 @@ class NotifyingList implements List { @override set first(T value) { _internalList.first = value; - _onItemUpdated.add(0); + _onItemUpdated.add(value); } @override set last(T value) { _internalList.last = value; - _onItemUpdated.add(_internalList.length - 1); + _onItemUpdated.add(value); } @override @@ -89,24 +89,20 @@ class NotifyingList implements List { @override void operator []=(int index, T value) { _internalList[index] = value; - _onItemUpdated.add(index); + _onItemUpdated.add(value); } @override void add(T value) { _internalList.add(value); - _onAdd.add(_internalList.length - 1); + _onAdd.add(value); } @override void addAll(Iterable iterable) { - int prevLength = _internalList.length; - _internalList.addAll(iterable); - for (int i = 0; i < iterable.length; i++) { - _onAdd.add(prevLength + i); + for (final e in iterable) { + add(e); } - - _onAnyUpdate(null); } @override @@ -126,11 +122,11 @@ class NotifyingList implements List { @override void clear() { - for (int i = 0; i < _internalList.length; i++) { - _onRemove.add(i); + List oldList = _internalList; + this._internalList = List.empty(growable: true); + for (final entry in oldList) { + _onRemove.add(entry); } - - _internalList.clear(); } @override @@ -196,7 +192,7 @@ class NotifyingList implements List { @override void insert(int index, T element) { _internalList.insert(index, element); - _onAdd.add(index); + _onAdd.add(element); } @override @@ -204,7 +200,7 @@ class NotifyingList implements List { int oldLength = iterable.length; _internalList.insertAll(index, iterable); for (int i = 0; i < oldLength; i++) { - _onAdd.add(oldLength + i); + _onAdd.add(_internalList[oldLength + i]); } } @@ -249,10 +245,8 @@ class NotifyingList implements List { @override bool remove(Object? value) { - var index = _internalList.indexWhere((element) => element == value); - if (index != -1) { - _onRemove.add(index); - _internalList.removeAt(index); + if (_internalList.remove(value)) { + _onRemove.add(value as T); return true; } @@ -261,33 +255,43 @@ class NotifyingList implements List { @override T removeAt(int index) { - _onRemove.add(index); - return _internalList.removeAt(index); + T value = _internalList.removeAt(index); + _onRemove.add(value); + return value; } @override T removeLast() { - _onRemove.add(_internalList.length - 1); - return _internalList.removeLast(); + T value = _internalList.removeLast(); + _onRemove.add(value); + return value; } @override void removeRange(int start, int end) { + List removed = List.empty(growable: true); for (int i = start; i < end; i++) { - _onRemove.add(i); + removed.add(i); + } + _internalList.removeRange(start, end); + for (final e in removed) { + _onRemove.add(e); } - - return _internalList.removeRange(start, end); } @override void removeWhere(bool Function(T element) test) { - for (int i = 0; i < _internalList.length; i++) { - var item = _internalList[i]; - if (test(item)) { - _onRemove.add(i); - _internalList.removeAt(i); + List removed = List.empty(growable: true); + _internalList.removeWhere((element) { + if (test(element)) { + removed.add(element); + return true; } + ; + return false; + }); + for (final entry in removed) { + _onRemove.add(entry); } } @@ -296,7 +300,7 @@ class NotifyingList implements List { _internalList.replaceRange(start, end, replacements); for (int i = start; i < end; i++) { - _onItemUpdated.add(i); + _onItemUpdated.add(_internalList[i]); } } @@ -310,20 +314,18 @@ class NotifyingList implements List { @override void setAll(int index, Iterable iterable) { + _internalList.setAll(index, iterable); for (int i = 0; i < iterable.length; i++) { - _onItemUpdated.add(index + i); + _onItemUpdated.add(_internalList[index + i]); } - - return _internalList.setAll(index, iterable); } @override void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + _internalList.setRange(start, end, iterable); for (int i = start; i < end; i++) { - _onItemUpdated.add(i); + _onItemUpdated.add(_internalList[i]); } - - return _internalList.setRange(start, end, iterable); } @override diff --git a/commet/lib/utils/notifying_map.dart b/commet/lib/utils/notifying_map.dart new file mode 100644 index 000000000..7728c6875 --- /dev/null +++ b/commet/lib/utils/notifying_map.dart @@ -0,0 +1,152 @@ +import 'dart:async'; + +class NotifyingMap implements Map { + late final Map _internalMap; + + late final StreamController> _onAdd; + + late final StreamController> _onRemove; + + // This stream is called after an item is added to the list + Stream> get onAdd => _onAdd.stream; + + // This stream is called just before an item is removed from the list, the item will still be accessible at this index until the stream is completed + Stream> get onRemove => _onRemove.stream; + + NotifyingMap({bool sync = true}) { + _internalMap = Map(); + _onAdd = StreamController.broadcast(sync: sync); + _onRemove = StreamController.broadcast(sync: sync); + } + + @override + V? operator [](Object? key) { + return _internalMap[key]; + } + + @override + void operator []=(K key, V value) { + update(key, (v) => value, ifAbsent: () => value); + } + + @override + void addAll(Map other) { + addEntries(other.entries); + } + + @override + void addEntries(Iterable> newEntries) { + for (final entry in newEntries) { + this[entry.key] = entry.value; + } + } + + @override + Map cast() { + return _internalMap.cast(); + } + + @override + void clear() { + Map oldmap = this._internalMap; + this._internalMap = Map(); + for (final entry in oldmap.entries) { + _onRemove.add(entry); + } + } + + @override + bool containsKey(Object? key) { + return this._internalMap.containsKey(key); + } + + @override + bool containsValue(Object? value) { + return this._internalMap.containsValue(value); + } + + @override + Iterable> get entries => this._internalMap.entries; + + @override + void forEach(void Function(K key, V value) action) { + this._internalMap.forEach(action); + } + + @override + bool get isEmpty => this._internalMap.isEmpty; + + @override + bool get isNotEmpty => this._internalMap.isNotEmpty; + + @override + Iterable get keys => this._internalMap.keys; + + @override + int get length => this._internalMap.length; + + @override + Map map(MapEntry Function(K key, V value) convert) { + return this._internalMap.map(convert); + } + + @override + V putIfAbsent(K key, V Function() ifAbsent) { + return update(key, (v) => v, ifAbsent: ifAbsent); + } + + @override + V? remove(Object? key) { + if (containsKey(key)) { + V value = _internalMap.remove(key)!; + _onRemove.add(MapEntry(key as K, value)); + return value; + } + return null; + } + + @override + void removeWhere(bool Function(K key, V value) test) { + List> removed = List.empty(growable: true); + _internalMap.removeWhere((key, value) { + if (test(key, value)) { + removed.add(MapEntry(key, value)); + return true; + } + ; + return false; + }); + for (final entry in removed) { + _onRemove.add(entry); + } + } + + @override + V update(K key, V Function(V value) update, {V Function()? ifAbsent}) { + if (ifAbsent == null) { + return _internalMap.update(key, update); + } + bool absent = true; + V? old_value = null; + V value = _internalMap.update(key, (V value) { + absent = false; + old_value = value; + return update(value); + }, ifAbsent: ifAbsent); + if (absent) { + _onAdd.add(MapEntry(key, value)); + } else { + _onRemove.add(MapEntry(key, old_value!)); + _onAdd.add(MapEntry(key, value)); + } + return value; + } + + @override + void updateAll(V Function(K key, V value) update) { + _internalMap.updateAll(update); + } + + @override + Iterable get values => _internalMap.values; +} diff --git a/commet/lib/utils/notifying_set.dart b/commet/lib/utils/notifying_set.dart new file mode 100644 index 000000000..fdd5f7b72 --- /dev/null +++ b/commet/lib/utils/notifying_set.dart @@ -0,0 +1,254 @@ +import 'dart:async'; + +class NotifyingSet implements Set { + late final Set _internalSet; + + late final StreamController _onAdd; + + late final StreamController _onRemove; + + // This stream is called after an item is added to the list + Stream get onAdd => _onAdd.stream; + + // This stream is called just before an item is removed from the list, the item will still be accessible at this index until the stream is completed + Stream get onRemove => _onRemove.stream; + + NotifyingSet({bool sync = true}) { + _internalSet = Set(); + _onAdd = StreamController.broadcast(sync: sync); + _onRemove = StreamController.broadcast(sync: sync); + } + + @override + bool add(T value) { + if (_internalSet.add(value)) { + _onAdd.add(value); + return true; + } + ; + return false; + } + + @override + void addAll(Iterable elements) { + for (final e in elements) { + add(e); + } + ; + } + + @override + bool any(bool Function(T element) test) { + return _internalSet.any(test); + } + + @override + Set cast() { + return _internalSet.cast(); + } + + @override + void clear() { + Set oldset = _internalSet; + this._internalSet = Set(); + for (final entry in oldset) { + _onRemove.add(entry); + } + } + + @override + bool contains(Object? value) { + return _internalSet.contains(value); + } + + @override + bool containsAll(Iterable other) { + return _internalSet.containsAll(other); + } + + @override + Set difference(Set other) { + return _internalSet.difference(other); + } + + @override + T elementAt(int index) { + return _internalSet.elementAt(index); + } + + @override + bool every(bool Function(T element) test) { + return _internalSet.every(test); + } + + @override + Iterable expand(Iterable Function(T element) toElements) { + return _internalSet.expand(toElements); + } + + @override + T get first => _internalSet.first; + + @override + T firstWhere(bool Function(T element) test, {T Function()? orElse}) { + return _internalSet.firstWhere(test, orElse: orElse); + } + + @override + T2 fold( + T2 initialValue, T2 Function(T2 previousValue, T element) combine) { + return _internalSet.fold(initialValue, combine); + } + + @override + Iterable followedBy(Iterable other) { + return _internalSet.followedBy(other); + } + + @override + void forEach(void Function(T element) action) { + return _internalSet.forEach(action); + } + + @override + Set intersection(Set other) { + return _internalSet.intersection(other); + } + + @override + bool get isEmpty => _internalSet.isEmpty; + + @override + bool get isNotEmpty => _internalSet.isNotEmpty; + + @override + Iterator get iterator => _internalSet.iterator; + + @override + String join([String separator = ""]) { + return _internalSet.join(separator); + } + + @override + T get last => _internalSet.last; + + @override + T lastWhere(bool Function(T element) test, {T Function()? orElse}) { + return _internalSet.lastWhere(test, orElse: orElse); + } + + @override + int get length => _internalSet.length; + + @override + T? lookup(Object? object) { + return _internalSet.lookup(object); + } + + @override + Iterable map(T2 Function(T e) toElement) { + return _internalSet.map(toElement); + } + + @override + T reduce(T Function(T value, T element) combine) { + return _internalSet.reduce(combine); + } + + @override + bool remove(Object? value) { + if (_internalSet.remove(value)) { + _onRemove.add(value as T); + return true; + } + ; + return false; + } + + @override + void removeAll(Iterable elements) { + for (final e in elements) { + remove(e); + } + } + + @override + void removeWhere(bool Function(T element) test) { + List removed = List.empty(growable: true); + _internalSet.removeWhere((element) { + if (test(element)) { + removed.add(element); + return true; + } + ; + return false; + }); + for (final entry in removed) { + _onRemove.add(entry); + } + } + + @override + void retainAll(Iterable elements) { + var diff = _internalSet.difference(Set.from(elements)); + removeAll(diff); + } + + @override + void retainWhere(bool Function(T element) test) { + removeWhere((element) => !test(element)); + } + + @override + T get single => _internalSet.single; + + @override + T singleWhere(bool Function(T element) test, {T Function()? orElse}) { + return _internalSet.singleWhere(test, orElse: orElse); + } + + @override + Iterable skip(int count) { + return _internalSet.skip(count); + } + + @override + Iterable skipWhile(bool Function(T value) test) { + return _internalSet.skipWhile(test); + } + + @override + Iterable take(int count) { + return _internalSet.take(count); + } + + @override + Iterable takeWhile(bool Function(T value) test) { + return _internalSet.takeWhile(test); + } + + @override + List toList({bool growable = true}) { + return _internalSet.toList(); + } + + @override + Set toSet() { + return _internalSet.toSet(); + } + + @override + Set union(Set other) { + return _internalSet.union(other); + } + + @override + Iterable where(bool Function(T element) test) { + return _internalSet.where(test); + } + + @override + Iterable whereType() { + return _internalSet.whereType(); + } +} diff --git a/commet/lib/utils/notifying_sub_map.dart b/commet/lib/utils/notifying_sub_map.dart new file mode 100644 index 000000000..308f9d622 --- /dev/null +++ b/commet/lib/utils/notifying_sub_map.dart @@ -0,0 +1,152 @@ +import 'dart:async'; +import 'package:commet/utils/notifying_map.dart'; + +class NotifyingSubMap implements NotifyingMap { + final NotifyingMap _parent; + + late final bool Function(V2? element) _condition; + + late int _length; + + NotifyingSubMap(this._parent, bool Function(V2? element)? condition) { + _condition = + (V2? element) => (element is V && (condition?.call(element) ?? true)); + _length = entries.length; + + onAdd.listen((e) { + _length = _length + 1; + }); + onRemove.listen((e) { + _length = _length - 1; + }); + } + + Stream> get onAdd => _parent.onAdd + .where((e) => _condition.call(e.value)) + .map((e) => MapEntry(e.key, e.value as V)); + + Stream> get onRemove => _parent.onRemove + .where((e) => _condition.call(e.value)) + .map((e) => MapEntry(e.key, e.value as V)); + + @override + V? operator [](Object? key) { + V2? value = _parent[key]; + if (_condition.call(value)) { + return value as V; + } + return null; + } + + @override + void operator []=(K key, V value) { + update(key, (v) => value, ifAbsent: () => value); + } + + @override + void addAll(Map other) { + addEntries(other.entries); + } + + @override + void addEntries(Iterable> newEntries) { + for (final entry in newEntries) { + this[entry.key] = entry.value; + } + } + + @override + Map cast() { + return _parent.cast(); + } + + @override + void clear() { + _parent.removeWhere((k, v) => _condition.call(v)); + } + + @override + bool containsKey(Object? key) { + return this._parent.containsKey(key) && _condition.call(this._parent[key]); + } + + @override + bool containsValue(Object? value) { + return this._parent.containsValue(value) && _condition.call(value as V2?); + } + + @override + Iterable> get entries => this + ._parent + .entries + .where((e) => _condition.call(e.value)) + .map((e) => MapEntry(e.key, e.value as V)); + + @override + void forEach(void Function(K key, V value) action) { + entries.forEach((e) => action(e.key, e.value)); + } + + @override + bool get isEmpty => _length == 0; + + @override + bool get isNotEmpty => !isEmpty; + + @override + Iterable get keys => entries.map((e) => e.key); + + @override + int get length => _length; + + @override + Map map(MapEntry Function(K key, V value) convert) { + return Map.fromEntries(entries.map((e) => convert(e.key, e.value))); + } + + @override + V putIfAbsent(K key, V Function() ifAbsent) { + return update(key, (v) => v, ifAbsent: ifAbsent); + } + + @override + V? remove(Object? key) { + if (containsKey(key)) { + V value = _parent.remove(key) as V; + return value; + } + return null; + } + + @override + void removeWhere(bool Function(K key, V value) test) { + _parent.removeWhere( + (key, value) => (_condition.call(value) && test(key, value as V))); + } + + @override + V update(K key, V Function(V value) update, {V Function()? ifAbsent}) { + return _parent.update(key, (value) { + if (_condition.call(value)) { + return update.call(value as V); + } + if (ifAbsent == null) { + return value; + } + return ifAbsent.call(); + }, ifAbsent: ifAbsent) as V; + } + + @override + void updateAll(V Function(K key, V value) update) { + _parent.updateAll((k, v) { + if (_condition.call(v)) { + return update(k, v as V); + } + return v; + }); + } + + @override + Iterable get values => entries.map((e) => e.value); +} diff --git a/commet/lib/utils/shortcuts_manager.dart b/commet/lib/utils/shortcuts_manager.dart index 89345e960..31955a252 100644 --- a/commet/lib/utils/shortcuts_manager.dart +++ b/commet/lib/utils/shortcuts_manager.dart @@ -42,7 +42,7 @@ class ShortcutsManager { if (loading != null) await loading; var cachedAvatar = await getCachedAvatarImage( - identifier: room.identifier, + identifier: room.roomId, placeholderColor: room.defaultColor, placeholderText: room.displayName, format: ShortcutIconFormat.jpeg, @@ -57,10 +57,10 @@ class ShortcutsManager { } var item = ShortcutItem( - id: room.identifier, - action: OpenRoomURI( - roomId: room.identifier, clientId: room.client.identifier) - .toString(), + id: room.roomId, + action: + OpenRoomURI(roomId: room.roomId, clientId: room.client.identifier) + .toString(), shortLabel: room.displayName, icon: icon, shortcutIconAsset: ShortcutIconAsset.memoryAsset, diff --git a/commet/lib/utils/system_wide_shortcuts/system_wide_shortcuts.dart b/commet/lib/utils/system_wide_shortcuts/system_wide_shortcuts.dart index e69623839..77bea58c3 100644 --- a/commet/lib/utils/system_wide_shortcuts/system_wide_shortcuts.dart +++ b/commet/lib/utils/system_wide_shortcuts/system_wide_shortcuts.dart @@ -34,13 +34,13 @@ class SystemWideShortcuts { static Map shortcuts = { "mute": AppShortcut( getDisplayName: () => "Mute", - callback: () => clientManager?.callManager.mute()), + callback: () => clientManager.callManager.mute()), "unmute": AppShortcut( getDisplayName: () => "Unmute", - callback: () => clientManager?.callManager.unmute()), + callback: () => clientManager.callManager.unmute()), "toggle_mute": AppShortcut( getDisplayName: () => "Toggle Mute", - callback: () => clientManager?.callManager.toggleMute()), + callback: () => clientManager.callManager.toggleMute()), }; static Future storeHotkeys() async { diff --git a/commet/lib/utils/text_utils.dart b/commet/lib/utils/text_utils.dart index 84ed9cfce..a57d1cdab 100644 --- a/commet/lib/utils/text_utils.dart +++ b/commet/lib/utils/text_utils.dart @@ -203,14 +203,12 @@ class TextUtils { } static String redactSensitiveInfo(String text) { - if (clientManager != null) { - for (final client in clientManager!.clients) { - if (client is MatrixClient) { - var token = client.getMatrixClient().accessToken; - - if (token != null) { - text = text.replaceAll(token, "[REDACTED ACCESS TOKEN]"); - } + for (final client in clientManager.clients) { + if (client is MatrixClient) { + var token = client.getMatrixClient().accessToken; + + if (token != null) { + text = text.replaceAll(token, "[REDACTED ACCESS TOKEN]"); } } } diff --git a/commet/lib/utils/update_checker.dart b/commet/lib/utils/update_checker.dart index d46e81fc5..b4c9b443a 100644 --- a/commet/lib/utils/update_checker.dart +++ b/commet/lib/utils/update_checker.dart @@ -53,7 +53,7 @@ class UpdateChecker { Log.i("Supports auto update: $canAutoUpdate"); if (time.isAfter(BuildConfig.BUILD_DATE)) { var tag = fields[key]; - clientManager!.alertManager.addAlert(Alert(AlertType.info, + clientManager.alertManager.addAlert(Alert(AlertType.info, messageGetter: () => "There is a newer version of Commet available: ${tag}", titleGetter: () => "Update Available", @@ -115,7 +115,7 @@ class UpdateChecker { await ErrorUtils.tryRun(context, () async { Log.i("Found installer, doing automatic update"); - for (var client in clientManager!.clients) { + for (var client in clientManager.clients) { await client.close(); } diff --git a/commet/lib/utils/window_management.dart b/commet/lib/utils/window_management.dart index 31247ae04..799477a93 100644 --- a/commet/lib/utils/window_management.dart +++ b/commet/lib/utils/window_management.dart @@ -75,10 +75,8 @@ class _WindowListener extends WindowListener { if (preferences.minimizeOnClose) { windowManager.minimize(); } else { - if (clientManager != null) { - for (var client in clientManager!.clients) { - await client.close(); - } + for (var client in clientManager.clients) { + await client.close(); } exit(0);