mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
subscription page (#6064)
Summary Implements cloud subscription management UI and flow for ComfyUI Cloud users. Core Features: - Subscription Status Tracking: Global reactive state management for subscription status across all components using shared subscriptionStatus ref - Subscribe to Run Button: Replaces the Run button in the actionbar with a "Subscribe to Run" button for users without active subscriptions - Subscription Required Dialog: Modal dialog with subscription benefits, pricing, and checkout flow with video background - Subscription Settings Panel: New settings panel showing subscription status, renewal date, and quick access to billing management - Auto-detection & Polling: Automatically polls subscription status after checkout completion and syncs state across the application https://github.com/user-attachments/assets/f41b8e6a-5845-48a7-8169-3a6fc0d2e5c8 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6064-subscription-page-28d6d73d36508135a2a0fe7c94b40852) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<Button
|
||||
:label="label || $t('subscription.required.subscribe')"
|
||||
:size="size"
|
||||
:class="buttonClass"
|
||||
:loading="isLoading"
|
||||
:disabled="isPolling"
|
||||
severity="primary"
|
||||
@click="handleSubscribe"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from 'primevue/button'
|
||||
import { onBeforeUnmount, ref } from 'vue'
|
||||
|
||||
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
label?: string
|
||||
size?: 'small' | 'large'
|
||||
buttonClass?: string
|
||||
}>(),
|
||||
{
|
||||
size: 'large',
|
||||
buttonClass: 'w-full font-bold'
|
||||
}
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
subscribed: []
|
||||
}>()
|
||||
|
||||
const { subscribe, isActiveSubscription, fetchStatus } = useSubscription()
|
||||
|
||||
const isLoading = ref(false)
|
||||
const isPolling = ref(false)
|
||||
let pollInterval: number | null = null
|
||||
|
||||
const POLL_INTERVAL_MS = 3000 // Poll every 3 seconds
|
||||
const MAX_POLL_DURATION_MS = 5 * 60 * 1000 // Stop polling after 5 minutes
|
||||
|
||||
const startPollingSubscriptionStatus = () => {
|
||||
isPolling.value = true
|
||||
isLoading.value = true
|
||||
|
||||
const startTime = Date.now()
|
||||
|
||||
const poll = async () => {
|
||||
try {
|
||||
if (Date.now() - startTime > MAX_POLL_DURATION_MS) {
|
||||
stopPolling()
|
||||
return
|
||||
}
|
||||
|
||||
await fetchStatus()
|
||||
|
||||
if (isActiveSubscription.value) {
|
||||
stopPolling()
|
||||
emit('subscribed')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'[SubscribeButton] Error polling subscription status:',
|
||||
error
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
void poll()
|
||||
pollInterval = window.setInterval(poll, POLL_INTERVAL_MS)
|
||||
}
|
||||
|
||||
const stopPolling = () => {
|
||||
if (pollInterval) {
|
||||
clearInterval(pollInterval)
|
||||
pollInterval = null
|
||||
}
|
||||
isPolling.value = false
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
const handleSubscribe = async () => {
|
||||
isLoading.value = true
|
||||
try {
|
||||
await subscribe()
|
||||
|
||||
startPollingSubscriptionStatus()
|
||||
} catch (error) {
|
||||
console.error('[SubscribeButton] Error initiating subscription:', error)
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stopPolling()
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user