Reduced memory footprint for long upload sessions

This commit is contained in:
Marcin Kurczewski 2015-03-19 22:07:43 +01:00
parent d98474cc6a
commit f75b4505a1
2 changed files with 94 additions and 44 deletions

View file

@ -78,7 +78,7 @@ App.Presenters.PostUploadPresenter = function(
fileName: null, fileName: null,
content: null, content: null,
url: null, url: null,
thumbnail: null, getThumbnail: function() { return promise.makeSilent(function(resolve, reject) { resolve(null); }); },
$tableRow: null, $tableRow: null,
}; };
} }
@ -111,7 +111,7 @@ App.Presenters.PostUploadPresenter = function(
} }
} }
$input.val(''); $input.val('');
var post = addPostFromUrl(url); var post = addPostFromURL(url);
selectPostTableRow(post); selectPostTableRow(post);
} }
@ -137,20 +137,13 @@ App.Presenters.PostUploadPresenter = function(
allPosts.push(post); allPosts.push(post);
setAllPosts(allPosts); setAllPosts(allPosts);
createPostTableRow(post); createPostTableRow(post);
updatePostThumbnailInTable(post);
} }
function postChanged(post) { function postChanged(post) {
updatePostTableRow(post); updatePostTableRow(post);
} }
function postThumbnailLoaded(post) {
var selectedPosts = getSelectedPosts();
if (selectedPosts.length === 1 && selectedPosts[0] === post && post.thumbnail !== null) {
updatePostThumbnailInForm(post);
}
updatePostThumbnailInTable(post);
}
function postTableRowClicked(e) { function postTableRowClicked(e) {
e.preventDefault(); e.preventDefault();
if (!interactionEnabled) { if (!interactionEnabled) {
@ -211,16 +204,17 @@ App.Presenters.PostUploadPresenter = function(
function postTableRowImageHovered(e) { function postTableRowImageHovered(e) {
var $img = jQuery(this); var $img = jQuery(this);
if ($img.parents('tr').data('post').thumbnail) { var post = $img.parents('tr').data('post');
post.getThumbnail(null, null).then(function(thumbnailDataURL) {
var $lightbox = jQuery('#lightbox'); var $lightbox = jQuery('#lightbox');
$lightbox.find('img').attr('src', $img.attr('src')); $lightbox.find('img').attr('src', thumbnailDataURL);
$lightbox $lightbox
.show() .show()
.css({ .css({
left: ($img.position().left + $img.outerWidth()) + 'px', left: ($img.position().left + $img.outerWidth()) + 'px',
top: ($img.position().top + ($img.outerHeight() - $lightbox.outerHeight()) / 2) + 'px', top: ($img.position().top + ($img.outerHeight() - $lightbox.outerHeight()) / 2) + 'px',
}); });
} });
} }
function postTableRowImageUnhovered(e) { function postTableRowImageUnhovered(e) {
@ -255,34 +249,81 @@ App.Presenters.PostUploadPresenter = function(
stopUpload(); stopUpload();
} }
function addPostFromFile(file) { function makeThumbnailFromDataURL(dataURL, thumbnailWidth, thumbnailHeight) {
var post = _.extend({}, getDefaultPost(), {fileName: file.name, file: file}); return promise.makeSilent(function(resolve, reject) {
var img = new Image();
img.src = dataURL;
img.onload = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = thumbnailWidth;
canvas.height = thumbnailHeight;
context.drawImage(
img,
0,
0,
canvas.width,
canvas.height);
resolve(canvas.toDataURL());
canvas = null;
};
});
}
fileDropper.readAsDataURL(file, function(content) { function addPostFromFile(file) {
if (file.type.match('image.*')) { var post = _.extend({}, getDefaultPost(), {
post.thumbnail = content; fileName: file.name,
postThumbnailLoaded(post); file: file,
} getThumbnail: function(thumbnailWidth, thumbnailHeight) {
if (file.type.match('image.*')) {
return promise.makeSilent(function(resolve, reject) {
fileDropper.readAsDataURL(file, function(contentDataURL) {
if (thumbnailWidth === null || thumbnailHeight === null) {
resolve(contentDataURL);
return;
}
makeThumbnailFromDataURL(contentDataURL, thumbnailWidth, thumbnailHeight)
.then(function(thumbnailDataURL) {
resolve(thumbnailDataURL);
});
});
});
} else {
return promise.makeSilent(function(resolve, reject) {
resolve(null);
});
}
},
}); });
postAdded(post); postAdded(post);
return post; return post;
} }
function addPostFromUrl(url) { function addPostFromURL(url) {
var post = _.extend({}, getDefaultPost(), {url: url, fileName: url}); var post = _.extend({}, getDefaultPost(), {
postAdded(post); url: url,
setPostsSource([post], url); fileName: url,
});
var matches = url.match(/watch.*?=([a-zA-Z0-9_-]+)/); var matches = url.match(/watch.*?=([a-zA-Z0-9_-]+)/);
if (matches) { if (matches) {
var youtubeThumbnailUrl = 'http://img.youtube.com/vi/' + matches[1] + '/mqdefault.jpg'; var youtubeThumbnailURL = 'http://img.youtube.com/vi/' + matches[1] + '/mqdefault.jpg';
post.thumbnail = youtubeThumbnailUrl; post.getThumbnail = function(thumbnailWidth, thumbnailHeight) {
postThumbnailLoaded(post); return promise.makeSilent(function(resolve, reject) {
resolve(youtubeThumbnailURL);
});
};
} else if (url.match(/image|img|jpg|png|gif/i)) { } else if (url.match(/image|img|jpg|png|gif/i)) {
post.thumbnail = url; post.getThumbnail = function(thumbnailWidth, thumbnailHeight) {
postThumbnailLoaded(post); return promise.makeSilent(function(resolve, reject) {
resolve(url);
});
};
} }
postAdded(post);
setPostsSource([post], url);
return post; return post;
} }
@ -314,21 +355,24 @@ App.Presenters.PostUploadPresenter = function(
} }
function updatePostThumbnailInForm(post) { function updatePostThumbnailInForm(post) {
if (post.thumbnail === null) { post.getThumbnail(null, null).then(function(thumbnailDataURL) {
$el.find('.form-slider .thumbnail img').hide(); if (thumbnailDataURL === null) {
} else { $el.find('.form-slider .thumbnail img').hide();
$el.find('.form-slider .thumbnail img').show()[0].setAttribute('src', post.thumbnail); } else {
} $el.find('.form-slider .thumbnail img').show()[0].setAttribute('src', thumbnailDataURL);
}
});
} }
function updatePostThumbnailInTable(post) { function updatePostThumbnailInTable(post) {
var $row = post.$tableRow; post.getThumbnail(30, 30).then(function(thumbnailDataURL) {
if (post.thumbnail === null) { var $row = post.$tableRow;
$row.find('img')[0].setAttribute('src', util.transparentPixel()); if (thumbnailDataURL === null) {
//huge speedup thanks to this condition $row.find('img')[0].setAttribute('src', util.transparentPixel());
} else if ($row.find('img').attr('src') !== post.thumbnail) { } else if ($row.find('img').attr('src') !== thumbnailDataURL) {
$row.find('img')[0].setAttribute('src', post.thumbnail); $row.find('img')[0].setAttribute('src', thumbnailDataURL);
} }
});
} }
function getAllPosts() { function getAllPosts() {
@ -360,6 +404,9 @@ App.Presenters.PostUploadPresenter = function(
showPostEditForm(selectedPosts); showPostEditForm(selectedPosts);
} }
$el.find('.post-table-op').prop('disabled', selectedPosts.length === 0); $el.find('.post-table-op').prop('disabled', selectedPosts.length === 0);
if (selectedPosts.length === 1) {
updatePostThumbnailInForm(selectedPosts[0]);
}
} }
function hidePostEditForm() { function hidePostEditForm() {

View file

@ -11,12 +11,14 @@ App.Promise = function(_, jQuery, progress) {
var active = []; var active = [];
var promiseId = 0; var promiseId = 0;
function make(callback) { function make(callback, useProgress) {
var deferred = jQuery.Deferred(); var deferred = jQuery.Deferred();
var promise = deferred.promise(); var promise = deferred.promise();
promise.promiseId = ++ promiseId; promise.promiseId = ++ promiseId;
progress.start(); if (useProgress === true) {
progress.start();
}
callback(function() { callback(function() {
try { try {
deferred.resolve.apply(deferred, arguments); deferred.resolve.apply(deferred, arguments);
@ -72,7 +74,8 @@ App.Promise = function(_, jQuery, progress) {
} }
return { return {
make: make, make: function(callback) { return make(callback, true); },
makeSilent: function(callback) { return make(callback, false); },
wait: wait, wait: wait,
getActive: getActive, getActive: getActive,
abortAll: abortAll, abortAll: abortAll,