Compare commits
	
		
			8 Commits
		
	
	
		
			2.4.2+76
			...
			e16bc80eea
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e16bc80eea | |||
| a4f6e8af56 | |||
| 060a97f5ec | |||
| 92f7e92018 | |||
| 5c483bd3b8 | |||
| 1c510d63fe | |||
| 115cb4adc1 | |||
| 54c098c274 | 
							
								
								
									
										
											BIN
										
									
								
								assets/fonts/Nunito-Bold.ttf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/fonts/Nunito-Bold.ttf
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/fonts/Nunito-Italic.ttf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/fonts/Nunito-Italic.ttf
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/fonts/Nunito-Regular.ttf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/fonts/Nunito-Regular.ttf
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -153,6 +153,11 @@ | ||||
|   "publisherRunBy": "Run by {}", | ||||
|   "fieldPublisherBelongToRealm": "Belongs to", | ||||
|   "fieldPublisherBelongToRealmUnset": "Unset Publisher Belongs to Realm", | ||||
|   "writePost": "Compose", | ||||
|   "postTypeStory": "Story", | ||||
|   "postTypeArticle": "Article", | ||||
|   "postTypeQuestion": "Question", | ||||
|   "postTypeVideo": "Video", | ||||
|   "writePostTypeStory": "Post a story", | ||||
|   "writePostTypeArticle": "Write an article", | ||||
|   "writePostTypeQuestion": "Ask a question", | ||||
| @@ -763,5 +768,6 @@ | ||||
|   "decrypting": "Decrypting……", | ||||
|   "decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online", | ||||
|   "messageUnablePreview": "Unable preview", | ||||
|   "messageUnablePreviewEncrypted": "Unable preview encrypted message" | ||||
|   "messageUnablePreviewEncrypted": "Unable preview encrypted message", | ||||
|   "postViewInGlobalDescription": "Do not view the post in the specific realm." | ||||
| } | ||||
|   | ||||
| @@ -137,6 +137,11 @@ | ||||
|   "publisherRunBy": "由 {} 管理", | ||||
|   "fieldPublisherBelongToRealm": "所属领域", | ||||
|   "fieldPublisherBelongToRealmUnset": "未设置发布者所属领域", | ||||
|   "writePost": "撰写", | ||||
|   "postTypeStory": "动态", | ||||
|   "postTypeArticle": "文章", | ||||
|   "postTypeQuestion": "问题", | ||||
|   "postTypeVideo": "视频", | ||||
|   "writePostTypeStory": "发动态", | ||||
|   "writePostTypeArticle": "写文章", | ||||
|   "writePostTypeQuestion": "提问题", | ||||
| @@ -761,5 +766,6 @@ | ||||
|   "decrypting": "解密中……", | ||||
|   "decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线", | ||||
|   "messageUnablePreview": "无法预览消息", | ||||
|   "messageUnablePreviewEncrypted": "无法预览加密消息" | ||||
|   "messageUnablePreviewEncrypted": "无法预览加密消息", | ||||
|   "postViewInGlobalDescription": "不查看特定领域的帖子。" | ||||
| } | ||||
|   | ||||
| @@ -137,6 +137,11 @@ | ||||
|   "publisherRunBy": "由 {} 管理", | ||||
|   "fieldPublisherBelongToRealm": "所屬領域", | ||||
|   "fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域", | ||||
|   "writePost": "撰寫", | ||||
|   "postTypeStory": "動態", | ||||
|   "postTypeArticle": "文章", | ||||
|   "postTypeQuestion": "問題", | ||||
|   "postTypeVideo": "視頻", | ||||
|   "writePostTypeStory": "發動態", | ||||
|   "writePostTypeArticle": "寫文章", | ||||
|   "writePostTypeQuestion": "提問題", | ||||
| @@ -761,5 +766,6 @@ | ||||
|   "decrypting": "解密中……", | ||||
|   "decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線", | ||||
|   "messageUnablePreview": "無法預覽消息", | ||||
|   "messageUnablePreviewEncrypted": "無法預覽加密消息" | ||||
|   "messageUnablePreviewEncrypted": "無法預覽加密消息", | ||||
|   "postViewInGlobalDescription": "不查看特定領域的帖子。" | ||||
| } | ||||
|   | ||||
| @@ -137,6 +137,11 @@ | ||||
|   "publisherRunBy": "由 {} 管理", | ||||
|   "fieldPublisherBelongToRealm": "所屬領域", | ||||
|   "fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域", | ||||
|   "writePost": "撰寫", | ||||
|   "postTypeStory": "動態", | ||||
|   "postTypeArticle": "文章", | ||||
|   "postTypeQuestion": "問題", | ||||
|   "postTypeVideo": "視頻", | ||||
|   "writePostTypeStory": "發動態", | ||||
|   "writePostTypeArticle": "寫文章", | ||||
|   "writePostTypeQuestion": "提問題", | ||||
| @@ -761,5 +766,6 @@ | ||||
|   "decrypting": "解密中……", | ||||
|   "decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線", | ||||
|   "messageUnablePreview": "無法預覽消息", | ||||
|   "messageUnablePreviewEncrypted": "無法預覽加密消息" | ||||
|   "messageUnablePreviewEncrypted": "無法預覽加密消息", | ||||
|   "postViewInGlobalDescription": "不查看特定領域的帖子。" | ||||
| } | ||||
|   | ||||
| @@ -71,7 +71,8 @@ class PostWriteMedia { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   PostWriteMedia.fromBytes(this.raw, this.name, this.type, {this.attachment, this.file}); | ||||
|   PostWriteMedia.fromBytes(this.raw, this.name, this.type, | ||||
|       {this.attachment, this.file}); | ||||
|  | ||||
|   bool get isEmpty => attachment == null && file == null && raw == null; | ||||
|  | ||||
| @@ -105,7 +106,8 @@ class PostWriteMedia { | ||||
|   }) { | ||||
|     if (attachment != null) { | ||||
|       final sn = context.read<SnNetworkProvider>(); | ||||
|       final ImageProvider provider = UniversalImage.provider(sn.getAttachmentUrl(attachment!.rid)); | ||||
|       final ImageProvider provider = | ||||
|           UniversalImage.provider(sn.getAttachmentUrl(attachment!.rid)); | ||||
|       if (width != null && height != null && !kIsWeb) { | ||||
|         return ResizeImage( | ||||
|           provider, | ||||
| @@ -116,7 +118,8 @@ class PostWriteMedia { | ||||
|       } | ||||
|       return provider; | ||||
|     } else if (file != null) { | ||||
|       final ImageProvider provider = kIsWeb ? NetworkImage(file!.path) : FileImage(File(file!.path)); | ||||
|       final ImageProvider provider = | ||||
|           kIsWeb ? NetworkImage(file!.path) : FileImage(File(file!.path)); | ||||
|       if (width != null && height != null) { | ||||
|         return ResizeImage( | ||||
|           provider, | ||||
| @@ -159,11 +162,14 @@ class PostWriteController extends ChangeNotifier { | ||||
|   final TextEditingController aliasController = TextEditingController(); | ||||
|   final TextEditingController rewardController = TextEditingController(); | ||||
|  | ||||
|   ContentInsertionConfiguration get contentInsertionConfiguration => ContentInsertionConfiguration( | ||||
|   ContentInsertionConfiguration get contentInsertionConfiguration => | ||||
|       ContentInsertionConfiguration( | ||||
|         onContentInserted: (KeyboardInsertedContent content) { | ||||
|           if (content.hasData) { | ||||
|             addAttachments( | ||||
|                 [PostWriteMedia.fromBytes(content.data!, 'attachmentInsertedImage'.tr(), SnMediaType.image)]); | ||||
|             addAttachments([ | ||||
|               PostWriteMedia.fromBytes(content.data!, | ||||
|                   'attachmentInsertedImage'.tr(), SnMediaType.image) | ||||
|             ]); | ||||
|           } | ||||
|         }, | ||||
|       ); | ||||
| @@ -193,7 +199,8 @@ class PostWriteController extends ChangeNotifier { | ||||
|  | ||||
|   String get description => descriptionController.text; | ||||
|  | ||||
|   bool get isRelatedNull => ![editingPost, repostingPost, replyingPost].any((ele) => ele != null); | ||||
|   bool get isRelatedNull => | ||||
|       ![editingPost, repostingPost, replyingPost].any((ele) => ele != null); | ||||
|  | ||||
|   bool isLoading = false, isBusy = false; | ||||
|   double? progress; | ||||
| @@ -237,14 +244,18 @@ class PostWriteController extends ChangeNotifier { | ||||
|         publishedAt = post.publishedAt; | ||||
|         publishedUntil = post.publishedUntil; | ||||
|         visibleUsers = List.from(post.visibleUsersList ?? [], growable: true); | ||||
|         invisibleUsers = List.from(post.invisibleUsersList ?? [], growable: true); | ||||
|         invisibleUsers = | ||||
|             List.from(post.invisibleUsersList ?? [], growable: true); | ||||
|         visibility = post.visibility; | ||||
|         tags = List.from(post.tags.map((ele) => ele.alias), growable: true); | ||||
|         categories = List.from(post.categories.map((ele) => ele.alias), growable: true); | ||||
|         attachments.addAll(post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []); | ||||
|         categories = | ||||
|             List.from(post.categories.map((ele) => ele.alias), growable: true); | ||||
|         attachments.addAll( | ||||
|             post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []); | ||||
|         poll = post.preload?.poll; | ||||
|  | ||||
|         if (post.preload?.thumbnail != null && (post.preload?.thumbnail?.rid.isNotEmpty ?? false)) { | ||||
|         if (post.preload?.thumbnail != null && | ||||
|             (post.preload?.thumbnail?.rid.isNotEmpty ?? false)) { | ||||
|           thumbnail = PostWriteMedia(post.preload!.thumbnail); | ||||
|         } | ||||
|         if (post.preload?.realm != null) { | ||||
| @@ -272,7 +283,8 @@ class PostWriteController extends ChangeNotifier { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<SnAttachment> _uploadAttachment(BuildContext context, PostWriteMedia media, | ||||
|   Future<SnAttachment> _uploadAttachment( | ||||
|       BuildContext context, PostWriteMedia media, | ||||
|       {bool isCompressed = false}) async { | ||||
|     final attach = context.read<SnAttachmentProvider>(); | ||||
|  | ||||
| @@ -281,7 +293,9 @@ class PostWriteController extends ChangeNotifier { | ||||
|       media.name, | ||||
|       'interactive', | ||||
|       null, | ||||
|       mimetype: media.raw != null && media.type == SnMediaType.image ? 'image/png' : null, | ||||
|       mimetype: media.raw != null && media.type == SnMediaType.image | ||||
|           ? 'image/png' | ||||
|           : null, | ||||
|     ); | ||||
|  | ||||
|     var item = await attach.chunkedUploadParts( | ||||
| @@ -297,9 +311,11 @@ class PostWriteController extends ChangeNotifier { | ||||
|  | ||||
|     if (media.type == SnMediaType.video && !isCompressed && context.mounted) { | ||||
|       try { | ||||
|         final compressedAttachment = await _tryCompressVideoCopy(context, media); | ||||
|         final compressedAttachment = | ||||
|             await _tryCompressVideoCopy(context, media); | ||||
|         if (compressedAttachment != null) { | ||||
|           item = await attach.updateOne(item, compressedId: compressedAttachment.id); | ||||
|           item = await attach.updateOne(item, | ||||
|               compressedId: compressedAttachment.id); | ||||
|         } | ||||
|       } catch (err) { | ||||
|         if (context.mounted) context.showErrorDialog(err); | ||||
| @@ -309,8 +325,10 @@ class PostWriteController extends ChangeNotifier { | ||||
|     return item; | ||||
|   } | ||||
|  | ||||
|   Future<SnAttachment?> _tryCompressVideoCopy(BuildContext context, PostWriteMedia media) async { | ||||
|     if (kIsWeb || !(Platform.isAndroid || Platform.isIOS || Platform.isMacOS)) return null; | ||||
|   Future<SnAttachment?> _tryCompressVideoCopy( | ||||
|       BuildContext context, PostWriteMedia media) async { | ||||
|     if (kIsWeb || !(Platform.isAndroid || Platform.isIOS || Platform.isMacOS)) | ||||
|       return null; | ||||
|     if (media.type != SnMediaType.video) return null; | ||||
|     if (media.file == null) return null; | ||||
|     if (VideoCompress.isCompressing) return null; | ||||
| @@ -334,7 +352,8 @@ class PostWriteController extends ChangeNotifier { | ||||
|     if (!context.mounted) return null; | ||||
|  | ||||
|     final compressedMedia = PostWriteMedia.fromFile(XFile(mediaInfo.path!)); | ||||
|     final compressedAttachment = await _uploadAttachment(context, compressedMedia, isCompressed: true); | ||||
|     final compressedAttachment = | ||||
|         await _uploadAttachment(context, compressedMedia, isCompressed: true); | ||||
|  | ||||
|     return compressedAttachment; | ||||
|   } | ||||
| @@ -370,18 +389,25 @@ class PostWriteController extends ChangeNotifier { | ||||
|           'content': contentController.text, | ||||
|           if (aliasController.text.isNotEmpty) 'alias': aliasController.text, | ||||
|           if (titleController.text.isNotEmpty) 'title': titleController.text, | ||||
|           if (descriptionController.text.isNotEmpty) 'description': descriptionController.text, | ||||
|           if (descriptionController.text.isNotEmpty) | ||||
|             'description': descriptionController.text, | ||||
|           if (rewardController.text.isNotEmpty) 'reward': rewardController.text, | ||||
|           if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.toJson(), | ||||
|           'attachments': | ||||
|               attachments.where((e) => e.attachment != null).map((e) => e.attachment!.toJson()).toList(growable: true), | ||||
|           if (thumbnail != null && thumbnail!.attachment != null) | ||||
|             'thumbnail': thumbnail!.attachment!.toJson(), | ||||
|           'attachments': attachments | ||||
|               .where((e) => e.attachment != null) | ||||
|               .map((e) => e.attachment!.toJson()) | ||||
|               .toList(growable: true), | ||||
|           'tags': tags.map((ele) => {'alias': ele}).toList(growable: true), | ||||
|           'categories': categories.map((ele) => {'alias': ele}).toList(growable: true), | ||||
|           'categories': | ||||
|               categories.map((ele) => {'alias': ele}).toList(growable: true), | ||||
|           'visibility': visibility, | ||||
|           'visible_users_list': visibleUsers, | ||||
|           'invisible_users_list': invisibleUsers, | ||||
|           if (publishedAt != null) 'published_at': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (publishedUntil != null) 'published_until': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (publishedAt != null) | ||||
|             'published_at': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (publishedUntil != null) | ||||
|             'published_until': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (replyingPost != null) 'reply_to': replyingPost!.toJson(), | ||||
|           if (repostingPost != null) 'repost_to': repostingPost!.toJson(), | ||||
|           if (poll != null) 'poll': poll!.toJson(), | ||||
| @@ -391,6 +417,12 @@ class PostWriteController extends ChangeNotifier { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   bool get isNotEmpty => | ||||
|       title.isNotEmpty || | ||||
|       description.isNotEmpty || | ||||
|       contentController.text.isNotEmpty || | ||||
|       attachments.isNotEmpty; | ||||
|  | ||||
|   bool temporaryRestored = false; | ||||
|  | ||||
|   void _temporaryLoad() { | ||||
| @@ -403,18 +435,24 @@ class PostWriteController extends ChangeNotifier { | ||||
|       titleController.text = data['title'] ?? ''; | ||||
|       descriptionController.text = data['description'] ?? ''; | ||||
|       rewardController.text = data['reward']?.toString() ?? ''; | ||||
|       if (data['thumbnail'] != null) thumbnail = PostWriteMedia(SnAttachment.fromJson(data['thumbnail'])); | ||||
|       attachments | ||||
|           .addAll(data['attachments'].map((ele) => PostWriteMedia(SnAttachment.fromJson(ele))).cast<PostWriteMedia>()); | ||||
|       if (data['thumbnail'] != null) | ||||
|         thumbnail = PostWriteMedia(SnAttachment.fromJson(data['thumbnail'])); | ||||
|       attachments.addAll(data['attachments'] | ||||
|           .map((ele) => PostWriteMedia(SnAttachment.fromJson(ele))) | ||||
|           .cast<PostWriteMedia>()); | ||||
|       tags = List.from(data['tags'].map((ele) => ele['alias'])); | ||||
|       categories = List.from(data['categories'].map((ele) => ele['alias'])); | ||||
|       visibility = data['visibility']; | ||||
|       visibleUsers = List.from(data['visible_users_list'] ?? []); | ||||
|       invisibleUsers = List.from(data['invisible_users_list'] ?? []); | ||||
|       if (data['published_at'] != null) publishedAt = DateTime.tryParse(data['published_at'])?.toLocal(); | ||||
|       if (data['published_until'] != null) publishedUntil = DateTime.tryParse(data['published_until'])?.toLocal(); | ||||
|       replyingPost = data['reply_to'] != null ? SnPost.fromJson(data['reply_to']) : null; | ||||
|       repostingPost = data['repost_to'] != null ? SnPost.fromJson(data['repost_to']) : null; | ||||
|       if (data['published_at'] != null) | ||||
|         publishedAt = DateTime.tryParse(data['published_at'])?.toLocal(); | ||||
|       if (data['published_until'] != null) | ||||
|         publishedUntil = DateTime.tryParse(data['published_until'])?.toLocal(); | ||||
|       replyingPost = | ||||
|           data['reply_to'] != null ? SnPost.fromJson(data['reply_to']) : null; | ||||
|       repostingPost = | ||||
|           data['repost_to'] != null ? SnPost.fromJson(data['repost_to']) : null; | ||||
|       poll = data['poll'] != null ? SnPoll.fromJson(data['poll']) : null; | ||||
|       realm = data['realm'] != null ? SnRealm.fromJson(data['realm']) : null; | ||||
|       temporaryRestored = true; | ||||
| @@ -463,7 +501,9 @@ class PostWriteController extends ChangeNotifier { | ||||
|           media.name, | ||||
|           'interactive', | ||||
|           null, | ||||
|           mimetype: media.raw != null && media.type == SnMediaType.image ? 'image/png' : null, | ||||
|           mimetype: media.raw != null && media.type == SnMediaType.image | ||||
|               ? 'image/png' | ||||
|               : null, | ||||
|         ); | ||||
|  | ||||
|         var item = await attach.chunkedUploadParts( | ||||
| @@ -472,16 +512,20 @@ class PostWriteController extends ChangeNotifier { | ||||
|           place.$2, | ||||
|           onProgress: (value) { | ||||
|             // Calculate overall progress for attachments | ||||
|             progress = math.max(((i + value) / attachments.length) * kAttachmentProgressWeight, value); | ||||
|             progress = math.max( | ||||
|                 ((i + value) / attachments.length) * kAttachmentProgressWeight, | ||||
|                 value); | ||||
|             notifyListeners(); | ||||
|           }, | ||||
|         ); | ||||
|  | ||||
|         try { | ||||
|           if (context.mounted) { | ||||
|             final compressedAttachment = await _tryCompressVideoCopy(context, media); | ||||
|             final compressedAttachment = | ||||
|                 await _tryCompressVideoCopy(context, media); | ||||
|             if (compressedAttachment != null) { | ||||
|               item = await attach.updateOne(item, compressedId: compressedAttachment.id); | ||||
|               item = await attach.updateOne(item, | ||||
|                   compressedId: compressedAttachment.id); | ||||
|             } | ||||
|           } | ||||
|         } catch (err) { | ||||
| @@ -518,16 +562,23 @@ class PostWriteController extends ChangeNotifier { | ||||
|           'content': contentController.text, | ||||
|           if (aliasController.text.isNotEmpty) 'alias': aliasController.text, | ||||
|           if (titleController.text.isNotEmpty) 'title': titleController.text, | ||||
|           if (descriptionController.text.isNotEmpty) 'description': descriptionController.text, | ||||
|           if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.rid, | ||||
|           'attachments': attachments.where((e) => e.attachment != null).map((e) => e.attachment!.rid).toList(), | ||||
|           if (descriptionController.text.isNotEmpty) | ||||
|             'description': descriptionController.text, | ||||
|           if (thumbnail != null && thumbnail!.attachment != null) | ||||
|             'thumbnail': thumbnail!.attachment!.rid, | ||||
|           'attachments': attachments | ||||
|               .where((e) => e.attachment != null) | ||||
|               .map((e) => e.attachment!.rid) | ||||
|               .toList(), | ||||
|           'tags': tags.map((ele) => {'alias': ele}).toList(), | ||||
|           'categories': categories.map((ele) => {'alias': ele}).toList(), | ||||
|           'visibility': visibility, | ||||
|           'visible_users_list': visibleUsers, | ||||
|           'invisible_users_list': invisibleUsers, | ||||
|           if (publishedAt != null) 'published_at': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (publishedUntil != null) 'published_until': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (publishedAt != null) | ||||
|             'published_at': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (publishedUntil != null) | ||||
|             'published_until': publishedAt!.toUtc().toIso8601String(), | ||||
|           if (replyingPost != null) 'reply_to': replyingPost!.id, | ||||
|           if (repostingPost != null) 'repost_to': repostingPost!.id, | ||||
|           if (reward != null) 'reward': reward, | ||||
| @@ -536,11 +587,14 @@ class PostWriteController extends ChangeNotifier { | ||||
|           if (realm != null) 'realm': realm!.id, | ||||
|         }, | ||||
|         onSendProgress: (count, total) { | ||||
|           progress = baseProgressVal + (count / total) * (kPostingProgressWeight / 2); | ||||
|           progress = | ||||
|               baseProgressVal + (count / total) * (kPostingProgressWeight / 2); | ||||
|           notifyListeners(); | ||||
|         }, | ||||
|         onReceiveProgress: (count, total) { | ||||
|           progress = baseProgressVal + (kPostingProgressWeight / 2) + (count / total) * (kPostingProgressWeight / 2); | ||||
|           progress = baseProgressVal + | ||||
|               (kPostingProgressWeight / 2) + | ||||
|               (count / total) * (kPostingProgressWeight / 2); | ||||
|           notifyListeners(); | ||||
|         }, | ||||
|         options: Options( | ||||
| @@ -683,7 +737,8 @@ class PostWriteController extends ChangeNotifier { | ||||
|     repostingPost = null; | ||||
|     mode = kTitleMap.keys.first; | ||||
|     temporaryRestored = false; | ||||
|     SharedPreferences.getInstance().then((prefs) => prefs.remove(kTemporaryStorageKey)); | ||||
|     SharedPreferences.getInstance() | ||||
|         .then((prefs) => prefs.remove(kTemporaryStorageKey)); | ||||
|     notifyListeners(); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -66,10 +66,10 @@ final _appRoutes = [ | ||||
|     builder: (context, state) => const ExploreScreen(), | ||||
|     routes: [ | ||||
|       GoRoute( | ||||
|         path: '/write/:mode', | ||||
|         path: '/write', | ||||
|         name: 'postEditor', | ||||
|         builder: (context, state) => PostEditorScreen( | ||||
|           mode: state.pathParameters['mode']!, | ||||
|           mode: state.uri.queryParameters['mode'], | ||||
|           postEditId: int.tryParse( | ||||
|             state.uri.queryParameters['editing'] ?? '', | ||||
|           ), | ||||
|   | ||||
| @@ -204,7 +204,6 @@ class _ChatScreenState extends State<ChatScreen> { | ||||
|               Theme.of(context).floatingActionButtonTheme.foregroundColor, | ||||
|           backgroundColor: | ||||
|               Theme.of(context).floatingActionButtonTheme.backgroundColor, | ||||
|           shape: const CircleBorder(), | ||||
|         ), | ||||
|         closeButtonBuilder: DefaultFloatingActionButtonBuilder( | ||||
|           child: const Icon(Symbols.close, size: 28), | ||||
| @@ -213,7 +212,6 @@ class _ChatScreenState extends State<ChatScreen> { | ||||
|               Theme.of(context).floatingActionButtonTheme.foregroundColor, | ||||
|           backgroundColor: | ||||
|               Theme.of(context).floatingActionButtonTheme.backgroundColor, | ||||
|           shape: const CircleBorder(), | ||||
|         ), | ||||
|         children: [ | ||||
|           Row( | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import 'package:dropdown_button2/dropdown_button2.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_expandable_fab/flutter_expandable_fab.dart'; | ||||
| @@ -19,6 +18,9 @@ import 'package:surface/widgets/navigation/app_scaffold.dart'; | ||||
| import 'package:surface/widgets/post/post_item.dart'; | ||||
| import 'package:very_good_infinite_list/very_good_infinite_list.dart'; | ||||
|  | ||||
| const kPostChannels = ['Global', 'Friends', 'Following']; | ||||
| const kPostChannelIcons = [Symbols.globe, Symbols.group, Symbols.subscriptions]; | ||||
|  | ||||
| const Map<String, IconData> kCategoryIcons = { | ||||
|   'technology': Symbols.tools_wrench, | ||||
|   'gaming': Symbols.gamepad, | ||||
| @@ -39,17 +41,17 @@ class ExploreScreen extends StatefulWidget { | ||||
|   State<ExploreScreen> createState() => _ExploreScreenState(); | ||||
| } | ||||
|  | ||||
| // You know what? I'm not going to make this a global variable. | ||||
| // Cuz the global key make the selected category not update to child widget when the category is changed. | ||||
| SnPostCategory? _selectedCategory; | ||||
|  | ||||
| class _ExploreScreenState extends State<ExploreScreen> | ||||
|     with SingleTickerProviderStateMixin { | ||||
|   late final TabController _tabController = | ||||
|       TabController(length: 4, vsync: this); | ||||
|     with TickerProviderStateMixin { | ||||
|   late TabController _tabController = TabController( | ||||
|     length: kPostChannels.length, | ||||
|     vsync: this, | ||||
|   ); | ||||
|  | ||||
|   final _fabKey = GlobalKey<ExpandableFabState>(); | ||||
|   final _listKeys = List.generate(4, (_) => GlobalKey<_PostListWidgetState>()); | ||||
|   final _listKey = GlobalKey<_PostListWidgetState>(); | ||||
|  | ||||
|   bool _showCategories = false; | ||||
|  | ||||
|   final List<SnPostCategory> _categories = List.empty(growable: true); | ||||
|  | ||||
| @@ -69,14 +71,64 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _clearFilter() { | ||||
|     _selectedCategory = null; | ||||
|   final List<SnRealm> _realms = List.empty(growable: true); | ||||
|  | ||||
|   Future<void> _fetchRealms() async { | ||||
|     try { | ||||
|       final rels = context.read<SnRealmProvider>(); | ||||
|       final out = await rels.listAvailableRealms(); | ||||
|       setState(() { | ||||
|         _realms.addAll(out); | ||||
|       }); | ||||
|     } catch (err) { | ||||
|       if (!mounted) return; | ||||
|       context.showErrorDialog(err); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _toggleShowCategories() { | ||||
|     _showCategories = !_showCategories; | ||||
|     if (_showCategories) { | ||||
|       _tabController = TabController(length: _categories.length, vsync: this); | ||||
|     } else { | ||||
|       _tabController = TabController(length: kPostChannels.length, vsync: this); | ||||
|     } | ||||
|     _tabListen(); | ||||
|     setState(() {}); | ||||
|   } | ||||
|  | ||||
|   void _tabListen() { | ||||
|     _tabController.addListener(() { | ||||
|       if (_tabController.indexIsChanging) { | ||||
|         if (_showCategories) { | ||||
|           _listKey.currentState?.setCategory(_categories[_tabController.index]); | ||||
|           _listKey.currentState?.refreshPosts(); | ||||
|           return; | ||||
|         } | ||||
|         switch (_tabController.index) { | ||||
|           case 0: | ||||
|           case 3: | ||||
|             _listKey.currentState?.setChannel(null); | ||||
|             break; | ||||
|           case 1: | ||||
|             _listKey.currentState?.setChannel('friends'); | ||||
|             break; | ||||
|           case 2: | ||||
|             _listKey.currentState?.setChannel('following'); | ||||
|             break; | ||||
|         } | ||||
|         _listKey.currentState?.refreshPosts(); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     _fetchCategories(); | ||||
|     super.initState(); | ||||
|     _tabListen(); | ||||
|     _fetchCategories(); | ||||
|     _fetchRealms(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
| @@ -86,7 +138,7 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
|   } | ||||
|  | ||||
|   Future<void> refreshPosts() async { | ||||
|     await _listKeys[_tabController.index].currentState?.refreshPosts(); | ||||
|     await _listKey.currentState?.refreshPosts(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
| @@ -111,7 +163,6 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
|               Theme.of(context).floatingActionButtonTheme.foregroundColor, | ||||
|           backgroundColor: | ||||
|               Theme.of(context).floatingActionButtonTheme.backgroundColor, | ||||
|           shape: const CircleBorder(), | ||||
|         ), | ||||
|         closeButtonBuilder: DefaultFloatingActionButtonBuilder( | ||||
|           child: const Icon(Symbols.close, size: 28), | ||||
| @@ -120,90 +171,24 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
|               Theme.of(context).floatingActionButtonTheme.foregroundColor, | ||||
|           backgroundColor: | ||||
|               Theme.of(context).floatingActionButtonTheme.backgroundColor, | ||||
|           shape: const CircleBorder(), | ||||
|         ), | ||||
|         children: [ | ||||
|           Row( | ||||
|             children: [ | ||||
|               Text('writePostTypeStory').tr(), | ||||
|               Text('writePost').tr(), | ||||
|               const Gap(20), | ||||
|               FloatingActionButton( | ||||
|                 heroTag: null, | ||||
|                 tooltip: 'writePostTypeStory'.tr(), | ||||
|                 tooltip: 'writePost'.tr(), | ||||
|                 onPressed: () { | ||||
|                   GoRouter.of(context).pushNamed('postEditor', pathParameters: { | ||||
|                     'mode': 'stories', | ||||
|                   }).then((value) { | ||||
|                   GoRouter.of(context).pushNamed('postEditor').then((value) { | ||||
|                     if (value == true) { | ||||
|                       refreshPosts(); | ||||
|                     } | ||||
|                   }); | ||||
|                   _fabKey.currentState!.toggle(); | ||||
|                 }, | ||||
|                 child: const Icon(Symbols.post_rounded), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|           Row( | ||||
|             children: [ | ||||
|               Text('writePostTypeArticle').tr(), | ||||
|               const Gap(20), | ||||
|               FloatingActionButton( | ||||
|                 heroTag: null, | ||||
|                 tooltip: 'writePostTypeArticle'.tr(), | ||||
|                 onPressed: () { | ||||
|                   GoRouter.of(context).pushNamed('postEditor', pathParameters: { | ||||
|                     'mode': 'articles', | ||||
|                   }).then((value) { | ||||
|                     if (value == true) { | ||||
|                       refreshPosts(); | ||||
|                     } | ||||
|                   }); | ||||
|                   _fabKey.currentState!.toggle(); | ||||
|                 }, | ||||
|                 child: const Icon(Symbols.news), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|           Row( | ||||
|             children: [ | ||||
|               Text('writePostTypeQuestion').tr(), | ||||
|               const Gap(20), | ||||
|               FloatingActionButton( | ||||
|                 heroTag: null, | ||||
|                 tooltip: 'writePostTypeQuestion'.tr(), | ||||
|                 onPressed: () { | ||||
|                   GoRouter.of(context).pushNamed('postEditor', pathParameters: { | ||||
|                     'mode': 'questions', | ||||
|                   }).then((value) { | ||||
|                     if (value == true) { | ||||
|                       refreshPosts(); | ||||
|                     } | ||||
|                   }); | ||||
|                   _fabKey.currentState!.toggle(); | ||||
|                 }, | ||||
|                 child: const Icon(Symbols.question_answer), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|           Row( | ||||
|             children: [ | ||||
|               Text('writePostTypeVideo').tr(), | ||||
|               const Gap(20), | ||||
|               FloatingActionButton( | ||||
|                 heroTag: null, | ||||
|                 tooltip: 'writePostTypeVideo'.tr(), | ||||
|                 onPressed: () { | ||||
|                   GoRouter.of(context).pushNamed('postEditor', pathParameters: { | ||||
|                     'mode': 'videos', | ||||
|                   }).then((value) { | ||||
|                     if (value == true) { | ||||
|                       refreshPosts(); | ||||
|                     } | ||||
|                   }); | ||||
|                   _fabKey.currentState!.toggle(); | ||||
|                 }, | ||||
|                 child: const Icon(Symbols.video_call), | ||||
|                 child: const Icon(Symbols.edit), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
| @@ -216,25 +201,62 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
|               handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), | ||||
|               sliver: SliverAppBar( | ||||
|                 leading: AutoAppBarLeading(), | ||||
|                 title: Text('screenExplore').tr(), | ||||
|                 titleSpacing: 0, | ||||
|                 title: Row( | ||||
|                   children: [ | ||||
|                     IconButton( | ||||
|                       padding: EdgeInsets.zero, | ||||
|                       constraints: const BoxConstraints(), | ||||
|                       visualDensity: VisualDensity.compact, | ||||
|                       icon: _listKey.currentState?.realm != null | ||||
|                           ? AccountImage( | ||||
|                               content: _listKey.currentState!.realm!.avatar, | ||||
|                               radius: 14, | ||||
|                             ) | ||||
|                           : const Icon(Symbols.group), | ||||
|                       onPressed: () { | ||||
|                         showModalBottomSheet( | ||||
|                           context: context, | ||||
|                           builder: (context) => _PostListRealmPopup( | ||||
|                             realms: _realms, | ||||
|                             onUpdate: (realm) { | ||||
|                               _listKey.currentState?.setRealm(realm); | ||||
|                               _listKey.currentState?.refreshPosts(); | ||||
|                               Future.delayed(const Duration(milliseconds: 100), | ||||
|                                   () { | ||||
|                                 if (mounted) { | ||||
|                                   setState(() {}); | ||||
|                                 } | ||||
|                               }); | ||||
|                             }, | ||||
|                           ), | ||||
|                         ); | ||||
|                       }, | ||||
|                     ), | ||||
|                     Expanded( | ||||
|                       child: Center( | ||||
|                         child: Text('screenExplore').tr(), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ], | ||||
|                 ), | ||||
|                 floating: true, | ||||
|                 snap: true, | ||||
|                 actions: [ | ||||
|                   IconButton( | ||||
|                     icon: const Icon(Symbols.category), | ||||
|                     style: _showCategories | ||||
|                         ? ButtonStyle( | ||||
|                             foregroundColor: WidgetStateProperty.all( | ||||
|                               Theme.of(context).colorScheme.primary, | ||||
|                             ), | ||||
|                             backgroundColor: MaterialStateProperty.all( | ||||
|                               Theme.of(context).colorScheme.secondaryContainer, | ||||
|                             ), | ||||
|                           ) | ||||
|                         : null, | ||||
|                     onPressed: () { | ||||
|                       showModalBottomSheet( | ||||
|                         context: context, | ||||
|                         builder: (context) => _PostCategoryPickerPopup( | ||||
|                           categories: _categories, | ||||
|                           selected: _selectedCategory, | ||||
|                         ), | ||||
|                       ).then((value) { | ||||
|                         if (value != null && context.mounted) { | ||||
|                           _selectedCategory = value == false ? null : value; | ||||
|                           refreshPosts(); | ||||
|                         } | ||||
|                       }); | ||||
|                       _toggleShowCategories(); | ||||
|                     }, | ||||
|                   ), | ||||
|                   IconButton( | ||||
| @@ -246,122 +268,74 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
|                   const Gap(8), | ||||
|                 ], | ||||
|                 bottom: TabBar( | ||||
|                   isScrollable: _showCategories, | ||||
|                   controller: _tabController, | ||||
|                   tabs: [ | ||||
|                     Tab( | ||||
|                       child: Row( | ||||
|                         mainAxisSize: MainAxisSize.min, | ||||
|                         crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                         children: [ | ||||
|                           Icon(Symbols.globe, | ||||
|                               size: 20, | ||||
|                               color: Theme.of(context) | ||||
|                                   .appBarTheme | ||||
|                                   .foregroundColor), | ||||
|                           const Gap(8), | ||||
|                           Flexible( | ||||
|                             child: Text( | ||||
|                               'postChannelGlobal', | ||||
|                               maxLines: 1, | ||||
|                             ).tr().textColor( | ||||
|                                 Theme.of(context).appBarTheme.foregroundColor), | ||||
|                           ), | ||||
|                   tabs: _showCategories | ||||
|                       ? [ | ||||
|                           for (final category in _categories) | ||||
|                             Tab( | ||||
|                               child: Row( | ||||
|                                 mainAxisSize: MainAxisSize.min, | ||||
|                                 crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                                 children: [ | ||||
|                                   Icon( | ||||
|                                       kCategoryIcons[category.alias] ?? | ||||
|                                           Symbols.question_mark, | ||||
|                                       color: Theme.of(context) | ||||
|                                           .appBarTheme | ||||
|                                           .foregroundColor!), | ||||
|                                   const Gap(8), | ||||
|                                   Flexible( | ||||
|                                     child: Text( | ||||
|                                       'postCategory${category.alias.capitalize()}' | ||||
|                                               .trExists() | ||||
|                                           ? 'postCategory${category.alias.capitalize()}' | ||||
|                                               .tr() | ||||
|                                           : category.name, | ||||
|                                       maxLines: 1, | ||||
|                                     ).textColor(Theme.of(context) | ||||
|                                         .appBarTheme | ||||
|                                         .foregroundColor!), | ||||
|                                   ), | ||||
|                                 ], | ||||
|                               ), | ||||
|                             ), | ||||
|                         ] | ||||
|                       : [ | ||||
|                           for (final channel in kPostChannels) | ||||
|                             Tab( | ||||
|                               child: Row( | ||||
|                                 mainAxisSize: MainAxisSize.min, | ||||
|                                 crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                                 children: [ | ||||
|                                   Icon( | ||||
|                                     kPostChannelIcons[ | ||||
|                                         kPostChannels.indexOf(channel)], | ||||
|                                     size: 20, | ||||
|                                     color: Theme.of(context) | ||||
|                                         .appBarTheme | ||||
|                                         .foregroundColor, | ||||
|                                   ), | ||||
|                                   const Gap(8), | ||||
|                                   Flexible( | ||||
|                                     child: Text( | ||||
|                                       'postChannel$channel', | ||||
|                                       maxLines: 1, | ||||
|                                     ).tr().textColor(Theme.of(context) | ||||
|                                         .appBarTheme | ||||
|                                         .foregroundColor), | ||||
|                                   ), | ||||
|                                 ], | ||||
|                               ), | ||||
|                             ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                     Tab( | ||||
|                       child: Row( | ||||
|                         mainAxisSize: MainAxisSize.min, | ||||
|                         crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                         children: [ | ||||
|                           Icon(Symbols.group, | ||||
|                               size: 20, | ||||
|                               color: Theme.of(context) | ||||
|                                   .appBarTheme | ||||
|                                   .foregroundColor), | ||||
|                           const Gap(8), | ||||
|                           Flexible( | ||||
|                             child: Text( | ||||
|                               'postChannelFriends', | ||||
|                               maxLines: 1, | ||||
|                               textAlign: TextAlign.center, | ||||
|                             ).tr().textColor( | ||||
|                                 Theme.of(context).appBarTheme.foregroundColor), | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                     Tab( | ||||
|                       child: Row( | ||||
|                         mainAxisSize: MainAxisSize.min, | ||||
|                         crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                         children: [ | ||||
|                           Icon(Symbols.subscriptions, | ||||
|                               size: 20, | ||||
|                               color: Theme.of(context) | ||||
|                                   .appBarTheme | ||||
|                                   .foregroundColor), | ||||
|                           const Gap(8), | ||||
|                           Flexible( | ||||
|                             child: Text( | ||||
|                               'postChannelFollowing', | ||||
|                               maxLines: 1, | ||||
|                             ).tr().textColor( | ||||
|                                 Theme.of(context).appBarTheme.foregroundColor), | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                     Tab( | ||||
|                       child: Row( | ||||
|                         mainAxisSize: MainAxisSize.min, | ||||
|                         crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                         children: [ | ||||
|                           Icon(Symbols.workspaces, | ||||
|                               size: 20, | ||||
|                               color: Theme.of(context) | ||||
|                                   .appBarTheme | ||||
|                                   .foregroundColor), | ||||
|                           const Gap(8), | ||||
|                           Flexible( | ||||
|                             child: Text( | ||||
|                               'postChannelRealm', | ||||
|                               maxLines: 1, | ||||
|                             ).tr().textColor( | ||||
|                                 Theme.of(context).appBarTheme.foregroundColor), | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ]; | ||||
|         }, | ||||
|         body: TabBarView( | ||||
|           controller: _tabController, | ||||
|           children: [ | ||||
|             _PostListWidget( | ||||
|               key: _listKeys[0], | ||||
|               onClearFilter: _clearFilter, | ||||
|             ), | ||||
|             _PostListWidget( | ||||
|               key: _listKeys[1], | ||||
|               channel: 'friends', | ||||
|               onClearFilter: _clearFilter, | ||||
|             ), | ||||
|             _PostListWidget( | ||||
|               key: _listKeys[2], | ||||
|               channel: 'following', | ||||
|               onClearFilter: _clearFilter, | ||||
|             ), | ||||
|             _PostListWidget( | ||||
|               key: _listKeys[3], | ||||
|               withRealm: true, | ||||
|               onClearFilter: _clearFilter, | ||||
|             ), | ||||
|           ], | ||||
|         body: _PostListWidget( | ||||
|           key: _listKey, | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
| @@ -369,15 +343,7 @@ class _ExploreScreenState extends State<ExploreScreen> | ||||
| } | ||||
|  | ||||
| class _PostListWidget extends StatefulWidget { | ||||
|   final String? channel; | ||||
|   final bool withRealm; | ||||
|   final Function onClearFilter; | ||||
|  | ||||
|   const _PostListWidget( | ||||
|       {super.key, | ||||
|       this.channel, | ||||
|       this.withRealm = false, | ||||
|       required this.onClearFilter}); | ||||
|   const _PostListWidget({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<_PostListWidget> createState() => _PostListWidgetState(); | ||||
| @@ -386,25 +352,13 @@ class _PostListWidget extends StatefulWidget { | ||||
| class _PostListWidgetState extends State<_PostListWidget> { | ||||
|   bool _isBusy = false; | ||||
|  | ||||
|   final List<SnPost> _posts = List.empty(growable: true); | ||||
|   final List<SnRealm> _realms = List.empty(growable: true); | ||||
|   SnRealm? _selectedRealm; | ||||
|   int? _postCount; | ||||
|   SnRealm? get realm => _selectedRealm; | ||||
|  | ||||
|   Future<void> _fetchRealms() async { | ||||
|     try { | ||||
|       final rels = context.read<SnRealmProvider>(); | ||||
|       final out = await rels.listAvailableRealms(); | ||||
|       setState(() { | ||||
|         _realms.addAll(out); | ||||
|         _selectedRealm = out.firstOrNull; | ||||
|       }); | ||||
|     } catch (err) { | ||||
|       if (!mounted) return; | ||||
|       context.showErrorDialog(err); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|   final List<SnPost> _posts = List.empty(growable: true); | ||||
|   SnRealm? _selectedRealm; | ||||
|   String? _selectedChannel; | ||||
|   SnPostCategory? _selectedCategory; | ||||
|   int? _postCount; | ||||
|  | ||||
|   Future<void> _fetchPosts() async { | ||||
|     if (_postCount != null && _posts.length >= _postCount!) return; | ||||
| @@ -416,7 +370,7 @@ class _PostListWidgetState extends State<_PostListWidget> { | ||||
|       take: 10, | ||||
|       offset: _posts.length, | ||||
|       categories: _selectedCategory != null ? [_selectedCategory!.alias] : null, | ||||
|       channel: widget.channel, | ||||
|       channel: _selectedChannel, | ||||
|       realm: _selectedRealm?.alias, | ||||
|     ); | ||||
|     final out = result.$1; | ||||
| @@ -429,6 +383,21 @@ class _PostListWidgetState extends State<_PostListWidget> { | ||||
|     if (mounted) setState(() => _isBusy = false); | ||||
|   } | ||||
|  | ||||
|   void setChannel(String? channel) { | ||||
|     _selectedChannel = channel; | ||||
|     setState(() {}); | ||||
|   } | ||||
|  | ||||
|   void setRealm(SnRealm? realm) { | ||||
|     _selectedRealm = realm; | ||||
|     setState(() {}); | ||||
|   } | ||||
|  | ||||
|   void setCategory(SnPostCategory? category) { | ||||
|     _selectedCategory = category; | ||||
|     setState(() {}); | ||||
|   } | ||||
|  | ||||
|   Future<void> refreshPosts() { | ||||
|     _postCount = null; | ||||
|     _posts.clear(); | ||||
| @@ -438,13 +407,7 @@ class _PostListWidgetState extends State<_PostListWidget> { | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     if (widget.withRealm) { | ||||
|       _fetchRealms().then((_) { | ||||
|         _fetchPosts(); | ||||
|       }); | ||||
|     } else { | ||||
|       _fetchPosts(); | ||||
|     } | ||||
|     _fetchPosts(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
| @@ -467,52 +430,13 @@ class _PostListWidgetState extends State<_PostListWidget> { | ||||
|               IconButton( | ||||
|                 icon: const Icon(Symbols.clear), | ||||
|                 onPressed: () { | ||||
|                   widget.onClearFilter.call(); | ||||
|                   setState(() => _selectedCategory = null); | ||||
|                   refreshPosts(); | ||||
|                 }, | ||||
|               ), | ||||
|             ], | ||||
|             padding: const EdgeInsets.only(left: 20, right: 4), | ||||
|           ), | ||||
|         if (widget.withRealm) | ||||
|           DropdownButtonHideUnderline( | ||||
|             child: DropdownButton2<SnRealm>( | ||||
|               isExpanded: true, | ||||
|               items: _realms | ||||
|                   .map( | ||||
|                     (ele) => DropdownMenuItem<SnRealm>( | ||||
|                       value: ele, | ||||
|                       child: Row( | ||||
|                         children: [ | ||||
|                           AccountImage( | ||||
|                             content: ele.avatar, | ||||
|                             fallbackWidget: const Icon(Symbols.group, size: 16), | ||||
|                             radius: 14, | ||||
|                           ), | ||||
|                           const Gap(8), | ||||
|                           Text( | ||||
|                             ele.name, | ||||
|                             style: Theme.of(context).textTheme.bodyMedium, | ||||
|                           ), | ||||
|                         ], | ||||
|                       ), | ||||
|                     ), | ||||
|                   ) | ||||
|                   .toList(), | ||||
|               value: _selectedRealm, | ||||
|               onChanged: (SnRealm? value) { | ||||
|                 setState(() => _selectedRealm = value); | ||||
|                 refreshPosts(); | ||||
|               }, | ||||
|               buttonStyleData: const ButtonStyleData( | ||||
|                 padding: EdgeInsets.only(left: 4, right: 12), | ||||
|               ), | ||||
|               menuItemStyleData: const MenuItemStyleData( | ||||
|                 height: 48, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|         if (widget.withRealm) const Divider(height: 1), | ||||
|         Expanded( | ||||
|           child: MediaQuery.removePadding( | ||||
|             context: context, | ||||
| @@ -521,6 +445,7 @@ class _PostListWidgetState extends State<_PostListWidget> { | ||||
|               displacement: 40 + MediaQuery.of(context).padding.top, | ||||
|               onRefresh: () => refreshPosts(), | ||||
|               child: InfiniteList( | ||||
|                 padding: EdgeInsets.only(top: 8), | ||||
|                 itemCount: _posts.length, | ||||
|                 isLoading: _isBusy, | ||||
|                 centerLoading: true, | ||||
| @@ -542,18 +467,21 @@ class _PostListWidgetState extends State<_PostListWidget> { | ||||
|                 separatorBuilder: (_, __) => const Gap(8), | ||||
|               ), | ||||
|             ), | ||||
|           ).padding(top: 8), | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _PostCategoryPickerPopup extends StatelessWidget { | ||||
|   final List<SnPostCategory> categories; | ||||
|   final SnPostCategory? selected; | ||||
| class _PostListRealmPopup extends StatelessWidget { | ||||
|   final List<SnRealm>? realms; | ||||
|   final Function(SnRealm?) onUpdate; | ||||
|  | ||||
|   const _PostCategoryPickerPopup({required this.categories, this.selected}); | ||||
|   const _PostListRealmPopup({ | ||||
|     required this.realms, | ||||
|     required this.onUpdate, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
| @@ -563,62 +491,38 @@ class _PostCategoryPickerPopup extends StatelessWidget { | ||||
|         Row( | ||||
|           crossAxisAlignment: CrossAxisAlignment.center, | ||||
|           children: [ | ||||
|             const Icon(Symbols.category, size: 24), | ||||
|             const Icon(Symbols.face, size: 24), | ||||
|             const Gap(16), | ||||
|             Text('postCategory') | ||||
|                 .tr() | ||||
|                 .textStyle(Theme.of(context).textTheme.titleLarge!), | ||||
|             Text('accountRealms', style: Theme.of(context).textTheme.titleLarge) | ||||
|                 .tr(), | ||||
|           ], | ||||
|         ).padding(horizontal: 20, top: 16, bottom: 12), | ||||
|         ListTile( | ||||
|           leading: const Icon(Symbols.clear), | ||||
|           title: Text('postFilterReset').tr(), | ||||
|           subtitle: Text('postFilterResetDescription').tr(), | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 20), | ||||
|           leading: const Icon(Symbols.close), | ||||
|           title: Text('postInGlobal').tr(), | ||||
|           subtitle: Text('postViewInGlobalDescription').tr(), | ||||
|           contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|           onTap: () { | ||||
|             Navigator.pop(context, false); | ||||
|             onUpdate.call(null); | ||||
|             Navigator.pop(context); | ||||
|           }, | ||||
|         ), | ||||
|         const Divider(height: 1), | ||||
|         Expanded( | ||||
|           child: GridView.count( | ||||
|             crossAxisCount: 4, | ||||
|             shrinkWrap: true, | ||||
|             physics: const NeverScrollableScrollPhysics(), | ||||
|             childAspectRatio: 1, | ||||
|             children: categories | ||||
|                 .map( | ||||
|                   (ele) => InkWell( | ||||
|                     onTap: () { | ||||
|                       _selectedCategory = ele; | ||||
|                       Navigator.pop(context, ele); | ||||
|                     }, | ||||
|                     child: Column( | ||||
|                       crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                       mainAxisAlignment: MainAxisAlignment.center, | ||||
|                       mainAxisSize: MainAxisSize.min, | ||||
|                       children: [ | ||||
|                         Icon( | ||||
|                           kCategoryIcons[ele.alias] ?? Symbols.question_mark, | ||||
|                           color: selected == ele | ||||
|                               ? Theme.of(context).colorScheme.primary | ||||
|                               : null, | ||||
|                         ), | ||||
|                         const Gap(4), | ||||
|                         Text( | ||||
|                           'postCategory${ele.alias.capitalize()}'.trExists() | ||||
|                               ? 'postCategory${ele.alias.capitalize()}'.tr() | ||||
|                               : ele.name, | ||||
|                         ) | ||||
|                             .textStyle(Theme.of(context).textTheme.titleMedium!) | ||||
|                             .textColor(selected == ele | ||||
|                                 ? Theme.of(context).colorScheme.primary | ||||
|                                 : null), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                 ) | ||||
|                 .toList(), | ||||
|           child: ListView.builder( | ||||
|             itemCount: realms?.length ?? 0, | ||||
|             itemBuilder: (context, idx) { | ||||
|               final realm = realms![idx]; | ||||
|               return ListTile( | ||||
|                 title: Text(realm.name), | ||||
|                 subtitle: Text('@${realm.alias}'), | ||||
|                 leading: AccountImage(content: realm.avatar, radius: 18), | ||||
|                 onTap: () { | ||||
|                   onUpdate.call(realm); | ||||
|                   Navigator.pop(context); | ||||
|                 }, | ||||
|               ); | ||||
|             }, | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|   | ||||
| @@ -18,6 +18,7 @@ import 'package:surface/controllers/post_write_controller.dart'; | ||||
| import 'package:surface/providers/config.dart'; | ||||
| import 'package:surface/providers/sn_attachment.dart'; | ||||
| import 'package:surface/providers/sn_network.dart'; | ||||
| import 'package:surface/providers/sn_realm.dart'; | ||||
| import 'package:surface/types/attachment.dart'; | ||||
| import 'package:surface/types/post.dart'; | ||||
| import 'package:surface/types/realm.dart'; | ||||
| @@ -36,7 +37,8 @@ import 'package:provider/provider.dart'; | ||||
| import 'package:surface/widgets/post/post_poll_editor.dart'; | ||||
| import 'package:uuid/uuid.dart'; | ||||
|  | ||||
| import '../../providers/sn_realm.dart'; | ||||
| const kPostTypes = ['Story', 'Article', 'Question', 'Video']; | ||||
| const kPostTypeAliases = ['stories', 'articles', 'questions', 'videos']; | ||||
|  | ||||
| class PostEditorExtra { | ||||
|   final String? text; | ||||
| @@ -53,7 +55,7 @@ class PostEditorExtra { | ||||
| } | ||||
|  | ||||
| class PostEditorScreen extends StatefulWidget { | ||||
|   final String mode; | ||||
|   final String? mode; | ||||
|   final int? postEditId; | ||||
|   final int? postReplyId; | ||||
|   final int? postRepostId; | ||||
| @@ -72,7 +74,10 @@ class PostEditorScreen extends StatefulWidget { | ||||
|   State<PostEditorScreen> createState() => _PostEditorScreenState(); | ||||
| } | ||||
|  | ||||
| class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
| class _PostEditorScreenState extends State<PostEditorScreen> | ||||
|     with SingleTickerProviderStateMixin { | ||||
|   late final TabController _tabController = | ||||
|       TabController(length: 4, vsync: this); | ||||
|   late final PostWriteController _writeController = PostWriteController( | ||||
|     doLoadFromTemporary: widget.postEditId == null, | ||||
|   ); | ||||
| @@ -209,6 +214,7 @@ class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
|  | ||||
|   @override | ||||
|   void dispose() { | ||||
|     _tabController.dispose(); | ||||
|     _writeController.dispose(); | ||||
|     if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS)) { | ||||
|       hotKeyManager.unregister(_pasteHotKey); | ||||
| @@ -220,14 +226,16 @@ class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     _registerHotKey(); | ||||
|     if (!PostWriteController.kTitleMap.keys.contains(widget.mode)) { | ||||
|       context.showErrorDialog('Unknown post type'); | ||||
|       Navigator.pop(context); | ||||
|     } else { | ||||
|       _writeController.setMode(widget.mode); | ||||
|     } | ||||
|     _fetchRealms(); | ||||
|     _fetchPublishers(); | ||||
|     if (widget.mode != null) { | ||||
|       _writeController.setMode(widget.mode!); | ||||
|     } | ||||
|     _tabController.addListener(() { | ||||
|       if (_tabController.indexIsChanging) { | ||||
|         _writeController.setMode(kPostTypeAliases[_tabController.index]); | ||||
|       } | ||||
|     }); | ||||
|     _writeController.fetchRelatedPost( | ||||
|       context, | ||||
|       editing: widget.postEditId, | ||||
| @@ -255,26 +263,10 @@ class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
|                 Navigator.pop(context); | ||||
|               }, | ||||
|             ), | ||||
|             title: RichText( | ||||
|               textAlign: TextAlign.center, | ||||
|               text: TextSpan(children: [ | ||||
|                 TextSpan( | ||||
|                   text: _writeController.title.isNotEmpty | ||||
|                       ? _writeController.title | ||||
|                       : 'untitled'.tr(), | ||||
|                   style: Theme.of(context).textTheme.titleLarge!.copyWith( | ||||
|                         color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                       ), | ||||
|                 ), | ||||
|                 const TextSpan(text: '\n'), | ||||
|                 TextSpan( | ||||
|                   text: PostWriteController.kTitleMap[widget.mode]!.tr(), | ||||
|                   style: Theme.of(context).textTheme.bodySmall!.copyWith( | ||||
|                         color: Theme.of(context).appBarTheme.foregroundColor!, | ||||
|                       ), | ||||
|                 ), | ||||
|               ]), | ||||
|               maxLines: 2, | ||||
|             title: Text( | ||||
|               _writeController.title.isNotEmpty | ||||
|                   ? _writeController.title | ||||
|                   : 'untitled'.tr(), | ||||
|             ), | ||||
|             actions: [ | ||||
|               IconButton( | ||||
| @@ -283,6 +275,24 @@ class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
|               ), | ||||
|               const Gap(8), | ||||
|             ], | ||||
|             bottom: _writeController.isNotEmpty || widget.mode != null | ||||
|                 ? null | ||||
|                 : TabBar( | ||||
|                     controller: _tabController, | ||||
|                     tabs: [ | ||||
|                       for (final type in kPostTypes) | ||||
|                         Tab( | ||||
|                           child: Text( | ||||
|                             'postType$type'.tr(), | ||||
|                             style: TextStyle( | ||||
|                               color: Theme.of(context) | ||||
|                                   .appBarTheme | ||||
|                                   .foregroundColor!, | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                     ], | ||||
|                   ), | ||||
|           ), | ||||
|           body: Column( | ||||
|             children: [ | ||||
| @@ -374,7 +384,7 @@ class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
|                   children: [ | ||||
|                     SingleChildScrollView( | ||||
|                       padding: EdgeInsets.only(bottom: 160), | ||||
|                       child: StyledWidget(switch (_writeController.mode) { | ||||
|                       child: switch (_writeController.mode) { | ||||
|                         'stories' => _PostStoryEditor( | ||||
|                             controller: _writeController, | ||||
|                             onTapPublisher: _showPublisherPopup, | ||||
| @@ -396,8 +406,7 @@ class _PostEditorScreenState extends State<PostEditorScreen> { | ||||
|                             onTapRealm: _showRealmPopup, | ||||
|                           ), | ||||
|                         _ => const Placeholder(), | ||||
|                       }) | ||||
|                           .padding(top: 8), | ||||
|                       }, | ||||
|                     ), | ||||
|                     if (_writeController.attachments.isNotEmpty || | ||||
|                         _writeController.thumbnail != null) | ||||
| @@ -720,7 +729,7 @@ class _PostStoryEditor extends StatelessWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Container( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 12), | ||||
|       padding: const EdgeInsets.only(left: 12, right: 12, top: 8), | ||||
|       constraints: const BoxConstraints(maxWidth: 640), | ||||
|       child: Row( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
| @@ -969,7 +978,7 @@ class _PostQuestionEditor extends StatelessWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Container( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 12), | ||||
|       padding: const EdgeInsets.only(left: 12, right: 12, top: 8), | ||||
|       constraints: const BoxConstraints(maxWidth: 640), | ||||
|       child: Row( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
| @@ -1053,7 +1062,7 @@ class _PostQuestionEditor extends StatelessWidget { | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ).padding(top: 8), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -1154,7 +1163,7 @@ class _PostVideoEditor extends StatelessWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Container( | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 12), | ||||
|       padding: const EdgeInsets.only(left: 12, right: 12, top: 8), | ||||
|       constraints: const BoxConstraints(maxWidth: 640), | ||||
|       child: Row( | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|   | ||||
| @@ -61,7 +61,7 @@ class _AppSharingListenerState extends State<AppSharingListener> { | ||||
|                       onTap: () { | ||||
|                         GoRouter.of(context).pushNamed( | ||||
|                           'postEditor', | ||||
|                           pathParameters: { | ||||
|                           queryParameters: { | ||||
|                             'mode': 'stories', | ||||
|                           }, | ||||
|                           extra: PostEditorExtra( | ||||
|   | ||||
| @@ -50,16 +50,17 @@ Future<ThemeData> createAppTheme( | ||||
|       useMaterial3 ?? (prefs.getBool(kMaterialYouToggleStoreKey) ?? true); | ||||
|  | ||||
|   final inUseFonts = (customFonts ?? prefs.getString(kAppCustomFonts)) | ||||
|       ?.split(',') | ||||
|       .map((ele) => ele.trim()) | ||||
|       .toList(); | ||||
|           ?.split(',') | ||||
|           .map((ele) => ele.trim()) | ||||
|           .toList() ?? | ||||
|       ['Nunito']; | ||||
|  | ||||
|   return ThemeData( | ||||
|     useMaterial3: useM3, | ||||
|     colorScheme: colorScheme, | ||||
|     brightness: brightness, | ||||
|     fontFamily: inUseFonts?.firstOrNull, | ||||
|     fontFamilyFallback: inUseFonts?.sublist(1), | ||||
|     fontFamily: inUseFonts.firstOrNull, | ||||
|     fontFamilyFallback: inUseFonts.sublist(1), | ||||
|     iconTheme: IconThemeData( | ||||
|       fill: 0, | ||||
|       weight: 400, | ||||
|   | ||||
| @@ -22,12 +22,14 @@ class AttachmentItem extends StatelessWidget { | ||||
|   final SnAttachment? data; | ||||
|   final String? heroTag; | ||||
|   final BoxFit fit; | ||||
|   final FilterQuality? filterQuality; | ||||
|  | ||||
|   const AttachmentItem({ | ||||
|     super.key, | ||||
|     this.fit = BoxFit.cover, | ||||
|     required this.data, | ||||
|     required this.heroTag, | ||||
|     this.filterQuality, | ||||
|   }); | ||||
|  | ||||
|   Widget _buildContent(BuildContext context) { | ||||
| @@ -47,6 +49,7 @@ class AttachmentItem extends StatelessWidget { | ||||
|             sn.getAttachmentUrl(data!.rid), | ||||
|             key: Key('attachment-${data!.rid}-$tag'), | ||||
|             fit: fit, | ||||
|             filterQuality: filterQuality, | ||||
|           ), | ||||
|         ); | ||||
|       case 'video': | ||||
| @@ -83,13 +86,16 @@ class _AttachmentItemSensitiveBlur extends StatefulWidget { | ||||
|   final Widget child; | ||||
|   final bool isCompact; | ||||
|  | ||||
|   const _AttachmentItemSensitiveBlur({required this.child, this.isCompact = false}); | ||||
|   const _AttachmentItemSensitiveBlur( | ||||
|       {required this.child, this.isCompact = false}); | ||||
|  | ||||
|   @override | ||||
|   State<_AttachmentItemSensitiveBlur> createState() => _AttachmentItemSensitiveBlurState(); | ||||
|   State<_AttachmentItemSensitiveBlur> createState() => | ||||
|       _AttachmentItemSensitiveBlurState(); | ||||
| } | ||||
|  | ||||
| class _AttachmentItemSensitiveBlurState extends State<_AttachmentItemSensitiveBlur> { | ||||
| class _AttachmentItemSensitiveBlurState | ||||
|     extends State<_AttachmentItemSensitiveBlur> { | ||||
|   bool _doesShow = false; | ||||
|  | ||||
|   @override | ||||
| @@ -124,10 +130,15 @@ class _AttachmentItemSensitiveBlurState extends State<_AttachmentItemSensitiveBl | ||||
|                       Text( | ||||
|                         'sensitiveContentDescription', | ||||
|                         textAlign: TextAlign.center, | ||||
|                       ).tr().fontSize(14).textColor(Colors.white.withOpacity(0.8)), | ||||
|                       ) | ||||
|                           .tr() | ||||
|                           .fontSize(14) | ||||
|                           .textColor(Colors.white.withOpacity(0.8)), | ||||
|                     if (!widget.isCompact) const Gap(16), | ||||
|                     InkWell( | ||||
|                       child: Text('sensitiveContentReveal').tr().textColor(Colors.white), | ||||
|                       child: Text('sensitiveContentReveal') | ||||
|                           .tr() | ||||
|                           .textColor(Colors.white), | ||||
|                       onTap: () { | ||||
|                         setState(() => _doesShow = !_doesShow); | ||||
|                       }, | ||||
| @@ -137,7 +148,9 @@ class _AttachmentItemSensitiveBlurState extends State<_AttachmentItemSensitiveBl | ||||
|               ).center(), | ||||
|             ), | ||||
|           ), | ||||
|         ).opacity(_doesShow ? 0 : 1, animate: true).animate(const Duration(milliseconds: 300), Curves.easeInOut), | ||||
|         ) | ||||
|             .opacity(_doesShow ? 0 : 1, animate: true) | ||||
|             .animate(const Duration(milliseconds: 300), Curves.easeInOut), | ||||
|         if (_doesShow) | ||||
|           Positioned( | ||||
|             top: 0, | ||||
| @@ -174,10 +187,12 @@ class _AttachmentItemContentVideo extends StatefulWidget { | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   State<_AttachmentItemContentVideo> createState() => _AttachmentItemContentVideoState(); | ||||
|   State<_AttachmentItemContentVideo> createState() => | ||||
|       _AttachmentItemContentVideoState(); | ||||
| } | ||||
|  | ||||
| class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo> { | ||||
| class _AttachmentItemContentVideoState | ||||
|     extends State<_AttachmentItemContentVideo> { | ||||
|   bool _showContent = false; | ||||
|   bool _showOriginal = false; | ||||
|  | ||||
| @@ -188,7 +203,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo | ||||
|     setState(() => _showContent = true); | ||||
|     MediaKit.ensureInitialized(); | ||||
|     final sn = context.read<SnNetworkProvider>(); | ||||
|     final url = _showOriginal ? sn.getAttachmentUrl(widget.data.rid) : sn.getAttachmentUrl(widget.data.compressed!.rid); | ||||
|     final url = _showOriginal | ||||
|         ? sn.getAttachmentUrl(widget.data.rid) | ||||
|         : sn.getAttachmentUrl(widget.data.compressed!.rid); | ||||
|     _videoPlayer = Player(); | ||||
|     _videoController = VideoController(_videoPlayer!); | ||||
|     _videoPlayer!.open(Media(url), play: !widget.isAutoload); | ||||
| @@ -201,7 +218,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo | ||||
|     final sn = context.read<SnNetworkProvider>(); | ||||
|     _videoPlayer?.open( | ||||
|       Media( | ||||
|         _showOriginal ? sn.getAttachmentUrl(widget.data.rid) : sn.getAttachmentUrl(widget.data.compressed!.rid), | ||||
|         _showOriginal | ||||
|             ? sn.getAttachmentUrl(widget.data.rid) | ||||
|             : sn.getAttachmentUrl(widget.data.compressed!.rid), | ||||
|       ), | ||||
|       play: true, | ||||
|     ); | ||||
| @@ -283,7 +302,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo | ||||
|                           ), | ||||
|                           Text( | ||||
|                             Duration( | ||||
|                               milliseconds: (widget.data.data['duration'] ?? 0).toInt() * 1000, | ||||
|                               milliseconds: | ||||
|                                   (widget.data.data['duration'] ?? 0).toInt() * | ||||
|                                       1000, | ||||
|                             ).toString(), | ||||
|                             style: GoogleFonts.robotoMono( | ||||
|                               fontSize: 12, | ||||
| @@ -346,7 +367,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo | ||||
|             MaterialDesktopCustomButton( | ||||
|               iconSize: 24, | ||||
|               onPressed: _toggleOriginal, | ||||
|               icon: _showOriginal ? const Icon(Symbols.high_quality, size: 24) : const Icon(Symbols.sd, size: 24), | ||||
|               icon: _showOriginal | ||||
|                   ? const Icon(Symbols.high_quality, size: 24) | ||||
|                   : const Icon(Symbols.sd, size: 24), | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
| @@ -354,8 +377,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo | ||||
|         child: Video( | ||||
|           controller: _videoController!, | ||||
|           aspectRatio: ratio, | ||||
|           controls: | ||||
|               !kIsWeb && (Platform.isAndroid || Platform.isIOS) ? MaterialVideoControls : MaterialDesktopVideoControls, | ||||
|           controls: !kIsWeb && (Platform.isAndroid || Platform.isIOS) | ||||
|               ? MaterialVideoControls | ||||
|               : MaterialDesktopVideoControls, | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
| @@ -378,10 +402,12 @@ class _AttachmentItemContentAudio extends StatefulWidget { | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   State<_AttachmentItemContentAudio> createState() => _AttachmentItemContentAudioState(); | ||||
|   State<_AttachmentItemContentAudio> createState() => | ||||
|       _AttachmentItemContentAudioState(); | ||||
| } | ||||
|  | ||||
| class _AttachmentItemContentAudioState extends State<_AttachmentItemContentAudio> { | ||||
| class _AttachmentItemContentAudioState | ||||
|     extends State<_AttachmentItemContentAudio> { | ||||
|   bool _showContent = false; | ||||
|  | ||||
|   double? _draggingValue; | ||||
| @@ -552,8 +578,12 @@ class _AttachmentItemContentAudioState extends State<_AttachmentItemContentAudio | ||||
|                             overlayShape: SliderComponentShape.noOverlay, | ||||
|                           ), | ||||
|                           child: Slider( | ||||
|                             secondaryTrackValue: _bufferedPosition.inMilliseconds.abs().toDouble(), | ||||
|                             value: _draggingValue?.abs() ?? _position.inMilliseconds.toDouble().abs(), | ||||
|                             secondaryTrackValue: _bufferedPosition | ||||
|                                 .inMilliseconds | ||||
|                                 .abs() | ||||
|                                 .toDouble(), | ||||
|                             value: _draggingValue?.abs() ?? | ||||
|                                 _position.inMilliseconds.toDouble().abs(), | ||||
|                             min: 0, | ||||
|                             max: math | ||||
|                                 .max( | ||||
| @@ -593,7 +623,9 @@ class _AttachmentItemContentAudioState extends State<_AttachmentItemContentAudio | ||||
|                   ), | ||||
|                   const Gap(16), | ||||
|                   IconButton.filled( | ||||
|                     icon: _isPlaying ? const Icon(Symbols.pause) : const Icon(Symbols.play_arrow), | ||||
|                     icon: _isPlaying | ||||
|                         ? const Icon(Symbols.pause) | ||||
|                         : const Icon(Symbols.play_arrow), | ||||
|                     onPressed: () { | ||||
|                       _audioPlayer!.playOrPause(); | ||||
|                     }, | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class AttachmentList extends StatefulWidget { | ||||
|   final double? minWidth; | ||||
|   final double? maxWidth; | ||||
|   final EdgeInsets? padding; | ||||
|   final FilterQuality? filterQuality; | ||||
|  | ||||
|   const AttachmentList({ | ||||
|     super.key, | ||||
| @@ -33,23 +34,27 @@ class AttachmentList extends StatefulWidget { | ||||
|     this.minWidth, | ||||
|     this.maxWidth, | ||||
|     this.padding, | ||||
|     this.filterQuality, | ||||
|   }); | ||||
|  | ||||
|   static const BorderRadius kDefaultRadius = BorderRadius.all(Radius.circular(8)); | ||||
|   static const BorderRadius kDefaultRadius = | ||||
|       BorderRadius.all(Radius.circular(8)); | ||||
|  | ||||
|   @override | ||||
|   State<AttachmentList> createState() => _AttachmentListState(); | ||||
| } | ||||
|  | ||||
| class _AttachmentListState extends State<AttachmentList> { | ||||
|   late final List<String> heroTags = List.generate(widget.data.length, (_) => const Uuid().v4()); | ||||
|   late final List<String> heroTags = | ||||
|       List.generate(widget.data.length, (_) => const Uuid().v4()); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return LayoutBuilder( | ||||
|       builder: (context, layoutConstraints) { | ||||
|         final borderSide = | ||||
|             widget.bordered ? BorderSide(width: 1, color: Theme.of(context).dividerColor) : BorderSide.none; | ||||
|         final borderSide = widget.bordered | ||||
|             ? BorderSide(width: 1, color: Theme.of(context).dividerColor) | ||||
|             : BorderSide.none; | ||||
|         final backgroundColor = Theme.of(context).colorScheme.surfaceContainer; | ||||
|         final constraints = BoxConstraints( | ||||
|           minWidth: widget.minWidth ?? 80, | ||||
| @@ -58,13 +63,13 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|  | ||||
|         if (widget.data.isEmpty) return const SizedBox.shrink(); | ||||
|         if (widget.data.length == 1) { | ||||
|           final singleAspectRatio = | ||||
|               widget.data[0]?.data['ratio']?.toDouble() ?? | ||||
|           final singleAspectRatio = widget.data[0]?.data['ratio']?.toDouble() ?? | ||||
|               switch (widget.data[0]?.mimetype.split('/').firstOrNull) { | ||||
|                 'audio' => 16 / 9, | ||||
|                 'video' => 16 / 9, | ||||
|                 _ => 1, | ||||
|               }.toDouble(); | ||||
|               } | ||||
|                   .toDouble(); | ||||
|  | ||||
|           return Container( | ||||
|             padding: widget.padding ?? EdgeInsets.zero, | ||||
| @@ -80,12 +85,18 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|                   ), | ||||
|                   child: ClipRRect( | ||||
|                     borderRadius: AttachmentList.kDefaultRadius, | ||||
|                     child: AttachmentItem(data: widget.data[0], heroTag: heroTags[0], fit: widget.fit), | ||||
|                     child: AttachmentItem( | ||||
|                       data: widget.data[0], | ||||
|                       heroTag: heroTags[0], | ||||
|                       fit: widget.fit, | ||||
|                       filterQuality: widget.filterQuality, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|               onTap: () { | ||||
|                 if (widget.data.firstOrNull?.mediaType != SnMediaType.image) return; | ||||
|                 if (widget.data.firstOrNull?.mediaType != SnMediaType.image) | ||||
|                   return; | ||||
|                 context.pushTransparentRoute( | ||||
|                   AttachmentZoomView( | ||||
|                     data: widget.data.where((ele) => ele != null).cast(), | ||||
| @@ -100,8 +111,10 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|         final fullOfImage = | ||||
|             widget.data.where((ele) => ele?.mediaType == SnMediaType.image).length == widget.data.length; | ||||
|         final fullOfImage = widget.data | ||||
|                 .where((ele) => ele?.mediaType == SnMediaType.image) | ||||
|                 .length == | ||||
|             widget.data.length; | ||||
|  | ||||
|         if (widget.gridded && fullOfImage) { | ||||
|           return Container( | ||||
| @@ -117,29 +130,38 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|                 crossAxisCount: math.min(widget.data.length, 2), | ||||
|                 crossAxisSpacing: 4, | ||||
|                 mainAxisSpacing: 4, | ||||
|                 children: | ||||
|                     widget.data | ||||
|                         .mapIndexed( | ||||
|                           (idx, ele) => GestureDetector( | ||||
|                             child: Container( | ||||
|                               constraints: constraints, | ||||
|                               child: AttachmentItem(data: ele, heroTag: heroTags[idx], fit: BoxFit.cover), | ||||
|                             ), | ||||
|                             onTap: () { | ||||
|                               if (widget.data[idx]!.mediaType != SnMediaType.image) return; | ||||
|                               context.pushTransparentRoute( | ||||
|                                 AttachmentZoomView( | ||||
|                                   data: widget.data.where((ele) => ele != null).cast(), | ||||
|                                   initialIndex: idx, | ||||
|                                   heroTags: heroTags, | ||||
|                                 ), | ||||
|                                 backgroundColor: Colors.black.withOpacity(0.7), | ||||
|                                 rootNavigator: true, | ||||
|                               ); | ||||
|                             }, | ||||
|                 children: widget.data | ||||
|                     .mapIndexed( | ||||
|                       (idx, ele) => GestureDetector( | ||||
|                         child: Container( | ||||
|                           constraints: constraints, | ||||
|                           child: AttachmentItem( | ||||
|                             data: ele, | ||||
|                             heroTag: heroTags[idx], | ||||
|                             fit: BoxFit.cover, | ||||
|                             filterQuality: widget.filterQuality, | ||||
|                           ), | ||||
|                         ) | ||||
|                         .toList(), | ||||
|                         ), | ||||
|                         onTap: () { | ||||
|                           if (widget.data[idx]!.mediaType != | ||||
|                               SnMediaType.image) { | ||||
|                             return; | ||||
|                           } | ||||
|                           context.pushTransparentRoute( | ||||
|                             AttachmentZoomView( | ||||
|                               data: widget.data | ||||
|                                   .where((ele) => ele != null) | ||||
|                                   .cast(), | ||||
|                               initialIndex: idx, | ||||
|                               heroTags: heroTags, | ||||
|                             ), | ||||
|                             backgroundColor: Colors.black.withOpacity(0.7), | ||||
|                             rootNavigator: true, | ||||
|                           ); | ||||
|                         }, | ||||
|                       ), | ||||
|                     ) | ||||
|                     .toList(), | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
| @@ -156,22 +178,26 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|             child: ClipRRect( | ||||
|               borderRadius: AttachmentList.kDefaultRadius, | ||||
|               child: Column( | ||||
|                 children: | ||||
|                     widget.data | ||||
|                         .mapIndexed( | ||||
|                           (idx, ele) => GestureDetector( | ||||
|                             child: AspectRatio( | ||||
|                               aspectRatio: ele?.data['ratio']?.toDouble() ?? 1, | ||||
|                               child: Container( | ||||
|                                 constraints: constraints, | ||||
|                                 child: AttachmentItem(data: ele, heroTag: heroTags[idx], fit: BoxFit.cover), | ||||
|                               ), | ||||
|                 children: widget.data | ||||
|                     .mapIndexed( | ||||
|                       (idx, ele) => GestureDetector( | ||||
|                         child: AspectRatio( | ||||
|                           aspectRatio: ele?.data['ratio']?.toDouble() ?? 1, | ||||
|                           child: Container( | ||||
|                             constraints: constraints, | ||||
|                             child: AttachmentItem( | ||||
|                               data: ele, | ||||
|                               heroTag: heroTags[idx], | ||||
|                               fit: BoxFit.cover, | ||||
|                               filterQuality: widget.filterQuality, | ||||
|                             ), | ||||
|                           ), | ||||
|                         ) | ||||
|                         .expand((ele) => [ele, const Divider(height: 1)]) | ||||
|                         .toList() | ||||
|                       ..removeLast(), | ||||
|                         ), | ||||
|                       ), | ||||
|                     ) | ||||
|                     .expand((ele) => [ele, const Divider(height: 1)]) | ||||
|                     .toList() | ||||
|                   ..removeLast(), | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
| @@ -179,6 +205,7 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|  | ||||
|         return Container( | ||||
|           constraints: BoxConstraints(maxHeight: constraints.maxHeight), | ||||
|           width: double.infinity, | ||||
|           child: AspectRatio( | ||||
|             aspectRatio: widget.data[0]?.data['ratio']?.toDouble() ?? 1, | ||||
|             child: ScrollConfiguration( | ||||
| @@ -189,16 +216,22 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|                 itemCount: widget.data.length, | ||||
|                 itemBuilder: (context, idx) { | ||||
|                   return Container( | ||||
|                     constraints: constraints.copyWith(maxWidth: widget.maxWidth), | ||||
|                     constraints: | ||||
|                         constraints.copyWith(maxWidth: widget.maxWidth), | ||||
|                     child: AspectRatio( | ||||
|                       aspectRatio: (widget.data[idx]?.data['ratio'] ?? 1).toDouble(), | ||||
|                       aspectRatio: | ||||
|                           (widget.data[idx]?.data['ratio'] ?? 1).toDouble(), | ||||
|                       child: GestureDetector( | ||||
|                         onTap: () { | ||||
|                           if (widget.data[idx]?.mediaType != SnMediaType.image) return; | ||||
|                           if (widget.data[idx]?.mediaType != SnMediaType.image) | ||||
|                             return; | ||||
|                           context.pushTransparentRoute( | ||||
|                             AttachmentZoomView( | ||||
|                               data: | ||||
|                                   widget.data.where((ele) => ele != null && ele.mediaType == SnMediaType.image).cast(), | ||||
|                               data: widget.data | ||||
|                                   .where((ele) => | ||||
|                                       ele != null && | ||||
|                                       ele.mediaType == SnMediaType.image) | ||||
|                                   .cast(), | ||||
|                               initialIndex: idx, | ||||
|                               heroTags: heroTags, | ||||
|                             ), | ||||
| @@ -212,18 +245,25 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|                             Container( | ||||
|                               decoration: BoxDecoration( | ||||
|                                 color: backgroundColor, | ||||
|                                 border: Border(top: borderSide, bottom: borderSide), | ||||
|                                 border: | ||||
|                                     Border(top: borderSide, bottom: borderSide), | ||||
|                                 borderRadius: AttachmentList.kDefaultRadius, | ||||
|                               ), | ||||
|                               child: ClipRRect( | ||||
|                                 borderRadius: AttachmentList.kDefaultRadius, | ||||
|                                 child: AttachmentItem(data: widget.data[idx], heroTag: heroTags[idx]), | ||||
|                                 child: AttachmentItem( | ||||
|                                   data: widget.data[idx], | ||||
|                                   heroTag: heroTags[idx], | ||||
|                                   filterQuality: widget.filterQuality, | ||||
|                                 ), | ||||
|                               ), | ||||
|                             ), | ||||
|                             Positioned( | ||||
|                               right: 8, | ||||
|                               bottom: 8, | ||||
|                               child: Chip(label: Text('${idx + 1}/${widget.data.length}')), | ||||
|                               child: Chip( | ||||
|                                   label: | ||||
|                                       Text('${idx + 1}/${widget.data.length}')), | ||||
|                             ), | ||||
|                           ], | ||||
|                         ), | ||||
| @@ -245,5 +285,6 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|  | ||||
| class _AttachmentListScrollBehavior extends MaterialScrollBehavior { | ||||
|   @override | ||||
|   Set<PointerDeviceKind> get dragDevices => {PointerDeviceKind.touch, PointerDeviceKind.mouse}; | ||||
|   Set<PointerDeviceKind> get dragDevices => | ||||
|       {PointerDeviceKind.touch, PointerDeviceKind.mouse}; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import 'dart:io'; | ||||
| import 'dart:math' show max; | ||||
|  | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:dismissible_page/dismissible_page.dart'; | ||||
| @@ -48,11 +47,14 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> { | ||||
|   bool _showOverlay = true; | ||||
|   bool _dismissable = true; | ||||
|  | ||||
|   int _page = 0; | ||||
|  | ||||
|   void _updatePage() { | ||||
|     setState(() { | ||||
|       if (_isCompletedDownload) { | ||||
|         setState(() => _isCompletedDownload = false); | ||||
|       } | ||||
|       _page = _pageController.page?.round() ?? 0; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
| @@ -155,7 +157,7 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> { | ||||
|         Navigator.of(context).pop(); | ||||
|       }, | ||||
|       direction: _dismissable | ||||
|           ? DismissiblePageDismissDirection.multi | ||||
|           ? DismissiblePageDismissDirection.down | ||||
|           : DismissiblePageDismissDirection.none, | ||||
|       backgroundColor: Colors.transparent, | ||||
|       isFullScreen: true, | ||||
| @@ -222,31 +224,11 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> { | ||||
|                       BoxDecoration(color: Colors.transparent), | ||||
|                 ); | ||||
|               }), | ||||
|               Positioned( | ||||
|                 top: max(MediaQuery.of(context).padding.top, 8), | ||||
|                 left: 14, | ||||
|                 child: IgnorePointer( | ||||
|                   ignoring: !_showOverlay, | ||||
|                   child: IconButton( | ||||
|                     constraints: const BoxConstraints(), | ||||
|                     icon: const Icon(Icons.close), | ||||
|                     style: ButtonStyle( | ||||
|                       backgroundColor: MaterialStateProperty.all( | ||||
|                         Theme.of(context).colorScheme.surface.withOpacity(0.5), | ||||
|                       ), | ||||
|                     ), | ||||
|                     onPressed: () { | ||||
|                       Navigator.of(context).pop(); | ||||
|                     }, | ||||
|                   ).opacity(_showOverlay ? 1 : 0, animate: true).animate( | ||||
|                       const Duration(milliseconds: 300), Curves.easeInOut), | ||||
|                 ), | ||||
|               ), | ||||
|               Align( | ||||
|                 alignment: Alignment.bottomCenter, | ||||
|                 child: IgnorePointer( | ||||
|                   child: Container( | ||||
|                     height: 300, | ||||
|                     height: 200, | ||||
|                     decoration: BoxDecoration( | ||||
|                       gradient: LinearGradient( | ||||
|                         begin: Alignment.bottomCenter, | ||||
| @@ -269,153 +251,130 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> { | ||||
|                 child: Material( | ||||
|                   color: Colors.transparent, | ||||
|                   child: Builder(builder: (context) { | ||||
|                     final ud = context.read<UserDirectoryProvider>(); | ||||
|                     final item = widget.data.elementAt( | ||||
|                       widget.data.length > 1 | ||||
|                           ? _pageController.page?.round() ?? 0 | ||||
|                           : 0, | ||||
|                     ); | ||||
|                     final account = ud.getFromCache(item.accountId); | ||||
|  | ||||
|                     return Column( | ||||
|                       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     return Row( | ||||
|                       children: [ | ||||
|                         if (item.accountId > 0) | ||||
|                           Row( | ||||
|                             children: [ | ||||
|                               IgnorePointer( | ||||
|                                 child: AccountImage( | ||||
|                                   content: account?.avatar, | ||||
|                                   radius: 19, | ||||
|                                 ), | ||||
|                               ), | ||||
|                               const Gap(8), | ||||
|                               Expanded( | ||||
|                                 child: IgnorePointer( | ||||
|                                   child: Column( | ||||
|                                     crossAxisAlignment: | ||||
|                                         CrossAxisAlignment.start, | ||||
|                                     children: [ | ||||
|                                       Text( | ||||
|                                         'attachmentUploadBy'.tr(), | ||||
|                                         style: Theme.of(context) | ||||
|                                             .textTheme | ||||
|                                             .bodySmall, | ||||
|                                       ), | ||||
|                                       Text( | ||||
|                                         account?.nick ?? 'unknown'.tr(), | ||||
|                                         style: Theme.of(context) | ||||
|                                             .textTheme | ||||
|                                             .bodyMedium, | ||||
|                                       ), | ||||
|                                     ], | ||||
|                                   ), | ||||
|                                 ), | ||||
|                               ), | ||||
|                               if (widget.data.length > 1) | ||||
|                                 IgnorePointer( | ||||
|                                   child: Text( | ||||
|                                     '${(_pageController.page?.round() ?? 0) + 1}/${widget.data.length}', | ||||
|                                     style: GoogleFonts.robotoMono(fontSize: 13), | ||||
|                                   ).padding(right: 8), | ||||
|                                 ), | ||||
|                               InkWell( | ||||
|                                 borderRadius: | ||||
|                                     const BorderRadius.all(Radius.circular(16)), | ||||
|                                 onTap: _isDownloading | ||||
|                                     ? null | ||||
|                                     : () => _saveToAlbum(widget.data.length > 1 | ||||
|                                         ? _pageController.page?.round() ?? 0 | ||||
|                                         : 0), | ||||
|                                 child: Container( | ||||
|                                   padding: const EdgeInsets.all(6), | ||||
|                                   child: !_isDownloading | ||||
|                                       ? !_isCompletedDownload | ||||
|                                           ? const Icon(Symbols.save_alt) | ||||
|                                           : const Icon(Symbols.download_done) | ||||
|                                       : SizedBox( | ||||
|                                           width: 24, | ||||
|                                           height: 24, | ||||
|                                           child: CircularProgressIndicator( | ||||
|                                             value: _progressOfDownload, | ||||
|                                             strokeWidth: 3, | ||||
|                                           ), | ||||
|                                         ), | ||||
|                                 ), | ||||
|                               ), | ||||
|                             ], | ||||
|                           ), | ||||
|                         const Gap(4), | ||||
|                         IgnorePointer( | ||||
|                           child: Text( | ||||
|                             item.alt, | ||||
|                             maxLines: 2, | ||||
|                             overflow: TextOverflow.ellipsis, | ||||
|                             style: const TextStyle( | ||||
|                               fontSize: 15, | ||||
|                               fontWeight: FontWeight.w500, | ||||
|                         IconButton( | ||||
|                           iconSize: 18, | ||||
|                           constraints: const BoxConstraints(), | ||||
|                           icon: const Icon(Icons.close), | ||||
|                           style: ButtonStyle( | ||||
|                             backgroundColor: MaterialStateProperty.all( | ||||
|                               Theme.of(context) | ||||
|                                   .colorScheme | ||||
|                                   .surface | ||||
|                                   .withOpacity(0.5), | ||||
|                             ), | ||||
|                           ), | ||||
|                           onPressed: () { | ||||
|                             Navigator.of(context).pop(); | ||||
|                           }, | ||||
|                         ), | ||||
|                         const Gap(2), | ||||
|                         IgnorePointer( | ||||
|                           child: Wrap( | ||||
|                             spacing: 6, | ||||
|                             children: [ | ||||
|                               if (item.metadata['exif'] == null) | ||||
|                                 Text( | ||||
|                                   '#${item.rid}', | ||||
|                                   style: metaTextStyle, | ||||
|                                 ), | ||||
|                               if (item.metadata['exif']?['Model'] != null) | ||||
|                                 Text( | ||||
|                                   'attachmentShotOn'.tr(args: [ | ||||
|                                     item.metadata['exif']?['Model'], | ||||
|                                   ]), | ||||
|                                   style: metaTextStyle, | ||||
|                                 ).padding(right: 2), | ||||
|                               if (item.metadata['exif']?['Megapixels'] != | ||||
|                                       null && | ||||
|                                   item.metadata['exif']?['Model'] != null) | ||||
|                                 Text( | ||||
|                                   '${item.metadata['exif']?['Megapixels']}MP', | ||||
|                                   style: metaTextStyle, | ||||
|                                 ) | ||||
|                               else | ||||
|                                 Text( | ||||
|                                   item.size.formatBytes(), | ||||
|                                   style: metaTextStyle, | ||||
|                                 ), | ||||
|                               if (item.metadata['width'] != null && | ||||
|                                   item.metadata['height'] != null) | ||||
|                                 Text( | ||||
|                                   '${item.metadata['width']}x${item.metadata['height']}', | ||||
|                                   style: metaTextStyle, | ||||
|                                 ), | ||||
|                             ], | ||||
|                         IconButton( | ||||
|                             iconSize: 20, | ||||
|                             constraints: const BoxConstraints(), | ||||
|                             padding: EdgeInsets.zero, | ||||
|                             visualDensity: VisualDensity.compact, | ||||
|                             icon: const Icon(Symbols.hide).padding(all: 6), | ||||
|                             onPressed: () { | ||||
|                               setState(() => _showOverlay = false); | ||||
|                             }), | ||||
|                         Expanded( | ||||
|                           child: IgnorePointer( | ||||
|                             child: Builder(builder: (context) { | ||||
|                               final item = widget.data.elementAt(_page); | ||||
|                               final doShowCameraInfo = | ||||
|                                   item.metadata['exif']?['Model'] != null; | ||||
|                               final exif = item.metadata['exif']; | ||||
|                               return Column( | ||||
|                                 children: [ | ||||
|                                   if (widget.data.length > 1) | ||||
|                                     Text( | ||||
|                                       '${_page + 1}/${widget.data.length}', | ||||
|                                       style: | ||||
|                                           GoogleFonts.robotoMono(fontSize: 13), | ||||
|                                     ).padding(right: 8), | ||||
|                                   if (doShowCameraInfo) | ||||
|                                     Text( | ||||
|                                       'attachmentShotOn' | ||||
|                                           .tr(args: [exif?['Model']]), | ||||
|                                       style: metaTextStyle, | ||||
|                                       textAlign: TextAlign.center, | ||||
|                                     ), | ||||
|                                   if (doShowCameraInfo) | ||||
|                                     Row( | ||||
|                                       spacing: 4, | ||||
|                                       mainAxisSize: MainAxisSize.min, | ||||
|                                       children: [ | ||||
|                                         if (exif?['Megapixels'] != null) | ||||
|                                           Text( | ||||
|                                             '${exif?['Megapixels']}MP', | ||||
|                                             style: metaTextStyle, | ||||
|                                           ), | ||||
|                                         if (exif?['ISO'] != null) | ||||
|                                           Text( | ||||
|                                             'ISO${exif['ISO']}', | ||||
|                                             style: metaTextStyle, | ||||
|                                           ), | ||||
|                                         if (exif?['FNumber'] != null) | ||||
|                                           Text( | ||||
|                                             'f/${exif['FNumber']}', | ||||
|                                             style: metaTextStyle, | ||||
|                                           ), | ||||
|                                       ], | ||||
|                                     ) | ||||
|                                 ], | ||||
|                               ); | ||||
|                             }), | ||||
|                           ), | ||||
|                         ), | ||||
|                         const Gap(4), | ||||
|                         InkWell( | ||||
|                           onTap: () { | ||||
|                         IconButton( | ||||
|                           constraints: const BoxConstraints(), | ||||
|                           padding: EdgeInsets.zero, | ||||
|                           visualDensity: VisualDensity.compact, | ||||
|                           icon: Container( | ||||
|                             padding: const EdgeInsets.all(6), | ||||
|                             child: !_isDownloading | ||||
|                                 ? !_isCompletedDownload | ||||
|                                     ? const Icon(Symbols.save_alt) | ||||
|                                     : const Icon(Symbols.download_done) | ||||
|                                 : SizedBox( | ||||
|                                     width: 20, | ||||
|                                     height: 20, | ||||
|                                     child: CircularProgressIndicator( | ||||
|                                       backgroundColor: Theme.of(context) | ||||
|                                           .colorScheme | ||||
|                                           .surfaceContainerHighest, | ||||
|                                       value: _progressOfDownload, | ||||
|                                       strokeWidth: 3, | ||||
|                                     ), | ||||
|                                   ), | ||||
|                           ), | ||||
|                           onPressed: | ||||
|                               _isDownloading ? null : () => _saveToAlbum(_page), | ||||
|                         ), | ||||
|                         IconButton( | ||||
|                           iconSize: 18, | ||||
|                           constraints: const BoxConstraints(), | ||||
|                           icon: const Icon(Icons.info_outline), | ||||
|                           style: ButtonStyle( | ||||
|                             backgroundColor: MaterialStateProperty.all( | ||||
|                               Theme.of(context) | ||||
|                                   .colorScheme | ||||
|                                   .surface | ||||
|                                   .withOpacity(0.5), | ||||
|                             ), | ||||
|                           ), | ||||
|                           onPressed: () { | ||||
|                             _showDetail = true; | ||||
|                             showModalBottomSheet( | ||||
|                               context: context, | ||||
|                               builder: (context) => _AttachmentZoomDetailPopup( | ||||
|                                 data: widget.data.elementAt( | ||||
|                                     widget.data.length > 1 | ||||
|                                         ? _pageController.page?.round() ?? 0 | ||||
|                                         : 0), | ||||
|                                 data: widget.data.elementAt(_page), | ||||
|                               ), | ||||
|                             ).then((_) { | ||||
|                               _showDetail = false; | ||||
|                             }); | ||||
|                           }, | ||||
|                           child: Text( | ||||
|                             'viewDetailedAttachment'.tr(), | ||||
|                             style: metaTextStyle.copyWith( | ||||
|                                 decoration: TextDecoration.underline), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ); | ||||
| @@ -427,18 +386,20 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> { | ||||
|           ), | ||||
|         ), | ||||
|         onTap: () { | ||||
|           if (_showOverlay) { | ||||
|             Navigator.pop(context); | ||||
|             return; | ||||
|           } | ||||
|           setState(() => _showOverlay = !_showOverlay); | ||||
|         }, | ||||
|         onVerticalDragUpdate: (details) { | ||||
|           if (_showDetail) return; | ||||
|           if (_showDetail || !_dismissable) return; | ||||
|           if (details.delta.dy <= -20) { | ||||
|             _showDetail = true; | ||||
|             showModalBottomSheet( | ||||
|               context: context, | ||||
|               builder: (context) => _AttachmentZoomDetailPopup( | ||||
|                 data: widget.data.elementAt(widget.data.length > 1 | ||||
|                     ? _pageController.page?.round() ?? 0 | ||||
|                     : 0), | ||||
|                 data: widget.data.elementAt(_page), | ||||
|               ), | ||||
|             ).then((_) { | ||||
|               _showDetail = false; | ||||
|   | ||||
| @@ -149,7 +149,6 @@ class PostItem extends StatelessWidget { | ||||
|  | ||||
|   void _doShareViaPicture(BuildContext context) async { | ||||
|     final box = context.findRenderObject() as RenderBox?; | ||||
|     context.showSnackbar('postSharingViaPicture'.tr()); | ||||
|  | ||||
|     final controller = ScreenshotController(); | ||||
|     final capturedImage = await controller.captureFromLongWidget( | ||||
| @@ -160,9 +159,9 @@ class PostItem extends StatelessWidget { | ||||
|           child: Material( | ||||
|             child: MultiProvider( | ||||
|               providers: [ | ||||
|                 // Create a copy of environments | ||||
|                 Provider<SnNetworkProvider>(create: (_) => context.read()), | ||||
|                 ChangeNotifierProvider<ConfigProvider>( | ||||
|                     create: (_) => context.read()), | ||||
|                 Provider<UserDirectoryProvider>(create: (_) => context.read()), | ||||
|               ], | ||||
|               child: ResponsiveBreakpoints.builder( | ||||
|                 breakpoints: ResponsiveBreakpoints.of(context).breakpoints, | ||||
| @@ -507,6 +506,8 @@ class PostShareImageWidget extends StatelessWidget { | ||||
|             StyledWidget(AttachmentList( | ||||
|               data: data.preload!.attachments!, | ||||
|               columned: true, | ||||
|               fit: BoxFit.contain, | ||||
|               filterQuality: FilterQuality.high, | ||||
|             )).padding(horizontal: 16, bottom: 8), | ||||
|           Column( | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
| @@ -1037,8 +1038,10 @@ class _PostContentHeader extends StatelessWidget { | ||||
|                   onTap: () { | ||||
|                     GoRouter.of(context).pushNamed( | ||||
|                       'postEditor', | ||||
|                       pathParameters: {'mode': data.typePlural}, | ||||
|                       queryParameters: {'editing': data.id.toString()}, | ||||
|                       queryParameters: { | ||||
|                         'editing': data.id.toString(), | ||||
|                         'mode': data.typePlural, | ||||
|                       }, | ||||
|                     ); | ||||
|                   }, | ||||
|                 ), | ||||
| @@ -1065,8 +1068,10 @@ class _PostContentHeader extends StatelessWidget { | ||||
|                 onTap: () { | ||||
|                   GoRouter.of(context).pushNamed( | ||||
|                     'postEditor', | ||||
|                     pathParameters: {'mode': 'stories'}, | ||||
|                     queryParameters: {'replying': data.id.toString()}, | ||||
|                     queryParameters: { | ||||
|                       'replying': data.id.toString(), | ||||
|                       'mode': data.typePlural, | ||||
|                     }, | ||||
|                   ); | ||||
|                 }, | ||||
|               ), | ||||
| @@ -1081,8 +1086,10 @@ class _PostContentHeader extends StatelessWidget { | ||||
|                 onTap: () { | ||||
|                   GoRouter.of(context).pushNamed( | ||||
|                     'postEditor', | ||||
|                     pathParameters: {'mode': 'stories'}, | ||||
|                     queryParameters: {'reposting': data.id.toString()}, | ||||
|                     queryParameters: { | ||||
|                       'reposting': data.id.toString(), | ||||
|                       'mode': 'stories', | ||||
|                     }, | ||||
|                   ); | ||||
|                 }, | ||||
|               ), | ||||
|   | ||||
| @@ -25,7 +25,8 @@ class PostMiniEditor extends StatefulWidget { | ||||
| } | ||||
|  | ||||
| class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|   final PostWriteController _writeController = PostWriteController(doLoadFromTemporary: false); | ||||
|   final PostWriteController _writeController = | ||||
|       PostWriteController(doLoadFromTemporary: false); | ||||
|  | ||||
|   bool _isFetching = false; | ||||
|  | ||||
| @@ -44,8 +45,9 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|         resp.data?.map((e) => SnPublisher.fromJson(e)) ?? [], | ||||
|       ); | ||||
|       final beforeId = config.prefs.getInt('int_last_publisher_id'); | ||||
|       _writeController | ||||
|           .setPublisher(_publishers?.where((ele) => ele.id == beforeId).firstOrNull ?? _publishers?.firstOrNull); | ||||
|       _writeController.setPublisher( | ||||
|           _publishers?.where((ele) => ele.id == beforeId).firstOrNull ?? | ||||
|               _publishers?.firstOrNull); | ||||
|     } catch (err) { | ||||
|       if (!mounted) return; | ||||
|       context.showErrorDialog(err); | ||||
| @@ -99,11 +101,17 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                                 Expanded( | ||||
|                                   child: Column( | ||||
|                                     mainAxisSize: MainAxisSize.min, | ||||
|                                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                                     crossAxisAlignment: | ||||
|                                         CrossAxisAlignment.start, | ||||
|                                     children: [ | ||||
|                                       Text(item.nick).textStyle(Theme.of(context).textTheme.bodyMedium!), | ||||
|                                       Text(item.nick).textStyle( | ||||
|                                           Theme.of(context) | ||||
|                                               .textTheme | ||||
|                                               .bodyMedium!), | ||||
|                                       Text('@${item.name}') | ||||
|                                           .textStyle(Theme.of(context).textTheme.bodySmall!) | ||||
|                                           .textStyle(Theme.of(context) | ||||
|                                               .textTheme | ||||
|                                               .bodySmall!) | ||||
|                                           .fontSize(12), | ||||
|                                     ], | ||||
|                                   ), | ||||
| @@ -120,7 +128,8 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                           CircleAvatar( | ||||
|                             radius: 16, | ||||
|                             backgroundColor: Colors.transparent, | ||||
|                             foregroundColor: Theme.of(context).colorScheme.onSurface, | ||||
|                             foregroundColor: | ||||
|                                 Theme.of(context).colorScheme.onSurface, | ||||
|                             child: const Icon(Symbols.add), | ||||
|                           ), | ||||
|                           const Gap(8), | ||||
| @@ -129,7 +138,8 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                               mainAxisSize: MainAxisSize.min, | ||||
|                               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                               children: [ | ||||
|                                 Text('publishersNew').tr().textStyle(Theme.of(context).textTheme.bodyMedium!), | ||||
|                                 Text('publishersNew').tr().textStyle( | ||||
|                                     Theme.of(context).textTheme.bodyMedium!), | ||||
|                               ], | ||||
|                             ), | ||||
|                           ), | ||||
| @@ -140,7 +150,9 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                   value: _writeController.publisher, | ||||
|                   onChanged: (SnPublisher? value) { | ||||
|                     if (value == null) { | ||||
|                       GoRouter.of(context).pushNamed('accountPublisherNew').then((value) { | ||||
|                       GoRouter.of(context) | ||||
|                           .pushNamed('accountPublisherNew') | ||||
|                           .then((value) { | ||||
|                         if (value == true) { | ||||
|                           _publishers = null; | ||||
|                           _fetchPublishers(); | ||||
| @@ -176,7 +188,8 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                     ), | ||||
|                     border: InputBorder.none, | ||||
|                   ), | ||||
|                   onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), | ||||
|                   onTapOutside: (_) => | ||||
|                       FocusManager.instance.primaryFocus?.unfocus(), | ||||
|                 ), | ||||
|               ), | ||||
|               const Gap(8), | ||||
| @@ -185,7 +198,8 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                 TweenAnimationBuilder<double>( | ||||
|                   tween: Tween(begin: 0, end: _writeController.progress), | ||||
|                   duration: Duration(milliseconds: 300), | ||||
|                   builder: (context, value, _) => LinearProgressIndicator(value: value, minHeight: 2), | ||||
|                   builder: (context, value, _) => | ||||
|                       LinearProgressIndicator(value: value, minHeight: 2), | ||||
|                 ) | ||||
|               else if (_writeController.isBusy) | ||||
|                 const LinearProgressIndicator(value: null, minHeight: 2), | ||||
| @@ -200,15 +214,17 @@ class _PostMiniEditorState extends State<PostMiniEditor> { | ||||
|                     onPressed: () { | ||||
|                       GoRouter.of(context).pushNamed( | ||||
|                         'postEditor', | ||||
|                         pathParameters: {'mode': 'stories'}, | ||||
|                         queryParameters: { | ||||
|                           if (widget.postReplyId != null) 'replying': widget.postReplyId.toString(), | ||||
|                           if (widget.postReplyId != null) | ||||
|                             'replying': widget.postReplyId.toString(), | ||||
|                           'mode': 'stories', | ||||
|                         }, | ||||
|                       ); | ||||
|                     }, | ||||
|                   ), | ||||
|                   TextButton.icon( | ||||
|                     onPressed: (_writeController.isBusy || _writeController.publisher == null) | ||||
|                     onPressed: (_writeController.isBusy || | ||||
|                             _writeController.publisher == null) | ||||
|                         ? null | ||||
|                         : () { | ||||
|                             _writeController.sendPost(context).then((_) { | ||||
|   | ||||
| @@ -34,11 +34,14 @@ class UniversalImage extends StatelessWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; | ||||
|     final double? resizeHeight = cacheHeight != null ? (cacheHeight! * devicePixelRatio) : null; | ||||
|     final double? resizeWidth = cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null; | ||||
|     final double? resizeHeight = | ||||
|         cacheHeight != null ? (cacheHeight! * devicePixelRatio) : null; | ||||
|     final double? resizeWidth = | ||||
|         cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null; | ||||
|  | ||||
|     return Image( | ||||
|       filterQuality: filterQuality ?? context.read<ConfigProvider>().imageQuality, | ||||
|       filterQuality: | ||||
|           filterQuality ?? context.read<ConfigProvider>().imageQuality, | ||||
|       image: kIsWeb | ||||
|           ? UniversalImage.provider(url) | ||||
|           : ResizeImage( | ||||
| @@ -52,7 +55,8 @@ class UniversalImage extends StatelessWidget { | ||||
|       fit: fit, | ||||
|       loadingBuilder: noProgressIndicator | ||||
|           ? null | ||||
|           : (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { | ||||
|           : (BuildContext context, Widget child, | ||||
|               ImageChunkEvent? loadingProgress) { | ||||
|               if (loadingProgress == null) return child; | ||||
|               return Container( | ||||
|                 constraints: BoxConstraints(maxHeight: 80), | ||||
| @@ -61,12 +65,15 @@ class UniversalImage extends StatelessWidget { | ||||
|                     tween: Tween( | ||||
|                       begin: 0, | ||||
|                       end: loadingProgress.expectedTotalBytes != null | ||||
|                           ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! | ||||
|                           ? loadingProgress.cumulativeBytesLoaded / | ||||
|                               loadingProgress.expectedTotalBytes! | ||||
|                           : 0, | ||||
|                     ), | ||||
|                     duration: const Duration(milliseconds: 300), | ||||
|                     builder: (context, value, _) => CircularProgressIndicator( | ||||
|                       value: loadingProgress.expectedTotalBytes != null ? value.toDouble() : null, | ||||
|                       value: loadingProgress.expectedTotalBytes != null | ||||
|                           ? value.toDouble() | ||||
|                           : null, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
| @@ -114,6 +121,7 @@ class AutoResizeUniversalImage extends StatelessWidget { | ||||
|   final BoxFit? fit; | ||||
|   final bool noProgressIndicator; | ||||
|   final bool noErrorWidget; | ||||
|   final FilterQuality? filterQuality; | ||||
|  | ||||
|   const AutoResizeUniversalImage( | ||||
|     this.url, { | ||||
| @@ -123,6 +131,7 @@ class AutoResizeUniversalImage extends StatelessWidget { | ||||
|     this.fit, | ||||
|     this.noProgressIndicator = false, | ||||
|     this.noErrorWidget = false, | ||||
|     this.filterQuality, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
| @@ -137,6 +146,7 @@ class AutoResizeUniversalImage extends StatelessWidget { | ||||
|         noErrorWidget: noErrorWidget, | ||||
|         cacheHeight: constraints.maxHeight, | ||||
|         cacheWidth: constraints.maxWidth, | ||||
|         filterQuality: filterQuality, | ||||
|       ); | ||||
|     }); | ||||
|   } | ||||
|   | ||||
							
								
								
									
										22
									
								
								pubspec.yaml
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								pubspec.yaml
									
									
									
									
									
								
							| @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev | ||||
| # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||||
| # In Windows, build-name is used as the major, minor, and patch parts | ||||
| # of the product and file versions while build-number is used as the build suffix. | ||||
| version: 2.4.2+76 | ||||
| version: 2.4.2+77 | ||||
|  | ||||
| environment: | ||||
|   sdk: ^3.5.4 | ||||
| @@ -187,18 +187,14 @@ flutter: | ||||
|   # "family" key with the font family name, and a "fonts" key with a | ||||
|   # list giving the asset and other descriptors for the font. For | ||||
|   # example: | ||||
|   # fonts: | ||||
|   #   - family: Schyler | ||||
|   #     fonts: | ||||
|   #       - asset: fonts/Schyler-Regular.ttf | ||||
|   #       - asset: fonts/Schyler-Italic.ttf | ||||
|   #         style: italic | ||||
|   #   - family: Trajan Pro | ||||
|   #     fonts: | ||||
|   #       - asset: fonts/TrajanPro.ttf | ||||
|   #       - asset: fonts/TrajanPro_Bold.ttf | ||||
|   #         weight: 700 | ||||
|   # | ||||
|   fonts: | ||||
|     - family: Nunito | ||||
|       fonts: | ||||
|         - asset: assets/fonts/Nunito-Regular.ttf | ||||
|         - asset: assets/fonts/Nunito-Bold.ttf | ||||
|           weight: 700 | ||||
|         - asset: assets/fonts/Nunito-Italic.ttf | ||||
|           style: italic | ||||
|   # For details regarding fonts from package dependencies, | ||||
|   # see https://flutter.dev/to/font-from-package | ||||
|  | ||||
|   | ||||
| @@ -1,192 +0,0 @@ | ||||
|  | ||||
| var CanvasKitInit = (() => { | ||||
|   var _scriptName = import.meta.url; | ||||
|    | ||||
|   return ( | ||||
| function(moduleArg = {}) { | ||||
|   var moduleRtn; | ||||
|  | ||||
| var r=moduleArg,aa,ca,da=new Promise((a,b)=>{aa=a;ca=b}),ea="object"==typeof window,ha="function"==typeof importScripts; | ||||
| (function(a){a.ce=a.ce||[];a.ce.push(function(){a.MakeSWCanvasSurface=function(b){var c=b,e="undefined"!==typeof OffscreenCanvas&&c instanceof OffscreenCanvas;if(!("undefined"!==typeof HTMLCanvasElement&&c instanceof HTMLCanvasElement||e||(c=document.getElementById(b),c)))throw"Canvas with id "+b+" was not found";if(b=a.MakeSurface(c.width,c.height))b.Ae=c;return b};a.MakeCanvasSurface||(a.MakeCanvasSurface=a.MakeSWCanvasSurface);a.MakeSurface=function(b,c){var e={width:b,height:c,colorType:a.ColorType.RGBA_8888, | ||||
| alphaType:a.AlphaType.Unpremul,colorSpace:a.ColorSpace.SRGB},f=b*c*4,k=a._malloc(f);if(e=a.Surface._makeRasterDirect(e,k,4*b))e.Ae=null,e.$e=b,e.Xe=c,e.Ye=f,e.He=k,e.getCanvas().clear(a.TRANSPARENT);return e};a.MakeRasterDirectSurface=function(b,c,e){return a.Surface._makeRasterDirect(b,c.byteOffset,e)};a.Surface.prototype.flush=function(b){a.$d(this.Zd);this._flush();if(this.Ae){var c=new Uint8ClampedArray(a.HEAPU8.buffer,this.He,this.Ye);c=new ImageData(c,this.$e,this.Xe);b?this.Ae.getContext("2d").putImageData(c, | ||||
| 0,0,b[0],b[1],b[2]-b[0],b[3]-b[1]):this.Ae.getContext("2d").putImageData(c,0,0)}};a.Surface.prototype.dispose=function(){this.He&&a._free(this.He);this.delete()};a.$d=a.$d||function(){};a.Be=a.Be||function(){return null}})})(r); | ||||
| (function(a){a.ce=a.ce||[];a.ce.push(function(){function b(l,p,v){return l&&l.hasOwnProperty(p)?l[p]:v}function c(l){var p=ja(ka);ka[p]=l;return p}function e(l){return l.naturalHeight||l.videoHeight||l.displayHeight||l.height}function f(l){return l.naturalWidth||l.videoWidth||l.displayWidth||l.width}function k(l,p,v,w){l.bindTexture(l.TEXTURE_2D,p);w||v.alphaType!==a.AlphaType.Premul||l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0);return p}function n(l,p,v){v||p.alphaType!==a.AlphaType.Premul|| | ||||
| l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);l.bindTexture(l.TEXTURE_2D,null)}a.GetWebGLContext=function(l,p){if(!l)throw"null canvas passed into makeWebGLContext";var v={alpha:b(p,"alpha",1),depth:b(p,"depth",1),stencil:b(p,"stencil",8),antialias:b(p,"antialias",0),premultipliedAlpha:b(p,"premultipliedAlpha",1),preserveDrawingBuffer:b(p,"preserveDrawingBuffer",0),preferLowPowerToHighPerformance:b(p,"preferLowPowerToHighPerformance",0),failIfMajorPerformanceCaveat:b(p,"failIfMajorPerformanceCaveat", | ||||
| 0),enableExtensionsByDefault:b(p,"enableExtensionsByDefault",1),explicitSwapControl:b(p,"explicitSwapControl",0),renderViaOffscreenBackBuffer:b(p,"renderViaOffscreenBackBuffer",0)};v.majorVersion=p&&p.majorVersion?p.majorVersion:"undefined"!==typeof WebGL2RenderingContext?2:1;if(v.explicitSwapControl)throw"explicitSwapControl is not supported";l=la(l,v);if(!l)return 0;oa(l);z.le.getExtension("WEBGL_debug_renderer_info");return l};a.deleteContext=function(l){z===pa[l]&&(z=null);"object"==typeof JSEvents&& | ||||
| JSEvents.Af(pa[l].le.canvas);pa[l]&&pa[l].le.canvas&&(pa[l].le.canvas.Ve=void 0);pa[l]=null};a._setTextureCleanup({deleteTexture:function(l,p){var v=ka[p];v&&pa[l].le.deleteTexture(v);ka[p]=null}});a.MakeWebGLContext=function(l){if(!this.$d(l))return null;var p=this._MakeGrContext();if(!p)return null;p.Zd=l;var v=p.delete.bind(p);p["delete"]=function(){a.$d(this.Zd);v()}.bind(p);return z.Je=p};a.MakeGrContext=a.MakeWebGLContext;a.GrDirectContext.prototype.getResourceCacheLimitBytes=function(){a.$d(this.Zd); | ||||
| this._getResourceCacheLimitBytes()};a.GrDirectContext.prototype.getResourceCacheUsageBytes=function(){a.$d(this.Zd);this._getResourceCacheUsageBytes()};a.GrDirectContext.prototype.releaseResourcesAndAbandonContext=function(){a.$d(this.Zd);this._releaseResourcesAndAbandonContext()};a.GrDirectContext.prototype.setResourceCacheLimitBytes=function(l){a.$d(this.Zd);this._setResourceCacheLimitBytes(l)};a.MakeOnScreenGLSurface=function(l,p,v,w,A,D){if(!this.$d(l.Zd))return null;p=void 0===A||void 0===D? | ||||
| this._MakeOnScreenGLSurface(l,p,v,w):this._MakeOnScreenGLSurface(l,p,v,w,A,D);if(!p)return null;p.Zd=l.Zd;return p};a.MakeRenderTarget=function(){var l=arguments[0];if(!this.$d(l.Zd))return null;if(3===arguments.length){var p=this._MakeRenderTargetWH(l,arguments[1],arguments[2]);if(!p)return null}else if(2===arguments.length){if(p=this._MakeRenderTargetII(l,arguments[1]),!p)return null}else return null;p.Zd=l.Zd;return p};a.MakeWebGLCanvasSurface=function(l,p,v){p=p||null;var w=l,A="undefined"!== | ||||
| typeof OffscreenCanvas&&w instanceof OffscreenCanvas;if(!("undefined"!==typeof HTMLCanvasElement&&w instanceof HTMLCanvasElement||A||(w=document.getElementById(l),w)))throw"Canvas with id "+l+" was not found";l=this.GetWebGLContext(w,v);if(!l||0>l)throw"failed to create webgl context: err "+l;l=this.MakeWebGLContext(l);p=this.MakeOnScreenGLSurface(l,w.width,w.height,p);return p?p:(p=w.cloneNode(!0),w.parentNode.replaceChild(p,w),p.classList.add("ck-replaced"),a.MakeSWCanvasSurface(p))};a.MakeCanvasSurface= | ||||
| a.MakeWebGLCanvasSurface;a.Surface.prototype.makeImageFromTexture=function(l,p){a.$d(this.Zd);l=c(l);if(p=this._makeImageFromTexture(this.Zd,l,p))p.ue=l;return p};a.Surface.prototype.makeImageFromTextureSource=function(l,p,v){p||={height:e(l),width:f(l),colorType:a.ColorType.RGBA_8888,alphaType:v?a.AlphaType.Premul:a.AlphaType.Unpremul};p.colorSpace||(p.colorSpace=a.ColorSpace.SRGB);a.$d(this.Zd);var w=z.le;v=k(w,w.createTexture(),p,v);2===z.version?w.texImage2D(w.TEXTURE_2D,0,w.RGBA,p.width,p.height, | ||||
| 0,w.RGBA,w.UNSIGNED_BYTE,l):w.texImage2D(w.TEXTURE_2D,0,w.RGBA,w.RGBA,w.UNSIGNED_BYTE,l);n(w,p);this._resetContext();return this.makeImageFromTexture(v,p)};a.Surface.prototype.updateTextureFromSource=function(l,p,v){if(l.ue){a.$d(this.Zd);var w=l.getImageInfo(),A=z.le,D=k(A,ka[l.ue],w,v);2===z.version?A.texImage2D(A.TEXTURE_2D,0,A.RGBA,f(p),e(p),0,A.RGBA,A.UNSIGNED_BYTE,p):A.texImage2D(A.TEXTURE_2D,0,A.RGBA,A.RGBA,A.UNSIGNED_BYTE,p);n(A,w,v);this._resetContext();ka[l.ue]=null;l.ue=c(D);w.colorSpace= | ||||
| l.getColorSpace();p=this._makeImageFromTexture(this.Zd,l.ue,w);v=l.Yd.ae;A=l.Yd.ee;l.Yd.ae=p.Yd.ae;l.Yd.ee=p.Yd.ee;p.Yd.ae=v;p.Yd.ee=A;p.delete();w.colorSpace.delete()}};a.MakeLazyImageFromTextureSource=function(l,p,v){p||={height:e(l),width:f(l),colorType:a.ColorType.RGBA_8888,alphaType:v?a.AlphaType.Premul:a.AlphaType.Unpremul};p.colorSpace||(p.colorSpace=a.ColorSpace.SRGB);var w={makeTexture:function(){var A=z,D=A.le,I=k(D,D.createTexture(),p,v);2===A.version?D.texImage2D(D.TEXTURE_2D,0,D.RGBA, | ||||
| p.width,p.height,0,D.RGBA,D.UNSIGNED_BYTE,l):D.texImage2D(D.TEXTURE_2D,0,D.RGBA,D.RGBA,D.UNSIGNED_BYTE,l);n(D,p,v);return c(I)},freeSrc:function(){}};"VideoFrame"===l.constructor.name&&(w.freeSrc=function(){l.close()});return a.Image._makeFromGenerator(p,w)};a.$d=function(l){return l?oa(l):!1};a.Be=function(){return z&&z.Je&&!z.Je.isDeleted()?z.Je:null}})})(r); | ||||
| (function(a){function b(g){return(f(255*g[3])<<24|f(255*g[0])<<16|f(255*g[1])<<8|f(255*g[2])<<0)>>>0}function c(g){if(g&&g._ck)return g;if(g instanceof Float32Array){for(var d=Math.floor(g.length/4),h=new Uint32Array(d),m=0;m<d;m++)h[m]=b(g.slice(4*m,4*(m+1)));return h}if(g instanceof Uint32Array)return g;if(g instanceof Array&&g[0]instanceof Float32Array)return g.map(b)}function e(g){if(void 0===g)return 1;var d=parseFloat(g);return g&&-1!==g.indexOf("%")?d/100:d}function f(g){return Math.round(Math.max(0, | ||||
| Math.min(g||0,255)))}function k(g,d){d&&d._ck||a._free(g)}function n(g,d,h){if(!g||!g.length)return K;if(g&&g._ck)return g.byteOffset;var m=a[d].BYTES_PER_ELEMENT;h||=a._malloc(g.length*m);a[d].set(g,h/m);return h}function l(g){var d={he:K,count:g.length,colorType:a.ColorType.RGBA_F32};if(g instanceof Float32Array)d.he=n(g,"HEAPF32"),d.count=g.length/4;else if(g instanceof Uint32Array)d.he=n(g,"HEAPU32"),d.colorType=a.ColorType.RGBA_8888;else if(g instanceof Array){if(g&&g.length){for(var h=a._malloc(16* | ||||
| g.length),m=0,t=h/4,u=0;u<g.length;u++)for(var x=0;4>x;x++)a.HEAPF32[t+m]=g[u][x],m++;g=h}else g=K;d.he=g}else throw"Invalid argument to copyFlexibleColorArray, Not a color array "+typeof g;return d}function p(g){if(!g)return K;var d=ba.toTypedArray();if(g.length){if(6===g.length||9===g.length)return n(g,"HEAPF32",P),6===g.length&&a.HEAPF32.set(Wc,6+P/4),P;if(16===g.length)return d[0]=g[0],d[1]=g[1],d[2]=g[3],d[3]=g[4],d[4]=g[5],d[5]=g[7],d[6]=g[12],d[7]=g[13],d[8]=g[15],P;throw"invalid matrix size"; | ||||
| }if(void 0===g.m11)throw"invalid matrix argument";d[0]=g.m11;d[1]=g.m21;d[2]=g.m41;d[3]=g.m12;d[4]=g.m22;d[5]=g.m42;d[6]=g.m14;d[7]=g.m24;d[8]=g.m44;return P}function v(g){if(!g)return K;var d=Y.toTypedArray();if(g.length){if(16!==g.length&&6!==g.length&&9!==g.length)throw"invalid matrix size";if(16===g.length)return n(g,"HEAPF32",ma);d.fill(0);d[0]=g[0];d[1]=g[1];d[3]=g[2];d[4]=g[3];d[5]=g[4];d[7]=g[5];d[10]=1;d[12]=g[6];d[13]=g[7];d[15]=g[8];6===g.length&&(d[12]=0,d[13]=0,d[15]=1);return ma}if(void 0=== | ||||
| g.m11)throw"invalid matrix argument";d[0]=g.m11;d[1]=g.m21;d[2]=g.m31;d[3]=g.m41;d[4]=g.m12;d[5]=g.m22;d[6]=g.m32;d[7]=g.m42;d[8]=g.m13;d[9]=g.m23;d[10]=g.m33;d[11]=g.m43;d[12]=g.m14;d[13]=g.m24;d[14]=g.m34;d[15]=g.m44;return ma}function w(g,d){return n(g,"HEAPF32",d||ia)}function A(g,d,h,m){var t=Ea.toTypedArray();t[0]=g;t[1]=d;t[2]=h;t[3]=m;return ia}function D(g){for(var d=new Float32Array(4),h=0;4>h;h++)d[h]=a.HEAPF32[g/4+h];return d}function I(g,d){return n(g,"HEAPF32",d||W)}function R(g,d){return n(g, | ||||
| "HEAPF32",d||ub)}a.Color=function(g,d,h,m){void 0===m&&(m=1);return a.Color4f(f(g)/255,f(d)/255,f(h)/255,m)};a.ColorAsInt=function(g,d,h,m){void 0===m&&(m=255);return(f(m)<<24|f(g)<<16|f(d)<<8|f(h)<<0&268435455)>>>0};a.Color4f=function(g,d,h,m){void 0===m&&(m=1);return Float32Array.of(g,d,h,m)};Object.defineProperty(a,"TRANSPARENT",{get:function(){return a.Color4f(0,0,0,0)}});Object.defineProperty(a,"BLACK",{get:function(){return a.Color4f(0,0,0,1)}});Object.defineProperty(a,"WHITE",{get:function(){return a.Color4f(1, | ||||
| 1,1,1)}});Object.defineProperty(a,"RED",{get:function(){return a.Color4f(1,0,0,1)}});Object.defineProperty(a,"GREEN",{get:function(){return a.Color4f(0,1,0,1)}});Object.defineProperty(a,"BLUE",{get:function(){return a.Color4f(0,0,1,1)}});Object.defineProperty(a,"YELLOW",{get:function(){return a.Color4f(1,1,0,1)}});Object.defineProperty(a,"CYAN",{get:function(){return a.Color4f(0,1,1,1)}});Object.defineProperty(a,"MAGENTA",{get:function(){return a.Color4f(1,0,1,1)}});a.getColorComponents=function(g){return[Math.floor(255* | ||||
| g[0]),Math.floor(255*g[1]),Math.floor(255*g[2]),g[3]]};a.parseColorString=function(g,d){g=g.toLowerCase();if(g.startsWith("#")){d=255;switch(g.length){case 9:d=parseInt(g.slice(7,9),16);case 7:var h=parseInt(g.slice(1,3),16);var m=parseInt(g.slice(3,5),16);var t=parseInt(g.slice(5,7),16);break;case 5:d=17*parseInt(g.slice(4,5),16);case 4:h=17*parseInt(g.slice(1,2),16),m=17*parseInt(g.slice(2,3),16),t=17*parseInt(g.slice(3,4),16)}return a.Color(h,m,t,d/255)}return g.startsWith("rgba")?(g=g.slice(5, | ||||
| -1),g=g.split(","),a.Color(+g[0],+g[1],+g[2],e(g[3]))):g.startsWith("rgb")?(g=g.slice(4,-1),g=g.split(","),a.Color(+g[0],+g[1],+g[2],e(g[3]))):g.startsWith("gray(")||g.startsWith("hsl")||!d||(g=d[g],void 0===g)?a.BLACK:g};a.multiplyByAlpha=function(g,d){g=g.slice();g[3]=Math.max(0,Math.min(g[3]*d,1));return g};a.Malloc=function(g,d){var h=a._malloc(d*g.BYTES_PER_ELEMENT);return{_ck:!0,length:d,byteOffset:h,qe:null,subarray:function(m,t){m=this.toTypedArray().subarray(m,t);m._ck=!0;return m},toTypedArray:function(){if(this.qe&& | ||||
| this.qe.length)return this.qe;this.qe=new g(a.HEAPU8.buffer,h,d);this.qe._ck=!0;return this.qe}}};a.Free=function(g){a._free(g.byteOffset);g.byteOffset=K;g.toTypedArray=null;g.qe=null};var P=K,ba,ma=K,Y,ia=K,Ea,fa,W=K,Ub,Ba=K,Vb,vb=K,Wb,wb=K,$a,Na=K,Xb,ub=K,Yb,Zb=K,Wc=Float32Array.of(0,0,1),K=0;a.onRuntimeInitialized=function(){function g(d,h,m,t,u,x,C){x||(x=4*t.width,t.colorType===a.ColorType.RGBA_F16?x*=2:t.colorType===a.ColorType.RGBA_F32&&(x*=4));var G=x*t.height;var F=u?u.byteOffset:a._malloc(G); | ||||
| if(C?!d._readPixels(t,F,x,h,m,C):!d._readPixels(t,F,x,h,m))return u||a._free(F),null;if(u)return u.toTypedArray();switch(t.colorType){case a.ColorType.RGBA_8888:case a.ColorType.RGBA_F16:d=(new Uint8Array(a.HEAPU8.buffer,F,G)).slice();break;case a.ColorType.RGBA_F32:d=(new Float32Array(a.HEAPU8.buffer,F,G)).slice();break;default:return null}a._free(F);return d}Ea=a.Malloc(Float32Array,4);ia=Ea.byteOffset;Y=a.Malloc(Float32Array,16);ma=Y.byteOffset;ba=a.Malloc(Float32Array,9);P=ba.byteOffset;Xb=a.Malloc(Float32Array, | ||||
| 12);ub=Xb.byteOffset;Yb=a.Malloc(Float32Array,12);Zb=Yb.byteOffset;fa=a.Malloc(Float32Array,4);W=fa.byteOffset;Ub=a.Malloc(Float32Array,4);Ba=Ub.byteOffset;Vb=a.Malloc(Float32Array,3);vb=Vb.byteOffset;Wb=a.Malloc(Float32Array,3);wb=Wb.byteOffset;$a=a.Malloc(Int32Array,4);Na=$a.byteOffset;a.ColorSpace.SRGB=a.ColorSpace._MakeSRGB();a.ColorSpace.DISPLAY_P3=a.ColorSpace._MakeDisplayP3();a.ColorSpace.ADOBE_RGB=a.ColorSpace._MakeAdobeRGB();a.GlyphRunFlags={IsWhiteSpace:a._GlyphRunFlags_isWhiteSpace};a.Path.MakeFromCmds= | ||||
| function(d){var h=n(d,"HEAPF32"),m=a.Path._MakeFromCmds(h,d.length);k(h,d);return m};a.Path.MakeFromVerbsPointsWeights=function(d,h,m){var t=n(d,"HEAPU8"),u=n(h,"HEAPF32"),x=n(m,"HEAPF32"),C=a.Path._MakeFromVerbsPointsWeights(t,d.length,u,h.length,x,m&&m.length||0);k(t,d);k(u,h);k(x,m);return C};a.Path.prototype.addArc=function(d,h,m){d=I(d);this._addArc(d,h,m);return this};a.Path.prototype.addCircle=function(d,h,m,t){this._addCircle(d,h,m,!!t);return this};a.Path.prototype.addOval=function(d,h,m){void 0=== | ||||
| m&&(m=1);d=I(d);this._addOval(d,!!h,m);return this};a.Path.prototype.addPath=function(){var d=Array.prototype.slice.call(arguments),h=d[0],m=!1;"boolean"===typeof d[d.length-1]&&(m=d.pop());if(1===d.length)this._addPath(h,1,0,0,0,1,0,0,0,1,m);else if(2===d.length)d=d[1],this._addPath(h,d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1,m);else if(7===d.length||10===d.length)this._addPath(h,d[1],d[2],d[3],d[4],d[5],d[6],d[7]||0,d[8]||0,d[9]||1,m);else return null;return this};a.Path.prototype.addPoly= | ||||
| function(d,h){var m=n(d,"HEAPF32");this._addPoly(m,d.length/2,h);k(m,d);return this};a.Path.prototype.addRect=function(d,h){d=I(d);this._addRect(d,!!h);return this};a.Path.prototype.addRRect=function(d,h){d=R(d);this._addRRect(d,!!h);return this};a.Path.prototype.addVerbsPointsWeights=function(d,h,m){var t=n(d,"HEAPU8"),u=n(h,"HEAPF32"),x=n(m,"HEAPF32");this._addVerbsPointsWeights(t,d.length,u,h.length,x,m&&m.length||0);k(t,d);k(u,h);k(x,m)};a.Path.prototype.arc=function(d,h,m,t,u,x){d=a.LTRBRect(d- | ||||
| m,h-m,d+m,h+m);u=(u-t)/Math.PI*180-360*!!x;x=new a.Path;x.addArc(d,t/Math.PI*180,u);this.addPath(x,!0);x.delete();return this};a.Path.prototype.arcToOval=function(d,h,m,t){d=I(d);this._arcToOval(d,h,m,t);return this};a.Path.prototype.arcToRotated=function(d,h,m,t,u,x,C){this._arcToRotated(d,h,m,!!t,!!u,x,C);return this};a.Path.prototype.arcToTangent=function(d,h,m,t,u){this._arcToTangent(d,h,m,t,u);return this};a.Path.prototype.close=function(){this._close();return this};a.Path.prototype.conicTo= | ||||
| function(d,h,m,t,u){this._conicTo(d,h,m,t,u);return this};a.Path.prototype.computeTightBounds=function(d){this._computeTightBounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Path.prototype.cubicTo=function(d,h,m,t,u,x){this._cubicTo(d,h,m,t,u,x);return this};a.Path.prototype.dash=function(d,h,m){return this._dash(d,h,m)?this:null};a.Path.prototype.getBounds=function(d){this._getBounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Path.prototype.lineTo=function(d, | ||||
| h){this._lineTo(d,h);return this};a.Path.prototype.moveTo=function(d,h){this._moveTo(d,h);return this};a.Path.prototype.offset=function(d,h){this._transform(1,0,d,0,1,h,0,0,1);return this};a.Path.prototype.quadTo=function(d,h,m,t){this._quadTo(d,h,m,t);return this};a.Path.prototype.rArcTo=function(d,h,m,t,u,x,C){this._rArcTo(d,h,m,t,u,x,C);return this};a.Path.prototype.rConicTo=function(d,h,m,t,u){this._rConicTo(d,h,m,t,u);return this};a.Path.prototype.rCubicTo=function(d,h,m,t,u,x){this._rCubicTo(d, | ||||
| h,m,t,u,x);return this};a.Path.prototype.rLineTo=function(d,h){this._rLineTo(d,h);return this};a.Path.prototype.rMoveTo=function(d,h){this._rMoveTo(d,h);return this};a.Path.prototype.rQuadTo=function(d,h,m,t){this._rQuadTo(d,h,m,t);return this};a.Path.prototype.stroke=function(d){d=d||{};d.width=d.width||1;d.miter_limit=d.miter_limit||4;d.cap=d.cap||a.StrokeCap.Butt;d.join=d.join||a.StrokeJoin.Miter;d.precision=d.precision||1;return this._stroke(d)?this:null};a.Path.prototype.transform=function(){if(1=== | ||||
| arguments.length){var d=arguments[0];this._transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1)}else if(6===arguments.length||9===arguments.length)d=arguments,this._transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1);else throw"transform expected to take 1 or 9 arguments. Got "+arguments.length;return this};a.Path.prototype.trim=function(d,h,m){return this._trim(d,h,!!m)?this:null};a.Image.prototype.encodeToBytes=function(d,h){var m=a.Be();d=d||a.ImageFormat.PNG;h=h||100; | ||||
| return m?this._encodeToBytes(d,h,m):this._encodeToBytes(d,h)};a.Image.prototype.makeShaderCubic=function(d,h,m,t,u){u=p(u);return this._makeShaderCubic(d,h,m,t,u)};a.Image.prototype.makeShaderOptions=function(d,h,m,t,u){u=p(u);return this._makeShaderOptions(d,h,m,t,u)};a.Image.prototype.readPixels=function(d,h,m,t,u){var x=a.Be();return g(this,d,h,m,t,u,x)};a.Canvas.prototype.clear=function(d){a.$d(this.Zd);d=w(d);this._clear(d)};a.Canvas.prototype.clipRRect=function(d,h,m){a.$d(this.Zd);d=R(d);this._clipRRect(d, | ||||
| h,m)};a.Canvas.prototype.clipRect=function(d,h,m){a.$d(this.Zd);d=I(d);this._clipRect(d,h,m)};a.Canvas.prototype.concat=function(d){a.$d(this.Zd);d=v(d);this._concat(d)};a.Canvas.prototype.drawArc=function(d,h,m,t,u){a.$d(this.Zd);d=I(d);this._drawArc(d,h,m,t,u)};a.Canvas.prototype.drawAtlas=function(d,h,m,t,u,x,C){if(d&&t&&h&&m&&h.length===m.length){a.$d(this.Zd);u||(u=a.BlendMode.SrcOver);var G=n(h,"HEAPF32"),F=n(m,"HEAPF32"),T=m.length/4,U=n(c(x),"HEAPU32");if(C&&"B"in C&&"C"in C)this._drawAtlasCubic(d, | ||||
| F,G,U,T,u,C.B,C.C,t);else{let q=a.FilterMode.Linear,y=a.MipmapMode.None;C&&(q=C.filter,"mipmap"in C&&(y=C.mipmap));this._drawAtlasOptions(d,F,G,U,T,u,q,y,t)}k(G,h);k(F,m);k(U,x)}};a.Canvas.prototype.drawCircle=function(d,h,m,t){a.$d(this.Zd);this._drawCircle(d,h,m,t)};a.Canvas.prototype.drawColor=function(d,h){a.$d(this.Zd);d=w(d);void 0!==h?this._drawColor(d,h):this._drawColor(d)};a.Canvas.prototype.drawColorInt=function(d,h){a.$d(this.Zd);this._drawColorInt(d,h||a.BlendMode.SrcOver)};a.Canvas.prototype.drawColorComponents= | ||||
| function(d,h,m,t,u){a.$d(this.Zd);d=A(d,h,m,t);void 0!==u?this._drawColor(d,u):this._drawColor(d)};a.Canvas.prototype.drawDRRect=function(d,h,m){a.$d(this.Zd);d=R(d,ub);h=R(h,Zb);this._drawDRRect(d,h,m)};a.Canvas.prototype.drawImage=function(d,h,m,t){a.$d(this.Zd);this._drawImage(d,h,m,t||null)};a.Canvas.prototype.drawImageCubic=function(d,h,m,t,u,x){a.$d(this.Zd);this._drawImageCubic(d,h,m,t,u,x||null)};a.Canvas.prototype.drawImageOptions=function(d,h,m,t,u,x){a.$d(this.Zd);this._drawImageOptions(d, | ||||
| h,m,t,u,x||null)};a.Canvas.prototype.drawImageNine=function(d,h,m,t,u){a.$d(this.Zd);h=n(h,"HEAP32",Na);m=I(m);this._drawImageNine(d,h,m,t,u||null)};a.Canvas.prototype.drawImageRect=function(d,h,m,t,u){a.$d(this.Zd);I(h,W);I(m,Ba);this._drawImageRect(d,W,Ba,t,!!u)};a.Canvas.prototype.drawImageRectCubic=function(d,h,m,t,u,x){a.$d(this.Zd);I(h,W);I(m,Ba);this._drawImageRectCubic(d,W,Ba,t,u,x||null)};a.Canvas.prototype.drawImageRectOptions=function(d,h,m,t,u,x){a.$d(this.Zd);I(h,W);I(m,Ba);this._drawImageRectOptions(d, | ||||
| W,Ba,t,u,x||null)};a.Canvas.prototype.drawLine=function(d,h,m,t,u){a.$d(this.Zd);this._drawLine(d,h,m,t,u)};a.Canvas.prototype.drawOval=function(d,h){a.$d(this.Zd);d=I(d);this._drawOval(d,h)};a.Canvas.prototype.drawPaint=function(d){a.$d(this.Zd);this._drawPaint(d)};a.Canvas.prototype.drawParagraph=function(d,h,m){a.$d(this.Zd);this._drawParagraph(d,h,m)};a.Canvas.prototype.drawPatch=function(d,h,m,t,u){if(24>d.length)throw"Need 12 cubic points";if(h&&4>h.length)throw"Need 4 colors";if(m&&8>m.length)throw"Need 4 shader coordinates"; | ||||
| a.$d(this.Zd);const x=n(d,"HEAPF32"),C=h?n(c(h),"HEAPU32"):K,G=m?n(m,"HEAPF32"):K;t||(t=a.BlendMode.Modulate);this._drawPatch(x,C,G,t,u);k(G,m);k(C,h);k(x,d)};a.Canvas.prototype.drawPath=function(d,h){a.$d(this.Zd);this._drawPath(d,h)};a.Canvas.prototype.drawPicture=function(d){a.$d(this.Zd);this._drawPicture(d)};a.Canvas.prototype.drawPoints=function(d,h,m){a.$d(this.Zd);var t=n(h,"HEAPF32");this._drawPoints(d,t,h.length/2,m);k(t,h)};a.Canvas.prototype.drawRRect=function(d,h){a.$d(this.Zd);d=R(d); | ||||
| this._drawRRect(d,h)};a.Canvas.prototype.drawRect=function(d,h){a.$d(this.Zd);d=I(d);this._drawRect(d,h)};a.Canvas.prototype.drawRect4f=function(d,h,m,t,u){a.$d(this.Zd);this._drawRect4f(d,h,m,t,u)};a.Canvas.prototype.drawShadow=function(d,h,m,t,u,x,C){a.$d(this.Zd);var G=n(u,"HEAPF32"),F=n(x,"HEAPF32");h=n(h,"HEAPF32",vb);m=n(m,"HEAPF32",wb);this._drawShadow(d,h,m,t,G,F,C);k(G,u);k(F,x)};a.getShadowLocalBounds=function(d,h,m,t,u,x,C){d=p(d);m=n(m,"HEAPF32",vb);t=n(t,"HEAPF32",wb);if(!this._getShadowLocalBounds(d, | ||||
| h,m,t,u,x,W))return null;h=fa.toTypedArray();return C?(C.set(h),C):h.slice()};a.Canvas.prototype.drawTextBlob=function(d,h,m,t){a.$d(this.Zd);this._drawTextBlob(d,h,m,t)};a.Canvas.prototype.drawVertices=function(d,h,m){a.$d(this.Zd);this._drawVertices(d,h,m)};a.Canvas.prototype.getDeviceClipBounds=function(d){this._getDeviceClipBounds(Na);var h=$a.toTypedArray();d?d.set(h):d=h.slice();return d};a.Canvas.prototype.quickReject=function(d){d=I(d);return this._quickReject(d)};a.Canvas.prototype.getLocalToDevice= | ||||
| function(){this._getLocalToDevice(ma);for(var d=ma,h=Array(16),m=0;16>m;m++)h[m]=a.HEAPF32[d/4+m];return h};a.Canvas.prototype.getTotalMatrix=function(){this._getTotalMatrix(P);for(var d=Array(9),h=0;9>h;h++)d[h]=a.HEAPF32[P/4+h];return d};a.Canvas.prototype.makeSurface=function(d){d=this._makeSurface(d);d.Zd=this.Zd;return d};a.Canvas.prototype.readPixels=function(d,h,m,t,u){a.$d(this.Zd);return g(this,d,h,m,t,u)};a.Canvas.prototype.saveLayer=function(d,h,m,t,u){h=I(h);return this._saveLayer(d|| | ||||
| null,h,m||null,t||0,u||a.TileMode.Clamp)};a.Canvas.prototype.writePixels=function(d,h,m,t,u,x,C,G){if(d.byteLength%(h*m))throw"pixels length must be a multiple of the srcWidth * srcHeight";a.$d(this.Zd);var F=d.byteLength/(h*m);x=x||a.AlphaType.Unpremul;C=C||a.ColorType.RGBA_8888;G=G||a.ColorSpace.SRGB;var T=F*h;F=n(d,"HEAPU8");h=this._writePixels({width:h,height:m,colorType:C,alphaType:x,colorSpace:G},F,T,t,u);k(F,d);return h};a.ColorFilter.MakeBlend=function(d,h,m){d=w(d);m=m||a.ColorSpace.SRGB; | ||||
| return a.ColorFilter._MakeBlend(d,h,m)};a.ColorFilter.MakeMatrix=function(d){if(!d||20!==d.length)throw"invalid color matrix";var h=n(d,"HEAPF32"),m=a.ColorFilter._makeMatrix(h);k(h,d);return m};a.ContourMeasure.prototype.getPosTan=function(d,h){this._getPosTan(d,W);d=fa.toTypedArray();return h?(h.set(d),h):d.slice()};a.ImageFilter.prototype.getOutputBounds=function(d,h,m){d=I(d,W);h=p(h);this._getOutputBounds(d,h,Na);h=$a.toTypedArray();return m?(m.set(h),m):h.slice()};a.ImageFilter.MakeDropShadow= | ||||
| function(d,h,m,t,u,x){u=w(u,ia);return a.ImageFilter._MakeDropShadow(d,h,m,t,u,x)};a.ImageFilter.MakeDropShadowOnly=function(d,h,m,t,u,x){u=w(u,ia);return a.ImageFilter._MakeDropShadowOnly(d,h,m,t,u,x)};a.ImageFilter.MakeImage=function(d,h,m,t){m=I(m,W);t=I(t,Ba);if("B"in h&&"C"in h)return a.ImageFilter._MakeImageCubic(d,h.B,h.C,m,t);const u=h.filter;let x=a.MipmapMode.None;"mipmap"in h&&(x=h.mipmap);return a.ImageFilter._MakeImageOptions(d,u,x,m,t)};a.ImageFilter.MakeMatrixTransform=function(d,h, | ||||
| m){d=p(d);if("B"in h&&"C"in h)return a.ImageFilter._MakeMatrixTransformCubic(d,h.B,h.C,m);const t=h.filter;let u=a.MipmapMode.None;"mipmap"in h&&(u=h.mipmap);return a.ImageFilter._MakeMatrixTransformOptions(d,t,u,m)};a.Paint.prototype.getColor=function(){this._getColor(ia);return D(ia)};a.Paint.prototype.setColor=function(d,h){h=h||null;d=w(d);this._setColor(d,h)};a.Paint.prototype.setColorComponents=function(d,h,m,t,u){u=u||null;d=A(d,h,m,t);this._setColor(d,u)};a.Path.prototype.getPoint=function(d, | ||||
| h){this._getPoint(d,W);d=fa.toTypedArray();return h?(h[0]=d[0],h[1]=d[1],h):d.slice(0,2)};a.Picture.prototype.makeShader=function(d,h,m,t,u){t=p(t);u=I(u);return this._makeShader(d,h,m,t,u)};a.Picture.prototype.cullRect=function(d){this._cullRect(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.PictureRecorder.prototype.beginRecording=function(d,h){d=I(d);return this._beginRecording(d,!!h)};a.Surface.prototype.getCanvas=function(){var d=this._getCanvas();d.Zd=this.Zd;return d};a.Surface.prototype.makeImageSnapshot= | ||||
| function(d){a.$d(this.Zd);d=n(d,"HEAP32",Na);return this._makeImageSnapshot(d)};a.Surface.prototype.makeSurface=function(d){a.$d(this.Zd);d=this._makeSurface(d);d.Zd=this.Zd;return d};a.Surface.prototype.Ze=function(d,h){this.te||(this.te=this.getCanvas());return requestAnimationFrame(function(){a.$d(this.Zd);d(this.te);this.flush(h)}.bind(this))};a.Surface.prototype.requestAnimationFrame||(a.Surface.prototype.requestAnimationFrame=a.Surface.prototype.Ze);a.Surface.prototype.We=function(d,h){this.te|| | ||||
| (this.te=this.getCanvas());requestAnimationFrame(function(){a.$d(this.Zd);d(this.te);this.flush(h);this.dispose()}.bind(this))};a.Surface.prototype.drawOnce||(a.Surface.prototype.drawOnce=a.Surface.prototype.We);a.PathEffect.MakeDash=function(d,h){h||=0;if(!d.length||1===d.length%2)throw"Intervals array must have even length";var m=n(d,"HEAPF32");h=a.PathEffect._MakeDash(m,d.length,h);k(m,d);return h};a.PathEffect.MakeLine2D=function(d,h){h=p(h);return a.PathEffect._MakeLine2D(d,h)};a.PathEffect.MakePath2D= | ||||
| function(d,h){d=p(d);return a.PathEffect._MakePath2D(d,h)};a.Shader.MakeColor=function(d,h){h=h||null;d=w(d);return a.Shader._MakeColor(d,h)};a.Shader.Blend=a.Shader.MakeBlend;a.Shader.Color=a.Shader.MakeColor;a.Shader.MakeLinearGradient=function(d,h,m,t,u,x,C,G){G=G||null;var F=l(m),T=n(t,"HEAPF32");C=C||0;x=p(x);var U=fa.toTypedArray();U.set(d);U.set(h,2);d=a.Shader._MakeLinearGradient(W,F.he,F.colorType,T,F.count,u,C,x,G);k(F.he,m);t&&k(T,t);return d};a.Shader.MakeRadialGradient=function(d,h,m, | ||||
| t,u,x,C,G){G=G||null;var F=l(m),T=n(t,"HEAPF32");C=C||0;x=p(x);d=a.Shader._MakeRadialGradient(d[0],d[1],h,F.he,F.colorType,T,F.count,u,C,x,G);k(F.he,m);t&&k(T,t);return d};a.Shader.MakeSweepGradient=function(d,h,m,t,u,x,C,G,F,T){T=T||null;var U=l(m),q=n(t,"HEAPF32");C=C||0;G=G||0;F=F||360;x=p(x);d=a.Shader._MakeSweepGradient(d,h,U.he,U.colorType,q,U.count,u,G,F,C,x,T);k(U.he,m);t&&k(q,t);return d};a.Shader.MakeTwoPointConicalGradient=function(d,h,m,t,u,x,C,G,F,T){T=T||null;var U=l(u),q=n(x,"HEAPF32"); | ||||
| F=F||0;G=p(G);var y=fa.toTypedArray();y.set(d);y.set(m,2);d=a.Shader._MakeTwoPointConicalGradient(W,h,t,U.he,U.colorType,q,U.count,C,F,G,T);k(U.he,u);x&&k(q,x);return d};a.Vertices.prototype.bounds=function(d){this._bounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.ce&&a.ce.forEach(function(d){d()})};a.computeTonalColors=function(g){var d=n(g.ambient,"HEAPF32"),h=n(g.spot,"HEAPF32");this._computeTonalColors(d,h);var m={ambient:D(d),spot:D(h)};k(d,g.ambient);k(h,g.spot);return m}; | ||||
| a.LTRBRect=function(g,d,h,m){return Float32Array.of(g,d,h,m)};a.XYWHRect=function(g,d,h,m){return Float32Array.of(g,d,g+h,d+m)};a.LTRBiRect=function(g,d,h,m){return Int32Array.of(g,d,h,m)};a.XYWHiRect=function(g,d,h,m){return Int32Array.of(g,d,g+h,d+m)};a.RRectXY=function(g,d,h){return Float32Array.of(g[0],g[1],g[2],g[3],d,h,d,h,d,h,d,h)};a.MakeAnimatedImageFromEncoded=function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._decodeAnimatedImage(d,g.byteLength))? | ||||
| g:null};a.MakeImageFromEncoded=function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._decodeImage(d,g.byteLength))?g:null};var ab=null;a.MakeImageFromCanvasImageSource=function(g){var d=g.width,h=g.height;ab||=document.createElement("canvas");ab.width=d;ab.height=h;var m=ab.getContext("2d",{willReadFrequently:!0});m.drawImage(g,0,0);g=m.getImageData(0,0,d,h);return a.MakeImage({width:d,height:h,alphaType:a.AlphaType.Unpremul,colorType:a.ColorType.RGBA_8888,colorSpace:a.ColorSpace.SRGB}, | ||||
| g.data,4*d)};a.MakeImage=function(g,d,h){var m=a._malloc(d.length);a.HEAPU8.set(d,m);return a._MakeImage(g,m,d.length,h)};a.MakeVertices=function(g,d,h,m,t,u){var x=t&&t.length||0,C=0;h&&h.length&&(C|=1);m&&m.length&&(C|=2);void 0===u||u||(C|=4);g=new a._VerticesBuilder(g,d.length/2,x,C);n(d,"HEAPF32",g.positions());g.texCoords()&&n(h,"HEAPF32",g.texCoords());g.colors()&&n(c(m),"HEAPU32",g.colors());g.indices()&&n(t,"HEAPU16",g.indices());return g.detach()};(function(g){g.ce=g.ce||[];g.ce.push(function(){function d(q){q&& | ||||
| (q.dir=0===q.dir?g.TextDirection.RTL:g.TextDirection.LTR);return q}function h(q){if(!q||!q.length)return[];for(var y=[],N=0;N<q.length;N+=5){var X=g.LTRBRect(q[N],q[N+1],q[N+2],q[N+3]),xa=g.TextDirection.LTR;0===q[N+4]&&(xa=g.TextDirection.RTL);y.push({rect:X,dir:xa})}g._free(q.byteOffset);return y}function m(q){q=q||{};void 0===q.weight&&(q.weight=g.FontWeight.Normal);q.width=q.width||g.FontWidth.Normal;q.slant=q.slant||g.FontSlant.Upright;return q}function t(q){if(!q||!q.length)return K;for(var y= | ||||
| [],N=0;N<q.length;N++){var X=u(q[N]);y.push(X)}return n(y,"HEAPU32")}function u(q){if(G[q])return G[q];var y=qa(q)+1,N=g._malloc(y);ra(q,N,y);return G[q]=N}function x(q){q._colorPtr=w(q.color);q._foregroundColorPtr=K;q._backgroundColorPtr=K;q._decorationColorPtr=K;q.foregroundColor&&(q._foregroundColorPtr=w(q.foregroundColor,F));q.backgroundColor&&(q._backgroundColorPtr=w(q.backgroundColor,T));q.decorationColor&&(q._decorationColorPtr=w(q.decorationColor,U));Array.isArray(q.fontFamilies)&&q.fontFamilies.length? | ||||
| (q._fontFamiliesPtr=t(q.fontFamilies),q._fontFamiliesLen=q.fontFamilies.length):(q._fontFamiliesPtr=K,q._fontFamiliesLen=0);if(q.locale){var y=q.locale;q._localePtr=u(y);q._localeLen=qa(y)}else q._localePtr=K,q._localeLen=0;if(Array.isArray(q.shadows)&&q.shadows.length){y=q.shadows;var N=y.map(function(na){return na.color||g.BLACK}),X=y.map(function(na){return na.blurRadius||0});q._shadowLen=y.length;for(var xa=g._malloc(8*y.length),xb=xa/4,yb=0;yb<y.length;yb++){var $b=y[yb].offset||[0,0];g.HEAPF32[xb]= | ||||
| $b[0];g.HEAPF32[xb+1]=$b[1];xb+=2}q._shadowColorsPtr=l(N).he;q._shadowOffsetsPtr=xa;q._shadowBlurRadiiPtr=n(X,"HEAPF32")}else q._shadowLen=0,q._shadowColorsPtr=K,q._shadowOffsetsPtr=K,q._shadowBlurRadiiPtr=K;Array.isArray(q.fontFeatures)&&q.fontFeatures.length?(y=q.fontFeatures,N=y.map(function(na){return na.name}),X=y.map(function(na){return na.value}),q._fontFeatureLen=y.length,q._fontFeatureNamesPtr=t(N),q._fontFeatureValuesPtr=n(X,"HEAPU32")):(q._fontFeatureLen=0,q._fontFeatureNamesPtr=K,q._fontFeatureValuesPtr= | ||||
| K);Array.isArray(q.fontVariations)&&q.fontVariations.length?(y=q.fontVariations,N=y.map(function(na){return na.axis}),X=y.map(function(na){return na.value}),q._fontVariationLen=y.length,q._fontVariationAxesPtr=t(N),q._fontVariationValuesPtr=n(X,"HEAPF32")):(q._fontVariationLen=0,q._fontVariationAxesPtr=K,q._fontVariationValuesPtr=K)}function C(q){g._free(q._fontFamiliesPtr);g._free(q._shadowColorsPtr);g._free(q._shadowOffsetsPtr);g._free(q._shadowBlurRadiiPtr);g._free(q._fontFeatureNamesPtr);g._free(q._fontFeatureValuesPtr); | ||||
| g._free(q._fontVariationAxesPtr);g._free(q._fontVariationValuesPtr)}g.Paragraph.prototype.getRectsForRange=function(q,y,N,X){q=this._getRectsForRange(q,y,N,X);return h(q)};g.Paragraph.prototype.getRectsForPlaceholders=function(){var q=this._getRectsForPlaceholders();return h(q)};g.Paragraph.prototype.getGlyphInfoAt=function(q){return d(this._getGlyphInfoAt(q))};g.Paragraph.prototype.getClosestGlyphInfoAtCoordinate=function(q,y){return d(this._getClosestGlyphInfoAtCoordinate(q,y))};g.TypefaceFontProvider.prototype.registerFont= | ||||
| function(q,y){q=g.Typeface.MakeTypefaceFromData(q);if(!q)return null;y=u(y);this._registerFont(q,y)};g.ParagraphStyle=function(q){q.disableHinting=q.disableHinting||!1;if(q.ellipsis){var y=q.ellipsis;q._ellipsisPtr=u(y);q._ellipsisLen=qa(y)}else q._ellipsisPtr=K,q._ellipsisLen=0;null==q.heightMultiplier&&(q.heightMultiplier=-1);q.maxLines=q.maxLines||0;q.replaceTabCharacters=q.replaceTabCharacters||!1;y=(y=q.strutStyle)||{};y.strutEnabled=y.strutEnabled||!1;y.strutEnabled&&Array.isArray(y.fontFamilies)&& | ||||
| y.fontFamilies.length?(y._fontFamiliesPtr=t(y.fontFamilies),y._fontFamiliesLen=y.fontFamilies.length):(y._fontFamiliesPtr=K,y._fontFamiliesLen=0);y.fontStyle=m(y.fontStyle);null==y.fontSize&&(y.fontSize=-1);null==y.heightMultiplier&&(y.heightMultiplier=-1);y.halfLeading=y.halfLeading||!1;y.leading=y.leading||0;y.forceStrutHeight=y.forceStrutHeight||!1;q.strutStyle=y;q.textAlign=q.textAlign||g.TextAlign.Start;q.textDirection=q.textDirection||g.TextDirection.LTR;q.textHeightBehavior=q.textHeightBehavior|| | ||||
| g.TextHeightBehavior.All;q.textStyle=g.TextStyle(q.textStyle);q.applyRoundingHack=!1!==q.applyRoundingHack;return q};g.TextStyle=function(q){q.color||(q.color=g.BLACK);q.decoration=q.decoration||0;q.decorationThickness=q.decorationThickness||0;q.decorationStyle=q.decorationStyle||g.DecorationStyle.Solid;q.textBaseline=q.textBaseline||g.TextBaseline.Alphabetic;null==q.fontSize&&(q.fontSize=-1);q.letterSpacing=q.letterSpacing||0;q.wordSpacing=q.wordSpacing||0;null==q.heightMultiplier&&(q.heightMultiplier= | ||||
| -1);q.halfLeading=q.halfLeading||!1;q.fontStyle=m(q.fontStyle);return q};var G={},F=g._malloc(16),T=g._malloc(16),U=g._malloc(16);g.ParagraphBuilder.Make=function(q,y){x(q.textStyle);y=g.ParagraphBuilder._Make(q,y);C(q.textStyle);return y};g.ParagraphBuilder.MakeFromFontProvider=function(q,y){x(q.textStyle);y=g.ParagraphBuilder._MakeFromFontProvider(q,y);C(q.textStyle);return y};g.ParagraphBuilder.MakeFromFontCollection=function(q,y){x(q.textStyle);y=g.ParagraphBuilder._MakeFromFontCollection(q,y); | ||||
| C(q.textStyle);return y};g.ParagraphBuilder.ShapeText=function(q,y,N){let X=0;for(const xa of y)X+=xa.length;if(X!==q.length)throw"Accumulated block lengths must equal text.length";return g.ParagraphBuilder._ShapeText(q,y,N)};g.ParagraphBuilder.prototype.pushStyle=function(q){x(q);this._pushStyle(q);C(q)};g.ParagraphBuilder.prototype.pushPaintStyle=function(q,y,N){x(q);this._pushPaintStyle(q,y,N);C(q)};g.ParagraphBuilder.prototype.addPlaceholder=function(q,y,N,X,xa){N=N||g.PlaceholderAlignment.Baseline; | ||||
| X=X||g.TextBaseline.Alphabetic;this._addPlaceholder(q||0,y||0,N,X,xa||0)};g.ParagraphBuilder.prototype.setWordsUtf8=function(q){var y=n(q,"HEAPU32");this._setWordsUtf8(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setWordsUtf16=function(q){var y=n(q,"HEAPU32");this._setWordsUtf16(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setGraphemeBreaksUtf8=function(q){var y=n(q,"HEAPU32");this._setGraphemeBreaksUtf8(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setGraphemeBreaksUtf16= | ||||
| function(q){var y=n(q,"HEAPU32");this._setGraphemeBreaksUtf16(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setLineBreaksUtf8=function(q){var y=n(q,"HEAPU32");this._setLineBreaksUtf8(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setLineBreaksUtf16=function(q){var y=n(q,"HEAPU32");this._setLineBreaksUtf16(y,q&&q.length||0);k(y,q)}})})(r);a.ce=a.ce||[];a.ce.push(function(){a.Path.prototype.op=function(g,d){return this._op(g,d)?this:null};a.Path.prototype.simplify=function(){return this._simplify()? | ||||
| this:null}});a.ce=a.ce||[];a.ce.push(function(){a.Canvas.prototype.drawText=function(g,d,h,m,t){var u=qa(g),x=a._malloc(u+1);ra(g,x,u+1);this._drawSimpleText(x,u,d,h,t,m);a._free(x)};a.Canvas.prototype.drawGlyphs=function(g,d,h,m,t,u){if(!(2*g.length<=d.length))throw"Not enough positions for the array of gyphs";a.$d(this.Zd);const x=n(g,"HEAPU16"),C=n(d,"HEAPF32");this._drawGlyphs(g.length,x,C,h,m,t,u);k(C,d);k(x,g)};a.Font.prototype.getGlyphBounds=function(g,d,h){var m=n(g,"HEAPU16"),t=a._malloc(16* | ||||
| g.length);this._getGlyphWidthBounds(m,g.length,K,t,d||null);d=new Float32Array(a.HEAPU8.buffer,t,4*g.length);k(m,g);if(h)return h.set(d),a._free(t),h;g=Float32Array.from(d);a._free(t);return g};a.Font.prototype.getGlyphIDs=function(g,d,h){d||(d=g.length);var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=a._malloc(2*d);d=this._getGlyphIDs(t,m-1,d,g);a._free(t);if(0>d)return a._free(g),null;t=new Uint16Array(a.HEAPU8.buffer,g,d);if(h)return h.set(t),a._free(g),h;h=Uint16Array.from(t);a._free(g);return h};a.Font.prototype.getGlyphIntercepts= | ||||
| function(g,d,h,m){var t=n(g,"HEAPU16"),u=n(d,"HEAPF32");return this._getGlyphIntercepts(t,g.length,!(g&&g._ck),u,d.length,!(d&&d._ck),h,m)};a.Font.prototype.getGlyphWidths=function(g,d,h){var m=n(g,"HEAPU16"),t=a._malloc(4*g.length);this._getGlyphWidthBounds(m,g.length,t,K,d||null);d=new Float32Array(a.HEAPU8.buffer,t,g.length);k(m,g);if(h)return h.set(d),a._free(t),h;g=Float32Array.from(d);a._free(t);return g};a.FontMgr.FromData=function(){if(!arguments.length)return null;var g=arguments;1===g.length&& | ||||
| Array.isArray(g[0])&&(g=arguments[0]);if(!g.length)return null;for(var d=[],h=[],m=0;m<g.length;m++){var t=new Uint8Array(g[m]),u=n(t,"HEAPU8");d.push(u);h.push(t.byteLength)}d=n(d,"HEAPU32");h=n(h,"HEAPU32");g=a.FontMgr._fromData(d,h,g.length);a._free(d);a._free(h);return g};a.Typeface.MakeTypefaceFromData=function(g){g=new Uint8Array(g);var d=n(g,"HEAPU8");return(g=a.Typeface._MakeTypefaceFromData(d,g.byteLength))?g:null};a.Typeface.MakeFreeTypeFaceFromData=a.Typeface.MakeTypefaceFromData;a.Typeface.prototype.getGlyphIDs= | ||||
| function(g,d,h){d||(d=g.length);var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=a._malloc(2*d);d=this._getGlyphIDs(t,m-1,d,g);a._free(t);if(0>d)return a._free(g),null;t=new Uint16Array(a.HEAPU8.buffer,g,d);if(h)return h.set(t),a._free(g),h;h=Uint16Array.from(t);a._free(g);return h};a.TextBlob.MakeOnPath=function(g,d,h,m){if(g&&g.length&&d&&d.countPoints()){if(1===d.countPoints())return this.MakeFromText(g,h);m||=0;var t=h.getGlyphIDs(g);t=h.getGlyphWidths(t);var u=[];d=new a.ContourMeasureIter(d,!1,1);for(var x= | ||||
| d.next(),C=new Float32Array(4),G=0;G<g.length&&x;G++){var F=t[G];m+=F/2;if(m>x.length()){x.delete();x=d.next();if(!x){g=g.substring(0,G);break}m=F/2}x.getPosTan(m,C);var T=C[2],U=C[3];u.push(T,U,C[0]-F/2*T,C[1]-F/2*U);m+=F/2}g=this.MakeFromRSXform(g,u,h);x&&x.delete();d.delete();return g}};a.TextBlob.MakeFromRSXform=function(g,d,h){var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=n(d,"HEAPF32");h=a.TextBlob._MakeFromRSXform(t,m-1,g,h);a._free(t);return h?h:null};a.TextBlob.MakeFromRSXformGlyphs=function(g, | ||||
| d,h){var m=n(g,"HEAPU16");d=n(d,"HEAPF32");h=a.TextBlob._MakeFromRSXformGlyphs(m,2*g.length,d,h);k(m,g);return h?h:null};a.TextBlob.MakeFromGlyphs=function(g,d){var h=n(g,"HEAPU16");d=a.TextBlob._MakeFromGlyphs(h,2*g.length,d);k(h,g);return d?d:null};a.TextBlob.MakeFromText=function(g,d){var h=qa(g)+1,m=a._malloc(h);ra(g,m,h);g=a.TextBlob._MakeFromText(m,h-1,d);a._free(m);return g?g:null};a.MallocGlyphIDs=function(g){return a.Malloc(Uint16Array,g)}});a.ce=a.ce||[];a.ce.push(function(){a.MakePicture= | ||||
| function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._MakePicture(d,g.byteLength))?g:null}});a.ce=a.ce||[];a.ce.push(function(){a.RuntimeEffect.Make=function(g,d){return a.RuntimeEffect._Make(g,{onError:d||function(h){console.log("RuntimeEffect error",h)}})};a.RuntimeEffect.MakeForBlender=function(g,d){return a.RuntimeEffect._MakeForBlender(g,{onError:d||function(h){console.log("RuntimeEffect error",h)}})};a.RuntimeEffect.prototype.makeShader=function(g,d){var h= | ||||
| !g._ck,m=n(g,"HEAPF32");d=p(d);return this._makeShader(m,4*g.length,h,d)};a.RuntimeEffect.prototype.makeShaderWithChildren=function(g,d,h){var m=!g._ck,t=n(g,"HEAPF32");h=p(h);for(var u=[],x=0;x<d.length;x++)u.push(d[x].Yd.ae);d=n(u,"HEAPU32");return this._makeShaderWithChildren(t,4*g.length,m,d,u.length,h)};a.RuntimeEffect.prototype.makeBlender=function(g){var d=!g._ck,h=n(g,"HEAPF32");return this._makeBlender(h,4*g.length,d)}})})(r);var sa=Object.assign({},r),ta="",ua,va; | ||||
| if(ea||ha)ha?ta=self.location.href:"undefined"!=typeof document&&document.currentScript&&(ta=document.currentScript.src),_scriptName&&(ta=_scriptName),ta.startsWith("blob:")?ta="":ta=ta.substr(0,ta.replace(/[?#].*/,"").lastIndexOf("/")+1),ha&&(va=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),ua=a=>fetch(a,{credentials:"same-origin"}).then(b=>b.ok?b.arrayBuffer():Promise.reject(Error(b.status+" : "+b.url))); | ||||
| var wa=console.log.bind(console),ya=console.error.bind(console);Object.assign(r,sa);sa=null;var za,Aa=!1,Ca,B,Da,Fa,E,H,J,Ga;function Ha(){var a=za.buffer;r.HEAP8=Ca=new Int8Array(a);r.HEAP16=Da=new Int16Array(a);r.HEAPU8=B=new Uint8Array(a);r.HEAPU16=Fa=new Uint16Array(a);r.HEAP32=E=new Int32Array(a);r.HEAPU32=H=new Uint32Array(a);r.HEAPF32=J=new Float32Array(a);r.HEAPF64=Ga=new Float64Array(a)}var Ia=[],Ja=[],Ka=[],La=0,Ma=null,Oa=null; | ||||
| function Pa(a){a="Aborted("+a+")";ya(a);Aa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ca(a);throw a;}var Qa=a=>a.startsWith("data:application/octet-stream;base64,"),Ra;function Sa(a){return ua(a).then(b=>new Uint8Array(b),()=>{if(va)var b=va(a);else throw"both async and sync fetching of the wasm failed";return b})}function Ta(a,b,c){return Sa(a).then(e=>WebAssembly.instantiate(e,b)).then(c,e=>{ya(`failed to asynchronously prepare wasm: ${e}`);Pa(e)})} | ||||
| function Ua(a,b){var c=Ra;return"function"!=typeof WebAssembly.instantiateStreaming||Qa(c)||"function"!=typeof fetch?Ta(c,a,b):fetch(c,{credentials:"same-origin"}).then(e=>WebAssembly.instantiateStreaming(e,a).then(b,function(f){ya(`wasm streaming compile failed: ${f}`);ya("falling back to ArrayBuffer instantiation");return Ta(c,a,b)}))}function Va(a){this.name="ExitStatus";this.message=`Program terminated with exit(${a})`;this.status=a}var Wa=a=>{a.forEach(b=>b(r))}; | ||||
| class Xa{constructor(a){this.ae=a-24}} | ||||
| var Ya=0,Za=0,bb="undefined"!=typeof TextDecoder?new TextDecoder:void 0,cb=(a,b=0,c=NaN)=>{var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&bb)return bb.decode(a.subarray(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var k=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|k);else{var n=a[b++]&63;f=224==(f&240)?(f&15)<<12|k<<6|n:(f&7)<<18|k<<12|n<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}, | ||||
| db={},eb=a=>{for(;a.length;){var b=a.pop();a.pop()(b)}};function fb(a){return this.fromWireType(H[a>>2])} | ||||
| var gb={},hb={},ib={},jb,lb=(a,b,c)=>{function e(l){l=c(l);if(l.length!==a.length)throw new jb("Mismatched type converter count");for(var p=0;p<a.length;++p)kb(a[p],l[p])}a.forEach(l=>ib[l]=b);var f=Array(b.length),k=[],n=0;b.forEach((l,p)=>{hb.hasOwnProperty(l)?f[p]=hb[l]:(k.push(l),gb.hasOwnProperty(l)||(gb[l]=[]),gb[l].push(()=>{f[p]=hb[l];++n;n===k.length&&e(f)}))});0===k.length&&e(f)},mb,L=a=>{for(var b="";B[a];)b+=mb[B[a++]];return b},M; | ||||
| function nb(a,b,c={}){var e=b.name;if(!a)throw new M(`type "${e}" must have a positive integer typeid pointer`);if(hb.hasOwnProperty(a)){if(c.lf)return;throw new M(`Cannot register type '${e}' twice`);}hb[a]=b;delete ib[a];gb.hasOwnProperty(a)&&(b=gb[a],delete gb[a],b.forEach(f=>f()))}function kb(a,b,c={}){return nb(a,b,c)} | ||||
| var ob=a=>{throw new M(a.Yd.de.be.name+" instance already deleted");},pb=!1,qb=()=>{},rb=(a,b,c)=>{if(b===c)return a;if(void 0===c.ge)return null;a=rb(a,b,c.ge);return null===a?null:c.cf(a)},sb={},tb={},zb=(a,b)=>{if(void 0===b)throw new M("ptr should not be undefined");for(;a.ge;)b=a.ye(b),a=a.ge;return tb[b]},Bb=(a,b)=>{if(!b.de||!b.ae)throw new jb("makeClassHandle requires ptr and ptrType");if(!!b.ie!==!!b.ee)throw new jb("Both smartPtrType and smartPtr must be specified");b.count={value:1};return Ab(Object.create(a, | ||||
| {Yd:{value:b,writable:!0}}))},Ab=a=>{if("undefined"===typeof FinalizationRegistry)return Ab=b=>b,a;pb=new FinalizationRegistry(b=>{b=b.Yd;--b.count.value;0===b.count.value&&(b.ee?b.ie.ne(b.ee):b.de.be.ne(b.ae))});Ab=b=>{var c=b.Yd;c.ee&&pb.register(b,{Yd:c},b);return b};qb=b=>{pb.unregister(b)};return Ab(a)},Cb=[];function Db(){} | ||||
| var Eb=(a,b)=>Object.defineProperty(b,"name",{value:a}),Fb=(a,b,c)=>{if(void 0===a[b].fe){var e=a[b];a[b]=function(...f){if(!a[b].fe.hasOwnProperty(f.length))throw new M(`Function '${c}' called with an invalid number of arguments (${f.length}) - expects one of (${a[b].fe})!`);return a[b].fe[f.length].apply(this,f)};a[b].fe=[];a[b].fe[e.oe]=e}},Gb=(a,b,c)=>{if(r.hasOwnProperty(a)){if(void 0===c||void 0!==r[a].fe&&void 0!==r[a].fe[c])throw new M(`Cannot register public name '${a}' twice`);Fb(r,a,a); | ||||
| if(r[a].fe.hasOwnProperty(c))throw new M(`Cannot register multiple overloads of a function with the same number of arguments (${c})!`);r[a].fe[c]=b}else r[a]=b,r[a].oe=c},Hb=a=>{a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?`_${a}`:a};function Ib(a,b,c,e,f,k,n,l){this.name=a;this.constructor=b;this.se=c;this.ne=e;this.ge=f;this.ff=k;this.ye=n;this.cf=l;this.pf=[]} | ||||
| var Jb=(a,b,c)=>{for(;b!==c;){if(!b.ye)throw new M(`Expected null or instance of ${c.name}, got an instance of ${b.name}`);a=b.ye(a);b=b.ge}return a};function Kb(a,b){if(null===b){if(this.Ke)throw new M(`null is not a valid ${this.name}`);return 0}if(!b.Yd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Yd.ae)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);return Jb(b.Yd.ae,b.Yd.de.be,this.be)} | ||||
| function Mb(a,b){if(null===b){if(this.Ke)throw new M(`null is not a valid ${this.name}`);if(this.De){var c=this.Le();null!==a&&a.push(this.ne,c);return c}return 0}if(!b||!b.Yd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Yd.ae)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);if(!this.Ce&&b.Yd.de.Ce)throw new M(`Cannot convert argument of type ${b.Yd.ie?b.Yd.ie.name:b.Yd.de.name} to parameter type ${this.name}`);c=Jb(b.Yd.ae,b.Yd.de.be,this.be);if(this.De){if(void 0=== | ||||
| b.Yd.ee)throw new M("Passing raw pointer to smart pointer is illegal");switch(this.uf){case 0:if(b.Yd.ie===this)c=b.Yd.ee;else throw new M(`Cannot convert argument of type ${b.Yd.ie?b.Yd.ie.name:b.Yd.de.name} to parameter type ${this.name}`);break;case 1:c=b.Yd.ee;break;case 2:if(b.Yd.ie===this)c=b.Yd.ee;else{var e=b.clone();c=this.qf(c,Nb(()=>e["delete"]()));null!==a&&a.push(this.ne,c)}break;default:throw new M("Unsupporting sharing policy");}}return c} | ||||
| function Ob(a,b){if(null===b){if(this.Ke)throw new M(`null is not a valid ${this.name}`);return 0}if(!b.Yd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Yd.ae)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);if(b.Yd.de.Ce)throw new M(`Cannot convert argument of type ${b.Yd.de.name} to parameter type ${this.name}`);return Jb(b.Yd.ae,b.Yd.de.be,this.be)} | ||||
| function Pb(a,b,c,e,f,k,n,l,p,v,w){this.name=a;this.be=b;this.Ke=c;this.Ce=e;this.De=f;this.nf=k;this.uf=n;this.Se=l;this.Le=p;this.qf=v;this.ne=w;f||void 0!==b.ge?this.toWireType=Mb:(this.toWireType=e?Kb:Ob,this.ke=null)} | ||||
| var Qb=(a,b,c)=>{if(!r.hasOwnProperty(a))throw new jb("Replacing nonexistent public symbol");void 0!==r[a].fe&&void 0!==c?r[a].fe[c]=b:(r[a]=b,r[a].oe=c)},O,Rb=(a,b,c=[])=>{a.includes("j")?(a=a.replace(/p/g,"i"),b=(0,r["dynCall_"+a])(b,...c)):b=O.get(b)(...c);return b},Sb=(a,b)=>(...c)=>Rb(a,b,c),Tb=(a,b)=>{a=L(a);var c=a.includes("j")?Sb(a,b):O.get(b);if("function"!=typeof c)throw new M(`unknown function pointer with signature ${a}: ${b}`);return c},ac,dc=a=>{a=bc(a);var b=L(a);cc(a);return b},ec= | ||||
| (a,b)=>{function c(k){f[k]||hb[k]||(ib[k]?ib[k].forEach(c):(e.push(k),f[k]=!0))}var e=[],f={};b.forEach(c);throw new ac(`${a}: `+e.map(dc).join([", "]));};function fc(a){for(var b=1;b<a.length;++b)if(null!==a[b]&&void 0===a[b].ke)return!0;return!1} | ||||
| function gc(a,b,c,e,f){var k=b.length;if(2>k)throw new M("argTypes array size mismatch! Must at least get return value and 'this' types!");var n=null!==b[1]&&null!==c,l=fc(b),p="void"!==b[0].name,v=k-2,w=Array(v),A=[],D=[];return Eb(a,function(...I){D.length=0;A.length=n?2:1;A[0]=f;if(n){var R=b[1].toWireType(D,this);A[1]=R}for(var P=0;P<v;++P)w[P]=b[P+2].toWireType(D,I[P]),A.push(w[P]);I=e(...A);if(l)eb(D);else for(P=n?1:2;P<b.length;P++){var ba=1===P?R:w[P-2];null!==b[P].ke&&b[P].ke(ba)}R=p?b[0].fromWireType(I): | ||||
| void 0;return R})} | ||||
| var hc=(a,b)=>{for(var c=[],e=0;e<a;e++)c.push(H[b+4*e>>2]);return c},ic=a=>{a=a.trim();const b=a.indexOf("(");return-1!==b?a.substr(0,b):a},jc=[],kc=[],lc=a=>{9<a&&0===--kc[a+1]&&(kc[a]=void 0,jc.push(a))},mc=a=>{if(!a)throw new M("Cannot use deleted val. handle = "+a);return kc[a]},Nb=a=>{switch(a){case void 0:return 2;case null:return 4;case !0:return 6;case !1:return 8;default:const b=jc.pop()||kc.length;kc[b]=a;kc[b+1]=1;return b}},nc={name:"emscripten::val",fromWireType:a=>{var b=mc(a);lc(a); | ||||
| return b},toWireType:(a,b)=>Nb(b),je:8,readValueFromPointer:fb,ke:null},oc=(a,b,c)=>{switch(b){case 1:return c?function(e){return this.fromWireType(Ca[e])}:function(e){return this.fromWireType(B[e])};case 2:return c?function(e){return this.fromWireType(Da[e>>1])}:function(e){return this.fromWireType(Fa[e>>1])};case 4:return c?function(e){return this.fromWireType(E[e>>2])}:function(e){return this.fromWireType(H[e>>2])};default:throw new TypeError(`invalid integer width (${b}): ${a}`);}},pc=(a,b)=> | ||||
| {var c=hb[a];if(void 0===c)throw a=`${b} has unknown type ${dc(a)}`,new M(a);return c},Lb=a=>{if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a},qc=(a,b)=>{switch(b){case 4:return function(c){return this.fromWireType(J[c>>2])};case 8:return function(c){return this.fromWireType(Ga[c>>3])};default:throw new TypeError(`invalid float width (${b}): ${a}`);}},rc=(a,b,c)=>{switch(b){case 1:return c?e=>Ca[e]:e=>B[e];case 2:return c?e=>Da[e>>1]:e=>Fa[e>> | ||||
| 1];case 4:return c?e=>E[e>>2]:e=>H[e>>2];default:throw new TypeError(`invalid integer width (${b}): ${a}`);}},ra=(a,b,c)=>{var e=B;if(!(0<c))return 0;var f=b;c=b+c-1;for(var k=0;k<a.length;++k){var n=a.charCodeAt(k);if(55296<=n&&57343>=n){var l=a.charCodeAt(++k);n=65536+((n&1023)<<10)|l&1023}if(127>=n){if(b>=c)break;e[b++]=n}else{if(2047>=n){if(b+1>=c)break;e[b++]=192|n>>6}else{if(65535>=n){if(b+2>=c)break;e[b++]=224|n>>12}else{if(b+3>=c)break;e[b++]=240|n>>18;e[b++]=128|n>>12&63}e[b++]=128|n>>6& | ||||
| 63}e[b++]=128|n&63}}e[b]=0;return b-f},qa=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b},sc="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0,tc=(a,b)=>{var c=a>>1;for(var e=c+b/2;!(c>=e)&&Fa[c];)++c;c<<=1;if(32<c-a&&sc)return sc.decode(B.subarray(a,c));c="";for(e=0;!(e>=b/2);++e){var f=Da[a+2*e>>1];if(0==f)break;c+=String.fromCharCode(f)}return c},uc=(a,b,c)=>{c??=2147483647;if(2>c)return 0;c-=2;var e= | ||||
| b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f)Da[b>>1]=a.charCodeAt(f),b+=2;Da[b>>1]=0;return b-e},vc=a=>2*a.length,wc=(a,b)=>{for(var c=0,e="";!(c>=b/4);){var f=E[a+4*c>>2];if(0==f)break;++c;65536<=f?(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023)):e+=String.fromCharCode(f)}return e},xc=(a,b,c)=>{c??=2147483647;if(4>c)return 0;var e=b;c=e+c-4;for(var f=0;f<a.length;++f){var k=a.charCodeAt(f);if(55296<=k&&57343>=k){var n=a.charCodeAt(++f);k=65536+((k&1023)<<10)|n&1023}E[b>>2]=k;b+= | ||||
| 4;if(b+4>c)break}E[b>>2]=0;return b-e},yc=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&++c;b+=4}return b},zc=(a,b,c)=>{var e=[];a=a.toWireType(e,c);e.length&&(H[b>>2]=Nb(e));return a},Ac=[],Bc={},Cc=a=>{var b=Bc[a];return void 0===b?L(a):b},Dc=()=>{function a(b){b.$$$embind_global$$$=b;var c="object"==typeof $$$embind_global$$$&&b.$$$embind_global$$$==b;c||delete b.$$$embind_global$$$;return c}if("object"==typeof globalThis)return globalThis;if("object"==typeof $$$embind_global$$$)return $$$embind_global$$$; | ||||
| "object"==typeof global&&a(global)?$$$embind_global$$$=global:"object"==typeof self&&a(self)&&($$$embind_global$$$=self);if("object"==typeof $$$embind_global$$$)return $$$embind_global$$$;throw Error("unable to get global object.");},Ec=a=>{var b=Ac.length;Ac.push(a);return b},Fc=(a,b)=>{for(var c=Array(a),e=0;e<a;++e)c[e]=pc(H[b+4*e>>2],"parameter "+e);return c},Gc=Reflect.construct,Q,Hc=a=>{var b=a.getExtension("ANGLE_instanced_arrays");b&&(a.vertexAttribDivisor=(c,e)=>b.vertexAttribDivisorANGLE(c, | ||||
| e),a.drawArraysInstanced=(c,e,f,k)=>b.drawArraysInstancedANGLE(c,e,f,k),a.drawElementsInstanced=(c,e,f,k,n)=>b.drawElementsInstancedANGLE(c,e,f,k,n))},Ic=a=>{var b=a.getExtension("OES_vertex_array_object");b&&(a.createVertexArray=()=>b.createVertexArrayOES(),a.deleteVertexArray=c=>b.deleteVertexArrayOES(c),a.bindVertexArray=c=>b.bindVertexArrayOES(c),a.isVertexArray=c=>b.isVertexArrayOES(c))},Jc=a=>{var b=a.getExtension("WEBGL_draw_buffers");b&&(a.drawBuffers=(c,e)=>b.drawBuffersWEBGL(c,e))},Kc=a=> | ||||
| {var b="ANGLE_instanced_arrays EXT_blend_minmax EXT_disjoint_timer_query EXT_frag_depth EXT_shader_texture_lod EXT_sRGB OES_element_index_uint OES_fbo_render_mipmap OES_standard_derivatives OES_texture_float OES_texture_half_float OES_texture_half_float_linear OES_vertex_array_object WEBGL_color_buffer_float WEBGL_depth_texture WEBGL_draw_buffers EXT_color_buffer_float EXT_conservative_depth EXT_disjoint_timer_query_webgl2 EXT_texture_norm16 NV_shader_noperspective_interpolation WEBGL_clip_cull_distance EXT_clip_control EXT_color_buffer_half_float EXT_depth_clamp EXT_float_blend EXT_polygon_offset_clamp EXT_texture_compression_bptc EXT_texture_compression_rgtc EXT_texture_filter_anisotropic KHR_parallel_shader_compile OES_texture_float_linear WEBGL_blend_func_extended WEBGL_compressed_texture_astc WEBGL_compressed_texture_etc WEBGL_compressed_texture_etc1 WEBGL_compressed_texture_s3tc WEBGL_compressed_texture_s3tc_srgb WEBGL_debug_renderer_info WEBGL_debug_shaders WEBGL_lose_context WEBGL_multi_draw WEBGL_polygon_mode".split(" "); | ||||
| return(a.getSupportedExtensions()||[]).filter(c=>b.includes(c))},Lc=1,Mc=[],Nc=[],Oc=[],Pc=[],ka=[],Qc=[],Rc=[],pa=[],Sc=[],Tc=[],Uc=[],Vc={},Xc={},Yc=4,Zc=0,ja=a=>{for(var b=Lc++,c=a.length;c<b;c++)a[c]=null;return b},$c=(a,b,c,e)=>{for(var f=0;f<a;f++){var k=Q[c](),n=k&&ja(e);k?(k.name=n,e[n]=k):S||=1282;E[b+4*f>>2]=n}},la=(a,b)=>{a.Ne||(a.Ne=a.getContext,a.getContext=function(e,f){f=a.Ne(e,f);return"webgl"==e==f instanceof WebGLRenderingContext?f:null});var c=1<b.majorVersion?a.getContext("webgl2", | ||||
| b):a.getContext("webgl",b);return c?ad(c,b):0},ad=(a,b)=>{var c=ja(pa),e={handle:c,attributes:b,version:b.majorVersion,le:a};a.canvas&&(a.canvas.Ve=e);pa[c]=e;("undefined"==typeof b.df||b.df)&&bd(e);return c},oa=a=>{z=pa[a];r.vf=Q=z?.le;return!(a&&!Q)},bd=a=>{a||=z;if(!a.mf){a.mf=!0;var b=a.le;b.zf=b.getExtension("WEBGL_multi_draw");b.xf=b.getExtension("EXT_polygon_offset_clamp");b.wf=b.getExtension("EXT_clip_control");b.Bf=b.getExtension("WEBGL_polygon_mode");Hc(b);Ic(b);Jc(b);b.Pe=b.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"); | ||||
| b.Re=b.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance");2<=a.version&&(b.me=b.getExtension("EXT_disjoint_timer_query_webgl2"));if(2>a.version||!b.me)b.me=b.getExtension("EXT_disjoint_timer_query");Kc(b).forEach(c=>{c.includes("lose_context")||c.includes("debug")||b.getExtension(c)})}},z,S,cd=(a,b)=>{Q.bindFramebuffer(a,Oc[b])},dd=a=>{Q.bindVertexArray(Rc[a])},ed=a=>Q.clear(a),fd=(a,b,c,e)=>Q.clearColor(a,b,c,e),gd=a=>Q.clearStencil(a),hd=(a,b)=>{for(var c=0;c<a;c++){var e=E[b+ | ||||
| 4*c>>2];Q.deleteVertexArray(Rc[e]);Rc[e]=null}},jd=[],kd=(a,b)=>{$c(a,b,"createVertexArray",Rc)};function ld(){var a=Kc(Q);return a=a.concat(a.map(b=>"GL_"+b))} | ||||
| var md=(a,b,c)=>{if(b){var e=void 0;switch(a){case 36346:e=1;break;case 36344:0!=c&&1!=c&&(S||=1280);return;case 34814:case 36345:e=0;break;case 34466:var f=Q.getParameter(34467);e=f?f.length:0;break;case 33309:if(2>z.version){S||=1282;return}e=ld().length;break;case 33307:case 33308:if(2>z.version){S||=1280;return}e=33307==a?3:0}if(void 0===e)switch(f=Q.getParameter(a),typeof f){case "number":e=f;break;case "boolean":e=f?1:0;break;case "string":S||=1280;return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:e= | ||||
| 0;break;default:S||=1280;return}else{if(f instanceof Float32Array||f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a<f.length;++a)switch(c){case 0:E[b+4*a>>2]=f[a];break;case 2:J[b+4*a>>2]=f[a];break;case 4:Ca[b+a]=f[a]?1:0}return}try{e=f.name|0}catch(k){S||=1280;ya(`GL_INVALID_ENUM in glGet${c}v: Unknown object returned from WebGL getParameter(${a})! (error: ${k})`);return}}break;default:S||=1280;ya(`GL_INVALID_ENUM in glGet${c}v: Native code calling glGet${c}v(${a}) and it returns ${f} of type ${typeof f}!`); | ||||
| return}switch(c){case 1:c=e;H[b>>2]=c;H[b+4>>2]=(c-H[b>>2])/4294967296;break;case 0:E[b>>2]=e;break;case 2:J[b>>2]=e;break;case 4:Ca[b]=e?1:0}}else S||=1281},nd=(a,b)=>md(a,b,0),od=(a,b,c)=>{if(c){a=Sc[a];b=2>z.version?Q.me.getQueryObjectEXT(a,b):Q.getQueryParameter(a,b);var e;"boolean"==typeof b?e=b?1:0:e=b;H[c>>2]=e;H[c+4>>2]=(e-H[c>>2])/4294967296}else S||=1281},qd=a=>{var b=qa(a)+1,c=pd(b);c&&ra(a,c,b);return c},rd=a=>{var b=Vc[a];if(!b){switch(a){case 7939:b=qd(ld().join(" "));break;case 7936:case 7937:case 37445:case 37446:(b= | ||||
| Q.getParameter(a))||(S||=1280);b=b?qd(b):0;break;case 7938:b=Q.getParameter(7938);var c=`OpenGL ES 2.0 (${b})`;2<=z.version&&(c=`OpenGL ES 3.0 (${b})`);b=qd(c);break;case 35724:b=Q.getParameter(35724);c=b.match(/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/);null!==c&&(3==c[1].length&&(c[1]+="0"),b=`OpenGL ES GLSL ES ${c[1]} (${b})`);b=qd(b);break;default:S||=1280}Vc[a]=b}return b},sd=(a,b)=>{if(2>z.version)return S||=1282,0;var c=Xc[a];if(c)return 0>b||b>=c.length?(S||=1281,0):c[b];switch(a){case 7939:return c= | ||||
| ld().map(qd),c=Xc[a]=c,0>b||b>=c.length?(S||=1281,0):c[b];default:return S||=1280,0}},td=a=>"]"==a.slice(-1)&&a.lastIndexOf("["),ud=a=>{a-=5120;return 0==a?Ca:1==a?B:2==a?Da:4==a?E:6==a?J:5==a||28922==a||28520==a||30779==a||30782==a?H:Fa},vd=(a,b,c,e,f)=>{a=ud(a);b=e*((Zc||c)*({5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4}[b-6402]||1)*a.BYTES_PER_ELEMENT+Yc-1&-Yc);return a.subarray(f>>>31-Math.clz32(a.BYTES_PER_ELEMENT),f+b>>>31-Math.clz32(a.BYTES_PER_ELEMENT))},V=a=>{var b=Q.bf;if(b){var c= | ||||
| b.xe[a];"number"==typeof c&&(b.xe[a]=c=Q.getUniformLocation(b,b.Te[a]+(0<c?`[${c}]`:"")));return c}S||=1282},wd=[],xd=[],yd={},Ad=()=>{if(!zd){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:"./this.program"},b;for(b in yd)void 0===yd[b]?delete a[b]:a[b]=yd[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);zd=c}return zd},zd,Bd=[null,[],[]]; | ||||
| jb=r.InternalError=class extends Error{constructor(a){super(a);this.name="InternalError"}};for(var Cd=Array(256),Dd=0;256>Dd;++Dd)Cd[Dd]=String.fromCharCode(Dd);mb=Cd;M=r.BindingError=class extends Error{constructor(a){super(a);this.name="BindingError"}}; | ||||
| Object.assign(Db.prototype,{isAliasOf:function(a){if(!(this instanceof Db&&a instanceof Db))return!1;var b=this.Yd.de.be,c=this.Yd.ae;a.Yd=a.Yd;var e=a.Yd.de.be;for(a=a.Yd.ae;b.ge;)c=b.ye(c),b=b.ge;for(;e.ge;)a=e.ye(a),e=e.ge;return b===e&&c===a},clone:function(){this.Yd.ae||ob(this);if(this.Yd.we)return this.Yd.count.value+=1,this;var a=Ab,b=Object,c=b.create,e=Object.getPrototypeOf(this),f=this.Yd;a=a(c.call(b,e,{Yd:{value:{count:f.count,ve:f.ve,we:f.we,ae:f.ae,de:f.de,ee:f.ee,ie:f.ie}}}));a.Yd.count.value+= | ||||
| 1;a.Yd.ve=!1;return a},["delete"](){this.Yd.ae||ob(this);if(this.Yd.ve&&!this.Yd.we)throw new M("Object already scheduled for deletion");qb(this);var a=this.Yd;--a.count.value;0===a.count.value&&(a.ee?a.ie.ne(a.ee):a.de.be.ne(a.ae));this.Yd.we||(this.Yd.ee=void 0,this.Yd.ae=void 0)},isDeleted:function(){return!this.Yd.ae},deleteLater:function(){this.Yd.ae||ob(this);if(this.Yd.ve&&!this.Yd.we)throw new M("Object already scheduled for deletion");Cb.push(this);this.Yd.ve=!0;return this}}); | ||||
| Object.assign(Pb.prototype,{gf(a){this.Se&&(a=this.Se(a));return a},Oe(a){this.ne?.(a)},je:8,readValueFromPointer:fb,fromWireType:function(a){function b(){return this.De?Bb(this.be.se,{de:this.nf,ae:c,ie:this,ee:a}):Bb(this.be.se,{de:this,ae:a})}var c=this.gf(a);if(!c)return this.Oe(a),null;var e=zb(this.be,c);if(void 0!==e){if(0===e.Yd.count.value)return e.Yd.ae=c,e.Yd.ee=a,e.clone();e=e.clone();this.Oe(a);return e}e=this.be.ff(c);e=sb[e];if(!e)return b.call(this);e=this.Ce?e.af:e.pointerType;var f= | ||||
| rb(c,this.be,e.be);return null===f?b.call(this):this.De?Bb(e.be.se,{de:e,ae:f,ie:this,ee:a}):Bb(e.be.se,{de:e,ae:f})}});ac=r.UnboundTypeError=((a,b)=>{var c=Eb(b,function(e){this.name=b;this.message=e;e=Error(e).stack;void 0!==e&&(this.stack=this.toString()+"\n"+e.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(a.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:`${this.name}: ${this.message}`};return c})(Error,"UnboundTypeError"); | ||||
| kc.push(0,1,void 0,1,null,1,!0,1,!1,1);r.count_emval_handles=()=>kc.length/2-5-jc.length;for(var Ed=0;32>Ed;++Ed)jd.push(Array(Ed));var Fd=new Float32Array(288);for(Ed=0;288>=Ed;++Ed)wd[Ed]=Fd.subarray(0,Ed);var Gd=new Int32Array(288);for(Ed=0;288>=Ed;++Ed)xd[Ed]=Gd.subarray(0,Ed); | ||||
| var Vd={F:(a,b,c)=>{var e=new Xa(a);H[e.ae+16>>2]=0;H[e.ae+4>>2]=b;H[e.ae+8>>2]=c;Ya=a;Za++;throw Ya;},V:function(){return 0},vd:()=>{},ud:function(){return 0},td:()=>{},sd:()=>{},U:function(){},rd:()=>{},nd:()=>{Pa("")},B:a=>{var b=db[a];delete db[a];var c=b.Le,e=b.ne,f=b.Qe,k=f.map(n=>n.kf).concat(f.map(n=>n.sf));lb([a],k,n=>{var l={};f.forEach((p,v)=>{var w=n[v],A=p.hf,D=p.jf,I=n[v+f.length],R=p.rf,P=p.tf;l[p.ef]={read:ba=>w.fromWireType(A(D,ba)),write:(ba,ma)=>{var Y=[];R(P,ba,I.toWireType(Y, | ||||
| ma));eb(Y)}}});return[{name:b.name,fromWireType:p=>{var v={},w;for(w in l)v[w]=l[w].read(p);e(p);return v},toWireType:(p,v)=>{for(var w in l)if(!(w in v))throw new TypeError(`Missing field: "${w}"`);var A=c();for(w in l)l[w].write(A,v[w]);null!==p&&p.push(e,A);return A},je:8,readValueFromPointer:fb,ke:e}]})},Y:()=>{},md:(a,b,c,e)=>{b=L(b);kb(a,{name:b,fromWireType:function(f){return!!f},toWireType:function(f,k){return k?c:e},je:8,readValueFromPointer:function(f){return this.fromWireType(B[f])},ke:null})}, | ||||
| l:(a,b,c,e,f,k,n,l,p,v,w,A,D)=>{w=L(w);k=Tb(f,k);l&&=Tb(n,l);v&&=Tb(p,v);D=Tb(A,D);var I=Hb(w);Gb(I,function(){ec(`Cannot construct ${w} due to unbound types`,[e])});lb([a,b,c],e?[e]:[],R=>{R=R[0];if(e){var P=R.be;var ba=P.se}else ba=Db.prototype;R=Eb(w,function(...Ea){if(Object.getPrototypeOf(this)!==ma)throw new M("Use 'new' to construct "+w);if(void 0===Y.pe)throw new M(w+" has no accessible constructor");var fa=Y.pe[Ea.length];if(void 0===fa)throw new M(`Tried to invoke ctor of ${w} with invalid number of parameters (${Ea.length}) - expected (${Object.keys(Y.pe).toString()}) parameters instead!`); | ||||
| return fa.apply(this,Ea)});var ma=Object.create(ba,{constructor:{value:R}});R.prototype=ma;var Y=new Ib(w,R,ma,D,P,k,l,v);if(Y.ge){var ia;(ia=Y.ge).ze??(ia.ze=[]);Y.ge.ze.push(Y)}P=new Pb(w,Y,!0,!1,!1);ia=new Pb(w+"*",Y,!1,!1,!1);ba=new Pb(w+" const*",Y,!1,!0,!1);sb[a]={pointerType:ia,af:ba};Qb(I,R);return[P,ia,ba]})},e:(a,b,c,e,f,k,n)=>{var l=hc(c,e);b=L(b);b=ic(b);k=Tb(f,k);lb([],[a],p=>{function v(){ec(`Cannot call ${w} due to unbound types`,l)}p=p[0];var w=`${p.name}.${b}`;b.startsWith("@@")&& | ||||
| (b=Symbol[b.substring(2)]);var A=p.be.constructor;void 0===A[b]?(v.oe=c-1,A[b]=v):(Fb(A,b,w),A[b].fe[c-1]=v);lb([],l,D=>{D=[D[0],null].concat(D.slice(1));D=gc(w,D,null,k,n);void 0===A[b].fe?(D.oe=c-1,A[b]=D):A[b].fe[c-1]=D;if(p.be.ze)for(const I of p.be.ze)I.constructor.hasOwnProperty(b)||(I.constructor[b]=D);return[]});return[]})},z:(a,b,c,e,f,k)=>{var n=hc(b,c);f=Tb(e,f);lb([],[a],l=>{l=l[0];var p=`constructor ${l.name}`;void 0===l.be.pe&&(l.be.pe=[]);if(void 0!==l.be.pe[b-1])throw new M(`Cannot register multiple constructors with identical number of parameters (${b- | ||||
| 1}) for class '${l.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`);l.be.pe[b-1]=()=>{ec(`Cannot construct ${l.name} due to unbound types`,n)};lb([],n,v=>{v.splice(1,0,null);l.be.pe[b-1]=gc(p,v,null,f,k);return[]});return[]})},a:(a,b,c,e,f,k,n,l)=>{var p=hc(c,e);b=L(b);b=ic(b);k=Tb(f,k);lb([],[a],v=>{function w(){ec(`Cannot call ${A} due to unbound types`,p)}v=v[0];var A=`${v.name}.${b}`;b.startsWith("@@")&&(b=Symbol[b.substring(2)]);l&&v.be.pf.push(b); | ||||
| var D=v.be.se,I=D[b];void 0===I||void 0===I.fe&&I.className!==v.name&&I.oe===c-2?(w.oe=c-2,w.className=v.name,D[b]=w):(Fb(D,b,A),D[b].fe[c-2]=w);lb([],p,R=>{R=gc(A,R,v,k,n);void 0===D[b].fe?(R.oe=c-2,D[b]=R):D[b].fe[c-2]=R;return[]});return[]})},q:(a,b,c)=>{a=L(a);lb([],[b],e=>{e=e[0];r[a]=e.fromWireType(c);return[]})},ld:a=>kb(a,nc),j:(a,b,c,e)=>{function f(){}b=L(b);f.values={};kb(a,{name:b,constructor:f,fromWireType:function(k){return this.constructor.values[k]},toWireType:(k,n)=>n.value,je:8, | ||||
| readValueFromPointer:oc(b,c,e),ke:null});Gb(b,f)},b:(a,b,c)=>{var e=pc(a,"enum");b=L(b);a=e.constructor;e=Object.create(e.constructor.prototype,{value:{value:c},constructor:{value:Eb(`${e.name}_${b}`,function(){})}});a.values[c]=e;a[b]=e},S:(a,b,c)=>{b=L(b);kb(a,{name:b,fromWireType:e=>e,toWireType:(e,f)=>f,je:8,readValueFromPointer:qc(b,c),ke:null})},w:(a,b,c,e,f,k)=>{var n=hc(b,c);a=L(a);a=ic(a);f=Tb(e,f);Gb(a,function(){ec(`Cannot call ${a} due to unbound types`,n)},b-1);lb([],n,l=>{l=[l[0],null].concat(l.slice(1)); | ||||
| Qb(a,gc(a,l,null,f,k),b-1);return[]})},C:(a,b,c,e,f)=>{b=L(b);-1===f&&(f=4294967295);f=l=>l;if(0===e){var k=32-8*c;f=l=>l<<k>>>k}var n=b.includes("unsigned")?function(l,p){return p>>>0}:function(l,p){return p};kb(a,{name:b,fromWireType:f,toWireType:n,je:8,readValueFromPointer:rc(b,c,0!==e),ke:null})},p:(a,b,c)=>{function e(k){return new f(Ca.buffer,H[k+4>>2],H[k>>2])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=L(c);kb(a,{name:c,fromWireType:e, | ||||
| je:8,readValueFromPointer:e},{lf:!0})},o:(a,b,c,e,f,k,n,l,p,v,w,A)=>{c=L(c);k=Tb(f,k);l=Tb(n,l);v=Tb(p,v);A=Tb(w,A);lb([a],[b],D=>{D=D[0];return[new Pb(c,D.be,!1,!1,!0,D,e,k,l,v,A)]})},R:(a,b)=>{b=L(b);var c="std::string"===b;kb(a,{name:b,fromWireType:function(e){var f=H[e>>2],k=e+4;if(c)for(var n=k,l=0;l<=f;++l){var p=k+l;if(l==f||0==B[p]){n=n?cb(B,n,p-n):"";if(void 0===v)var v=n;else v+=String.fromCharCode(0),v+=n;n=p+1}}else{v=Array(f);for(l=0;l<f;++l)v[l]=String.fromCharCode(B[k+l]);v=v.join("")}cc(e); | ||||
| return v},toWireType:function(e,f){f instanceof ArrayBuffer&&(f=new Uint8Array(f));var k="string"==typeof f;if(!(k||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array))throw new M("Cannot pass non-string to std::string");var n=c&&k?qa(f):f.length;var l=pd(4+n+1),p=l+4;H[l>>2]=n;if(c&&k)ra(f,p,n+1);else if(k)for(k=0;k<n;++k){var v=f.charCodeAt(k);if(255<v)throw cc(p),new M("String has UTF-16 code units that do not fit in 8 bits");B[p+k]=v}else for(k=0;k<n;++k)B[p+k]=f[k]; | ||||
| null!==e&&e.push(cc,l);return l},je:8,readValueFromPointer:fb,ke(e){cc(e)}})},M:(a,b,c)=>{c=L(c);if(2===b){var e=tc;var f=uc;var k=vc;var n=l=>Fa[l>>1]}else 4===b&&(e=wc,f=xc,k=yc,n=l=>H[l>>2]);kb(a,{name:c,fromWireType:l=>{for(var p=H[l>>2],v,w=l+4,A=0;A<=p;++A){var D=l+4+A*b;if(A==p||0==n(D))w=e(w,D-w),void 0===v?v=w:(v+=String.fromCharCode(0),v+=w),w=D+b}cc(l);return v},toWireType:(l,p)=>{if("string"!=typeof p)throw new M(`Cannot pass non-string to C++ string type ${c}`);var v=k(p),w=pd(4+v+b); | ||||
| H[w>>2]=v/b;f(p,w+4,v+b);null!==l&&l.push(cc,w);return w},je:8,readValueFromPointer:fb,ke(l){cc(l)}})},A:(a,b,c,e,f,k)=>{db[a]={name:L(b),Le:Tb(c,e),ne:Tb(f,k),Qe:[]}},d:(a,b,c,e,f,k,n,l,p,v)=>{db[a].Qe.push({ef:L(b),kf:c,hf:Tb(e,f),jf:k,sf:n,rf:Tb(l,p),tf:v})},kd:(a,b)=>{b=L(b);kb(a,{yf:!0,name:b,je:0,fromWireType:()=>{},toWireType:()=>{}})},jd:()=>1,id:()=>{throw Infinity;},E:(a,b,c)=>{a=mc(a);b=pc(b,"emval::as");return zc(b,c,a)},L:(a,b,c,e)=>{a=Ac[a];b=mc(b);return a(null,b,c,e)},t:(a,b,c,e,f)=> | ||||
| {a=Ac[a];b=mc(b);c=Cc(c);return a(b,b[c],e,f)},c:lc,K:a=>{if(0===a)return Nb(Dc());a=Cc(a);return Nb(Dc()[a])},n:(a,b,c)=>{var e=Fc(a,b),f=e.shift();a--;var k=Array(a);b=`methodCaller<(${e.map(n=>n.name).join(", ")}) => ${f.name}>`;return Ec(Eb(b,(n,l,p,v)=>{for(var w=0,A=0;A<a;++A)k[A]=e[A].readValueFromPointer(v+w),w+=e[A].je;n=1===c?Gc(l,k):l.apply(n,k);return zc(f,p,n)}))},y:(a,b)=>{a=mc(a);b=mc(b);return Nb(a[b])},H:a=>{9<a&&(kc[a+1]+=1)},G:()=>Nb([]),f:a=>Nb(Cc(a)),D:()=>Nb({}),hd:a=>{a=mc(a); | ||||
| return!a},m:a=>{var b=mc(a);eb(b);lc(a)},h:(a,b,c)=>{a=mc(a);b=mc(b);c=mc(c);a[b]=c},g:(a,b)=>{a=pc(a,"_emval_take_value");a=a.readValueFromPointer(b);return Nb(a)},X:function(){return-52},W:function(){},gd:(a,b,c,e)=>{var f=(new Date).getFullYear(),k=(new Date(f,0,1)).getTimezoneOffset();f=(new Date(f,6,1)).getTimezoneOffset();H[a>>2]=60*Math.max(k,f);E[b>>2]=Number(k!=f);b=n=>{var l=Math.abs(n);return`UTC${0<=n?"-":"+"}${String(Math.floor(l/60)).padStart(2,"0")}${String(l%60).padStart(2,"0")}`}; | ||||
| a=b(k);b=b(f);f<k?(ra(a,c,17),ra(b,e,17)):(ra(a,e,17),ra(b,c,17))},fd:()=>performance.now(),ed:a=>Q.activeTexture(a),dd:(a,b)=>{Q.attachShader(Nc[a],Qc[b])},cd:(a,b)=>{Q.beginQuery(a,Sc[b])},bd:(a,b)=>{Q.me.beginQueryEXT(a,Sc[b])},ad:(a,b,c)=>{Q.bindAttribLocation(Nc[a],b,c?cb(B,c):"")},$c:(a,b)=>{35051==a?Q.Ie=b:35052==a&&(Q.re=b);Q.bindBuffer(a,Mc[b])},_c:cd,Zc:(a,b)=>{Q.bindRenderbuffer(a,Pc[b])},Yc:(a,b)=>{Q.bindSampler(a,Tc[b])},Xc:(a,b)=>{Q.bindTexture(a,ka[b])},Wc:dd,Vc:dd,Uc:(a,b,c,e)=>Q.blendColor(a, | ||||
| b,c,e),Tc:a=>Q.blendEquation(a),Sc:(a,b)=>Q.blendFunc(a,b),Rc:(a,b,c,e,f,k,n,l,p,v)=>Q.blitFramebuffer(a,b,c,e,f,k,n,l,p,v),Qc:(a,b,c,e)=>{2<=z.version?c&&b?Q.bufferData(a,B,e,c,b):Q.bufferData(a,b,e):Q.bufferData(a,c?B.subarray(c,c+b):b,e)},Pc:(a,b,c,e)=>{2<=z.version?c&&Q.bufferSubData(a,b,B,e,c):Q.bufferSubData(a,b,B.subarray(e,e+c))},Oc:a=>Q.checkFramebufferStatus(a),Nc:ed,Mc:fd,Lc:gd,Kc:(a,b,c,e)=>Q.clientWaitSync(Uc[a],b,(c>>>0)+4294967296*e),Jc:(a,b,c,e)=>{Q.colorMask(!!a,!!b,!!c,!!e)},Ic:a=> | ||||
| {Q.compileShader(Qc[a])},Hc:(a,b,c,e,f,k,n,l)=>{2<=z.version?Q.re||!n?Q.compressedTexImage2D(a,b,c,e,f,k,n,l):Q.compressedTexImage2D(a,b,c,e,f,k,B,l,n):Q.compressedTexImage2D(a,b,c,e,f,k,B.subarray(l,l+n))},Gc:(a,b,c,e,f,k,n,l,p)=>{2<=z.version?Q.re||!l?Q.compressedTexSubImage2D(a,b,c,e,f,k,n,l,p):Q.compressedTexSubImage2D(a,b,c,e,f,k,n,B,p,l):Q.compressedTexSubImage2D(a,b,c,e,f,k,n,B.subarray(p,p+l))},Fc:(a,b,c,e,f)=>Q.copyBufferSubData(a,b,c,e,f),Ec:(a,b,c,e,f,k,n,l)=>Q.copyTexSubImage2D(a,b,c, | ||||
| e,f,k,n,l),Dc:()=>{var a=ja(Nc),b=Q.createProgram();b.name=a;b.Ge=b.Ee=b.Fe=0;b.Me=1;Nc[a]=b;return a},Cc:a=>{var b=ja(Qc);Qc[b]=Q.createShader(a);return b},Bc:a=>Q.cullFace(a),Ac:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Mc[e];f&&(Q.deleteBuffer(f),f.name=0,Mc[e]=null,e==Q.Ie&&(Q.Ie=0),e==Q.re&&(Q.re=0))}},zc:(a,b)=>{for(var c=0;c<a;++c){var e=E[b+4*c>>2],f=Oc[e];f&&(Q.deleteFramebuffer(f),f.name=0,Oc[e]=null)}},yc:a=>{if(a){var b=Nc[a];b?(Q.deleteProgram(b),b.name=0,Nc[a]=null):S||=1281}}, | ||||
| xc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Sc[e];f&&(Q.deleteQuery(f),Sc[e]=null)}},wc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Sc[e];f&&(Q.me.deleteQueryEXT(f),Sc[e]=null)}},vc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Pc[e];f&&(Q.deleteRenderbuffer(f),f.name=0,Pc[e]=null)}},uc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Tc[e];f&&(Q.deleteSampler(f),f.name=0,Tc[e]=null)}},tc:a=>{if(a){var b=Qc[a];b?(Q.deleteShader(b),Qc[a]=null):S||=1281}},sc:a=>{if(a){var b=Uc[a];b? | ||||
| (Q.deleteSync(b),b.name=0,Uc[a]=null):S||=1281}},rc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=ka[e];f&&(Q.deleteTexture(f),f.name=0,ka[e]=null)}},qc:hd,pc:hd,oc:a=>{Q.depthMask(!!a)},nc:a=>Q.disable(a),mc:a=>{Q.disableVertexAttribArray(a)},lc:(a,b,c)=>{Q.drawArrays(a,b,c)},kc:(a,b,c,e)=>{Q.drawArraysInstanced(a,b,c,e)},jc:(a,b,c,e,f)=>{Q.Pe.drawArraysInstancedBaseInstanceWEBGL(a,b,c,e,f)},ic:(a,b)=>{for(var c=jd[a],e=0;e<a;e++)c[e]=E[b+4*e>>2];Q.drawBuffers(c)},hc:(a,b,c,e)=>{Q.drawElements(a, | ||||
| b,c,e)},gc:(a,b,c,e,f)=>{Q.drawElementsInstanced(a,b,c,e,f)},fc:(a,b,c,e,f,k,n)=>{Q.Pe.drawElementsInstancedBaseVertexBaseInstanceWEBGL(a,b,c,e,f,k,n)},ec:(a,b,c,e,f,k)=>{Q.drawElements(a,e,f,k)},dc:a=>Q.enable(a),cc:a=>{Q.enableVertexAttribArray(a)},bc:a=>Q.endQuery(a),ac:a=>{Q.me.endQueryEXT(a)},$b:(a,b)=>(a=Q.fenceSync(a,b))?(b=ja(Uc),a.name=b,Uc[b]=a,b):0,_b:()=>Q.finish(),Zb:()=>Q.flush(),Yb:(a,b,c,e)=>{Q.framebufferRenderbuffer(a,b,c,Pc[e])},Xb:(a,b,c,e,f)=>{Q.framebufferTexture2D(a,b,c,ka[e], | ||||
| f)},Wb:a=>Q.frontFace(a),Vb:(a,b)=>{$c(a,b,"createBuffer",Mc)},Ub:(a,b)=>{$c(a,b,"createFramebuffer",Oc)},Tb:(a,b)=>{$c(a,b,"createQuery",Sc)},Sb:(a,b)=>{for(var c=0;c<a;c++){var e=Q.me.createQueryEXT();if(!e){for(S||=1282;c<a;)E[b+4*c++>>2]=0;break}var f=ja(Sc);e.name=f;Sc[f]=e;E[b+4*c>>2]=f}},Rb:(a,b)=>{$c(a,b,"createRenderbuffer",Pc)},Qb:(a,b)=>{$c(a,b,"createSampler",Tc)},Pb:(a,b)=>{$c(a,b,"createTexture",ka)},Ob:kd,Nb:kd,Mb:a=>Q.generateMipmap(a),Lb:(a,b,c)=>{c?E[c>>2]=Q.getBufferParameter(a, | ||||
| b):S||=1281},Kb:()=>{var a=Q.getError()||S;S=0;return a},Jb:(a,b)=>md(a,b,2),Ib:(a,b,c,e)=>{a=Q.getFramebufferAttachmentParameter(a,b,c);if(a instanceof WebGLRenderbuffer||a instanceof WebGLTexture)a=a.name|0;E[e>>2]=a},Hb:nd,Gb:(a,b,c,e)=>{a=Q.getProgramInfoLog(Nc[a]);null===a&&(a="(unknown error)");b=0<b&&e?ra(a,e,b):0;c&&(E[c>>2]=b)},Fb:(a,b,c)=>{if(c)if(a>=Lc)S||=1281;else if(a=Nc[a],35716==b)a=Q.getProgramInfoLog(a),null===a&&(a="(unknown error)"),E[c>>2]=a.length+1;else if(35719==b){if(!a.Ge){var e= | ||||
| Q.getProgramParameter(a,35718);for(b=0;b<e;++b)a.Ge=Math.max(a.Ge,Q.getActiveUniform(a,b).name.length+1)}E[c>>2]=a.Ge}else if(35722==b){if(!a.Ee)for(e=Q.getProgramParameter(a,35721),b=0;b<e;++b)a.Ee=Math.max(a.Ee,Q.getActiveAttrib(a,b).name.length+1);E[c>>2]=a.Ee}else if(35381==b){if(!a.Fe)for(e=Q.getProgramParameter(a,35382),b=0;b<e;++b)a.Fe=Math.max(a.Fe,Q.getActiveUniformBlockName(a,b).length+1);E[c>>2]=a.Fe}else E[c>>2]=Q.getProgramParameter(a,b);else S||=1281},Eb:od,Db:od,Cb:(a,b,c)=>{if(c){a= | ||||
| Q.getQueryParameter(Sc[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;E[c>>2]=e}else S||=1281},Bb:(a,b,c)=>{if(c){a=Q.me.getQueryObjectEXT(Sc[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;E[c>>2]=e}else S||=1281},Ab:(a,b,c)=>{c?E[c>>2]=Q.getQuery(a,b):S||=1281},zb:(a,b,c)=>{c?E[c>>2]=Q.me.getQueryEXT(a,b):S||=1281},yb:(a,b,c)=>{c?E[c>>2]=Q.getRenderbufferParameter(a,b):S||=1281},xb:(a,b,c,e)=>{a=Q.getShaderInfoLog(Qc[a]);null===a&&(a="(unknown error)");b=0<b&&e?ra(a,e,b):0;c&&(E[c>>2]=b)},wb:(a,b,c,e)=> | ||||
| {a=Q.getShaderPrecisionFormat(a,b);E[c>>2]=a.rangeMin;E[c+4>>2]=a.rangeMax;E[e>>2]=a.precision},vb:(a,b,c)=>{c?35716==b?(a=Q.getShaderInfoLog(Qc[a]),null===a&&(a="(unknown error)"),E[c>>2]=a?a.length+1:0):35720==b?(a=Q.getShaderSource(Qc[a]),E[c>>2]=a?a.length+1:0):E[c>>2]=Q.getShaderParameter(Qc[a],b):S||=1281},ub:rd,tb:sd,sb:(a,b)=>{b=b?cb(B,b):"";if(a=Nc[a]){var c=a,e=c.xe,f=c.Ue,k;if(!e){c.xe=e={};c.Te={};var n=Q.getProgramParameter(c,35718);for(k=0;k<n;++k){var l=Q.getActiveUniform(c,k);var p= | ||||
| l.name;l=l.size;var v=td(p);v=0<v?p.slice(0,v):p;var w=c.Me;c.Me+=l;f[v]=[l,w];for(p=0;p<l;++p)e[w]=p,c.Te[w++]=v}}c=a.xe;e=0;f=b;k=td(b);0<k&&(e=parseInt(b.slice(k+1))>>>0,f=b.slice(0,k));if((f=a.Ue[f])&&e<f[0]&&(e+=f[1],c[e]=c[e]||Q.getUniformLocation(a,b)))return e}else S||=1281;return-1},rb:(a,b,c)=>{for(var e=jd[b],f=0;f<b;f++)e[f]=E[c+4*f>>2];Q.invalidateFramebuffer(a,e)},qb:(a,b,c,e,f,k,n)=>{for(var l=jd[b],p=0;p<b;p++)l[p]=E[c+4*p>>2];Q.invalidateSubFramebuffer(a,l,e,f,k,n)},pb:a=>Q.isSync(Uc[a]), | ||||
| ob:a=>(a=ka[a])?Q.isTexture(a):0,nb:a=>Q.lineWidth(a),mb:a=>{a=Nc[a];Q.linkProgram(a);a.xe=0;a.Ue={}},lb:(a,b,c,e,f,k)=>{Q.Re.multiDrawArraysInstancedBaseInstanceWEBGL(a,E,b>>2,E,c>>2,E,e>>2,H,f>>2,k)},kb:(a,b,c,e,f,k,n,l)=>{Q.Re.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(a,E,b>>2,c,E,e>>2,E,f>>2,E,k>>2,H,n>>2,l)},jb:(a,b)=>{3317==a?Yc=b:3314==a&&(Zc=b);Q.pixelStorei(a,b)},ib:(a,b)=>{Q.me.queryCounterEXT(Sc[a],b)},hb:a=>Q.readBuffer(a),gb:(a,b,c,e,f,k,n)=>{if(2<=z.version)if(Q.Ie)Q.readPixels(a, | ||||
| b,c,e,f,k,n);else{var l=ud(k);n>>>=31-Math.clz32(l.BYTES_PER_ELEMENT);Q.readPixels(a,b,c,e,f,k,l,n)}else(l=vd(k,f,c,e,n))?Q.readPixels(a,b,c,e,f,k,l):S||=1280},fb:(a,b,c,e)=>Q.renderbufferStorage(a,b,c,e),eb:(a,b,c,e,f)=>Q.renderbufferStorageMultisample(a,b,c,e,f),db:(a,b,c)=>{Q.samplerParameterf(Tc[a],b,c)},cb:(a,b,c)=>{Q.samplerParameteri(Tc[a],b,c)},bb:(a,b,c)=>{Q.samplerParameteri(Tc[a],b,E[c>>2])},ab:(a,b,c,e)=>Q.scissor(a,b,c,e),$a:(a,b,c,e)=>{for(var f="",k=0;k<b;++k){var n=(n=H[c+4*k>>2])? | ||||
| cb(B,n,e?H[e+4*k>>2]:void 0):"";f+=n}Q.shaderSource(Qc[a],f)},_a:(a,b,c)=>Q.stencilFunc(a,b,c),Za:(a,b,c,e)=>Q.stencilFuncSeparate(a,b,c,e),Ya:a=>Q.stencilMask(a),Xa:(a,b)=>Q.stencilMaskSeparate(a,b),Wa:(a,b,c)=>Q.stencilOp(a,b,c),Va:(a,b,c,e)=>Q.stencilOpSeparate(a,b,c,e),Ua:(a,b,c,e,f,k,n,l,p)=>{if(2<=z.version){if(Q.re){Q.texImage2D(a,b,c,e,f,k,n,l,p);return}if(p){var v=ud(l);p>>>=31-Math.clz32(v.BYTES_PER_ELEMENT);Q.texImage2D(a,b,c,e,f,k,n,l,v,p);return}}v=p?vd(l,n,e,f,p):null;Q.texImage2D(a, | ||||
| b,c,e,f,k,n,l,v)},Ta:(a,b,c)=>Q.texParameterf(a,b,c),Sa:(a,b,c)=>{Q.texParameterf(a,b,J[c>>2])},Ra:(a,b,c)=>Q.texParameteri(a,b,c),Qa:(a,b,c)=>{Q.texParameteri(a,b,E[c>>2])},Pa:(a,b,c,e,f)=>Q.texStorage2D(a,b,c,e,f),Oa:(a,b,c,e,f,k,n,l,p)=>{if(2<=z.version){if(Q.re){Q.texSubImage2D(a,b,c,e,f,k,n,l,p);return}if(p){var v=ud(l);Q.texSubImage2D(a,b,c,e,f,k,n,l,v,p>>>31-Math.clz32(v.BYTES_PER_ELEMENT));return}}p=p?vd(l,n,f,k,p):null;Q.texSubImage2D(a,b,c,e,f,k,n,l,p)},Na:(a,b)=>{Q.uniform1f(V(a),b)},Ma:(a, | ||||
| b,c)=>{if(2<=z.version)b&&Q.uniform1fv(V(a),J,c>>2,b);else{if(288>=b)for(var e=wd[b],f=0;f<b;++f)e[f]=J[c+4*f>>2];else e=J.subarray(c>>2,c+4*b>>2);Q.uniform1fv(V(a),e)}},La:(a,b)=>{Q.uniform1i(V(a),b)},Ka:(a,b,c)=>{if(2<=z.version)b&&Q.uniform1iv(V(a),E,c>>2,b);else{if(288>=b)for(var e=xd[b],f=0;f<b;++f)e[f]=E[c+4*f>>2];else e=E.subarray(c>>2,c+4*b>>2);Q.uniform1iv(V(a),e)}},Ja:(a,b,c)=>{Q.uniform2f(V(a),b,c)},Ia:(a,b,c)=>{if(2<=z.version)b&&Q.uniform2fv(V(a),J,c>>2,2*b);else{if(144>=b){b*=2;for(var e= | ||||
| wd[b],f=0;f<b;f+=2)e[f]=J[c+4*f>>2],e[f+1]=J[c+(4*f+4)>>2]}else e=J.subarray(c>>2,c+8*b>>2);Q.uniform2fv(V(a),e)}},Ha:(a,b,c)=>{Q.uniform2i(V(a),b,c)},Ga:(a,b,c)=>{if(2<=z.version)b&&Q.uniform2iv(V(a),E,c>>2,2*b);else{if(144>=b){b*=2;for(var e=xd[b],f=0;f<b;f+=2)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2]}else e=E.subarray(c>>2,c+8*b>>2);Q.uniform2iv(V(a),e)}},Fa:(a,b,c,e)=>{Q.uniform3f(V(a),b,c,e)},Ea:(a,b,c)=>{if(2<=z.version)b&&Q.uniform3fv(V(a),J,c>>2,3*b);else{if(96>=b){b*=3;for(var e=wd[b],f=0;f< | ||||
| b;f+=3)e[f]=J[c+4*f>>2],e[f+1]=J[c+(4*f+4)>>2],e[f+2]=J[c+(4*f+8)>>2]}else e=J.subarray(c>>2,c+12*b>>2);Q.uniform3fv(V(a),e)}},Da:(a,b,c,e)=>{Q.uniform3i(V(a),b,c,e)},Ca:(a,b,c)=>{if(2<=z.version)b&&Q.uniform3iv(V(a),E,c>>2,3*b);else{if(96>=b){b*=3;for(var e=xd[b],f=0;f<b;f+=3)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2],e[f+2]=E[c+(4*f+8)>>2]}else e=E.subarray(c>>2,c+12*b>>2);Q.uniform3iv(V(a),e)}},Ba:(a,b,c,e,f)=>{Q.uniform4f(V(a),b,c,e,f)},Aa:(a,b,c)=>{if(2<=z.version)b&&Q.uniform4fv(V(a),J,c>>2,4* | ||||
| b);else{if(72>=b){var e=wd[4*b],f=J;c>>=2;b*=4;for(var k=0;k<b;k+=4){var n=c+k;e[k]=f[n];e[k+1]=f[n+1];e[k+2]=f[n+2];e[k+3]=f[n+3]}}else e=J.subarray(c>>2,c+16*b>>2);Q.uniform4fv(V(a),e)}},za:(a,b,c,e,f)=>{Q.uniform4i(V(a),b,c,e,f)},ya:(a,b,c)=>{if(2<=z.version)b&&Q.uniform4iv(V(a),E,c>>2,4*b);else{if(72>=b){b*=4;for(var e=xd[b],f=0;f<b;f+=4)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2],e[f+2]=E[c+(4*f+8)>>2],e[f+3]=E[c+(4*f+12)>>2]}else e=E.subarray(c>>2,c+16*b>>2);Q.uniform4iv(V(a),e)}},xa:(a,b,c,e)=> | ||||
| {if(2<=z.version)b&&Q.uniformMatrix2fv(V(a),!!c,J,e>>2,4*b);else{if(72>=b){b*=4;for(var f=wd[b],k=0;k<b;k+=4)f[k]=J[e+4*k>>2],f[k+1]=J[e+(4*k+4)>>2],f[k+2]=J[e+(4*k+8)>>2],f[k+3]=J[e+(4*k+12)>>2]}else f=J.subarray(e>>2,e+16*b>>2);Q.uniformMatrix2fv(V(a),!!c,f)}},wa:(a,b,c,e)=>{if(2<=z.version)b&&Q.uniformMatrix3fv(V(a),!!c,J,e>>2,9*b);else{if(32>=b){b*=9;for(var f=wd[b],k=0;k<b;k+=9)f[k]=J[e+4*k>>2],f[k+1]=J[e+(4*k+4)>>2],f[k+2]=J[e+(4*k+8)>>2],f[k+3]=J[e+(4*k+12)>>2],f[k+4]=J[e+(4*k+16)>>2],f[k+ | ||||
| 5]=J[e+(4*k+20)>>2],f[k+6]=J[e+(4*k+24)>>2],f[k+7]=J[e+(4*k+28)>>2],f[k+8]=J[e+(4*k+32)>>2]}else f=J.subarray(e>>2,e+36*b>>2);Q.uniformMatrix3fv(V(a),!!c,f)}},va:(a,b,c,e)=>{if(2<=z.version)b&&Q.uniformMatrix4fv(V(a),!!c,J,e>>2,16*b);else{if(18>=b){var f=wd[16*b],k=J;e>>=2;b*=16;for(var n=0;n<b;n+=16){var l=e+n;f[n]=k[l];f[n+1]=k[l+1];f[n+2]=k[l+2];f[n+3]=k[l+3];f[n+4]=k[l+4];f[n+5]=k[l+5];f[n+6]=k[l+6];f[n+7]=k[l+7];f[n+8]=k[l+8];f[n+9]=k[l+9];f[n+10]=k[l+10];f[n+11]=k[l+11];f[n+12]=k[l+12];f[n+ | ||||
| 13]=k[l+13];f[n+14]=k[l+14];f[n+15]=k[l+15]}}else f=J.subarray(e>>2,e+64*b>>2);Q.uniformMatrix4fv(V(a),!!c,f)}},ua:a=>{a=Nc[a];Q.useProgram(a);Q.bf=a},ta:(a,b)=>Q.vertexAttrib1f(a,b),sa:(a,b)=>{Q.vertexAttrib2f(a,J[b>>2],J[b+4>>2])},ra:(a,b)=>{Q.vertexAttrib3f(a,J[b>>2],J[b+4>>2],J[b+8>>2])},qa:(a,b)=>{Q.vertexAttrib4f(a,J[b>>2],J[b+4>>2],J[b+8>>2],J[b+12>>2])},pa:(a,b)=>{Q.vertexAttribDivisor(a,b)},oa:(a,b,c,e,f)=>{Q.vertexAttribIPointer(a,b,c,e,f)},na:(a,b,c,e,f,k)=>{Q.vertexAttribPointer(a,b,c, | ||||
| !!e,f,k)},ma:(a,b,c,e)=>Q.viewport(a,b,c,e),la:(a,b,c,e)=>{Q.waitSync(Uc[a],b,(c>>>0)+4294967296*e)},ka:a=>{var b=B.length;a>>>=0;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+1/c);e=Math.min(e,a+100663296);a:{e=(Math.min(2147483648,65536*Math.ceil(Math.max(a,e)/65536))-za.buffer.byteLength+65535)/65536|0;try{za.grow(e);Ha();var f=1;break a}catch(k){}f=void 0}if(f)return!0}return!1},ja:()=>z?z.handle:0,qd:(a,b)=>{var c=0;Ad().forEach((e,f)=>{var k=b+c;f=H[a+4*f>>2]=k;for(k=0;k<e.length;++k)Ca[f++]= | ||||
| e.charCodeAt(k);Ca[f]=0;c+=e.length+1});return 0},pd:(a,b)=>{var c=Ad();H[a>>2]=c.length;var e=0;c.forEach(f=>e+=f.length+1);H[b>>2]=e;return 0},ia:a=>{throw new Va(a);},N:()=>52,_:function(){return 52},od:()=>52,Z:function(){return 70},T:(a,b,c,e)=>{for(var f=0,k=0;k<c;k++){var n=H[b>>2],l=H[b+4>>2];b+=8;for(var p=0;p<l;p++){var v=B[n+p],w=Bd[a];0===v||10===v?((1===a?wa:ya)(cb(w)),w.length=0):w.push(v)}f+=l}H[e>>2]=f;return 0},ha:cd,ga:ed,fa:fd,ea:gd,J:nd,Q:rd,da:sd,k:Hd,u:Id,i:Jd,I:Kd,ca:Ld,P:Md, | ||||
| O:Nd,s:Od,x:Pd,r:Qd,v:Rd,ba:Sd,aa:Td,$:Ud},Z=function(){var a={a:Vd};La++;Ra??=r.locateFile?Qa("canvaskit.wasm")?"canvaskit.wasm":ta+"canvaskit.wasm":(new URL("canvaskit.wasm",import.meta.url)).href;Ua(a,function(b){Z=b.instance.exports;za=Z.wd;Ha();O=Z.zd;Ja.unshift(Z.xd);La--;0==La&&(null!==Ma&&(clearInterval(Ma),Ma=null),Oa&&(b=Oa,Oa=null,b()))}).catch(ca);return{}}(),bc=a=>(bc=Z.yd)(a),pd=r._malloc=a=>(pd=r._malloc=Z.Ad)(a),cc=r._free=a=>(cc=r._free=Z.Bd)(a),Wd=(a,b)=>(Wd=Z.Cd)(a,b), | ||||
| Xd=a=>(Xd=Z.Dd)(a),Yd=()=>(Yd=Z.Ed)();r.dynCall_viji=(a,b,c,e,f)=>(r.dynCall_viji=Z.Fd)(a,b,c,e,f);r.dynCall_vijiii=(a,b,c,e,f,k,n)=>(r.dynCall_vijiii=Z.Gd)(a,b,c,e,f,k,n);r.dynCall_viiiiij=(a,b,c,e,f,k,n,l)=>(r.dynCall_viiiiij=Z.Hd)(a,b,c,e,f,k,n,l);r.dynCall_iiiji=(a,b,c,e,f,k)=>(r.dynCall_iiiji=Z.Id)(a,b,c,e,f,k);r.dynCall_jii=(a,b,c)=>(r.dynCall_jii=Z.Jd)(a,b,c);r.dynCall_vij=(a,b,c,e)=>(r.dynCall_vij=Z.Kd)(a,b,c,e);r.dynCall_jiiiiii=(a,b,c,e,f,k,n)=>(r.dynCall_jiiiiii=Z.Ld)(a,b,c,e,f,k,n); | ||||
| r.dynCall_jiiiiji=(a,b,c,e,f,k,n,l)=>(r.dynCall_jiiiiji=Z.Md)(a,b,c,e,f,k,n,l);r.dynCall_ji=(a,b)=>(r.dynCall_ji=Z.Nd)(a,b);r.dynCall_iijj=(a,b,c,e,f,k)=>(r.dynCall_iijj=Z.Od)(a,b,c,e,f,k);r.dynCall_iiji=(a,b,c,e,f)=>(r.dynCall_iiji=Z.Pd)(a,b,c,e,f);r.dynCall_iijjiii=(a,b,c,e,f,k,n,l,p)=>(r.dynCall_iijjiii=Z.Qd)(a,b,c,e,f,k,n,l,p);r.dynCall_iij=(a,b,c,e)=>(r.dynCall_iij=Z.Rd)(a,b,c,e);r.dynCall_vijjjii=(a,b,c,e,f,k,n,l,p,v)=>(r.dynCall_vijjjii=Z.Sd)(a,b,c,e,f,k,n,l,p,v); | ||||
| r.dynCall_jiji=(a,b,c,e,f)=>(r.dynCall_jiji=Z.Td)(a,b,c,e,f);r.dynCall_viijii=(a,b,c,e,f,k,n)=>(r.dynCall_viijii=Z.Ud)(a,b,c,e,f,k,n);r.dynCall_iiiiij=(a,b,c,e,f,k,n)=>(r.dynCall_iiiiij=Z.Vd)(a,b,c,e,f,k,n);r.dynCall_iiiiijj=(a,b,c,e,f,k,n,l,p)=>(r.dynCall_iiiiijj=Z.Wd)(a,b,c,e,f,k,n,l,p);r.dynCall_iiiiiijj=(a,b,c,e,f,k,n,l,p,v)=>(r.dynCall_iiiiiijj=Z.Xd)(a,b,c,e,f,k,n,l,p,v);function Rd(a,b,c,e,f){var k=Yd();try{O.get(a)(b,c,e,f)}catch(n){Xd(k);if(n!==n+0)throw n;Wd(1,0)}} | ||||
| function Id(a,b,c){var e=Yd();try{return O.get(a)(b,c)}catch(f){Xd(e);if(f!==f+0)throw f;Wd(1,0)}}function Pd(a,b,c){var e=Yd();try{O.get(a)(b,c)}catch(f){Xd(e);if(f!==f+0)throw f;Wd(1,0)}}function Hd(a,b){var c=Yd();try{return O.get(a)(b)}catch(e){Xd(c);if(e!==e+0)throw e;Wd(1,0)}}function Od(a,b){var c=Yd();try{O.get(a)(b)}catch(e){Xd(c);if(e!==e+0)throw e;Wd(1,0)}}function Jd(a,b,c,e){var f=Yd();try{return O.get(a)(b,c,e)}catch(k){Xd(f);if(k!==k+0)throw k;Wd(1,0)}} | ||||
| function Ud(a,b,c,e,f,k,n,l,p,v){var w=Yd();try{O.get(a)(b,c,e,f,k,n,l,p,v)}catch(A){Xd(w);if(A!==A+0)throw A;Wd(1,0)}}function Qd(a,b,c,e){var f=Yd();try{O.get(a)(b,c,e)}catch(k){Xd(f);if(k!==k+0)throw k;Wd(1,0)}}function Td(a,b,c,e,f,k,n){var l=Yd();try{O.get(a)(b,c,e,f,k,n)}catch(p){Xd(l);if(p!==p+0)throw p;Wd(1,0)}}function Md(a,b,c,e,f,k,n,l){var p=Yd();try{return O.get(a)(b,c,e,f,k,n,l)}catch(v){Xd(p);if(v!==v+0)throw v;Wd(1,0)}} | ||||
| function Sd(a,b,c,e,f,k){var n=Yd();try{O.get(a)(b,c,e,f,k)}catch(l){Xd(n);if(l!==l+0)throw l;Wd(1,0)}}function Kd(a,b,c,e,f){var k=Yd();try{return O.get(a)(b,c,e,f)}catch(n){Xd(k);if(n!==n+0)throw n;Wd(1,0)}}function Nd(a,b,c,e,f,k,n,l,p,v){var w=Yd();try{return O.get(a)(b,c,e,f,k,n,l,p,v)}catch(A){Xd(w);if(A!==A+0)throw A;Wd(1,0)}}function Ld(a,b,c,e,f,k,n){var l=Yd();try{return O.get(a)(b,c,e,f,k,n)}catch(p){Xd(l);if(p!==p+0)throw p;Wd(1,0)}}var Zd,$d;Oa=function ae(){Zd||be();Zd||(Oa=ae)}; | ||||
| function be(){if(!(0<La)){if(!$d&&($d=1,Wa(Ia),0<La))return;Zd||(Zd=1,r.calledRun=1,Aa||(Wa(Ja),aa(r),r.onRuntimeInitialized?.(),Wa(Ka)))}}be();moduleRtn=da; | ||||
|  | ||||
|  | ||||
|   return moduleRtn; | ||||
| } | ||||
| ); | ||||
| })(); | ||||
| export default CanvasKitInit; | ||||
										
											Binary file not shown.
										
									
								
							| @@ -127,9 +127,29 @@ | ||||
|     <img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt=""> | ||||
| </picture> | ||||
|  | ||||
| <script> | ||||
| {{flutter_js}} | ||||
| {{flutter_build_config}} | ||||
|  | ||||
| <script src="flutter_bootstrap.js" async=""></script> | ||||
| const searchParams = new URLSearchParams(window.location.search); | ||||
| const renderer = searchParams.get('renderer'); | ||||
| let cdn = searchParams.get('cdn'); | ||||
|  | ||||
| if (cdn) { | ||||
|   localStorage.setItem('sn-web-canvaskit-cdn', cdn); | ||||
| } else { | ||||
|   const storagedCdn = localStorage.getItem('sn-web-canvaskit-cdn'); | ||||
|   cdn = storagedCdn ?? 'com'; | ||||
| } | ||||
|  | ||||
| _flutter.loader.load({ | ||||
|   config: { | ||||
|     renderer: renderer ?? 'canvaskit', | ||||
|     canvasKitVariant: 'full', | ||||
|     canvasKitBaseUrl: `https://www.gstatic.${cdn}/flutter-canvaskit/f73bfc4522dd0bc87bbcdb4bb3088082755c5e87`, | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
		Reference in New Issue
	
	Block a user