fix(compose-modal): avoid WebGL if it's not needed

This commit is contained in:
Taye Adeyemi 2025-01-12 12:48:27 +01:00
parent 7fe6dad609
commit 103712b6db

View file

@ -1015,19 +1015,29 @@ export default {
}, },
created() { created() {
try {
this.editor = new MediaEditor({ this.editor = new MediaEditor({
effects: filterEffects, effects: filterEffects,
onEdit: (index, {effect, intensity, crop}) => { onEdit: (sourceIndex, {effect, intensity, crop}) => {
if (index >= this.files.length) return if (sourceIndex >= this.files.length) return
const file = this.files[index] const file = this.files[sourceIndex]
this.$set(file, 'editState', { effect, intensity, crop }) this.$set(file, 'editState', { effect, intensity, crop })
}, },
onRenderPreview: (sourceIndex, previewUrl) => { onRenderPreview: (sourceIndex, previewUrl) => {
if (sourceIndex >= this.files.length) return
const file = this.files[sourceIndex]
const { editState } = file
const media = this.media[sourceIndex] const media = this.media[sourceIndex]
if (media) media.preview_url = previewUrl
// If the image was edited, use the preview image from the editor.
if (editState && (editState.crop || editState.effect !== -1)) media.preview_url = previewUrl
// When no edits are applied, use the original media URL.
// This limits broken previews with firefox's resistFingerprinting setting.
else media.preview_url = media.url
}, },
}) })
} catch {}
}, },
computed: { computed: {
@ -1054,8 +1064,9 @@ export default {
}, },
destroyed() { destroyed() {
this.files.forEach(fileInfo => { this.media.forEach(media => {
URL.revokeObjectURL(fileInfo.url); URL.revokeObjectURL(media.url);
URL.revokeObjectURL(media.preview_url);
}) })
this.files.length = this.media.length = 0 this.files.length = this.media.length = 0
this.editor = undefined this.editor = undefined
@ -1161,7 +1172,7 @@ export default {
const type = file.type.replace(/\/.*/, '') const type = file.type.replace(/\/.*/, '')
const url = URL.createObjectURL(file) const url = URL.createObjectURL(file)
const preview_url = type === 'image' ? url : '/storage/no-preview.png' const preview_url = type === 'image' ? URL.createObjectURL(file) : '/storage/no-preview.png'
this.files.push({ file, editState: undefined }) this.files.push({ file, editState: undefined })
this.media.push({ url, preview_url, type }) this.media.push({ url, preview_url, type })
@ -1182,8 +1193,17 @@ export default {
const media = this.media[i] const media = this.media[i]
if (media.type === 'image' && fileInfo.editState) { if (media.type === 'image' && fileInfo.editState) {
const { editState, cropperBlob } = fileInfo
// If the WebGL editor is supported by the browser, apply the edits and use the resulting blob
if (this.editor && (editState.effect !== -1 || !!editState.crop)) {
file = await this.editor.toBlob(i) file = await this.editor.toBlob(i)
} }
// Otherwise, only the cropped result from cropper.js may be used
else if (cropperBlob) {
file = cropperBlob
}
}
let form = new FormData(); let form = new FormData();
form.append('file', file); form.append('file', file);
@ -1555,12 +1575,29 @@ export default {
break; break;
case 'cropPhoto': case 'cropPhoto':
const { editState } = this.files[this.carouselCursor] const file = this.files[this.carouselCursor]
const { cropper } = this.$refs
// update the file state in this vue component
const croppedState = { const croppedState = {
...editState, ...file.editState,
crop: this.$refs.cropper.getData() crop: cropper.getData()
} }
if (this.editor) {
// also update the file state in the WebGL editor
this.editor.setEditState(this.carouselCursor, croppedState) this.editor.setEditState(this.carouselCursor, croppedState)
} else {
// if the browser can't run the WebGL editor, get the cropped image from cropper.js
cropper.getCroppedCanvas().toBlob((blob) => {
const { media } = this.media[this.carouselCursor]
file.croppedBlob = blob
URL.revokeObjectURL(media.preview_url)
media.preview_url = URL.createObjectURL(blob)
})
}
this.page = 2; this.page = 2;
break; break;