mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-03 10:10:10 -06:00
[client] Show completed downloads
This commit is contained in:
@@ -13,14 +13,9 @@ import 'package:state_notifier/state_notifier.dart';
|
||||
const _keyDownloadTaskId = 'downloadTaskId';
|
||||
|
||||
class DownloadManagerState {
|
||||
final List<DownloadTask> running;
|
||||
final List<DownloadTask> finished;
|
||||
final List<DownloadTask> tasks;
|
||||
|
||||
const DownloadManagerState([this.running = const [], this.finished = const []]);
|
||||
|
||||
DownloadManagerState copyWith({List<DownloadTask>? running, List<DownloadTask>? finished}) {
|
||||
return DownloadManagerState(running ?? this.running, finished ?? this.finished);
|
||||
}
|
||||
const DownloadManagerState([this.tasks = const []]);
|
||||
}
|
||||
|
||||
class DownloadManager extends StateNotifier<DownloadManagerState> {
|
||||
@@ -38,13 +33,11 @@ class DownloadManager extends StateNotifier<DownloadManagerState> {
|
||||
if (status is DownloadStatusError || status is DownloadStatusFinished) {
|
||||
Future.microtask(() {
|
||||
remove?.call();
|
||||
final running = List.of(state.running)..remove(task);
|
||||
state = DownloadManagerState(running, [...state.finished, task]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
state = state.copyWith(running: [...state.running, task]);
|
||||
state = DownloadManagerState([...state.tasks, task]);
|
||||
try {
|
||||
task.status = const DownloadStatusStarting();
|
||||
final response = await account.apiClient.dispatchRequestRaw(ResourceContentsRequest(r.id));
|
||||
|
||||
@@ -24,7 +24,7 @@ class _DownloadButtonState extends State<DownloadButton> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_subscription = context.read<DownloadManager>().stream.listen((state) {
|
||||
for (final task in state.running) {
|
||||
for (final task in state.tasks) {
|
||||
if (!listeners.containsKey(task)) {
|
||||
final status = task.status;
|
||||
if (status is DownloadStatusRunning) {
|
||||
|
||||
86
client/lib/ui/sync/sliver_downloads.dart
Normal file
86
client/lib/ui/sync/sliver_downloads.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:phylum/integrations/download_manager.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
const _showedDownloads = 3;
|
||||
|
||||
class DownloadsSliver extends StatefulWidget {
|
||||
const DownloadsSliver({super.key});
|
||||
|
||||
@override
|
||||
State<DownloadsSliver> createState() => _DownloadsSliverState();
|
||||
}
|
||||
|
||||
class _DownloadsSliverState extends State<DownloadsSliver> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final allTasks = context.select<DownloadManagerState, List<DownloadTask>>((state) => state.tasks);
|
||||
final tasks = allTasks.sublist(max(allTasks.length - _showedDownloads, 0)).toList(growable: false);
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, i) {
|
||||
if (i == 0) {
|
||||
return const ListTile(dense: true, title: Text('Downloads'));
|
||||
}
|
||||
if (i > tasks.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton(
|
||||
onPressed: () {},
|
||||
child: Text('View All (${allTasks.length - _showedDownloads} More)'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _DownloadTaskView(task: tasks[tasks.length - i]);
|
||||
},
|
||||
childCount: tasks.length + 1 + (allTasks.length >= _showedDownloads ? 1 : 0),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DownloadTaskView extends StatefulWidget {
|
||||
final DownloadTask task;
|
||||
|
||||
_DownloadTaskView({required this.task}) : super(key: ValueKey(task.id));
|
||||
|
||||
@override
|
||||
State<_DownloadTaskView> createState() => _DownloadTaskViewState();
|
||||
}
|
||||
|
||||
class _DownloadTaskViewState extends State<_DownloadTaskView> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder(
|
||||
stream: widget.task.statusNotifier.stream,
|
||||
initialData: widget.task.status,
|
||||
builder: (contetx, snapshot) {
|
||||
final status = snapshot.data!;
|
||||
return ListTile(title: Text(widget.task.resourceName), subtitle: buildSubtitle(status));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSubtitle(DownloadStatus status) {
|
||||
return switch (status) {
|
||||
DownloadStatusStarting _ => const LinearProgressIndicator(value: null),
|
||||
DownloadStatusRunning(received: int received, size: int size) => LinearProgressIndicator(value: (received * 1.0) / size),
|
||||
_ => Text(status.toString()),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:phylum/integrations/download_manager.dart';
|
||||
import 'package:phylum/ui/sync/action_queue_list.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:phylum/ui/sync/sliver_downloads.dart';
|
||||
|
||||
class SyncDialog extends StatelessWidget {
|
||||
const SyncDialog({super.key});
|
||||
@@ -42,69 +41,3 @@ class SyncDialog extends StatelessWidget {
|
||||
slivers: [DownloadsSliver(), ActionQueueSliver()],
|
||||
);
|
||||
}
|
||||
|
||||
class DownloadsSliver extends StatefulWidget {
|
||||
const DownloadsSliver({super.key});
|
||||
|
||||
@override
|
||||
State<DownloadsSliver> createState() => _DownloadsSliverState();
|
||||
}
|
||||
|
||||
class _DownloadsSliverState extends State<DownloadsSliver> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final running = context.select<DownloadManagerState, List<DownloadTask>>((state) => state.running);
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, i) {
|
||||
if (i == 0) {
|
||||
return const ListTile(dense: true, title: Text('Downloads'));
|
||||
}
|
||||
return _DownloadTaskView(task: running[running.length - i]);
|
||||
},
|
||||
childCount: running.length + 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DownloadTaskView extends StatefulWidget {
|
||||
final DownloadTask task;
|
||||
|
||||
_DownloadTaskView({required this.task}) : super(key: ValueKey(task.id));
|
||||
|
||||
@override
|
||||
State<_DownloadTaskView> createState() => _DownloadTaskViewState();
|
||||
}
|
||||
|
||||
class _DownloadTaskViewState extends State<_DownloadTaskView> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder(
|
||||
stream: widget.task.statusNotifier.stream,
|
||||
initialData: widget.task.status,
|
||||
builder: (contetx, snapshot) {
|
||||
final status = snapshot.data!;
|
||||
return ListTile(title: Text(widget.task.resourceName), subtitle: buildSubtitle(status));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSubtitle(DownloadStatus status) {
|
||||
return switch (status) {
|
||||
DownloadStatusStarting _ => const LinearProgressIndicator(value: null),
|
||||
DownloadStatusRunning(received: int received, size: int size) => LinearProgressIndicator(value: (received * 1.0) / size),
|
||||
_ => Text(status.toString()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user