Skip to content

Commit e7f640b

Browse files
subscription improve (#6339)
## Summary Run keyboard shortcut bypasses paywall Top Up button visible before paywall (confusing - hide until subscribed) Question mark icon next to commercial models has no tooltip (hide until added) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6339-subscription-improve-29a6d73d3650818e92c7f60eda01646a) by [Unito](https://www.unito.io) --------- Co-authored-by: bymyself <[email protected]>
1 parent 6e4471a commit e7f640b

File tree

7 files changed

+86
-15
lines changed

7 files changed

+86
-15
lines changed

src/components/topbar/CurrentUserPopover.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ vi.mock('@/services/dialogService', () => ({
6969
}))
7070
}))
7171

72+
// Mock the firebaseAuthStore
73+
vi.mock('@/stores/firebaseAuthStore', () => ({
74+
useFirebaseAuthStore: vi.fn(() => ({
75+
getAuthHeader: vi
76+
.fn()
77+
.mockResolvedValue({ Authorization: 'Bearer mock-token' })
78+
}))
79+
}))
80+
81+
// Mock the useSubscription composable
82+
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
83+
useSubscription: vi.fn(() => ({
84+
isActiveSubscription: vi.fn().mockReturnValue(true)
85+
}))
86+
}))
87+
7288
// Mock UserAvatar component
7389
vi.mock('@/components/common/UserAvatar.vue', () => ({
7490
default: {

src/components/topbar/CurrentUserPopover.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@
6767
</div>
6868
<div class="flex items-center justify-between">
6969
<UserCredit text-class="text-2xl" />
70-
<Button :label="$t('credits.topUp.topUp')" @click="handleTopUp" />
70+
<Button
71+
v-if="isActiveSubscription"
72+
:label="$t('credits.topUp.topUp')"
73+
@click="handleTopUp"
74+
/>
7175
</div>
7276
</div>
7377
</div>
@@ -82,6 +86,7 @@ import UserAvatar from '@/components/common/UserAvatar.vue'
8286
import UserCredit from '@/components/common/UserCredit.vue'
8387
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
8488
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
89+
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
8590
import { useDialogService } from '@/services/dialogService'
8691
8792
const emit = defineEmits<{
@@ -92,6 +97,7 @@ const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } =
9297
useCurrentUser()
9398
const authActions = useFirebaseAuthActions()
9499
const dialogService = useDialogService()
100+
const { isActiveSubscription } = useSubscription()
95101
96102
const handleOpenUserSettings = () => {
97103
dialogService.showSettingsDialog('user')

src/composables/useCoreCommands.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import type { Point } from '@/lib/litegraph/src/litegraph'
2222
import { useAssetBrowserDialog } from '@/platform/assets/composables/useAssetBrowserDialog'
2323
import { createModelNodeFromAsset } from '@/platform/assets/utils/createModelNodeFromAsset'
24+
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
2425
import { isCloud } from '@/platform/distribution/types'
2526
import { useSettingStore } from '@/platform/settings/settingStore'
2627
import { SUPPORT_URL } from '@/platform/support/config'
@@ -63,6 +64,8 @@ import { ManagerTab } from '@/workbench/extensions/manager/types/comfyManagerTyp
6364

6465
import { useWorkflowTemplateSelectorDialog } from './useWorkflowTemplateSelectorDialog'
6566

67+
const { isActiveSubscription, showSubscriptionDialog } = useSubscription()
68+
6669
const moveSelectedNodesVersionAdded = '1.22.2'
6770

6871
export function useCoreCommands(): ComfyCommand[] {
@@ -453,6 +456,11 @@ export function useCoreCommands(): ComfyCommand[] {
453456
versionAdded: '1.3.7',
454457
category: 'essentials' as const,
455458
function: async () => {
459+
if (!isActiveSubscription.value) {
460+
showSubscriptionDialog()
461+
return
462+
}
463+
456464
const batchCount = useQueueSettingsStore().batchCount
457465

458466
if (isCloud) {
@@ -469,6 +477,11 @@ export function useCoreCommands(): ComfyCommand[] {
469477
versionAdded: '1.3.7',
470478
category: 'essentials' as const,
471479
function: async () => {
480+
if (!isActiveSubscription.value) {
481+
showSubscriptionDialog()
482+
return
483+
}
484+
472485
const batchCount = useQueueSettingsStore().batchCount
473486

474487
if (isCloud) {
@@ -484,6 +497,11 @@ export function useCoreCommands(): ComfyCommand[] {
484497
label: 'Queue Selected Output Nodes',
485498
versionAdded: '1.19.6',
486499
function: async () => {
500+
if (!isActiveSubscription.value) {
501+
showSubscriptionDialog()
502+
return
503+
}
504+
487505
const batchCount = useQueueSettingsStore().batchCount
488506
const selectedNodes = getSelectedNodes()
489507
const selectedOutputNodes = filterOutputNodes(selectedNodes)

src/locales/en/main.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,7 @@
16401640
"beta": "BETA",
16411641
"perMonth": "USD / month",
16421642
"renewsDate": "Renews {date}",
1643+
"expiresDate": "Expires {date}",
16431644
"manageSubscription": "Manage subscription",
16441645
"apiNodesBalance": "\"API Nodes\" Credit Balance",
16451646
"apiNodesDescription": "For running commercial/proprietary models",

src/platform/cloud/subscription/components/SubscriptionPanel.vue

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,20 @@
2323
<span>{{ $t('subscription.perMonth') }}</span>
2424
</div>
2525
<div v-if="isActiveSubscription" class="text-xs text-muted">
26-
{{
27-
$t('subscription.renewsDate', {
28-
date: formattedRenewalDate
29-
})
30-
}}
26+
<template v-if="isCancelled">
27+
{{
28+
$t('subscription.expiresDate', {
29+
date: formattedEndDate
30+
})
31+
}}
32+
</template>
33+
<template v-else>
34+
{{
35+
$t('subscription.renewsDate', {
36+
date: formattedRenewalDate
37+
})
38+
}}
39+
</template>
3140
</div>
3241
</div>
3342
<Button
@@ -58,14 +67,6 @@
5867
<div class="text-xs text-muted">
5968
{{ $t('subscription.apiNodesDescription') }}
6069
</div>
61-
<Button
62-
icon="pi pi-question-circle"
63-
text
64-
rounded
65-
size="small"
66-
severity="secondary"
67-
class="h-5 w-5"
68-
/>
6970
</div>
7071
</div>
7172

@@ -137,6 +138,7 @@
137138
@click="handleViewUsageHistory"
138139
/>
139140
<Button
141+
v-if="isActiveSubscription"
140142
:label="$t('subscription.addApiCredits')"
141143
severity="secondary"
142144
class="text-xs"
@@ -219,7 +221,9 @@ const customerEventService = useCustomerEventsService()
219221
220222
const {
221223
isActiveSubscription,
224+
isCancelled,
222225
formattedRenewalDate,
226+
formattedEndDate,
223227
formattedMonthlyPrice,
224228
manageSubscription,
225229
handleViewUsageHistory,

src/platform/cloud/subscription/composables/useSubscription.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ interface CloudSubscriptionCheckoutResponse {
2121
interface CloudSubscriptionStatusResponse {
2222
is_active: boolean
2323
subscription_id: string
24-
renewal_date: string
24+
renewal_date: string | null
25+
end_date?: string | null
2526
}
2627

2728
const subscriptionStatus = ref<CloudSubscriptionStatusResponse | null>(null)
@@ -44,6 +45,10 @@ export function useSubscription() {
4445

4546
const { isLoggedIn } = useCurrentUser()
4647

48+
const isCancelled = computed(() => {
49+
return !!subscriptionStatus.value?.end_date
50+
})
51+
4752
const formattedRenewalDate = computed(() => {
4853
if (!subscriptionStatus.value?.renewal_date) return ''
4954

@@ -56,6 +61,18 @@ export function useSubscription() {
5661
})
5762
})
5863

64+
const formattedEndDate = computed(() => {
65+
if (!subscriptionStatus.value?.end_date) return ''
66+
67+
const endDate = new Date(subscriptionStatus.value.end_date)
68+
69+
return endDate.toLocaleDateString('en-US', {
70+
month: 'short',
71+
day: 'numeric',
72+
year: 'numeric'
73+
})
74+
})
75+
5976
const formattedMonthlyPrice = computed(
6077
() => `$${MONTHLY_SUBSCRIPTION_PRICE.toFixed(0)}`
6178
)
@@ -197,7 +214,9 @@ export function useSubscription() {
197214
return {
198215
// State
199216
isActiveSubscription,
217+
isCancelled,
200218
formattedRenewalDate,
219+
formattedEndDate,
201220
formattedMonthlyPrice,
202221

203222
// Actions

tests-ui/tests/composables/useCoreCommands.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ vi.mock('@/composables/auth/useFirebaseAuthActions', () => ({
8585
useFirebaseAuthActions: vi.fn(() => ({}))
8686
}))
8787

88+
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
89+
useSubscription: vi.fn(() => ({
90+
isActiveSubscription: vi.fn().mockReturnValue(true),
91+
showSubscriptionDialog: vi.fn()
92+
}))
93+
}))
94+
8895
describe('useCoreCommands', () => {
8996
const mockSubgraph = {
9097
nodes: [

0 commit comments

Comments
 (0)