@@ -69,23 +69,15 @@ export class FileSystemDrive implements Contents.IDrive {
69
69
} ;
70
70
}
71
71
72
- let parentHandle = root ;
73
- // If requesting a file/directory that is not under root, we need the right directory handle
74
- for ( const subPath of path . split ( '/' ) . slice ( 0 , - 1 ) ) {
75
- parentHandle = await parentHandle . getDirectoryHandle ( subPath ) ;
76
- }
72
+ const parentHandle = await this . getParentHandle ( path ) ;
77
73
78
74
const parentPath = PathExt . dirname ( path ) ;
79
75
const localPath = PathExt . basename ( path ) ;
80
76
81
77
let localHandle : FileSystemDirectoryHandle | FileSystemFileHandle ;
82
78
83
- const currentContent = await toArray ( parentHandle . values ( ) ) ;
84
-
85
79
if ( localPath ) {
86
- localHandle = currentContent . filter (
87
- element => element . name === localPath
88
- ) [ 0 ] ;
80
+ localHandle = await this . getHandle ( parentHandle , localPath ) ;
89
81
} else {
90
82
localHandle = parentHandle ;
91
83
}
@@ -137,7 +129,7 @@ export class FileSystemDrive implements Contents.IDrive {
137
129
}
138
130
139
131
return {
140
- name : PathExt . basename ( parentPath ) ,
132
+ name : localPath ,
141
133
path : PathExt . join ( parentPath , localPath ) ,
142
134
last_modified : '' ,
143
135
created : '' ,
@@ -155,8 +147,43 @@ export class FileSystemDrive implements Contents.IDrive {
155
147
throw new Error ( 'Method not implemented.' ) ;
156
148
}
157
149
158
- newUntitled ( options ?: Contents . ICreateOptions ) : Promise < Contents . IModel > {
159
- throw new Error ( 'Method not implemented.' ) ;
150
+ async newUntitled (
151
+ options ?: Contents . ICreateOptions
152
+ ) : Promise < Contents . IModel > {
153
+ const type = options ?. type || 'directory' ;
154
+ const path = PathExt . join (
155
+ options ?. path || '' ,
156
+ type === 'directory' ? 'Untitled Folder' : 'untitled'
157
+ ) ;
158
+ const ext = options ?. ext || 'txt' ;
159
+
160
+ const parentHandle = await this . getParentHandle ( path ) ;
161
+
162
+ const parentPath = PathExt . dirname ( path ) ;
163
+ let localPath = PathExt . basename ( path ) ;
164
+ const name = localPath ;
165
+
166
+ if ( type === 'directory' ) {
167
+ let i = 1 ;
168
+ while ( await this . hasHandle ( parentHandle , localPath ) ) {
169
+ localPath = `${ name } ${ i ++ } ` ;
170
+ }
171
+
172
+ await parentHandle . getDirectoryHandle ( localPath , { create : true } ) ;
173
+
174
+ return this . get ( PathExt . join ( parentPath , localPath ) ) ;
175
+ } else {
176
+ let i = 1 ;
177
+ while ( await this . hasHandle ( parentHandle , `${ localPath } .${ ext } ` ) ) {
178
+ localPath = `${ name } ${ i ++ } ` ;
179
+ }
180
+
181
+ const filename = `${ localPath } .${ ext } ` ;
182
+
183
+ await parentHandle . getFileHandle ( filename , { create : true } ) ;
184
+
185
+ return this . get ( PathExt . join ( parentPath , filename ) ) ;
186
+ }
160
187
}
161
188
162
189
delete ( path : string ) : Promise < void > {
@@ -171,17 +198,7 @@ export class FileSystemDrive implements Contents.IDrive {
171
198
path : string ,
172
199
options ?: Partial < Contents . IModel >
173
200
) : Promise < Contents . IModel > {
174
- const root = this . _rootHandle ;
175
-
176
- if ( ! root ) {
177
- throw new Error ( 'No root file handle' ) ;
178
- }
179
-
180
- let parentHandle = root ;
181
- // If saving a file that is not under root, we need the right directory handle
182
- for ( const subPath of path . split ( '/' ) . slice ( 0 , - 1 ) ) {
183
- parentHandle = await parentHandle . getDirectoryHandle ( subPath ) ;
184
- }
201
+ const parentHandle = await this . getParentHandle ( path ) ;
185
202
186
203
const handle = await parentHandle . getFileHandle ( PathExt . basename ( path ) ) ;
187
204
const writable = await handle . createWritable ( { } ) ;
@@ -195,6 +212,7 @@ export class FileSystemDrive implements Contents.IDrive {
195
212
await writable . write ( content ) ;
196
213
}
197
214
await writable . close ( ) ;
215
+
198
216
return this . get ( path ) ;
199
217
}
200
218
@@ -226,6 +244,50 @@ export class FileSystemDrive implements Contents.IDrive {
226
244
return Promise . resolve ( void 0 ) ;
227
245
}
228
246
247
+ private async getParentHandle (
248
+ path : string
249
+ ) : Promise < FileSystemDirectoryHandle > {
250
+ const root = this . _rootHandle ;
251
+
252
+ if ( ! root ) {
253
+ throw new Error ( 'No root file handle' ) ;
254
+ }
255
+
256
+ let parentHandle = root ;
257
+ // If saving a file that is not under root, we need the right directory handle
258
+ for ( const subPath of path . split ( '/' ) . slice ( 0 , - 1 ) ) {
259
+ parentHandle = await parentHandle . getDirectoryHandle ( subPath ) ;
260
+ }
261
+
262
+ return parentHandle ;
263
+ }
264
+
265
+ private async getHandle (
266
+ parentHandle : FileSystemDirectoryHandle ,
267
+ localPath : string
268
+ ) : Promise < FileSystemDirectoryHandle | FileSystemFileHandle > {
269
+ const content = await toArray ( parentHandle . values ( ) ) ;
270
+
271
+ const matches = content . filter ( element => element . name === localPath ) ;
272
+
273
+ if ( matches . length ) {
274
+ return matches [ 0 ] ;
275
+ }
276
+
277
+ throw new Error ( `${ localPath } does not exist.` ) ;
278
+ }
279
+
280
+ private async hasHandle (
281
+ parentHandle : FileSystemDirectoryHandle ,
282
+ localPath : string
283
+ ) : Promise < boolean > {
284
+ const content = await toArray ( parentHandle . values ( ) ) ;
285
+
286
+ const matches = content . filter ( element => element . name === localPath ) ;
287
+
288
+ return Boolean ( matches . length ) ;
289
+ }
290
+
229
291
private _isDisposed = false ;
230
292
private _fileChanged = new Signal < Contents . IDrive , Contents . IChangedArgs > (
231
293
this
0 commit comments