don't use compound name, use isSubscriptionRequirementMet

This commit is contained in:
bymyself
2025-12-05 18:06:07 -08:00
parent cd15c2706d
commit 5fd6aa69b8
17 changed files with 62 additions and 54 deletions

View File

@@ -1,7 +1,7 @@
<template>
<component
:is="currentButton"
:key="isSubscribedOrIsNotCloud ? 'queue' : 'subscribe'"
:key="isSubscriptionRequirementMet ? 'queue' : 'subscribe'"
/>
</template>
<script setup lang="ts">
@@ -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 { isSubscribedOrIsNotCloud } = useSubscription()
const { isSubscriptionRequirementMet } = useSubscription()
const currentButton = computed(() =>
isSubscribedOrIsNotCloud.value ? ComfyQueueButton : SubscribeToRunButton
isSubscriptionRequirementMet.value ? ComfyQueueButton : SubscribeToRunButton
)
</script>

View File

@@ -15,7 +15,7 @@
<UserCredit text-class="text-3xl font-bold" />
<Skeleton v-if="loading" width="2rem" height="2rem" />
<Button
v-else-if="isSubscribedOrIsNotCloud"
v-else-if="isSubscriptionRequirementMet"
:label="$t('credits.purchaseCredits')"
:loading="loading"
@click="handlePurchaseCreditsClick"
@@ -146,9 +146,9 @@ const authActions = useFirebaseAuthActions()
const commandStore = useCommandStore()
const telemetry = useTelemetry()
const subscription = isCloud ? useSubscription() : null
const isSubscribedOrIsNotCloud = computed(() => {
const isSubscriptionRequirementMet = computed(() => {
if (!isCloud) return true
return subscription?.isSubscribedOrIsNotCloud.value ?? false
return subscription?.isSubscriptionRequirementMet.value ?? false
})
const loading = computed(() => authStore.loading)
const balanceLoading = computed(() => authStore.isFetchingBalance)

View File

@@ -82,7 +82,7 @@ vi.mock('@/stores/firebaseAuthStore', () => ({
const mockFetchStatus = vi.fn().mockResolvedValue(undefined)
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
useSubscription: vi.fn(() => ({
isSubscribedOrIsNotCloud: { value: true },
isSubscriptionRequirementMet: { value: true },
fetchStatus: mockFetchStatus
}))
}))

View File

@@ -24,7 +24,7 @@
</div>
<div
v-if="isSubscribedOrIsNotCloud"
v-if="isSubscriptionRequirementMet"
class="flex items-center justify-between"
>
<div class="flex flex-col gap-1">
@@ -71,7 +71,7 @@
/>
<Button
v-if="isSubscribedOrIsNotCloud"
v-if="isSubscriptionRequirementMet"
class="justify-start"
:label="$t(planSettingsLabel)"
icon="pi pi-receipt"
@@ -98,7 +98,7 @@
<script setup lang="ts">
import Button from 'primevue/button'
import Divider from 'primevue/divider'
import { onMounted } from 'vue'
import { computed, onMounted } from 'vue'
import UserAvatar from '@/components/common/UserAvatar.vue'
import UserCredit from '@/components/common/UserCredit.vue'
@@ -125,7 +125,10 @@ const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } =
useCurrentUser()
const authActions = useFirebaseAuthActions()
const dialogService = useDialogService()
const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()
const subscription = isCloud ? useSubscription() : null
const isSubscriptionRequirementMet =
subscription?.isSubscriptionRequirementMet ?? computed(() => true)
const fetchStatus = subscription?.fetchStatus ?? (async () => {})
const handleOpenUserSettings = () => {
dialogService.showSettingsDialog('user')

View File

@@ -6,7 +6,6 @@ import { useErrorHandling } from '@/composables/useErrorHandling'
import type { ErrorRecoveryStrategy } from '@/composables/useErrorHandling'
import { t } from '@/i18n'
import { isCloud } from '@/platform/distribution/types'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import { useTelemetry } from '@/platform/telemetry'
import { useToastStore } from '@/platform/updates/common/toastStore'
import { useDialogService } from '@/services/dialogService'
@@ -83,8 +82,11 @@ export const useFirebaseAuthActions = () => {
const purchaseCredits = wrapWithErrorHandlingAsync(async (amount: number) => {
if (isCloud) {
const { isSubscribedOrIsNotCloud } = useSubscription()
if (!isSubscribedOrIsNotCloud.value) return
const { useSubscription } = await import(
'@/platform/cloud/subscription/composables/useSubscription'
)
const { isSubscriptionRequirementMet } = useSubscription()
if (!isSubscriptionRequirementMet.value) return
}
const response = await authStore.initiateCreditPurchase({

View File

@@ -91,7 +91,7 @@ export function useCoreCommands(): ComfyCommand[] {
const subscription = isCloud ? useSubscription() : null
const subscriptionState =
subscription?.isSubscribedOrIsNotCloud ?? defaultSubscriptionState
subscription?.isSubscriptionRequirementMet ?? defaultSubscriptionState
const subscriptionDialog = subscription?.showSubscriptionDialog ?? noop
const moveSelectedNodes = (

View File

@@ -51,7 +51,8 @@ const emit = defineEmits<{
subscribed: []
}>()
const { subscribe, isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()
const { subscribe, isSubscriptionRequirementMet, fetchStatus } =
useSubscription()
const telemetry = useTelemetry()
const isLoading = ref(false)
@@ -76,7 +77,7 @@ const startPollingSubscriptionStatus = () => {
await fetchStatus()
if (isSubscribedOrIsNotCloud.value) {
if (isSubscriptionRequirementMet.value) {
stopPolling()
telemetry?.trackMonthlySubscriptionSucceeded()
emit('subscribed')

View File

@@ -4,7 +4,7 @@
<div class="flex items-baseline gap-2">
<span class="text-2xl font-inter font-semibold leading-tight">
{{
isSubscribedOrIsNotCloud
isSubscriptionRequirementMet
? $t('subscription.title')
: $t('subscription.titleUnsubscribed')
}}
@@ -27,7 +27,7 @@
}}</span>
</div>
<div
v-if="isSubscribedOrIsNotCloud"
v-if="isSubscriptionRequirementMet"
class="text-sm text-text-secondary"
>
<template v-if="isCancelled">
@@ -47,7 +47,7 @@
</div>
</div>
<Button
v-if="isSubscribedOrIsNotCloud"
v-if="isSubscriptionRequirementMet"
:label="$t('subscription.manageSubscription')"
severity="secondary"
class="text-xs bg-interface-menu-component-surface-selected"
@@ -196,7 +196,7 @@
{{ $t('subscription.viewUsageHistory') }}
</a>
<Button
v-if="isSubscribedOrIsNotCloud"
v-if="isSubscriptionRequirementMet"
:label="$t('subscription.addCredits')"
severity="secondary"
class="p-2 min-h-8 bg-interface-menu-component-surface-selected"
@@ -320,7 +320,7 @@ import { cn } from '@/utils/tailwindUtil'
const { buildDocsUrl } = useExternalLink()
const {
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
isCancelled,
formattedRenewalDate,
formattedEndDate,

View File

@@ -31,7 +31,7 @@ function useSubscriptionInternal() {
const subscriptionStatus = ref<CloudSubscriptionStatusResponse | null>(null)
const telemetry = useTelemetry()
const isSubscribedOrIsNotCloud = computed(() => {
const isSubscriptionRequirementMet = computed(() => {
if (!isCloud || !window.__CONFIG__?.subscription_required) return true
return subscriptionStatus.value?.is_active ?? false
@@ -111,7 +111,7 @@ function useSubscriptionInternal() {
const { startCancellationWatcher, stopCancellationWatcher } =
useSubscriptionCancellationWatcher({
fetchStatus,
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
subscriptionStatus,
telemetry,
shouldWatchCancellation
@@ -125,7 +125,7 @@ function useSubscriptionInternal() {
const requireActiveSubscription = async (): Promise<void> => {
await fetchSubscriptionStatus()
if (!isSubscribedOrIsNotCloud.value) {
if (!isSubscriptionRequirementMet.value) {
showSubscriptionDialog()
}
}
@@ -223,7 +223,7 @@ function useSubscriptionInternal() {
return {
// State
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
isCancelled,
formattedRenewalDate,
formattedEndDate,

View File

@@ -36,8 +36,8 @@ export function useSubscriptionActions() {
void handleRefresh()
})
const handleAddApiCredits = () => {
dialogService.showTopUpCreditsDialog()
const handleAddApiCredits = async () => {
await dialogService.showTopUpCreditsDialog()
}
const handleMessageSupport = async () => {

View File

@@ -12,7 +12,7 @@ const CANCELLATION_BACKOFF_MULTIPLIER = 3 // 5s, 15s, 45s, 135s intervals
type CancellationWatcherOptions = {
fetchStatus: () => Promise<CloudSubscriptionStatusResponse | null | void>
isSubscribedOrIsNotCloud: ComputedRef<boolean>
isSubscriptionRequirementMet: ComputedRef<boolean>
subscriptionStatus: Ref<CloudSubscriptionStatusResponse | null>
telemetry: Pick<TelemetryProvider, 'trackMonthlySubscriptionCancelled'> | null
shouldWatchCancellation: () => boolean
@@ -20,7 +20,7 @@ type CancellationWatcherOptions = {
export function useSubscriptionCancellationWatcher({
fetchStatus,
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
subscriptionStatus,
telemetry,
shouldWatchCancellation
@@ -73,7 +73,7 @@ export function useSubscriptionCancellationWatcher({
try {
await fetchStatus()
if (!isSubscribedOrIsNotCloud.value) {
if (!isSubscriptionRequirementMet.value) {
if (!cancellationTracked.value) {
cancellationTracked.value = true
try {

View File

@@ -681,8 +681,8 @@ export class ComfyApp {
isInsufficientCredits: true
})
} else {
const { isSubscribedOrIsNotCloud } = useSubscription()
if (isSubscribedOrIsNotCloud.value) {
const { isSubscriptionRequirementMet } = useSubscription()
if (isSubscriptionRequirementMet.value) {
useDialogService().showTopUpCreditsDialog({
isInsufficientCredits: true
})

View File

@@ -17,7 +17,6 @@ import SettingDialogHeader from '@/components/dialog/header/SettingDialogHeader.
import { t } from '@/i18n'
import { useTelemetry } from '@/platform/telemetry'
import { isCloud } from '@/platform/distribution/types'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import SettingDialogContent from '@/platform/settings/components/SettingDialogContent.vue'
import type { ExecutionErrorWsMessage } from '@/schemas/apiSchema'
import { useDialogStore } from '@/stores/dialogStore'
@@ -377,12 +376,15 @@ export const useDialogService = () => {
})
}
function showTopUpCreditsDialog(options?: {
async function showTopUpCreditsDialog(options?: {
isInsufficientCredits?: boolean
}) {
if (isCloud) {
const { isSubscribedOrIsNotCloud } = useSubscription()
if (!isSubscribedOrIsNotCloud.value) return
const { useSubscription } = await import(
'@/platform/cloud/subscription/composables/useSubscription'
)
const { isSubscriptionRequirementMet } = useSubscription()
if (!isSubscriptionRequirementMet.value) return
}
return dialogStore.showDialog({

View File

@@ -100,7 +100,7 @@ vi.mock('@/composables/auth/useFirebaseAuthActions', () => ({
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
useSubscription: vi.fn(() => ({
isSubscribedOrIsNotCloud: { value: true },
isSubscriptionRequirementMet: { value: true },
showSubscriptionDialog: vi.fn()
}))
}))

View File

@@ -7,7 +7,7 @@ import SubscriptionPanel from '@/platform/cloud/subscription/components/Subscrip
// Mock composables
const mockSubscriptionData = {
isSubscribedOrIsNotCloud: false,
isSubscriptionRequirementMet: false,
isCancelled: false,
formattedRenewalDate: '2024-12-31',
formattedEndDate: '2024-12-31',
@@ -120,14 +120,14 @@ describe('SubscriptionPanel', () => {
describe('subscription state functionality', () => {
it('shows correct UI for active subscription', () => {
mockSubscriptionData.isSubscribedOrIsNotCloud = true
mockSubscriptionData.isSubscriptionRequirementMet = true
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Manage Subscription')
expect(wrapper.text()).toContain('Add Credits')
})
it('shows correct UI for inactive subscription', () => {
mockSubscriptionData.isSubscribedOrIsNotCloud = false
mockSubscriptionData.isSubscriptionRequirementMet = false
const wrapper = createWrapper()
expect(wrapper.findComponent({ name: 'SubscribeButton' }).exists()).toBe(
true
@@ -137,14 +137,14 @@ describe('SubscriptionPanel', () => {
})
it('shows renewal date for active non-cancelled subscription', () => {
mockSubscriptionData.isSubscribedOrIsNotCloud = true
mockSubscriptionData.isSubscriptionRequirementMet = true
mockSubscriptionData.isCancelled = false
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Renews 2024-12-31')
})
it('shows expiry date for cancelled subscription', () => {
mockSubscriptionData.isSubscribedOrIsNotCloud = true
mockSubscriptionData.isSubscriptionRequirementMet = true
mockSubscriptionData.isCancelled = true
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Expires 2024-12-31')

View File

@@ -92,7 +92,7 @@ describe('useSubscription', () => {
})
describe('computed properties', () => {
it('should compute isSubscribedOrIsNotCloud correctly when subscription is active', async () => {
it('should compute isSubscriptionRequirementMet correctly when subscription is active', async () => {
vi.mocked(global.fetch).mockResolvedValue({
ok: true,
json: async () => ({
@@ -103,13 +103,13 @@ describe('useSubscription', () => {
} as Response)
mockIsLoggedIn.value = true
const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()
const { isSubscriptionRequirementMet, fetchStatus } = useSubscription()
await fetchStatus()
expect(isSubscribedOrIsNotCloud.value).toBe(true)
expect(isSubscriptionRequirementMet.value).toBe(true)
})
it('should compute isSubscribedOrIsNotCloud as false when subscription is inactive', async () => {
it('should compute isSubscriptionRequirementMet as false when subscription is inactive', async () => {
vi.mocked(global.fetch).mockResolvedValue({
ok: true,
json: async () => ({
@@ -120,10 +120,10 @@ describe('useSubscription', () => {
} as Response)
mockIsLoggedIn.value = true
const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()
const { isSubscriptionRequirementMet, fetchStatus } = useSubscription()
await fetchStatus()
expect(isSubscribedOrIsNotCloud.value).toBe(false)
expect(isSubscriptionRequirementMet.value).toBe(false)
})
it('should format renewal date correctly', async () => {

View File

@@ -24,7 +24,7 @@ describe('useSubscriptionCancellationWatcher', () => {
baseStatus
)
const isActive = ref(true)
const isSubscribedOrIsNotCloud = computed(() => isActive.value)
const isSubscriptionRequirementMet = computed(() => isActive.value)
let shouldWatch = true
const shouldWatchCancellation = () => shouldWatch
@@ -76,7 +76,7 @@ describe('useSubscriptionCancellationWatcher', () => {
const { startCancellationWatcher } = initWatcher({
fetchStatus,
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
subscriptionStatus,
telemetry: telemetryMock,
shouldWatchCancellation
@@ -106,7 +106,7 @@ describe('useSubscriptionCancellationWatcher', () => {
const { startCancellationWatcher } = initWatcher({
fetchStatus,
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
subscriptionStatus,
telemetry: telemetryMock,
shouldWatchCancellation
@@ -128,7 +128,7 @@ describe('useSubscriptionCancellationWatcher', () => {
const { startCancellationWatcher } = initWatcher({
fetchStatus,
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
subscriptionStatus,
telemetry: telemetryMock,
shouldWatchCancellation
@@ -153,7 +153,7 @@ describe('useSubscriptionCancellationWatcher', () => {
const { startCancellationWatcher } = initWatcher({
fetchStatus,
isSubscribedOrIsNotCloud,
isSubscriptionRequirementMet,
subscriptionStatus,
telemetry: telemetryMock,
shouldWatchCancellation