mirror of
https://github.com/pixelfed/pixelfed.git
synced 2025-02-07 04:10:46 +00:00
Merge pull request #5455 from taye/fix-webgl-filters
fix(compose-modal): avoid WebGL if it's not needed
This commit is contained in:
commit
6ef4af29fe
3 changed files with 90 additions and 26 deletions
37
package-lock.json
generated
37
package-lock.json
generated
|
@ -44,7 +44,7 @@
|
||||||
"vue-loading-overlay": "^3.3.3",
|
"vue-loading-overlay": "^3.3.3",
|
||||||
"vue-timeago": "^5.1.2",
|
"vue-timeago": "^5.1.2",
|
||||||
"vue-tribute": "^1.0.7",
|
"vue-tribute": "^1.0.7",
|
||||||
"webgl-media-editor": "^0.0.1",
|
"webgl-media-editor": "^0.0.6",
|
||||||
"zuck.js": "^1.6.0"
|
"zuck.js": "^1.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -2323,6 +2323,12 @@
|
||||||
"m3u8-parser": "~4.7.1"
|
"m3u8-parser": "~4.7.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@reactively/core": {
|
||||||
|
"version": "0.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reactively/core/-/core-0.0.8.tgz",
|
||||||
|
"integrity": "sha512-5uAnNf2gQSm3gM7z6Lx079H1/MuDQQI+5aYfwyDFGR9nHZj8yblLY/6aOJVWp+NcBwXVBKuWQ28qWHD9F1qN1w==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/@thaunknown/simple-peer": {
|
"node_modules/@thaunknown/simple-peer": {
|
||||||
"version": "10.0.11",
|
"version": "10.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@thaunknown/simple-peer/-/simple-peer-10.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@thaunknown/simple-peer/-/simple-peer-10.0.11.tgz",
|
||||||
|
@ -5645,6 +5651,15 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fine-jsx": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/fine-jsx/-/fine-jsx-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-UKQ0ymyZnA605yf7np/wAv3iTs6i9oRKgyYmz+dX+F3VanYEBr60zRQ+WPcYzXMtl9NghNxT736qHfDBjoXVDg==",
|
||||||
|
"license": "AGPL-3.0-only",
|
||||||
|
"dependencies": {
|
||||||
|
"@reactively/core": "^0.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fizzy-ui-utils": {
|
"node_modules/fizzy-ui-utils": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz",
|
||||||
|
@ -10749,16 +10764,28 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/webgl-effects": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/webgl-effects/-/webgl-effects-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-P+qxcO0QyydUnHHwnsge2ckou85Pnsdgn0BKAjrhD9LiPFz5i2hq8rT8AdS7wNdXrXyqlM1Y0id+AB0gKTDtpQ==",
|
||||||
|
"license": "AGPL-3.0-only",
|
||||||
|
"dependencies": {
|
||||||
|
"gl-matrix": "^3.4.3",
|
||||||
|
"twgl.js": "^5.5.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/webgl-media-editor": {
|
"node_modules/webgl-media-editor": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/webgl-media-editor/-/webgl-media-editor-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webgl-media-editor/-/webgl-media-editor-0.0.6.tgz",
|
||||||
"integrity": "sha512-TxnuRl3rpWa1Cia/pn+vh+0iz3yDNwzsrnRGJ61YkdZAYuimu2afBivSHv0RK73hKza6Y/YoRCkuEcsFmtxPNw==",
|
"integrity": "sha512-hqpIY+a+ay3QzXKECC4pFSHS0dVogV3GlBWzuSwBzEeGZcs7MeEYxLhFdqUa1D2xFtNnXb0pAo+1lCndYDKP2A==",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cropperjs": "^1.6.2",
|
"cropperjs": "^1.6.2",
|
||||||
|
"fine-jsx": "^0.0.5",
|
||||||
"gl-matrix": "^3.4.3",
|
"gl-matrix": "^3.4.3",
|
||||||
"throttle-debounce": "^5.0.2",
|
"throttle-debounce": "^5.0.2",
|
||||||
"twgl.js": "^5.5.4"
|
"twgl.js": "^5.5.4",
|
||||||
|
"webgl-effects": "^0.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
"vue-loading-overlay": "^3.3.3",
|
"vue-loading-overlay": "^3.3.3",
|
||||||
"vue-timeago": "^5.1.2",
|
"vue-timeago": "^5.1.2",
|
||||||
"vue-tribute": "^1.0.7",
|
"vue-tribute": "^1.0.7",
|
||||||
"webgl-media-editor": "^0.0.1",
|
"webgl-media-editor": "^0.0.6",
|
||||||
"zuck.js": "^1.6.0"
|
"zuck.js": "^1.6.0"
|
||||||
},
|
},
|
||||||
"collective": {
|
"collective": {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue