Skip to content

Commit eade429

Browse files
committed
refactor(nextcloud,neon_files): Introduce PathUri for WebDAV path handling
Signed-off-by: jld3103 <jld3103yt@gmail.com>
1 parent 1f45ff4 commit eade429

File tree

19 files changed

+482
-237
lines changed

19 files changed

+482
-237
lines changed
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
part of '../neon_files.dart';
22

33
abstract interface class FilesBrowserBlocEvents {
4-
void setPath(final List<String> path);
4+
void setPath(final PathUri uri);
55

6-
void createFolder(final List<String> path);
6+
void createFolder(final PathUri uri);
77
}
88

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

12-
BehaviorSubject<List<String>> get path;
12+
BehaviorSubject<PathUri> get uri;
1313
}
1414

1515
class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents, FilesBrowserBlocStates {
1616
FilesBrowserBloc(
1717
this.options,
1818
this.account, {
19-
final List<String>? initialPath,
19+
final PathUri? initialPath,
2020
}) {
2121
if (initialPath != null) {
22-
path.add(initialPath);
22+
uri.add(initialPath);
2323
}
2424

2525
unawaited(refresh());
@@ -31,24 +31,24 @@ class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents
3131
@override
3232
void dispose() {
3333
unawaited(files.close());
34-
unawaited(path.close());
34+
unawaited(uri.close());
3535
super.dispose();
3636
}
3737

3838
@override
3939
BehaviorSubject<Result<List<WebDavFile>>> files = BehaviorSubject<Result<List<WebDavFile>>>();
4040

4141
@override
42-
BehaviorSubject<List<String>> path = BehaviorSubject<List<String>>.seeded([]);
42+
BehaviorSubject<PathUri> uri = BehaviorSubject.seeded(PathUri.cwd());
4343

4444
@override
4545
Future<void> refresh() async {
4646
await RequestManager.instance.wrapWebDav<List<WebDavFile>>(
4747
account.id,
48-
'files-${path.value.join('/')}',
48+
'files-${uri.value.path}',
4949
files,
5050
() => account.client.webdav.propfind(
51-
Uri(pathSegments: path.value),
51+
uri.value,
5252
prop: WebDavPropWithoutValues.fromBools(
5353
davgetcontenttype: true,
5454
davgetetag: true,
@@ -65,13 +65,13 @@ class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents
6565
}
6666

6767
@override
68-
void setPath(final List<String> p) {
69-
path.add(p);
68+
void setPath(final PathUri uri) {
69+
this.uri.add(uri);
7070
unawaited(refresh());
7171
}
7272

7373
@override
74-
void createFolder(final List<String> path) {
75-
wrapAction(() async => account.client.webdav.mkcol(Uri(pathSegments: path)));
74+
void createFolder(final PathUri uri) {
75+
wrapAction(() async => account.client.webdav.mkcol(uri));
7676
}
7777
}

packages/neon/neon_files/lib/blocs/files.dart

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
part of '../neon_files.dart';
22

33
abstract interface class FilesBlocEvents {
4-
void uploadFile(final List<String> path, final String localPath);
4+
void uploadFile(final PathUri uri, final String localPath);
55

6-
void syncFile(final List<String> path);
6+
void syncFile(final PathUri uri);
77

8-
void openFile(final List<String> path, final String etag, final String? mimeType);
8+
void openFile(final PathUri uri, final String etag, final String? mimeType);
99

10-
void shareFileNative(final List<String> path, final String etag);
10+
void shareFileNative(final PathUri uri, final String etag);
1111

12-
void delete(final List<String> path);
12+
void delete(final PathUri uri);
1313

14-
void rename(final List<String> path, final String name);
14+
void rename(final PathUri uri, final String name);
1515

16-
void move(final List<String> path, final List<String> destination);
16+
void move(final PathUri uri, final PathUri destination);
1717

18-
void copy(final List<String> path, final List<String> destination);
18+
void copy(final PathUri uri, final PathUri destination);
1919

20-
void addFavorite(final List<String> path);
20+
void addFavorite(final PathUri uri);
2121

22-
void removeFavorite(final List<String> path);
22+
void removeFavorite(final PathUri uri);
2323
}
2424

2525
abstract interface class FilesBlocStates {
@@ -58,35 +58,35 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
5858
BehaviorSubject<List<FilesTask>> tasks = BehaviorSubject<List<FilesTask>>.seeded([]);
5959

6060
@override
61-
void addFavorite(final List<String> path) {
61+
void addFavorite(final PathUri uri) {
6262
wrapAction(
6363
() async => account.client.webdav.proppatch(
64-
Uri(pathSegments: path),
64+
uri,
6565
set: WebDavProp(ocfavorite: 1),
6666
),
6767
);
6868
}
6969

7070
@override
71-
void copy(final List<String> path, final List<String> destination) {
72-
wrapAction(() async => account.client.webdav.copy(Uri(pathSegments: path), Uri(pathSegments: destination)));
71+
void copy(final PathUri uri, final PathUri destination) {
72+
wrapAction(() async => account.client.webdav.copy(uri, destination));
7373
}
7474

7575
@override
76-
void delete(final List<String> path) {
77-
wrapAction(() async => account.client.webdav.delete(Uri(pathSegments: path)));
76+
void delete(final PathUri uri) {
77+
wrapAction(() async => account.client.webdav.delete(uri));
7878
}
7979

8080
@override
81-
void move(final List<String> path, final List<String> destination) {
82-
wrapAction(() async => account.client.webdav.move(Uri(pathSegments: path), Uri(pathSegments: destination)));
81+
void move(final PathUri uri, final PathUri destination) {
82+
wrapAction(() async => account.client.webdav.move(uri, destination));
8383
}
8484

8585
@override
86-
void openFile(final List<String> path, final String etag, final String? mimeType) {
86+
void openFile(final PathUri uri, final String etag, final String? mimeType) {
8787
wrapAction(
8888
() async {
89-
final file = await _cacheFile(path, etag);
89+
final file = await _cacheFile(uri, etag);
9090

9191
final result = await OpenFile.open(file.path, type: mimeType);
9292
if (result.type != ResultType.done) {
@@ -98,10 +98,10 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
9898
}
9999

100100
@override
101-
void shareFileNative(final List<String> path, final String etag) {
101+
void shareFileNative(final PathUri uri, final String etag) {
102102
wrapAction(
103103
() async {
104-
final file = await _cacheFile(path, etag);
104+
final file = await _cacheFile(uri, etag);
105105

106106
await Share.shareXFiles([XFile(file.path)]);
107107
},
@@ -115,52 +115,52 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
115115
}
116116

117117
@override
118-
void removeFavorite(final List<String> path) {
118+
void removeFavorite(final PathUri uri) {
119119
wrapAction(
120120
() async => account.client.webdav.proppatch(
121-
Uri(pathSegments: path),
121+
uri,
122122
set: WebDavProp(ocfavorite: 0),
123123
),
124124
);
125125
}
126126

127127
@override
128-
void rename(final List<String> path, final String name) {
128+
void rename(final PathUri uri, final String name) {
129129
wrapAction(
130130
() async => account.client.webdav.move(
131-
Uri(pathSegments: path),
132-
Uri(pathSegments: List.from(path)..last = name),
131+
uri,
132+
uri.rename(name),
133133
),
134134
);
135135
}
136136

137137
@override
138-
void syncFile(final List<String> path) {
138+
void syncFile(final PathUri uri) {
139139
wrapAction(
140140
() async {
141141
final file = File(
142-
p.join(
142+
p.joinAll([
143143
await NeonPlatform.instance.userAccessibleAppDataPath,
144144
account.humanReadableID,
145145
'files',
146-
path.join(Platform.pathSeparator),
147-
),
146+
...uri.pathSegments,
147+
]),
148148
);
149149
if (!file.parent.existsSync()) {
150150
file.parent.createSync(recursive: true);
151151
}
152-
await _downloadFile(path, file);
152+
await _downloadFile(uri, file);
153153
},
154154
disableTimeout: true,
155155
);
156156
}
157157

158158
@override
159-
void uploadFile(final List<String> path, final String localPath) {
159+
void uploadFile(final PathUri uri, final String localPath) {
160160
wrapAction(
161161
() async {
162162
final task = FilesUploadTask(
163-
path: path,
163+
uri: uri,
164164
file: File(localPath),
165165
);
166166
tasks.add(tasks.value..add(task));
@@ -171,27 +171,27 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
171171
);
172172
}
173173

174-
Future<File> _cacheFile(final List<String> path, final String etag) async {
174+
Future<File> _cacheFile(final PathUri uri, final String etag) async {
175175
final cacheDir = await getApplicationCacheDirectory();
176-
final file = File(p.join(cacheDir.path, 'files', etag.replaceAll('"', ''), path.last));
176+
final file = File(p.join(cacheDir.path, 'files', etag.replaceAll('"', ''), uri.name));
177177

178178
if (!file.existsSync()) {
179-
debugPrint('Downloading ${Uri(pathSegments: path)} since it does not exist');
179+
debugPrint('Downloading $uri since it does not exist');
180180
if (!file.parent.existsSync()) {
181181
await file.parent.create(recursive: true);
182182
}
183-
await _downloadFile(path, file);
183+
await _downloadFile(uri, file);
184184
}
185185

186186
return file;
187187
}
188188

189189
Future<void> _downloadFile(
190-
final List<String> path,
190+
final PathUri uri,
191191
final File file,
192192
) async {
193193
final task = FilesDownloadTask(
194-
path: path,
194+
uri: uri,
195195
file: file,
196196
);
197197
tasks.add(tasks.value..add(task));
@@ -200,12 +200,12 @@ class FilesBloc extends InteractiveBloc implements FilesBlocEvents, FilesBlocSta
200200
}
201201

202202
FilesBrowserBloc getNewFilesBrowserBloc({
203-
final List<String>? initialPath,
203+
final PathUri? initialUri,
204204
}) =>
205205
FilesBrowserBloc(
206206
options,
207207
account,
208-
initialPath: initialPath,
208+
initialPath: initialUri,
209209
);
210210

211211
void _downloadParallelismListener() {

packages/neon/neon_files/lib/dialogs/choose_create.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class FilesChooseCreateDialog extends StatefulWidget {
88
});
99

1010
final FilesBloc bloc;
11-
final List<String> basePath;
11+
final PathUri basePath;
1212

1313
@override
1414
State<FilesChooseCreateDialog> createState() => _FilesChooseCreateDialogState();
@@ -43,7 +43,10 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
4343
}
4444
}
4545
}
46-
widget.bloc.uploadFile([...widget.basePath, p.basename(file.path)], file.path);
46+
widget.bloc.uploadFile(
47+
widget.basePath.join(PathUri.parse(p.basename(file.path))),
48+
file.path,
49+
);
4750
}
4851

4952
@override
@@ -104,12 +107,12 @@ class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
104107
onTap: () async {
105108
Navigator.of(context).pop();
106109

107-
final result = await showDialog<List<String>>(
110+
final result = await showDialog<String>(
108111
context: context,
109112
builder: (final context) => const FilesCreateFolderDialog(),
110113
);
111114
if (result != null) {
112-
widget.bloc.browser.createFolder([...widget.basePath, ...result]);
115+
widget.bloc.browser.createFolder(widget.basePath.join(PathUri.parse(result)));
113116
}
114117
},
115118
),

packages/neon/neon_files/lib/dialogs/choose_folder.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class FilesChooseFolderDialog extends StatelessWidget {
1111
final FilesBrowserBloc bloc;
1212
final FilesBloc filesBloc;
1313

14-
final List<String> originalPath;
14+
final PathUri originalPath;
1515

1616
@override
1717
Widget build(final BuildContext context) => AlertDialog(
@@ -28,29 +28,29 @@ class FilesChooseFolderDialog extends StatelessWidget {
2828
mode: FilesBrowserMode.selectDirectory,
2929
),
3030
),
31-
StreamBuilder<List<String>>(
32-
stream: bloc.path,
33-
builder: (final context, final pathSnapshot) => pathSnapshot.hasData
31+
StreamBuilder<PathUri>(
32+
stream: bloc.uri,
33+
builder: (final context, final uriSnapshot) => uriSnapshot.hasData
3434
? Container(
3535
margin: const EdgeInsets.all(10),
3636
child: Row(
3737
mainAxisAlignment: MainAxisAlignment.spaceBetween,
3838
children: [
3939
ElevatedButton(
4040
onPressed: () async {
41-
final result = await showDialog<List<String>>(
41+
final result = await showDialog<String>(
4242
context: context,
4343
builder: (final context) => const FilesCreateFolderDialog(),
4444
);
4545
if (result != null) {
46-
bloc.createFolder([...pathSnapshot.requireData, ...result]);
46+
bloc.createFolder(uriSnapshot.requireData.join(PathUri.parse(result)));
4747
}
4848
},
4949
child: Text(FilesLocalizations.of(context).folderCreate),
5050
),
5151
ElevatedButton(
52-
onPressed: !(const ListEquality<String>().equals(originalPath, pathSnapshot.data))
53-
? () => Navigator.of(context).pop(pathSnapshot.data)
52+
onPressed: originalPath != uriSnapshot.requireData
53+
? () => Navigator.of(context).pop(uriSnapshot.requireData)
5454
: null,
5555
child: Text(FilesLocalizations.of(context).folderChoose),
5656
),

packages/neon/neon_files/lib/dialogs/create_folder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class _FilesCreateFolderDialogState extends State<FilesCreateFolderDialog> {
2222

2323
void submit() {
2424
if (formKey.currentState!.validate()) {
25-
Navigator.of(context).pop(controller.text.split('/'));
25+
Navigator.of(context).pop(controller.text);
2626
}
2727
}
2828

0 commit comments

Comments
 (0)