From 970421a0d83f0392a300339b67621481dd800b5d Mon Sep 17 00:00:00 2001 From: Abrish Sabri Date: Thu, 15 May 2025 05:19:53 -0500 Subject: [PATCH 1/3] refactor: event-getter --- lib/src/event.dart | 61 +++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/lib/src/event.dart b/lib/src/event.dart index 43f4d27cd..b325ba06e 100644 --- a/lib/src/event.dart +++ b/lib/src/event.dart @@ -534,13 +534,13 @@ class Event extends MatrixEvent { } /// Gets the info map of file events, or a blank map if none present - Map get infoMap => + Map get infoMap => content.tryGetMap('info') ?? {}; /// Gets the thumbnail info map of file events, or a blank map if nonepresent - Map get thumbnailInfoMap => infoMap['thumbnail_info'] is Map - ? infoMap['thumbnail_info'] - : {}; + Map get thumbnailInfoMap => infoMap['thumbnail_info'] is Map + ? (infoMap['thumbnail_info'] as Map).cast() + : {}; /// Returns if a file event has an attachment bool get hasAttachment => content['url'] is String || content['file'] is Map; @@ -556,20 +556,18 @@ class Event extends MatrixEvent { bool get isThumbnailEncrypted => infoMap['thumbnail_file'] is Map; /// Gets the mimetype of the attachment of a file event, or a blank string if not present - String get attachmentMimetype => infoMap['mimetype'] is String - ? infoMap['mimetype'].toLowerCase() - : (content - .tryGetMap('file') - ?.tryGet('mimetype') ?? + String get attachmentMimetype => + infoMap.tryGet('mimetype')?.toLowerCase() ?? + (content.tryGetMap('file')?.tryGet('mimetype') ?? ''); /// Gets the mimetype of the thumbnail of a file event, or a blank string if not present - String get thumbnailMimetype => thumbnailInfoMap['mimetype'] is String - ? thumbnailInfoMap['mimetype'].toLowerCase() - : (infoMap['thumbnail_file'] is Map && - infoMap['thumbnail_file']['mimetype'] is String - ? infoMap['thumbnail_file']['mimetype'] - : ''); + String get thumbnailMimetype => + thumbnailInfoMap.tryGet('mimetype')?.toLowerCase() ?? + (infoMap + .tryGetMap('thumbnail_file') + ?.tryGet('mimetype') ?? + ''); /// Gets the underlying mxc url of an attachment of a file event, or null if not present Uri? get attachmentMxcUrl { @@ -582,7 +580,7 @@ class Event extends MatrixEvent { /// Gets the underlying mxc url of a thumbnail of a file event, or null if not present Uri? get thumbnailMxcUrl { final url = isThumbnailEncrypted - ? infoMap['thumbnail_file']['url'] + ? (infoMap['thumbnail_file'] as Map)['url'] : infoMap['thumbnail_url']; return url is String ? Uri.tryParse(url) : null; } @@ -592,7 +590,7 @@ class Event extends MatrixEvent { if (getThumbnail && infoMap['size'] is int && thumbnailInfoMap['size'] is int && - infoMap['size'] <= thumbnailInfoMap['size']) { + (infoMap['size'] as int) <= (thumbnailInfoMap['size'] as int)) { getThumbnail = false; } if (getThumbnail && !hasThumbnail) { @@ -641,12 +639,12 @@ class Event extends MatrixEvent { if (getThumbnail && method == ThumbnailMethod.scale && thisInfoMap['size'] is int && - thisInfoMap['size'] < minNoThumbSize) { + (thisInfoMap['size'] as int) < minNoThumbSize) { getThumbnail = false; } // now generate the actual URLs if (getThumbnail) { - return await Uri.parse(thisMxcUrl).getThumbnailUri( + return await Uri.parse(thisMxcUrl as String).getThumbnailUri( room.client, width: width, height: height, @@ -654,7 +652,7 @@ class Event extends MatrixEvent { animated: animated, ); } else { - return await Uri.parse(thisMxcUrl).getDownloadUri(room.client); + return await Uri.parse(thisMxcUrl as String).getDownloadUri(room.client); } } @@ -696,12 +694,12 @@ class Event extends MatrixEvent { if (getThumbnail && method == ThumbnailMethod.scale && thisInfoMap['size'] is int && - thisInfoMap['size'] < minNoThumbSize) { + (thisInfoMap['size'] as int) < minNoThumbSize) { getThumbnail = false; } // now generate the actual URLs if (getThumbnail) { - return Uri.parse(thisMxcUrl).getThumbnail( + return Uri.parse(thisMxcUrl as String).getThumbnail( room.client, width: width, height: height, @@ -709,7 +707,7 @@ class Event extends MatrixEvent { animated: animated, ); } else { - return Uri.parse(thisMxcUrl).getDownloadLink(room.client); + return Uri.parse(thisMxcUrl as String).getDownloadLink(room.client); } } @@ -728,7 +726,7 @@ class Event extends MatrixEvent { final database = room.client.database; final storeable = thisInfoMap['size'] is int && - thisInfoMap['size'] <= database.maxFileSize; + (thisInfoMap['size'] as int) <= database.maxFileSize; Uint8List? uint8list; if (storeable) { @@ -770,7 +768,7 @@ class Event extends MatrixEvent { // Is this file storeable? final thisInfoMap = getThumbnail ? thumbnailInfoMap : infoMap; var storeable = thisInfoMap['size'] is int && - thisInfoMap['size'] <= database.maxFileSize; + (thisInfoMap['size'] as int) <= database.maxFileSize; Uint8List? uint8list; if (storeable) { @@ -802,16 +800,17 @@ class Event extends MatrixEvent { // Decrypt the file if (isEncrypted) { - final fileMap = - getThumbnail ? infoMap['thumbnail_file'] : content['file']; - if (!fileMap['key']['key_ops'].contains('decrypt')) { + final fileMap = getThumbnail + ? infoMap['thumbnail_file'] as Map + : content['file'] as Map; + if (!(fileMap['key'] as Map)['key_ops'].contains('decrypt')) { throw ("Missing 'decrypt' in 'key_ops'."); } final encryptedFile = EncryptedFile( data: uint8list, - iv: fileMap['iv'], - k: fileMap['key']['k'], - sha256: fileMap['hashes']['sha256'], + iv: fileMap['iv'] as String, + k: (fileMap['key'] as Map)['k'] as String, + sha256: (fileMap['hashes'] as Map)['sha256'] as String, ); uint8list = await room.client.nativeImplementations.decryptFile(encryptedFile); From 5fe0866913d26846ca110b0f8ad7ff38b9ca87ad Mon Sep 17 00:00:00 2001 From: Abrish Sabri Date: Thu, 15 May 2025 05:19:53 -0500 Subject: [PATCH 2/3] refactor: event-getter --- test/webrtc_stub.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/webrtc_stub.dart b/test/webrtc_stub.dart index 70516e922..8f8053b3f 100644 --- a/test/webrtc_stub.dart +++ b/test/webrtc_stub.dart @@ -849,4 +849,8 @@ class MockVideoRenderer implements VideoRenderer { // Mock implementation for disposing VideoRenderer Logs().i('Mock: Disposing VideoRenderer'); } + + @override + // TODO: implement videoValue + RTCVideoValue get videoValue => throw UnimplementedError(); } From 73ca422b420f9b846dd9c8750c8b6727118924fe Mon Sep 17 00:00:00 2001 From: Abrish Sabri Date: Thu, 15 May 2025 05:19:53 -0500 Subject: [PATCH 3/3] refactor: event-getter --- .../msc_1236_widgets/src/widget.dart | 268 +++++++++--------- test/webrtc_stub.dart | 4 - 2 files changed, 134 insertions(+), 138 deletions(-) diff --git a/lib/msc_extensions/msc_1236_widgets/src/widget.dart b/lib/msc_extensions/msc_1236_widgets/src/widget.dart index 3d15591cd..9381312d7 100644 --- a/lib/msc_extensions/msc_1236_widgets/src/widget.dart +++ b/lib/msc_extensions/msc_1236_widgets/src/widget.dart @@ -1,134 +1,134 @@ -import 'package:matrix/src/room.dart'; - -class MatrixWidget { - final Room room; - final String? creatorUserId; - final Map? data; - final String? id; - final String? name; - final String type; - - /// use [buildWidgetUrl] instead - final String url; - final bool waitForIframeLoad; - - MatrixWidget({ - required this.room, - this.creatorUserId, - this.data = const {}, - this.id, - required this.name, - required this.type, - required this.url, - this.waitForIframeLoad = false, - }); - - factory MatrixWidget.fromJson(Map json, Room room) => - MatrixWidget( - room: room, - creatorUserId: - json.containsKey('creatorUserId') ? json['creatorUserId'] : null, - data: json.containsKey('data') ? json['data'] : {}, - id: json.containsKey('id') ? json['id'] : null, - name: json['name'], - type: json['type'], - url: json['url'], - waitForIframeLoad: json.containsKey('waitForIframeLoad') - ? json['waitForIframeLoad'] - : false, - ); - - /// creates an `m.etherpad` [MatrixWidget] - factory MatrixWidget.etherpad(Room room, String name, Uri url) => - MatrixWidget( - room: room, - name: name, - type: 'm.etherpad', - url: url.toString(), - data: { - 'url': url.toString(), - }, - ); - - /// creates an `m.jitsi` [MatrixWidget] - factory MatrixWidget.jitsi( - Room room, - String name, - Uri url, { - bool isAudioOnly = false, - }) => - MatrixWidget( - room: room, - name: name, - type: 'm.jitsi', - url: url.toString(), - data: { - 'domain': url.host, - 'conferenceId': url.pathSegments.last, - 'isAudioOnly': isAudioOnly, - }, - ); - - /// creates an `m.video` [MatrixWidget] - factory MatrixWidget.video(Room room, String name, Uri url) => MatrixWidget( - room: room, - name: name, - type: 'm.video', - url: url.toString(), - data: { - 'url': url.toString(), - }, - ); - - /// creates an `m.custom` [MatrixWidget] - factory MatrixWidget.custom(Room room, String name, Uri url) => MatrixWidget( - room: room, - name: name, - type: 'm.custom', - url: url.toString(), - data: { - 'url': url.toString(), - }, - ); - - Future buildWidgetUrl() async { - // See https://github.com/matrix-org/matrix-doc/issues/1236 for a - // description, specifically the section - // `What does the other stuff in content mean?` - final userProfile = await room.client.getUserProfile(room.client.userID!); - var parsedUri = url; - - // a key-value map with the strings to be replaced - final replaceMap = { - r'$matrix_user_id': room.client.userID!, - r'$matrix_room_id': room.id, - r'$matrix_display_name': userProfile.displayname ?? '', - r'$matrix_avatar_url': userProfile.avatarUrl?.toString() ?? '', - // removing potentially dangerous keys containing anything but - // `[a-zA-Z0-9_-]` as well as non string values - if (data != null) - ...Map.from(data!) - ..removeWhere( - (key, value) => - !RegExp(r'^[\w-]+$').hasMatch(key) || !value is String, - ) - ..map((key, value) => MapEntry('\$key', value)), - }; - - replaceMap.forEach((key, value) { - parsedUri = parsedUri.replaceAll(key, Uri.encodeComponent(value)); - }); - - return Uri.parse(parsedUri); - } - - Map toJson() => { - 'creatorUserId': creatorUserId, - 'data': data, - 'id': id, - 'name': name, - 'type': type, - 'url': url, - 'waitForIframeLoad': waitForIframeLoad, - }; -} +import 'package:matrix/src/room.dart'; + +class MatrixWidget { + final Room room; + final String? creatorUserId; + final Map? data; + final String? id; + final String? name; + final String type; + + /// use [buildWidgetUrl] instead + final String url; + final bool waitForIframeLoad; + + MatrixWidget({ + required this.room, + this.creatorUserId, + this.data = const {}, + this.id, + required this.name, + required this.type, + required this.url, + this.waitForIframeLoad = false, + }); + + factory MatrixWidget.fromJson(Map json, Room room) => + MatrixWidget( + room: room, + creatorUserId: + json.containsKey('creatorUserId') ? json['creatorUserId'] : null, + data: json.containsKey('data') ? json['data'] : {}, + id: json.containsKey('id') ? json['id'] : null, + name: json['name'], + type: json['type'], + url: json['url'], + waitForIframeLoad: json.containsKey('waitForIframeLoad') + ? json['waitForIframeLoad'] + : false, + ); + + /// creates an `m.etherpad` [MatrixWidget] + factory MatrixWidget.etherpad(Room room, String name, Uri url) => + MatrixWidget( + room: room, + name: name, + type: 'm.etherpad', + url: url.toString(), + data: { + 'url': url.toString(), + }, + ); + + /// creates an `m.jitsi` [MatrixWidget] + factory MatrixWidget.jitsi( + Room room, + String name, + Uri url, { + bool isAudioOnly = false, + }) => + MatrixWidget( + room: room, + name: name, + type: 'm.jitsi', + url: url.toString(), + data: { + 'domain': url.host, + 'conferenceId': url.pathSegments.last, + 'isAudioOnly': isAudioOnly, + }, + ); + + /// creates an `m.video` [MatrixWidget] + factory MatrixWidget.video(Room room, String name, Uri url) => MatrixWidget( + room: room, + name: name, + type: 'm.video', + url: url.toString(), + data: { + 'url': url.toString(), + }, + ); + + /// creates an `m.custom` [MatrixWidget] + factory MatrixWidget.custom(Room room, String name, Uri url) => MatrixWidget( + room: room, + name: name, + type: 'm.custom', + url: url.toString(), + data: { + 'url': url.toString(), + }, + ); + + Future buildWidgetUrl() async { + // See https://github.com/matrix-org/matrix-doc/issues/1236 for a + // description, specifically the section + // `What does the other stuff in content mean?` + final userProfile = await room.client.getUserProfile(room.client.userID!); + var parsedUri = url; + + // a key-value map with the strings to be replaced + final replaceMap = { + r'$matrix_user_id': room.client.userID!, + r'$matrix_room_id': room.id, + r'$matrix_display_name': userProfile.displayname ?? '', + r'$matrix_avatar_url': userProfile.avatarUrl?.toString() ?? '', + // removing potentially dangerous keys containing anything but + // `[a-zA-Z0-9_-]` as well as non string values + if (data != null) + ...Map.from(data!) + ..removeWhere( + (key, value) => + !RegExp(r'^[\w-]+$').hasMatch(key) || !value is String, + ) + ..map((key, value) => MapEntry('\$key', value)), + }; + + replaceMap.forEach((key, value) { + parsedUri = parsedUri.replaceAll(key, Uri.encodeComponent(value)); + }); + + return Uri.parse(parsedUri); + } + + Map toJson() => { + 'creatorUserId': creatorUserId, + 'data': data, + 'id': id, + 'name': name, + 'type': type, + 'url': url, + 'waitForIframeLoad': waitForIframeLoad, + }; +} diff --git a/test/webrtc_stub.dart b/test/webrtc_stub.dart index 8f8053b3f..70516e922 100644 --- a/test/webrtc_stub.dart +++ b/test/webrtc_stub.dart @@ -849,8 +849,4 @@ class MockVideoRenderer implements VideoRenderer { // Mock implementation for disposing VideoRenderer Logs().i('Mock: Disposing VideoRenderer'); } - - @override - // TODO: implement videoValue - RTCVideoValue get videoValue => throw UnimplementedError(); }