diff --git a/index.html b/index.html index 28202f3..b628d53 100644 --- a/index.html +++ b/index.html @@ -7,17 +7,6 @@ -
diff --git a/src/App.svelte b/src/App.svelte index 11b98f9..8aed45d 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -4,12 +4,12 @@ import "@litegraph-ts/core/css/litegraph.css"; import "./scss/global.scss"; - import { onMount } from 'svelte'; - export let app: ComfyAppState; + export let isMobile: boolean - - - +{#if isMobile} +
Redirecting...
+{:else} + +{/if} diff --git a/src/lib/ComfyGraphCanvas.ts b/src/lib/ComfyGraphCanvas.ts index ae686bb..220d85e 100644 --- a/src/lib/ComfyGraphCanvas.ts +++ b/src/lib/ComfyGraphCanvas.ts @@ -333,7 +333,8 @@ export default class ComfyGraphCanvas extends LGraphCanvas { /** * Handle keypress * - * Ctrl + M mute/unmute selected nodes + * Ctrl + M mute/unmute selected nodes + * Ctrl + Space open node searchbox */ override processKey(e: KeyboardEvent): boolean | undefined { const res = super.processKey(e); @@ -353,7 +354,7 @@ export default class ComfyGraphCanvas extends LGraphCanvas { } if (e.type == "keydown") { - // Ctrl + M mute/unmute + // Ctrl + M - mute/unmute if (e.keyCode == 77 && e.ctrlKey) { if (this.selected_nodes) { for (var i in this.selected_nodes) { @@ -366,6 +367,21 @@ export default class ComfyGraphCanvas extends LGraphCanvas { } block_default = true; } + // Ctrl + Space - open node searchbox + else if (e.keyCode == 32 && e.ctrlKey) { + const event = new MouseEvent("click"); + const searchBox = this.showSearchBox(event); + const rect = this.canvas.getBoundingClientRect(); + const sbRect = searchBox.getBoundingClientRect(); + const clientX = rect.left + rect.width / 2 - sbRect.width / 2; + const clientY = rect.top + rect.height / 2 - sbRect.height / 2 + searchBox.style.left = `${clientX}px`; + searchBox.style.top = `${clientY}px`; + // TODO better API + event.initMouseEvent("click", true, true, window, 1, clientX, clientY, clientX, clientY, false, false, false, false, 0, null); + this.adjustMouseEvent(event); + block_default = true; + } } this.graph.change(); diff --git a/src/lib/api.ts b/src/lib/api.ts index 7d7f47d..dc8765b 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -125,8 +125,17 @@ export default class ComfyAPI { }, 1000); } + private getHostname(): string { + let hostname = this.hostname || location.hostname; + if (hostname === "localhost") { + // For dev use, assume same hostname as connected server + hostname = location.hostname; + } + return hostname; + } + private getBackendUrl(): string { - const hostname = this.hostname || location.hostname; + const hostname = this.getHostname() const port = this.port || location.port; return `${window.location.protocol}//${hostname}:${port}` } @@ -146,7 +155,7 @@ export default class ComfyAPI { existingSession = "?clientId=" + existingSession; } - const hostname = this.hostname || location.hostname; + const hostname = this.getHostname() const port = this.port || location.port; this.socket = new WebSocket( diff --git a/src/lib/components/ComfyApp.ts b/src/lib/components/ComfyApp.ts index 6eb6d7f..73f840d 100644 --- a/src/lib/components/ComfyApp.ts +++ b/src/lib/components/ComfyApp.ts @@ -211,7 +211,13 @@ export default class ComfyApp { this.lCanvas.allow_interaction = uiUnlocked; // await this.#invokeExtensionsAsync("init"); - const defs = await this.api.getNodeDefs(); + let defs; + try { + defs = await this.api.getNodeDefs(); + } + catch (error) { + throw new Error(`Could not reach ComfyUI at ${this.api.getBackendUrl()}`); + } await this.registerNodes(defs); // Load previous workflow diff --git a/src/lib/stores/configState.ts b/src/lib/stores/configState.ts index e6fe1e9..75069b1 100644 --- a/src/lib/stores/configState.ts +++ b/src/lib/stores/configState.ts @@ -24,7 +24,12 @@ let changedOptions: Partial> = {} function getBackendURL(): string { const state = get(store); - return `${window.location.protocol}//${state.comfyUIHostname}:${state.comfyUIPort}` + let hostname = state.comfyUIHostname + if (hostname === "localhost") { + // For dev use, assume same hostname as connected server + hostname = location.hostname; + } + return `${window.location.protocol}//${hostname}:${state.comfyUIPort}` } function canShowNotificationText(): boolean { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index e340256..bb5ee75 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -618,6 +618,9 @@ export async function readFileToText(file: File): Promise { reader.onload = async () => { resolve(reader.result as string); }; + reader.onerror = async () => { + reject(reader.error); + } reader.readAsText(file); }) } @@ -709,3 +712,12 @@ export function canvasToBlob(canvas: HTMLCanvasElement): Promise { canvas.toBlob(resolve); }); } + +export type SafetensorsMetadata = Record + +export async function getSafetensorsMetadata(folder: string, filename: string): Promise { + const url = configState.getBackendURL(); + const params = new URLSearchParams({ filename }) + + return fetch(new Request(url + `/view_metadata/${folder}?` + params)).then(r => r.json()) +} diff --git a/src/lib/widgets/ComboWidget.svelte b/src/lib/widgets/ComboWidget.svelte index 63816c1..ef04d9a 100644 --- a/src/lib/widgets/ComboWidget.svelte +++ b/src/lib/widgets/ComboWidget.svelte @@ -8,6 +8,7 @@ import { type WidgetLayout } from "$lib/stores/layoutStates"; import { get, writable, type Writable } from "svelte/store"; import { isDisabled } from "./utils" + import { getSafetensorsMetadata } from '$lib/utils'; export let widget: WidgetLayout | null = null; export let isMobile: boolean = false; let node: ComfyComboNode | null = null; diff --git a/src/main-desktop.ts b/src/main-desktop.ts index f91c7f9..77e0916 100644 --- a/src/main-desktop.ts +++ b/src/main-desktop.ts @@ -1,3 +1,20 @@ +const params = new URLSearchParams(window.location.search) + +const MOBILE_USER_AGENTS = ["iPhone", "iPad", "Android", "BlackBerry", "WebOs"].map(a => new RegExp(a, "i")) + +function isMobileBrowser(userAgent: string): boolean { + return MOBILE_USER_AGENTS.some(a => userAgent.match(a)) +} + +const isMobile = isMobileBrowser(navigator.userAgent); + +if (params.get("desktop") !== "true") { + if (isMobile) { + window.location.href = "/mobile/" + } +} + + // Run node registration before anthing else, in the proper order import "$lib/nodeImports"; @@ -12,7 +29,7 @@ const comfyApp = new ComfyApp(); const app = new App({ target: document.getElementById("app-root"), - props: { app: comfyApp } + props: { app: comfyApp, isMobile } }) export default app; diff --git a/vite.config.ts b/vite.config.ts index 25f1aab..1373ffd 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -55,6 +55,7 @@ export default defineConfig({ }, }, build: { + minify: isProduction, sourcemap: true, rollupOptions: { input: {