Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<component
:is="currentButton"
:key="isActiveSubscription ? 'queue' : 'subscribe'"
:key="isSubscribedOrIsNotCloud ? 'queue' : 'subscribe'"
/>
</template>
<script setup lang="ts">
Expand All @@ -11,9 +11,9 @@ import ComfyQueueButton from '@/components/actionbar/ComfyRunButton/ComfyQueueBu
import SubscribeToRunButton from '@/platform/cloud/subscription/components/SubscribeToRun.vue'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'

const { isActiveSubscription } = useSubscription()
const { isSubscribedOrIsNotCloud } = useSubscription()

const currentButton = computed(() =>
isActiveSubscription.value ? ComfyQueueButton : SubscribeToRunButton
isSubscribedOrIsNotCloud.value ? ComfyQueueButton : SubscribeToRunButton
)
</script>
9 changes: 7 additions & 2 deletions src/components/dialog/content/setting/CreditsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<UserCredit text-class="text-3xl font-bold" />
<Skeleton v-if="loading" width="2rem" height="2rem" />
<Button
v-else-if="isActiveSubscription"
v-else-if="isSubscribedOrIsNotCloud"
:label="$t('credits.purchaseCredits')"
:loading="loading"
@click="handlePurchaseCreditsClick"
Expand Down Expand Up @@ -125,6 +125,7 @@ import UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.v
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { useExternalLink } from '@/composables/useExternalLink'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import { isCloud } from '@/platform/distribution/types'
import { useTelemetry } from '@/platform/telemetry'
import { useDialogService } from '@/services/dialogService'
import { useCommandStore } from '@/stores/commandStore'
Expand All @@ -144,7 +145,11 @@ const authStore = useFirebaseAuthStore()
const authActions = useFirebaseAuthActions()
const commandStore = useCommandStore()
const telemetry = useTelemetry()
const { isActiveSubscription } = useSubscription()
const subscription = isCloud ? useSubscription() : null
const isSubscribedOrIsNotCloud = computed(() => {
if (!isCloud) return true
return subscription?.isSubscribedOrIsNotCloud.value ?? false
})
const loading = computed(() => authStore.loading)
const balanceLoading = computed(() => authStore.isFetchingBalance)

Expand Down
2 changes: 1 addition & 1 deletion src/components/topbar/CurrentUserPopover.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ vi.mock('@/stores/firebaseAuthStore', () => ({
const mockFetchStatus = vi.fn().mockResolvedValue(undefined)
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
useSubscription: vi.fn(() => ({
isActiveSubscription: { value: true },
isSubscribedOrIsNotCloud: { value: true },
fetchStatus: mockFetchStatus
}))
}))
Expand Down
9 changes: 6 additions & 3 deletions src/components/topbar/CurrentUserPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
</div>
</div>

<div v-if="isActiveSubscription" class="flex items-center justify-between">
<div
v-if="isSubscribedOrIsNotCloud"
class="flex items-center justify-between"
>
<div class="flex flex-col gap-1">
<UserCredit text-class="text-2xl" />
<Button
Expand Down Expand Up @@ -68,7 +71,7 @@
/>

<Button
v-if="isActiveSubscription"
v-if="isSubscribedOrIsNotCloud"
class="justify-start"
:label="$t(planSettingsLabel)"
icon="pi pi-receipt"
Expand Down Expand Up @@ -122,7 +125,7 @@ const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } =
useCurrentUser()
const authActions = useFirebaseAuthActions()
const dialogService = useDialogService()
const { isActiveSubscription, fetchStatus } = useSubscription()
const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()

