diff --git a/www/code/inner.js b/www/code/inner.js index 6ec2c439d..5f2cf3df1 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -348,13 +348,11 @@ define([ getContainer: getThumbnailContainer, filter: function (el, before) { if (before) { - // Overflow visible to the parents makes it look better but - // it creates chaos in the editbale area - //$(el).parents().css('overflow', 'visible'); + $(el).parents().css('overflow', 'visible'); $(el).css('max-height', Math.max(600, $(el).width()) + 'px'); return; } - //$(el).parents().css('overflow', ''); + $(el).parents().css('overflow', ''); $(el).css('max-height', ''); } } diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js index eb15c831b..dd8e37ec0 100644 --- a/www/common/common-thumbnail.js +++ b/www/common/common-thumbnail.js @@ -1,6 +1,11 @@ define([ + '/common/common-util.js', + '/common/visible.js', + '/common/common-hash.js', + '/file/file-crypto.js', + '/bower_components/localforage/dist/localforage.min.js', '/bower_components/tweetnacl/nacl-fast.min.js', -], function () { +], function (Util, Visible, Hash, FileCrypto, localForage) { var Nacl = window.nacl; var Thumb = { dimension: 100, @@ -190,5 +195,82 @@ define([ require(['/bower_components/html2canvas/build/html2canvas.min.js'], todo); }; + Thumb.initPadThumbnails = function (opts) { + if (!opts.href || !opts.getContent) { + throw new Error("href and getContent are needed for thumbnails"); + } + var oldThumbnailState; + var mkThumbnail = function () { + var content = opts.getContent(); + if (content === oldThumbnailState) { return; } + Thumb.fromDOM(opts, function (err, b64) { + oldThumbnailState = content; + Thumb.setPadThumbnail(opts.href, b64); + }); + }; + var nafa = Util.notAgainForAnother(mkThumbnail, Thumb.UPDATE_INTERVAL); + var to; + var tUntil; + var interval = function () { + tUntil = nafa(); + if (tUntil) { + window.clearTimeout(to); + to = window.setTimeout(interval, tUntil+1); + return; + } + to = window.setTimeout(interval, Thumb.UPDATE_INTERVAL+1); + }; + Visible.onChange(function (v) { + if (v) { + window.clearTimeout(to); + return; + } + interval(); + }); + if (!Visible.currently()) { to = window.setTimeout(interval, Thumb.UPDATE_FIRST); } + }; + + var addThumbnail = function (err, thumb, $span, cb) { + var img = new Image(); + img.src = thumb.slice(0,5) === 'data:' ? thumb : 'data:;base64,'+thumb; + $span.find('.cp-icon').hide(); + $span.prepend(img); + cb($(img)); + }; + Thumb.setPadThumbnail = function (href, b64, cb) { + cb = cb || function () {}; + var k ='thumbnail-' + href; + localForage.setItem(k, b64, cb); + }; + Thumb.displayThumbnail = function (href, $container, cb) { + cb = cb || function () {}; + var parsed = Hash.parsePadUrl(href); + var k ='thumbnail-' + href; + var whenNewThumb = function () { + var secret = Hash.getSecrets('file', parsed.hash); + var hexFileName = Util.base64ToHex(secret.channel); + var src = Hash.getBlobPathFromHex(hexFileName); + var cryptKey = secret.keys && secret.keys.fileKeyStr; + var key = Nacl.util.decodeBase64(cryptKey); + FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) { + if (!metadata.thumbnail) { + return void localForage.setItem(k, 'EMPTY'); + } + localForage.setItem(k, metadata.thumbnail, function (err) { + addThumbnail(err, metadata.thumbnail, $container, cb); + }); + }); + }; + localForage.getItem(k, function (err, v) { + if (!v && parsed.type === 'file') { + // We can only create thumbnails for files here since we can't easily decrypt pads + return void whenNewThumb(); + } + if (!v) { return; } + if (v === 'EMPTY') { return; } + addThumbnail(err, v, $container, cb); + }); + }; + return Thumb; }); diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index 4429745a8..ae0d3f3b6 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -8,7 +8,6 @@ define([ '/common/cryptpad-common.js', '/bower_components/nthen/index.js', '/common/sframe-common.js', - '/common/sframe-common-interface.js', '/customize/messages.js', '/common/common-util.js', '/common/common-thumbnail.js', @@ -27,7 +26,6 @@ define([ Cryptpad, nThen, SFCommon, - SFUI, Messages, Util, Thumb, @@ -270,23 +268,16 @@ define([ var privateDat = cpNfInner.metadataMgr.getPrivateData(); if (options.thumbnail && privateDat.thumbnails) { - var oldThumbnailState; var hash = privateDat.availableHashes.editHash || privateDat.availableHashes.viewHash; - var href = privateDat.pathname + '#' + hash; - var mkThumbnail = function () { - if (!hash) { return; } - if (state !== STATE.READY) { return; } - if (!cpNfInner.chainpad) { return; } - var content = cpNfInner.chainpad.getUserDoc(); - if (content === oldThumbnailState) { return; } - Thumb.fromDOM(options.thumbnail, function (err, b64) { - oldThumbnailState = content; - SFUI.setPadThumbnail(href, b64); - }); - }; - window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL); - window.setTimeout(mkThumbnail, Thumb.UPDATE_FIRST); + if (hash) { + options.thumbnail.href = privateDat.pathname + '#' + hash; + options.thumbnail.getContent = function () { + if (!cpNfInner.chainpad) { return; } + return cpNfInner.chainpad.getUserDoc(); + }; + Thumb.initPadThumbnails(options.thumbnail); + } } if (newPad) { diff --git a/www/common/sframe-common-interface.js b/www/common/sframe-common-interface.js index 70c79fae4..0438c896e 100644 --- a/www/common/sframe-common-interface.js +++ b/www/common/sframe-common-interface.js @@ -3,16 +3,13 @@ define([ '/api/config', '/common/cryptpad-common.js', '/common/common-util.js', - '/common/common-hash.js', '/common/media-tag.js', '/common/tippy.min.js', '/customize/application_config.js', - '/file/file-crypto.js', - '/bower_components/localforage/dist/localforage.min.js', '/bower_components/tweetnacl/nacl-fast.min.js', 'css!/common/tippy.css', -], function ($, Config, Cryptpad, Util, Hash, MediaTag, Tippy, AppConfig, FileCrypto, localForage) { +], function ($, Config, Cryptpad, Util, MediaTag, Tippy, AppConfig) { var UI = {}; var Messages = Cryptpad.Messages; var Nacl = window.nacl; @@ -33,49 +30,6 @@ define([ * - createDropdown */ - var addThumbnail = function (err, thumb, $span, cb) { - var img = new Image(); - img.src = thumb.slice(0,5) === 'data:' ? thumb : 'data:;base64,'+thumb; - $span.find('.cp-icon').hide(); - $span.prepend(img); - cb($(img)); - }; - UI.setPadThumbnail = function (href, b64, cb) { - cb = cb || $.noop; - var k ='thumbnail-' + href; - localForage.setItem(k, b64, cb); - }; - localForage.removeItem('thumbnail-/1/edit/lqg6RRnynI76LV0sR8F0YA/Nh1SNXxB5U2UjaADvODfvI5l/'); - UI.displayThumbnail = function (href, $container, cb) { - cb = cb || $.noop; - var parsed = Hash.parsePadUrl(href); - var k ='thumbnail-' + href; - var whenNewThumb = function () { - var secret = Hash.getSecrets('file', parsed.hash); - var hexFileName = Util.base64ToHex(secret.channel); - var src = Hash.getBlobPathFromHex(hexFileName); - var cryptKey = secret.keys && secret.keys.fileKeyStr; - var key = Nacl.util.decodeBase64(cryptKey); - FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) { - if (!metadata.thumbnail) { - return void localForage.setItem(k, 'EMPTY'); - } - localForage.setItem(k, metadata.thumbnail, function (err) { - addThumbnail(err, metadata.thumbnail, $container, cb); - }); - }); - }; - localForage.getItem(k, function (err, v) { - if (!v && parsed.type === 'file') { - // We can only create thumbnails for files here since we can't easily decrypt pads - return void whenNewThumb(); - } - if (!v) { return; } - if (v === 'EMPTY') { return; } - addThumbnail(err, v, $container, cb); - }); - }; - UI.updateTags = function (common, href) { var sframeChan = common.getSframeChannel(); sframeChan.query('Q_TAGS_GET', href || null, function (err, res) { diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index 19506e038..2a539e88e 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -14,7 +14,8 @@ define([ '/customize/application_config.js', '/common/cryptpad-common.js', '/common/common-realtime.js', - '/common/common-util.js' + '/common/common-util.js', + '/common/common-thumbnail.js' ], function ( $, nThen, @@ -30,7 +31,8 @@ define([ AppConfig, Cryptpad, CommonRealtime, - Util + Util, + Thumb ) { // Chainpad Netflux Inner @@ -80,7 +82,9 @@ define([ funcs.createButton = callWithCommon(UI.createButton); funcs.createUsageBar = callWithCommon(UI.createUsageBar); funcs.updateTags = callWithCommon(UI.updateTags); - funcs.displayThumbnail = UI.displayThumbnail; + + // Thumb + funcs.displayThumbnail = Thumb.displayThumbnail; // History funcs.getHistory = callWithCommon(History.create); diff --git a/www/filepicker/app-filepicker.less b/www/filepicker/app-filepicker.less index 69e92d69d..a28ec8008 100644 --- a/www/filepicker/app-filepicker.less +++ b/www/filepicker/app-filepicker.less @@ -47,6 +47,11 @@ align-items: center; + img { + max-width: 100px; + max-height: 100px; + } + .cp-filepicker-content-element-name { overflow: hidden; text-overflow: ellipsis; diff --git a/www/poll/inner.js b/www/poll/inner.js index 18f1eb845..a71f663d7 100644 --- a/www/poll/inner.js +++ b/www/poll/inner.js @@ -22,6 +22,7 @@ define([ 'cm/mode/markdown/markdown', 'css!cm/lib/codemirror.css', + '/bower_components/file-saver/FileSaver.min.js', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', @@ -801,16 +802,20 @@ define([ var initThumbnails = function () { var oldThumbnailState; var privateDat = metadataMgr.getPrivateData(); + if (!privateDat.thumbnails) { return; } // Thumbnails are disabled var hash = privateDat.availableHashes.editHash || privateDat.availableHashes.viewHash; + if (!hash) { return; } var href = privateDat.pathname + '#' + hash; var $el = $('.cp-app-poll-realtime'); //var $el = $('#cp-app-poll-table'); + var scrollTop; var options = { getContainer: function () { return $el[0]; }, filter: function (el, before) { if (before) { - //$el.parents().css('overflow', 'visible'); + $el.parents().css('overflow', 'visible'); + scrollTop = $('#cp-app-poll-form').scrollTop(); $el.css('max-height', Math.max(600, $(el).width()) + 'px'); $el.find('tr td:first-child, tr td:last-child, tr td:nth-last-child(2)') .css('position', 'static'); @@ -820,7 +825,7 @@ define([ $el.find('#cp-app-poll-table-scroll').css('max-width', '100%'); return; } - //$el.parents().css('overflow', ''); + $el.parents().css('overflow', ''); $el.css('max-height', ''); $el.find('#cp-app-poll-comments').css('display', ''); $el.find('#cp-app-poll-table-container').css('text-align', ''); @@ -828,20 +833,12 @@ define([ $el.find('#cp-app-poll-table-scroll').css('max-width', ''); $el.find('tr td:first-child, tr td:last-child, tr td:nth-last-child(2)') .css('position', ''); - } - }; - var mkThumbnail = function () { - if (!hash) { return; } - if (!APP.proxy) { return; } - var content = JSON.stringify(APP.proxy.content); - if (content === oldThumbnailState) { return; } - Thumb.fromDOM(options, function (err, b64) { - oldThumbnailState = content; - SFUI.setPadThumbnail(href, b64); - }); + $('#cp-app-poll-form').scrollTop(scrollTop); + }, + href: href, + getContent: function () { return JSON.stringify(APP.proxy.content); } }; - window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL); - window.setTimeout(mkThumbnail, Thumb.UPDATE_FIRST); + Thumb.initPadThumbnails(options); }; var checkDeletedCells = function () { diff --git a/www/whiteboard/inner.js b/www/whiteboard/inner.js index a118d2ede..7550cb98d 100644 --- a/www/whiteboard/inner.js +++ b/www/whiteboard/inner.js @@ -377,6 +377,7 @@ define([ var initThumbnails = function () { var oldThumbnailState; var privateDat = metadataMgr.getPrivateData(); + if (!privateDat.thumbnails) { return; } var hash = privateDat.availableHashes.editHash || privateDat.availableHashes.viewHash; var href = privateDat.pathname + '#' + hash; @@ -389,7 +390,7 @@ define([ var D = Thumb.getResizedDimensions($canvas[0], 'pad'); Thumb.fromCanvas($canvas[0], D, function (err, b64) { oldThumbnailState = content; - SFUI.setPadThumbnail(href, b64); + Thumb.setPadThumbnail(href, b64); }); }; window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL);