fix Cloudbadge (#6063)

This pull request refactors how top bar badges are handled in the
application, making badge rendering extensible and moving cloud badge
logic into the extension system. The main changes include replacing the
old `CloudBetaBadge` component with a new, generic badge system,
introducing a Pinia store for badge management, and updating the
extension API to support top bar badges.

**Badge System Refactor and Extensibility**

* Replaced the hardcoded `CloudBetaBadge` with a new `TopbarBadges`
component, which dynamically renders badges from the store instead of
relying on the `isCloud` flag in `TopMenubar.vue`.
[[1]](diffhunk://#diff-b7d7bf1028f09fb907c09edf27631214d005c93b80eaff7cf15cfd53671b1e8aL9-R9)
[[2]](diffhunk://#diff-b7d7bf1028f09fb907c09edf27631214d005c93b80eaff7cf15cfd53671b1e8aL43-R48)

* Renamed and refactored `CloudBetaBadge.vue` to `TopbarBadge.vue`,
making it accept a generic `badge` prop and removing i18n logic from the
component.

* Added a new `TopbarBadges.vue` component to render all badges from the
`topbarBadgeStore`.

**Badge Data Management**

* Introduced a new Pinia store `topbarBadgeStore` that aggregates top
bar badges from all extensions, enabling dynamic badge management.

**Extension System Integration**

* Updated the extension API (`ComfyExtension` interface) to support a
new `topbarBadges` property, allowing extensions to contribute badges to
the top bar.

* Added a core extension (`cloudBadge.ts`) that registers a "Comfy
Cloud" beta badge when running in a cloud environment, using the new
badge system.
[[1]](diffhunk://#diff-b7818ca9daae2411d56695777160b8132507f2a3ff4f700d2510453c8833ca75R1-R16)
[[2]](diffhunk://#diff-236993d9e4213efe96d267c75c3292d32b93aa4dd6c3318d26a397e0ae56bc87R2)

**Type Definitions**

* Added a new `TopbarBadge` type to `comfy.ts` to define the structure
for top bar badges, supporting optional labels.
This commit is contained in:
Johnpaul Chiwetelu
2025-10-15 05:27:19 +01:00
committed by GitHub
parent 476d6df1ca
commit fb3ab88f04
7 changed files with 78 additions and 9 deletions

View File

@@ -6,7 +6,7 @@
style="background: var(--border-color)"
>
<WorkflowTabs />
<CloudBetaBadge v-if="isCloud" />
<TopbarBadges />
</div>
<div
v-show="showTopMenu"
@@ -40,13 +40,12 @@ import Actionbar from '@/components/actionbar/ComfyActionbar.vue'
import CommandMenubar from '@/components/topbar/CommandMenubar.vue'
import CurrentUserButton from '@/components/topbar/CurrentUserButton.vue'
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
import { isCloud } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { app } from '@/scripts/app'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { electronAPI, isElectron, isNativeWindow } from '@/utils/envUtil'
import CloudBetaBadge from './CloudBetaBadge.vue'
import TopbarBadges from './TopbarBadges.vue'
const workspaceState = useWorkspaceStore()
const settingStore = useSettingStore()

View File

@@ -1,19 +1,20 @@
<template>
<div class="flex items-center gap-2 bg-comfy-menu-secondary px-3">
<div
v-if="badge.label"
class="rounded-full bg-white px-1.5 py-0.5 text-xxxs font-semibold text-black"
>
{{ betaString }}
{{ badge.label }}
</div>
<div class="font-inter text-sm font-extrabold text-slate-100">
{{ cloudText }}
{{ badge.text }}
</div>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import type { TopbarBadge } from '@/types/comfy'
const { t } = useI18n()
const betaString = t('g.beta')
const cloudText = 'Comfy Cloud'
defineProps<{
badge: TopbarBadge
}>()
</script>

View File

@@ -0,0 +1,17 @@
<template>
<div class="flex">
<TopbarBadge
v-for="badge in topbarBadgeStore.badges"
:key="badge.text"
:badge
/>
</div>
</template>
<script lang="ts" setup>
import { useTopbarBadgeStore } from '@/stores/topbarBadgeStore'
import TopbarBadge from './TopbarBadge.vue'
const topbarBadgeStore = useTopbarBadgeStore()
</script>

View File

@@ -0,0 +1,16 @@
import { t } from '@/i18n'
import { isCloud } from '@/platform/distribution/types'
import { useExtensionService } from '@/services/extensionService'
useExtensionService().registerExtension({
name: 'Comfy.CloudBadge',
// Only show badge when running in cloud environment
topbarBadges: isCloud
? [
{
label: t('g.beta'),
text: 'Comfy Cloud'
}
]
: undefined
})

View File

@@ -1,3 +1,5 @@
import { isCloud } from '@/platform/distribution/types'
import './clipspace'
import './contextMenuFilter'
import './dynamicPrompts'
@@ -21,3 +23,7 @@ import './uploadAudio'
import './uploadImage'
import './webcamCapture'
import './widgetInputs'
if (isCloud) {
import('./cloudBadge')
}

View File

@@ -0,0 +1,18 @@
import { defineStore } from 'pinia'
import { computed } from 'vue'
import type { TopbarBadge } from '@/types/comfy'
import { useExtensionStore } from './extensionStore'
export const useTopbarBadgeStore = defineStore('topbarBadge', () => {
const extensionStore = useExtensionStore()
const badges = computed<TopbarBadge[]>(() =>
extensionStore.extensions.flatMap((e) => e.topbarBadges ?? [])
)
return {
badges
}
})

View File

@@ -33,6 +33,14 @@ type MenuCommandGroup = {
commands: string[]
}
export interface TopbarBadge {
text: string
/**
* Optional badge label (e.g., "BETA", "ALPHA", "NEW")
*/
label?: string
}
export type MissingNodeType =
| string
// Primarily used by group nodes.
@@ -74,6 +82,10 @@ export interface ComfyExtension {
* Badges to add to the about page
*/
aboutPageBadges?: AboutPageBadge[]
/**
* Badges to add to the top bar
*/
topbarBadges?: TopbarBadge[]
/**
* Allows any initialisation, e.g. loading resources. Called after the canvas is created but before nodes are added
* @param app The ComfyUI app instance