[client] Show completed downloads

This commit is contained in:
Abhishek Shroff
2024-09-25 22:01:43 +05:30
parent 42d1645239
commit 575c540fc7
4 changed files with 91 additions and 79 deletions

View File

@@ -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));

View File

@@ -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) {

View 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()),
};
}
}

View File

@@ -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()),
};
}
}