Merge branch 'krille/create-rooms-methods' into 'main'
feat: More advanced create chat methods See merge request famedly/company/frontend/famedlysdk!877
This commit is contained in:
		
						commit
						b350d5ab5b
					
				|  | @ -556,24 +556,102 @@ class Client extends MatrixApi { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /// Returns an existing direct room ID with this user or creates a new one. |   /// Returns an existing direct room ID with this user or creates a new one. | ||||||
|   /// Returns null on error. |   /// By default encryption will be enabled if the client supports encryption | ||||||
|   Future<String> startDirectChat(String mxid) async { |   /// and the other user has uploaded any encryption keys. | ||||||
|  |   Future<String> startDirectChat( | ||||||
|  |     String mxid, { | ||||||
|  |     bool? enableEncryption, | ||||||
|  |     List<StateEvent>? initialState, | ||||||
|  |     bool waitForSync = true, | ||||||
|  |   }) async { | ||||||
|     // Try to find an existing direct chat |     // Try to find an existing direct chat | ||||||
|     var roomId = getDirectChatFromUserId(mxid); |     final directChatRoomId = getDirectChatFromUserId(mxid); | ||||||
|     if (roomId != null) return roomId; |     if (directChatRoomId != null) return directChatRoomId; | ||||||
|  | 
 | ||||||
|  |     enableEncryption ??= await userOwnsEncryptionKeys(mxid); | ||||||
|  |     if (enableEncryption) { | ||||||
|  |       initialState ??= []; | ||||||
|  |       if (!initialState.any((s) => s.type == EventTypes.Encryption)) { | ||||||
|  |         initialState.add(StateEvent( | ||||||
|  |           content: { | ||||||
|  |             'algorithm': supportedGroupEncryptionAlgorithms.first, | ||||||
|  |           }, | ||||||
|  |           type: EventTypes.Encryption, | ||||||
|  |         )); | ||||||
|  |       } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // Start a new direct chat |     // Start a new direct chat | ||||||
|     roomId = await createRoom( |     final roomId = await createRoom( | ||||||
|       invite: [mxid], |       invite: [mxid], | ||||||
|       isDirect: true, |       isDirect: true, | ||||||
|       preset: CreateRoomPreset.trustedPrivateChat, |       preset: CreateRoomPreset.trustedPrivateChat, | ||||||
|  |       initialState: initialState, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  |     if (waitForSync && getRoomById(roomId) == null) { | ||||||
|  |       // Wait for room actually appears in sync | ||||||
|  |       await onSync.stream | ||||||
|  |           .firstWhere((sync) => sync.rooms?.join?.containsKey(roomId) ?? false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     await Room(id: roomId, client: this).addToDirectChat(mxid); |     await Room(id: roomId, client: this).addToDirectChat(mxid); | ||||||
| 
 | 
 | ||||||
|     return roomId; |     return roomId; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /// Simplified method to create a new group chat. By default it is a private | ||||||
|  |   /// chat. The encryption is enabled if this client supports encryption and | ||||||
|  |   /// the preset is not a public chat. | ||||||
|  |   Future<String> createGroupChat({ | ||||||
|  |     String? groupName, | ||||||
|  |     bool? enableEncryption, | ||||||
|  |     List<String>? invite, | ||||||
|  |     CreateRoomPreset preset = CreateRoomPreset.privateChat, | ||||||
|  |     List<StateEvent>? initialState, | ||||||
|  |     bool waitForSync = true, | ||||||
|  |   }) async { | ||||||
|  |     enableEncryption ??= | ||||||
|  |         encryptionEnabled && preset != CreateRoomPreset.publicChat; | ||||||
|  |     if (enableEncryption) { | ||||||
|  |       initialState ??= []; | ||||||
|  |       if (!initialState.any((s) => s.type == EventTypes.Encryption)) { | ||||||
|  |         initialState.add(StateEvent( | ||||||
|  |           content: { | ||||||
|  |             'algorithm': supportedGroupEncryptionAlgorithms.first, | ||||||
|  |           }, | ||||||
|  |           type: EventTypes.Encryption, | ||||||
|  |         )); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     final roomId = await createRoom( | ||||||
|  |       invite: invite, | ||||||
|  |       preset: preset, | ||||||
|  |       name: groupName, | ||||||
|  |       initialState: initialState, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     if (waitForSync) { | ||||||
|  |       if (getRoomById(roomId) == null) { | ||||||
|  |         // Wait for room actually appears in sync | ||||||
|  |         await onSync.stream.firstWhere( | ||||||
|  |             (sync) => sync.rooms?.join?.containsKey(roomId) ?? false); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return roomId; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /// Checks if the given user has encryption keys. May query keys from the | ||||||
|  |   /// server to answer this. | ||||||
|  |   Future<bool> userOwnsEncryptionKeys(String userId) async { | ||||||
|  |     if (userId == userID) return encryptionEnabled; | ||||||
|  |     if (_userDeviceKeys.containsKey(userId)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     final keys = await queryKeys({userId: []}); | ||||||
|  |     return keys.deviceKeys?.isNotEmpty ?? false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   /// Creates a new space and returns the Room ID. The parameters are mostly |   /// Creates a new space and returns the Room ID. The parameters are mostly | ||||||
|   /// the same like in [createRoom()]. |   /// the same like in [createRoom()]. | ||||||
|   /// Be aware that spaces appear in the [rooms] list. You should check if a |   /// Be aware that spaces appear in the [rooms] list. You should check if a | ||||||
|  |  | ||||||
|  | @ -148,7 +148,17 @@ class User extends Event { | ||||||
| 
 | 
 | ||||||
|   /// Returns an existing direct chat ID with this user or creates a new one. |   /// Returns an existing direct chat ID with this user or creates a new one. | ||||||
|   /// Returns null on error. |   /// Returns null on error. | ||||||
|   Future<String> startDirectChat() async => room.client.startDirectChat(id); |   Future<String> startDirectChat({ | ||||||
|  |     bool? enableEncryption, | ||||||
|  |     List<StateEvent>? initialState, | ||||||
|  |     bool waitForSync = true, | ||||||
|  |   }) async => | ||||||
|  |       room.client.startDirectChat( | ||||||
|  |         id, | ||||||
|  |         enableEncryption: enableEncryption, | ||||||
|  |         initialState: initialState, | ||||||
|  |         waitForSync: waitForSync, | ||||||
|  |       ); | ||||||
| 
 | 
 | ||||||
|   /// The newest presence of this user if there is any and null if not. |   /// The newest presence of this user if there is any and null if not. | ||||||
|   Presence? get presence => room.client.presences[id]; |   Presence? get presence => room.client.presences[id]; | ||||||
|  |  | ||||||
|  | @ -67,14 +67,25 @@ class DeviceKeysList { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<KeyVerification> startVerification() async { |   /// Starts a verification with this device. This might need to create a new | ||||||
|  |   /// direct chat to send the verification request over this room. For this you | ||||||
|  |   /// can set parameters here. | ||||||
|  |   Future<KeyVerification> startVerification({ | ||||||
|  |     bool? newDirectChatEnableEncryption, | ||||||
|  |     List<StateEvent>? newDirectChatInitialState, | ||||||
|  |   }) async { | ||||||
|     final encryption = client.encryption; |     final encryption = client.encryption; | ||||||
|     if (encryption == null) { |     if (encryption == null) { | ||||||
|       throw Exception('Encryption not enabled'); |       throw Exception('Encryption not enabled'); | ||||||
|     } |     } | ||||||
|     if (userId != client.userID) { |     if (userId != client.userID) { | ||||||
|       // in-room verification with someone else |       // in-room verification with someone else | ||||||
|       final roomId = await client.startDirectChat(userId); |       final roomId = await client.startDirectChat( | ||||||
|  |         userId, | ||||||
|  |         enableEncryption: newDirectChatEnableEncryption, | ||||||
|  |         initialState: newDirectChatInitialState, | ||||||
|  |         waitForSync: false, | ||||||
|  |       ); | ||||||
| 
 | 
 | ||||||
|       final room = |       final room = | ||||||
|           client.getRoomById(roomId) ?? Room(id: roomId, client: client); |           client.getRoomById(roomId) ?? Room(id: roomId, client: client); | ||||||
|  |  | ||||||
|  | @ -560,6 +560,12 @@ void main() { | ||||||
|           bunnyContent); |           bunnyContent); | ||||||
|       await client.dispose(closeDatabase: true); |       await client.dispose(closeDatabase: true); | ||||||
|     }); |     }); | ||||||
|  |     test('startDirectChat', () async { | ||||||
|  |       await matrix.startDirectChat('@alice:example.com', waitForSync: false); | ||||||
|  |     }); | ||||||
|  |     test('createGroupChat', () async { | ||||||
|  |       await matrix.createGroupChat(groupName: 'Testgroup', waitForSync: false); | ||||||
|  |     }); | ||||||
|     test('Test the fake store api', () async { |     test('Test the fake store api', () async { | ||||||
|       final database = await getDatabase(null); |       final database = await getDatabase(null); | ||||||
|       final client1 = Client( |       final client1 = Client( | ||||||
|  |  | ||||||
|  | @ -252,7 +252,7 @@ void main() { | ||||||
|       expect(req?.room != null, false); |       expect(req?.room != null, false); | ||||||
| 
 | 
 | ||||||
|       req = await client.userDeviceKeys['@alice:example.com'] |       req = await client.userDeviceKeys['@alice:example.com'] | ||||||
|           ?.startVerification(); |           ?.startVerification(newDirectChatEnableEncryption: false); | ||||||
|       expect(req != null, true); |       expect(req != null, true); | ||||||
|       expect(req?.room != null, true); |       expect(req?.room != null, true); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  | @ -119,7 +119,9 @@ void main() { | ||||||
|       client1.userDeviceKeys[client1.userID]!.masterKey! |       client1.userDeviceKeys[client1.userID]!.masterKey! | ||||||
|           .setDirectVerified(false); |           .setDirectVerified(false); | ||||||
|       final req1 = |       final req1 = | ||||||
|           await client1.userDeviceKeys[client2.userID]!.startVerification(); |           await client1.userDeviceKeys[client2.userID]!.startVerification( | ||||||
|  |         newDirectChatEnableEncryption: false, | ||||||
|  |       ); | ||||||
|       var evt = getLastSentEvent(req1); |       var evt = getLastSentEvent(req1); | ||||||
|       expect(req1.state, KeyVerificationState.waitingAccept); |       expect(req1.state, KeyVerificationState.waitingAccept); | ||||||
| 
 | 
 | ||||||
|  | @ -221,8 +223,8 @@ void main() { | ||||||
|       client1.userDeviceKeys[client1.userID]!.masterKey! |       client1.userDeviceKeys[client1.userID]!.masterKey! | ||||||
|           .setDirectVerified(true); |           .setDirectVerified(true); | ||||||
|       await client1.encryption!.ssss.clearCache(); |       await client1.encryption!.ssss.clearCache(); | ||||||
|       final req1 = |       final req1 = await client1.userDeviceKeys[client2.userID]! | ||||||
|           await client1.userDeviceKeys[client2.userID]!.startVerification(); |           .startVerification(newDirectChatEnableEncryption: false); | ||||||
|       expect(req1.state, KeyVerificationState.askSSSS); |       expect(req1.state, KeyVerificationState.askSSSS); | ||||||
|       await req1.openSSSS(recoveryKey: ssssKey); |       await req1.openSSSS(recoveryKey: ssssKey); | ||||||
|       await Future.delayed(Duration(seconds: 1)); |       await Future.delayed(Duration(seconds: 1)); | ||||||
|  | @ -241,8 +243,8 @@ void main() { | ||||||
|       // the other one has to have their master key verified to trigger asking for ssss |       // the other one has to have their master key verified to trigger asking for ssss | ||||||
|       client2.userDeviceKeys[client2.userID]!.masterKey! |       client2.userDeviceKeys[client2.userID]!.masterKey! | ||||||
|           .setDirectVerified(true); |           .setDirectVerified(true); | ||||||
|       final req1 = |       final req1 = await client1.userDeviceKeys[client2.userID]! | ||||||
|           await client1.userDeviceKeys[client2.userID]!.startVerification(); |           .startVerification(newDirectChatEnableEncryption: false); | ||||||
|       var evt = getLastSentEvent(req1); |       var evt = getLastSentEvent(req1); | ||||||
|       expect(req1.state, KeyVerificationState.waitingAccept); |       expect(req1.state, KeyVerificationState.waitingAccept); | ||||||
| 
 | 
 | ||||||
|  | @ -345,8 +347,8 @@ void main() { | ||||||
|       // make sure our master key is *not* verified to not triger SSSS for now |       // make sure our master key is *not* verified to not triger SSSS for now | ||||||
|       client1.userDeviceKeys[client1.userID]!.masterKey! |       client1.userDeviceKeys[client1.userID]!.masterKey! | ||||||
|           .setDirectVerified(false); |           .setDirectVerified(false); | ||||||
|       final req1 = |       final req1 = await client1.userDeviceKeys[client2.userID]! | ||||||
|           await client1.userDeviceKeys[client2.userID]!.startVerification(); |           .startVerification(newDirectChatEnableEncryption: false); | ||||||
|       var evt = getLastSentEvent(req1); |       var evt = getLastSentEvent(req1); | ||||||
|       expect(req1.state, KeyVerificationState.waitingAccept); |       expect(req1.state, KeyVerificationState.waitingAccept); | ||||||
| 
 | 
 | ||||||
|  | @ -375,8 +377,8 @@ void main() { | ||||||
|       // make sure our master key is *not* verified to not triger SSSS for now |       // make sure our master key is *not* verified to not triger SSSS for now | ||||||
|       client1.userDeviceKeys[client1.userID]!.masterKey! |       client1.userDeviceKeys[client1.userID]!.masterKey! | ||||||
|           .setDirectVerified(false); |           .setDirectVerified(false); | ||||||
|       final req1 = |       final req1 = await client1.userDeviceKeys[client2.userID]! | ||||||
|           await client1.userDeviceKeys[client2.userID]!.startVerification(); |           .startVerification(newDirectChatEnableEncryption: false); | ||||||
|       var evt = getLastSentEvent(req1); |       var evt = getLastSentEvent(req1); | ||||||
|       expect(req1.state, KeyVerificationState.waitingAccept); |       expect(req1.state, KeyVerificationState.waitingAccept); | ||||||
| 
 | 
 | ||||||
|  | @ -436,8 +438,8 @@ void main() { | ||||||
|       // make sure our master key is *not* verified to not triger SSSS for now |       // make sure our master key is *not* verified to not triger SSSS for now | ||||||
|       client1.userDeviceKeys[client1.userID]!.masterKey! |       client1.userDeviceKeys[client1.userID]!.masterKey! | ||||||
|           .setDirectVerified(false); |           .setDirectVerified(false); | ||||||
|       final req1 = |       final req1 = await client1.userDeviceKeys[client2.userID]! | ||||||
|           await client1.userDeviceKeys[client2.userID]!.startVerification(); |           .startVerification(newDirectChatEnableEncryption: false); | ||||||
|       final evt = getLastSentEvent(req1); |       final evt = getLastSentEvent(req1); | ||||||
|       expect(req1.state, KeyVerificationState.waitingAccept); |       expect(req1.state, KeyVerificationState.waitingAccept); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ void main() { | ||||||
|       await user1.setPower(50); |       await user1.setPower(50); | ||||||
|     }); |     }); | ||||||
|     test('startDirectChat', () async { |     test('startDirectChat', () async { | ||||||
|       await user1.startDirectChat(); |       await user1.startDirectChat(waitForSync: false); | ||||||
|     }); |     }); | ||||||
|     test('getPresence', () async { |     test('getPresence', () async { | ||||||
|       await client.handleSync(SyncUpdate.fromJson({ |       await client.handleSync(SyncUpdate.fromJson({ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue