Skip to content

Commit a457534

Browse files
authored
[System Pop Up] Improve help center menu behavior and Electron compatibility (#4330)
1 parent 5cc1a8d commit a457534

File tree

1 file changed

+133
-84
lines changed

1 file changed

+133
-84
lines changed

src/components/helpcenter/HelpCenterMenuContent.vue

Lines changed: 133 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<nav class="help-menu-section" role="menubar">
55
<button
66
v-for="menuItem in menuItems"
7+
v-show="menuItem.visible !== false"
78
:key="menuItem.key"
89
type="button"
910
class="help-menu-item"
@@ -29,14 +30,20 @@
2930
@mouseenter="onSubmenuHover"
3031
@mouseleave="onSubmenuLeave"
3132
>
32-
<template v-for="submenuItem in submenuItems" :key="submenuItem.key">
33-
<div v-if="submenuItem.type === 'divider'" class="submenu-divider" />
33+
<template
34+
v-for="submenuItem in moreMenuItem?.items"
35+
:key="submenuItem.key"
36+
>
37+
<div
38+
v-if="submenuItem.type === 'divider'"
39+
v-show="submenuItem.visible !== false"
40+
class="submenu-divider"
41+
/>
3442
<button
3543
v-else
44+
v-show="submenuItem.visible !== false"
3645
type="button"
3746
class="help-menu-item submenu-item"
38-
:class="{ disabled: submenuItem.disabled }"
39-
:disabled="submenuItem.disabled"
4047
role="menuitem"
4148
@click="submenuItem.action"
4249
>
@@ -117,32 +124,28 @@ import { type CSSProperties, computed, nextTick, onMounted, ref } from 'vue'
117124
import { useI18n } from 'vue-i18n'
118125
119126
import { type ReleaseNote } from '@/services/releaseService'
127+
import { useCommandStore } from '@/stores/commandStore'
120128
import { useReleaseStore } from '@/stores/releaseStore'
121129
import { electronAPI, isElectron } from '@/utils/envUtil'
122130
import { formatVersionAnchor } from '@/utils/formatUtil'
123131
124132
// Types
125133
interface MenuItem {
126134
key: string
127-
icon: string
128-
label: string
129-
action: () => void
130-
}
131-
132-
interface SubmenuItem {
133-
key: string
134-
type?: 'item' | 'divider'
135+
icon?: string
135136
label?: string
136137
action?: () => void
137-
disabled?: boolean
138+
visible?: boolean
139+
type?: 'item' | 'divider'
140+
items?: MenuItem[]
138141
}
139142
140143
// Constants
141144
const EXTERNAL_LINKS = {
142145
DOCS: 'https://docs.comfy.org/',
143146
DISCORD: 'https://www.comfy.org/discord',
144147
GITHUB: 'https://github.com/comfyanonymous/ComfyUI',
145-
DESKTOP_GUIDE: 'https://docs.comfy.org/installation/desktop',
148+
DESKTOP_GUIDE: 'https://comfyorg.notion.site/',
146149
UPDATE_GUIDE: 'https://docs.comfy.org/installation/update_comfyui'
147150
} as const
148151
@@ -164,6 +167,12 @@ const SUBMENU_CONFIG = {
164167
// Composables
165168
const { t, locale } = useI18n()
166169
const releaseStore = useReleaseStore()
170+
const commandStore = useCommandStore()
171+
172+
// Emits
173+
const emit = defineEmits<{
174+
close: []
175+
}>()
167176
168177
// State
169178
const isSubmenuVisible = ref(false)
@@ -174,66 +183,99 @@ let hoverTimeout: number | null = null
174183
// Computed
175184
const hasReleases = computed(() => releaseStore.releases.length > 0)
176185
177-
const menuItems = computed<MenuItem[]>(() => [
178-
{
179-
key: 'docs',
180-
icon: 'pi pi-book',
181-
label: t('helpCenter.docs'),
182-
action: () => openExternalLink(EXTERNAL_LINKS.DOCS)
183-
},
184-
{
185-
key: 'discord',
186-
icon: 'pi pi-discord',
187-
label: 'Discord',
188-
action: () => openExternalLink(EXTERNAL_LINKS.DISCORD)
189-
},
190-
{
191-
key: 'github',
192-
icon: 'pi pi-github',
193-
label: t('helpCenter.github'),
194-
action: () => openExternalLink(EXTERNAL_LINKS.GITHUB)
195-
},
196-
{
197-
key: 'help',
198-
icon: 'pi pi-question-circle',
199-
label: t('helpCenter.helpFeedback'),
200-
action: () => openExternalLink(EXTERNAL_LINKS.DISCORD)
201-
},
202-
{
203-
key: 'more',
204-
icon: '',
205-
label: t('helpCenter.more'),
206-
action: () => {} // No action for more item
207-
}
208-
])
209-
210-
const submenuItems = computed<SubmenuItem[]>(() => [
211-
{
212-
key: 'desktop-guide',
213-
type: 'item',
214-
label: t('helpCenter.desktopUserGuide'),
215-
action: () => openExternalLink(EXTERNAL_LINKS.DESKTOP_GUIDE),
216-
disabled: false
217-
},
218-
{
219-
key: 'dev-tools',
220-
type: 'item',
221-
label: t('helpCenter.openDevTools'),
222-
action: openDevTools,
223-
disabled: !isElectron()
224-
},
225-
{
226-
key: 'divider-1',
227-
type: 'divider'
228-
},
229-
{
230-
key: 'reinstall',
231-
type: 'item',
232-
label: t('helpCenter.reinstall'),
233-
action: onReinstall,
234-
disabled: !isElectron()
235-
}
236-
])
186+
const moreMenuItem = computed(() =>
187+
menuItems.value.find((item) => item.key === 'more')
188+
)
189+
190+
const menuItems = computed<MenuItem[]>(() => {
191+
const moreItems: MenuItem[] = [
192+
{
193+
key: 'desktop-guide',
194+
type: 'item',
195+
label: t('helpCenter.desktopUserGuide'),
196+
action: () => {
197+
openExternalLink(EXTERNAL_LINKS.DESKTOP_GUIDE)
198+
emit('close')
199+
}
200+
},
201+
{
202+
key: 'dev-tools',
203+
type: 'item',
204+
label: t('helpCenter.openDevTools'),
205+
visible: isElectron(),
206+
action: () => {
207+
openDevTools()
208+
emit('close')
209+
}
210+
},
211+
{
212+
key: 'divider-1',
213+
type: 'divider',
214+
visible: isElectron()
215+
},
216+
{
217+
key: 'reinstall',
218+
type: 'item',
219+
label: t('helpCenter.reinstall'),
220+
visible: isElectron(),
221+
action: () => {
222+
onReinstall()
223+
emit('close')
224+
}
225+
}
226+
]
227+
228+
return [
229+
{
230+
key: 'docs',
231+
type: 'item',
232+
icon: 'pi pi-book',
233+
label: t('helpCenter.docs'),
234+
action: () => {
235+
openExternalLink(EXTERNAL_LINKS.DOCS)
236+
emit('close')
237+
}
238+
},
239+
{
240+
key: 'discord',
241+
type: 'item',
242+
icon: 'pi pi-discord',
243+
label: 'Discord',
244+
action: () => {
245+
openExternalLink(EXTERNAL_LINKS.DISCORD)
246+
emit('close')
247+
}
248+
},
249+
{
250+
key: 'github',
251+
type: 'item',
252+
icon: 'pi pi-github',
253+
label: t('helpCenter.github'),
254+
action: () => {
255+
openExternalLink(EXTERNAL_LINKS.GITHUB)
256+
emit('close')
257+
}
258+
},
259+
{
260+
key: 'help',
261+
type: 'item',
262+
icon: 'pi pi-question-circle',
263+
label: t('helpCenter.helpFeedback'),
264+
action: () => {
265+
void commandStore.execute('Comfy.Feedback')
266+
emit('close')
267+
}
268+
},
269+
{
270+
key: 'more',
271+
type: 'item',
272+
icon: '',
273+
label: t('helpCenter.more'),
274+
action: () => {}, // No action for more item
275+
items: moreItems
276+
}
277+
]
278+
})
237279
238280
// Utility Functions
239281
const openExternalLink = (url: string): void => {
@@ -251,8 +293,12 @@ const calculateSubmenuPosition = (button: HTMLElement): CSSProperties => {
251293
const rect = button.getBoundingClientRect()
252294
const submenuWidth = 210 // Width defined in CSS
253295
254-
// Get actual submenu height if available, otherwise use estimated height
255-
const submenuHeight = submenuRef.value?.offsetHeight || 120 // More realistic estimate for 2 items
296+
// Get actual submenu height if available, otherwise estimate based on visible item count
297+
const visibleItemCount =
298+
moreMenuItem.value?.items?.filter((item) => item.visible !== false)
299+
.length || 0
300+
const estimatedHeight = visibleItemCount * 48 + 16 // ~48px per item + padding
301+
const submenuHeight = submenuRef.value?.offsetHeight || estimatedHeight
256302
257303
// Get viewport dimensions
258304
const viewportWidth = window.innerWidth
@@ -282,6 +328,8 @@ const calculateSubmenuPosition = (button: HTMLElement): CSSProperties => {
282328
top = SUBMENU_CONFIG.OFFSET_PX
283329
}
284330
331+
top -= 8
332+
285333
return {
286334
position: 'fixed',
287335
top: `${top}px`,
@@ -328,7 +376,13 @@ const onMenuItemHover = async (
328376
key: string,
329377
event: MouseEvent
330378
): Promise<void> => {
331-
if (key !== 'more') return
379+
if (key !== 'more' || !moreMenuItem.value?.items) return
380+
381+
// Don't show submenu if all items are hidden
382+
const hasVisibleItems = moreMenuItem.value.items.some(
383+
(item) => item.visible !== false
384+
)
385+
if (!hasVisibleItems) return
332386
333387
clearHoverTimeout()
334388
@@ -380,10 +434,12 @@ const onReleaseClick = (release: ReleaseNote): void => {
380434
const versionAnchor = formatVersionAnchor(release.version)
381435
const changelogUrl = `${getChangelogUrl()}#${versionAnchor}`
382436
openExternalLink(changelogUrl)
437+
emit('close')
383438
}
384439
385440
const onUpdate = (_: ReleaseNote): void => {
386441
openExternalLink(EXTERNAL_LINKS.UPDATE_GUIDE)
442+
emit('close')
387443
}
388444
389445
// Generate language-aware changelog URL
@@ -551,13 +607,6 @@ onMounted(async () => {
551607
box-shadow: none;
552608
}
553609
554-
.submenu-item.disabled,
555-
.submenu-item:disabled {
556-
opacity: 0.5;
557-
cursor: not-allowed;
558-
pointer-events: none;
559-
}
560-
561610
.submenu-divider {
562611
height: 1px;
563612
background: #3e3e3e;

0 commit comments

Comments
 (0)