This commit is contained in:
2023-09-07 19:48:27 +08:00
parent 01764d005f
commit 1af4ed6313
3 changed files with 91 additions and 24 deletions

View File

@@ -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);
});
}));

View File

@@ -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<Thumbnail> createState() => _Thumbnail();
}
enum _ThumbnailMenu {
copyImage,
copyImgUrl,
}
class _Thumbnail extends State<Thumbnail> {
Uint8List? _data;
bool _isLoading = false;
@@ -111,11 +117,52 @@ class _Thumbnail extends State<Thumbnail> {
super.dispose();
}
Future<void> 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 = <PopupMenuEntry<_ThumbnailMenu>>[
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<Thumbnail> {
},
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,

32
lib/utils/clipboard.dart Normal file
View File

@@ -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<void> 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<void> copyTextToClipboard(String text) async {
final item = DataWriterItem();
item.add(Formats.plainText(text));
await ClipboardWriter.instance.write([item]);
}