mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-10 01:50:08 +00:00
## Summary Extracts desktop UI into apps/desktop-ui package with minimal changes. ## Changes - **What**: - Separates desktop-specific code into standalone package with independent Vite config, router, and i18n - Drastically simplifies the main app router by removing all desktop routes - Adds a some code duplication, most due to the existing design - Some duplication can be refactored to be *simpler* on either side - no need to split things by `isElectron()` - Rudimentary storybook support has been added - **Breaking**: Stacked PR for publishing must be merged before this PR makes it to stable core (but publishing _could_ be done manually) - #5915 - **Dependencies**: Takes full advantage of pnpm catalog. No additional dependencies added. ## Review Focus - Should be no changes to normal frontend operation - Scripts added to root package.json are acceptable - The duplication in this PR is copied as is, wherever possible. Any corrections or fix-ups beyond the scope of simply migrating the functionality as-is, can be addressed in later PRs. That said, if any changes are made, it instantly becomes more difficult to separate the duplicated code out into a shared utility. - Tracking issue to address concerns: #5925 ### i18n Fixing i18n is out of scope for this PR. It is a larger task that we should consider carefully and implement properly. Attempting to isolate the desktop i18n and duplicate the _current_ localisation scripts would be wasted energy.
106 lines
2.6 KiB
TypeScript
106 lines
2.6 KiB
TypeScript
import { FitAddon } from '@xterm/addon-fit'
|
|
import { Terminal } from '@xterm/xterm'
|
|
import '@xterm/xterm/css/xterm.css'
|
|
import { debounce } from 'es-toolkit/compat'
|
|
import type { Ref } from 'vue'
|
|
import { markRaw, onMounted, onUnmounted } from 'vue'
|
|
|
|
export function useTerminal(element: Ref<HTMLElement | undefined>) {
|
|
const fitAddon = new FitAddon()
|
|
const terminal = markRaw(
|
|
new Terminal({
|
|
convertEol: true,
|
|
theme: { background: '#171717' }
|
|
})
|
|
)
|
|
terminal.loadAddon(fitAddon)
|
|
|
|
terminal.attachCustomKeyEventHandler((event) => {
|
|
// Allow default browser copy/paste handling
|
|
if (
|
|
event.type === 'keydown' &&
|
|
(event.ctrlKey || event.metaKey) &&
|
|
((event.key === 'c' && terminal.hasSelection()) || event.key === 'v')
|
|
) {
|
|
// TODO: Deselect text after copy/paste; use IPC.
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
|
|
onMounted(async () => {
|
|
if (element.value) {
|
|
terminal.open(element.value)
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
terminal.dispose()
|
|
})
|
|
|
|
return {
|
|
terminal,
|
|
useAutoSize({
|
|
root,
|
|
autoRows = true,
|
|
autoCols = true,
|
|
minCols = Number.NEGATIVE_INFINITY,
|
|
minRows = Number.NEGATIVE_INFINITY,
|
|
onResize
|
|
}: {
|
|
root: Ref<HTMLElement | undefined>
|
|
autoRows?: boolean
|
|
autoCols?: boolean
|
|
minCols?: number
|
|
minRows?: number
|
|
onResize?: () => void
|
|
}) {
|
|
const ensureValidRows = (rows: number | undefined): number => {
|
|
if (rows == null || isNaN(rows)) {
|
|
return (root.value?.clientHeight ?? 80) / 20
|
|
}
|
|
return rows
|
|
}
|
|
|
|
const ensureValidCols = (cols: number | undefined): number => {
|
|
if (cols == null || isNaN(cols)) {
|
|
// Sometimes this is NaN if so, estimate.
|
|
return (root.value?.clientWidth ?? 80) / 8
|
|
}
|
|
return cols
|
|
}
|
|
|
|
const resize = () => {
|
|
const dims = fitAddon.proposeDimensions()
|
|
// Sometimes propose returns NaN, so we may need to estimate.
|
|
terminal.resize(
|
|
Math.max(
|
|
autoCols ? ensureValidCols(dims?.cols) : terminal.cols,
|
|
minCols
|
|
),
|
|
Math.max(
|
|
autoRows ? ensureValidRows(dims?.rows) : terminal.rows,
|
|
minRows
|
|
)
|
|
)
|
|
onResize?.()
|
|
}
|
|
|
|
const resizeObserver = new ResizeObserver(debounce(resize, 25))
|
|
|
|
onMounted(async () => {
|
|
if (root.value) {
|
|
resizeObserver.observe(root.value)
|
|
resize()
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
resizeObserver.disconnect()
|
|
})
|
|
|
|
return { resize }
|
|
}
|
|
}
|
|
}
|