mirror of
https://github.com/lifegpc/eh_downloader_flutter.git
synced 2026-07-08 01:30:28 +08:00
Update context menu for image
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
@@ -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),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user