Преглед изворни кода

Move preview revocation to thumbnail-generator

Renée Kooi пре 6 година
родитељ
комит
62b1fe9a96

+ 0 - 6
packages/@uppy/core/src/index.js

@@ -8,7 +8,6 @@ const DefaultStore = require('@uppy/store-default')
 const getFileType = require('@uppy/utils/lib/getFileType')
 const getFileType = require('@uppy/utils/lib/getFileType')
 const getFileNameAndExtension = require('@uppy/utils/lib/getFileNameAndExtension')
 const getFileNameAndExtension = require('@uppy/utils/lib/getFileNameAndExtension')
 const generateFileID = require('@uppy/utils/lib/generateFileID')
 const generateFileID = require('@uppy/utils/lib/generateFileID')
-const isObjectURL = require('@uppy/utils/lib/isObjectURL')
 const getTimeStamp = require('@uppy/utils/lib/getTimeStamp')
 const getTimeStamp = require('@uppy/utils/lib/getTimeStamp')
 const Plugin = require('./Plugin') // Exported from here.
 const Plugin = require('./Plugin') // Exported from here.
 
 
@@ -500,11 +499,6 @@ class Uppy {
     this._calculateTotalProgress()
     this._calculateTotalProgress()
     this.emit('file-removed', removedFile)
     this.emit('file-removed', removedFile)
     this.log(`File removed: ${removedFile.id}`)
     this.log(`File removed: ${removedFile.id}`)
-
-    // Clean up object URLs.
-    if (removedFile.preview && isObjectURL(removedFile.preview)) {
-      URL.revokeObjectURL(removedFile.preview)
-    }
   }
   }
 
 
   pauseResume (fileID) {
   pauseResume (fileID) {

+ 28 - 6
packages/@uppy/thumbnail-generator/src/index.js

@@ -1,10 +1,10 @@
 const { Plugin } = require('@uppy/core')
 const { Plugin } = require('@uppy/core')
 const dataURItoBlob = require('@uppy/utils/lib/dataURItoBlob')
 const dataURItoBlob = require('@uppy/utils/lib/dataURItoBlob')
+const isObjectURL = require('@uppy/utils/lib/isObjectURL')
 const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported')
 const isPreviewSupported = require('@uppy/utils/lib/isPreviewSupported')
 
 
 /**
 /**
  * The Thumbnail Generator plugin
  * The Thumbnail Generator plugin
- *
  */
  */
 
 
 module.exports = class ThumbnailGenerator extends Plugin {
 module.exports = class ThumbnailGenerator extends Plugin {
@@ -25,7 +25,8 @@ module.exports = class ThumbnailGenerator extends Plugin {
       ...opts
       ...opts
     }
     }
 
 
-    this.addToQueue = this.addToQueue.bind(this)
+    this.onFileAdded = this.onFileAdded.bind(this)
+    this.onFileRemoved = this.onFileRemoved.bind(this)
     this.onRestored = this.onRestored.bind(this)
     this.onRestored = this.onRestored.bind(this)
   }
   }
 
 
@@ -198,24 +199,45 @@ module.exports = class ThumbnailGenerator extends Plugin {
     return Promise.resolve()
     return Promise.resolve()
   }
   }
 
 
