Merge branch 'widgets' into 'main'

feat: implement retrieving a room's widgets

See merge request famedly/company/frontend/famedlysdk!940
This commit is contained in:
Lanna Michalke 2022-02-02 07:57:25 +00:00
commit 70c51ac3ee
3 changed files with 82 additions and 1 deletions

View File

@ -24,6 +24,7 @@ import 'package:collection/collection.dart';
import 'package:html_unescape/html_unescape.dart'; import 'package:html_unescape/html_unescape.dart';
import 'package:matrix/src/utils/crypto/crypto.dart'; import 'package:matrix/src/utils/crypto/crypto.dart';
import 'package:matrix/src/utils/space_child.dart'; import 'package:matrix/src/utils/space_child.dart';
import 'package:matrix/widget.dart';
import '../matrix.dart'; import '../matrix.dart';
import 'utils/markdown.dart'; import 'utils/markdown.dart';
@ -369,6 +370,17 @@ class Room {
: []; : [];
} }
/// Returns all present Widgets in the room.
List<MatrixWidget> get widgets => {
...states['m.widget'] ?? {},
...states['im.vector.modular.widgets'] ?? {},
}
.values
.map(
(e) => MatrixWidget.fromJson(e.content, this),
)
.toList();
/// Your current client instance. /// Your current client instance.
final Client client; final Client client;
@ -501,7 +513,7 @@ class Room {
/// Returns true if this room is unread /// Returns true if this room is unread
bool get isUnread => notificationCount > 0 || markedUnread; bool get isUnread => notificationCount > 0 || markedUnread;
@Deprecated('Use [markUnread] instead') @Deprecated('Use [markUnread] instead')
Future<void> setUnread(bool unread) => markUnread(unread); Future<void> setUnread(bool unread) => markUnread(unread);
/// Sets an unread flag manually for this room. This changes the local account /// Sets an unread flag manually for this room. This changes the local account

65
lib/widget.dart Normal file
View File

@ -0,0 +1,65 @@
import 'package:matrix/src/room.dart';
class MatrixWidget {
final Room room;
final String creatorUserId;
final Map<String, dynamic> data;
final String id;
final String name;
final String type;
final String url;
final bool waitForIframeLoad;
MatrixWidget({
required this.room,
required this.creatorUserId,
required this.data,
required this.id,
required this.name,
required this.type,
/// use [buildWidgetUrl] instead
required this.url,
required this.waitForIframeLoad,
});
factory MatrixWidget.fromJson(Map<String, dynamic> json, Room room) =>
MatrixWidget(
room: room,
creatorUserId: json['creatorUserId'],
data: json['data'],
id: json['id'],
name: json['name'],
type: json['type'],
url: json['url'],
waitForIframeLoad: json['waitForIframeLoad'],
);
Future<Uri> 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.ownProfile;
var parsedUri = url;
// a key-value map with the strings to be replaced
final replaceMap = {
r'$matrix_user_id': userProfile.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
...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);
}
}

View File

@ -921,6 +921,10 @@ void main() {
expect(room.getState('m.room.message') != null, true); expect(room.getState('m.room.message') != null, true);
}); });
test('Widgets', () {
expect(room.widgets.isEmpty, true);
});
test('Spaces', () async { test('Spaces', () async {
expect(room.isSpace, false); expect(room.isSpace, false);
room.states['m.room.create'] = { room.states['m.room.create'] = {