mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +00:00
refactor: extract desktop cloud promo controller
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
import DesktopCloudNotificationController from './DesktopCloudNotificationController.vue'
|
||||
|
||||
const settingState = {
|
||||
shown: false
|
||||
}
|
||||
|
||||
const settingStore = {
|
||||
load: vi.fn<() => Promise<void>>(),
|
||||
get: vi.fn((key: string) =>
|
||||
key === 'Comfy.Desktop.CloudNotificationShown'
|
||||
? settingState.shown
|
||||
: undefined
|
||||
),
|
||||
set: vi.fn(async (_key: string, value: boolean) => {
|
||||
settingState.shown = value
|
||||
})
|
||||
}
|
||||
|
||||
const dialogService = {
|
||||
showCloudNotification: vi.fn<() => Promise<void>>()
|
||||
}
|
||||
|
||||
const electron = {
|
||||
getPlatform: vi.fn(() => 'darwin')
|
||||
}
|
||||
|
||||
vi.mock('@/platform/distribution/types', () => ({
|
||||
isDesktop: true
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/settings/settingStore', () => ({
|
||||
useSettingStore: () => settingStore
|
||||
}))
|
||||
|
||||
vi.mock('@/services/dialogService', () => ({
|
||||
useDialogService: () => dialogService
|
||||
}))
|
||||
|
||||
vi.mock('@/utils/envUtil', () => ({
|
||||
electronAPI: () => electron
|
||||
}))
|
||||
|
||||
function createDeferred() {
|
||||
let resolve!: () => void
|
||||
const promise = new Promise<void>((res) => {
|
||||
resolve = res
|
||||
})
|
||||
|
||||
return { promise, resolve }
|
||||
}
|
||||
|
||||
describe('DesktopCloudNotificationController', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
vi.clearAllMocks()
|
||||
|
||||
settingState.shown = false
|
||||
electron.getPlatform.mockReturnValue('darwin')
|
||||
settingStore.load.mockResolvedValue(undefined)
|
||||
settingStore.set.mockImplementation(
|
||||
async (_key: string, value: boolean) => {
|
||||
settingState.shown = value
|
||||
}
|
||||
)
|
||||
dialogService.showCloudNotification.mockResolvedValue(undefined)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('waits for settings to load before deciding whether to show the notification', async () => {
|
||||
const loadSettings = createDeferred()
|
||||
settingStore.load.mockImplementation(() => loadSettings.promise)
|
||||
|
||||
const wrapper = mount(DesktopCloudNotificationController)
|
||||
await nextTick()
|
||||
|
||||
settingState.shown = true
|
||||
loadSettings.resolve()
|
||||
|
||||
await flushPromises()
|
||||
await vi.advanceTimersByTimeAsync(2000)
|
||||
|
||||
expect(dialogService.showCloudNotification).not.toHaveBeenCalled()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('marks the notification as shown before awaiting dialog close', async () => {
|
||||
const dialogOpen = createDeferred()
|
||||
dialogService.showCloudNotification.mockImplementation(
|
||||
() => dialogOpen.promise
|
||||
)
|
||||
|
||||
const wrapper = mount(DesktopCloudNotificationController)
|
||||
|
||||
await flushPromises()
|
||||
await vi.advanceTimersByTimeAsync(2000)
|
||||
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Desktop.CloudNotificationShown',
|
||||
true
|
||||
)
|
||||
expect(settingStore.set.mock.invocationCallOrder[0]).toBeLessThan(
|
||||
dialogService.showCloudNotification.mock.invocationCallOrder[0]
|
||||
)
|
||||
|
||||
dialogOpen.resolve()
|
||||
await flushPromises()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
|
||||
import { isDesktop } from '@/platform/distribution/types'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { electronAPI } from '@/utils/envUtil'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const dialogService = useDialogService()
|
||||
|
||||
let cloudNotificationTimer: ReturnType<typeof setTimeout> | undefined
|
||||
|
||||
onMounted(() => {
|
||||
if (!isDesktop || electronAPI()?.getPlatform() !== 'darwin') return
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
await settingStore.load()
|
||||
} catch (error) {
|
||||
console.warn('[CloudNotification] Failed to load settings', error)
|
||||
return
|
||||
}
|
||||
|
||||
if (settingStore.get('Comfy.Desktop.CloudNotificationShown')) return
|
||||
|
||||
cloudNotificationTimer = setTimeout(async () => {
|
||||
try {
|
||||
await settingStore.set('Comfy.Desktop.CloudNotificationShown', true)
|
||||
await dialogService.showCloudNotification()
|
||||
} catch (error) {
|
||||
console.warn('[CloudNotification] Failed to show', error)
|
||||
await settingStore
|
||||
.set('Comfy.Desktop.CloudNotificationShown', false)
|
||||
.catch((resetError) => {
|
||||
console.warn(
|
||||
'[CloudNotification] Failed to reset shown state',
|
||||
resetError
|
||||
)
|
||||
})
|
||||
}
|
||||
}, 2000)
|
||||
})()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cloudNotificationTimer) clearTimeout(cloudNotificationTimer)
|
||||
})
|
||||
</script>
|
||||
@@ -1,465 +0,0 @@
|
||||
import { flushPromises, shallowMount } from '@vue/test-utils'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { nextTick, reactive, ref } from 'vue'
|
||||
|
||||
import GraphView from '@/views/GraphView.vue'
|
||||
|
||||
const linearMode = ref(false)
|
||||
const isBuilderMode = ref(false)
|
||||
|
||||
const workspaceTheme = reactive({
|
||||
light_theme: true,
|
||||
colors: {
|
||||
comfy_base: {
|
||||
'input-text': '#000000'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const queueStore = reactive({
|
||||
tasks: [],
|
||||
maxHistoryItems: 0,
|
||||
update: vi.fn().mockResolvedValue(undefined)
|
||||
})
|
||||
|
||||
const sidebarTabStore = reactive({
|
||||
activeSidebarTabId: null as string | null,
|
||||
registerCoreSidebarTabs: vi.fn()
|
||||
})
|
||||
|
||||
const settingValues = reactive({
|
||||
shown: false
|
||||
})
|
||||
|
||||
const settingStore = {
|
||||
load: vi.fn<() => Promise<void>>(),
|
||||
get: vi.fn((key: string) => {
|
||||
switch (key) {
|
||||
case 'Comfy.Desktop.CloudNotificationShown':
|
||||
return settingValues.shown
|
||||
case 'Comfy.TextareaWidget.FontSize':
|
||||
return 12
|
||||
case 'Comfy.TreeExplorer.ItemPadding':
|
||||
return 8
|
||||
case 'Comfy.Locale':
|
||||
return 'en'
|
||||
case 'Comfy.UseNewMenu':
|
||||
return 'Enabled'
|
||||
case 'Comfy.Queue.MaxHistoryItems':
|
||||
return 100
|
||||
case 'Comfy.Toast.DisableReconnectingToast':
|
||||
return false
|
||||
case 'Comfy.Server.ServerConfigValues':
|
||||
return {}
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
}),
|
||||
set: vi.fn(async (_key: string, value: boolean) => {
|
||||
settingValues.shown = value
|
||||
})
|
||||
}
|
||||
|
||||
const dialogService = {
|
||||
showCloudNotification: vi.fn<() => Promise<void>>()
|
||||
}
|
||||
|
||||
const executionStore = {
|
||||
bindExecutionEvents: vi.fn(),
|
||||
unbindExecutionEvents: vi.fn()
|
||||
}
|
||||
|
||||
const versionCompatibilityStore = {
|
||||
initialize: vi.fn().mockResolvedValue(undefined)
|
||||
}
|
||||
|
||||
const colorPaletteStore = reactive({
|
||||
completedActivePalette: workspaceTheme
|
||||
})
|
||||
|
||||
const electron = {
|
||||
changeTheme: vi.fn(),
|
||||
showContextMenu: vi.fn(),
|
||||
getPlatform: vi.fn(() => 'darwin'),
|
||||
Events: {
|
||||
incrementUserProperty: vi.fn(),
|
||||
trackEvent: vi.fn()
|
||||
}
|
||||
}
|
||||
|
||||
vi.mock('@vueuse/core', async (importOriginal) => {
|
||||
const actual = (await importOriginal()) as Record<string, unknown>
|
||||
return {
|
||||
...actual,
|
||||
useEventListener: vi.fn(),
|
||||
useIntervalFn: vi.fn()
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('pinia', async (importOriginal) => {
|
||||
const actual = (await importOriginal()) as Record<string, unknown>
|
||||
return {
|
||||
...actual,
|
||||
storeToRefs: (store: object) => store
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('primevue/usetoast', () => ({
|
||||
useToast: () => ({
|
||||
add: vi.fn(),
|
||||
remove: vi.fn()
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('vue-i18n', () => ({
|
||||
useI18n: () => ({
|
||||
t: (key: string) => key
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/base/common/async', () => ({
|
||||
runWhenGlobalIdle: (cb: () => void) => cb()
|
||||
}))
|
||||
|
||||
vi.mock('@/components/MenuHamburger.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/builder/BuilderFooterToolbar.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/builder/BuilderMenu.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/builder/BuilderToolbar.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/dialog/UnloadWindowConfirmDialog.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/graph/GraphCanvas.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/toast/GlobalToast.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/components/toast/RerouteMigrationToast.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/useAppMode', () => ({
|
||||
useAppMode: () => ({
|
||||
isBuilderMode
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/useBrowserTabTitle', () => ({
|
||||
useBrowserTabTitle: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/useCoreCommands', () => ({
|
||||
useCoreCommands: vi.fn(() => ({}))
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/useErrorHandling', () => ({
|
||||
useErrorHandling: () => ({
|
||||
wrapWithErrorHandling: (fn: (...args: unknown[]) => unknown) => fn,
|
||||
wrapWithErrorHandlingAsync: (
|
||||
fn: (...args: unknown[]) => Promise<unknown>
|
||||
) => fn
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/useProgressFavicon', () => ({
|
||||
useProgressFavicon: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/constants/serverConfig', () => ({
|
||||
SERVER_CONFIG_ITEMS: []
|
||||
}))
|
||||
|
||||
vi.mock('@/i18n', () => ({
|
||||
i18n: {
|
||||
global: {
|
||||
locale: {
|
||||
value: 'en'
|
||||
}
|
||||
}
|
||||
},
|
||||
loadLocale: vi.fn().mockResolvedValue(undefined)
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/distribution/types', () => ({
|
||||
isCloud: false,
|
||||
isDesktop: true
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/assets/components/AssetExportProgressDialog.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/assets/components/ModelImportProgressDialog.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/keybindings/keybindingService', () => ({
|
||||
useKeybindingService: () => ({
|
||||
registerCoreKeybindings: vi.fn(),
|
||||
registerUserKeybindings: vi.fn(),
|
||||
keybindHandler: vi.fn()
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/remote/comfyui/useQueuePolling', () => ({
|
||||
useQueuePolling: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/settings/settingStore', () => ({
|
||||
useSettingStore: () => settingStore
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/telemetry', () => ({
|
||||
useTelemetry: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/updates/common/useFrontendVersionMismatchWarning', () => ({
|
||||
useFrontendVersionMismatchWarning: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/updates/common/versionCompatibilityStore', () => ({
|
||||
useVersionCompatibilityStore: () => versionCompatibilityStore
|
||||
}))
|
||||
|
||||
vi.mock('@/renderer/core/canvas/canvasStore', () => ({
|
||||
useCanvasStore: () => ({
|
||||
linearMode
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/scripts/api', () => ({
|
||||
api: {}
|
||||
}))
|
||||
|
||||
vi.mock('@/scripts/app', () => ({
|
||||
app: {
|
||||
ui: {
|
||||
menuContainer: document.createElement('div'),
|
||||
restoreMenuPosition: vi.fn()
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/services/autoQueueService', () => ({
|
||||
setupAutoQueueHandler: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/services/dialogService', () => ({
|
||||
useDialogService: () => dialogService
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/assetsStore', () => ({
|
||||
useAssetsStore: () => ({
|
||||
updateHistory: vi.fn().mockResolvedValue(undefined)
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/commandStore', () => ({
|
||||
useCommandStore: () => ({
|
||||
registerCommands: vi.fn()
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/executionStore', () => ({
|
||||
useExecutionStore: () => executionStore
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/firebaseAuthStore', () => ({
|
||||
useFirebaseAuthStore: () => ({
|
||||
isAuthenticated: false
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/menuItemStore', () => ({
|
||||
useMenuItemStore: () => ({
|
||||
registerCoreMenuCommands: vi.fn()
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/modelStore', () => ({
|
||||
useModelStore: () => ({
|
||||
loadModelFolders: vi.fn().mockResolvedValue(undefined)
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/nodeDefStore', () => ({
|
||||
useNodeDefStore: () => ({
|
||||
nodeSearchService: {
|
||||
searchNode: vi.fn()
|
||||
}
|
||||
}),
|
||||
useNodeFrequencyStore: () => ({
|
||||
loadNodeFrequencies: vi.fn().mockResolvedValue(undefined)
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/queueStore', () => ({
|
||||
useQueuePendingTaskCountStore: () => ({
|
||||
update: vi.fn()
|
||||
}),
|
||||
useQueueStore: () => queueStore
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/serverConfigStore', () => ({
|
||||
useServerConfigStore: () => ({
|
||||
loadServerConfig: vi.fn()
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/workspace/bottomPanelStore', () => ({
|
||||
useBottomPanelStore: () => ({
|
||||
registerCoreBottomPanelTabs: vi.fn().mockResolvedValue(undefined)
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/workspace/colorPaletteStore', () => ({
|
||||
useColorPaletteStore: () => colorPaletteStore
|
||||
}))
|
||||
|
||||
vi.mock('@/stores/workspace/sidebarTabStore', () => ({
|
||||
useSidebarTabStore: () => sidebarTabStore
|
||||
}))
|
||||
|
||||
vi.mock('@/utils/envUtil', () => ({
|
||||
electronAPI: () => electron
|
||||
}))
|
||||
|
||||
vi.mock('@/views/LinearView.vue', () => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock(
|
||||
'@/platform/workspace/components/toasts/InviteAcceptedToast.vue',
|
||||
() => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
vi.mock(
|
||||
'@/workbench/extensions/manager/components/ManagerProgressToast.vue',
|
||||
() => ({
|
||||
default: {
|
||||
template: '<div />'
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
function createDeferred() {
|
||||
let resolve!: () => void
|
||||
const promise = new Promise<void>((res) => {
|
||||
resolve = res
|
||||
})
|
||||
|
||||
return { promise, resolve }
|
||||
}
|
||||
|
||||
describe('GraphView cloud notification', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
vi.clearAllMocks()
|
||||
|
||||
linearMode.value = false
|
||||
isBuilderMode.value = false
|
||||
sidebarTabStore.activeSidebarTabId = null
|
||||
settingValues.shown = false
|
||||
electron.getPlatform.mockReturnValue('darwin')
|
||||
|
||||
settingStore.load.mockResolvedValue(undefined)
|
||||
settingStore.set.mockImplementation(
|
||||
async (_key: string, value: boolean) => {
|
||||
settingValues.shown = value
|
||||
}
|
||||
)
|
||||
dialogService.showCloudNotification.mockResolvedValue(undefined)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
function mountGraphView() {
|
||||
return shallowMount(GraphView)
|
||||
}
|
||||
|
||||
it('waits for settings to load before deciding whether to show the notification', async () => {
|
||||
const loadSettings = createDeferred()
|
||||
settingStore.load.mockImplementation(() => loadSettings.promise)
|
||||
|
||||
const wrapper = mountGraphView()
|
||||
await nextTick()
|
||||
|
||||
settingValues.shown = true
|
||||
loadSettings.resolve()
|
||||
|
||||
await flushPromises()
|
||||
await vi.advanceTimersByTimeAsync(2000)
|
||||
|
||||
expect(dialogService.showCloudNotification).not.toHaveBeenCalled()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('marks the notification as shown before awaiting dialog close', async () => {
|
||||
const dialogOpen = createDeferred()
|
||||
dialogService.showCloudNotification.mockImplementation(
|
||||
() => dialogOpen.promise
|
||||
)
|
||||
|
||||
const wrapper = mountGraphView()
|
||||
|
||||
await flushPromises()
|
||||
await vi.advanceTimersByTimeAsync(2000)
|
||||
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Desktop.CloudNotificationShown',
|
||||
true
|
||||
)
|
||||
expect(settingStore.set.mock.invocationCallOrder[0]).toBeLessThan(
|
||||
dialogService.showCloudNotification.mock.invocationCallOrder[0]
|
||||
)
|
||||
|
||||
dialogOpen.resolve()
|
||||
await flushPromises()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
@@ -26,6 +26,7 @@
|
||||
<ModelImportProgressDialog />
|
||||
<AssetExportProgressDialog />
|
||||
<ManagerProgressToast />
|
||||
<DesktopCloudNotificationController />
|
||||
<UnloadWindowConfirmDialog v-if="!isDesktop" />
|
||||
<MenuHamburger />
|
||||
</template>
|
||||
@@ -63,6 +64,7 @@ import type { ServerConfig, ServerConfigValue } from '@/constants/serverConfig'
|
||||
import { i18n, loadLocale } from '@/i18n'
|
||||
import AssetExportProgressDialog from '@/platform/assets/components/AssetExportProgressDialog.vue'
|
||||
import ModelImportProgressDialog from '@/platform/assets/components/ModelImportProgressDialog.vue'
|
||||
import DesktopCloudNotificationController from '@/platform/cloud/notification/components/DesktopCloudNotificationController.vue'
|
||||
import { isCloud, isDesktop } from '@/platform/distribution/types'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
@@ -73,7 +75,6 @@ import type { StatusWsMessageStatus } from '@/schemas/apiSchema'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
import { setupAutoQueueHandler } from '@/services/autoQueueService'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useKeybindingService } from '@/platform/keybindings/keybindingService'
|
||||
import { useAppMode } from '@/composables/useAppMode'
|
||||
import { useAssetsStore } from '@/stores/assetsStore'
|
||||
@@ -111,10 +112,8 @@ const queueStore = useQueueStore()
|
||||
const assetsStore = useAssetsStore()
|
||||
const versionCompatibilityStore = useVersionCompatibilityStore()
|
||||
const graphCanvasContainerRef = ref<HTMLDivElement | null>(null)
|
||||
const dialogService = useDialogService()
|
||||
const { isBuilderMode } = useAppMode()
|
||||
const { linearMode } = storeToRefs(useCanvasStore())
|
||||
let cloudNotificationTimer: ReturnType<typeof setTimeout> | undefined
|
||||
|
||||
watch(linearMode, (isLinear) => {
|
||||
if (isLinear) {
|
||||
@@ -288,41 +287,10 @@ onMounted(() => {
|
||||
} catch (e) {
|
||||
console.error('Failed to init ComfyUI frontend', e)
|
||||
}
|
||||
|
||||
if (!isDesktop || electronAPI()?.getPlatform() !== 'darwin') return
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
await settingStore.load()
|
||||
} catch (error) {
|
||||
console.warn('[CloudNotification] Failed to load settings', error)
|
||||
return
|
||||
}
|
||||
|
||||
if (settingStore.get('Comfy.Desktop.CloudNotificationShown')) return
|
||||
|
||||
cloudNotificationTimer = setTimeout(async () => {
|
||||
try {
|
||||
await settingStore.set('Comfy.Desktop.CloudNotificationShown', true)
|
||||
await dialogService.showCloudNotification()
|
||||
} catch (error) {
|
||||
console.warn('[CloudNotification] Failed to show', error)
|
||||
await settingStore
|
||||
.set('Comfy.Desktop.CloudNotificationShown', false)
|
||||
.catch((resetError) => {
|
||||
console.warn(
|
||||
'[CloudNotification] Failed to reset shown state',
|
||||
resetError
|
||||
)
|
||||
})
|
||||
}
|
||||
}, 2000)
|
||||
})()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
executionStore.unbindExecutionEvents()
|
||||
if (cloudNotificationTimer) clearTimeout(cloudNotificationTimer)
|
||||
})
|
||||
|
||||
useEventListener(window, 'keydown', useKeybindingService().keybindHandler)
|
||||
|
||||
Reference in New Issue
Block a user