|
@@ -1766,57 +1766,91 @@ export default {
|
|
|
|
|
|
applyFilterToMedia() {
|
|
|
// this is where the magic happens
|
|
|
- var ua = navigator.userAgent.toLowerCase();
|
|
|
- if(ua.indexOf('firefox') == -1 && ua.indexOf('chrome') == -1) {
|
|
|
- this.isPosting = false;
|
|
|
- swal('Oops!', 'Your browser does not support the filter feature.', 'error');
|
|
|
- this.page = 3;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
let count = this.media.filter(m => m.filter_class).length;
|
|
|
if(count) {
|
|
|
this.page = 'filteringMedia';
|
|
|
this.filteringRemainingCount = count;
|
|
|
this.$nextTick(() => {
|
|
|
this.isFilteringMedia = true;
|
|
|
- this.media.forEach((media, idx) => this.applyFilterToMediaSave(media, idx));
|
|
|
+ Promise.all(this.media.map(media => {
|
|
|
+ return this.applyFilterToMediaSave(media);
|
|
|
+ })).catch(err => {
|
|
|
+ console.error(err);
|
|
|
+ swal('Oops!', 'An error occurred while applying filters to your media. Please refresh the page and try again. If the problem persist, please try a different web browser.', 'error');
|
|
|
+ });
|
|
|
})
|
|
|
} else {
|
|
|
this.page = 3;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- applyFilterToMediaSave(media, idx) {
|
|
|
+ async applyFilterToMediaSave(media) {
|
|
|
if(!media.filter_class) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- let self = this;
|
|
|
- let data = null;
|
|
|
- const canvas = document.createElement('canvas');
|
|
|
- const ctx = canvas.getContext('2d');
|
|
|
- let image = document.createElement('img');
|
|
|
+ // Load image
|
|
|
+ const image = document.createElement('img');
|
|
|
image.src = media.url;
|
|
|
- image.addEventListener('load', e => {
|
|
|
+ await new Promise((resolve, reject) => {
|
|
|
+ image.addEventListener('load', () => resolve());
|
|
|
+ image.addEventListener('error', () => {
|
|
|
+ reject(new Error('Failed to load image'));
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // Create canvas
|
|
|
+ let canvas;
|
|
|
+ let usingOffscreenCanvas = false;
|
|
|
+ if('OffscreenCanvas' in window) {
|
|
|
+ canvas = new OffscreenCanvas(image.width, image.height);
|
|
|
+ usingOffscreenCanvas = true;
|
|
|
+ } else {
|
|
|
+ canvas = document.createElement('canvas');
|
|
|
canvas.width = image.width;
|
|
|
canvas.height = image.height;
|
|
|
- ctx.filter = App.util.filterCss[media.filter_class];
|
|
|
- ctx.drawImage(image, 0, 0, image.width, image.height);
|
|
|
- ctx.save();
|
|
|
- canvas.toBlob(function(blob) {
|
|
|
- data = new FormData();
|
|
|
- data.append('file', blob);
|
|
|
- data.append('id', media.id);
|
|
|
- axios.post('/api/compose/v0/media/update', data)
|
|
|
- .then(res => {
|
|
|
- self.media[idx].is_filtered = true;
|
|
|
- self.updateFilteringMedia();
|
|
|
- }).catch(err => {
|
|
|
- });
|
|
|
- }, media.mime, 0.9);
|
|
|
- });
|
|
|
- ctx.clearRect(0, 0, image.width, image.height);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Draw image with filter to canvas
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+ if (!ctx) {
|
|
|
+ throw new Error('Failed to get canvas context');
|
|
|
+ }
|
|
|
+ if (!('filter' in ctx)) {
|
|
|
+ throw new Error('Canvas filter not supported');
|
|
|
+ }
|
|
|
+ ctx.filter = App.util.filterCss[media.filter_class];
|
|
|
+ ctx.drawImage(image, 0, 0, image.width, image.height);
|
|
|
+ ctx.save();
|
|
|
+
|
|
|
+ // Convert canvas to blob
|
|
|
+ let blob;
|
|
|
+ if(usingOffscreenCanvas) {
|
|
|
+ blob = await canvas.convertToBlob({
|
|
|
+ type: media.mime,
|
|
|
+ quality: 1,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ blob = await new Promise(resolve => {
|
|
|
+ canvas.toBlob(blob => {
|
|
|
+ if(blob) {
|
|
|
+ resolve(blob);
|
|
|
+ } else {
|
|
|
+ reject(
|
|
|
+ new Error('Failed to convert canvas to blob'),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }, media.mime, 1);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Upload blob / Update media
|
|
|
+ const data = new FormData();
|
|
|
+ data.append('file', blob);
|
|
|
+ data.append('id', media.id);
|
|
|
+ await axios.post('/api/compose/v0/media/update', data);
|
|
|
+ media.is_filtered = true;
|
|
|
+ this.updateFilteringMedia();
|
|
|
},
|
|
|
|
|
|
updateFilteringMedia() {
|