From 1af4ed6313172d9d6e5efdd099bccbcab979f10a Mon Sep 17 00:00:00 2001 From: lifegpc Date: Thu, 7 Sep 2023 19:48:27 +0800 Subject: [PATCH] Update --- lib/components/image.dart | 25 ++------------- lib/components/thumbnail.dart | 58 +++++++++++++++++++++++++++++++++-- lib/utils/clipboard.dart | 32 +++++++++++++++++++ 3 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 lib/utils/clipboard.dart diff --git a/lib/components/image.dart b/lib/components/image.dart index b084bd0..f45852b 100644 --- a/lib/components/image.dart +++ b/lib/components/image.dart @@ -2,19 +2,11 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:logging/logging.dart'; -import 'package:super_clipboard/super_clipboard.dart'; import 'package:super_context_menu/super_context_menu.dart'; -import '../platform/to_png_none.dart' - if (dart.library.html) '../platform/to_png.dart'; +import '../utils/clipboard.dart'; final _log = Logger("ImageWithContextMenu"); -enum ImageFmt { - jpg, - png, - gif, -} - class ImageWithContextMenu extends StatelessWidget { const ImageWithContextMenu(this.data, {Key? key, this.uri, this.fmt = ImageFmt.jpg}) @@ -31,16 +23,7 @@ class ImageWithContextMenu extends StatelessWidget { title: AppLocalizations.of(context)!.copyImage, callback: () async { try { - final item = DataWriterItem(); - if (!kIsWeb) { - item.add(fmt == ImageFmt.jpg - ? Formats.jpeg(data) - : Formats.png(data)); - } else { - item.add(Formats.png( - fmt == ImageFmt.jpg ? await jpgToPng(data) : data)); - } - await ClipboardWriter.instance.write([item]); + await copyImageToClipboard(data, fmt); } catch (err) { _log.warning("Failed to copy image to clipboard:", err); } @@ -50,9 +33,7 @@ class ImageWithContextMenu extends StatelessWidget { list.add(MenuAction( title: AppLocalizations.of(context)!.copyImgUrl, callback: () { - final item = DataWriterItem(); - item.add(Formats.plainText(uri!)); - ClipboardWriter.instance.write([item]).catchError((err) { + copyTextToClipboard(uri!).catchError((err) { _log.warning("Failed to copy image to clipboard:", err); }); })); diff --git a/lib/components/thumbnail.dart b/lib/components/thumbnail.dart index d987bc8..38c0b0e 100644 --- a/lib/components/thumbnail.dart +++ b/lib/components/thumbnail.dart @@ -7,6 +7,7 @@ import 'package:logging/logging.dart'; import '../api/client.dart'; import '../api/gallery.dart'; import '../globals.dart'; +import '../utils/clipboard.dart'; import 'image.dart'; final _log = Logger("Thumbnail"); @@ -41,6 +42,11 @@ class Thumbnail extends StatefulWidget { State createState() => _Thumbnail(); } +enum _ThumbnailMenu { + copyImage, + copyImgUrl, +} + class _Thumbnail extends State { Uint8List? _data; bool _isLoading = false; @@ -111,11 +117,52 @@ class _Thumbnail extends State { super.dispose(); } + Future onItemSelected(_ThumbnailMenu v) async { + switch (v) { + case _ThumbnailMenu.copyImage: + try { + copyImageToClipboard(_data!, ImageFmt.jpg); + } catch (err) { + _log.warning("Failed to copy image to clipboard:", err); + } + break; + case _ThumbnailMenu.copyImgUrl: + try { + copyTextToClipboard(_uri!); + } catch (err) { + _log.warning("Failed to copy image url to clipboard:", err); + } + break; + } + } + @override Widget build(BuildContext context) { final isLoading = _data == null && _error == null; final isNsfw = widget._pMeta.isNsfw; if (isLoading && !_isLoading) _fetchData(); + final iconSize = Theme.of(context).iconTheme.size; + final moreVertMenu = Positioned( + right: 0, + top: 0, + width: iconSize, + height: iconSize, + child: PopupMenuButton( + icon: const Icon(Icons.more_vert), + onSelected: (v) { + onItemSelected(v); + }, + itemBuilder: (context) { + var list = >[ + PopupMenuItem( + value: _ThumbnailMenu.copyImage, + child: Text(AppLocalizations.of(context)!.copyImage)), + PopupMenuItem( + value: _ThumbnailMenu.copyImgUrl, + child: Text(AppLocalizations.of(context)!.copyImgUrl)), + ]; + return list; + })); return SizedBox( width: widget.width.toDouble(), height: widget.height.toDouble(), @@ -147,10 +194,17 @@ class _Thumbnail extends State { }, icon: const Icon(Icons.visibility), ), - )) + )), + moreVertMenu ], ) - : ImageWithContextMenu(_data!, uri: _uri) + : Stack(children: [ + SizedBox( + width: widget.width.toDouble(), + height: widget.height.toDouble(), + child: ImageWithContextMenu(_data!, uri: _uri)), + moreVertMenu + ]) : Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/utils/clipboard.dart b/lib/utils/clipboard.dart new file mode 100644 index 0000000..76d5c39 --- /dev/null +++ b/lib/utils/clipboard.dart @@ -0,0 +1,32 @@ +import 'package:flutter/foundation.dart'; +import 'package:super_clipboard/super_clipboard.dart'; +import '../platform/to_png_none.dart' + if (dart.library.html) '../platform/to_png.dart'; + +enum ImageFmt { + jpg, + png, + gif, +} + +Future copyImageToClipboard(Uint8List data, ImageFmt fmt) async { + final item = DataWriterItem(); + if (!kIsWeb) { + item.add(fmt == ImageFmt.jpg + ? Formats.jpeg(data) + : fmt == ImageFmt.gif + ? Formats.gif(data) + : Formats.png(data)); + } else { + item.add(fmt == ImageFmt.gif + ? Formats.gif(data) + : Formats.png(fmt == ImageFmt.jpg ? await jpgToPng(data) : data)); + } + await ClipboardWriter.instance.write([item]); +} + +Future copyTextToClipboard(String text) async { + final item = DataWriterItem(); + item.add(Formats.plainText(text)); + await ClipboardWriter.instance.write([item]); +}