diff --git a/public/scripts/network.js b/public/scripts/network.js index 91284429..0c479cc5 100644 --- a/public/scripts/network.js +++ b/public/scripts/network.js @@ -332,6 +332,8 @@ class Peer { this._filesQueue = []; this._busy = false; + this.maxMessageSize = 65536; // 64 KB + // evaluate auto accept this._evaluateAutoAccept(); } @@ -450,14 +452,7 @@ class Peer { Events.fire('set-progress', {peerId: this._peerId, progress: 0.8, status: 'prepare'}) - let dataUrl = ''; - if (files[0].type.split('/')[0] === 'image') { - try { - dataUrl = await getThumbnailAsDataUrl(files[0], 400, null, 0.9); - } catch (e) { - console.error(e); - } - } + let dataUrl = await this.getFileTransferThumbnail(files[0]); Events.fire('set-progress', {peerId: this._peerId, progress: 1, status: 'prepare'}) @@ -472,6 +467,27 @@ class Peer { Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'wait'}) } + async getFileTransferThumbnail(image) { + if (image.type.split('/')[0] !== 'image') return ''; + + let dataUrl = ''; + try { + // Iteratively lower thumbnail quality until its size is less than maxMessageSize - 2 kB + let quality = 1; + do { + quality -= 0.1; + if (quality <= 0) { + console.error("Could not create thumbnail that fits into one message."); + return ''; + } + dataUrl = await getThumbnailAsDataUrl(image, 450, 450, quality); + } while (new Blob([dataUrl]).size + 2_000 > this.maxMessageSize); + } catch (e) { + console.error(e); + } + return dataUrl; + } + async sendFiles() { for (let i=0; i this._onBeforeUnload(e)); Events.on('pagehide', _ => this._onPageHide()); Events.fire('peer-connected', {peerId: this._peerId, connectionHash: this.getConnectionHash()}); + this._setMaxMessageSize(); + } + + _setMaxMessageSize() { + this.maxMessageSize = this._conn && this._conn.sctp + ? Math.min(this._conn.sctp.maxMessageSize, 1048576) // 1 MB max + : 262144; // 256 KB } _onMessage(message) { diff --git a/public/scripts/ui.js b/public/scripts/ui.js index c9bd3658..1d7761af 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -281,10 +281,8 @@ class PeersUI { if (files[0].type.split('/')[0] === 'image') { try { - let imageUrl = await getThumbnailAsDataUrl(files[0], 80, null, 0.9); - + let imageUrl = await getThumbnailAsDataUrl(files[0], 80, 80, 0.9); this.$shareModeImageThumb.style.backgroundImage = `url(${imageUrl})`; - this.$shareModeImageThumb.removeAttribute('hidden'); } catch (e) { console.error(e); diff --git a/public/scripts/util.js b/public/scripts/util.js index fc418ff8..36d212ca 100644 --- a/public/scripts/util.js +++ b/public/scripts/util.js @@ -493,26 +493,40 @@ function getThumbnailAsDataUrl(file, width = undefined, height = undefined, qual await waitUntilImageIsLoaded(imageUrl); - let imageWidth = image.width; - let imageHeight = image.height; let canvas = document.createElement('canvas'); + let heightForSpecifiedWidth; + let widthForSpecifiedHeight; - // resize the canvas and draw the image data into it + if (width) { + heightForSpecifiedWidth = Math.floor(image.height * width / image.width); + } + if (height) { + widthForSpecifiedHeight = Math.floor(image.width * height / image.height); + } + + // resize the canvas and draw the image on it if (width && height) { - canvas.width = width; - canvas.height = height; + // mode "contain": preserve aspect ratio and use arguments as boundaries + if (height > heightForSpecifiedWidth) { + canvas.width = width; + canvas.height = heightForSpecifiedWidth; + } + else { + canvas.width = widthForSpecifiedHeight; + canvas.height = height; + } } else if (width) { canvas.width = width; - canvas.height = Math.floor(imageHeight * width / imageWidth) + canvas.height = heightForSpecifiedWidth; } else if (height) { - canvas.width = Math.floor(imageWidth * height / imageHeight); + canvas.width = widthForSpecifiedHeight; canvas.height = height; } else { - canvas.width = imageWidth; - canvas.height = imageHeight + canvas.width = image.width; + canvas.height = image.height } let ctx = canvas.getContext("2d");