From 234c2809598f7aa2046099376ea71237f9c131c6 Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Fri, 28 Apr 2023 16:50:16 -0700 Subject: [PATCH] Queuing from mobile UI --- src/AppMobile.svelte | 17 +- src/lib/components/ComfyApp.ts | 10 +- src/lib/components/ComfyPane.svelte | 26 +- src/lib/utils.ts | 28 ++ src/main-mobile.ts | 17 - src/mobile/routes/graph.svelte | 7 +- src/mobile/routes/home.svelte | 29 +- src/mobile/routes/list-subworkflows.svelte | 29 ++ src/mobile/routes/subworkflow.svelte | 80 +++++ src/scss/global.scss | 2 +- src/scss/gradio.scss | 365 +++++++++++++++++++++ 11 files changed, 553 insertions(+), 57 deletions(-) create mode 100644 src/mobile/routes/list-subworkflows.svelte create mode 100644 src/mobile/routes/subworkflow.svelte create mode 100644 src/scss/gradio.scss diff --git a/src/AppMobile.svelte b/src/AppMobile.svelte index b7782ae..9bf41d5 100644 --- a/src/AppMobile.svelte +++ b/src/AppMobile.svelte @@ -18,11 +18,14 @@ import { f7, f7ready } from 'framework7-svelte'; import "framework7/css/bundle" + import "./scss/global.scss"; import HomePage from './mobile/routes/home.svelte'; import AboutPage from './mobile/routes/about.svelte'; import LoginPage from './mobile/routes/login.svelte'; import GraphPage from './mobile/routes/graph.svelte'; + import ListSubWorkflowsPage from './mobile/routes/list-subworkflows.svelte'; + import SubWorkflowPage from './mobile/routes/subworkflow.svelte'; function onBackKeyDown(e) { if(f7.view.current.router.currentRoute.path == '/'){ @@ -63,6 +66,14 @@ path: '/graph/', component: GraphPage, }, + { + path: '/subworkflows/', + component: ListSubWorkflowsPage, + }, + { + path: '/subworkflows/:subworkflowID/', + component: SubWorkflowPage, + }, ], popup: { closeOnEscape: true, @@ -79,6 +90,7 @@ } +{#if app} - - +{/if} diff --git a/src/lib/components/ComfyApp.ts b/src/lib/components/ComfyApp.ts index 8d27968..e57e3f8 100644 --- a/src/lib/components/ComfyApp.ts +++ b/src/lib/components/ComfyApp.ts @@ -77,6 +77,14 @@ export default class ComfyApp { shiftDown: boolean = false; selectedGroupMoving: boolean = false; + private static _instance: ComfyApp; + + static get instance(): ComfyApp { + if (!ComfyApp._instance) + ComfyApp._instance = new ComfyApp() + return ComfyApp._instance + } + private queueItems: QueueItem[] = []; private processingQueue: boolean = false; @@ -125,7 +133,7 @@ export default class ComfyApp { } // Save current workflow automatically - setInterval(this.requestAutosave.bind(this), 1000); + setInterval(this.requestAutosave.bind(this), 15000); this.addApiUpdateHandlers(); this.addDropHandler(); diff --git a/src/lib/components/ComfyPane.svelte b/src/lib/components/ComfyPane.svelte index 55d842a..34b229d 100644 --- a/src/lib/components/ComfyPane.svelte +++ b/src/lib/components/ComfyPane.svelte @@ -3,9 +3,6 @@ import { get } from "svelte/store" import { Block, BlockTitle } from "@gradio/atoms"; import { Move } from 'radix-icons-svelte'; - import ComboWidget from "$lib/widgets/ComboWidget.svelte"; - import RangeWidget from "$lib/widgets/RangeWidget.svelte"; - import TextWidget from "$lib/widgets/TextWidget.svelte"; import widgetState, { type WidgetDrawState, type WidgetUIState } from "$lib/stores/widgetState"; import queueState from "$lib/stores/queueState"; import nodeState from "$lib/stores/nodeState"; @@ -20,6 +17,7 @@ import ComfyApp from "./ComfyApp"; import type { LGraphNode } from "@litegraph-ts/core"; import type { DragItem } from "./ComfyUIPane"; + import { getComponentForWidgetState } from "$lib/utils" export let dragItems: DragItem[] = []; let dragDisabled = true; @@ -62,28 +60,6 @@ dragItems = dragItems; } - function getComponentForWidgetState(item: WidgetUIState): any { - let ctor: any = null; - - // custom widgets with TypeScript sources - let override = ComfyApp.widget_type_overrides[item.widget.type] - if (override) { - return override; - } - - // litegraph.ts built-in widgets - switch (item.widget.type) { - case "combo": - return ComboWidget; - case "number": - return RangeWidget; - case "text": - return TextWidget; - } - - return null; - } - function updateNodeName(node: LGraphNode, value: string) { nodeState.nodeStateChanged(node); } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 35c72e4..6f24cad 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,3 +1,9 @@ +import ComfyApp from "./components/ComfyApp"; +import ComboWidget from "$lib/widgets/ComboWidget.svelte"; +import RangeWidget from "$lib/widgets/RangeWidget.svelte"; +import TextWidget from "$lib/widgets/TextWidget.svelte"; + import widgetState, { type WidgetDrawState, type WidgetUIState } from "$lib/stores/widgetState"; + export function download(filename: string, text: string, type: string = "text/plain") { const blob = new Blob([text], { type: type }); const url = URL.createObjectURL(blob); @@ -11,3 +17,25 @@ export function download(filename: string, text: string, type: string = "text/pl window.URL.revokeObjectURL(url); }, 0); } + +export function getComponentForWidgetState(item: WidgetUIState): any { + let ctor: any = null; + + // custom widgets with TypeScript sources + let override = ComfyApp.widget_type_overrides[item.widget.type] + if (override) { + return override; + } + + // litegraph.ts built-in widgets + switch (item.widget.type) { + case "combo": + return ComboWidget; + case "number": + return RangeWidget; + case "text": + return TextWidget; + } + + return null; +} diff --git a/src/main-mobile.ts b/src/main-mobile.ts index e27966e..4ba38cd 100644 --- a/src/main-mobile.ts +++ b/src/main-mobile.ts @@ -10,21 +10,4 @@ const app = new AppMobile({ target: document.getElementById('app'), }) -function onBackKeyDown(e: Event) { - console.log(f7.view.current.router.currentRoute.name) - e.preventDefault(); - // Handle the back button - if(f7.view.current.router.currentRoute.name == 'index'){ - // exitApp(); - e.preventDefault(); - } else { - f7.dialog.close() - f7.view.main.router.back() - return false; - } -} - -document.addEventListener("backbutton", onBackKeyDown, false); -document.addEventListener("popstate", onBackKeyDown, false); - export default app; diff --git a/src/mobile/routes/graph.svelte b/src/mobile/routes/graph.svelte index 2fbe4d0..3ed641f 100644 --- a/src/mobile/routes/graph.svelte +++ b/src/mobile/routes/graph.svelte @@ -1,11 +1,11 @@ @@ -77,14 +91,15 @@ - + - - - - + + + diff --git a/src/mobile/routes/list-subworkflows.svelte b/src/mobile/routes/list-subworkflows.svelte new file mode 100644 index 0000000..98f6706 --- /dev/null +++ b/src/mobile/routes/list-subworkflows.svelte @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/src/mobile/routes/subworkflow.svelte b/src/mobile/routes/subworkflow.svelte new file mode 100644 index 0000000..94b17b9 --- /dev/null +++ b/src/mobile/routes/subworkflow.svelte @@ -0,0 +1,80 @@ + + + + + + Queue Prompt + + + {#each Object.entries($widgetState) as [id, ws]} + {@const node = app.lGraph.getNodeById(id)} +
+ + + {#each $widgetState[id] as item} + + {/each} + {#if $uiState.unlocked} +
+ {/if} + +
+ {/each} + + + diff --git a/src/scss/global.scss b/src/scss/global.scss index 8b13789..150b1d6 100644 --- a/src/scss/global.scss +++ b/src/scss/global.scss @@ -1 +1 @@ - +@import "gradio" diff --git a/src/scss/gradio.scss b/src/scss/gradio.scss new file mode 100644 index 0000000..21d6a27 --- /dev/null +++ b/src/scss/gradio.scss @@ -0,0 +1,365 @@ +:root { + --primary-50: #fff7ed; + --primary-100: #ffedd5; + --primary-200: #fed7aa; + --primary-300: #fdba74; + --primary-400: #fb923c; + --primary-500: #f97316; + --primary-600: #ea580c; + --primary-700: #c2410c; + --primary-800: #9a3412; + --primary-900: #7c2d12; + --primary-950: #6c2e12; + --secondary-50: #eff6ff; + --secondary-100: #dbeafe; + --secondary-200: #bfdbfe; + --secondary-300: #93c5fd; + --secondary-400: #60a5fa; + --secondary-500: #3b82f6; + --secondary-600: #2563eb; + --secondary-700: #1d4ed8; + --secondary-800: #1e40af; + --secondary-900: #1e3a8a; + --secondary-950: #1d3660; + --neutral-50: #f9fafb; + --neutral-100: #f3f4f6; + --neutral-200: #e5e7eb; + --neutral-300: #d1d5db; + --neutral-400: #9ca3af; + --neutral-500: #6b7280; + --neutral-600: #4b5563; + --neutral-700: #374151; + --neutral-800: #1f2937; + --neutral-900: #111827; + --neutral-950: #0b0f19; + --spacing-xxs: 1px; + --spacing-xs: 2px; + --spacing-sm: 4px; + --spacing-md: 6px; + --spacing-lg: 8px; + --spacing-xl: 10px; + --spacing-xxl: 16px; + --radius-xxs: 1px; + --radius-xs: 2px; + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-xxl: 22px; + --text-xxs: 9px; + --text-xs: 10px; + --text-sm: 12px; + --text-md: 14px; + --text-lg: 16px; + --text-xl: 22px; + --text-xxl: 26px; + --color-accent: var(--primary-500); + --color-accent-soft: var(--primary-50); + --background-fill-primary: white; + --background-fill-secondary: var(--neutral-50); + --border-color-accent: var(--primary-300); + --border-color-primary: var(--neutral-200); + --text-color-code-background-fill: var(--neutral-200); + --text-color-code-border: var(--border-color-primary); + --link-text-color: var(--secondary-600); + --link-text-color-active: var(--secondary-600); + --link-text-color-hover: var(--secondary-700); + --link-text-color-visited: var(--secondary-500); + --body-text-color-subdued: var(--neutral-400); + --body-background-fill: var(--background-fill-primary); + --body-text-color: var(--neutral-800); + --body-text-size: var(--text-md); + --body-text-weight: 400; + --embed-radius: var(--radius-lg); + --shadow-drop: rgba(0, 0, 0, 0.05) 0px 1px 2px 0px; + --shadow-drop-lg: 0 1px 3px 0 rgb(0 0 0 / 0.1), + 0 1px 2px -1px rgb(0 0 0 / 0.1); + --shadow-inset: rgba(0, 0, 0, 0.05) 0px 2px 4px 0px inset; + --shadow-spread: 3px; + --block-background-fill: var(--background-fill-primary); + --block-border-color: var(--border-color-primary); + --block-border-width: 1px; + --block-info-text-color: var(--body-text-color-subdued); + --block-info-text-size: var(--text-sm); + --block-info-text-weight: 400; + --block-label-background-fill: var(--background-fill-primary); + --block-label-border-color: var(--border-color-primary); + --block-label-border-width: 1px; + --block-label-text-color: var(--neutral-500); + --block-label-icon-color: var(--block-label-text-color); + --block-label-margin: 0; + --block-label-padding: var(--spacing-sm) var(--spacing-lg); + --block-label-radius: calc(var(--radius-lg) - 1px) 0 + calc(var(--radius-lg) - 1px) 0; + --block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0 + calc(var(--radius-lg) - 1px); + --block-label-text-size: var(--text-sm); + --block-label-text-weight: 400; + --block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px); + --block-radius: var(--radius-lg); + --block-shadow: var(--shadow-drop); + --block-title-background-fill: none; + --block-title-border-color: none; + --block-title-border-width: 0px; + --block-title-text-color: var(--neutral-500); + --block-title-padding: 0; + --block-title-radius: none; + --block-title-text-size: var(--text-md); + --block-title-text-weight: 400; + --container-radius: var(--radius-lg); + --form-gap-width: 1px; + --layout-gap: var(--spacing-xxl); + --panel-background-fill: var(--background-fill-secondary); + --panel-border-color: var(--border-color-primary); + --panel-border-width: 0; + --section-header-text-size: var(--text-md); + --section-header-text-weight: 400; + --checkbox-background-color: var(--background-fill-primary); + --checkbox-background-color-focus: var(--background-fill-primary); + --checkbox-background-color-hover: var(--background-fill-primary); + --checkbox-background-color-selected: var(--secondary-600); + --checkbox-border-color: var(--neutral-300); + --checkbox-border-color-focus: var(--secondary-500); + --checkbox-border-color-hover: var(--neutral-300); + --checkbox-border-color-selected: var(--secondary-600); + --checkbox-border-radius: var(--radius-sm); + --checkbox-border-width: var(--input-border-width); + --checkbox-label-background-fill: linear-gradient( + to top, + var(--neutral-50), + white + ); + --checkbox-label-background-fill-hover: linear-gradient( + to top, + var(--neutral-100), + white + ); + --checkbox-label-background-fill-selected: var( + --checkbox-label-background-fill + ); + --checkbox-label-border-color: var(--border-color-primary); + --checkbox-label-border-color-hover: var(--border-color-primary); + --checkbox-label-border-width: var(--input-border-width); + --checkbox-label-gap: var(--spacing-lg); + --checkbox-label-padding: var(--spacing-md) calc(2 * var(--spacing-md)); + --checkbox-label-shadow: var(--shadow-drop); + --checkbox-label-text-size: var(--text-md); + --checkbox-label-text-weight: 400; + --checkbox-shadow: var(--input-shadow); + --checkbox-label-text-color: var(--body-text-color); + --checkbox-label-text-color-selected: var(--checkbox-label-text-color); + --error-background-fill: linear-gradient( + to right, + #fee2e2, + var(--background-fill-secondary) + ); + --error-border-color: #fecaca; + --error-border-width: 1px; + --error-text-color: #ef4444; + --prose-header-text-weight: 600; + --input-background-fill: white; + --input-background-fill-focus: var(--secondary-500); + --input-background-fill-hover: var(--input-background-fill); + --input-border-color: var(--border-color-primary); + --input-border-color-focus: var(--secondary-300); + --input-border-color-hover: var(--border-color-primary); + --input-border-width: 1px; + --input-padding: var(--spacing-xl); + --input-placeholder-color: var(--neutral-400); + --input-radius: var(--radius-lg); + --input-shadow: 0 0 0 var(--shadow-spread) transparent, var(--shadow-inset); + --input-shadow-focus: 0 0 0 var(--shadow-spread) var(--secondary-50), + var(--shadow-inset); + --input-text-size: var(--text-md); + --input-text-weight: 400; + --loader-color: var(--color-accent); + --prose-text-size: var(--text-md); + --prose-text-weight: 400; + --stat-background-fill: linear-gradient( + to right, + var(--primary-400), + var(--primary-200) + ); + --table-border-color: var(--neutral-300); + --table-even-background-fill: white; + --table-odd-background-fill: var(--neutral-50); + --table-radius: var(--radius-lg); + --table-row-focus: var(--color-accent-soft); + --button-border-width: var(--input-border-width); + --button-cancel-background-fill: linear-gradient( + to bottom right, + #fee2e2, + #fecaca + ); + --button-cancel-background-fill-hover: linear-gradient( + to bottom right, + #fee2e2, + #fee2e2 + ); + --button-cancel-border-color: #fecaca; + --button-cancel-border-color-hover: var(--button-cancel-border-color); + --button-cancel-text-color: #dc2626; + --button-cancel-text-color-hover: var(--button-cancel-text-color); + --button-large-padding: var(--spacing-lg) calc(2 * var(--spacing-lg)); + --button-large-radius: var(--radius-lg); + --button-large-text-size: var(--text-lg); + --button-large-text-weight: 600; + --button-primary-background-fill: linear-gradient( + to bottom right, + var(--primary-100), + var(--primary-300) + ); + --button-primary-background-fill-hover: linear-gradient( + to bottom right, + var(--primary-100), + var(--primary-200) + ); + --button-primary-border-color: var(--primary-200); + --button-primary-border-color-hover: var(--button-primary-border-color); + --button-primary-text-color: var(--primary-600); + --button-primary-text-color-hover: var(--button-primary-text-color); + --button-secondary-background-fill: linear-gradient( + to bottom right, + var(--neutral-100), + var(--neutral-200) + ); + --button-secondary-background-fill-hover: linear-gradient( + to bottom right, + var(--neutral-100), + var(--neutral-100) + ); + --button-secondary-border-color: var(--neutral-200); + --button-secondary-border-color-hover: var(--button-secondary-border-color); + --button-secondary-text-color: var(--neutral-700); + --button-secondary-text-color-hover: var(--button-secondary-text-color); + --button-shadow: var(--shadow-drop); + --button-shadow-active: var(--shadow-inset); + --button-shadow-hover: var(--shadow-drop-lg); + --button-small-padding: var(--spacing-sm) calc(2 * var(--spacing-sm)); + --button-small-radius: var(--radius-lg); + --button-small-text-size: var(--text-md); + --button-small-text-weight: 400; + --button-transition: none; +} +.dark { + --color-accent-soft: var(--neutral-900); + --background-fill-primary: var(--neutral-950); + --background-fill-secondary: var(--neutral-900); + --border-color-accent: var(--neutral-600); + --border-color-primary: var(--neutral-700); + --text-color-code-background-fill: var(--neutral-800); + --link-text-color-active: var(--secondary-500); + --link-text-color: var(--secondary-500); + --link-text-color-hover: var(--secondary-400); + --link-text-color-visited: var(--secondary-600); + --body-text-color-subdued: var(--neutral-400); + --body-background-fill: var(--background-fill-primary); + --body-text-color: var(--neutral-100); + --shadow-spread: 1px; + --block-background-fill: var(--neutral-800); + --block-border-color: var(--border-color-primary); + --block-border-width: 1px; + --block-info-text-color: var(--body-text-color-subdued); + --block-label-background-fill: var(--background-fill-secondary); + --block-label-border-color: var(--border-color-primary); + --block-label-border-width: 1px; + --block-label-text-color: var(--neutral-200); + --block-shadow: none; + --block-title-background-fill: none; + --block-title-border-color: none; + --block-title-border-width: 0px; + --block-title-text-color: var(--neutral-200); + --panel-background-fill: var(--background-fill-secondary); + --panel-border-color: var(--border-color-primary); + --checkbox-background-color: var(--neutral-800); + --checkbox-background-color-focus: var(--checkbox-background-color); + --checkbox-background-color-hover: var(--checkbox-background-color); + --checkbox-background-color-selected: var(--secondary-600); + --checkbox-border-color: var(--neutral-700); + --checkbox-border-color-focus: var(--secondary-500); + --checkbox-border-color-hover: var(--neutral-600); + --checkbox-border-color-selected: var(--secondary-600); + --checkbox-label-background-fill: linear-gradient( + to top, + var(--neutral-900), + var(--neutral-800) + ); + --checkbox-label-background-fill-hover: linear-gradient( + to top, + var(--neutral-900), + var(--neutral-800) + ); + --checkbox-label-background-fill-selected: var( + --checkbox-label-background-fill + ); + --checkbox-label-border-color: var(--border-color-primary); + --checkbox-label-border-color-hover: var(--border-color-primary); + --checkbox-label-text-color: var(--body-text-color); + --checkbox-label-text-color-selected: var(--checkbox-label-text-color); + --error-background-fill: var(--background-fill-primary); + --error-border-color: var(--border-color-primary); + --error-border-width: var(--error-border-width); + --error-text-color: #ef4444; + --input-background-fill: var(--neutral-800); + --input-background-fill-focus: var(--secondary-600); + --input-background-fill-hover: var(--input-background-fill); + --input-border-color: var(--border-color-primary); + --input-border-color-focus: var(--neutral-700); + --input-border-color-hover: var(--border-color-primary); + --input-placeholder-color: var(--neutral-500); + --input-shadow: var(--input-shadow); + --input-shadow-focus: 0 0 0 var(--shadow-spread) var(--neutral-700), + var(--shadow-inset); + --loader-color: var(--loader-color); + --stat-background-fill: linear-gradient( + to right, + var(--primary-400), + var(--primary-600) + ); + --table-border-color: var(--neutral-700); + --table-even-background-fill: var(--neutral-950); + --table-odd-background-fill: var(--neutral-900); + --table-row-focus: var(--color-accent-soft); + --button-cancel-background-fill: linear-gradient( + to bottom right, + #dc2626, + #b91c1c + ); + --button-cancel-background-fill-hover: linear-gradient( + to bottom right, + #dc2626, + #dc2626 + ); + --button-cancel-border-color: #dc2626; + --button-cancel-border-color-hover: var(--button-cancel-border-color); + --button-cancel-text-color: white; + --button-cancel-text-color-hover: var(--button-cancel-text-color); + --button-primary-background-fill: linear-gradient( + to bottom right, + var(--primary-600), + var(--primary-700) + ); + --button-primary-background-fill-hover: linear-gradient( + to bottom right, + var(--primary-600), + var(--primary-600) + ); + --button-primary-border-color: var(--primary-600); + --button-primary-border-color-hover: var(--button-primary-border-color); + --button-primary-text-color: white; + --button-primary-text-color-hover: var(--button-primary-text-color); + --button-secondary-background-fill: linear-gradient( + to bottom right, + var(--neutral-600), + var(--neutral-700) + ); + --button-secondary-background-fill-hover: linear-gradient( + to bottom right, + var(--neutral-600), + var(--neutral-600) + ); + --button-secondary-border-color: var(--neutral-600); + --button-secondary-border-color-hover: var(--button-secondary-border-color); + --button-secondary-text-color: white; + --button-secondary-text-color-hover: var(--button-secondary-text-color); +}