page view

This commit is contained in:
wgh19
2024-05-16 15:35:58 +08:00
parent 8c57dd30fb
commit a8ebebfedd
2 changed files with 147 additions and 76 deletions

View File

@@ -76,6 +76,19 @@ class _IllustPageState extends State<IllustPage> {
}); });
} }
void openImage(int index) {
var images = <String>[];
for(var i = 0; i < widget.illust.images.length; i++) {
var downloadFile = DownloadManager().getImage(widget.illust.id, i);
if(downloadFile != null) {
images.add("file://${downloadFile.path}");
} else {
images.add(widget.illust.images[i].original);
}
}
ImagePage.show(images, initialPage: index);
}
Widget buildImage(double width, double height, int index) { Widget buildImage(double width, double height, int index) {
if (index == 0) { if (index == 0) {
return Text( return Text(
@@ -108,9 +121,7 @@ class _IllustPageState extends State<IllustPage> {
width: imageWidth, width: imageWidth,
height: imageHeight, height: imageHeight,
child: GestureDetector( child: GestureDetector(
onTap: () => ImagePage.show(downloadFile == null onTap: () => openImage(index),
? widget.illust.images[index].original
: "file://${downloadFile.path}"),
child: Image( child: Image(
key: ValueKey(index), key: ValueKey(index),
image: downloadFile == null image: downloadFile == null

View File

@@ -1,7 +1,9 @@
import 'dart:io'; import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:photo_view/photo_view.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:pixes/components/md.dart'; import 'package:pixes/components/md.dart';
import 'package:pixes/components/page_route.dart'; import 'package:pixes/components/page_route.dart';
import 'package:pixes/foundation/app.dart'; import 'package:pixes/foundation/app.dart';
@@ -14,13 +16,16 @@ import 'package:share_plus/share_plus.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
class ImagePage extends StatefulWidget { class ImagePage extends StatefulWidget {
const ImagePage(this.url, {super.key}); const ImagePage(this.urls, {this.initialPage = 1, super.key});
final String url; final List<String> urls;
static show(String url) { final int initialPage;
static show(List<String> urls, {int initialPage = 1}) {
App.rootNavigatorKey.currentState App.rootNavigatorKey.currentState
?.push(AppPageRoute(builder: (context) => ImagePage(url))); ?.push(AppPageRoute(
builder: (context) => ImagePage(urls, initialPage: initialPage)));
} }
@override @override
@@ -56,70 +61,25 @@ class _ImagePageState extends State<ImagePage> with WindowListener {
}); });
} }
@override late var controller = PageController(initialPage: widget.initialPage);
Widget build(BuildContext context) {
return Container( late int currentPage = widget.initialPage;
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
color: FluentTheme.of(context).micaBackgroundColor,
child: Stack(
children: [
Positioned.fill(
child: PhotoView(
backgroundDecoration: BoxDecoration(
color: FluentTheme.of(context).micaBackgroundColor),
filterQuality: FilterQuality.medium,
imageProvider: widget.url.startsWith("file://")
? FileImage(File(widget.url.replaceFirst("file://", "")))
: CachedImageProvider(widget.url) as ImageProvider,
)),
Positioned(
top: 0,
left: 0,
right: 0,
child: SizedBox(
height: 36,
child: Row(
children: [
const SizedBox(
width: 6,
),
IconButton(
icon: const Icon(FluentIcons.back).paddingAll(2),
onPressed: () => context.pop()),
const Expanded(
child: DragToMoveArea(
child: SizedBox.expand(),
),
),
buildActions(),
if (App.isDesktop)
WindowButtons(
key: ValueKey(windowButtonKey),
),
],
),
),
),
],
),
);
}
var menuController = FlyoutController(); var menuController = FlyoutController();
Future<File?> getFile() async { Future<File?> getFile() async {
if (widget.url.startsWith("file://")) { var image = widget.urls[currentPage];
return File(widget.url.replaceFirst("file://", "")); if(image.startsWith("file://")){
return File(image.replaceFirst("file://", ""));
} }
var res = await CacheManager().findCache(widget.url); var file = await CacheManager().findCache(image);
if(res == null){ return file == null
return null; ? null
} : File(file);
return File(res);
} }
String getExtensionName() { String getExtensionName() {
var fileName = widget.url.split('/').last; var fileName = widget.urls[currentPage].split('/').last;
if(fileName.contains('.')){ if(fileName.contains('.')){
return '.${fileName.split('.').last}'; return '.${fileName.split('.').last}';
} }
@@ -142,15 +102,12 @@ class _ImagePageState extends State<ImagePage> with WindowListener {
MenuFlyoutItem(text: Text("Share".tl), onPressed: () async{ MenuFlyoutItem(text: Text("Share".tl), onPressed: () async{
var file = await getFile(); var file = await getFile();
if(file != null){ if(file != null){
var ext = getExtensionName();
var fileName = file.path.split('/').last; var fileName = file.path.split('/').last;
String ext;
if(!fileName.contains('.')){ if(!fileName.contains('.')){
ext = getExtensionName(); fileName += ext;
fileName += getExtensionName();
} else {
ext = file.path.split('.').last;
} }
var mediaType = switch(ext.replaceFirst('.', "")){ var mediaType = switch(ext){
'jpg' => 'image/jpeg', 'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
'png' => 'image/png', 'png' => 'image/png',
@@ -158,17 +115,120 @@ class _ImagePageState extends State<ImagePage> with WindowListener {
'webp' => 'image/webp', 'webp' => 'image/webp',
_ => 'application/octet-stream' _ => 'application/octet-stream'
}; };
Share.shareXFiles([XFile.fromData( Share.shareXFiles([XFile(file.path, mimeType: mediaType, name: fileName)]);
await file.readAsBytes(),
mimeType: mediaType,
name: fileName)]
);
} }
}), }),
], ],
)); ));
} }
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
color: FluentTheme.of(context).micaBackgroundColor,
child: Listener(
onPointerSignal: (event) {
if(event is PointerScrollEvent &&
!HardwareKeyboard.instance.isControlPressed) {
if(event.scrollDelta.dy > 0
&& controller.page!.toInt() < widget.urls.length - 1) {
controller.jumpToPage(controller.page!.toInt() + 1);
} else if(event.scrollDelta.dy < 0 && controller.page!.toInt() > 0){
controller.jumpToPage(controller.page!.toInt() - 1);
}
}
},
child: LayoutBuilder(
builder: (context, constrains) {
var height = constrains.maxHeight;
return Stack(
children: [
Positioned.fill(child: PhotoViewGallery.builder(
pageController: controller,
backgroundDecoration: const BoxDecoration(
color: Colors.transparent
),
itemCount: widget.urls.length,
builder: (context, index) {
var image = widget.urls[index];
return PhotoViewGalleryPageOptions(
imageProvider: image.startsWith("file://")
? FileImage(File(image.replaceFirst("file://", "")))
: CachedImageProvider(image) as ImageProvider,
);
},
onPageChanged: (index) {
setState(() {
currentPage = index;
});
},
)),
Positioned(
top: 0,
left: 0,
right: 0,
child: SizedBox(
height: 36,
child: Row(
children: [
const SizedBox(width: 6,),
IconButton(
icon: const Icon(FluentIcons.back).paddingAll(2),
onPressed: () => context.pop()
),
const Expanded(
child: DragToMoveArea(child: SizedBox.expand(),),
),
buildActions(),
if(App.isDesktop)
WindowButtons(key: ValueKey(windowButtonKey),),
],
),
),
),
Positioned(
left: 0,
top: height / 2 - 9,
child: IconButton(
icon: const Icon(FluentIcons.chevron_left, size: 18,),
onPressed: () {
controller.previousPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
},
).paddingAll(8),
),
Positioned(
right: 0,
top: height / 2 - 9,
child: IconButton(
icon: const Icon(FluentIcons.chevron_right, size: 18),
onPressed: () {
controller.nextPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
},
).paddingAll(8),
),
Positioned(
left: 12,
bottom: 8,
child: Text(
"${currentPage + 1}/${widget.urls.length}",
),
)
],
);
},
),
),
);
}
Widget buildActions() { Widget buildActions() {
var width = MediaQuery.of(context).size.width; var width = MediaQuery.of(context).size.width;
return FlyoutTarget( return FlyoutTarget(