save more images

This commit is contained in:
niuhuan 2021-11-12 13:41:26 +08:00
parent 84f1f05f89
commit 15435bc602
7 changed files with 127 additions and 141 deletions

View File

@ -44,8 +44,14 @@ Future<dynamic> saveImage(String path, BuildContext context) async {
if (folder != null) { if (folder != null) {
future = method.convertImageToJPEG100(path, folder); future = method.convertImageToJPEG100(path, folder);
} }
} else {
defaultToast(context, '暂不支持该平台');
return;
}
if (future == null) {
defaultToast(context, '保存取消');
return;
} }
if (future != null) {
try { try {
await future; await future;
defaultToast(context, '保存成功'); defaultToast(context, '保存成功');
@ -53,9 +59,6 @@ Future<dynamic> saveImage(String path, BuildContext context) async {
print("$e\n$s"); print("$e\n$s");
defaultToast(context, '保存失败'); defaultToast(context, '保存失败');
} }
} else {
defaultToast(context, '暂不支持该平台');
}
} }
/// , /// ,

View File

@ -1,10 +1,10 @@
/// ///
class OssImage { class RemoteImageInfo {
late String originalName; late String originalName;
late String path; late String path;
late String fileServer; late String fileServer;
OssImage.fromJson(Map<String, dynamic> json) { RemoteImageInfo.fromJson(Map<String, dynamic> json) {
this.originalName = json["originalName"]; this.originalName = json["originalName"];
this.path = json["path"]; this.path = json["path"];
this.fileServer = json["fileServer"]; this.fileServer = json["fileServer"];
@ -21,7 +21,7 @@ class BasicUser {
late int exp; late int exp;
late int level; late int level;
late List<String> characters; late List<String> characters;
late OssImage avatar; late RemoteImageInfo avatar;
BasicUser.fromJson(Map<String, dynamic> json) { BasicUser.fromJson(Map<String, dynamic> json) {
this.id = json["_id"]; this.id = json["_id"];
@ -34,7 +34,8 @@ class BasicUser {
this.characters = json["characters"] == null this.characters = json["characters"] == null
? [] ? []
: List.of(json["characters"]).map((e) => "$e").toList(); : 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 id;
late String title; late String title;
late String description; late String description;
late OssImage thumb; late RemoteImageInfo thumb;
late bool isWeb; late bool isWeb;
late bool active; late bool active;
late String link; late String link;
@ -84,7 +85,7 @@ class Category {
this.id = json["_id"]; this.id = json["_id"];
this.title = json["title"]; this.title = json["title"];
this.description = json["description"]; this.description = json["description"];
this.thumb = OssImage.fromJson(json["thumb"]); this.thumb = RemoteImageInfo.fromJson(json["thumb"]);
this.isWeb = json["isWeb"]; this.isWeb = json["isWeb"];
this.active = json["active"]; this.active = json["active"];
this.link = json["link"]; this.link = json["link"];
@ -112,7 +113,7 @@ class ComicSimple {
late int epsCount; late int epsCount;
late bool finished; late bool finished;
late List<String> categories; late List<String> categories;
late OssImage thumb; late RemoteImageInfo thumb;
late int likesCount; late int likesCount;
ComicSimple.fromJson(Map<String, dynamic> json) { ComicSimple.fromJson(Map<String, dynamic> json) {
@ -123,7 +124,7 @@ class ComicSimple {
this.epsCount = json["epsCount"]; this.epsCount = json["epsCount"];
this.finished = json["finished"]; this.finished = json["finished"];
this.categories = List<String>.from(json["categories"]); this.categories = List<String>.from(json["categories"]);
this.thumb = OssImage.fromJson(json["thumb"]); this.thumb = RemoteImageInfo.fromJson(json["thumb"]);
this.likesCount = json["likesCount"]; this.likesCount = json["likesCount"];
} }
} }
@ -212,11 +213,11 @@ class PicturePage extends Page {
/// ///
class Picture { class Picture {
late String id; late String id;
late OssImage media; late RemoteImageInfo media;
Picture.fromJson(Map<String, dynamic> json) { Picture.fromJson(Map<String, dynamic> json) {
this.id = json["_id"]; 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 id;
late String title; late String title;
late String version; late String version;
late OssImage icon; late RemoteImageInfo icon;
late String publisher; late String publisher;
late bool adult; late bool adult;
late bool suggest; late bool suggest;
@ -516,7 +517,7 @@ class GameSimple {
this.id = json["_id"]; this.id = json["_id"];
this.title = json["title"]; this.title = json["title"];
this.version = json["version"]; this.version = json["version"];
this.icon = OssImage.fromJson(json["icon"]); this.icon = RemoteImageInfo.fromJson(json["icon"]);
this.publisher = json["publisher"]; this.publisher = json["publisher"];
this.adult = json["adult"]; this.adult = json["adult"];
this.suggest = json["suggest"]; this.suggest = json["suggest"];
@ -531,7 +532,7 @@ class GameInfo extends GameSimple {
late String description; late String description;
late String updateContent; late String updateContent;
late String videoLink; late String videoLink;
late List<OssImage> screenshots; late List<RemoteImageInfo> screenshots;
late int commentsCount; late int commentsCount;
late int downloadsCount; late int downloadsCount;
late bool isLiked; late bool isLiked;
@ -548,7 +549,7 @@ class GameInfo extends GameSimple {
this.videoLink = json["videoLink"]; this.videoLink = json["videoLink"];
this.screenshots = List.of(json["screenshots"]) this.screenshots = List.of(json["screenshots"])
.map((e) => Map<String, dynamic>.of(e)) .map((e) => Map<String, dynamic>.of(e))
.map((e) => OssImage.fromJson(e)) .map((e) => RemoteImageInfo.fromJson(e))
.toList(); .toList();
this.commentsCount = json["commentsCount"]; this.commentsCount = json["commentsCount"];
this.downloadsCount = json["downloadsCount"]; this.downloadsCount = json["downloadsCount"];
@ -658,8 +659,9 @@ class GameCommentChildrenPage extends Page {
: super.fromJson(json) { : super.fromJson(json) {
this.docs = []; this.docs = [];
if (json["docs"] != null) { if (json["docs"] != null) {
docs.addAll( docs.addAll(List.of(json["docs"])
List.of(json["docs"]).map((e) => GameCommentChild.fromJson(e)).toList()); .map((e) => GameCommentChild.fromJson(e))
.toList());
} }
} }
} }

View File

@ -40,15 +40,15 @@ class ComicReaderScreen extends StatefulWidget {
class _ComicReaderScreenState extends State<ComicReaderScreen> { class _ComicReaderScreenState extends State<ComicReaderScreen> {
late Ep _ep; late Ep _ep;
late bool _fullScreen = false; late bool _fullScreen = false;
late Future<List<OssImage>> _future; late Future<List<RemoteImageInfo>> _future;
int? _lastChangeRank; int? _lastChangeRank;
bool _replacement = false; bool _replacement = false;
Future<List<OssImage>> _load() async { Future<List<RemoteImageInfo>> _load() async {
if (widget.initPictureRank == null) { if (widget.initPictureRank == null) {
await method.storeViewEp(widget.comicInfo.id, _ep.order, _ep.title, 1); await method.storeViewEp(widget.comicInfo.id, _ep.order, _ep.title, 1);
} }
List<OssImage> list = []; List<RemoteImageInfo> list = [];
var _needLoadPage = 0; var _needLoadPage = 0;
late PicturePage page; late PicturePage page;
do { do {
@ -165,7 +165,7 @@ class _ComicReaderScreenState extends State<ComicReaderScreen> {
}); });
}, },
successBuilder: successBuilder:
(BuildContext context, AsyncSnapshot<List<OssImage>> snapshot) { (BuildContext context, AsyncSnapshot<List<RemoteImageInfo>> snapshot) {
return ImageReader( return ImageReader(
ImageReaderStruct( ImageReaderStruct(
images: snapshot.data! images: snapshot.data!

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view.dart';
import 'package:pikapika/basic/Common.dart';
import 'package:pikapika/basic/Cross.dart'; import 'package:pikapika/basic/Cross.dart';
import 'package:pikapika/screens/components/Images.dart'; import 'package:pikapika/screens/components/Images.dart';
@ -13,9 +14,20 @@ class FilePhotoViewScreen extends StatelessWidget {
Widget build(BuildContext context) => Scaffold( Widget build(BuildContext context) => Scaffold(
body: Stack( body: Stack(
children: [ children: [
PhotoView( GestureDetector(
onLongPress: () async {
String? choose =
await chooseListDialog(context, '请选择', ['保存图片']);
switch (choose) {
case '保存图片':
saveImage(filePath, context);
break;
}
},
child: PhotoView(
imageProvider: ResourceFileImageProvider(filePath), imageProvider: ResourceFileImageProvider(filePath),
), ),
),
InkWell( InkWell(
onTap: () => Navigator.of(context).pop(), onTap: () => Navigator.of(context).pop(),
child: Container( child: Container(
@ -31,26 +43,6 @@ class FilePhotoViewScreen extends StatelessWidget {
child: Icon(Icons.keyboard_backspace, color: Colors.white), 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),
),
),
),
], ],
), ),
); );

View File

@ -8,28 +8,12 @@ const double _avatarMargin = 5;
const double _avatarBorderSize = 1.5; const double _avatarBorderSize = 1.5;
// //
class Avatar extends StatefulWidget { class Avatar extends StatelessWidget {
final OssImage avatarImage; final RemoteImageInfo avatarImage;
final double size; final double size;
const Avatar(this.avatarImage, {this.size = 50}); 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
@ -43,34 +27,14 @@ class _AvatarState extends State<Avatar> {
width: _avatarBorderSize, width: _avatarBorderSize,
)), )),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(widget.size)), borderRadius: BorderRadius.all(Radius.circular(this.size)),
child: _image(), 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),
);
},
);
}
} }

View File

@ -554,26 +554,11 @@ class _WebToonReaderImageState extends State<_WebToonReaderImage> {
return buildLoading(widget.size.width, widget.size.height); return buildLoading(widget.size.width, widget.size.height);
} }
var data = snapshot.data!; var data = snapshot.data!;
return GestureDetector( return buildFile(
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(
data.finalPath, data.finalPath,
widget.size.width, widget.size.width,
widget.size.height, widget.size.height,
), context: context,
); );
}, },
); );
@ -726,7 +711,8 @@ class _GalleryReaderState extends State<_GalleryReader> {
); );
} }
return PhotoViewGalleryPageOptions( return PhotoViewGalleryPageOptions(
imageProvider: ResourceRemoteImageProvider(item.fileServer, item.path), imageProvider:
ResourceRemoteImageProvider(item.fileServer, item.path),
errorBuilder: (b, e, s) { errorBuilder: (b, e, s) {
print("$e,$s"); print("$e,$s");
return LayoutBuilder( return LayoutBuilder(

View File

@ -2,12 +2,16 @@ import 'dart:typed_data';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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:pikapika/basic/Method.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:pikapika/basic/config/ConvertToPNG.dart'; import 'package:pikapika/basic/config/ConvertToPNG.dart';
import 'dart:io'; import 'dart:io';
import 'dart:ui' as ui show Codec; import 'dart:ui' as ui show Codec;
import '../FilePhotoViewScreen.dart';
Future<Uint8List> _loadImageFile(String path) { Future<Uint8List> _loadImageFile(String path) {
if (convertToPNG()) { if (convertToPNG()) {
return method.convertToPNG(path); return method.convertToPNG(path);
@ -180,7 +184,12 @@ class _DownloadImageState extends State<DownloadImage> {
@override @override
Widget build(BuildContext context) { 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) { if (_mock) {
return buildMock(widget.width, widget.height); return buildMock(widget.width, widget.height);
} }
return pathFutureImage(_future, widget.width, widget.height, return pathFutureImage(
fit: widget.fit); _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, Widget buildSvg(String source, double? width, double? height,
{Color? color, double? margin}) { {Color? color, double? margin}) {
return Container( var widget = Container(
width: width, width: width,
height: height, height: height,
padding: margin != null ? EdgeInsets.all(10) : null, 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) { Widget buildMock(double? width, double? height) {
return Container( var widget = Container(
width: width, width: width,
height: height, height: height,
padding: EdgeInsets.all(10), 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) { Widget buildError(double? width, double? height) {
@ -292,8 +331,8 @@ Widget buildLoading(double? width, double? height) {
} }
Widget buildFile(String file, double? width, double? height, Widget buildFile(String file, double? width, double? height,
{BoxFit fit = BoxFit.cover}) { {BoxFit fit = BoxFit.cover, BuildContext? context}) {
return Image( var image = Image(
image: ResourceFileImageProvider(file), image: ResourceFileImageProvider(file),
width: width, width: width,
height: height, height: height,
@ -304,21 +343,21 @@ Widget buildFile(String file, double? width, double? height,
}, },
fit: fit, 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, child: image,
{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);
});
} }