diff --git a/lib/components/image.dart b/lib/components/image.dart index b2c52d0..ec2c258 100644 --- a/lib/components/image.dart +++ b/lib/components/image.dart @@ -12,6 +12,7 @@ class ImageWithContextMenu extends StatelessWidget { const ImageWithContextMenu(this.data, {super.key, this.uri, + this.originalUri, this.dir, this.fileName, this.fmt = ImageFmt.jpg, @@ -21,6 +22,7 @@ class ImageWithContextMenu extends StatelessWidget { this.changeAd}); final Uint8List data; final String? uri; + final String? originalUri; final ImageFmt fmt; final String? fileName; final String? dir; @@ -65,6 +67,16 @@ class ImageWithContextMenu extends StatelessWidget { } })); } + if (originalUri != null) { + list.add(MenuAction( + title: AppLocalizations.of(context)!.copyOriImgUrl, + callback: () { + copyTextToClipboard(originalUri!).catchError((err) { + _log.warning( + "Failed to copy original image to clipboard:", err); + }); + })); + } if ((isNsfw != null && changeNsfw != null) || (isAd != null && changeAd != null)) { list.add(MenuSeparator()); diff --git a/lib/components/thumbnail.dart b/lib/components/thumbnail.dart index 632dc51..c968cbd 100644 --- a/lib/components/thumbnail.dart +++ b/lib/components/thumbnail.dart @@ -67,6 +67,7 @@ enum _ThumbnailMenu { markAsSfw, markAsAd, markAsNonAd, + copyOriImgUrl, } class _Thumbnail extends State { @@ -261,14 +262,14 @@ class _Thumbnail extends State { switch (v) { case _ThumbnailMenu.copyImage: try { - copyImageToClipboard(_data!, ImageFmt.jpg); + await copyImageToClipboard(_data!, ImageFmt.jpg); } catch (err, stack) { _log.warning("Failed to copy image to clipboard: $err\n$stack"); } break; case _ThumbnailMenu.copyImgUrl: try { - copyTextToClipboard(_uri!); + await copyTextToClipboard(_uri!); } catch (err, stack) { _log.warning("Failed to copy image url to clipboard: $err\n$stack"); } @@ -293,6 +294,15 @@ class _Thumbnail extends State { case _ThumbnailMenu.markAsNonAd: await _markAsAd(false); break; + case _ThumbnailMenu.copyOriImgUrl: + try { + final uri = api.getFileUrl(_fileId!); + await copyTextToClipboard(uri); + } catch (err, stack) { + _log.warning( + "Failed to copy original image url to clipboard: $err\n$stack"); + } + break; } } @@ -301,6 +311,7 @@ class _Thumbnail extends State { final isLoading = _data == null && _error == null; final isNsfw = widget._pMeta.isNsfw; final isAd = widget._pMeta.isAd; + final i18n = AppLocalizations.of(context)!; if (isLoading && !_isLoading) _fetchData(); _iconSize ??= Theme.of(context).iconTheme.size; final iconSize = MediaQuery.of(context).size.width < 400 @@ -320,13 +331,15 @@ class _Thumbnail extends State { var list = >[ PopupMenuItem( value: _ThumbnailMenu.copyImage, - child: Text(AppLocalizations.of(context)!.copyImage)), + child: Text(i18n.copyImage)), PopupMenuItem( value: _ThumbnailMenu.copyImgUrl, - child: Text(AppLocalizations.of(context)!.copyImgUrl)), + child: Text(i18n.copyImgUrl)), PopupMenuItem( - value: _ThumbnailMenu.saveAs, - child: Text(AppLocalizations.of(context)!.saveAs)), + value: _ThumbnailMenu.copyOriImgUrl, + child: Text(i18n.copyOriImgUrl)), + PopupMenuItem( + value: _ThumbnailMenu.saveAs, child: Text(i18n.saveAs)), ]; if (auth.canEditGallery == true) { list += [ @@ -335,23 +348,24 @@ class _Thumbnail extends State { value: isNsfw ? _ThumbnailMenu.markAsSfw : _ThumbnailMenu.markAsNsfw, - child: Text(isNsfw - ? AppLocalizations.of(context)!.markAsSfw - : AppLocalizations.of(context)!.markAsNsfw)), + child: Text(isNsfw ? i18n.markAsSfw : i18n.markAsNsfw)), PopupMenuItem( value: isAd ? _ThumbnailMenu.markAsNonAd : _ThumbnailMenu.markAsAd, - child: Text(isAd - ? AppLocalizations.of(context)!.markAsNonAd - : AppLocalizations.of(context)!.markAsAd)), + child: Text(isAd ? i18n.markAsNonAd : i18n.markAsAd)), ]; } return list; })); + String? oUri; + if (_fileId != null) { + oUri = api.getFileUrl(_fileId!); + } final timg = _data != null ? ImageWithContextMenu(_data!, uri: _uri, + originalUri: oUri, fileName: _fileName, dir: _dir, isNsfw: @@ -432,7 +446,7 @@ class _Thumbnail extends State { }); }, icon: const Icon(Icons.refresh), - label: Text(AppLocalizations.of(context)!.retry)) + label: Text(i18n.retry)) ]))); } } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9a730f2..25ea6a7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -242,5 +242,6 @@ "logoutConfirm": "Do you want to log out?", "failedLogout": "Failed to log out: ", "createExportZipTask": "Create export as ZIP file task", - "outputDir": "Output directory" + "outputDir": "Output directory", + "copyOriImgUrl": "Copy original image URL to clipboard" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 7295b04..6fa3fe9 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -242,5 +242,6 @@ "logoutConfirm": "是否退出登录", "failedLogout": "退出登录失败:", "createExportZipTask": "新建导出为ZIP文件任务", - "outputDir": "输出文件夹" + "outputDir": "输出文件夹", + "copyOriImgUrl": "复制原图链接到剪贴板" }