A framework for building convergent cross-platform Nextcloud clients using Flutter.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

105 lines
3.4 KiB

part of '../neon_files.dart';
@immutable
class FilesSync implements SyncImplementation<FilesSyncMapping, WebDavFile, FileSystemEntity> {
const FilesSync();
@override
String get appId => AppIDs.files;
@override
Future<FilesSyncSources> getSources(final Account account, final FilesSyncMapping mapping) async {
// This shouldn't be necessary, but it sadly is because of https://github.com/flutter/flutter/issues/25659.
// Alternative would be to use https://pub.dev/packages/shared_storage,
// but to be efficient we'd need https://github.com/alexrintt/shared-storage/issues/91
// or copy the files to the app cache (which is also not optimal).
if (Platform.isAndroid && !await Permission.manageExternalStorage.request().isGranted) {
throw const MissingPermissionException(Permission.manageExternalStorage);
}
return FilesSyncSources(
account.client,
mapping.remotePath,
mapping.localPath,
);
}
@override
Map<String, dynamic> serializeMapping(final FilesSyncMapping mapping) => mapping.toJson();
@override
FilesSyncMapping deserializeMapping(final Map<String, dynamic> json) => FilesSyncMapping.fromJson(json);
@override
Future<FilesSyncMapping?> addMapping(final BuildContext context, final Account account) async {
final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final appsBloc = accountsBloc.getAppsBlocFor(account);
final filesBloc = appsBloc.getAppBlocByID(AppIDs.files)! as FilesBloc;
final filesBrowserBloc = filesBloc.getNewFilesBrowserBloc();
final remotePath = await showDialog<PathUri>(
context: context,
builder: (final context) => FilesChooseFolderDialog(
bloc: filesBrowserBloc,
filesBloc: filesBloc,
originalPath: PathUri.cwd(),
),
);
filesBrowserBloc.dispose();
if (remotePath == null) {
return null;
}
final localPath = await FileUtils.pickDirectory();
if (localPath == null) {
return null;
}
if (!context.mounted) {
return null;
}
return FilesSyncMapping(
appId: AppIDs.files,
accountId: account.id,
remotePath: remotePath,
localPath: Directory(localPath),
journal: SyncJournal(),
);
}
@override
String getMappingDisplayTitle(final FilesSyncMapping mapping) => mapping.remotePath.toString();
@override
String getMappingDisplaySubtitle(final FilesSyncMapping mapping) => mapping.localPath.path;
@override
String getMappingId(final FilesSyncMapping mapping) =>
'${Uri.encodeComponent(mapping.remotePath.toString())}-${Uri.encodeComponent(mapping.localPath.path)}';
@override
Widget getConflictDetailsLocal(final BuildContext context, final FileSystemEntity object) {
final stat = object.statSync();
return FilesFileTile(
showFullPath: true,
filesBloc: NeonProvider.of<FilesBloc>(context),
details: FileDetails(
uri: PathUri.parse(object.path),
size: stat.size,
etag: '',
mimeType: '',
lastModified: stat.modified,
hasPreview: false,
isFavorite: false,
),
);
}
@override
Widget getConflictDetailsRemote(final BuildContext context, final WebDavFile object) => FilesFileTile(
showFullPath: true,
filesBloc: NeonProvider.of<FilesBloc>(context),
details: FileDetails.fromWebDav(
file: object,
),
);
}