mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-05-11 22:59:23 -05:00
[client] Show failed actions
This commit is contained in:
@@ -24,10 +24,22 @@ Self-hosted cloud file storage
|
||||
[ ] Thumbnails
|
||||
[ ] Sync Manager
|
||||
[x] View List of pending actions
|
||||
[ ] Retry / Edit / Delete failed actions
|
||||
[ ] Retry / Edit / Delete failed downloads
|
||||
[ ] View in-progress downloads
|
||||
[x] View failed actions
|
||||
[ ] Actions for failed actions
|
||||
[x] Delete
|
||||
[x] Retry
|
||||
[ ] Edit
|
||||
[x] View in-progress downloads
|
||||
[ ] View transfer rate and ETA
|
||||
[ ] View finished downloads (in current session)
|
||||
[ ] Actions for completed downloads
|
||||
[ ] Open
|
||||
[ ] Open Folder
|
||||
[ ] Actions for failed downloads
|
||||
[ ] Delete
|
||||
[ ] Retry
|
||||
[ ] Edit
|
||||
[ ] View all past downloads
|
||||
[ ] Public access
|
||||
[ ] Download files
|
||||
[ ] View folders
|
||||
|
||||
@@ -16,7 +16,7 @@ class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase({required this.id}) : super(_openConnection(id));
|
||||
|
||||
@override
|
||||
int get schemaVersion => 5;
|
||||
int get schemaVersion => 6;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
|
||||
@@ -157,10 +157,6 @@ class $ResourcesTable extends Resources
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
List<Set<GeneratedColumn>> get uniqueKeys => [
|
||||
{parent, name},
|
||||
];
|
||||
@override
|
||||
Resource map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return Resource(
|
||||
|
||||
@@ -15,8 +15,8 @@ class Resources extends Table {
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
|
||||
@override
|
||||
List<Set<Column<Object>>>? get uniqueKeys => [
|
||||
{parent, name}
|
||||
];
|
||||
// @override
|
||||
// List<Set<Column<Object>>>? get uniqueKeys => [
|
||||
// {parent, name}
|
||||
// ];
|
||||
}
|
||||
|
||||
@@ -6,32 +6,39 @@ import 'package:provider/provider.dart';
|
||||
import 'package:state_notifier/state_notifier.dart';
|
||||
|
||||
class ActionQueueStatusNotifier extends ChangeNotifier {
|
||||
final Map<StateNotifier<ActionStatus>, RemoveListener> _listeners = {};
|
||||
final Map<StateNotifier<ActionStatus>, ActionStatus> _statusMap = {};
|
||||
final Map<QueuedAction<PhylumAccount>, RemoveListener> _listeners = {};
|
||||
final Map<QueuedAction<PhylumAccount>, ActionStatus> _statusMap = {};
|
||||
List<QueuedAction<PhylumAccount>>? last;
|
||||
late final RemoveListener removeListenerCallback;
|
||||
bool paused = false;
|
||||
bool unreachable = false;
|
||||
|
||||
int get submitting => _count<ActionStatusUploading>();
|
||||
int get error => _count<ActionStatusError>();
|
||||
int get submittingCount => _count<ActionStatusUploading>();
|
||||
int get errorCount => _count<ActionStatusError>();
|
||||
int _count<T extends ActionStatus>() => _statusMap.values.fold(0, (acc, status) => status is T ? acc + 1 : acc);
|
||||
List<QueuedAction<PhylumAccount>>? _failedActions;
|
||||
List<QueuedAction<PhylumAccount>> get failedActions {
|
||||
_failedActions ??= List.of(_statusMap.entries.where((e) => e.value is ActionStatusError).map((e) => e.key), growable: false);
|
||||
return _failedActions!;
|
||||
}
|
||||
|
||||
ActionQueueStatusNotifier(BuildContext context) {
|
||||
removeListenerCallback = context.read<PhylumActionQueue>().addListener((state) {
|
||||
if (state.actions != last) {
|
||||
for (final action in state.actions) {
|
||||
final notifier = action.statusNotifier;
|
||||
if (!_listeners.containsKey(notifier)) {
|
||||
_listeners[notifier] = notifier.addListener((status) {
|
||||
if (!_listeners.containsKey(action)) {
|
||||
_listeners[action] = action.statusNotifier.addListener((status) {
|
||||
// Ignore progress updates
|
||||
if (_statusMap[notifier].runtimeType != status.runtimeType) {
|
||||
_statusMap[notifier] = status;
|
||||
if (_statusMap[action].runtimeType != status.runtimeType) {
|
||||
if (status is ActionStatusError || _statusMap[action] is ActionStatusError) {
|
||||
_failedActions = null;
|
||||
}
|
||||
_statusMap[action] = status;
|
||||
if (status is ActionStatusDone) {
|
||||
Future.microtask(() {
|
||||
_listeners[notifier]?.call();
|
||||
_listeners.remove(notifier);
|
||||
_statusMap.remove(notifier);
|
||||
_listeners[action]?.call();
|
||||
_listeners.remove(action);
|
||||
_statusMap.remove(action);
|
||||
});
|
||||
}
|
||||
notifyListeners();
|
||||
|
||||
@@ -43,8 +43,8 @@ class _ServerStatusButtonState extends State<ServerStatusButton> {
|
||||
final notifier = context.watch<ActionQueueStatusNotifier>();
|
||||
_ServerStatus state = _ServerStatus.done;
|
||||
if (notifier.unreachable) state = _ServerStatus.unreachable;
|
||||
if (notifier.error > 0) state = _ServerStatus.error;
|
||||
if (notifier.submitting > 0) state = _ServerStatus.syncing;
|
||||
if (notifier.errorCount > 0) state = _ServerStatus.error;
|
||||
if (notifier.submittingCount > 0) state = _ServerStatus.syncing;
|
||||
if (notifier.paused) state = _ServerStatus.paused;
|
||||
return ListTile(
|
||||
leading: Icon(state.icon),
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:offtheline/offtheline.dart';
|
||||
import 'package:phylum/libphylum/phylum_account.dart';
|
||||
import 'package:phylum/ui/app/action_queue_status_notifier.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'action_view.dart';
|
||||
|
||||
class SliverErrors extends StatelessWidget {
|
||||
const SliverErrors({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final actions = context.select<ActionQueueStatusNotifier, List<QueuedAction<PhylumAccount>>>((state) {
|
||||
final failedActions = state.failedActions;
|
||||
return failedActions;
|
||||
});
|
||||
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, i) {
|
||||
if (i == 0) {
|
||||
return const ListTile(dense: true, title: Text('Errors'));
|
||||
}
|
||||
return ActionView(action: actions[i - 1]);
|
||||
},
|
||||
childCount: actions.isEmpty ? 0 : actions.length + 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:phylum/ui/sync/sliver_uploads.dart';
|
||||
import 'package:phylum/ui/sync/sliver_downloads.dart';
|
||||
|
||||
import 'sliver_errors.dart';
|
||||
|
||||
class SyncDialog extends StatelessWidget {
|
||||
const SyncDialog({super.key});
|
||||
|
||||
@@ -38,6 +40,6 @@ class SyncDialog extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget buildContents(BuildContext context) => const CustomScrollView(
|
||||
slivers: [DownloadsSliver(), SliverUploads()],
|
||||
slivers: [DownloadsSliver(), SliverUploads(), SliverErrors()],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user