+  onFileAdded (file) {
+    if (!file.preview) {
+      this.addToQueue(file)
+    }
+  }
+
+  onFileRemoved (file) {
+    const index = this.queue.indexOf(file)
+    if (index !== -1) {
+      this.queue.splice(index, 1)
+    }
+
+    // Clean up object URLs.
+    if (file.preview && isObjectURL(file.preview)) {
+      URL.revokeObjectURL(file.preview)
+    }
+  }
+
   onRestored () {
   onRestored () {
-    const fileIDs = Object.keys(this.uppy.getState().files)
+    const { files } = this.uppy.getState()
+    const fileIDs = Object.keys(files)
     fileIDs.forEach((fileID) => {
     fileIDs.forEach((fileID) => {
       const file = this.uppy.getFile(fileID)
       const file = this.uppy.getFile(fileID)
       if (!file.isRestored) return
       if (!file.isRestored) return
       // Only add blob URLs; they are likely invalid after being restored.
       // Only add blob URLs; they are likely invalid after being restored.
-      if (!file.preview || /^blob:/.test(file.preview)) {
+      if (!file.preview || isObjectURL(file.preview)) {
         this.addToQueue(file)
         this.addToQueue(file)
       }
       }
     })
     })
   }
   }
 
 
   install () {
   install () {
-    this.uppy.on('file-added', this.addToQueue)
+    this.uppy.on('file-added', this.onFileAdded)
+    this.uppy.on('file-removed', this.onFileRemoved)
     this.uppy.on('restored', this.onRestored)
     this.uppy.on('restored', this.onRestored)
   }
   }
   uninstall () {
   uninstall () {
-    this.uppy.off('file-added', this.addToQueue)
+    this.uppy.off('file-added', this.onFileAdded)
+    this.uppy.off('file-removed', this.onFileRemoved)
     this.uppy.off('restored', this.onRestored)
     this.uppy.off('restored', this.onRestored)
   }
   }
 }
 }

+ 43 - 5
packages/@uppy/thumbnail-generator/src/index.test.js

@@ -37,8 +37,8 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
       plugin.addToQueue = jest.fn()
       plugin.addToQueue = jest.fn()
       plugin.install()
       plugin.install()
 
 
-      expect(core.on).toHaveBeenCalledTimes(2)
-      expect(core.on).toHaveBeenCalledWith('file-added', plugin.addToQueue)
+      expect(core.on).toHaveBeenCalledTimes(3)
+      expect(core.on).toHaveBeenCalledWith('file-added', plugin.onFileAdded)
     })
     })
   })
   })
 
 
@@ -53,12 +53,12 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
       plugin.addToQueue = jest.fn()
       plugin.addToQueue = jest.fn()
       plugin.install()
       plugin.install()
 
 
-      expect(core.on).toHaveBeenCalledTimes(2)
+      expect(core.on).toHaveBeenCalledTimes(3)
 
 
       plugin.uninstall()
       plugin.uninstall()
 
 
-      expect(core.off).toHaveBeenCalledTimes(2)
-      expect(core.off).toHaveBeenCalledWith('file-added', plugin.addToQueue)
+      expect(core.off).toHaveBeenCalledTimes(3)
+      expect(core.off).toHaveBeenCalledWith('file-added', plugin.onFileAdded)
     })
     })
   })
   })
 
 
@@ -113,6 +113,44 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
           expect(plugin.queueProcessing).toEqual(false)
           expect(plugin.queueProcessing).toEqual(false)
         })
         })
     })
     })
+
+    it('should revoke object URLs when files are removed', async () => {
+      const core = new MockCore()
+      const plugin = new ThumbnailGeneratorPlugin(core)
+      plugin.install()
+
+      URL.revokeObjectURL = jest.fn(() => null)
+
+      try {
+        plugin.createThumbnail = jest.fn(async () => {
+          await delay(50)
+          return 'blob:http://uppy.io/fake-thumbnail'
+        })
+        plugin.setPreviewURL = jest.fn((id, preview) => {
+          if (id === 1) file1.preview = preview
+          if (id === 2) file2.preview = preview
+        })
+
+        const file1 = { id: 1, name: 'bar.jpg', type: 'image/jpeg' }
+        const file2 = { id: 2, name: 'bar2.jpg', type: 'image/jpeg' }
+        core.emit('file-added', file1)
+        core.emit('file-added', file2)
+        expect(plugin.queue).toHaveLength(1)
+        // should drop it from the queue
+        core.emit('file-removed', file2)
+        expect(plugin.queue).toHaveLength(0)
+
+        expect(plugin.createThumbnail).toHaveBeenCalledTimes(1)
+        expect(URL.revokeObjectURL).not.toHaveBeenCalled()
+
+        await delay(110)
+
+        core.emit('file-removed', file1)
+        expect(URL.revokeObjectURL).toHaveBeenCalledTimes(1)
+      } finally {
+        delete URL.revokeObjectURL
+      }
+    })
   })
   })
 
 
   describe('events', () => {
   describe('events', () => {