const handleOpenUserSettings = () => {
dialogService.showSettingsDialog('user')
Expand Down
6 changes: 4 additions & 2 deletions src/composables/auth/useFirebaseAuthActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ export const useFirebaseAuthActions = () => {
)

const purchaseCredits = wrapWithErrorHandlingAsync(async (amount: number) => {
const { isActiveSubscription } = useSubscription()
if (!isActiveSubscription.value) return
if (isCloud) {
const { isSubscribedOrIsNotCloud } = useSubscription()
if (!isSubscribedOrIsNotCloud.value) return
}

const response = await authStore.initiateCreditPurchase({
amount_micros: usdToMicros(amount),
Expand Down
8 changes: 4 additions & 4 deletions src/composables/useCoreCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import { ManagerTab } from '@/workbench/extensions/manager/types/comfyManagerTyp

import { useWorkflowTemplateSelectorDialog } from './useWorkflowTemplateSelectorDialog'

const { isActiveSubscription, showSubscriptionDialog } = useSubscription()
const { isSubscribedOrIsNotCloud, showSubscriptionDialog } = useSubscription()

const moveSelectedNodesVersionAdded = '1.22.2'

Expand Down Expand Up @@ -475,7 +475,7 @@ export function useCoreCommands(): ComfyCommand[] {
trigger_source?: ExecutionTriggerSource
}) => {
useTelemetry()?.trackRunButton(metadata)
if (!isActiveSubscription.value) {
if (!isSubscribedOrIsNotCloud.value) {
showSubscriptionDialog()
return
}
Expand All @@ -498,7 +498,7 @@ export function useCoreCommands(): ComfyCommand[] {
trigger_source?: ExecutionTriggerSource
}) => {
useTelemetry()?.trackRunButton(metadata)
if (!isActiveSubscription.value) {
if (!isSubscribedOrIsNotCloud.value) {
showSubscriptionDialog()
return
}
Expand All @@ -520,7 +520,7 @@ export function useCoreCommands(): ComfyCommand[] {
trigger_source?: ExecutionTriggerSource
}) => {
useTelemetry()?.trackRunButton(metadata)
if (!isActiveSubscription.value) {
if (!isSubscribedOrIsNotCloud.value) {
showSubscriptionDialog()
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const emit = defineEmits<{
subscribed: []
}>()
const { subscribe, isActiveSubscription, fetchStatus } = useSubscription()
const { subscribe, isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()
const telemetry = useTelemetry()
const isLoading = ref(false)
Expand All @@ -76,7 +76,7 @@ const startPollingSubscriptionStatus = () => {
await fetchStatus()
if (isActiveSubscription.value) {
if (isSubscribedOrIsNotCloud.value) {
stopPolling()
telemetry?.trackMonthlySubscriptionSucceeded()
emit('subscribed')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="flex items-baseline gap-2">
<span class="text-2xl font-inter font-semibold leading-tight">
{{
isActiveSubscription
isSubscribedOrIsNotCloud
? $t('subscription.title')
: $t('subscription.titleUnsubscribed')
}}
Expand All @@ -27,7 +27,7 @@
}}</span>
</div>
<div
v-if="isActiveSubscription"
v-if="isSubscribedOrIsNotCloud"
class="text-sm text-text-secondary"
>
<template v-if="isCancelled">
Expand All @@ -47,7 +47,7 @@
</div>
</div>
<Button
v-if="isActiveSubscription"
v-if="isSubscribedOrIsNotCloud"
:label="$t('subscription.manageSubscription')"
severity="secondary"
class="text-xs bg-interface-menu-component-surface-selected"
Expand Down Expand Up @@ -196,7 +196,7 @@
{{ $t('subscription.viewUsageHistory') }}
</a>
<Button
v-if="isActiveSubscription"
v-if="isSubscribedOrIsNotCloud"
:label="$t('subscription.addCredits')"
severity="secondary"
class="p-2 min-h-8 bg-interface-menu-component-surface-selected"
Expand Down Expand Up @@ -320,7 +320,7 @@ import { cn } from '@/utils/tailwindUtil'
const { buildDocsUrl } = useExternalLink()

const {
isActiveSubscription,
isSubscribedOrIsNotCloud,
isCancelled,
formattedRenewalDate,
formattedEndDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function useSubscriptionInternal() {
const { startCancellationWatcher, stopCancellationWatcher } =
useSubscriptionCancellationWatcher({
fetchStatus,
isActiveSubscription: isSubscribedOrIsNotCloud,
isSubscribedOrIsNotCloud,
subscriptionStatus,
telemetry,
shouldWatchCancellation
Expand Down Expand Up @@ -223,7 +223,7 @@ function useSubscriptionInternal() {

return {
// State
isActiveSubscription: isSubscribedOrIsNotCloud,
isSubscribedOrIsNotCloud,
isCancelled,
formattedRenewalDate,
formattedEndDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ const CANCELLATION_BACKOFF_MULTIPLIER = 3 // 5s, 15s, 45s, 135s intervals

type CancellationWatcherOptions = {
fetchStatus: () => Promise<CloudSubscriptionStatusResponse | null | void>
isActiveSubscription: ComputedRef<boolean>
isSubscribedOrIsNotCloud: ComputedRef<boolean>
subscriptionStatus: Ref<CloudSubscriptionStatusResponse | null>
telemetry: Pick<TelemetryProvider, 'trackMonthlySubscriptionCancelled'> | null
shouldWatchCancellation: () => boolean
}

export function useSubscriptionCancellationWatcher({
fetchStatus,
isActiveSubscription,
isSubscribedOrIsNotCloud,
subscriptionStatus,
telemetry,
shouldWatchCancellation
Expand Down Expand Up @@ -73,7 +73,7 @@ export function useSubscriptionCancellationWatcher({
try {
await fetchStatus()

if (!isActiveSubscription.value) {
if (!isSubscribedOrIsNotCloud.value) {
if (!cancellationTracked.value) {
cancellationTracked.value = true
try {
Expand Down
10 changes: 8 additions & 2 deletions src/scripts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,17 @@ export class ComfyApp {
'Payment Required: Please add credits to your account to use this node.'
)
) {
const { isActiveSubscription } = useSubscription()
if (isActiveSubscription.value) {
if (!isCloud) {
useDialogService().showTopUpCreditsDialog({
isInsufficientCredits: true
})
} else {
const { isSubscribedOrIsNotCloud } = useSubscription()
if (isSubscribedOrIsNotCloud.value) {
useDialogService().showTopUpCreditsDialog({
isInsufficientCredits: true
})
}
}
} else {
useDialogService().showExecutionErrorDialog(detail)
Expand Down
6 changes: 4 additions & 2 deletions src/services/dialogService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,10 @@ export const useDialogService = () => {
function showTopUpCreditsDialog(options?: {
isInsufficientCredits?: boolean
}) {
const { isActiveSubscription } = useSubscription()
if (!isActiveSubscription.value) return
if (isCloud) {
const { isSubscribedOrIsNotCloud } = useSubscription()
if (!isSubscribedOrIsNotCloud.value) return
}

return dialogStore.showDialog({
key: 'top-up-credits',
Expand Down
2 changes: 1 addition & 1 deletion tests-ui/tests/composables/useCoreCommands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ vi.mock('@/composables/auth/useFirebaseAuthActions', () => ({

vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
useSubscription: vi.fn(() => ({
isActiveSubscription: vi.fn().mockReturnValue(true),
isSubscribedOrIsNotCloud: vi.fn().mockReturnValue(true),
showSubscriptionDialog: vi.fn()
}))
}))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SubscriptionPanel from '@/platform/cloud/subscription/components/Subscrip

// Mock composables
const mockSubscriptionData = {
isActiveSubscription: false,
isSubscribedOrIsNotCloud: false,
isCancelled: false,
formattedRenewalDate: '2024-12-31',
formattedEndDate: '2024-12-31',
Expand Down Expand Up @@ -120,14 +120,14 @@ describe('SubscriptionPanel', () => {

describe('subscription state functionality', () => {
it('shows correct UI for active subscription', () => {
mockSubscriptionData.isActiveSubscription = true
mockSubscriptionData.isSubscribedOrIsNotCloud = true
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Manage Subscription')
expect(wrapper.text()).toContain('Add Credits')
})

it('shows correct UI for inactive subscription', () => {
mockSubscriptionData.isActiveSubscription = false
mockSubscriptionData.isSubscribedOrIsNotCloud = false
const wrapper = createWrapper()
expect(wrapper.findComponent({ name: 'SubscribeButton' }).exists()).toBe(
true
Expand All @@ -137,14 +137,14 @@ describe('SubscriptionPanel', () => {
})

it('shows renewal date for active non-cancelled subscription', () => {
mockSubscriptionData.isActiveSubscription = true
mockSubscriptionData.isSubscribedOrIsNotCloud = true
mockSubscriptionData.isCancelled = false
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Renews 2024-12-31')
})

it('shows expiry date for cancelled subscription', () => {
mockSubscriptionData.isActiveSubscription = true
mockSubscriptionData.isSubscribedOrIsNotCloud = true
mockSubscriptionData.isCancelled = true
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Expires 2024-12-31')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('useSubscription', () => {
})

describe('computed properties', () => {
it('should compute isActiveSubscription correctly when subscription is active', async () => {
it('should compute isSubscribedOrIsNotCloud correctly when subscription is active', async () => {
vi.mocked(global.fetch).mockResolvedValue({
ok: true,
json: async () => ({
Expand All @@ -103,13 +103,13 @@ describe('useSubscription', () => {
} as Response)

mockIsLoggedIn.value = true
const { isActiveSubscription, fetchStatus } = useSubscription()
const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()

await fetchStatus()
expect(isActiveSubscription.value).toBe(true)
expect(isSubscribedOrIsNotCloud.value).toBe(true)
})

it('should compute isActiveSubscription as false when subscription is inactive', async () => {
it('should compute isSubscribedOrIsNotCloud as false when subscription is inactive', async () => {
vi.mocked(global.fetch).mockResolvedValue({
ok: true,
json: async () => ({
Expand All @@ -120,10 +120,10 @@ describe('useSubscription', () => {
} as Response)

mockIsLoggedIn.value = true
const { isActiveSubscription, fetchStatus } = useSubscription()
const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()

await fetchStatus()
expect(isActiveSubscription.value).toBe(false)
expect(isSubscribedOrIsNotCloud.value).toBe(false)
})

it('should format renewal date correctly', async () => {
Expand Down
Loading
Loading