[TS] Fix ts-strict errors in Vue components (Part 3) (#3126)

This commit is contained in:
Chenlei Hu
2025-03-18 11:38:43 -04:00
committed by GitHub
parent a85a1bf794
commit 96ff8a7785
18 changed files with 56 additions and 40 deletions

View File

@@ -2,8 +2,8 @@
<Splitter
class="splitter-overlay-root splitter-overlay"
:pt:gutter="sidebarPanelVisible ? '' : 'hidden'"
:key="activeSidebarTabId"
:stateKey="activeSidebarTabId"
:key="activeSidebarTabId ?? undefined"
:stateKey="activeSidebarTabId ?? undefined"
stateStorage="local"
>
<SplitterPanel

View File

@@ -99,7 +99,7 @@ const isValidSource = computed(
() => sourcePath.value !== '' && pathError.value === ''
)
const validateSource = async (sourcePath: string) => {
const validateSource = async (sourcePath: string | undefined) => {
if (!sourcePath) {
pathError.value = ''
return
@@ -109,7 +109,7 @@ const validateSource = async (sourcePath: string) => {
pathError.value = ''
const validation = await electron.validateComfyUISource(sourcePath)
if (!validation.isValid) pathError.value = validation.error
if (!validation.isValid) pathError.value = validation.error ?? 'ERROR'
} catch (error) {
console.error(error)
pathError.value = t('install.pathValidationFailed')

View File

@@ -74,8 +74,8 @@ const description = computed(() =>
)
// Use a minimum run time to ensure tasks "feel" like they have run
const reactiveLoading = computed(() => runner.value.refreshing)
const reactiveExecuting = computed(() => runner.value.executing)
const reactiveLoading = computed(() => !!runner.value.refreshing)
const reactiveExecuting = computed(() => !!runner.value.executing)
const isLoading = useMinLoadingDurationRef(reactiveLoading, 250)
const isExecuting = useMinLoadingDurationRef(reactiveExecuting, 250)

View File

@@ -71,16 +71,16 @@ const severity = computed<VueSeverity>(() =>
)
// Use a minimum run time to ensure tasks "feel" like they have run
const reactiveLoading = computed(() => runner.value.refreshing)
const reactiveExecuting = computed(() => runner.value.executing)
const reactiveLoading = computed(() => !!runner.value.refreshing)
const reactiveExecuting = computed(() => !!runner.value.executing)
const isLoading = useMinLoadingDurationRef(reactiveLoading, 250)
const isExecuting = useMinLoadingDurationRef(reactiveExecuting, 250)
// Popover
const infoPopover = ref()
const infoPopover = ref<InstanceType<typeof Popover> | null>(null)
const toggle = (event: Event) => {
infoPopover.value.toggle(event)
infoPopover.value?.toggle(event)
}
</script>

View File

@@ -35,7 +35,7 @@ let xterm: Terminal | null = null
// Created and destroyed with the Drawer - contents copied from hidden buffer
const terminalCreated = (
{ terminal, useAutoSize }: ReturnType<typeof useTerminal>,
root: Ref<HTMLElement>
root: Ref<HTMLElement | undefined>
) => {
xterm = terminal
useAutoSize({ root, autoRows: true, autoCols: true })

View File

@@ -26,7 +26,7 @@
class="node-lib-search-box p-2 2xl:p-4"
v-model:modelValue="searchQuery"
@search="handleSearch"
@show-filter="($event) => searchFilter.toggle($event)"
@show-filter="($event) => searchFilter?.toggle($event)"
@remove-filter="onRemoveFilter"
:placeholder="$t('g.searchNodes') + '...'"
filter-icon="pi pi-filter"
@@ -97,7 +97,7 @@ const { expandNode, toggleNodeOnEvent } = useTreeExpansion(expandedKeys)
const nodeBookmarkTreeExplorerRef = ref<InstanceType<
typeof NodeBookmarkTreeExplorer
> | null>(null)
const searchFilter = ref(null)
const searchFilter = ref<InstanceType<typeof Popover> | null>(null)
const alphabeticalSort = ref(false)
const searchQuery = ref<string>('')

View File

@@ -194,7 +194,7 @@ const confirmRemoveAll = (event: Event) => {
})
}
const menu = ref(null)
const menu = ref<InstanceType<typeof ContextMenu> | null>(null)
const menuTargetTask = ref<TaskItemImpl | null>(null)
const menuTargetNode = ref<ComfyNode | null>(null)
const menuItems = computed<MenuItem[]>(() => [
@@ -213,7 +213,11 @@ const menuItems = computed<MenuItem[]>(() => [
{
label: t('g.goToNode'),
icon: 'pi pi-arrow-circle-right',
command: () => useLitegraphService().goToNode(menuTargetNode.value?.id),
command: () => {
if (!menuTargetNode.value) return
useLitegraphService().goToNode(menuTargetNode.value.id)
},
visible: !!menuTargetNode.value
}
])
@@ -225,7 +229,7 @@ const handleContextMenu = ({
}: {
task: TaskItemImpl
event: Event
node?: ComfyNode
node: ComfyNode | null
}) => {
menuTargetTask.value = task
menuTargetNode.value = node

View File

@@ -1,9 +1,9 @@
<template>
<div class="flex flex-col">
<div>
{{ getDownloadLabel(download.savePath) }}
{{ getDownloadLabel(download.savePath ?? '') }}
</div>
<div v-if="['cancelled', 'error'].includes(download.status)">
<div v-if="['cancelled', 'error'].includes(download.status ?? '')">
<Chip
class="h-6 text-sm font-light bg-red-700 mt-2"
removable
@@ -14,15 +14,17 @@
</div>
<div
class="mt-2 flex flex-row items-center gap-2"
v-if="['in_progress', 'paused', 'completed'].includes(download.status)"
v-if="
['in_progress', 'paused', 'completed'].includes(download.status ?? '')
"
>
<!-- Temporary fix for issue when % only comes into view only if the progress bar is large enough
https://comfy-organization.slack.com/archives/C07H3GLKDPF/p1731551013385499
-->
<ProgressBar
class="flex-1"
:value="Number((download.progress * 100).toFixed(1))"
:show-value="download.progress > 0.1"
:value="Number(((download.progress ?? 0) * 100).toFixed(1))"
:show-value="(download.progress ?? 0) > 0.1"
/>
<Button
@@ -51,7 +53,7 @@
rounded
severity="danger"
@click="triggerCancelDownload"
v-if="['in_progress', 'paused'].includes(download.status)"
v-if="['in_progress', 'paused'].includes(download.status ?? '')"
icon="pi pi-times-circle"
v-tooltip.top="t('electronFileDownload.cancel')"
/>
@@ -79,7 +81,7 @@ const props = defineProps<{
}>()
const getDownloadLabel = (savePath: string) => {
let parts = (savePath ?? '').split('/')
let parts = savePath.split('/')
parts = parts.length === 1 ? parts[0].split('\\') : parts
const name = parts.pop()
const dir = parts.pop()

View File

@@ -97,6 +97,8 @@ const extraMenuItems = (
label: t('g.customize'),
icon: 'pi pi-palette',
command: () => {
if (!menuTargetNode.data) return
const customization =
nodeBookmarkStore.bookmarksCustomization[menuTargetNode.data.nodePath]
initialIcon.value =

View File

@@ -79,6 +79,8 @@ const nodePreviewStyle = ref<CSSProperties>({
const handleNodeHover = async () => {
const hoverTarget = nodeContentElement.value
if (!hoverTarget) return
const targetRect = hoverTarget.getBoundingClientRect()
const previewHeight = previewRef.value?.$el.offsetHeight || 0
@@ -107,7 +109,8 @@ const handleMouseLeave = () => {
isHovered.value = false
}
onMounted(() => {
nodeContentElement.value = container.value?.closest('.p-tree-node-content')
nodeContentElement.value =
container.value?.closest('.p-tree-node-content') ?? null
nodeContentElement.value?.addEventListener('mouseenter', handleMouseEnter)
nodeContentElement.value?.addEventListener('mouseleave', handleMouseLeave)
})

View File

@@ -8,7 +8,7 @@
"
>
<ResultItem
v-if="flatOutputs.length"
v-if="flatOutputs.length && coverResult"
:result="coverResult"
@preview="handlePreview"
/>
@@ -42,7 +42,12 @@
:label="`${node?.type} (#${node?.id})`"
link
size="small"
@click="litegraphService.goToNode(node?.id)"
@click="
() => {
if (!node) return
litegraphService.goToNode(node.id)
}
"
/>
</Tag>
<Tag :severity="taskTagSeverity(task.displayStatus)">
@@ -95,7 +100,7 @@ const coverResult = flatOutputs.length
const node: ComfyNode | null =
flatOutputs.length && props.task.workflow
? props.task.workflow.nodes.find(
(n: ComfyNode) => n.id == coverResult.nodeId
(n: ComfyNode) => n.id == coverResult?.nodeId
) ?? null
: null
const progressPreviewBlobUrl = ref('')
@@ -103,7 +108,7 @@ const progressPreviewBlobUrl = ref('')
const emit = defineEmits<{
(
e: 'contextmenu',
value: { task: TaskItemImpl; event: MouseEvent; node?: ComfyNode }
value: { task: TaskItemImpl; event: MouseEvent; node: ComfyNode | null }
): void
(e: 'preview', value: TaskItemImpl): void
(e: 'task-output-length-clicked', value: TaskItemImpl): void

View File

@@ -20,12 +20,12 @@ import TreeExplorerTreeNode from '@/components/common/TreeExplorerTreeNode.vue'
import { ComfyWorkflow, useWorkflowBookmarkStore } from '@/stores/workflowStore'
import type { RenderedTreeExplorerNode } from '@/types/treeExplorerTypes'
const props = defineProps<{
const { node } = defineProps<{
node: RenderedTreeExplorerNode<ComfyWorkflow>
}>()
const workflowBookmarkStore = useWorkflowBookmarkStore()
const isBookmarked = computed(() =>
workflowBookmarkStore.isBookmarked(props.node.data.path)
const isBookmarked = computed(
() => node.data && workflowBookmarkStore.isBookmarked(node.data.path)
)
</script>

View File

@@ -90,7 +90,7 @@ const { isReady } = useAsyncState(
null
)
const selectedTab = ref<WorkflowTemplates | null>()
const selectedTab = ref<WorkflowTemplates | null>(null)
const selectFirstTab = () => {
const firstTab = workflowTemplatesStore.groupedTemplates[0].modules[0]
handleTabSelection(firstTab)
@@ -118,7 +118,7 @@ const loadWorkflow = async (id: string) => {
workflowLoading.value = id
let json
if (selectedTab.value.moduleName === 'default') {
if (selectedTab.value?.moduleName === 'default') {
// Default templates provided by frontend are served on this separate endpoint
json = await fetch(api.fileURL(`/templates/${id}.json`)).then((r) =>
r.json()
@@ -126,13 +126,13 @@ const loadWorkflow = async (id: string) => {
} else {
json = await fetch(
api.apiURL(
`/workflow_templates/${selectedTab.value.moduleName}/${id}.json`
`/workflow_templates/${selectedTab.value?.moduleName}/${id}.json`
)
).then((r) => r.json())
}
useDialogStore().closeDialog()
const workflowName =
selectedTab.value.moduleName === 'default'
selectedTab.value?.moduleName === 'default'
? t(`templateWorkflows.template.${id}`, id)
: id
await app.loadGraphData(json, true, true, workflowName)

View File

@@ -131,7 +131,7 @@ import MirrorsConfiguration from '@/components/install/MirrorsConfiguration.vue'
import { electronAPI } from '@/utils/envUtil'
import BaseViewTemplate from '@/views/templates/BaseViewTemplate.vue'
const device = ref<TorchDeviceType>(null)
const device = ref<TorchDeviceType | null>(null)
const installPath = ref('')
const pathError = ref('')

View File

@@ -64,7 +64,7 @@ const { t } = useI18n()
const electron = electronAPI()
const basePath = ref<string>(null)
const basePath = ref<string | null>(null)
const sep = ref<'\\' | '/'>('/')
const restartApp = (message?: string) => electron.restartApp(message)

View File

@@ -74,7 +74,7 @@ const updateProgress = ({ status: newStatus }: { status: ProgressStatus }) => {
const terminalCreated = (
{ terminal, useAutoSize }: ReturnType<typeof useTerminal>,
root: Ref<HTMLElement>
root: Ref<HTMLElement | undefined>
) => {
xterm = terminal

View File

@@ -79,7 +79,7 @@ const login = async () => {
userStore.login(user)
router.push('/')
} catch (err) {
loginError.value = err.message ?? JSON.stringify(err)
loginError.value = err instanceof Error ? err.message : JSON.stringify(err)
}
}

View File

@@ -52,7 +52,7 @@ onMounted(async () => {
electronAPI().changeTheme({
...(props.dark ? darkTheme : lightTheme),
height: topMenuRef.value.getBoundingClientRect().height
height: topMenuRef.value?.getBoundingClientRect().height ?? 0
})
}
})