download and downloading page

This commit is contained in:
wgh19
2024-05-14 13:49:54 +08:00
parent 615720ab49
commit 842a52f53d
13 changed files with 661 additions and 68 deletions

View File

@@ -1,15 +0,0 @@
import 'package:fluent_ui/fluent_ui.dart';
class DownloadPage extends StatefulWidget {
const DownloadPage({super.key});
@override
State<DownloadPage> createState() => _DownloadPageState();
}
class _DownloadPageState extends State<DownloadPage> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

View File

@@ -0,0 +1,15 @@
import 'package:fluent_ui/fluent_ui.dart';
class DownloadedPage extends StatefulWidget {
const DownloadedPage({super.key});
@override
State<DownloadedPage> createState() => _DownloadedPageState();
}
class _DownloadedPageState extends State<DownloadedPage> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

View File

@@ -0,0 +1,166 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/components/md.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/foundation/image_provider.dart';
import 'package:pixes/network/download.dart';
import 'package:pixes/utils/translation.dart';
import '../utils/io.dart';
class DownloadingPage extends StatefulWidget {
const DownloadingPage({super.key});
@override
State<DownloadingPage> createState() => _DownloadingPageState();
}
class _DownloadingPageState extends State<DownloadingPage> {
@override
void initState() {
DownloadManager().registerUiUpdater(() => setState((){}));
super.initState();
}
@override
void dispose() {
DownloadManager().removeUiUpdater();
super.dispose();
}
Map<String, FlyoutController> controller = {};
@override
Widget build(BuildContext context) {
return ScaffoldPage(
content: CustomScrollView(
slivers: [
buildTop(),
const SliverPadding(padding: EdgeInsets.only(top: 16)),
buildContent()
],
),
);
}
Widget buildTop() {
int bytesPerSecond = DownloadManager().bytesPerSecond;
return SliverToBoxAdapter(
child: SizedBox(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text("${"Speed".tl}: ${bytesToText(bytesPerSecond)}/s",
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
),
),
);
}
Widget buildContent() {
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
var task = DownloadManager().tasks[index];
return buildItem(task);
},
childCount: DownloadManager().tasks.length
),
).sliverPaddingHorizontal(12);
}
Widget buildItem(DownloadingTask task) {
controller[task.illust.id.toString()] ??= FlyoutController();
return Card(
padding: const EdgeInsets.symmetric(vertical: 8),
child: SizedBox(
height: 96,
child: Row(
children: [
const SizedBox(width: 12),
Container(
height: double.infinity,
width: 72,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(color: ColorScheme.of(context).outlineVariant, width: 0.6),
),
child: Image(
image: CachedImageProvider(task.illust.images.first.medium),
fit: BoxFit.cover,
filterQuality: FilterQuality.medium,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(task.illust.title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 4),
Text(task.illust.author.name, style: const TextStyle(fontSize: 12, color: Colors.grey)),
const Spacer(),
if(task.error == null)
Text("${task.downloadedImages}/${task.totalImages} ${"Downloaded".tl}", style: const TextStyle(fontSize: 12, color: Colors.grey))
else
Text("Error: ${task.error!.replaceAll("\n", " ")}", style: TextStyle(fontSize: 12, color: ColorScheme.of(context).error), maxLines: 2,),
],
),
),
const SizedBox(width: 4),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if(task.error != null)
Button(
child: Text("Retry".tl).fixWidth(46),
onPressed: () {
task.retry();
setState(() {});
},
),
const SizedBox(height: 4),
FlyoutTarget(
controller: controller[task.illust.id.toString()]!,
child: Button(
child: Text("Cancel".tl, style: TextStyle(color: ColorScheme.of(context).error),).fixWidth(46),
onPressed: (){
controller[task.illust.id.toString()]!.showFlyout(
navigatorKey: App.rootNavigatorKey.currentState,
builder: (context) {
return FlyoutContent(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Are you sure you want to cancel this download?'.tl,
style: const TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12.0),
Button(
onPressed: () {
Flyout.of(context).close();
task.cancel();
setState(() {});
},
child: Text('Yes'.tl),
),
],
),
);
},
);
}
),
)
],
),
const SizedBox(width: 12),
],
),
),
);
}
}

View File

