From 986ca6e252ca3a3d00a7d2df56c57141bf952bc3 Mon Sep 17 00:00:00 2001 From: Abdo Date: Sun, 27 Jul 2025 18:24:09 +0300 Subject: [PATCH] Hide IO toast on note change --- ts/routes/image-occlusion/MaskEditor.svelte | 5 ++++ ts/routes/image-occlusion/Toast.svelte | 6 ++-- .../add-or-update-note.svelte.ts | 20 ++----------- ts/routes/image-occlusion/mask-editor.ts | 12 ++------ .../image-occlusion/toast-utils.svelte.ts | 30 +++++++++++++++++++ ts/routes/image-occlusion/types.ts | 6 ++++ 6 files changed, 49 insertions(+), 30 deletions(-) create mode 100644 ts/routes/image-occlusion/toast-utils.svelte.ts diff --git a/ts/routes/image-occlusion/MaskEditor.svelte b/ts/routes/image-occlusion/MaskEditor.svelte index e90239755..0a3c766ca 100644 --- a/ts/routes/image-occlusion/MaskEditor.svelte +++ b/ts/routes/image-occlusion/MaskEditor.svelte @@ -17,12 +17,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { MaskEditorAPI } from "./tools/api"; import { onResize } from "./tools/tool-zoom"; import { saveNeededStore } from "./store"; + import { destroyToast, initToast } from "./toast-utils.svelte"; + import type Toast from "./Toast.svelte"; export let mode: IOMode; const iconSize = 80; let innerWidth = 0; const startingTool = mode.kind === "add" ? "draw-rectangle" : "cursor"; let canvas: fabric.Canvas | null = null; + let toast: Toast | null = null; $: { globalThis.maskEditor = canvas ? new MaskEditorAPI(canvas) : null; @@ -67,11 +70,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html onMount(() => { window.addEventListener("resize", resizeEvent); + toast = initToast(); }); onDestroy(() => { window.removeEventListener("resize", resizeEvent); unsubscribe(); + destroyToast(toast); }); const resizeEvent = () => { diff --git a/ts/routes/image-occlusion/Toast.svelte b/ts/routes/image-occlusion/Toast.svelte index 17a26f558..a18d60928 100644 --- a/ts/routes/image-occlusion/Toast.svelte +++ b/ts/routes/image-occlusion/Toast.svelte @@ -6,10 +6,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import Icon from "$lib/components/Icon.svelte"; import IconButton from "$lib/components/IconButton.svelte"; import { mdiClose } from "$lib/components/icons"; + import type { ToastProps } from "./types"; + + let { showToast, type, message }: ToastProps = $props(); - export let type: "success" | "error" = "success"; - export let message; - export let showToast = false; const closeToast = () => { showToast = false; }; diff --git a/ts/routes/image-occlusion/add-or-update-note.svelte.ts b/ts/routes/image-occlusion/add-or-update-note.svelte.ts index 98955f7a5..bbf57204c 100644 --- a/ts/routes/image-occlusion/add-or-update-note.svelte.ts +++ b/ts/routes/image-occlusion/add-or-update-note.svelte.ts @@ -6,11 +6,10 @@ import { addImageOcclusionNote, updateImageOcclusionNote } from "@generated/back import * as tr from "@generated/ftl"; import { get } from "svelte/store"; -import { mount } from "svelte"; import type { IOAddingMode, IOMode } from "./lib"; import { exportShapesToClozeDeletions } from "./shapes/to-cloze"; import { notesDataStore, tagsWritable } from "./store"; -import Toast from "./Toast.svelte"; +import { showToast } from "./toast-utils.svelte"; export const addOrUpdateNote = async function( mode: IOMode, @@ -54,24 +53,11 @@ export const addOrUpdateNote = async function( // show toast message const showResult = (noteId: bigint | null, result: OpChanges, count: number) => { - const props = $state({ - message: "", - type: "error" as "error" | "success", - showToast: true, - }); - mount(Toast, { - target: document.body, - props, - }); - if (result.note) { const msg = noteId ? tr.browsingCardsUpdated({ count: count }) : tr.importingCardsAdded({ count: count }); - props.message = msg; - props.type = "success"; - props.showToast = true; + showToast(msg, "success"); } else { const msg = tr.notetypesErrorGeneratingCloze(); - props.message = msg; - props.showToast = true; + showToast(msg, "error"); } }; diff --git a/ts/routes/image-occlusion/mask-editor.ts b/ts/routes/image-occlusion/mask-editor.ts index d3ed6acf8..4f0282fa6 100644 --- a/ts/routes/image-occlusion/mask-editor.ts +++ b/ts/routes/image-occlusion/mask-editor.ts @@ -7,10 +7,9 @@ import * as tr from "@generated/ftl"; import { fabric } from "fabric"; import { get } from "svelte/store"; -import { mount } from "svelte"; import { optimumCssSizeForCanvas } from "./canvas-scale"; import { hideAllGuessOne, notesDataStore, saveNeededStore, tagsWritable, textEditingState } from "./store"; -import Toast from "./Toast.svelte"; +import { showToast } from "./toast-utils.svelte"; import { addShapesToCanvasFromCloze } from "./tools/add-from-cloze"; import { enableSelectable, makeShapesRemainInCanvas, moveShapeToCanvasBoundaries } from "./tools/lib"; import { modifiedPolygon } from "./tools/tool-polygon"; @@ -51,14 +50,7 @@ export const setupMaskEditorForEdit = async ( const clozeNoteResponse = await getImageOcclusionNote({ noteId: BigInt(noteId) }); const kind = clozeNoteResponse.value?.case; if (!kind || kind === "error") { - mount(Toast, { - target: document.body, - props: { - message: tr.notetypesErrorGettingImagecloze(), - type: "error", - showToast: true, - }, - }); + showToast(tr.notetypesErrorGettingImagecloze(), "error"); throw "error getting cloze"; } diff --git a/ts/routes/image-occlusion/toast-utils.svelte.ts b/ts/routes/image-occlusion/toast-utils.svelte.ts new file mode 100644 index 000000000..d308c1b4a --- /dev/null +++ b/ts/routes/image-occlusion/toast-utils.svelte.ts @@ -0,0 +1,30 @@ +import { mount, unmount } from "svelte"; +import Toast from "./Toast.svelte"; +import type { ToastProps } from "./types"; + +const toastProps: ToastProps = $state({ + showToast: false, + type: "success", + message: "", +}); + +export function initToast(): Toast { + return mount(Toast, { + target: document.body, + props: toastProps, + }); +} + +export function destroyToast(toast: Toast) { + unmount(toast); +} + +export function showToast(message: string, type: "success" | "error") { + toastProps.message = message; + toastProps.type = type; + toastProps.showToast = true; +} + +export function hideToast() { + toastProps.showToast = false; +} diff --git a/ts/routes/image-occlusion/types.ts b/ts/routes/image-occlusion/types.ts index 2ade47768..81ee57b4b 100644 --- a/ts/routes/image-occlusion/types.ts +++ b/ts/routes/image-occlusion/types.ts @@ -9,3 +9,9 @@ export interface Size { export type ConstructorParams = { [P in keyof T]?: T[P]; }; + +export interface ToastProps { + message: string; + type: "success" | "error"; + showToast: boolean; +}