import FsDriverBase from '@joplin/lib/fs-driver-base' ; const RNFetchBlob = require ( 'rn-fetch-blob' ) . default ; const RNFS = require ( 'react-native-fs' ) ; export default class FsDriverRN extends FsDriverBase { public appendFileSync ( ) { throw new Error ( 'Not implemented' ) ; } public appendFile ( path , content , encoding = 'base64' ) { return RNFS . appendFile ( path , content , encoding ) ; } public writeFile ( path , content , encoding = 'base64' ) { return RNFetchBlob . fs . writeFile ( path , content , encoding ) ; } public async remove ( path ) { return await this . unlink ( path ) ; } private rnfsStatToStd_ ( stat , path ) { return { birthtime : stat . ctime ? stat . ctime : stat . mtime , mtime : stat . mtime , isDirectory : ( ) => stat . isDirectory ( ) , path : path , size : stat . size , } ; } public async readDirStats ( path , options = null ) { if ( ! options ) options = { } ; if ( ! ( 'recursive' in options ) ) options . recursive = false ; let items = [ ] ; try { items = await RNFS . readDir ( path ) ; } catch ( error ) { throw new Error ( `Could not read directory: ${ path }: ${ error . message }` ) ; } let output = [ ] ; for ( let i = 0 ; i < items . length ; i ++ ) { const item = items [ i ] ; const relativePath = item . path . substr ( path . length + 1 ) ; output . push ( this . rnfsStatToStd_ ( item , relativePath ) ) ; output = await this . readDirStatsHandleRecursion_ ( path , item , output , options ) ; } return output ; } public async move ( source , dest ) { return RNFS . moveFile ( source , dest ) ; } public async exists ( path ) { return RNFS . exists ( path ) ; } public async mkdir ( path ) { return RNFS . mkdir ( path ) ; } public async stat ( path ) { try { const r = await RNFS . stat ( path ) ; return this . rnfsStatToStd_ ( r , path ) ; } catch ( error ) { if ( error && ( ( error . message && error . message . indexOf ( 'exist' ) >= 0 ) || error . code === 'ENOENT' ) ) { return null ; } else { throw error ; } } } public async setTimestamp ( ) { } public async open ( path , mode ) { const stat = await this . stat ( path ) ; return { path : path , offset : 0 , mode : mode , stat : stat , } ; } public close ( ) { return null ; } public readFile ( path , encoding = 'utf8' ) { if ( encoding === 'Buffer' ) throw new Error ( 'Raw buffer output not supported for FsDriverRN.readFile' ) ; return RNFS . readFile ( path , encoding ) ; } public async copy ( source , dest ) { let retry = false ; try { await RNFS . copyFile ( source , dest ) ; } catch ( error ) { retry = true ; await this . unlink ( dest ) ; } if ( retry ) await RNFS . copyFile ( source , dest ) ; } public async unlink ( path ) { try { await RNFS . unlink ( path ) ; } catch ( error ) { if ( error && ( ( error . message && error . message . indexOf ( 'exist' ) >= 0 ) || error . code === 'ENOENT' ) ) { } else { throw error ; } } } public async readFileChunk ( handle , length , encoding = 'base64' ) { if ( handle . offset + length > handle . stat . size ) { length = handle . stat . size - handle . offset ; } if ( ! length ) return null ; const output = await RNFS . read ( handle . path , length , handle . offset , encoding ) ; handle . offset += length ; return output ? output : null ; } public resolve ( path ) { throw new Error ( `Not implemented: resolve(): ${ path }` ) ; } public resolveRelativePathWithinDir ( _baseDir , relativePath ) { throw new Error ( `Not implemented: resolveRelativePathWithinDir(): ${ relativePath }` ) ; } public async md5File ( path ) { throw new Error ( `Not implemented: md5File(): ${ path }` ) ; } }