Add viewed history, diagnostics, tag chips and SWF viewer

This commit is contained in:
2026-05-24 11:35:43 +03:00
parent b02c776628
commit 361d0b3910
49 changed files with 4956 additions and 446 deletions
+72 -8
View File
@@ -148,13 +148,7 @@ class GelbooruProvider implements ContentProvider, CommentProvider {
}
List<PostComment> _commentsFromResponse(dynamic data, String postId) {
final raw = switch (data) {
List() => data,
{'comments': final List comments} => comments,
{'@attributes': _, 'comment': final List comments} => comments,
{'comment': final List comments} => comments,
_ => const [],
};
final raw = _commentItems(data);
return raw
.whereType<Map>()
.map((item) {
@@ -165,10 +159,18 @@ class GelbooruProvider implements ContentProvider, CommentProvider {
providerId: id,
authorName: (json['creator'] ??
json['creator_name'] ??
json['creator_id'] ??
json['user'] ??
json['username'] ??
json['author'] ??
'')
.toString(),
body: (json['body'] ?? json['comment'] ?? '').toString(),
body: (json['body'] ??
json['comment'] ??
json['content'] ??
json['text'] ??
'')
.toString(),
createdAt: DateTime.tryParse(
(json['created_at'] ?? json['created'] ?? '').toString(),
) ??
@@ -178,4 +180,66 @@ class GelbooruProvider implements ContentProvider, CommentProvider {
.where((comment) => comment.body.trim().isNotEmpty)
.toList();
}
List<dynamic> _commentItems(dynamic data) {
if (data is List) return data;
if (data is String) return _commentItemsFromText(data);
if (data is! Map) return const [];
final json = Map<String, dynamic>.from(data);
final comments = json['comments'];
if (comments is List) return comments;
if (comments is Map) return _commentItems(comments);
final comment = json['comment'];
if (comment is List) return comment;
if (comment is Map) return [comment];
return const [];
}
List<Map<String, dynamic>> _commentItemsFromText(String text) {
final items = <Map<String, dynamic>>[];
for (final match in RegExp(r'<comment\b([^>]*)>(.*?)</comment>',
caseSensitive: false, dotAll: true)
.allMatches(text)) {
final attrs = _attributes(match.group(1) ?? '');
final body = _tagValue(match.group(2) ?? '', 'body') ??
_tagValue(match.group(2) ?? '', 'comment') ??
match.group(2) ??
'';
items.add({...attrs, 'body': body});
}
for (final match
in RegExp(r'<comment\b([^>]*)/?>', caseSensitive: false, dotAll: true)
.allMatches(text)) {
final attrs = _attributes(match.group(1) ?? '');
if (attrs.isNotEmpty) items.add(attrs);
}
return items;
}
Map<String, dynamic> _attributes(String source) {
final result = <String, dynamic>{};
for (final match in RegExp(r'''([A-Za-z0-9_:-]+)\s*=\s*["']([^"']*)["']''')
.allMatches(source)) {
result[match.group(1)!] = _decodeEntities(match.group(2) ?? '');
}
return result;
}
String? _tagValue(String source, String tag) {
final match =
RegExp('<$tag[^>]*>(.*?)</$tag>', caseSensitive: false, dotAll: true)
.firstMatch(source);
final value = match?.group(1);
return value == null ? null : _decodeEntities(value.trim());
}
String _decodeEntities(String value) {
return value
.replaceAll('&amp;', '&')
.replaceAll('&lt;', '<')
.replaceAll('&gt;', '>')
.replaceAll('&quot;', '"')
.replaceAll('&#039;', "'")
.replaceAll('&apos;', "'");
}
}