Line data Source code
1 : /* MIT License
2 : *
3 : * Copyright (C) 2019, 2020, 2021 Famedly GmbH
4 : *
5 : * Permission is hereby granted, free of charge, to any person obtaining a copy
6 : * of this software and associated documentation files (the "Software"), to deal
7 : * in the Software without restriction, including without limitation the rights
8 : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : * copies of the Software, and to permit persons to whom the Software is
10 : * furnished to do so, subject to the following conditions:
11 : *
12 : * The above copyright notice and this permission notice shall be included in all
13 : * copies or substantial portions of the Software.
14 : *
15 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 : * SOFTWARE.
22 : */
23 :
24 : import 'package:matrix/matrix_api_lite/model/basic_event.dart';
25 : import 'package:matrix/matrix_api_lite/utils/filter_map_extension.dart';
26 : import 'package:matrix/matrix_api_lite/utils/try_get_map_extension.dart';
27 :
28 : extension ImagePackContentBasicEventExtension on BasicEvent {
29 2 : ImagePackContent get parsedImagePackContent =>
30 4 : ImagePackContent.fromJson(content);
31 : }
32 :
33 : enum ImagePackUsage {
34 : sticker,
35 : emoticon,
36 : }
37 :
38 2 : List<ImagePackUsage>? imagePackUsageFromJson(List<String>? json) => json
39 6 : ?.map((v) => {
40 : 'sticker': ImagePackUsage.sticker,
41 : 'emoticon': ImagePackUsage.emoticon,
42 2 : }[v])
43 2 : .whereType<ImagePackUsage>()
44 2 : .toList();
45 :
46 0 : List<String> imagePackUsageToJson(
47 : List<ImagePackUsage>? usage, List<String>? prevUsage) {
48 0 : final knownUsages = <String>{'sticker', 'emoticon'};
49 : final usagesStr = usage
50 0 : ?.map((v) => {
51 : ImagePackUsage.sticker: 'sticker',
52 : ImagePackUsage.emoticon: 'emoticon',
53 0 : }[v])
54 0 : .whereType<String>()
55 0 : .toList() ??
56 0 : [];
57 : // first we add all the unknown usages and the previous known usages which are new again
58 : final newUsages = prevUsage
59 0 : ?.where((v) => !knownUsages.contains(v) || usagesStr.contains(v))
60 0 : .toList() ??
61 0 : [];
62 : // now we need to add the new usages that we didn't add yet
63 0 : newUsages.addAll(usagesStr.where((v) => !newUsages.contains(v)));
64 : return newUsages;
65 : }
66 :
67 : class ImagePackContent {
68 : // we want to preserve potential custom keys in this object
69 : final Map<String, Object?> _json;
70 :
71 : Map<String, ImagePackImageContent> images;
72 : ImagePackPackContent pack;
73 :
74 0 : ImagePackContent({required this.images, required this.pack}) : _json = {};
75 :
76 2 : ImagePackContent.fromJson(Map<String, Object?> json)
77 6 : : _json = Map.fromEntries(json.entries.where(
78 8 : (e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))),
79 2 : pack = ImagePackPackContent.fromJson(
80 4 : json.tryGetMap<String, Object?>('pack') ?? {}),
81 6 : images = json.tryGetMap<String, Object?>('images')?.catchMap((k, v) =>
82 2 : MapEntry(
83 : k,
84 2 : ImagePackImageContent.fromJson(
85 : v as Map<String, Object?>))) ??
86 : // the "emoticons" key needs a small migration on the key, ":string:" --> "string"
87 2 : json.tryGetMap<String, Object?>('emoticons')?.catchMap((k, v) =>
88 0 : MapEntry(
89 0 : k.startsWith(':') && k.endsWith(':')
90 0 : ? k.substring(1, k.length - 1)
91 : : k,
92 0 : ImagePackImageContent.fromJson(
93 : v as Map<String, Object?>))) ??
94 : // the "short" key was still just a map from shortcode to mxc uri
95 2 : json.tryGetMap<String, String>('short')?.catchMap((k, v) =>
96 0 : MapEntry(
97 0 : k.startsWith(':') && k.endsWith(':')
98 0 : ? k.substring(1, k.length - 1)
99 : : k,
100 0 : ImagePackImageContent(url: Uri.parse(v)))) ??
101 2 : {};
102 :
103 0 : Map<String, Object?> toJson() => {
104 0 : ..._json,
105 0 : 'images': images.map((k, v) => MapEntry(k, v.toJson())),
106 0 : 'pack': pack.toJson(),
107 : };
108 : }
109 :
110 : class ImagePackImageContent {
111 : // we want to preserve potential custom keys in this object
112 : final Map<String, Object?> _json;
113 :
114 : Uri url;
115 : String? body;
116 : Map<String, Object?>? info;
117 : List<ImagePackUsage>? usage;
118 :
119 0 : ImagePackImageContent({required this.url, this.body, this.info, this.usage})
120 0 : : _json = {};
121 :
122 2 : ImagePackImageContent.fromJson(Map<String, Object?> json)
123 4 : : _json = Map.fromEntries(json.entries
124 10 : .where((e) => !['url', 'body', 'info'].contains(e.key))),
125 4 : url = Uri.parse(json['url'] as String),
126 2 : body = json.tryGet('body'),
127 2 : info = json.tryGetMap<String, Object?>('info'),
128 4 : usage = imagePackUsageFromJson(json.tryGetList<String>('usage'));
129 :
130 0 : Map<String, Object?> toJson() {
131 0 : return {
132 0 : ...Map.from(_json)..remove('usage'),
133 0 : 'url': url.toString(),
134 0 : if (body != null) 'body': body,
135 0 : if (info != null) 'info': info,
136 0 : if (usage != null)
137 0 : 'usage': imagePackUsageToJson(usage, _json.tryGetList<String>('usage')),
138 : };
139 : }
140 : }
141 :
142 : class ImagePackPackContent {
143 : // we want to preserve potential custom keys in this object
144 : final Map<String, Object?> _json;
145 :
146 : String? displayName;
147 : Uri? avatarUrl;
148 : List<ImagePackUsage>? usage;
149 : String? attribution;
150 :
151 0 : ImagePackPackContent(
152 : {this.displayName, this.avatarUrl, this.usage, this.attribution})
153 0 : : _json = {};
154 :
155 2 : ImagePackPackContent.fromJson(Map<String, Object?> json)
156 8 : : _json = Map.fromEntries(json.entries.where((e) =>
157 6 : !['display_name', 'avatar_url', 'attribution'].contains(e.key))),
158 2 : displayName = json.tryGet('display_name'),
159 : // we default to an invalid uri
160 4 : avatarUrl = Uri.tryParse(json.tryGet('avatar_url') ?? '.::'),
161 4 : usage = imagePackUsageFromJson(json.tryGetList<String>('usage')),
162 2 : attribution = json.tryGet('attribution');
163 :
164 0 : Map<String, Object?> toJson() {
165 0 : return {
166 0 : ...Map.from(_json)..remove('usage'),
167 0 : if (displayName != null) 'display_name': displayName,
168 0 : if (avatarUrl != null) 'avatar_url': avatarUrl.toString(),
169 0 : if (usage != null)
170 0 : 'usage': imagePackUsageToJson(usage, _json.tryGetList<String>('usage')),
171 0 : if (attribution != null) 'attribution': attribution,
172 : };
173 : }
174 : }
|