@@ -26,10 +26,13 @@ import {
2626} from '../utils/notifications/NotificationsHelper' ;
2727import { AsyncReturnType } from '../utils/TypeHelper' ;
2828import { safeTakeEvery as takeEvery , safeTakeLatest as takeLatest } from './SafeEffects' ;
29+ import { FSModule } from 'browserfs/dist/node/core/FS' ;
30+ import { rmFilesInDirRecursively , writeFileRecursively } from '../fileSystem/FileSystemUtils' ;
31+ import { refreshFileView } from '../fileSystemView/FileSystemViewList' ;
2932
3033const DISCOVERY_DOCS = [ 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest' ] ;
3134const SCOPES =
32- 'profile https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/userinfo.email' ;
35+ 'profile https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive ' ;
3336const UPLOAD_PATH = 'https://www.googleapis.com/upload/drive/v3/files' ;
3437const USER_INFO_PATH = 'https://www.googleapis.com/oauth2/v3/userinfo' ;
3538
@@ -87,10 +90,67 @@ export function* persistenceSaga(): SagaIterator {
8790 let toastKey : string | undefined ;
8891 try {
8992 yield call ( ensureInitialisedAndAuthorised ) ;
90- const { id, name, picked } = yield call ( pickFile , 'Pick a file to open' ) ;
93+ const { id, name, mimeType, picked } = yield call ( pickFile ,
94+ 'Pick a file/folder to open' ,
95+ {
96+ pickFolders : true
97+ }
98+ ) ; // id, name, picked gotten here
9199 if ( ! picked ) {
92100 return ;
93101 }
102+
103+ // Note: for mimeType, text/plain -> file, application/vnd.google-apps.folder -> folder
104+
105+ if ( mimeType === "application/vnd.google-apps.folder" ) { // handle folders
106+ yield call ( console . log , "is folder" ) ;
107+
108+ const fileList = yield call ( getFilesOfFolder , id , name ) ; // this needed the extra scope mimetypes to have every file
109+ // TODO: add type for each resp?
110+ yield call ( console . log , "fileList" , fileList ) ;
111+
112+
113+
114+ const fileSystem : FSModule | null = yield select (
115+ ( state : OverallState ) => state . fileSystem . inBrowserFileSystem
116+ ) ;
117+ // If the file system is not initialised, do nothing.
118+ if ( fileSystem === null ) {
119+ yield call ( console . log , "no filesystem!" ) ;
120+ return ;
121+ }
122+ yield call ( console . log , "there is a filesystem" ) ;
123+
124+ // rmdir everything TODO replace everything hardcoded with playground?
125+ yield call ( rmFilesInDirRecursively , fileSystem , "/playground" ) ;
126+
127+
128+ for ( const currFile of fileList ) {
129+ // TODO add code to actually load contents here
130+ const contents = yield call ( [ gapi . client . drive . files , 'get' ] , { fileId : currFile . id , alt : 'media' } ) ;
131+ yield call ( writeFileRecursively , fileSystem , "/playground" + currFile . path , contents . body ) ;
132+ }
133+
134+
135+
136+
137+
138+
139+
140+
141+
142+
143+
144+
145+
146+ // refresh needed
147+ yield put ( store . dispatch ( actions . removeEditorTabsForDirectory ( "playground" , "/" ) ) ) ; // deletes all active tabs
148+ yield call ( refreshFileView ) ; // refreshes folder view TODO super jank
149+
150+ return ;
151+ }
152+
153+
94154 const confirmOpen : boolean = yield call ( showSimpleConfirmDialog , {
95155 title : 'Opening from Google Drive' ,
96156 contents : (
@@ -112,7 +172,7 @@ export function* persistenceSaga(): SagaIterator {
112172 intent : Intent . PRIMARY
113173 } ) ;
114174
115- const { result : meta } = yield call ( [ gapi . client . drive . files , 'get' ] , {
175+ const { result : meta } = yield call ( [ gapi . client . drive . files , 'get' ] , { // get fileid here using gapi.client.drive.files
116176 fileId : id ,
117177 fields : 'appProperties'
118178 } ) ;
@@ -123,12 +183,12 @@ export function* persistenceSaga(): SagaIterator {
123183 if ( activeEditorTabIndex === null ) {
124184 throw new Error ( 'No active editor tab found.' ) ;
125185 }
126- yield put ( actions . updateEditorValue ( 'playground' , activeEditorTabIndex , contents . body ) ) ;
186+ yield put ( actions . updateEditorValue ( 'playground' , activeEditorTabIndex , contents . body ) ) ; // CONTENTS OF SELECTED FILE LOADED HERE
127187 yield put ( actions . playgroundUpdatePersistenceFile ( { id, name, lastSaved : new Date ( ) } ) ) ;
128188 if ( meta && meta . appProperties ) {
129189 yield put (
130190 actions . chapterSelect (
131- parseInt ( meta . appProperties . chapter || '4' , 10 ) as Chapter ,
191+ parseInt ( meta . appProperties . chapter || '4' , 10 ) as Chapter , // how does this work??
132192 meta . appProperties . variant || Variant . DEFAULT ,
133193 'playground'
134194 )
@@ -452,6 +512,7 @@ function pickFile(
452512 . setCallback ( ( data : any ) => {
453513 switch ( data [ google . picker . Response . ACTION ] ) {
454514 case google . picker . Action . PICKED : {
515+ console . log ( "data" , data ) ;
455516 const { id, name, mimeType, parentId } = data . docs [ 0 ] ;
456517 res ( { id, name, mimeType, parentId, picked : true } ) ;
457518 break ;
@@ -468,6 +529,53 @@ function pickFile(
468529 } ) ;
469530}
470531
532+ async function getFilesOfFolder ( // recursively get files
533+ folderId : string ,
534+ currFolderName : string ,
535+ currPath : string = '' // pass in name of folder picked
536+ ) {
537+ console . log ( folderId , currPath , currFolderName ) ;
538+ let fileList : gapi . client . drive . File [ ] | undefined ;
539+
540+ await gapi . client . drive . files . list ( {
541+ q : '\'' + folderId + '\'' + ' in parents and trashed = false' ,
542+ } ) . then ( res => {
543+ fileList = res . result . files
544+ } ) ;
545+
546+ console . log ( "fileList" , fileList ) ;
547+
548+ if ( ! fileList || fileList . length === 0 ) {
549+ return [ {
550+ name : currFolderName ,
551+ id : folderId ,
552+ path : currPath + '/' + currFolderName ,
553+ isFile : false
554+ } ] ;
555+ }
556+
557+
558+ let ans : any [ ] = [ ] ; // TODO: add type for each resp?
559+ for ( const currFile of fileList ) {
560+ if ( currFile . mimeType === "application/vnd.google-apps.folder" ) { // folder
561+ ans = ans . concat ( await
562+ getFilesOfFolder ( currFile . id ! , currFile . name ! , currPath + '/' + currFolderName )
563+ ) ;
564+ }
565+ else { // file
566+ console . log ( "found file " + currFile . name ) ;
567+ ans . push ( {
568+ name : currFile . name ,
569+ id : currFile . id ,
570+ path : currPath + '/' + currFolderName + '/' + currFile . name ,
571+ isFile : true
572+ } ) ;
573+ }
574+ }
575+
576+ return ans ;
577+ }
578+
471579function createFile (
472580 filename : string ,
473581 parent : string ,
0 commit comments