@@ -28,7 +28,7 @@ import {
28
28
import { AsyncReturnType } from '../utils/TypeHelper' ;
29
29
import { safeTakeEvery as takeEvery , safeTakeLatest as takeLatest } from './SafeEffects' ;
30
30
import { FSModule } from 'browserfs/dist/node/core/FS' ;
31
- import { rmFilesInDirRecursively , writeFileRecursively } from '../fileSystem/FileSystemUtils' ;
31
+ import { retrieveFilesInWorkspaceAsRecord , rmFilesInDirRecursively , writeFileRecursively } from '../fileSystem/FileSystemUtils' ;
32
32
import { refreshFileView } from '../fileSystemView/FileSystemViewList' ;
33
33
34
34
const DISCOVERY_DOCS = [ 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest' ] ;
@@ -173,8 +173,6 @@ export function* persistenceSaga(): SagaIterator {
173
173
174
174
yield call ( showSuccessMessage , `Loaded folder ${ name } .` , 1000 ) ;
175
175
176
- // TODO the Google Drive button isn't blue even after loading stuff
177
-
178
176
return ;
179
177
}
180
178
@@ -347,10 +345,80 @@ export function* persistenceSaga(): SagaIterator {
347
345
}
348
346
} ) ;
349
347
350
- yield takeEvery (
348
+ yield takeEvery ( // TODO work on this
351
349
PERSISTENCE_SAVE_ALL ,
352
350
function * ( ) {
353
- yield console . log ( "pers save all!" ) ;
351
+ // Case init: Don't care, delete everything in remote and save again
352
+ // Callable only if persistenceObject isFolder
353
+
354
+ const [ currFolderObject ] = yield select (
355
+ ( state : OverallState ) => [
356
+ state . playground . persistenceObject
357
+ ]
358
+ ) ;
359
+ if ( ! currFolderObject ) {
360
+ yield call ( console . log , "no obj!" ) ;
361
+ return ;
362
+ }
363
+
364
+ console . log ( "currFolderObj" , currFolderObject ) ;
365
+
366
+ const fileSystem : FSModule | null = yield select (
367
+ ( state : OverallState ) => state . fileSystem . inBrowserFileSystem
368
+ ) ;
369
+ // If the file system is not initialised, do nothing.
370
+ if ( fileSystem === null ) {
371
+ yield call ( console . log , "no filesystem!" ) ;
372
+ return ;
373
+ }
374
+ yield call ( console . log , "there is a filesystem" ) ;
375
+
376
+ const currFiles : Record < string , string > = yield call ( retrieveFilesInWorkspaceAsRecord , "playground" , fileSystem ) ;
377
+ // TODO this does not get bare folders, is it a necessity?
378
+ // behaviour of open folder for GDrive loads even empty folders
379
+ yield call ( console . log , "currfiles" , currFiles ) ;
380
+
381
+ //const fileNameRegex = new RegExp('@"[^\\]+$"');
382
+ for ( const currFullFilePath of Object . keys ( currFiles ) ) {
383
+ const currFileContent = currFiles [ currFullFilePath ] ;
384
+ const regexResult = / ^ ( .* [ \\ \/ ] ) ? ( \. * .* ?) ( \. [ ^ . ] + ?| ) $ / . exec ( currFullFilePath ) ;
385
+ if ( regexResult === null ) {
386
+ yield call ( console . log , "Regex null!" ) ;
387
+ continue ;
388
+ }
389
+ const currFileName = regexResult [ 2 ] + regexResult [ 3 ] ;
390
+ const currFileParentFolders : string [ ] = regexResult [ 1 ] . slice (
391
+ ( "/playground/" + currFolderObject . name + "/" ) . length , - 1 )
392
+ . split ( "/" ) ;
393
+
394
+ // /fold1/ becomes ["fold1"]
395
+ // /fold1/fold2/ becomes ["fold1", "fold2"]
396
+ // If in top level folder, becomes [""]
397
+
398
+ yield call ( getContainingFolderIdRecursively , currFileParentFolders ,
399
+ currFolderObject . id ) ;
400
+
401
+ // yield call(
402
+ // createFile,
403
+ // fileName,
404
+ // currFolderObject.id,
405
+
406
+ // );
407
+
408
+ yield call ( console . log , "name" , currFileName , "content" , currFileContent
409
+ , "path" , currFileParentFolders ) ;
410
+ }
411
+
412
+
413
+ // Case 1: Open picker to select location for saving, similar to save all
414
+ // 1a No folder exists on remote, simple save
415
+ // 1b Folder exists, popup confirmation to destroy remote folder and replace
416
+
417
+ // Case 2: Location already decided (PersistenceObject exists with isFolder === true)
418
+ // TODO: Modify functions here to update string[] in persistenceObject for Folder
419
+ // 2a No changes to folder/file structure, only content needs updating
420
+ // TODO Maybe update the colors of the side view as well to reflect which have been modified?
421
+ // 2b Changes to folder/file structure -> Delete and replace changed files
354
422
}
355
423
) ;
356
424
@@ -595,6 +663,52 @@ async function getFilesOfFolder( // recursively get files
595
663
return ans ;
596
664
}
597
665
666
+ async function getContainingFolderIdRecursively ( // TODO memoize?
667
+ parentFolders : string [ ] ,
668
+ topFolderId : string ,
669
+ currDepth : integer = 0
670
+ ) : Promise < string > {
671
+ if ( parentFolders [ 0 ] === '' || currDepth === parentFolders . length ) {
672
+ return topFolderId ;
673
+ }
674
+ const currFolderName = parentFolders [ parentFolders . length - 1 - currDepth ] ;
675
+
676
+ const immediateParentFolderId = await getContainingFolderIdRecursively (
677
+ parentFolders ,
678
+ topFolderId ,
679
+ currDepth + 1
680
+ ) ;
681
+
682
+ let folderList : gapi . client . drive . File [ ] | undefined ;
683
+
684
+ await gapi . client . drive . files . list ( {
685
+ q : '\'' + immediateParentFolderId + '\'' + ' in parents and trashed = false and mimeType = \''
686
+ + "application/vnd.google-apps.folder" + '\'' ,
687
+ } ) . then ( res => {
688
+ folderList = res . result . files
689
+ } ) ;
690
+
691
+ if ( ! folderList ) {
692
+ console . log ( "create!" , currFolderName ) ;
693
+ const newId = await createFolderAndReturnId ( immediateParentFolderId , currFolderName ) ;
694
+ return newId ;
695
+ }
696
+
697
+ console . log ( "folderList gcfir" , folderList ) ;
698
+
699
+ for ( const currFolder of folderList ) {
700
+ if ( currFolder . name === currFolderName ) {
701
+ console . log ( "found " , currFolder . name , " and id is " , currFolder . id ) ;
702
+ return currFolder . id ! ;
703
+ }
704
+ }
705
+
706
+ console . log ( "create!" , currFolderName ) ;
707
+ const newId = await createFolderAndReturnId ( immediateParentFolderId , currFolderName ) ;
708
+ return newId ;
709
+
710
+ }
711
+
598
712
function createFile (
599
713
filename : string ,
600
714
parent : string ,
@@ -606,13 +720,15 @@ function createFile(
606
720
const meta = {
607
721
name,
608
722
mimeType,
609
- parents : [ parent ] ,
723
+ parents : [ parent ] , //[id of the parent folder as a string]
610
724
appProperties : {
611
725
source : true ,
612
726
...config
613
727
}
614
728
} ;
615
729
730
+ console . log ( "METATAAAAAA" , meta ) ;
731
+
616
732
const { body, headers } = createMultipartBody ( meta , contents , mimeType ) ;
617
733
618
734
return gapi . client
@@ -644,6 +760,8 @@ function updateFile(
644
760
}
645
761
} ;
646
762
763
+ console . log ( "META" , meta ) ;
764
+
647
765
const { body, headers } = createMultipartBody ( meta , contents , mimeType ) ;
648
766
649
767
return gapi . client . request ( {
@@ -657,6 +775,32 @@ function updateFile(
657
775
} ) ;
658
776
}
659
777
778
+ function createFolderAndReturnId (
779
+ parentFolderId : string ,
780
+ folderName : string
781
+ ) : Promise < string > {
782
+ const name = folderName ;
783
+ const mimeType = 'application/vnd.google-apps.folder' ;
784
+ const meta = {
785
+ name,
786
+ mimeType,
787
+ parents : [ parentFolderId ] , //[id of the parent folder as a string]
788
+ }
789
+
790
+ const { body, headers } = createMultipartBody ( meta , '' , mimeType ) ;
791
+
792
+ return gapi . client
793
+ . request ( {
794
+ path : UPLOAD_PATH ,
795
+ method : 'POST' ,
796
+ params : {
797
+ uploadType : 'multipart'
798
+ } ,
799
+ headers,
800
+ body
801
+ } ) . then ( res => res . result . id )
802
+ } ;
803
+
660
804
function createMultipartBody (
661
805
meta : any ,
662
806
contents : string ,
0 commit comments