Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions lib/Listener/CSPListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ public function handle(Event $event): void {
$csp->addAllowedConnectDomain($server);
}

$csp->addAllowedWorkerSrcDomain('\'self\'');

$event->addPolicy($csp);
}
}
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
138 changes: 31 additions & 107 deletions src/components/CallView/shared/VideoBackground.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
@notify="setBlur" />
</div>
<img
v-if="hasPicture"
v-if="hasPicture && !useAverageColor"
ref="backgroundImage"
:src="backgroundImage"
:src="backgroundImageUrl"
:style="backgroundStyle"
class="video-background__picture"
alt="">
Expand All @@ -43,13 +43,13 @@
</template>

<script>
import { average } from 'color.js'
import axios from '@nextcloud/axios'
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'
import blur from '../../../utils/imageBlurrer'

const browserStorage = getBuilder('nextcloud').persist().build()

Expand Down Expand Up @@ -94,18 +94,24 @@ export default {
data() {
return {
hasPicture: false,
useCssBlurFilter: true,
useAverageColor: false,
blur: 0,
blurredBackgroundImage: null,
blurredBackgroundImageCache: {},
blurredBackgroundImageSource: null,
pendingGenerateBlurredBackgroundImageCount: 0,
isDestroyed: false,
}
},

computed: {
backgroundImageAverageColor() {
if (!this.backgroundImageUrlToAverage) {
return ''
}

return this.$store.getters.getCachedBackgroundImageAverageColor(this.backgroundImageUrlToAverage)
},
backgroundColor() {
if (this.hasPicture && this.useAverageColor) {
return this.backgroundImageAverageColor
}

// If the prop is empty. We're not checking for the default value
// because the user's displayName might be '?'
if (!this.displayName) {
Expand All @@ -115,9 +121,6 @@ export default {
return `rgb(${color.r}, ${color.g}, ${color.b})`
}
},
backgroundImage() {
return this.useCssBlurFilter ? this.backgroundImageUrl : this.blurredBackgroundImage
},
backgroundImageUrl() {
if (!this.user) {
return null
Expand All @@ -129,7 +132,7 @@ export default {
return this.gridBlur ? this.gridBlur : this.blur
},
backgroundStyle() {
if (!this.useCssBlurFilter) {
if (this.useAverageColor) {
return {}
}

Expand All @@ -138,63 +141,42 @@ export default {
}
},
// Special computed property to combine the properties that should be
// watched to set (or not) the blurred background image source.
backgroundImageUrlToBlur() {
if (this.useCssBlurFilter) {
// watched to set (or not) the background image average color.
backgroundImageUrlToAverage() {
if (!this.useAverageColor) {
return null
}

return this.backgroundImageUrl
},
// Special computed property to combine the properties that should be
// watched to generate (or not) the blurred background image.
generatedBackgroundBlur() {
if (!this.hasPicture || this.useCssBlurFilter) {
return false
}

if (!this.blurredBackgroundImageSource) {
return false
}

return this.backgroundBlur
},
},

watch: {
backgroundImageUrlToBlur: {
backgroundImageUrlToAverage: {
immediate: true,
handler() {
this.blurredBackgroundImageSource = null

if (!this.backgroundImageUrlToBlur) {
if (!this.backgroundImageUrlToAverage) {
return
}

const image = new Image()
image.onload = () => {
createImageBitmap(image).then(imageBitmap => {
this.blurredBackgroundImageSource = imageBitmap
})
}
image.src = this.backgroundImageUrlToBlur
},
},
generatedBackgroundBlur: {
immediate: true,
handler() {
if (this.generatedBackgroundBlur === false) {
if (this.backgroundImageAverageColor) {
// Already calculated, no need to do it again.
return
}

this.generateBlurredBackgroundImage()
average(this.backgroundImageUrlToAverage, { format: 'hex' }).then(color => {
this.$store.dispatch('setCachedBackgroundImageAverageColor', {
videoBackgroundId: this.backgroundImageUrlToAverage,
backgroundImageAverageColor: color,
})
})
},
},
},

async beforeMount() {
if (this.isChrome) {
this.useCssBlurFilter = false
if (!this.isFirefox) {
this.useAverageColor = true
}

if (!this.user) {
Expand Down Expand Up @@ -228,69 +210,11 @@ export default {
}
},

beforeDestroy() {
this.isDestroyed = true
},

methods: {
// Calculate the background blur based on the height of the background element
setBlur({ width, height }) {
this.blur = this.$store.getters.getBlurRadius(width, height)
},

generateBlurredBackgroundImage() {
// Reset image source so the width and height are adjusted to
// the element rather than to the previous image being shown.
this.$refs.backgroundImage.src = ''

let width = this.$refs.backgroundImage.width
let height = this.$refs.backgroundImage.height

// Restore the current background so it is shown instead of an empty
// background while the new one is being generated.
this.$refs.backgroundImage.src = this.blurredBackgroundImage

const sourceAspectRatio = this.blurredBackgroundImageSource.width / this.blurredBackgroundImageSource.height
const canvasAspectRatio = width / height

if (canvasAspectRatio > sourceAspectRatio) {
height = width / sourceAspectRatio
} else if (canvasAspectRatio < sourceAspectRatio) {
width = height * sourceAspectRatio
}

const cacheId = this.backgroundImageUrl + '-' + width + '-' + height + '-' + this.backgroundBlur
if (this.blurredBackgroundImageCache[cacheId]) {
this.blurredBackgroundImage = this.blurredBackgroundImageCache[cacheId]

return
}

if (this.pendingGenerateBlurredBackgroundImageCount) {
this.pendingGenerateBlurredBackgroundImageCount++

return
}

this.pendingGenerateBlurredBackgroundImageCount = 1

blur(this.blurredBackgroundImageSource, width, height, this.backgroundBlur).then(image => {
if (this.isDestroyed) {
return
}

this.blurredBackgroundImage = image
this.blurredBackgroundImageCache[cacheId] = this.blurredBackgroundImage

const generateBlurredBackgroundImageCalledAgain = this.pendingGenerateBlurredBackgroundImageCount > 1

this.pendingGenerateBlurredBackgroundImageCount = 0

if (generateBlurredBackgroundImageCalledAgain) {
this.generateBlurredBackgroundImage()
}
})
},
},
}
</script>
Expand Down
16 changes: 16 additions & 0 deletions src/store/callViewStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const state = {
selectedVideoPeerId: null,
videoBackgroundBlur: 1,
participantRaisedHands: {},
backgroundImageAverageColorCache: {},
}

const getters = {
Expand All @@ -59,6 +60,9 @@ const getters = {
isParticipantRaisedHand: (state) => (sessionId) => {
return state.participantRaisedHands[sessionId]?.state
},
getCachedBackgroundImageAverageColor: (state) => (videoBackgroundId) => {
return state.backgroundImageAverageColorCache[videoBackgroundId]
},
}

const mutations = {
Expand Down Expand Up @@ -94,6 +98,12 @@ const mutations = {
clearParticipantHandRaised(state) {
state.participantRaisedHands = {}
},
setCachedBackgroundImageAverageColor(state, { videoBackgroundId, backgroundImageAverageColor }) {
Vue.set(state.backgroundImageAverageColorCache, videoBackgroundId, backgroundImageAverageColor)
},
clearBackgroundImageAverageColorCache(state) {
state.backgroundImageAverageColorCache = {}
},
}

const actions = {
Expand All @@ -118,6 +128,8 @@ const actions = {
leaveCall(context) {
// clear raised hands as they were specific to the call
context.commit('clearParticipantHandRaised')

context.commit('clearBackgroundImageAverageColorCache')
},

/**
Expand Down Expand Up @@ -152,6 +164,10 @@ const actions = {
context.commit('setParticipantHandRaised', { sessionId, raisedHand })
},

setCachedBackgroundImageAverageColor(context, { videoBackgroundId, backgroundImageAverageColor }) {
context.commit('setCachedBackgroundImageAverageColor', { videoBackgroundId, backgroundImageAverageColor })
},

/**
* Starts presentation mode.
*
Expand Down
92 changes: 0 additions & 92 deletions src/utils/imageBlurrer.js

This file was deleted.

Loading