Line data Source code
1 : import 'package:matrix/src/room.dart';
2 :
3 : class MatrixWidget {
4 : final Room room;
5 : final String? creatorUserId;
6 : final Map<String, dynamic>? data;
7 : final String? id;
8 : final String? name;
9 : final String type;
10 :
11 : /// use [buildWidgetUrl] instead
12 : final String url;
13 : final bool waitForIframeLoad;
14 :
15 2 : MatrixWidget({
16 : required this.room,
17 : this.creatorUserId,
18 : this.data = const {},
19 : this.id,
20 : required this.name,
21 : required this.type,
22 : required this.url,
23 : this.waitForIframeLoad = false,
24 : });
25 :
26 2 : factory MatrixWidget.fromJson(Map<String, dynamic> json, Room room) =>
27 2 : MatrixWidget(
28 : room: room,
29 : creatorUserId:
30 4 : json.containsKey('creatorUserId') ? json['creatorUserId'] : null,
31 4 : data: json.containsKey('data') ? json['data'] : {},
32 4 : id: json.containsKey('id') ? json['id'] : null,
33 2 : name: json['name'],
34 2 : type: json['type'],
35 2 : url: json['url'],
36 2 : waitForIframeLoad: json.containsKey('waitForIframeLoad')
37 2 : ? json['waitForIframeLoad']
38 : : false,
39 : );
40 :
41 : /// creates an `m.etherpad` [MatrixWidget]
42 0 : factory MatrixWidget.etherpad(Room room, String name, Uri url) =>
43 0 : MatrixWidget(
44 : room: room,
45 : name: name,
46 : type: 'm.etherpad',
47 0 : url: url.toString(),
48 0 : data: {
49 0 : 'url': url.toString(),
50 : },
51 : );
52 :
53 : /// creates an `m.jitsi` [MatrixWidget]
54 0 : factory MatrixWidget.jitsi(Room room, String name, Uri url,
55 : {bool isAudioOnly = false}) =>
56 0 : MatrixWidget(
57 : room: room,
58 : name: name,
59 : type: 'm.jitsi',
60 0 : url: url.toString(),
61 0 : data: {
62 0 : 'domain': url.host,
63 0 : 'conferenceId': url.pathSegments.last,
64 : 'isAudioOnly': isAudioOnly,
65 : },
66 : );
67 :
68 : /// creates an `m.video` [MatrixWidget]
69 0 : factory MatrixWidget.video(Room room, String name, Uri url) => MatrixWidget(
70 : room: room,
71 : name: name,
72 : type: 'm.video',
73 0 : url: url.toString(),
74 0 : data: {
75 0 : 'url': url.toString(),
76 : },
77 : );
78 :
79 : /// creates an `m.custom` [MatrixWidget]
80 0 : factory MatrixWidget.custom(Room room, String name, Uri url) => MatrixWidget(
81 : room: room,
82 : name: name,
83 : type: 'm.custom',
84 0 : url: url.toString(),
85 0 : data: {
86 0 : 'url': url.toString(),
87 : },
88 : );
89 :
90 0 : Future<Uri> buildWidgetUrl() async {
91 : // See https://github.com/matrix-org/matrix-doc/issues/1236 for a
92 : // description, specifically the section
93 : // `What does the other stuff in content mean?`
94 0 : final userProfile = await room.client.fetchOwnProfile();
95 0 : var parsedUri = url;
96 :
97 : // a key-value map with the strings to be replaced
98 0 : final replaceMap = {
99 0 : r'$matrix_user_id': userProfile.userId,
100 0 : r'$matrix_room_id': room.id,
101 0 : r'$matrix_display_name': userProfile.displayName ?? '',
102 0 : r'$matrix_avatar_url': userProfile.avatarUrl?.toString() ?? '',
103 : // removing potentially dangerous keys containing anything but
104 : // `[a-zA-Z0-9_-]` as well as non string values
105 0 : if (data != null)
106 0 : ...Map.from(data!)
107 0 : ..removeWhere((key, value) =>
108 0 : !RegExp(r'^[\w-]+$').hasMatch(key) || !value is String)
109 0 : ..map((key, value) => MapEntry('\$key', value)),
110 : };
111 :
112 0 : replaceMap.forEach((key, value) {
113 0 : parsedUri = parsedUri.replaceAll(key, Uri.encodeComponent(value));
114 : });
115 :
116 0 : return Uri.parse(parsedUri);
117 : }
118 :
119 0 : Map<String, dynamic> toJson() => {
120 0 : 'creatorUserId': creatorUserId,
121 0 : 'data': data,
122 0 : 'id': id,
123 0 : 'name': name,
124 0 : 'type': type,
125 0 : 'url': url,
126 0 : 'waitForIframeLoad': waitForIframeLoad,
127 : };
128 : }
|