Update context menu for image

This commit is contained in:
2023-09-09 13:52:27 +08:00
parent 4ec4d61656
commit 6a44090e24
7 changed files with 57 additions and 14 deletions

View File

@@ -17,7 +17,9 @@ class GalleryBasicInfo extends StatelessWidget {
child: Column(children: [ child: Column(children: [
Expanded( Expanded(
child: Row(children: [ child: Row(children: [
Expanded(flex: 2, child: Thumbnail(firstPage, fileId: fileId)), Expanded(
flex: 2,
child: Thumbnail(firstPage, fileId: fileId, gid: gMeta.gid)),
Expanded( Expanded(
flex: 3, flex: 3,
child: Column( child: Column(

View File

@@ -67,9 +67,12 @@ class _GalleryInfo extends State<GalleryInfo> with ThemeModeWidget {
fileId: firstFileId, controller: controller), fileId: firstFileId, controller: controller),
]), ]),
), ),
ThumbnailGridView(widget.gData.pages, ThumbnailGridView(
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: useMobile ? 2 : 5), widget.gData.pages,
files: widget.files), SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: useMobile ? 2 : 5),
files: widget.files,
gid: widget.gData.meta.gid),
], ],
); );
} }

View File

@@ -21,7 +21,9 @@ class GalleryInfoDesktop extends StatelessWidget {
width: 1280, width: 1280,
child: Row(children: [ child: Row(children: [
Expanded( Expanded(
flex: 3, child: Thumbnail(gData.pages.first, fileId: fileId)), flex: 3,
child: Thumbnail(gData.pages.first,
fileId: fileId, gid: gData.meta.gid)),
Expanded( Expanded(
flex: 7, flex: 7,
child: Column( child: Column(

View File

@@ -3,17 +3,20 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:super_context_menu/super_context_menu.dart'; import 'package:super_context_menu/super_context_menu.dart';
import '../globals.dart';
import '../utils/clipboard.dart'; import '../utils/clipboard.dart';
final _log = Logger("ImageWithContextMenu"); final _log = Logger("ImageWithContextMenu");
class ImageWithContextMenu extends StatelessWidget { class ImageWithContextMenu extends StatelessWidget {
const ImageWithContextMenu(this.data, const ImageWithContextMenu(this.data,
{Key? key, this.uri, this.fmt = ImageFmt.jpg}) {Key? key, this.uri, this.dir, this.fileName, this.fmt = ImageFmt.jpg})
: super(key: key); : super(key: key);
final Uint8List data; final Uint8List data;
final String? uri; final String? uri;
final ImageFmt fmt; final ImageFmt fmt;
final String? fileName;
final String? dir;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ContextMenuWidget( return ContextMenuWidget(
@@ -38,6 +41,18 @@ class ImageWithContextMenu extends StatelessWidget {
}); });
})); }));
} }
if (fileName != null) {
list.add(MenuAction(
title: AppLocalizations.of(context)!.saveAs,
callback: () {
try {
platformPath.saveFile(fileName!, fmt.toMimeType(), data,
dir: dir ?? "");
} catch (err) {
_log.warning("Failed to save image:", err);
}
}));
}
return Menu(children: list); return Menu(children: list);
}, },
child: Image.memory(data)); child: Image.memory(data));

View File

