From 901cf32360653714eea17e288901fa80eb472d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Mon, 18 Jan 2021 19:59:16 +0100 Subject: [PATCH 1/6] Show the average color of the user avatar as video background in Safari MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Safari suffers the same performance hit as Chromium when using the blur filter. However, Safari does not support using the blur filter on canvases, so the same workaround used for Chromium does not work in Safari. To solve this, and to still use a background with colors related to the avatar, the average of the colors in the avatar is used. Signed-off-by: Daniel Calviño Sánchez --- package-lock.json | 5 +++ package.json | 1 + .../CallView/shared/VideoBackground.vue | 42 ++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e19dea0cb2..bc0dd7851f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7530,6 +7530,11 @@ "simple-swizzle": "^0.2.2" } }, + "color.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/color.js/-/color.js-1.2.0.tgz", + "integrity": "sha512-0ajlNgWWOR7EK9N6l2h0YKsZPzMCLQG5bheCoTGpGfhkR8tB5eQNItdua1oFHDTeq9JKgSzQJqo+Gp3V/xW+Lw==" + }, "colorette": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", diff --git a/package.json b/package.json index a5e42daadbf..b7cf79f7dd9 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@nextcloud/vue": "^3.4.0", "@nextcloud/vue-dashboard": "^1.0.1", "attachmediastream": "^2.1.0", + "color.js": "^1.2.0", "crypto-js": "^4.0.0", "debounce": "^1.2.0", "emoji-regex": "^9.2.0", diff --git a/src/components/CallView/shared/VideoBackground.vue b/src/components/CallView/shared/VideoBackground.vue index 8ff2878ba1a..990e656cbbc 100644 --- a/src/components/CallView/shared/VideoBackground.vue +++ b/src/components/CallView/shared/VideoBackground.vue @@ -30,7 +30,7 @@ @notify="setBlur" /> diff --git a/src/utils/imageBlurrer.js b/src/utils/imageBlurrer.js deleted file mode 100644 index 2a29e27d117..00000000000 --- a/src/utils/imageBlurrer.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * - * @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -import { generateFilePath } from '@nextcloud/router' - -let worker - -const pendingResults = {} -let pendingResultsNextId = 0 - -function loadWorker() { - try { - worker = new Worker(generateFilePath('spreed', '', 'js/image-blurrer-worker.js')) - worker.onmessage = function(message) { - const pendingResult = pendingResults[message.data.id] - if (!pendingResult) { - console.debug('No pending result for blurring image with id ' + message.data.id) - - return - } - - pendingResult(message.data.blurredImageAsDataUrl) - - delete pendingResults[message.data.id] - } - } catch (exception) { - worker = null - console.error('Image blurrer worker could not be loaded', exception) - } -} - -function blurSync(image, width, height, blurRadius) { - return new Promise((resolve, reject) => { - const canvas = document.createElement('canvas') - canvas.width = width - canvas.height = height - - const context = canvas.getContext('2d') - context.filter = `blur(${blurRadius}px)` - context.drawImage(image, 0, 0, canvas.width, canvas.height) - - resolve(canvas.toDataURL()) - }) -} - -export default function blur(image, width, height, blurRadius) { - if (typeof OffscreenCanvas === 'undefined') { - return blurSync(image, width, height, blurRadius) - } - - if (worker === undefined) { - loadWorker() - } - - if (!worker) { - return blurSync(image, width, height, blurRadius) - } - - const id = pendingResultsNextId - - pendingResultsNextId++ - - return new Promise((resolve, reject) => { - pendingResults[id] = resolve - - worker.postMessage({ - id: id, - image: image, - width: width, - height: height, - blurRadius: blurRadius, - }) - }) -} diff --git a/src/utils/imageBlurrerWorker.js b/src/utils/imageBlurrerWorker.js deleted file mode 100644 index 756da1ff0a2..00000000000 --- a/src/utils/imageBlurrerWorker.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * - * @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -const fileReaderSync = new global.FileReaderSync() - -onmessage = function(message) { - const offscreenCanvas = new OffscreenCanvas(message.data.width, message.data.height) - - const context = offscreenCanvas.getContext('2d') - context.filter = `blur(${message.data.blurRadius}px)` - context.drawImage(message.data.image, 0, 0, offscreenCanvas.width, offscreenCanvas.height) - - offscreenCanvas.convertToBlob().then(blob => { - postMessage({ - id: message.data.id, - blurredImageAsDataUrl: fileReaderSync.readAsDataURL(blob), - }) - }) -} diff --git a/webpack.common.js b/webpack.common.js index fd5e11bbdce..959514bb7fe 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -7,11 +7,6 @@ module.exports = { entry: { 'admin-settings': path.join(__dirname, 'src', 'mainAdminSettings.js'), 'collections': path.join(__dirname, 'src', 'collections.js'), - // There is a "worker-loader" plugin for Webpack, but I was not able to - // get it to work ("publicPath" uses "output.publicPath" rather than the - // one set in the plugin - // https://github.com/webpack-contrib/worker-loader/issues/281). - 'image-blurrer-worker': path.join(__dirname, 'src', 'utils/imageBlurrerWorker.js'), 'talk': path.join(__dirname, 'src', 'main.js'), 'talk-files-sidebar': [ path.join(__dirname, 'src', 'mainFilesSidebar.js'), From 9eb01887df8c72e88f1b2075f913ef3e126a04a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Mon, 25 Jan 2021 09:42:34 +0100 Subject: [PATCH 4/6] Replace blur with average color in video background in all cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency between browsers now the average color is shown in all cases, even if CSS blur filters work fine in Firefox. Signed-off-by: Daniel Calviño Sánchez --- .../CallView/shared/VideoBackground.vue | 51 +++---------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/src/components/CallView/shared/VideoBackground.vue b/src/components/CallView/shared/VideoBackground.vue index fc874441edd..3359d436f62 100644 --- a/src/components/CallView/shared/VideoBackground.vue +++ b/src/components/CallView/shared/VideoBackground.vue @@ -29,14 +29,7 @@ class="observer" @notify="setBlur" /> - -
@@ -49,7 +42,6 @@ import usernameToColor from '@nextcloud/vue/dist/Functions/usernameToColor' import { generateUrl } from '@nextcloud/router' import { ResizeObserver } from 'vue-resize' import { getBuilder } from '@nextcloud/browser-storage' -import browserCheck from '../../../mixins/browserCheck' const browserStorage = getBuilder('nextcloud').persist().build() @@ -72,10 +64,6 @@ export default { ResizeObserver, }, - mixins: [ - browserCheck, - ], - props: { displayName: { type: String, @@ -94,21 +82,20 @@ export default { data() { return { hasPicture: false, - useAverageColor: false, blur: 0, } }, computed: { backgroundImageAverageColor() { - if (!this.backgroundImageUrlToAverage) { + if (!this.backgroundImageUrl) { return '' } - return this.$store.getters.getCachedBackgroundImageAverageColor(this.backgroundImageUrlToAverage) + return this.$store.getters.getCachedBackgroundImageAverageColor(this.backgroundImageUrl) }, backgroundColor() { - if (this.hasPicture && this.useAverageColor) { + if (this.hasPicture) { return this.backgroundImageAverageColor } @@ -131,31 +118,13 @@ export default { backgroundBlur() { return this.gridBlur ? this.gridBlur : this.blur }, - backgroundStyle() { - if (this.useAverageColor) { - return {} - } - - return { - filter: `blur(${this.backgroundBlur}px)`, - } - }, - // Special computed property to combine the properties that should be - // watched to set (or not) the background image average color. - backgroundImageUrlToAverage() { - if (!this.useAverageColor) { - return null - } - - return this.backgroundImageUrl - }, }, watch: { - backgroundImageUrlToAverage: { + backgroundImageUrl: { immediate: true, handler() { - if (!this.backgroundImageUrlToAverage) { + if (!this.backgroundImageUrl) { return } @@ -164,9 +133,9 @@ export default { return } - average(this.backgroundImageUrlToAverage, { format: 'hex' }).then(color => { + average(this.backgroundImageUrl, { format: 'hex' }).then(color => { this.$store.dispatch('setCachedBackgroundImageAverageColor', { - videoBackgroundId: this.backgroundImageUrlToAverage, + videoBackgroundId: this.backgroundImageUrl, backgroundImageAverageColor: color, }) }) @@ -175,10 +144,6 @@ export default { }, async beforeMount() { - if (!this.isFirefox) { - this.useAverageColor = true - } - if (!this.user) { return } From 69b9fe6953d3b69a0cff110d616e427a8ef9aa29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Mon, 25 Jan 2021 09:44:25 +0100 Subject: [PATCH 5/6] Remove no longer needed blur related code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel Calviño Sánchez --- src/components/CallView/Grid/Grid.vue | 6 ---- src/components/CallView/shared/Video.vue | 11 ++---- .../CallView/shared/VideoBackground.vue | 36 +------------------ src/store/callViewStore.js | 8 ----- 4 files changed, 3 insertions(+), 58 deletions(-) diff --git a/src/components/CallView/Grid/Grid.vue b/src/components/CallView/Grid/Grid.vue index c562625183a..c048850ed88 100644 --- a/src/components/CallView/Grid/Grid.vue +++ b/src/components/CallView/Grid/Grid.vue @@ -72,7 +72,6 @@ :is-selected="isSelected(callParticipantModel)" :fit-video="false" :video-container-aspect-ratio="videoContainerAspectRatio" - :video-background-blur="videoBackgroundBlur" :shared-data="sharedDatas[callParticipantModel.attributes.peerId]" @click-video="handleClickVideo($event, callParticipantModel.attributes.peerId)" /> @@ -439,11 +438,6 @@ export default { } }, - // Blur radius for each background in the grid - videoBackgroundBlur() { - return this.$store.getters.getBlurRadius(this.videoWidth, this.videoHeight) - }, - stripeOpen() { return this.$store.getters.isStripeOpen }, diff --git a/src/components/CallView/shared/Video.vue b/src/components/CallView/shared/Video.vue index 2d5c9f3fbd4..acaec600949 100644 --- a/src/components/CallView/shared/Video.vue +++ b/src/components/CallView/shared/Video.vue @@ -50,8 +50,7 @@