Files
venera/lib/pages/downloading_page.dart
2025-01-31 13:08:24 +08:00

239 lines
6.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:venera/components/components.dart';
import 'package:venera/foundation/app.dart';
import 'package:venera/foundation/image_provider/cached_image.dart';
import 'package:venera/foundation/local.dart';
import 'package:venera/network/download.dart';
import 'package:venera/utils/io.dart';
import 'package:venera/utils/translations.dart';
class DownloadingPage extends StatefulWidget {
const DownloadingPage({super.key});
@override
State<DownloadingPage> createState() => _DownloadingPageState();
}
class _DownloadingPageState extends State<DownloadingPage> {
@override
void initState() {
LocalManager().addListener(update);
super.initState();
}
@override
void dispose() {
LocalManager().removeListener(update);
super.dispose();
}
void update() {
if(mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return PopUpWidgetScaffold(
title: "",
body: ListView.builder(
itemCount: LocalManager().downloadingTasks.length + 1,
itemBuilder: (BuildContext context, int i) {
if (i == 0) {
return buildTop();
}
i--;
return _DownloadTaskTile(
key: ValueKey(LocalManager().downloadingTasks[i]),
task: LocalManager().downloadingTasks[i],
);
},
),
);
}
Widget buildTop() {
int speed = 0;
if (LocalManager().downloadingTasks.isNotEmpty) {
speed = LocalManager().downloadingTasks.first.speed;
}
var first = LocalManager().downloadingTasks.firstOrNull;
return Container(
height: 48,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: context.colorScheme.outlineVariant,
width: 0.6,
),
),
),
child: Row(
children: [
if (first?.isPaused == true)
Text(
"Paused".tl,
style: ts.s18.bold,
)
else if (first?.isError == true)
Text(
"Error".tl,
style: ts.s18.bold,
)
else
Text(
"${bytesToReadableString(speed)}/s",
style: ts.s18.bold,
),
const Spacer(),
if (first?.isPaused == true || first?.isError == true)
OutlinedButton(
child: Row(
children: [
const Icon(Icons.play_arrow, size: 18),
const SizedBox(width: 4),
Text("Start".tl),
],
),
onPressed: () {
first!.resume();
},
)
else if (first != null)
OutlinedButton(
child: Row(
children: [
const Icon(Icons.pause, size: 18),
const SizedBox(width: 4),
Text("Pause".tl),
],
),
onPressed: () {
first.pause();
},
),
],
).paddingHorizontal(16),
);
}
}
class _DownloadTaskTile extends StatefulWidget {
const _DownloadTaskTile({required this.task, super.key});
final DownloadTask task;
@override
State<_DownloadTaskTile> createState() => _DownloadTaskTileState();
}
class _DownloadTaskTileState extends State<_DownloadTaskTile> {
late DownloadTask task;
@override
void initState() {
task = widget.task;
task.addListener(update);
super.initState();
}
@override
void dispose() {
task.removeListener(update);
super.dispose();
}
@override
void didUpdateWidget(covariant _DownloadTaskTile oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.task != widget.task) {
task.removeListener(update);
task = widget.task;
task.addListener(update);
}
}
void update() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return Container(
height: 136,
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
child: Row(
children: [
Container(
width: 82,
height: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: context.colorScheme.primaryContainer,
),
clipBehavior: Clip.antiAlias,
child: widget.task.cover == null
? null
: Image(
image: CachedImageProvider(widget.task.cover!),
filterQuality: FilterQuality.medium,
fit: BoxFit.cover,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
widget.task.title,
style: Theme.of(context).textTheme.bodyMedium,
maxLines: 2,
),
),
MenuButton(
entries: [
MenuEntry(
icon: Icons.close,
text: "Cancel".tl,
onClick: () {
widget.task.cancel();
},
),
MenuEntry(
icon: Icons.vertical_align_top,
text: "Move To First".tl,
onClick: () {
LocalManager().moveToFirst(widget.task);
},
),
],
),
],
),
const Spacer(),
if (!widget.task.isPaused || widget.task.isError)
Text(
widget.task.message,
style: ts.s12,
maxLines: 3,
),
const SizedBox(height: 4),
LinearProgressIndicator(
value: widget.task.progress,
),
const SizedBox(height: 8),
],
),
),
],
),
);
}
}