feat(stage): hide flux purchase UI for Steam builds via VITE_DISABLE_FLUX_PURCHASE (#1912)

This commit is contained in:
Lulu
2026-06-08 13:51:10 +08:00
committed by GitHub
parent d91dab7bf0
commit 0647f5b37a
7 changed files with 47 additions and 23 deletions
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { isStageTamagotchi } from '@proj-airi/stage-shared'
import { isFluxPurchaseDisabled, isStageTamagotchi } from '@proj-airi/stage-shared'
import { client } from '@proj-airi/stage-ui/composables/api'
import { useAnalytics } from '@proj-airi/stage-ui/composables/use-analytics'
import { useAuthStore } from '@proj-airi/stage-ui/stores/auth'
@@ -17,6 +17,8 @@ const authStore = useAuthStore()
const { credits } = storeToRefs(authStore)
const { trackPricingViewed, trackPlanSelected, trackCheckoutStarted } = useAnalytics()
const fluxPurchaseDisabled = isFluxPurchaseDisabled()
// On desktop, checkout happens in the external system browser (see handleBuy), so
// the app never receives the success_url redirect that web/mobile use to refresh.
// Re-pull the FLUX balance whenever the window regains focus; the balance source
@@ -230,13 +232,15 @@ async function fetchPackages() {
}
onMounted(async () => {
Promise.allSettled([fetchPackages(), authStore.updateCredits(), fetchStats(), fetchAuditHistory()])
Promise.allSettled([authStore.updateCredits(), fetchStats(), fetchAuditHistory(), ...(fluxPurchaseDisabled ? [] : [fetchPackages()])])
// PostHog funnel step 1: pricing surface view. Today this is an in-app
// settings page (already-authenticated users); when we add a public
// pricing landing page the surface label changes but the event stays the
// same, so the funnel definition in PostHog doesn't need re-wiring.
trackPricingViewed('settings_flux', 'one_time')
if (!fluxPurchaseDisabled) {
trackPricingViewed('settings_flux', 'one_time')
}
if (route.query.success === 'true') {
message.value = { type: 'success', text: t('settings.pages.flux.checkout.success') }
@@ -316,13 +320,13 @@ async function handleBuy(stripePriceId: string) {
{{ formatNumber(credits) }}
</h2>
<p text="sm neutral-500">
{{ t('settings.pages.flux.description') }}
{{ t(fluxPurchaseDisabled ? 'settings.pages.account.fluxBalance' : 'settings.pages.flux.description') }}
</p>
</div>
</div>
</div>
<div flex="~ col gap-4">
<div v-if="!fluxPurchaseDisabled" flex="~ col gap-4">
<!-- Currency selector -->
<div v-if="currencyOptions.length > 1" flex="~ justify-start sm:justify-end">
<SelectTab
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { isFluxPurchaseDisabled } from '@proj-airi/stage-shared'
import {
ProviderSettingsContainer,
ProviderSettingsLayout,
@@ -18,6 +19,7 @@ const { isAuthenticated, credits, needsLogin } = storeToRefs(authStore)
const providerId = 'official-provider'
const providerMetadata = providersStore.getProviderMetadata(providerId)
const fluxPurchaseDisabled = isFluxPurchaseDisabled()
function handleLogin() {
needsLogin.value = true
@@ -62,6 +64,7 @@ function handleLogin() {
</span>
</div>
<button
v-if="!fluxPurchaseDisabled"
type="button"
class="rounded-full bg-primary-500/10 px-6 py-2 text-sm text-primary-600 font-semibold transition-all dark:bg-primary-400/10 hover:bg-primary-500 dark:text-primary-400 hover:text-white dark:hover:bg-primary-400 dark:hover:text-neutral-900"
@click="router.push('/settings/flux')"
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { isFluxPurchaseDisabled } from '@proj-airi/stage-shared'
import {
ProviderSettingsContainer,
ProviderSettingsLayout,
@@ -23,6 +24,7 @@ const { isAuthenticated, credits, needsLogin } = storeToRefs(authStore)
const providerId = 'official-provider-speech-streaming'
const providerMetadata = computed(() => providersStore.getProviderMetadata(providerId))
const fluxPurchaseDisabled = isFluxPurchaseDisabled()
const providerConfig = computed(() => providersStore.getProviderConfig(providerId))
@@ -149,6 +151,7 @@ function handleLogin() {
</span>
</div>
<button
v-if="!fluxPurchaseDisabled"
type="button"
class="rounded-full bg-primary-500/10 px-6 py-2 text-sm text-primary-600 font-semibold transition-all dark:bg-primary-400/10 hover:bg-primary-500 dark:text-primary-400 hover:text-white dark:hover:bg-primary-400 dark:hover:text-neutral-900"
@click="router.push('/settings/flux')"
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { isFluxPurchaseDisabled } from '@proj-airi/stage-shared'
import {
ProviderSettingsContainer,
ProviderSettingsLayout,
@@ -18,6 +19,7 @@ const { isAuthenticated, credits, needsLogin } = storeToRefs(authStore)
const providerId = 'official-provider-speech'
const providerMetadata = providersStore.getProviderMetadata(providerId)
const fluxPurchaseDisabled = isFluxPurchaseDisabled()
function handleLogin() {
needsLogin.value = true
@@ -62,6 +64,7 @@ function handleLogin() {
</span>
</div>
<button
v-if="!fluxPurchaseDisabled"
type="button"
class="rounded-full bg-primary-500/10 px-6 py-2 text-sm text-primary-600 font-semibold transition-all dark:bg-primary-400/10 hover:bg-primary-500 dark:text-primary-400 hover:text-white dark:hover:bg-primary-400 dark:hover:text-neutral-900"
@click="router.push('/settings/flux')"
+4
View File
@@ -8,3 +8,7 @@ export function isEnvTruthy(value: string | undefined | null): boolean {
return false
return /^(?:1|true|t|yes|y|on)$/i.test(value.trim())
}
export function isFluxPurchaseDisabled(): boolean {
return isEnvTruthy(import.meta.env.VITE_DISABLE_FLUX_PURCHASE)
}
@@ -1,3 +1,5 @@
import { isFluxPurchaseDisabled } from '@proj-airi/stage-shared'
import factorioPoster from '../../../assets/factorio-simple.png'
import onboardingPoster from '../../../assets/onboarding.avif'
@@ -49,24 +51,28 @@ export const promoBannerVisuals: PromoBannerVisual[] = [
fallbackIconClass: 'text-cyan-100',
fallbackClass: 'from-cyan-300/25 via-sky-300/14 to-blue-400/20',
},
{
key: 'spring',
image: '',
action: { type: 'route', to: '/settings/flux' },
accentClass: 'from-amber-400/30 via-orange-300/18 to-transparent',
fallbackIcon: 'i-solar:gift-bold-duotone',
fallbackIconClass: 'text-white/88',
fallbackClass: 'from-amber-300/25 via-rose-300/14 to-fuchsia-400/20',
},
{
key: 'coupon',
image: '',
action: { type: 'route', to: '/settings/flux' },
accentClass: 'from-emerald-400/28 via-teal-300/16 to-transparent',
fallbackIcon: 'i-solar:ticket-sale-bold-duotone',
fallbackIconClass: 'text-emerald-100',
fallbackClass: 'from-emerald-300/24 via-cyan-300/12 to-teal-400/18',
},
...(isFluxPurchaseDisabled()
? []
: [
{
key: 'spring',
image: '',
action: { type: 'route', to: '/settings/flux' },
accentClass: 'from-amber-400/30 via-orange-300/18 to-transparent',
fallbackIcon: 'i-solar:gift-bold-duotone',
fallbackIconClass: 'text-white/88',
fallbackClass: 'from-amber-300/25 via-rose-300/14 to-fuchsia-400/20',
},
{
key: 'coupon',
image: '',
action: { type: 'route', to: '/settings/flux' },
accentClass: 'from-emerald-400/28 via-teal-300/16 to-transparent',
fallbackIcon: 'i-solar:ticket-sale-bold-duotone',
fallbackIconClass: 'text-emerald-100',
fallbackClass: 'from-emerald-300/24 via-cyan-300/12 to-teal-400/18',
},
] satisfies PromoBannerVisual[]),
{
key: 'home',
image: '',
+1
View File
@@ -1,6 +1,7 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_DISABLE_FLUX_PURCHASE?: string
readonly VITE_ENABLE_POSTHOG?: string
readonly VITE_POSTHOG_PROJECT_KEY_WEB?: string
readonly VITE_POSTHOG_PROJECT_KEY_DESKTOP?: string