Jelajahi Sumber

Rename RestoreFiles to GoldenRetriever

Renée Kooi 7 tahun lalu
induk
melakukan
172575fb79

+ 2 - 2
README.md

@@ -26,7 +26,7 @@ const Dashboard = require('uppy/lib/plugins/Dashboard')
 const Webcam = require('uppy/lib/plugins/Webcam')
 const GoogleDrive = require('uppy/lib/plugins/GoogleDrive')
 const Tus10 = require('uppy/lib/plugins/Tus10')
- 
+
 const uppy = Uppy({ autoProceed: false })
   .use(Dashboard, { trigger: '#select-files' })
   .use(Webcam, { target: Dashboard })
@@ -106,7 +106,7 @@ If you like, you can also use a pre-built bundle, for example from [unpkg CDN](h
 - `ProgressBar` — minimal progress bar that fills itself when upload progresses
 - `StatusBar` — more detailed progress, pause/resume/cancel buttons, percentage, speed, uploaded/total sizes (included by default with `Dashboard`)
 - `Informer` — send notifications like “smile” before taking a selfie or “upload failed” when all is lost (also included by default with `Dashboard`)
-- `RestoreFiles` — restores files after a browser crash, like it’s nothing
+- `GoldenRetriever` — restores files after a browser crash, like it’s nothing
 - `ReduxDevTools` — for your emerging [time traveling](https://github.com/gaearon/redux-devtools) needs
 - `GoogleDrive` — select files from [Google Drive](https://www.google.com/drive/)
 - `Dropbox` — select files from [Dropbox](https://www.dropbox.com/)

+ 0 - 0
src/plugins/Tus10.js → Tus.js


+ 4 - 4
examples/bundled-example/main.js

@@ -1,17 +1,17 @@
-const Uppy = require('../../src/core/Core.js')
+const Uppy = require('../../src/core')
 const Dashboard = require('../../src/plugins/Dashboard')
 // const GoogleDrive = require('../../src/plugins/GoogleDrive')
 const Dropbox = require('../../src/plugins/Dropbox')
 const Instagram = require('../../src/plugins/Instagram')
 // const Webcam = require('../../src/plugins/Webcam')
 const Tus10 = require('../../src/plugins/Tus10')
-// const Multipart = require('../../src/plugins/Multipart')
+// const XHRUpload = require('../../src/plugins/XHRUpload')
 // const FileInput = require('../../src/plugins/FileInput')
 const MetaData = require('../../src/plugins/MetaData')
 // const Informer = require('../../src/plugins/Informer')
 // const StatusBar = require('../../src/plugins/StatusBar')
 // const DragDrop = require('../../src/plugins/DragDrop')
-// const RestoreFiles = require('../../src/plugins/RestoreFiles')
+// const GoldenRetriever = require('../../src/plugins/GoldenRetriever')
 
 const PROTOCOL = location.protocol === 'https:' ? 'https' : 'http'
 const TUS_ENDPOINT = PROTOCOL + '://master.tus.io/files/'
@@ -68,7 +68,7 @@ const uppy = Uppy({
       { id: 'caption', name: 'Caption', value: 'none', placeholder: 'describe what the image is about' }
     ]
   })
-  // .use(RestoreFiles, {serviceWorker: true})
+  // .use(GoldenRetriever, {serviceWorker: true})
   .run()
 
 uppy.on('core:success', (fileList) => {

+ 4 - 4
examples/multiple-instances/main.js

@@ -1,8 +1,8 @@
 const Uppy = require('uppy/lib/core')
 const Dashboard = require('uppy/lib/plugins/Dashboard')
-const RestoreFiles = require('uppy/lib/plugins/RestoreFiles')
+const GoldenRetriever = require('uppy/lib/plugins/GoldenRetriever')
 
-// Initialise two Uppy instances with the RestoreFiles plugin,
+// Initialise two Uppy instances with the GoldenRetriever plugin,
 // but with different `id`s.
 const a = Uppy({
   id: 'a',
@@ -13,7 +13,7 @@ const a = Uppy({
     inline: true,
     maxWidth: 400
   })
-  .use(RestoreFiles, { serviceWorker: false })
+  .use(GoldenRetriever, { serviceWorker: false })
   .run()
 
 const b = Uppy({
@@ -25,7 +25,7 @@ const b = Uppy({
     inline: true,
     maxWidth: 400
   })
-  .use(RestoreFiles, { serviceWorker: false })
+  .use(GoldenRetriever, { serviceWorker: false })
   .run()
 
 window.a = a

+ 17 - 2
src/index.js

@@ -30,7 +30,7 @@ const Transloadit = require('./plugins/Transloadit')
 const AwsS3 = require('./plugins/AwsS3')
 
 // Other?
-const RestoreFiles = require('./plugins/RestoreFiles')
+const GoldenRetriever = require('./plugins/GoldenRetriever')
 const ReduxDevTools = require('./plugins/ReduxDevTools')
 const ReduxStore = require('./plugins/Redux')
 
@@ -53,7 +53,22 @@ module.exports = {
   Dashboard,
   MetaData,
   Webcam,
-  RestoreFiles,
+  GoldenRetriever,
   ReduxDevTools,
   ReduxStore
 }
+
+Object.defineProperty(module.exports, 'RestoreFiles', {
+  enumerable: true,
+  configurable: true,
+  get: () => {
+    console.warn('Uppy.RestoreFiles is deprecated and will be removed in v0.22. Use Uppy.GoldenRetriever instead.')
+    Object.defineProperty(module.exports, 'RestoreFiles', {
+      enumerable: true,
+      configurable: true,
+      writable: true,
+      value: GoldenRetriever
+    })
+    return GoldenRetriever
+  }
+})

+ 0 - 0
src/plugins/RestoreFiles/IndexedDBStore.js → src/plugins/GoldenRetriever/IndexedDBStore.js


+ 0 - 0
src/plugins/RestoreFiles/MetaDataStore.js → src/plugins/GoldenRetriever/MetaDataStore.js


+ 0 - 0
src/plugins/RestoreFiles/ServiceWorker.js → src/plugins/GoldenRetriever/ServiceWorker.js


+ 0 - 0
src/plugins/RestoreFiles/ServiceWorkerStore.js → src/plugins/GoldenRetriever/ServiceWorkerStore.js


+ 0 - 0
src/plugins/RestoreFiles/cleanup.js → src/plugins/GoldenRetriever/cleanup.js


+ 234 - 0
src/plugins/GoldenRetriever/index.js

@@ -0,0 +1,234 @@
+const Plugin = require('../Plugin')
+const ServiceWorkerStore = require('./ServiceWorkerStore')
+const IndexedDBStore = require('./IndexedDBStore')
+const MetaDataStore = require('./MetaDataStore')
+
+/**
+* The Golden Retriever plugin — restores selected files and resumes uploads
+* after a closed tab or a browser crash!
+*
+* Uses localStorage, IndexedDB and ServiceWorker to do its magic, read more:
+* https://uppy.io/blog/2017/07/golden-retriever/
+*/
+module.exports = class GoldenRetriever extends Plugin {
+  constructor (core, opts) {
+    super(core, opts)
+    this.type = 'debugger'
+    this.id = 'GoldenRetriever'
+    this.title = 'Restore Files'
+
+    const defaultOptions = {
+      expires: 24 * 60 * 60 * 1000, // 24 hours
+      serviceWorker: false
+    }
+
+    this.opts = Object.assign({}, defaultOptions, opts)
+
+    this.MetaDataStore = new MetaDataStore({
+      expires: this.opts.expires,
+      storeName: core.getID()
+    })
+    this.ServiceWorkerStore = null
+    if (this.opts.serviceWorker) {
+      this.ServiceWorkerStore = new ServiceWorkerStore({ storeName: core.getID() })
+    }
+    this.IndexedDBStore = new IndexedDBStore(Object.assign(
+      { expires: this.opts.expires },
+      opts.indexedDB || {},
+      { storeName: core.getID() }))
+
+    this.saveFilesStateToLocalStorage = this.saveFilesStateToLocalStorage.bind(this)
+    this.loadFilesStateFromLocalStorage = this.loadFilesStateFromLocalStorage.bind(this)
+    this.loadFileBlobsFromServiceWorker = this.loadFileBlobsFromServiceWorker.bind(this)
+    this.loadFileBlobsFromIndexedDB = this.loadFileBlobsFromIndexedDB.bind(this)
+    this.onBlobsLoaded = this.onBlobsLoaded.bind(this)
+  }
+
+  loadFilesStateFromLocalStorage () {
+    const savedState = this.MetaDataStore.load()
+
+    if (savedState) {
+      this.core.log('Recovered some state from Local Storage')
+      this.core.setState(savedState)
+    }
+  }
+
+  /**
+   * Get file objects that are currently waiting: they've been selected,
+   * but aren't yet being uploaded.
+   */
+  getWaitingFiles () {
+    const waitingFiles = {}
+
+    const allFiles = this.core.state.files
+    Object.keys(allFiles).forEach((fileID) => {
+      const file = this.core.getFile(fileID)
+      if (!file.progress || !file.progress.uploadStarted) {
+        waitingFiles[fileID] = file
+      }
+    })
+
+    return waitingFiles
+  }
+
+  /**
+   * Get file objects that are currently being uploaded. If a file has finished
+   * uploading, but the other files in the same batch have not, the finished
+   * file is also returned.
+   */
+  getUploadingFiles () {
+    const uploadingFiles = {}
+
+    const { currentUploads } = this.core.state
+    if (currentUploads) {
+      const uploadIDs = Object.keys(currentUploads)
+      uploadIDs.forEach((uploadID) => {
+        const filesInUpload = currentUploads[uploadID].fileIDs
+        filesInUpload.forEach((fileID) => {
+          uploadingFiles[fileID] = this.core.getFile(fileID)
+        })
+      })
+    }
+
+    return uploadingFiles
+  }
+
+  saveFilesStateToLocalStorage () {
+    const filesToSave = Object.assign(
+      this.getWaitingFiles(),
+      this.getUploadingFiles()
+    )
+
+    this.MetaDataStore.save({
+      currentUploads: this.core.state.currentUploads,
+      files: filesToSave
+    })
+  }
+
+  loadFileBlobsFromServiceWorker () {
+    this.ServiceWorkerStore.list().then((blobs) => {
+      const numberOfFilesRecovered = Object.keys(blobs).length
+      const numberOfFilesTryingToRecover = Object.keys(this.core.state.files).length
+      if (numberOfFilesRecovered === numberOfFilesTryingToRecover) {
+        this.core.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Service Worker!`)
+        this.core.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
+        this.onBlobsLoaded(blobs)
+      } else {
+        this.core.log('Failed to recover blobs from Service Worker, trying IndexedDB now...')
+        this.loadFileBlobsFromIndexedDB()
+      }
+    })
+  }
+
+  loadFileBlobsFromIndexedDB () {
+    this.IndexedDBStore.list().then((blobs) => {
+      const numberOfFilesRecovered = Object.keys(blobs).length
+
+      if (numberOfFilesRecovered > 0) {
+        this.core.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Indexed DB!`)
+        this.core.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
+        return this.onBlobsLoaded(blobs)
+      }
+      this.core.log('Couldn’t recover anything from IndexedDB :(')
+    })
+  }
+
+  onBlobsLoaded (blobs) {
+    const obsoleteBlobs = []
+    const updatedFiles = Object.assign({}, this.core.state.files)
+    Object.keys(blobs).forEach((fileID) => {
+      const originalFile = this.core.getFile(fileID)
+      if (!originalFile) {
+        obsoleteBlobs.push(fileID)
+        return
+      }
+
+      const cachedData = blobs[fileID]
+
+      const updatedFileData = {
+        data: cachedData,
+        isRestored: true
+      }
+      const updatedFile = Object.assign({}, originalFile, updatedFileData)
+      updatedFiles[fileID] = updatedFile
+
+      this.core.generatePreview(updatedFile)
+    })
+    this.core.setState({
+      files: updatedFiles
+    })
+    this.core.emit('core:restored')
+
+    if (obsoleteBlobs.length) {
+      this.deleteBlobs(obsoleteBlobs).then(() => {
+        this.core.log(`[GoldenRetriever] cleaned up ${obsoleteBlobs.length} old files`)
+      })
+    }
+  }
+
+  deleteBlobs (fileIDs) {
+    const promises = []
+    fileIDs.forEach((id) => {
+      if (this.ServiceWorkerStore) {
+        promises.push(this.ServiceWorkerStore.delete(id))
+      }
+      if (this.IndexedDBStore) {
+        promises.push(this.IndexedDBStore.delete(id))
+      }
+    })
+    return Promise.all(promises)
+  }
+
+  install () {
+    this.loadFilesStateFromLocalStorage()
+
+    if (Object.keys(this.core.state.files).length > 0) {
+      if (this.ServiceWorkerStore) {
+        this.core.log('Attempting to load files from Service Worker...')
+        this.loadFileBlobsFromServiceWorker()
+      } else {
+        this.core.log('Attempting to load files from Indexed DB...')
+        this.loadFileBlobsFromIndexedDB()
+      }
+    }
+
+    this.core.on('core:file-added', (file) => {
+      if (file.isRemote) return
+
+      if (this.ServiceWorkerStore) {
+        this.ServiceWorkerStore.put(file).catch((err) => {
+          this.core.log('Could not store file', 'error')
+          this.core.log(err)
+        })
+      }
+
+      this.IndexedDBStore.put(file).catch((err) => {
+        this.core.log('Could not store file', 'error')
+        this.core.log(err)
+      })
+    })
+
+    this.core.on('core:file-removed', (fileID) => {
+      if (this.ServiceWorkerStore) this.ServiceWorkerStore.delete(fileID)
+      this.IndexedDBStore.delete(fileID)
+    })
+
+    this.core.on('core:success', (fileIDs) => {
+      this.deleteBlobs(fileIDs).then(() => {
+        this.core.log(`[GoldenRetriever] removed ${fileIDs.length} files that finished uploading`)
+      })
+    })
+
+    this.core.on('core:state-update', this.saveFilesStateToLocalStorage)
+
+    this.core.on('core:restored', () => {
+      // start all uploads again when file blobs are restored
+      const { currentUploads } = this.core.getState()
+      if (currentUploads) {
+        Object.keys(currentUploads).forEach((uploadId) => {
+          this.core.restore(uploadId, currentUploads[uploadId])
+        })
+      }
+    })
+  }
+}

+ 3 - 232
src/plugins/RestoreFiles/index.js

@@ -1,234 +1,5 @@
-const Plugin = require('../Plugin')
-const ServiceWorkerStore = require('./ServiceWorkerStore')
-const IndexedDBStore = require('./IndexedDBStore')
-const MetaDataStore = require('./MetaDataStore')
+const GoldenRetriever = require('../GoldenRetriever')
 
-/**
-* Restore Files plugin — restores selected files and resumes uploads
-* after a closed tab or a browser crash!
-*
-* Uses localStorage, IndexedDB and ServiceWorker to do its magic, read more:
-* https://uppy.io/blog/2017/07/golden-retriever/
-*/
-module.exports = class RestoreFiles extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
-    this.type = 'debugger'
-    this.id = 'RestoreFiles'
-    this.title = 'Restore Files'
+console.warn('Using `uppy/lib/plugins/RestoreFiles` is deprecated and will be removed in v0.22. Please use `uppy/lib/plugins/GoldenRetriever` instead.')
 
-    const defaultOptions = {
-      expires: 24 * 60 * 60 * 1000, // 24 hours
-      serviceWorker: false
-    }
-
-    this.opts = Object.assign({}, defaultOptions, opts)
-
-    this.MetaDataStore = new MetaDataStore({
-      expires: this.opts.expires,
-      storeName: core.getID()
-    })
-    this.ServiceWorkerStore = null
-    if (this.opts.serviceWorker) {
-      this.ServiceWorkerStore = new ServiceWorkerStore({ storeName: core.getID() })
-    }
-    this.IndexedDBStore = new IndexedDBStore(Object.assign(
-      { expires: this.opts.expires },
-      opts.indexedDB || {},
-      { storeName: core.getID() }))
-
-    this.saveFilesStateToLocalStorage = this.saveFilesStateToLocalStorage.bind(this)
-    this.loadFilesStateFromLocalStorage = this.loadFilesStateFromLocalStorage.bind(this)
-    this.loadFileBlobsFromServiceWorker = this.loadFileBlobsFromServiceWorker.bind(this)
-    this.loadFileBlobsFromIndexedDB = this.loadFileBlobsFromIndexedDB.bind(this)
-    this.onBlobsLoaded = this.onBlobsLoaded.bind(this)
-  }
-
-  loadFilesStateFromLocalStorage () {
-    const savedState = this.MetaDataStore.load()
-
-    if (savedState) {
-      this.core.log('Recovered some state from Local Storage')
-      this.core.setState(savedState)
-    }
-  }
-
-  /**
-   * Get file objects that are currently waiting: they've been selected,
-   * but aren't yet being uploaded.
-   */
-  getWaitingFiles () {
-    const waitingFiles = {}
-
-    const allFiles = this.core.state.files
-    Object.keys(allFiles).forEach((fileID) => {
-      const file = this.core.getFile(fileID)
-      if (!file.progress || !file.progress.uploadStarted) {
-        waitingFiles[fileID] = file
-      }
-    })
-
-    return waitingFiles
-  }
-
-  /**
-   * Get file objects that are currently being uploaded. If a file has finished
-   * uploading, but the other files in the same batch have not, the finished
-   * file is also returned.
-   */
-  getUploadingFiles () {
-    const uploadingFiles = {}
-
-    const { currentUploads } = this.core.state
-    if (currentUploads) {
-      const uploadIDs = Object.keys(currentUploads)
-      uploadIDs.forEach((uploadID) => {
-        const filesInUpload = currentUploads[uploadID].fileIDs
-        filesInUpload.forEach((fileID) => {
-          uploadingFiles[fileID] = this.core.getFile(fileID)
-        })
-      })
-    }
-
-    return uploadingFiles
-  }
-
-  saveFilesStateToLocalStorage () {
-    const filesToSave = Object.assign(
-      this.getWaitingFiles(),
-      this.getUploadingFiles()
-    )
-
-    this.MetaDataStore.save({
-      currentUploads: this.core.state.currentUploads,
-      files: filesToSave
-    })
-  }
-
-  loadFileBlobsFromServiceWorker () {
-    this.ServiceWorkerStore.list().then((blobs) => {
-      const numberOfFilesRecovered = Object.keys(blobs).length
-      const numberOfFilesTryingToRecover = Object.keys(this.core.state.files).length
-      if (numberOfFilesRecovered === numberOfFilesTryingToRecover) {
-        this.core.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Service Worker!`)
-        this.core.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
-        this.onBlobsLoaded(blobs)
-      } else {
-        this.core.log('Failed to recover blobs from Service Worker, trying IndexedDB now...')
-        this.loadFileBlobsFromIndexedDB()
-      }
-    })
-  }
-
-  loadFileBlobsFromIndexedDB () {
-    this.IndexedDBStore.list().then((blobs) => {
-      const numberOfFilesRecovered = Object.keys(blobs).length
-
-      if (numberOfFilesRecovered > 0) {
-        this.core.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Indexed DB!`)
-        this.core.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
-        return this.onBlobsLoaded(blobs)
-      }
-      this.core.log('Couldn’t recover anything from IndexedDB :(')
-    })
-  }
-
-  onBlobsLoaded (blobs) {
-    const obsoleteBlobs = []
-    const updatedFiles = Object.assign({}, this.core.state.files)
-    Object.keys(blobs).forEach((fileID) => {
-      const originalFile = this.core.getFile(fileID)
-      if (!originalFile) {
-        obsoleteBlobs.push(fileID)
-        return
-      }
-
-      const cachedData = blobs[fileID]
-
-      const updatedFileData = {
-        data: cachedData,
-        isRestored: true
-      }
-      const updatedFile = Object.assign({}, originalFile, updatedFileData)
-      updatedFiles[fileID] = updatedFile
-
-      this.core.generatePreview(updatedFile)
-    })
-    this.core.setState({
-      files: updatedFiles
-    })
-    this.core.emit('core:restored')
-
-    if (obsoleteBlobs.length) {
-      this.deleteBlobs(obsoleteBlobs).then(() => {
-        this.core.log(`RestoreFiles: cleaned up ${obsoleteBlobs.length} old files`)
-      })
-    }
-  }
-
-  deleteBlobs (fileIDs) {
-    const promises = []
-    fileIDs.forEach((id) => {
-      if (this.ServiceWorkerStore) {
-        promises.push(this.ServiceWorkerStore.delete(id))
-      }
-      if (this.IndexedDBStore) {
-        promises.push(this.IndexedDBStore.delete(id))
-      }
-    })
-    return Promise.all(promises)
-  }
-
-  install () {
-    this.loadFilesStateFromLocalStorage()
-
-    if (Object.keys(this.core.state.files).length > 0) {
-      if (this.ServiceWorkerStore) {
-        this.core.log('Attempting to load files from Service Worker...')
-        this.loadFileBlobsFromServiceWorker()
-      } else {
-        this.core.log('Attempting to load files from Indexed DB...')
-        this.loadFileBlobsFromIndexedDB()
-      }
-    }
-
-    this.core.on('core:file-added', (file) => {
-      if (file.isRemote) return
-
-      if (this.ServiceWorkerStore) {
-        this.ServiceWorkerStore.put(file).catch((err) => {
-          this.core.log('Could not store file', 'error')
-          this.core.log(err)
-        })
-      }
-
-      this.IndexedDBStore.put(file).catch((err) => {
-        this.core.log('Could not store file', 'error')
-        this.core.log(err)
-      })
-    })
-
-    this.core.on('core:file-removed', (fileID) => {
-      if (this.ServiceWorkerStore) this.ServiceWorkerStore.delete(fileID)
-      this.IndexedDBStore.delete(fileID)
-    })
-
-    this.core.on('core:success', (fileIDs) => {
-      this.deleteBlobs(fileIDs).then(() => {
-        this.core.log(`RestoreFiles: removed ${fileIDs.length} files that finished uploading`)
-      })
-    })
-
-    this.core.on('core:state-update', this.saveFilesStateToLocalStorage)
-
-    this.core.on('core:restored', () => {
-      // start all uploads again when file blobs are restored
-      const { currentUploads } = this.core.getState()
-      if (currentUploads) {
-        Object.keys(currentUploads).forEach((uploadId) => {
-          this.core.restore(uploadId, currentUploads[uploadId])
-        })
-      }
-    })
-  }
-}
+module.exports = GoldenRetriever

+ 4 - 3
website/src/docs/golden-retriever.md

@@ -5,22 +5,23 @@ permalink: docs/golden-retriever/
 order: 40
 ---
 
-Golden Retriever plugin, also known and used as `RestoreFiles`, saves selected files in your browser cache (Local Storage for metadata, then Service Worker for all blobs + IndexedDB for small blobs), so that if the browser crashes, Uppy can restore everything and continue uploading like nothing happened. Read more about it [on the blog](https://uppy.io/blog/2017/07/golden-retriever/).
+Golden Retriever plugin saves selected files in your browser cache (Local Storage for metadata, then Service Worker for all blobs + IndexedDB for small blobs), so that if the browser crashes, Uppy can restore everything and continue uploading like nothing happened. Read more about it [on the blog](https://uppy.io/blog/2017/07/golden-retriever/).
 
 1\. Bundle your own service worker `sw.js` file with Uppy Golden Retriever’s service worker. If you’re using Browserify, just bundle it separately, for Webpack there is a plugin [serviceworker-webpack-plugin](https://github.com/oliviertassinari/serviceworker-webpack-plugin).
 
 ```js
 // sw.js
 
-require('uppy/lib/RestoreFiles/ServiceWorker.js')
+require('uppy/lib/plugins/GoldenRetriever/ServiceWorker.js')
 ```
 
 2\. Register it in your app entry point:
 
 ```js
 // you app.js entry point
+const GoldenRetriever = require('uppy/lib/plugins/GoldenRetriever')
 
-uppy.use(RestoreFiles, {serviceWorker: true})
+uppy.use(GoldenRetriever, {serviceWorker: true})
 uppy.run()
 
 if ('serviceWorker' in navigator) {