@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/material.dart' show Icons;
import 'package:pixes/components/animated_image.dart';
@@ -69,6 +71,11 @@ class _IllustPageState extends State<IllustPage> {
}
Widget buildImage(double width, double height, int index) {
File? downloadFile;
if(widget.illust.downloaded) {
downloadFile = DownloadManager().getImage(widget.illust.id, index);
}
if (index == 0) {
return Text(
widget.illust.title,
@@ -93,9 +100,13 @@ class _IllustPageState extends State<IllustPage> {
width: imageWidth,
height: imageHeight,
child: GestureDetector(
onTap: () => ImagePage.show(widget.illust.images[index].original),
onTap: () => ImagePage.show(downloadFile == null
? widget.illust.images[index].original
: "file://${downloadFile.path}"),
child: Image(
image: CachedImageProvider(widget.illust.images[index].large),
image: downloadFile == null
? CachedImageProvider(widget.illust.images[index].large) as ImageProvider
: FileImage(downloadFile) as ImageProvider,
width: imageWidth,
fit: BoxFit.cover,
height: imageHeight,
@@ -123,14 +134,9 @@ class _IllustPageState extends State<IllustPage> {
),
);
if (index == 0) {
return Hero(
tag: "illust_${widget.illust.id}",
child: image,
);
} else {
return image;
}
return Center(
child: image,
);
}
}
@@ -374,7 +380,10 @@ class _BottomBarState extends State<_BottomBar> {
});
}
void download() {}
void download() {
DownloadManager().addDownloadingTask(widget.illust);
setState(() {});
}
bool showText = width > 640;
@@ -416,24 +425,47 @@ class _BottomBarState extends State<_BottomBar> {
yield const SizedBox(width: 8,);
if (!widget.illust.downloaded) {
yield Button(
onPressed: download,
child: SizedBox(
height: 28,
child: Row(
children: [
const Icon(
FluentIcons.download,
size: 18,
),
if(showText)
const SizedBox(width: 8,),
if(showText)
Text("Download".tl),
],
if(widget.illust.downloading) {
yield Button(
onPressed: () => {},
child: SizedBox(
height: 28,
child: Row(
children: [
Icon(
FluentIcons.download,
color: ColorScheme.of(context).outline,
size: 18,
),
if(showText)
const SizedBox(width: 8,),
if(showText)
Text("Downloading".tl,
style: TextStyle(color: ColorScheme.of(context).outline),),
],
),
),
),
);
);
} else {
yield Button(
onPressed: download,
child: SizedBox(
height: 28,
child: Row(
children: [
const Icon(
FluentIcons.download,
size: 18,
),
if(showText)
const SizedBox(width: 8,),
if(showText)
Text("Download".tl),
],
),
),
);
}
}
yield const SizedBox(width: 8,);

View File

@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:photo_view/photo_view.dart';
import 'package:pixes/components/page_route.dart';
@@ -60,7 +62,9 @@ class _ImagePageState extends State<ImagePage> with WindowListener{
color: Colors.transparent
),
filterQuality: FilterQuality.medium,
imageProvider: CachedImageProvider(widget.url),
imageProvider: widget.url.startsWith("file://")
? FileImage(File(widget.url.replaceFirst("file://", "")))
: CachedImageProvider(widget.url) as ImageProvider,
)),
Positioned(
top: 0,

View File

@@ -8,6 +8,7 @@ import "package:pixes/components/md.dart";
import "package:pixes/foundation/app.dart";
import "package:pixes/network/network.dart";
import "package:pixes/pages/bookmarks.dart";
import "package:pixes/pages/downloaded_page.dart";
import "package:pixes/pages/following_artworks.dart";
import "package:pixes/pages/ranking.dart";
import "package:pixes/pages/recommendation_page.dart";
@@ -20,7 +21,7 @@ import "package:pixes/utils/translation.dart";
import "package:window_manager/window_manager.dart";
import "../components/page_route.dart";
import "download_page.dart";
import "downloading_page.dart";
const _kAppBarHeight = 36.0;
@@ -34,7 +35,7 @@ class MainPage extends StatefulWidget {
class _MainPageState extends State<MainPage> with WindowListener {
final navigatorKey = GlobalKey<NavigatorState>();
int index = 3;
int index = 4;
int windowButtonKey = 0;
@@ -101,9 +102,14 @@ class _MainPageState extends State<MainPage> with WindowListener {
title: Text('Search'.tl),
body: const SizedBox.shrink(),
),
PaneItem(
icon: const Icon(MdIcons.downloading, size: 20,),
title: Text('Downloading'.tl),
body: const SizedBox.shrink(),
),
PaneItem(
icon: const Icon(MdIcons.download, size: 20,),
title: Text('Download'.tl),
title: Text('Downloaded'.tl),
body: const SizedBox.shrink(),
),
PaneItemSeparator(),
@@ -148,7 +154,8 @@ class _MainPageState extends State<MainPage> with WindowListener {
static final pageBuilders = <Widget Function()>[
() => UserInfoPage(appdata.account!.user.id),
() => const SearchPage(),
() => const DownloadPage(),
() => const DownloadingPage(),
() => const DownloadedPage(),
() => const RecommendationPage(),
() => const BookMarkedArtworkPage(),
() => const FollowingArtworksPage(),