mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-05 19:21:23 -06:00
[client] Show sync errors in list
This commit is contained in:
@@ -15,6 +15,8 @@ import 'package:phylum/libphylum/requests/resource_detail_request.dart';
|
||||
import 'package:phylum/libphylum/responses/responses.dart';
|
||||
import 'package:phylum/libphylum/util/uuid.dart';
|
||||
|
||||
const performLocalNameCheck = true;
|
||||
|
||||
class ResourceRepository {
|
||||
final PhylumAccount account;
|
||||
|
||||
@@ -33,27 +35,29 @@ class ResourceRepository {
|
||||
required NameConflictResolution conflictResolution,
|
||||
String? id,
|
||||
}) async {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
String? deletedId;
|
||||
id ??= generateUuid();
|
||||
String localName = name;
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
case nameConflictDelete:
|
||||
conflictResolution = nameConflictDelete;
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
String? deletedId;
|
||||
if (performLocalNameCheck) {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
case nameConflictDelete:
|
||||
conflictResolution = nameConflictDelete;
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id ??= generateUuid();
|
||||
await account.addAction(ResourceMkdirAction(
|
||||
parent: parent,
|
||||
resourceName: name,
|
||||
@@ -73,25 +77,27 @@ class ResourceRepository {
|
||||
required String name,
|
||||
NameConflictResolution conflictResolution = nameConflictError,
|
||||
}) async {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
String localName = name;
|
||||
String id = generateUuid();
|
||||
String localName = name;
|
||||
String? deletedId;
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
id = existing.first.id;
|
||||
break;
|
||||
case nameConflictDelete:
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
if (performLocalNameCheck) {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
id = existing.first.id;
|
||||
break;
|
||||
case nameConflictDelete:
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
}
|
||||
}
|
||||
}
|
||||
final f = File(path);
|
||||
@@ -118,23 +124,25 @@ class ResourceRepository {
|
||||
required String parent,
|
||||
required NameConflictResolution conflictResolution,
|
||||
}) async {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
String? deletedId;
|
||||
String localName = name;
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
case nameConflictDelete:
|
||||
conflictResolution = nameConflictDelete;
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
String? deletedId;
|
||||
if (performLocalNameCheck) {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
case nameConflictDelete:
|
||||
conflictResolution = nameConflictDelete;
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
}
|
||||
}
|
||||
}
|
||||
await account.addAction(ResourceMoveAction(
|
||||
@@ -162,23 +170,25 @@ class ResourceRepository {
|
||||
}
|
||||
|
||||
String id = generateUuid();
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
String? deletedId;
|
||||
String localName = name;
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
case nameConflictDelete:
|
||||
conflictResolution = nameConflictDelete;
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
if (performLocalNameCheck) {
|
||||
var existing = await account.db.getResourcesByName(parent: parent, name: name);
|
||||
if (existing.isNotEmpty) {
|
||||
switch (conflictResolution) {
|
||||
case nameConflictError:
|
||||
throw NameConflictException(existing.first);
|
||||
case nameConflictRename:
|
||||
localName = await _createUniqueName(existing, parent, name);
|
||||
break;
|
||||
case nameConflictOverwrite:
|
||||
case nameConflictDelete:
|
||||
conflictResolution = nameConflictDelete;
|
||||
deletedId = existing.first.id;
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported conflict resolution');
|
||||
}
|
||||
}
|
||||
}
|
||||
await account.addAction(ResourceCopyAction(
|
||||
|
||||
@@ -41,7 +41,7 @@ class PhylumApiErrorResponse extends ApiResponse<PhylumAccount> {
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String get description => 'Api Error: $message';
|
||||
String get description => message;
|
||||
|
||||
@override
|
||||
bool get success => false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:offtheline/offtheline.dart';
|
||||
import 'package:phylum/libphylum/actions/action_resource.dart';
|
||||
import 'package:phylum/libphylum/db/db.dart';
|
||||
import 'package:phylum/libphylum/phylum_api_types.dart';
|
||||
@@ -9,6 +10,30 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import '../../libphylum/explorer/explorer_controller.dart';
|
||||
|
||||
enum _SyncState {
|
||||
none(Icons.block),
|
||||
waiting(Icons.cloud_queue),
|
||||
error(Icons.sync_problem),
|
||||
syncing(Icons.sync);
|
||||
|
||||
const _SyncState(this.icon);
|
||||
|
||||
final IconData icon;
|
||||
|
||||
factory _SyncState.fromStatus(ActionStatus status) {
|
||||
if (status is ActionStatusReady || status is ActionStatusWaiting) {
|
||||
return _SyncState.waiting;
|
||||
}
|
||||
if (status is ActionStatusUploading) {
|
||||
return _SyncState.syncing;
|
||||
}
|
||||
if (status is ActionStatusError) {
|
||||
return _SyncState.error;
|
||||
}
|
||||
return _SyncState.none;
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceDetailsRow extends StatelessWidget {
|
||||
final Resource resource;
|
||||
final bool dropTargetActive;
|
||||
@@ -20,8 +45,15 @@ class ResourceDetailsRow extends StatelessWidget {
|
||||
final showBorder = context.select<ExplorerState, bool>((state) => state.focusId == resource.id && state.showFocus);
|
||||
final highlight = context.select<ExplorerState, bool>((state) => state.isSelected(resource.id));
|
||||
final dim = context.select<ExplorerState, bool>((state) => state.isSelected(resource.id) && state.dragging);
|
||||
final hasChanges = context.select<PhylumActionQueueState, bool>(
|
||||
(state) => state.actions.any((action) => action is ResourceAction && action.resourceId == resource.id));
|
||||
final sync = context.select<PhylumActionQueueState, _SyncState>((state) {
|
||||
return state.actions.fold(_SyncState.none, (acc, action) {
|
||||
if (action is ResourceAction && action.resourceId == resource.id) {
|
||||
final actionState = _SyncState.fromStatus(action.status);
|
||||
if (actionState.index > acc.index) return actionState;
|
||||
}
|
||||
return acc;
|
||||
});
|
||||
});
|
||||
final theme = Theme.of(context);
|
||||
final colorScheme = theme.colorScheme;
|
||||
final border = dropTargetActive
|
||||
@@ -83,10 +115,10 @@ class ResourceDetailsRow extends StatelessWidget {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (hasChanges)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 6.0),
|
||||
child: Icon(Icons.sync, size: 14),
|
||||
if (sync != _SyncState.none)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 6.0),
|
||||
child: Icon(sync.icon, size: 14),
|
||||
),
|
||||
if (resource.permissions != null)
|
||||
const Padding(
|
||||
|
||||
Reference in New Issue
Block a user