From dc4d3d4e6517caf0b6bb6d2abd8b0a8c8e1d44df Mon Sep 17 00:00:00 2001 From: gsuess Date: Thu, 8 Jan 2015 12:19:28 +0100 Subject: [PATCH] Prevented Flickering when an image is uploaded and `.url()` is used within a volatile autorun. --- lib/upload.js | 97 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 27 deletions(-) diff --git a/lib/upload.js b/lib/upload.js index 3bd59a7..0a05b26 100644 --- a/lib/upload.js +++ b/lib/upload.js @@ -19,8 +19,8 @@ Slingshot.Upload = function (directive, metaData) { loaded = new ReactiveVar(), total = new ReactiveVar(), status = new ReactiveVar("idle"), - dataUri = new ReactiveVar(), - preloaded= new ReactiveVar(); + dataUri, + preloaded; function buildFormData() { var formData = new window.FormData(); @@ -212,42 +212,85 @@ Slingshot.Upload = function (directive, metaData) { */ url: function (preload) { - var status = self.status(); - - if (preload && !self.isImage()) - throw new Error("Cannot pre-load anything other than images"); - - if (self.instructions && status === "done") { - var download = self.instructions.download; + if (!dataUri) { + var localUrl = new ReactiveVar(), + URL = (window.URL || window.webkitURL); + + dataUri = new ReactiveVar(); + + Tracker.nonreactive(function () { + + /* + It is important that we generate the local url not more than once + throughout the entire lifecycle of `self` to prevent flickering. + */ + + var previewRequirement = new Tracker.Dependency(); + + Tracker.autorun(function (computation) { + if (self.file) { + if (URL) { + localUrl.set(URL.createObjectURL(self.file)); + computation.stop(); + } + else if (Tracker.active && window.FileReader) { + readDataUrl(self.file, function (result) { + localUrl.set(result); + computation.stop(); + }); + } + } + else { + previewRequirement.depend(); + } + }); - if (preload && preloaded.get() !== download) { - preloadImage(download, function () { - preloaded.set(download); + Tracker.autorun(function (computation) { + var status = self.status(); + + if (self.instructions && status === "done") { + computation.stop(); + dataUri.set(self.instructions.download); + } + else if (status === "failed" || status === "aborted") { + computation.stop(); + } + else if (self.file && !dataUri.curValue) { + previewRequirement.changed(); + dataUri.set(localUrl.get()); + } }); - } - else { - dataUri.set(); - return download; - } + }); } - if (status !== "failed" && status !== "aborted" && self.file) { - var URL = (window.URL || window.webkitURL); + if (preload) { - if (URL) - return URL.createObjectURL(self.file); + if (self.file && !self.isImage()) + throw new Error("Cannot pre-load anything other than images"); - if (Tracker.active && window.FileReader) { - var url = dataUri.get(); + if (!preloaded) { + Tracker.nonreactive(function () { + preloaded = new ReactiveVar(); - if (url) - return url; + Tracker.autorun(function (computation) { + var url = dataUri.get(); - readDataUrl(self.file, function (result) { - dataUri.set(result); + if (self.instructions) { + preloadImage(url, function () { + computation.stop(); + preloaded.set(url); + }); + } + else + preloaded.set(url); + }); }); } + + return preloaded.get(); } + else + return dataUri.get(); }, /** Gets an upload parameter for the directive.