diff --git a/src/composables/useFeatureFlags.ts b/src/composables/useFeatureFlags.ts index bb493385dd..07b82ff40c 100644 --- a/src/composables/useFeatureFlags.ts +++ b/src/composables/useFeatureFlags.ts @@ -13,7 +13,8 @@ export enum ServerFeatureFlag { MODEL_UPLOAD_BUTTON_ENABLED = 'model_upload_button_enabled', ASSET_UPDATE_OPTIONS_ENABLED = 'asset_update_options_enabled', PRIVATE_MODELS_ENABLED = 'private_models_enabled', - SUBSCRIPTION_TIERS_ENABLED = 'subscription_tiers_enabled' + SUBSCRIPTION_TIERS_ENABLED = 'subscription_tiers_enabled', + ONBOARDING_SURVEY_ENABLED = 'onboarding_survey_enabled' } /** @@ -66,6 +67,12 @@ export function useFeatureFlags() { true // Default to true (new design) ) ) + }, + get onboardingSurveyEnabled() { + return ( + remoteConfig.value.onboarding_survey_enabled ?? + api.getServerFeature(ServerFeatureFlag.ONBOARDING_SURVEY_ENABLED, true) + ) } }) diff --git a/src/platform/cloud/onboarding/CloudSurveyView.vue b/src/platform/cloud/onboarding/CloudSurveyView.vue index 3de6c5a8d1..7d8a983ac3 100644 --- a/src/platform/cloud/onboarding/CloudSurveyView.vue +++ b/src/platform/cloud/onboarding/CloudSurveyView.vue @@ -225,6 +225,7 @@ import { computed, onMounted, ref } from 'vue' import { useI18n } from 'vue-i18n' import { useRouter } from 'vue-router' +import { useFeatureFlags } from '@/composables/useFeatureFlags' import { getSurveyCompletedStatus, submitSurvey @@ -234,14 +235,20 @@ import { useTelemetry } from '@/platform/telemetry' const { t } = useI18n() const router = useRouter() +const { flags } = useFeatureFlags() +const onboardingSurveyEnabled = computed(() => flags.onboardingSurveyEnabled) // Check if survey is already completed on mount onMounted(async () => { + if (!onboardingSurveyEnabled.value) { + await router.replace({ name: 'cloud-user-check' }) + return + } try { const surveyCompleted = await getSurveyCompletedStatus() if (surveyCompleted) { - // User already completed survey, redirect to waitlist - await router.replace({ name: 'cloud-waitlist' }) + // User already completed survey, return to onboarding flow + await router.replace({ name: 'cloud-user-check' }) } else { // Track survey opened event if (isCloud) { @@ -342,6 +349,10 @@ const goTo = (step: number, activate: (val: string | number) => void) => { // Submit const onSubmitSurvey = async () => { try { + if (!onboardingSurveyEnabled.value) { + await router.replace({ name: 'cloud-user-check' }) + return + } isSubmitting.value = true // prepare payload with consistent structure const payload = { diff --git a/src/platform/cloud/onboarding/UserCheckView.vue b/src/platform/cloud/onboarding/UserCheckView.vue index 1260327280..30cac201ad 100644 --- a/src/platform/cloud/onboarding/UserCheckView.vue +++ b/src/platform/cloud/onboarding/UserCheckView.vue @@ -30,6 +30,7 @@ import { computed, nextTick, ref } from 'vue' import { useRouter } from 'vue-router' import { useErrorHandling } from '@/composables/useErrorHandling' +import { useFeatureFlags } from '@/composables/useFeatureFlags' import { getSurveyCompletedStatus, getUserCloudStatus @@ -40,6 +41,10 @@ import CloudSurveyViewSkeleton from './skeletons/CloudSurveyViewSkeleton.vue' const router = useRouter() const { wrapWithErrorHandlingAsync } = useErrorHandling() +const { flags } = useFeatureFlags() +const onboardingSurveyEnabled = computed( + () => flags.onboardingSurveyEnabled ?? true +) const skeletonType = ref<'login' | 'survey' | 'waitlist' | 'loading'>('loading') @@ -51,6 +56,11 @@ const { wrapWithErrorHandlingAsync(async () => { await nextTick() + if (!onboardingSurveyEnabled.value) { + await router.replace({ path: '/' }) + return + } + const [cloudUserStats, surveyStatus] = await Promise.all([ getUserCloudStatus(), getSurveyCompletedStatus() @@ -63,7 +73,7 @@ const { return } - // Survey is required for all users + // Survey is required for all users when feature flag is enabled if (!surveyStatus) { skeletonType.value = 'survey' await router.replace({ name: 'cloud-survey' }) diff --git a/src/platform/remoteConfig/types.ts b/src/platform/remoteConfig/types.ts index 1faf919e4c..4ac7d28318 100644 --- a/src/platform/remoteConfig/types.ts +++ b/src/platform/remoteConfig/types.ts @@ -38,6 +38,7 @@ export type RemoteConfig = { asset_update_options_enabled?: boolean private_models_enabled?: boolean subscription_tiers_enabled?: boolean + onboarding_survey_enabled?: boolean stripe_publishable_key?: string stripe_pricing_table_id?: string } diff --git a/src/router.ts b/src/router.ts index 59a691322f..5ca66c9535 100644 --- a/src/router.ts +++ b/src/router.ts @@ -7,6 +7,7 @@ import { } from 'vue-router' import type { RouteLocationNormalized } from 'vue-router' +import { useFeatureFlags } from '@/composables/useFeatureFlags' import { isCloud } from '@/platform/distribution/types' import { useDialogService } from '@/services/dialogService' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' @@ -89,6 +90,7 @@ installPreservedQueryTracker(router, [ ]) if (isCloud) { + const { flags } = useFeatureFlags() const PUBLIC_ROUTE_NAMES = new Set([ 'cloud-login', 'cloud-signup', @@ -165,9 +167,12 @@ if (isCloud) { return next({ name: 'cloud-login' }) } - // User is logged in - check if they need onboarding + // User is logged in - check if they need onboarding (when enabled) // For root path, check actual user status to handle waitlisted users if (!isElectron() && isLoggedIn && to.path === '/') { + if (!flags.onboardingSurveyEnabled) { + return next() + } // Import auth functions dynamically to avoid circular dependency const { getSurveyCompletedStatus } = await import('@/platform/cloud/onboarding/auth') @@ -175,7 +180,7 @@ if (isCloud) { // Check user's actual status const surveyCompleted = await getSurveyCompletedStatus() - // Survey is required for all users regardless of whitelist status + // Survey is required for all users (when feature flag enabled) if (!surveyCompleted) { return next({ name: 'cloud-survey' }) }