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:
Terry Jia
2025-10-18 23:21:30 -04:00
committed by GitHub
parent d83e34d0fc
commit 7e1e8e3b65
22 changed files with 1232 additions and 14 deletions

View File

@@ -0,0 +1,76 @@
<template>
<div class="grid h-full grid-cols-5 px-10 pb-10">
<div
class="relative col-span-2 flex items-center justify-center overflow-hidden rounded-sm"
>
<video
autoplay
loop
muted
playsinline
class="h-full min-w-[125%] object-cover"
style="margin-left: -20%"
>
<source
src="/assets/images/cloud-subscription.webm"
type="video/webm"
/>
</video>
</div>
<div class="col-span-3 flex flex-col justify-between pl-8">
<div>
<div class="flex flex-col gap-4">
<div class="inline-flex items-center gap-2">
<div class="text-sm text-muted">
{{ $t('subscription.required.title') }}
</div>
<TopbarBadges
reverse-order
no-padding
text-class="!text-sm !font-normal"
/>
</div>
<div class="flex items-baseline gap-2">
<span class="text-4xl font-bold">{{ formattedMonthlyPrice }}</span>
<span class="text-xl">{{ $t('subscription.perMonth') }}</span>
</div>
</div>
<SubscriptionBenefits class="mt-6 text-muted" />
</div>
<div class="flex flex-col">
<SubscribeButton @subscribed="handleSubscribed" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import TopbarBadges from '@/components/topbar/TopbarBadges.vue'
import SubscribeButton from '@/platform/cloud/subscription/components/SubscribeButton.vue'
import SubscriptionBenefits from '@/platform/cloud/subscription/components/SubscriptionBenefits.vue'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
const emit = defineEmits<{
close: [subscribed: boolean]
}>()
const { formattedMonthlyPrice } = useSubscription()
const handleSubscribed = () => {
emit('close', true)
}
</script>
<style scoped>
:deep(.bg-comfy-menu-secondary) {
background-color: transparent;
}
:deep(.p-button) {
color: white;
}
</style>