import { action , computed , observable , toJS } from 'mobx' ; import { RefObject } from 'react' ; import { CustomFileType , FileNameTypes , FileTransformType , FileTypes , FileWithMetadata , InputFilesType } from '~@types/fileTypes' ; import formats from '../dist/formats' ; import AbstractStore from './store' ; import TerminalStore from './terminalStore' ; class FileStore extends AbstractStore { @ observable terminalStore = TerminalStore ; @ observable oldFiles : Array < string > = [ ] ; @ observable currentFile : CustomFileType = { name : '' , type : 'video' , path : '' } ; @ observable files : InputFilesType = { } ; /**
     * File object for electron, only contains metadata and cleans out the entire file
     *
     * When this object is defined the main file object this.files will be deleted
     */ @ observable loadedFiles : FileNameTypes = { } ; @ observable dropzoneRef : RefObject < HTMLDivElement > | undefined ; constructor ( ) { super ( ) ; this . init ( ) ; } @ action init = ( ) => { this . oldFiles = [ ] ; this . currentFile = { name : '' , type : 'video' , path : '' } ; this . files = { } ; } ; param fileName getFileExtension = ( fileName ) => { const filePathArr = fileName . split ( '.' ) ; return filePathArr [ filePathArr . length - 1 ] ; } ; param inputSize sizeHumanReadable = ( inputSize ) => { let fileSize = inputSize ; const fSExt = [ 'Bytes' , 'KB' , 'MB' , 'GB' ] ; let i = 0 ; while ( fileSize > 900 ) { fileSize /= 1024 ; i += 1 ; } const exactSize = `${ Math . round ( fileSize * 100 ) / 100 } ${ fSExt [ i ] }` ; return exactSize ; } ; param originalFile param type link param count param extension renameFile = ( originalFile , type , count , extension ) : FileWithMetadata => { const { file } = originalFile ; console . info ( 'File Ingestion original file' , originalFile ) ; const newFile = new File ( [ file ] , `${ type }-input-${ count }.${ extension }` , { type : file . type , lastModified : file . lastModified } ) ; return { file : newFile , uuid : originalFile . uuid , preview : originalFile . preview , customType : originalFile . customType , videoMetadata : originalFile . videoMetadata , path : originalFile . path } ; } ; /**
     * Returns current file extension **without the dot**
     * Example mov, mp4
     */ @ computed get currentFileExtension ( ) { const { currentFile } = this ; console . info ( currentFile ) ; const nameArray = currentFile . name . split ( '.' ) ; const ext = nameArray [ nameArray . length - 1 ] ; return ext ; } /**
     * Returns a computed string for blobType which takes the value of the current file extension
     * and return `video/$ext`. An example would be for an test.mov file it returns `video/mov`
     */ @ computed get defaultBlobType ( ) { const { currentFileExtension } = this ; const blobType = `video/${ currentFileExtension }` ; return blobType ; } /**
     * Returns if the current file extension is displayable or not,
     * i.e, can the browser video tag support this extension
     */ @ computed get isDisplayable ( ) { const ext = `.${ this . currentFileExtension }` ; console . info ( 'Current file extension' , ext ) ; for ( const key of Object . keys ( formats ) ) { const currentFormat = formats [ key ] ; if ( currentFormat . extension === ext ) { return currentFormat . display ; } } return false ; } /**
     * Returns an array of all the files from all category
     *
     */ @ computed get allFiles ( ) { const { files } = this ; let fileValues = [ ] ; if ( files . audio ) { fileValues = fileValues . concat ( files . audio ) ; } if ( files . video ) { fileValues = fileValues . concat ( files . video ) ; } if ( files . image ) { fileValues = fileValues . concat ( files . image ) ; } if ( files . other ) { fileValues = fileValues . concat ( files . other ) ; } return fileValues ; } @ computed get fileData ( ) { const { allFiles , getFileExtension , sizeHumanReadable } = this ; const fileData = allFiles . map ( ( { file , videoMetadata } ) => ( { size : sizeHumanReadable ( file . size ) , ext : getFileExtension ( file . name ) , duration : videoMetadata ?. duration || 'undefined' } ) ) ; return fileData ; } @ computed get fileReference ( ) { return toJS ( this . files ) ; } @ action ( 'Update Current File' ) updateCurrentFile = ( fileConfig ) => { this . oldFiles . push ( this . currentFile . name ) ; this . currentFile = fileConfig ; } ; @ action ( 'Set dropzone ref' ) setDropzoneRef = ( ref ) => { this . dropzoneRef = ref ; } ; @ action ( 'Open file drawer' ) openFileDrawer = ( ) => { const { dropzoneRef } = this ; if ( dropzoneRef && dropzoneRef . current ) { dropzoneRef . current . click ( ) ; } } ; param newTransform link link @ action ( 'Update Files Operational Transform' ) updateFiles = ( newTransform ) => { const { getFileExtension , renameFile } = this ; for ( const transform of newTransform ) { const { state , type } = transform ; const currentFileList = this . allFiles ; switch ( state ) { case 'Move' : { if ( currentFileList ) { const { position , secondPosition } = transform ; if ( position && secondPosition ) { const newFileForPosition = renameFile ( currentFileList [ secondPosition ] , type , secondPosition , getFileExtension ( currentFileList [ secondPosition ] . file . name ) ) ; const newFileForSecondPosition = renameFile ( currentFileList [ position ] , type , position , getFileExtension ( currentFileList [ position ] . file . name ) ) ; currentFileList [ position ] = newFileForPosition ; currentFileList [ secondPosition ] = newFileForSecondPosition ; const files = { } ; currentFileList . forEach ( file => files [ file . customType ] ? files [ file . customType ] ! . push ( file ) : ( files [ file . customType ] = [ file ] ) ) ; this . files = files ; } } break ; } case 'Delete' : { if ( currentFileList ) { const { position } = transform ; if ( position ) { currentFileList . splice ( position , 1 ) ; } const files = { } ; currentFileList . forEach ( file => files [ file . customType ] ? files [ file . customType ] ! . push ( file ) : ( files [ file . customType ] = [ file ] ) ) ; this . files = files ; } break ; } case 'Insert' : { const { fileObj } = transform ; if ( fileObj ) { const { file } = fileObj ; if ( file ) { const renamedFile = renameFile ( fileObj , type , currentFileList ?. length || 0 , getFileExtension ( file . name ) ) ; this . files [ renamedFile . customType ] = this . files [ renamedFile . customType ] ? this . files [ renamedFile . customType ] ! . concat ( renamedFile ) : [ renamedFile ] ; if ( this . terminalStore && this . terminalStore . updateTerminalText ) { this . terminalStore . updateTerminalText ( `Received File ${ file . name }` ) ; } } } break ; } default : { break ; } } } } ; @ action ( 'Update Loaded Files' ) updateLoadedFiles = ( loadedFiles ) => { this . loadedFiles = loadedFiles ; } ; } const fileStore = new FileStore ( ) ; export default fileStore ;