diff --git a/Makefile b/Makefile index d9e4e92e..439e89ca 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,9 @@ build-js-production: rm -f js/* && npm run build patch-external: - patch -p1 < patches/scroller-perf.patch - patch -p1 < patches/scroller-sticky.patch + patch -p1 -N < patches/scroller-perf.patch || true + patch -p1 -N < patches/scroller-sticky.patch || true + bash ./patches/filerobot-patch.sh watch-js: npm run watch diff --git a/patches/filerobot-loadImage.js b/patches/filerobot-loadImage.js new file mode 100644 index 00000000..dc602774 --- /dev/null +++ b/patches/filerobot-loadImage.js @@ -0,0 +1,22 @@ +/** + * Filerobot has issues with loading images from HTML elements. + * We need to wait for the react object to be created properly before loading. + * This is a monkey patch to select an existing image using a global, but after wait. + */ + +import loadImageOriginal from './loadImageOriginal.js'; + +var loadImage = function() { + const image = globalThis._fileRobotOverrideImage; + if (image) { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(image); + }, 0); + }); + } + + return loadImageOriginal.apply(this, arguments); +} + +export default loadImage; \ No newline at end of file diff --git a/patches/filerobot-patch.sh b/patches/filerobot-patch.sh new file mode 100644 index 00000000..21fb6914 --- /dev/null +++ b/patches/filerobot-patch.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +target="node_modules/react-filerobot-image-editor/lib/utils" + +if [ -f $target/loadImageOriginal.js ]; then + echo "Filerobot is already patched, copying patch again ..." +else + if [ ! -f $target/loadImage.js ]; then + echo "Filerobot not installed or patch outdated" + exit 1 + fi + + echo "Patching filerobot-image-editor ..." + cp $target/loadImage.js $target/loadImageOriginal.js +fi + +cp patches/filerobot-loadImage.js $target/loadImage.js \ No newline at end of file diff --git a/src/components/viewer/ImageEditor.vue b/src/components/viewer/ImageEditor.vue index 4997ea93..e386ebc8 100644 --- a/src/components/viewer/ImageEditor.vue +++ b/src/components/viewer/ImageEditor.vue @@ -52,7 +52,10 @@ export default defineComponent({ computed: { config(): FilerobotImageEditorConfig & { theme: any } { return { - source: "nonexistent", + source: + this.photo.h && this.photo.w + ? utils.getPreviewUrl(this.photo, false, "screen") + : API.IMAGE_DECODABLE(this.photo.fileid, this.photo.etag), defaultSavedImageName: this.defaultSavedImageName, defaultSavedImageType: this.defaultSavedImageType, @@ -145,10 +148,9 @@ export default defineComponent({ async mounted() { await loadFilerobot(); - const div = this.$refs.editor; - const config = this.config; - config.source = await this.getImg(); + globalThis._fileRobotOverrideImage = await this.getImage(); + const div = this.$refs.editor; this.imageEditor = new FilerobotImageEditor(div, this.config); this.imageEditor.render(); @@ -160,29 +162,25 @@ export default defineComponent({ if (this.imageEditor) { this.imageEditor.terminate(); } + globalThis._fileRobotOverrideImage = undefined; window.removeEventListener("keydown", this.handleKeydown, true); }, methods: { - async getImg(): Promise { - if (this.photo.w && this.photo.h) { - // Fetch the image to a blob - const preview = utils.getPreviewUrl(this.photo, false, 2048); + async getImage(): Promise { + const img = new Image(); - // Fetch preview image - const img = new Image(); + await new Promise(async (resolve) => { + img.onload = resolve; + img.src = await fetchImage(this.config.source); + }); + + if (this.photo.w && this.photo.h) { img.height = this.photo.h; img.width = this.photo.w; - await new Promise(async (resolve) => { - img.onload = resolve; - img.src = await fetchImage(preview); - }); - - return img; } - // If we don't have the size, we need to use the original image - return API.IMAGE_DECODABLE(this.photo.fileid, this.photo.etag); + return img; }, onClose(closingReason, haveNotSavedChanges) { @@ -241,13 +239,9 @@ export default defineComponent({ // Success, emit an appropriate event showSuccess(this.t("memories", "Image saved successfully")); - console.log(state); - if (fileid !== this.photo.fileid) { - console.log("Fileid changed", fileid); emit("files:file:created", { fileid }); } else { - console.log("Fileid unchanged", fileid); emit("files:file:updated", { fileid }); } this.onClose(undefined, false); diff --git a/src/components/viewer/Viewer.vue b/src/components/viewer/Viewer.vue index 641b8cb1..30e882aa 100644 --- a/src/components/viewer/Viewer.vue +++ b/src/components/viewer/Viewer.vue @@ -779,10 +779,7 @@ export default defineComponent({ /** Get base data object */ getItemData(photo: IPhoto) { - const sw = Math.floor(screen.width * devicePixelRatio); - const sh = Math.floor(screen.height * devicePixelRatio); - let previewUrl = utils.getPreviewUrl(photo, false, [sw, sh]); - + let previewUrl = utils.getPreviewUrl(photo, false, "screen"); const isvideo = photo.flag & this.c.FLAG_IS_VIDEO; // Preview aren't animated diff --git a/src/services/utils/helpers.ts b/src/services/utils/helpers.ts index cbf35ff1..76787496 100644 --- a/src/services/utils/helpers.ts +++ b/src/services/utils/helpers.ts @@ -5,8 +5,16 @@ import { API } from "../API"; export function getPreviewUrl( photo: IPhoto, square: boolean, - size: number | [number, number] + size: number | [number, number] | "screen" ) { + // Screen-appropriate size + if (size === "screen") { + const sw = Math.floor(screen.width * devicePixelRatio); + const sh = Math.floor(screen.height * devicePixelRatio); + size = [sw, sh]; + } + + // Convert to array const [x, y] = typeof size === "number" ? [size, size] : size; return API.Q(API.IMAGE_PREVIEW(photo.fileid), {