diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index 6f6610cb48..7ac4857625 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -59,6 +59,7 @@ module.exports = { "linebreak-style": ["error", "unix"], "eol-last": ["error", "always"], "max-len": ["error", { code: 200, tabWidth: 4 }], + "prefer-destructuring": "off", "no-console": "warn", "no-debugger": "warn", "no-param-reassign": ["error", { props: false }], @@ -71,7 +72,7 @@ module.exports = { "@typescript-eslint/indent": "off", "@typescript-eslint/camelcase": "off", "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", ignoreRestSiblings: true }], "@typescript-eslint/explicit-function-return-type": ["error"], // Import plugin config (used to intelligently validate module import statements) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 0de5a2442a..20bf48b8ab 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -318,11 +318,8 @@ export default defineComponent({ this.inputManager = createInputManager(this.editor, this.$el.parentElement, this.dialog, this.documents, this.fullscreen); }, beforeUnmount() { - const { inputManager } = this; - if (inputManager) inputManager.removeListeners(); - - const { editor } = this; - editor.instance.free(); + this.inputManager?.removeListeners(); + this.editor.instance.free(); }, components: { MainWindow, diff --git a/frontend/src/components/panels/Document.vue b/frontend/src/components/panels/Document.vue index 94d1d97044..fa6905cd97 100644 --- a/frontend/src/components/panels/Document.vue +++ b/frontend/src/components/panels/Document.vue @@ -329,22 +329,21 @@ export default defineComponent({ const rulerHorizontal = this.$refs.rulerHorizontal as typeof CanvasRuler; const rulerVertical = this.$refs.rulerVertical as typeof CanvasRuler; - if (rulerHorizontal) rulerHorizontal.handleResize(); - if (rulerVertical) rulerVertical.handleResize(); + rulerHorizontal?.handleResize(); + rulerVertical?.handleResize(); }, pasteFile(e: DragEvent) { const { dataTransfer } = e; if (!dataTransfer) return; e.preventDefault(); - Array.from(dataTransfer.items).forEach((item) => { + Array.from(dataTransfer.items).forEach(async (item) => { const file = item.getAsFile(); - if (file && file.type.startsWith("image")) { - file.arrayBuffer().then((buffer): void => { - const u8Array = new Uint8Array(buffer); + if (file?.type.startsWith("image")) { + const buffer = await file.arrayBuffer(); + const u8Array = new Uint8Array(buffer); - this.editor.instance.paste_image(file.type, u8Array, e.clientX, e.clientY); - }); + this.editor.instance.paste_image(file.type, u8Array, e.clientX, e.clientY); } }); }, @@ -400,11 +399,13 @@ export default defineComponent({ const range = document.createRange(); range.selectNodeContents(addedInput); + const selection = window.getSelection(); if (selection) { selection.removeAllRanges(); selection.addRange(range); } + addedInput.focus(); addedInput.click(); }); @@ -455,24 +456,20 @@ export default defineComponent({ this.canvasCursor = updateMouseCursor.cursor; }); this.editor.dispatcher.subscribeJsMessage(TriggerTextCommit, () => { - if (this.textInput) this.editor.instance.on_change_text(textInputCleanup(this.textInput.innerText)); + if (this.textInput) { + const textCleaned = textInputCleanup(this.textInput.innerText); + this.editor.instance.on_change_text(textCleaned); + } }); - this.editor.dispatcher.subscribeJsMessage(TriggerFontLoad, (triggerFontLoad) => { - fetch(triggerFontLoad.font) - .then((response) => response.arrayBuffer()) - .then((response) => { - this.editor.instance.on_font_load(triggerFontLoad.font, new Uint8Array(response), false); - }); + this.editor.dispatcher.subscribeJsMessage(TriggerFontLoad, async (triggerFontLoad) => { + const response = await fetch(triggerFontLoad.font); + const responseBuffer = await response.arrayBuffer(); + this.editor.instance.on_font_load(triggerFontLoad.font, new Uint8Array(responseBuffer), false); }); this.editor.dispatcher.subscribeJsMessage(TriggerDefaultFontLoad, loadDefaultFont); - this.editor.dispatcher.subscribeJsMessage(TriggerTextCopy, async (triggerTextCopy) => { - // Clipboard API supported? - if (!navigator.clipboard) return; - - // copy text to clipboard - if (navigator.clipboard.writeText) { - await navigator.clipboard.writeText(triggerTextCopy.copy_text); - } + this.editor.dispatcher.subscribeJsMessage(TriggerTextCopy, (triggerTextCopy) => { + // If the Clipboard API is supported in the browser, copy text to the clipboard + navigator.clipboard?.writeText?.(triggerTextCopy.copy_text); }); this.editor.dispatcher.subscribeJsMessage(DisplayEditableTextbox, (displayEditableTextbox) => { @@ -511,15 +508,15 @@ export default defineComponent({ this.editor.dispatcher.subscribeJsMessage(TriggerViewportResize, this.viewportResize); this.editor.dispatcher.subscribeJsMessage(UpdateImageData, (updateImageData) => { - updateImageData.image_data.forEach((element) => { + updateImageData.image_data.forEach(async (element) => { // Using updateImageData.image_data.buffer returns undefined for some reason? const blob = new Blob([new Uint8Array(element.image_data.values()).buffer], { type: element.mime }); const url = URL.createObjectURL(blob); - createImageBitmap(blob).then((image) => { - this.editor.instance.set_image_blob_url(element.path, url, image.width, image.height); - }); + const image = await createImageBitmap(blob); + + this.editor.instance.set_image_blob_url(element.path, url, image.width, image.height); }); }); diff --git a/frontend/src/components/panels/LayerTree.vue b/frontend/src/components/panels/LayerTree.vue index 21cbbf4571..984e663390 100644 --- a/frontend/src/components/panels/LayerTree.vue +++ b/frontend/src/components/panels/LayerTree.vue @@ -42,11 +42,11 @@ class="layer-row" v-for="(listing, index) in layers" :key="String(listing.entry.path.slice(-1))" - :class="{ 'insert-folder': draggingData && draggingData.highlightFolder && draggingData.insertFolder === listing.entry.path }" + :class="{ 'insert-folder': draggingData?.highlightFolder && draggingData?.insertFolder === listing.entry.path }" > { (tree.querySelector("[data-text-input]:not([disabled])") as HTMLInputElement).select(); }); }, - async onEditLayerNameChange(listing: LayerListingInfo, inputElement: EventTarget | null) { + onEditLayerNameChange(listing: LayerListingInfo, inputElement: EventTarget | null) { // Eliminate duplicate events if (!listing.editingName) return; @@ -434,8 +434,7 @@ export default defineComponent({ listing.editingName = false; this.$nextTick(() => { - const selection = window.getSelection(); - if (selection) selection.removeAllRanges(); + window.getSelection()?.removeAllRanges(); }); }, async setLayerBlendMode(newSelectedIndex: number) { @@ -536,7 +535,7 @@ export default defineComponent({ // Stop the drag from being shown as cancelled event.preventDefault(); - const tree = (this.$refs.layerTreeList as typeof LayoutCol).$el as HTMLElement; + const tree: HTMLElement = (this.$refs.layerTreeList as typeof LayoutCol).$el; this.draggingData = this.calculateDragIndex(tree, event.clientY); }, async drop() { @@ -594,8 +593,8 @@ export default defineComponent({ mounted() { this.editor.dispatcher.subscribeJsMessage(DisplayDocumentLayerTreeStructure, (displayDocumentLayerTreeStructure) => { const layerWithNameBeingEdited = this.layers.find((layer: LayerListingInfo) => layer.editingName); - const layerPathWithNameBeingEdited = layerWithNameBeingEdited && layerWithNameBeingEdited.entry.path; - const layerIdWithNameBeingEdited = layerPathWithNameBeingEdited && layerPathWithNameBeingEdited.slice(-1)[0]; + const layerPathWithNameBeingEdited = layerWithNameBeingEdited?.entry.path; + const layerIdWithNameBeingEdited = layerPathWithNameBeingEdited?.slice(-1)[0]; const path = [] as bigint[]; this.layers = [] as LayerListingInfo[]; @@ -606,9 +605,18 @@ export default defineComponent({ path.push(layerId); const mapping = cache.get(path.toString()); - if (mapping) layers.push({ folderIndex: index, bottomLayer: index === folder.children.length - 1, entry: mapping, editingName: layerIdWithNameBeingEdited === layerId }); + if (mapping) { + layers.push({ + folderIndex: index, + bottomLayer: index === folder.children.length - 1, + entry: mapping, + editingName: layerIdWithNameBeingEdited === layerId, + }); + } + // Call self recursively if there are any children if (item.children.length >= 1) recurse(item, layers, cache); + path.pop(); }); }; @@ -626,6 +634,7 @@ export default defineComponent({ } else { this.layerCache.set(targetPath.toString(), targetLayer); } + this.setBlendModeForSelectedLayers(); this.setOpacityForSelectedLayers(); }); diff --git a/frontend/src/components/widgets/WidgetRow.vue b/frontend/src/components/widgets/WidgetRow.vue index 937b422055..3ea9445c02 100644 --- a/frontend/src/components/widgets/WidgetRow.vue +++ b/frontend/src/components/widgets/WidgetRow.vue @@ -1,5 +1,4 @@