@@ -8,6 +8,7 @@ import 'package:path/path.dart';
import '../api/client.dart'; import '../api/client.dart';
import '../api/gallery.dart'; import '../api/gallery.dart';
import '../globals.dart'; import '../globals.dart';
import '../utils.dart';
import '../utils/clipboard.dart'; import '../utils/clipboard.dart';
import 'image.dart'; import 'image.dart';
@@ -15,7 +16,7 @@ final _log = Logger("Thumbnail");
class Thumbnail extends StatefulWidget { class Thumbnail extends StatefulWidget {
const Thumbnail(ExtendedPMeta pMeta, const Thumbnail(ExtendedPMeta pMeta,
{Key? key, int? max, int? width, int? height, int? fileId}) {Key? key, int? max, int? width, int? height, int? fileId, this.gid})
: _pMeta = pMeta, : _pMeta = pMeta,
_max = max ?? 1200, _max = max ?? 1200,
_width = width, _width = width,
@@ -27,6 +28,7 @@ class Thumbnail extends StatefulWidget {
final int? _width; final int? _width;
final int? _height; final int? _height;
final int? _fileId; final int? _fileId;
final int? gid;
int get height => _height != null int get height => _height != null
? _height! ? _height!
@@ -58,6 +60,7 @@ class _Thumbnail extends State<Thumbnail> {
String? _uri; String? _uri;
CancelToken? _cancel; CancelToken? _cancel;
String? _fileName; String? _fileName;
String _dir = "";
Future<void> _fetchData() async { Future<void> _fetchData() async {
try { try {
_cancel = CancelToken(); _cancel = CancelToken();
@@ -110,6 +113,7 @@ class _Thumbnail extends State<Thumbnail> {
_showNsfw = false; _showNsfw = false;
_uri = null; _uri = null;
_fileName = "${basenameWithoutExtension(widget._pMeta.name)}_thumb"; _fileName = "${basenameWithoutExtension(widget._pMeta.name)}_thumb";
_dir = isAndroid && widget.gid != null ? widget.gid!.toString() : "";
super.initState(); super.initState();
} }
@@ -139,7 +143,8 @@ class _Thumbnail extends State<Thumbnail> {
break; break;
case _ThumbnailMenu.saveAs: case _ThumbnailMenu.saveAs:
try { try {
await platformPath.saveFile(_fileName!, "image/jpeg", _data!); await platformPath.saveFile(_fileName!, "image/jpeg", _data!,
dir: _dir);
} catch (err) { } catch (err) {
_log.warning("Failed to save image:", err); _log.warning("Failed to save image:", err);
} }
@@ -194,8 +199,10 @@ class _Thumbnail extends State<Thumbnail> {
sigmaX: 10, sigmaX: 10,
sigmaY: 10, sigmaY: 10,
tileMode: TileMode.decal), tileMode: TileMode.decal),
child: child: ImageWithContextMenu(_data!,
ImageWithContextMenu(_data!, uri: _uri))), uri: _uri,
fileName: _fileName,
dir: _dir))),
SizedBox( SizedBox(
width: widget.width.toDouble(), width: widget.width.toDouble(),
height: widget.height.toDouble(), height: widget.height.toDouble(),
@@ -216,7 +223,8 @@ class _Thumbnail extends State<Thumbnail> {
SizedBox( SizedBox(
width: widget.width.toDouble(), width: widget.width.toDouble(),
height: widget.height.toDouble(), height: widget.height.toDouble(),
child: ImageWithContextMenu(_data!, uri: _uri)), child: ImageWithContextMenu(_data!,
uri: _uri, fileName: _fileName, dir: _dir)),
moreVertMenu moreVertMenu
]) ])
: Center( : Center(

View File

@@ -5,9 +5,11 @@ import '../globals.dart';
import 'thumbnail.dart'; import 'thumbnail.dart';
class ThumbnailGridView extends StatelessWidget { class ThumbnailGridView extends StatelessWidget {
const ThumbnailGridView(this.pages, this.gridDelegate, {Key? key, this.files}) const ThumbnailGridView(this.pages, this.gridDelegate,
{Key? key, this.files, this.gid})
: super(key: key); : super(key: key);
final List<ExtendedPMeta> pages; final List<ExtendedPMeta> pages;
final int? gid;
final EhFiles? files; final EhFiles? files;
final SliverGridDelegate gridDelegate; final SliverGridDelegate gridDelegate;
@@ -24,7 +26,7 @@ class ThumbnailGridView extends StatelessWidget {
files != null ? files!.files[page.token]!.first.id : null; files != null ? files!.files[page.token]!.first.id : null;
return Container( return Container(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: Thumbnail(page, fileId: fileId)); child: Thumbnail(page, fileId: fileId, gid: gid));
}); });
} }
} }

View File

@@ -6,7 +6,18 @@ import '../platform/to_png_none.dart'
enum ImageFmt { enum ImageFmt {
jpg, jpg,
png, png,
gif, gif;
String toMimeType() {
switch (this) {
case ImageFmt.jpg:
return "image/jpeg";
case ImageFmt.png:
return "image/png";
case ImageFmt.gif:
return "image/gif";
}
}
} }
Future<void> copyImageToClipboard(Uint8List data, ImageFmt fmt) async { Future<void> copyImageToClipboard(Uint8List data, ImageFmt fmt) async {