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