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(
55 : Room room,
56 : String name,
57 : Uri url, {
58 : bool isAudioOnly = false,
59 : }) =>
60 0 : MatrixWidget(
61 : room: room,
62 : name: name,
63 : type: 'm.jitsi',
64 0 : url: url.toString(),
65 0 : data: {
66 0 : 'domain': url.host,
67 0 : 'conferenceId': url.pathSegments.last,
68 : 'isAudioOnly': isAudioOnly,
69 : },
70 : );
71 :
72 : /// creates an `m.video` [MatrixWidget]
73 0 : factory MatrixWidget.video(Room room, String name, Uri url) => MatrixWidget(
74 : room: room,
75 : name: name,
76 : type: 'm.video',
77 0 : url: url.toString(),
78 0 : data: {
79 0 : 'url': url.toString(),
80 : },
81 : );
82 :
83 : /// creates an `m.custom` [MatrixWidget]
84 0 : factory MatrixWidget.custom(Room room, String name, Uri url) => MatrixWidget(
85 : room: room,
86 : name: name,
87 : type: 'm.custom',
88 0 : url: url.toString(),
89 0 : data: {
90 0 : 'url': url.toString(),
91 : },
92 : );
93 :
94 0 : Future<Uri> buildWidgetUrl() async {
95 : // See https://github.com/matrix-org/matrix-doc/issues/1236 for a
96 : // description, specifically the section
97 : // `What does the other stuff in content mean?`
98 0 : final userProfile = await room.client.getUserProfile(room.client.userID!);
99 0 : var parsedUri = url;
100 :
101 : // a key-value map with the strings to be replaced
102 0 : final replaceMap = {
103 0 : r'$matrix_user_id': room.client.userID!,
104 0 : r'$matrix_room_id': room.id,
105 0 : r'$matrix_display_name': userProfile.displayname ?? '',
106 0 : r'$matrix_avatar_url': userProfile.avatarUrl?.toString() ?? '',
107 : // removing potentially dangerous keys containing anything but
108 : // `[a-zA-Z0-9_-]` as well as non string values
109 0 : if (data != null)
110 0 : ...Map.from(data!)
111 0 : ..removeWhere(
112 0 : (key, value) =>
113 0 : !RegExp(r'^[\w-]+$').hasMatch(key) || !value is String,
114 : )
115 0 : ..map((key, value) => MapEntry('\$key', value)),
116 : };
117 :
118 0 : replaceMap.forEach((key, value) {
119 0 : parsedUri = parsedUri.replaceAll(key, Uri.encodeComponent(value));
120 : });
121 :
122 0 : return Uri.parse(parsedUri);
123 : }
124 :
125 0 : Map<String, dynamic> toJson() => {
126 0 : 'creatorUserId': creatorUserId,
127 0 : 'data': data,
128 0 : 'id': id,
129 0 : 'name': name,
130 0 : 'type': type,
131 0 : 'url': url,
132 0 : 'waitForIframeLoad': waitForIframeLoad,
133 : };
134 : }
|