save more images
This commit is contained in:
parent
84f1f05f89
commit
15435bc602
|
@ -44,8 +44,14 @@ Future<dynamic> saveImage(String path, BuildContext context) async {
|
|||
if (folder != null) {
|
||||
future = method.convertImageToJPEG100(path, folder);
|
||||
}
|
||||
} else {
|
||||
defaultToast(context, '暂不支持该平台');
|
||||
return;
|
||||
}
|
||||
if (future == null) {
|
||||
defaultToast(context, '保存取消');
|
||||
return;
|
||||
}
|
||||
if (future != null) {
|
||||
try {
|
||||
await future;
|
||||
defaultToast(context, '保存成功');
|
||||
|
@ -53,9 +59,6 @@ Future<dynamic> saveImage(String path, BuildContext context) async {
|
|||
print("$e\n$s");
|
||||
defaultToast(context, '保存失败');
|
||||
}
|
||||
} else {
|
||||
defaultToast(context, '暂不支持该平台');
|
||||
}
|
||||
}
|
||||
|
||||
/// 保存图片且保持静默, 用于批量导出到相册
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/// 图片
|
||||
class OssImage {
|
||||
class RemoteImageInfo {
|
||||
late String originalName;
|
||||
late String path;
|
||||
late String fileServer;
|
||||
|
||||
OssImage.fromJson(Map<String, dynamic> json) {
|
||||
RemoteImageInfo.fromJson(Map<String, dynamic> json) {
|
||||
this.originalName = json["originalName"];
|
||||
this.path = json["path"];
|
||||
this.fileServer = json["fileServer"];
|
||||
|
@ -21,7 +21,7 @@ class BasicUser {
|
|||
late int exp;
|
||||
late int level;
|
||||
late List<String> characters;
|
||||
late OssImage avatar;
|
||||
late RemoteImageInfo avatar;
|
||||
|
||||
BasicUser.fromJson(Map<String, dynamic> json) {
|
||||
this.id = json["_id"];
|
||||
|
@ -34,7 +34,8 @@ class BasicUser {
|
|||
this.characters = json["characters"] == null
|
||||
? []
|
||||
: List.of(json["characters"]).map((e) => "$e").toList();
|
||||
this.avatar = OssImage.fromJson(Map<String, dynamic>.of(json["avatar"]));
|
||||
this.avatar =
|
||||
RemoteImageInfo.fromJson(Map<String, dynamic>.of(json["avatar"]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +76,7 @@ class Category {
|
|||
late String id;
|
||||
late String title;
|
||||
late String description;
|
||||
late OssImage thumb;
|
||||
late RemoteImageInfo thumb;
|
||||
late bool isWeb;
|
||||
late bool active;
|
||||
late String link;
|
||||
|
@ -84,7 +85,7 @@ class Category {
|
|||
this.id = json["_id"];
|
||||
this.title = json["title"];
|
||||
this.description = json["description"];
|
||||
this.thumb = OssImage.fromJson(json["thumb"]);
|
||||
this.thumb = RemoteImageInfo.fromJson(json["thumb"]);
|
||||
this.isWeb = json["isWeb"];
|
||||
this.active = json["active"];
|
||||
this.link = json["link"];
|
||||
|
@ -112,7 +113,7 @@ class ComicSimple {
|
|||
late int epsCount;
|
||||
late bool finished;
|
||||
late List<String> categories;
|
||||
late OssImage thumb;
|
||||
late RemoteImageInfo thumb;
|
||||
late int likesCount;
|
||||
|
||||
ComicSimple.fromJson(Map<String, dynamic> json) {
|
||||
|
@ -123,7 +124,7 @@ class ComicSimple {
|
|||
this.epsCount = json["epsCount"];
|
||||
this.finished = json["finished"];
|
||||
this.categories = List<String>.from(json["categories"]);
|
||||
this.thumb = OssImage.fromJson(json["thumb"]);
|
||||
this.thumb = RemoteImageInfo.fromJson(json["thumb"]);
|
||||
this.likesCount = json["likesCount"];
|
||||
}
|
||||
}
|
||||
|
@ -212,11 +213,11 @@ class PicturePage extends Page {
|
|||
/// 漫画图片信息
|
||||
class Picture {
|
||||
late String id;
|
||||
late OssImage media;
|
||||
late RemoteImageInfo media;
|
||||
|
||||
Picture.fromJson(Map<String, dynamic> json) {
|
||||
this.id = json["_id"];
|
||||
this.media = OssImage.fromJson(json["media"]);
|
||||
this.media = RemoteImageInfo.fromJson(json["media"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -504,7 +505,7 @@ class GameSimple {
|
|||
late String id;
|
||||
late String title;
|
||||
late String version;
|
||||
late OssImage icon;
|
||||
late RemoteImageInfo icon;
|
||||
late String publisher;
|
||||
late bool adult;
|
||||
late bool suggest;
|
||||
|
@ -516,7 +517,7 @@ class GameSimple {
|
|||
this.id = json["_id"];
|
||||
this.title = json["title"];
|
||||
this.version = json["version"];
|
||||
this.icon = OssImage.fromJson(json["icon"]);
|
||||
this.icon = RemoteImageInfo.fromJson(json["icon"]);
|
||||
this.publisher = json["publisher"];
|
||||
this.adult = json["adult"];
|
||||
this.suggest = json["suggest"];
|
||||
|
@ -531,7 +532,7 @@ class GameInfo extends GameSimple {
|
|||
late String description;
|
||||
late String updateContent;
|
||||
late String videoLink;
|
||||
late List<OssImage> screenshots;
|
||||
late List<RemoteImageInfo> screenshots;
|
||||
late int commentsCount;
|
||||
late int downloadsCount;
|
||||
late bool isLiked;
|
||||
|
@ -548,7 +549,7 @@ class GameInfo extends GameSimple {
|
|||
this.videoLink = json["videoLink"];
|
||||
this.screenshots = List.of(json["screenshots"])
|
||||
.map((e) => Map<String, dynamic>.of(e))
|
||||
.map((e) => OssImage.fromJson(e))
|
||||
.map((e) => RemoteImageInfo.fromJson(e))
|
||||
.toList();
|
||||
this.commentsCount = json["commentsCount"];
|
||||
this.downloadsCount = json["downloadsCount"];
|
||||
|
@ -658,8 +659,9 @@ class GameCommentChildrenPage extends Page {
|
|||
: super.fromJson(json) {
|
||||
this.docs = [];
|
||||
if (json["docs"] != null) {
|
||||
docs.addAll(
|
||||
List.of(json["docs"]).map((e) => GameCommentChild.fromJson(e)).toList());
|
||||
docs.addAll(List.of(json["docs"])
|
||||
.map((e) => GameCommentChild.fromJson(e))
|
||||
.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,15 +40,15 @@ class ComicReaderScreen extends StatefulWidget {
|
|||
class _ComicReaderScreenState extends State<ComicReaderScreen> {
|
||||
late Ep _ep;
|
||||
late bool _fullScreen = false;
|
||||
late Future<List<OssImage>> _future;
|
||||
late Future<List<RemoteImageInfo>> _future;
|
||||
int? _lastChangeRank;
|
||||
bool _replacement = false;
|
||||
|
||||
Future<List<OssImage>> _load() async {
|
||||
Future<List<RemoteImageInfo>> _load() async {
|
||||
if (widget.initPictureRank == null) {
|
||||
await method.storeViewEp(widget.comicInfo.id, _ep.order, _ep.title, 1);
|
||||
}
|
||||
List<OssImage> list = [];
|
||||
List<RemoteImageInfo> list = [];
|
||||
var _needLoadPage = 0;
|
||||
late PicturePage page;
|
||||
do {
|
||||
|
@ -165,7 +165,7 @@ class _ComicReaderScreenState extends State<ComicReaderScreen> {
|
|||
});
|
||||
},
|
||||
successBuilder:
|
||||
(BuildContext context, AsyncSnapshot<List<OssImage>> snapshot) {
|
||||
(BuildContext context, AsyncSnapshot<List<RemoteImageInfo>> snapshot) {
|
||||
return ImageReader(
|
||||
ImageReaderStruct(
|
||||
images: snapshot.data!
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:pikapika/basic/Common.dart';
|
||||
import 'package:pikapika/basic/Cross.dart';
|
||||
import 'package:pikapika/screens/components/Images.dart';
|
||||
|
||||
|
@ -13,9 +14,20 @@ class FilePhotoViewScreen extends StatelessWidget {
|
|||
Widget build(BuildContext context) => Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
PhotoView(
|
||||
GestureDetector(
|
||||
onLongPress: () async {
|
||||
String? choose =
|
||||
await chooseListDialog(context, '请选择', ['保存图片']);
|
||||
switch (choose) {
|
||||
case '保存图片':
|
||||
saveImage(filePath, context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
child: PhotoView(
|
||||
imageProvider: ResourceFileImageProvider(filePath),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: Container(
|
||||
|
@ -31,26 +43,6 @@ class FilePhotoViewScreen extends StatelessWidget {
|
|||
child: Icon(Icons.keyboard_backspace, color: Colors.white),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
saveImage(filePath, context);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(top: 30),
|
||||
padding: EdgeInsets.only(left: 4, right: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(.75),
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(8),
|
||||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Icon(Icons.save, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -8,28 +8,12 @@ const double _avatarMargin = 5;
|
|||
const double _avatarBorderSize = 1.5;
|
||||
|
||||
// 头像
|
||||
class Avatar extends StatefulWidget {
|
||||
final OssImage avatarImage;
|
||||
class Avatar extends StatelessWidget {
|
||||
final RemoteImageInfo avatarImage;
|
||||
final double size;
|
||||
|
||||
const Avatar(this.avatarImage, {this.size = 50});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AvatarState();
|
||||
}
|
||||
|
||||
class _AvatarState extends State<Avatar> {
|
||||
late Future<String> _future = _load();
|
||||
|
||||
Future<String> _load() async {
|
||||
if (widget.avatarImage.fileServer == '') {
|
||||
return '';
|
||||
}
|
||||
return method
|
||||
.remoteImageData(widget.avatarImage.fileServer, widget.avatarImage.path)
|
||||
.then((value) => value.finalPath);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
@ -43,34 +27,14 @@ class _AvatarState extends State<Avatar> {
|
|||
width: _avatarBorderSize,
|
||||
)),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(widget.size)),
|
||||
child: _image(),
|
||||
borderRadius: BorderRadius.all(Radius.circular(this.size)),
|
||||
child: RemoteImage(
|
||||
fileServer: this.avatarImage.fileServer,
|
||||
path: this.avatarImage.path,
|
||||
width: this.size,
|
||||
height: this.size,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _image() {
|
||||
return FutureBuilder(
|
||||
future: _future,
|
||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
return buildError(widget.size, widget.size);
|
||||
}
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return buildLoading(widget.size, widget.size);
|
||||
}
|
||||
if (snapshot.data == '' || snapshot.data == null) {
|
||||
return buildMock(widget.size, widget.size);
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => FilePhotoViewScreen(snapshot.data!),
|
||||
));
|
||||
},
|
||||
child: buildFile(snapshot.data!, widget.size, widget.size),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -554,26 +554,11 @@ class _WebToonReaderImageState extends State<_WebToonReaderImage> {
|
|||
return buildLoading(widget.size.width, widget.size.height);
|
||||
}
|
||||
var data = snapshot.data!;
|
||||
return GestureDetector(
|
||||
onLongPress: () async {
|
||||
String? choose =
|
||||
await chooseListDialog(context, '请选择', ['预览图片', '保存图片']);
|
||||
switch (choose) {
|
||||
case '预览图片':
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => FilePhotoViewScreen(data.finalPath),
|
||||
));
|
||||
break;
|
||||
case '保存图片':
|
||||
saveImage(data.finalPath, context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
child: buildFile(
|
||||
return buildFile(
|
||||
data.finalPath,
|
||||
widget.size.width,
|
||||
widget.size.height,
|
||||
),
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -726,7 +711,8 @@ class _GalleryReaderState extends State<_GalleryReader> {
|
|||
);
|
||||
}
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: ResourceRemoteImageProvider(item.fileServer, item.path),
|
||||
imageProvider:
|
||||
ResourceRemoteImageProvider(item.fileServer, item.path),
|
||||
errorBuilder: (b, e, s) {
|
||||
print("$e,$s");
|
||||
return LayoutBuilder(
|
||||
|
|
|
@ -2,12 +2,16 @@ import 'dart:typed_data';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:pikapika/basic/Common.dart';
|
||||
import 'package:pikapika/basic/Cross.dart';
|
||||
import 'package:pikapika/basic/Method.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:pikapika/basic/config/ConvertToPNG.dart';
|
||||
import 'dart:io';
|
||||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import '../FilePhotoViewScreen.dart';
|
||||
|
||||
Future<Uint8List> _loadImageFile(String path) {
|
||||
if (convertToPNG()) {
|
||||
return method.convertToPNG(path);
|
||||
|
@ -180,7 +184,12 @@ class _DownloadImageState extends State<DownloadImage> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return pathFutureImage(_future, widget.width, widget.height);
|
||||
return pathFutureImage(
|
||||
_future,
|
||||
widget.width,
|
||||
widget.height,
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,16 +234,44 @@ class _RemoteImageState extends State<RemoteImage> {
|
|||
if (_mock) {
|
||||
return buildMock(widget.width, widget.height);
|
||||
}
|
||||
return pathFutureImage(_future, widget.width, widget.height,
|
||||
fit: widget.fit);
|
||||
return pathFutureImage(
|
||||
_future,
|
||||
widget.width,
|
||||
widget.height,
|
||||
fit: widget.fit,
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget pathFutureImage(Future<String> future, double? width, double? height,
|
||||
{BoxFit fit = BoxFit.cover, BuildContext? context}) {
|
||||
return FutureBuilder(
|
||||
future: future,
|
||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
print("${snapshot.error}");
|
||||
print("${snapshot.stackTrace}");
|
||||
return buildError(width, height);
|
||||
}
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return buildLoading(width, height);
|
||||
}
|
||||
return buildFile(
|
||||
snapshot.data!,
|
||||
width,
|
||||
height,
|
||||
fit: fit,
|
||||
context: context,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 通用方法
|
||||
|
||||
Widget buildSvg(String source, double? width, double? height,
|
||||
{Color? color, double? margin}) {
|
||||
return Container(
|
||||
var widget = Container(
|
||||
width: width,
|
||||
height: height,
|
||||
padding: margin != null ? EdgeInsets.all(10) : null,
|
||||
|
@ -247,10 +284,11 @@ Widget buildSvg(String source, double? width, double? height,
|
|||
),
|
||||
),
|
||||
);
|
||||
return GestureDetector(onLongPress: () {}, child: widget);
|
||||
}
|
||||
|
||||
Widget buildMock(double? width, double? height) {
|
||||
return Container(
|
||||
var widget = Container(
|
||||
width: width,
|
||||
height: height,
|
||||
padding: EdgeInsets.all(10),
|
||||
|
@ -263,6 +301,7 @@ Widget buildMock(double? width, double? height) {
|
|||
),
|
||||
),
|
||||
);
|
||||
return GestureDetector(onLongPress: () {}, child: widget);
|
||||
}
|
||||
|
||||
Widget buildError(double? width, double? height) {
|
||||
|
@ -292,8 +331,8 @@ Widget buildLoading(double? width, double? height) {
|
|||
}
|
||||
|
||||
Widget buildFile(String file, double? width, double? height,
|
||||
{BoxFit fit = BoxFit.cover}) {
|
||||
return Image(
|
||||
{BoxFit fit = BoxFit.cover, BuildContext? context}) {
|
||||
var image = Image(
|
||||
image: ResourceFileImageProvider(file),
|
||||
width: width,
|
||||
height: height,
|
||||
|
@ -304,21 +343,21 @@ Widget buildFile(String file, double? width, double? height,
|
|||
},
|
||||
fit: fit,
|
||||
);
|
||||
if (context == null) return image;
|
||||
return GestureDetector(
|
||||
onLongPress: () async {
|
||||
String? choose = await chooseListDialog(context, '请选择', ['预览图片', '保存图片']);
|
||||
switch (choose) {
|
||||
case '预览图片':
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => FilePhotoViewScreen(file),
|
||||
));
|
||||
break;
|
||||
case '保存图片':
|
||||
saveImage(file, context);
|
||||
break;
|
||||
}
|
||||
|
||||
Widget pathFutureImage(Future<String> future, double? width, double? height,
|
||||
{BoxFit fit = BoxFit.cover}) {
|
||||
return FutureBuilder(
|
||||
future: future,
|
||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
print("${snapshot.error}");
|
||||
print("${snapshot.stackTrace}");
|
||||
return buildError(width, height);
|
||||
}
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return buildLoading(width, height);
|
||||
}
|
||||
return buildFile(snapshot.data!, width, height, fit: fit);
|
||||
});
|
||||
},
|
||||
child: image,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue