From 7a0de45482dba225a829f58e105879731d9ccd4b Mon Sep 17 00:00:00 2001 From: jjbrunton Date: Fri, 28 Aug 2026 14:36:33 +0100 Subject: [PATCH] feat(mobile): align store-safe experience Remove client-side adult-content preferences and badges so the centrally reviewed catalogue is the single visibility boundary.\n\nUse neutral relationship-focused copy across onboarding, discovery, paywall, and login surfaces, and retain biometric controls under App Lock for both native platforms. --- apps/mobile/app/(app)/dares.tsx | 2 +- apps/mobile/app/(app)/onboarding.tsx | 149 ++---------------- apps/mobile/app/(app)/quiz.tsx | 4 +- apps/mobile/app/(auth)/login.tsx | 2 +- apps/mobile/app/pack/[id].tsx | 25 --- .../src/__tests__/stores/packsStore.test.ts | 17 +- .../src/components/BoutiquePackCard.tsx | 30 ---- .../src/components/discovery/ContentTile.tsx | 20 --- .../mobile/src/components/paywall/Paywall.tsx | 4 +- .../components/tutorials/MatchesTutorial.tsx | 2 +- .../ui/IntensitySlider/constants.ts | 12 +- .../src/features/profile/ProfileScreen.tsx | 6 +- .../profile/components/PrivacySettings.tsx | 58 +++---- .../profile/hooks/useProfileSettings.ts | 54 +------ .../profile/screens/PreferencesScreen.tsx | 9 +- .../swipe/components/SwipeNoPacksState.tsx | 2 +- .../swipe/components/SwipeNoPartnerState.tsx | 4 +- apps/mobile/src/store/packsStore.ts | 36 +---- 18 files changed, 68 insertions(+), 368 deletions(-) diff --git a/apps/mobile/app/(app)/dares.tsx b/apps/mobile/app/(app)/dares.tsx index 447535a..f182163 100644 --- a/apps/mobile/app/(app)/dares.tsx +++ b/apps/mobile/app/(app)/dares.tsx @@ -54,7 +54,7 @@ export default function DaresScreen() { {/* Description */} - Push your boundaries together with tantalising challenges designed to ignite passion and create unforgettable moments. + Try playful challenges together and create unforgettable moments. {/* Feature hints */} diff --git a/apps/mobile/app/(app)/onboarding.tsx b/apps/mobile/app/(app)/onboarding.tsx index 6bcd0f9..0c3a471 100644 --- a/apps/mobile/app/(app)/onboarding.tsx +++ b/apps/mobile/app/(app)/onboarding.tsx @@ -24,7 +24,6 @@ import Animated, { import { GradientBackground } from '../../src/components/ui/GradientBackground'; import { GlassCard } from '../../src/components/ui/GlassCard'; import { GlassButton } from '../../src/components/ui/GlassButton'; -import { GlassToggle } from '../../src/components/ui/GlassToggle'; import { Paywall } from '../../src/components/paywall'; import { colors, gradients, spacing, typography, radius, shadows } from '../../src/theme'; import { useAuthStore } from '../../src/store'; @@ -44,23 +43,17 @@ const GENDER_OPTIONS: { value: Gender; label: string; icon: string }[] = [ { value: 'prefer-not-to-say', label: 'Skip', icon: 'remove-circle-outline' }, ]; -type UsageReason = 'improve_communication' | 'spice_up_intimacy' | 'deeper_connection' | 'have_fun' | 'strengthen_relationship'; +type UsageReason = 'improve_communication' | 'reconnect' | 'deeper_connection' | 'have_fun' | 'strengthen_relationship'; const PURPOSE_OPTIONS: { value: UsageReason; label: string; icon: string }[] = [ { value: 'improve_communication', label: 'Improve communication', icon: 'chatbubbles' }, - { value: 'spice_up_intimacy', label: 'Spice up intimacy', icon: 'flame' }, + { value: 'reconnect', label: 'Feel more connected', icon: 'flame' }, { value: 'deeper_connection', label: 'Build deeper connection', icon: 'heart' }, { value: 'have_fun', label: 'Have fun together', icon: 'happy' }, { value: 'strengthen_relationship', label: 'Strengthen our relationship', icon: 'shield-checkmark' }, ]; -// Intensity thresholds for backwards compatibility -// When hide_nsfw=true, max_intensity=2 (mild content only) -// When hide_nsfw=false, max_intensity=5 (all content) -const NSFW_OFF_INTENSITY = 2; -const NSFW_ON_INTENSITY = 5; - -type Stage = 'avatar' | 'name' | 'gender' | 'purpose' | 'content' | 'notifications'; +type Stage = 'avatar' | 'name' | 'gender' | 'purpose' | 'notifications'; export default function OnboardingScreen() { const router = useRouter(); @@ -72,7 +65,6 @@ export default function OnboardingScreen() { const [name, setName] = useState(initialUser.current?.name || ''); const [gender, setGender] = useState(initialUser.current?.gender || null); const [usageReason, setUsageReason] = useState(null); - const [hideNsfw, setHideNsfw] = useState(initialUser.current?.hide_nsfw ?? false); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [showPaywall, setShowPaywall] = useState(false); @@ -137,14 +129,9 @@ export default function OnboardingScreen() { setError('Please select what brings you to Sauci'); return; } - setStage('content'); - Events.onboardingStageComplete('purpose'); - }; - - const handleContentContinue = () => { - setStage('notifications'); - Events.onboardingStageComplete('content'); - }; + setStage('notifications'); + Events.onboardingStageComplete('purpose'); + }; const handleEnableNotifications = async () => { setIsLoading(true); @@ -182,18 +169,17 @@ export default function OnboardingScreen() { } } - // Derive intensity from hide_nsfw for backwards compatibility - const maxIntensity = hideNsfw ? NSFW_OFF_INTENSITY : NSFW_ON_INTENSITY; - const showExplicitContent = !hideNsfw; - const updatedFields: string[] = ["name", "gender", "usage_reason", "max_intensity", "show_explicit_content", "hide_nsfw"]; + const updatedFields: string[] = ["name", "gender", "usage_reason"]; const updateData: Record = { name: name.trim(), gender, usage_reason: usageReason, - max_intensity: maxIntensity, - show_explicit_content: showExplicitContent, - hide_nsfw: hideNsfw, + // Preserve the safest legacy profile values. Catalogue + // eligibility is enforced centrally by reviewed status. + max_intensity: 2, + show_explicit_content: false, + hide_nsfw: true, onboarding_completed: true, onboarding_version: REQUIRED_ONBOARDING_VERSION, updated_at: new Date().toISOString(), @@ -505,73 +491,6 @@ export default function OnboardingScreen() { ); - case 'content': - return ( - - - - - - Content Preferences - - Choose what type of content you'd like to see - - - - - - - - - - - Hide Adult Content - - Only show mild, family-friendly question packs - - - - - - - - You can change this anytime in settings - - - {error && ( - - - {error} - - )} - - - - - Continue - - - - ); - case 'notifications': return ( { setError(null); - if (stage === 'notifications') setStage('content'); - else if (stage === 'content') setStage('purpose'); + if (stage === 'notifications') setStage('purpose'); else if (stage === 'purpose') setStage('gender'); else if (stage === 'gender') setStage('name'); else if (stage === 'name') setStage('avatar'); @@ -677,8 +595,7 @@ export default function OnboardingScreen() { - - + @@ -954,44 +871,6 @@ const styles = StyleSheet.create({ color: colors.text, fontWeight: '600', }, - contentToggleRow: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - }, - contentToggleLeft: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - marginRight: spacing.md, - }, - contentToggleIcon: { - width: 48, - height: 48, - borderRadius: 24, - alignItems: 'center', - justifyContent: 'center', - marginRight: spacing.md, - }, - contentToggleText: { - flex: 1, - }, - contentToggleLabel: { - ...typography.headline, - color: colors.text, - }, - contentToggleDescription: { - ...typography.caption1, - color: colors.textSecondary, - marginTop: 2, - }, - contentNote: { - ...typography.caption1, - color: colors.textSecondary, - textAlign: 'center', - marginTop: spacing.lg, - }, - radioOuterSelected: { borderColor: colors.primary, }, diff --git a/apps/mobile/app/(app)/quiz.tsx b/apps/mobile/app/(app)/quiz.tsx index 5cf76e5..0111677 100644 --- a/apps/mobile/app/(app)/quiz.tsx +++ b/apps/mobile/app/(app)/quiz.tsx @@ -34,7 +34,7 @@ export default function QuizScreen() { style={styles.content} > {/* Title section */} - INTIMACY + CONNECTION Quiz {/* Decorative separator */} @@ -61,7 +61,7 @@ export default function QuizScreen() { - Uncover hidden desires + Learn what makes each other tick diff --git a/apps/mobile/app/(auth)/login.tsx b/apps/mobile/app/(auth)/login.tsx index e765fa7..b8c2be0 100755 --- a/apps/mobile/app/(auth)/login.tsx +++ b/apps/mobile/app/(auth)/login.tsx @@ -489,7 +489,7 @@ export default function LoginScreen() { /> Sauci - Explore intimacy together + Grow closer together diff --git a/apps/mobile/app/pack/[id].tsx b/apps/mobile/app/pack/[id].tsx index 96259c0..b4acc48 100644 --- a/apps/mobile/app/pack/[id].tsx +++ b/apps/mobile/app/pack/[id].tsx @@ -242,14 +242,6 @@ export default function PackDetailsScreen() { {category ? category.name.toUpperCase() : 'PREVIEW'} - {/* Explicit badge */} - {pack?.is_explicit && ( - - - 18+ EXPLICIT - - )} - {/* Icon with enhanced glow for premium */} {pack?.is_premium && ( @@ -591,23 +583,6 @@ const styles = StyleSheet.create({ labelPremium: { color: colors.premium.gold, }, - explicitBadge: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: colors.error, - paddingHorizontal: spacing.md, - paddingVertical: spacing.xs, - borderRadius: radius.full, - gap: spacing.xs, - marginBottom: spacing.md, - }, - explicitBadgeText: { - ...typography.caption2, - fontWeight: '700', - color: colors.text, - letterSpacing: 1, - }, - // Removed glow styles iconGlowOuter: { display: 'none', diff --git a/apps/mobile/src/__tests__/stores/packsStore.test.ts b/apps/mobile/src/__tests__/stores/packsStore.test.ts index 0b70786..54a1abc 100644 --- a/apps/mobile/src/__tests__/stores/packsStore.test.ts +++ b/apps/mobile/src/__tests__/stores/packsStore.test.ts @@ -18,15 +18,12 @@ describe('packsStore', () => { beforeEach(() => { jest.clearAllMocks(); usePacksStore.setState({ packs: [], categories: [], enabledPackIds: [], packProgress: new Map(), isLoading: false } as any); - useAuthStore.setState({ user: { id: 'me', couple_id: 'c1', hide_nsfw: false } } as any); + useAuthStore.setState({ user: { id: 'me', couple_id: 'c1' } } as any); }); - it('fetches categories/packs and filters by hide_nsfw', async () => { - // Set hide_nsfw to true - should filter intensity to max 2 - useAuthStore.setState({ user: { id: 'me', couple_id: 'c1', hide_nsfw: true } } as any); - + it('fetches the centrally reviewed public catalogue', async () => { const categoriesQuery = createThenableQuery({ data: [{ id: 'cat1' }] }); - const packsQuery = createThenableQuery({ data: [{ id: 'pack1', is_explicit: false }] }); + const packsQuery = createThenableQuery({ data: [{ id: 'pack1' }] }); const enabledQuery = createThenableQuery({ data: [{ pack_id: 'pack1' }] }); const responsesQuery = createThenableQuery({ data: [] }); @@ -38,14 +35,12 @@ describe('packsStore', () => { await usePacksStore.getState().fetchPacks(); - // When hide_nsfw=true, max_intensity=2, so or filter is called - expect(packsQuery.or).toHaveBeenCalledWith('max_intensity.is.null,max_intensity.lte.2'); - // When hide_nsfw=true, explicit packs are filtered out - expect(packsQuery.eq).toHaveBeenCalledWith('is_explicit', false); + expect(packsQuery.eq).toHaveBeenCalledWith('is_public', true); + expect(packsQuery.or).not.toHaveBeenCalled(); const state = usePacksStore.getState(); expect(state.categories).toEqual([{ id: 'cat1' }]); - expect(state.packs).toEqual([{ id: 'pack1', is_explicit: false }]); + expect(state.packs).toEqual([{ id: 'pack1' }]); expect(state.enabledPackIds).toEqual(['pack1']); expect(state.isLoading).toBe(false); }); diff --git a/apps/mobile/src/components/BoutiquePackCard.tsx b/apps/mobile/src/components/BoutiquePackCard.tsx index 03d3674..c8a037e 100644 --- a/apps/mobile/src/components/BoutiquePackCard.tsx +++ b/apps/mobile/src/components/BoutiquePackCard.tsx @@ -92,18 +92,6 @@ export function BoutiquePackCard({ {/* Content */} - {/* Explicit Badge (top-left) */} - {pack.is_explicit && ( - - - 18+ - - )} - {/* PRO Badge (top-right) */} {pack.is_premium && ( - {pack.is_explicit && ( - - - 18+ - - )} {isNew && ( NEW @@ -129,20 +123,6 @@ const styles = StyleSheet.create({ flexDirection: 'row', gap: spacing.xs, }, - explicitBadge: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: colors.error, - paddingHorizontal: spacing.sm, - paddingVertical: 2, - borderRadius: radius.xs, - gap: 2, - }, - explicitBadgeText: { - ...typography.caption2, - fontWeight: '700', - color: colors.text, - }, newBadge: { backgroundColor: 'rgba(255, 255, 255, 0.95)', paddingHorizontal: spacing.sm, diff --git a/apps/mobile/src/components/paywall/Paywall.tsx b/apps/mobile/src/components/paywall/Paywall.tsx index c4fff61..65fb33f 100644 --- a/apps/mobile/src/components/paywall/Paywall.tsx +++ b/apps/mobile/src/components/paywall/Paywall.tsx @@ -34,7 +34,7 @@ const FEATURES = [ { icon: "layers" as const, title: "All Premium Packs", - description: "Unlock every intimate collection", + description: "Unlock every question collection", }, { icon: "sparkles" as const, @@ -206,7 +206,7 @@ export function Paywall({ visible, onClose, onSuccess, offeringId }: PaywallProp Sauci Pro - Unlock the full intimate experience + Unlock the full couples experience diff --git a/apps/mobile/src/components/tutorials/MatchesTutorial.tsx b/apps/mobile/src/components/tutorials/MatchesTutorial.tsx index b28a6e4..683aaa9 100644 --- a/apps/mobile/src/components/tutorials/MatchesTutorial.tsx +++ b/apps/mobile/src/components/tutorials/MatchesTutorial.tsx @@ -48,7 +48,7 @@ const STEPS: TutorialStep[] = [ { key: "photos", title: "Share Pictures Privately", - description: "Send photos that only your partner can see. Your intimate moments stay between the two of you, safe and private.", + description: "Send photos that only your partner can see. Your shared moments stay between the two of you, safe and private.", icon: "images", gradient: gradients.premiumRose as [string, string], }, diff --git a/apps/mobile/src/components/ui/IntensitySlider/constants.ts b/apps/mobile/src/components/ui/IntensitySlider/constants.ts index e6d2b0b..897cb94 100644 --- a/apps/mobile/src/components/ui/IntensitySlider/constants.ts +++ b/apps/mobile/src/components/ui/IntensitySlider/constants.ts @@ -8,17 +8,17 @@ export interface IntensityLevelConfig { } export const INTENSITY_LEVELS: IntensityLevelConfig[] = [ - { level: 1, label: 'Gentle', emoji: '💭', description: 'Pure emotional connection & non-sexual bonding' }, - { level: 2, label: 'Warm', emoji: '💕', description: 'Romantic atmosphere & affectionate touch' }, - { level: 3, label: 'Playful', emoji: '😏', description: 'Light sexual exploration & sensual discovery' }, - { level: 4, label: 'Steamy', emoji: '🔥', description: 'Explicit sexual activities & moderate adventure' }, - { level: 5, label: 'Intense', emoji: '🌶️', description: 'Advanced/BDSM/Extreme exploration' }, + { level: 1, label: 'Gentle', emoji: '💭', description: 'Easy conversation and everyday connection' }, + { level: 2, label: 'Warm', emoji: '💕', description: 'Romance, appreciation, and thoughtful moments' }, + { level: 3, label: 'Playful', emoji: '✨', description: 'Light-hearted questions and shared laughter' }, + { level: 4, label: 'Adventurous', emoji: '🌍', description: 'New experiences and ideas to try together' }, + { level: 5, label: 'Deep', emoji: '🌱', description: 'Meaningful reflection and honest conversation' }, ]; export const HEAT_COLORS = [ '#9b59b6', // Purple - gentle '#e94560', // Rose - warm '#ff6b6b', // Coral - playful - '#ff4757', // Red - steamy + '#ff4757', // Red - adventurous '#ff3333', // Bright red - intense ]; diff --git a/apps/mobile/src/features/profile/ProfileScreen.tsx b/apps/mobile/src/features/profile/ProfileScreen.tsx index 3ad37c3..4502cd3 100644 --- a/apps/mobile/src/features/profile/ProfileScreen.tsx +++ b/apps/mobile/src/features/profile/ProfileScreen.tsx @@ -160,9 +160,9 @@ export function ProfileScreen() { /> router.push('/(app)/settings/preferences')} /> diff --git a/apps/mobile/src/features/profile/components/PrivacySettings.tsx b/apps/mobile/src/features/profile/components/PrivacySettings.tsx index 50f445d..4efe3d6 100644 --- a/apps/mobile/src/features/profile/components/PrivacySettings.tsx +++ b/apps/mobile/src/features/profile/components/PrivacySettings.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { View, StyleSheet } from 'react-native'; +import { Text, View, StyleSheet } from 'react-native'; import { SettingsSection } from './SettingsSection'; import { SwitchItem } from './SwitchItem'; import { colors, spacing } from '../../../theme'; @@ -10,9 +10,6 @@ interface PrivacySettingsProps { biometricType: string; isUpdatingBiometric: boolean; onBiometricToggle: (value: boolean) => void; - hideNsfw: boolean; - isUpdatingHideNsfw: boolean; - onHideNsfwToggle: (value: boolean) => void; } export const PrivacySettings: React.FC = ({ @@ -21,44 +18,37 @@ export const PrivacySettings: React.FC = ({ biometricType, isUpdatingBiometric, onBiometricToggle, - hideNsfw, - isUpdatingHideNsfw, - onHideNsfwToggle, }) => { return ( - - {/* Hide Adult Content Toggle */} - - - {/* Biometric Toggle */} + {biometricAvailable && ( - <> - - - + + )} + {!biometricAvailable && ( + + + Biometric app lock is not available on this device. + + )} ); }; const styles = StyleSheet.create({ - divider: { - height: 1, - backgroundColor: colors.border, - marginVertical: spacing.lg, + unavailableRow: { + paddingHorizontal: spacing.lg, + paddingVertical: spacing.md, + }, + unavailableText: { + color: colors.textSecondary, + lineHeight: 20, }, }); diff --git a/apps/mobile/src/features/profile/hooks/useProfileSettings.ts b/apps/mobile/src/features/profile/hooks/useProfileSettings.ts index d55d8f0..ff0fa02 100644 --- a/apps/mobile/src/features/profile/hooks/useProfileSettings.ts +++ b/apps/mobile/src/features/profile/hooks/useProfileSettings.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import { Alert, Linking, Platform } from 'react-native'; -import { useAuthStore, useSubscriptionStore, usePacksStore } from '../../../store'; +import { useAuthStore, useSubscriptionStore } from '../../../store'; import { supabase } from '../../../lib/supabase'; import { Events } from '../../../lib/analytics'; import { useAvatarPicker } from '../../../hooks/useAvatarPicker'; @@ -16,15 +16,8 @@ import { getBiometricType, } from '../../../lib/biometricAuth'; -// Intensity thresholds for backwards compatibility -// When hide_nsfw=true, max_intensity=2 (mild content only) -// When hide_nsfw=false, max_intensity=5 (all content) -const NSFW_OFF_INTENSITY = 2; -const NSFW_ON_INTENSITY = 5; - export function useProfileSettings() { const { user, fetchUser } = useAuthStore(); - const { fetchPacks } = usePacksStore(); const { restorePurchases, isPurchasing } = useSubscriptionStore(); // Name Editing @@ -69,10 +62,6 @@ export function useProfileSettings() { onUploadError: handleAvatarUploadError, }); - // Hide NSFW - const [hideNsfw, setHideNsfw] = useState(!!user?.hide_nsfw); - const [isUpdatingHideNsfw, setIsUpdatingHideNsfw] = useState(false); - // Notifications const [pushEnabled, setPushEnabled] = useState(!!user?.push_token); const [isUpdatingPush, setIsUpdatingPush] = useState(false); @@ -92,7 +81,6 @@ export function useProfileSettings() { setNewName(user.name); } setPushEnabled(!!user?.push_token); - setHideNsfw(!!user?.hide_nsfw); }, [user]); // Check biometric availability @@ -229,43 +217,6 @@ export function useProfileSettings() { } }; - const handleHideNsfwToggle = async (value: boolean) => { - if (!user?.id) return; - - const previous = hideNsfw; - setHideNsfw(value); - setIsUpdatingHideNsfw(true); - - // Derive intensity from hide_nsfw for backwards compatibility - const maxIntensity = value ? NSFW_OFF_INTENSITY : NSFW_ON_INTENSITY; - const showExplicitContent = !value; - - try { - const { error } = await supabase - .from('profiles') - .update({ - hide_nsfw: value, - max_intensity: maxIntensity, - show_explicit_content: showExplicitContent, - updated_at: new Date().toISOString(), - }) - .eq('id', user.id); - - if (error) throw error; - - // Refresh user data and packs to reflect the change - await fetchUser(); - await fetchPacks(); - Events.profileUpdated(["hide_nsfw", "max_intensity", "show_explicit_content"]); - } catch (error) { - // Revert on error - setHideNsfw(previous); - Alert.alert("Error", "Failed to update preference. Please try again."); - } finally { - setIsUpdatingHideNsfw(false); - } - }; - // Subscription Actions const handleRestorePurchases = async () => { const restored = await restorePurchases(); @@ -294,8 +245,6 @@ export function useProfileSettings() { biometricEnabled: biometricEnabledState, biometricType, isUpdatingBiometric, - hideNsfw, - isUpdatingHideNsfw, showPaywall, setShowPaywall, isPurchasing, @@ -306,7 +255,6 @@ export function useProfileSettings() { handleAvatarPress, handlePushToggle, handleBiometricToggle, - handleHideNsfwToggle, handleRestorePurchases, handleManageSubscription, }; diff --git a/apps/mobile/src/features/profile/screens/PreferencesScreen.tsx b/apps/mobile/src/features/profile/screens/PreferencesScreen.tsx index 33fb458..14d0257 100644 --- a/apps/mobile/src/features/profile/screens/PreferencesScreen.tsx +++ b/apps/mobile/src/features/profile/screens/PreferencesScreen.tsx @@ -7,14 +7,14 @@ import { useProfileSettings } from '../hooks'; import { ScreenHeader, PrivacySettings } from '../components'; /** - * Preferences sub-screen for content and biometric settings. + * App-lock settings shared by iOS and Android. */ export function PreferencesScreen() { const settings = useProfileSettings(); return ( - + + /> ); diff --git a/apps/mobile/src/features/swipe/components/SwipeNoPacksState.tsx b/apps/mobile/src/features/swipe/components/SwipeNoPacksState.tsx index 7645fbe..acada53 100644 --- a/apps/mobile/src/features/swipe/components/SwipeNoPacksState.tsx +++ b/apps/mobile/src/features/swipe/components/SwipeNoPacksState.tsx @@ -17,7 +17,7 @@ export const SwipeNoPacksState = ({ onBrowsePacks }: SwipeNoPacksStateProps) => badgeText="NO PACKS ENABLED" description="Select the question packs that interest you and your partner. Each pack explores different aspects of your relationship." features={[ - { icon: "flame-outline", text: "From playful to passionate", color: accent }, + { icon: "flame-outline", text: "From playful to adventurous", color: accent }, { icon: "shield-checkmark-outline", text: "Safe space to explore", color: accent }, { icon: "infinite-outline", text: "New packs added regularly", color: accent }, ]} diff --git a/apps/mobile/src/features/swipe/components/SwipeNoPartnerState.tsx b/apps/mobile/src/features/swipe/components/SwipeNoPartnerState.tsx index 3afdf6e..bbd9abb 100644 --- a/apps/mobile/src/features/swipe/components/SwipeNoPartnerState.tsx +++ b/apps/mobile/src/features/swipe/components/SwipeNoPartnerState.tsx @@ -38,10 +38,10 @@ export const SwipeNoPartnerState = ({ hasCouple, onPairPress }: SwipeNoPartnerSt } features={[ { icon: "lock-closed-outline", text: "Private and secure", color: accent }, - { icon: "sparkles", text: "Discover hidden desires", color: accent }, + { icon: "sparkles", text: "Discover new things together", color: accent }, { icon: "chatbubble-ellipses-outline", text: "Chat about your matches", color: accent }, ]} - teaser={hasCouple ? "Your partner is just a code away" : "Begin your intimate journey together"} + teaser={hasCouple ? "Your partner is just a code away" : "Begin your journey together"} action={{ label: hasCouple ? "View Invite Code" : "Pair Now", onPress: onPairPress, diff --git a/apps/mobile/src/store/packsStore.ts b/apps/mobile/src/store/packsStore.ts index 233df82..5b6d081 100644 --- a/apps/mobile/src/store/packsStore.ts +++ b/apps/mobile/src/store/packsStore.ts @@ -4,16 +4,6 @@ import { Events } from "../lib/analytics"; import type { QuestionPack, Category } from "@/types"; import { useAuthStore } from "./authStore"; -// Intensity thresholds derived from hide_nsfw for backwards compatibility -// When hide_nsfw=true, max_intensity=2 (mild content only) -// When hide_nsfw=false, max_intensity=5 (all content) -const NSFW_OFF_INTENSITY = 2; -const NSFW_ON_INTENSITY = 5; - -const getMaxIntensityFromHideNsfw = (hideNsfw: boolean) => { - return hideNsfw ? NSFW_OFF_INTENSITY : NSFW_ON_INTENSITY; -}; - // Progress data for a pack export interface PackProgressData { totalQuestions: number; @@ -26,13 +16,11 @@ interface PacksState { enabledPackIds: string[]; packProgress: Map; isLoading: boolean; - showAllIntensities: boolean; fetchPacks: () => Promise; fetchEnabledPacks: () => Promise; fetchPackProgress: () => Promise; ensureEnabledPacksLoaded: () => Promise; togglePack: (packId: string) => Promise<{ success: boolean; reason?: string }>; - setShowAllIntensities: (value: boolean) => void; clearPacks: () => void; getPackProgress: (packId: string) => PackProgressData | undefined; } @@ -43,16 +31,10 @@ export const usePacksStore = create((set, get) => ({ enabledPackIds: [], packProgress: new Map(), isLoading: false, - showAllIntensities: false, fetchPacks: async () => { set({ isLoading: true }); - // Get hide_nsfw preference and derive max_intensity from it - const hideNsfw = useAuthStore.getState().user?.hide_nsfw ?? false; - const maxIntensity = getMaxIntensityFromHideNsfw(hideNsfw); - const showAllIntensities = get().showAllIntensities; - // Fetch categories const { data: categories } = await supabase .from("categories") @@ -64,22 +46,12 @@ export const usePacksStore = create((set, get) => ({ const visibleCategoryIds = new Set(visibleCategories.map(category => category.id)); // Fetch packs with category info and question count - let query = supabase + const query = supabase .from("question_packs") .select("*, category:categories(*), questions(count)") .eq("is_public", true) .order("sort_order"); - // Filter out packs above user's intensity preference (unless showing all) - if (maxIntensity < 5 && !showAllIntensities) { - query = query.or(`max_intensity.is.null,max_intensity.lte.${maxIntensity}`); - } - - // Filter out explicit packs when user has hide_nsfw enabled - if (hideNsfw) { - query = query.eq("is_explicit", false); - } - const { data: packs } = await query; const visiblePacks = (packs ?? []).filter(pack => { @@ -171,12 +143,6 @@ export const usePacksStore = create((set, get) => ({ return { success: true }; }, - setShowAllIntensities: (value: boolean) => { - set({ showAllIntensities: value }); - // Refetch packs with new filter setting - get().fetchPacks(); - }, - fetchPackProgress: async () => { const userId = useAuthStore.getState().user?.id; if (!userId) {