Skip to content

Commit

Permalink
refactor(nextcloud,neon_files): Introduce PathUri for WebDAV path han…
Browse files Browse the repository at this point in the history
…dling

Signed-off-by: jld3103 <[email protected]>
  • Loading branch information
provokateurin committed Nov 3, 2023
1 parent 8796b8c commit dd5ed6e
Show file tree
Hide file tree
Showing 18 changed files with 377 additions and 203 deletions.
22 changes: 11 additions & 11 deletions packages/neon/neon_files/lib/blocs/browser.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
part of '../neon_files.dart';

abstract interface class FilesBrowserBlocEvents {
void setPath(final List<String> path);
void setPath(final PathUri path);

void createFolder(final List<String> path);
void createFolder(final PathUri path);
}

abstract interface class FilesBrowserBlocStates {
BehaviorSubject<Result<List<WebDavFile>>> get files;

BehaviorSubject<List<String>> get path;
BehaviorSubject<PathUri> get path;
}

class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents, FilesBrowserBlocStates {
FilesBrowserBloc(
this.options,
this.account, {
final List<String>? initialPath,
final PathUri? initialPath,
}) {
if (initialPath != null) {
path.add(initialPath);
Expand All @@ -39,16 +39,16 @@ class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents
BehaviorSubject<Result<List<WebDavFile>>> files = BehaviorSubject<Result<List<WebDavFile>>>();

@override
BehaviorSubject<List<String>> path = BehaviorSubject<List<String>>.seeded([]);
BehaviorSubject<PathUri> path = BehaviorSubject.seeded(PathUri());

@override
Future<void> refresh() async {
await RequestManager.instance.wrapWebDav<List<WebDavFile>>(
account.id,
'files-${path.value.join('/')}',
'files-${path.value.path}',
files,
() => account.client.webdav.propfind(
Uri(pathSegments: path.value),
path.value,
prop: WebDavPropWithoutValues.fromBools(
davgetcontenttype: true,
davgetetag: true,
Expand All @@ -65,13 +65,13 @@ class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents
}

@override
void setPath(final List<String> p) {
path.add(p);
void setPath(final PathUri path) {
this.path.add(path);
unawaited(refresh());
}

@override
void createFolder(final List<String> path) {
wrapAction(() async => account.client.webdav.mkcol(Uri(pathSegments: path)));
void createFolder(final PathUri path) {
wrapAction(() async => account.client.webdav.mkcol(path));
}
}
70 changes: 35 additions & 35 deletions packages/neon/neon_files/lib/blocs/files.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
part of '../neon_files.dart';

abstract interface class FilesBlocEvents {
void uploadFile(final List<String> path, final String localPath);
void uploadFile(final PathUri path, final String localPath);

void syncFile(final List<String> path);
void syncFile(final PathUri path);

void openFile(final List<String> path, final String etag, final String? mimeType);
void openFile(final PathUri path, final String etag, final String? mimeType);

void shareFileNative(final List<String> path, final String etag);
void shareFileNative(final PathUri path, final String etag);

void delete(final List<String> path);
void delete(final PathUri path);

void rename(final List<String> path, final String name);
void rename(final PathUri path, final String name);

void move(final List<String> path, final List<String> destination);
void move(final PathUri path, final PathUri destination);

void copy(final List<String> path, final List<String> destination);
void copy(final PathUri path, final PathUri destination);

void addFavorite(final List<String> path);
void addFavorite(final PathUri path);

void removeFavorite(final List<String> path);
void removeFavorite(final PathUri path);
}

abstract interface class FilesBlocStates {
Expand Down Expand Up @@ -58,32 +58,32 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
BehaviorSubject<List<FilesTask>> tasks = BehaviorSubject<List<FilesTask>>.seeded([]);

@override
void addFavorite(final List<String> path) {
void addFavorite(final PathUri path) {
wrapAction(
() async => account.client.webdav.proppatch(
Uri(pathSegments: path),
path,
set: WebDavProp(ocfavorite: 1),
),
);
}

@override
void copy(final List<String> path, final List<String> destination) {
wrapAction(() async => account.client.webdav.copy(Uri(pathSegments: path), Uri(pathSegments: destination)));
void copy(final PathUri path, final PathUri destination) {
wrapAction(() async => account.client.webdav.copy(path, destination));
}

@override
void delete(final List<String> path) {
wrapAction(() async => account.client.webdav.delete(Uri(pathSegments: path)));
void delete(final PathUri path) {
wrapAction(() async => account.client.webdav.delete(path));
}

@override
void move(final List<String> path, final List<String> destination) {
wrapAction(() async => account.client.webdav.move(Uri(pathSegments: path), Uri(pathSegments: destination)));
void move(final PathUri path, final PathUri destination) {
wrapAction(() async => account.client.webdav.move(path, destination));
}

@override
void openFile(final List<String> path, final String etag, final String? mimeType) {
void openFile(final PathUri path, final String etag, final String? mimeType) {
wrapAction(
() async {
final file = await _cacheFile(path, etag);
Expand All @@ -98,7 +98,7 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
}

@override
void shareFileNative(final List<String> path, final String etag) {
void shareFileNative(final PathUri path, final String etag) {
wrapAction(
() async {
final file = await _cacheFile(path, etag);
Expand All @@ -115,36 +115,36 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
}

@override
void removeFavorite(final List<String> path) {
void removeFavorite(final PathUri path) {
wrapAction(
() async => account.client.webdav.proppatch(
Uri(pathSegments: path),
path,
set: WebDavProp(ocfavorite: 0),
),
);
}

@override
void rename(final List<String> path, final String name) {
void rename(final PathUri path, final String name) {
wrapAction(
() async => account.client.webdav.move(
Uri(pathSegments: path),
Uri(pathSegments: List.from(path)..last = name),
path,
PathUri(pathSegments: List.from(path.pathSegments)..last = name),
),
);
}

@override
void syncFile(final List<String> path) {
void syncFile(final PathUri path) {
wrapAction(
() async {
final file = File(
p.join(
p.joinAll([
await NeonPlatform.instance.userAccessibleAppDataPath,
account.humanReadableID,
'files',
path.join(Platform.pathSeparator),
),
...path.pathSegments,
]),
);
if (!file.parent.existsSync()) {
file.parent.createSync(recursive: true);
Expand All @@ -156,7 +156,7 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
}

@override
void uploadFile(final List<String> path, final String localPath) {
void uploadFile(final PathUri path, final String localPath) {
wrapAction(
() async {
final task = FilesUploadTask(
Expand All @@ -171,12 +171,12 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
);
}

Future<File> _cacheFile(final List<String> path, final String etag) async {
Future<File> _cacheFile(final PathUri path, final String etag) async {
final cacheDir = await getApplicationCacheDirectory();
final file = File(p.join(cacheDir.path, 'files', etag.replaceAll('"', ''), path.last));
final file = File(p.join(cacheDir.path, 'files', etag.replaceAll('"', ''), path.pathSegments.last));

if (!file.existsSync()) {
debugPrint('Downloading ${Uri(pathSegments: path)} since it does not exist');
debugPrint('Downloading $path since it does not exist');
if (!file.parent.existsSync()) {
await file.parent.create(recursive: true);
}
Expand All @@ -187,7 +187,7 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
}

Future<void> _downloadFile(
final List<String> path,
final PathUri path,
final File file,
) async {
final task = FilesDownloadTask(
Expand All @@ -200,7 +200,7 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
}

FilesBrowserBloc getNewFilesBrowserBloc({
final List<String>? initialPath,
final PathUri? initialPath,
}) =>
FilesBrowserBloc(
options,
Expand Down
23 changes: 19 additions & 4 deletions packages/neon/neon_files/lib/dialogs/choose_create.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class FilesChooseCreateDialog extends StatefulWidget {
});

final FilesBloc bloc;
final List<String> basePath;
final PathUri basePath;

@override
State<FilesChooseCreateDialog> createState() => _FilesChooseCreateDialogState();
Expand Down Expand Up @@ -43,7 +43,15 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
}
}
}
widget.bloc.uploadFile([...widget.basePath, p.basename(file.path)], file.path);
widget.bloc.uploadFile(
PathUri(
pathSegments: [
...widget.basePath.pathSegments,
p.basename(file.path),
],
),
file.path,
);
}

@override
Expand Down Expand Up @@ -104,12 +112,19 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
onTap: () async {
Navigator.of(context).pop();

final result = await showDialog<List<String>>(
final result = await showDialog<String>(
context: context,
builder: (final context) => const FilesCreateFolderDialog(),
);
if (result != null) {
widget.bloc.browser.createFolder([...widget.basePath, ...result]);
widget.bloc.browser.createFolder(
PathUri(
pathSegments: [
...widget.basePath.pathSegments,
result,
],
),
);
}
},
),
Expand Down
19 changes: 13 additions & 6 deletions packages/neon/neon_files/lib/dialogs/choose_folder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class FilesChooseFolderDialog extends StatelessWidget {
final FilesBrowserBloc bloc;
final FilesBloc filesBloc;

final List<String> originalPath;
final PathUri originalPath;

@override
Widget build(final BuildContext context) => AlertDialog(
Expand All @@ -28,7 +28,7 @@ class FilesChooseFolderDialog extends StatelessWidget {
mode: FilesBrowserMode.selectDirectory,
),
),
StreamBuilder<List<String>>(
StreamBuilder<PathUri>(
stream: bloc.path,
builder: (final context, final pathSnapshot) => pathSnapshot.hasData
? Container(
Expand All @@ -38,19 +38,26 @@ class FilesChooseFolderDialog extends StatelessWidget {
children: [
ElevatedButton(
onPressed: () async {
final result = await showDialog<List<String>>(
final result = await showDialog<String>(
context: context,
builder: (final context) => const FilesCreateFolderDialog(),
);
if (result != null) {
bloc.createFolder([...pathSnapshot.requireData, ...result]);
bloc.createFolder(
PathUri(
pathSegments: [
...pathSnapshot.requireData.pathSegments,
result,
],
),
);
}
},
child: Text(FilesLocalizations.of(context).folderCreate),
),
ElevatedButton(
onPressed: !(const ListEquality<String>().equals(originalPath, pathSnapshot.data))
? () => Navigator.of(context).pop(pathSnapshot.data)
onPressed: originalPath.path != pathSnapshot.requireData.path
? () => Navigator.of(context).pop(pathSnapshot.requireData)
: null,
child: Text(FilesLocalizations.of(context).folderChoose),
),
Expand Down
2 changes: 1 addition & 1 deletion packages/neon/neon_files/lib/dialogs/create_folder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class _FilesCreateFolderDialogState extends State<FilesCreateFolderDialog> {

void submit() {
if (formKey.currentState!.validate()) {
Navigator.of(context).pop(controller.text.split('/'));
Navigator.of(context).pop(controller.text);
}
}

Expand Down
7 changes: 2 additions & 5 deletions packages/neon/neon_files/lib/models/file_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ class FileDetails {

FileDetails.fromWebDav({
required final WebDavFile file,
required final List<String> path,
}) : path = List.from(path)..add(file.name),
}) : path = file.path,
isDirectory = file.isDirectory,
size = file.size,
etag = file.etag,
Expand Down Expand Up @@ -64,9 +63,7 @@ class FileDetails {
}
}

String get name => path.last;

final List<String> path;
final PathUri path;

final bool isDirectory;

Expand Down
8 changes: 4 additions & 4 deletions packages/neon/neon_files/lib/pages/details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class FilesDetailsPage extends StatelessWidget {
Widget build(final BuildContext context) => Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(details.name),
title: Text(details.path.basename),
),
body: SafeArea(
child: ListView(
Expand Down Expand Up @@ -42,9 +42,9 @@ class FilesDetailsPage extends StatelessWidget {
for (final entry in {
details.isDirectory
? FilesLocalizations.of(context).detailsFolderName
: FilesLocalizations.of(context).detailsFileName: details.name,
FilesLocalizations.of(context).detailsParentFolder:
details.path.length == 1 ? '/' : details.path.sublist(0, details.path.length - 1).join('/'),
: FilesLocalizations.of(context).detailsFileName: details.path.basename,
if (details.path.pathSegments.isNotEmpty)
FilesLocalizations.of(context).detailsParentFolder: details.path.dirname.path,
if (details.size != null) ...{
details.isDirectory
? FilesLocalizations.of(context).detailsFolderSize
Expand Down
Loading

0 comments on commit dd5ed6e

Please sign in to comment.