diff --git a/.gitignore b/.gitignore
index f0d6434..663039f 100755
--- a/.gitignore
+++ b/.gitignore
@@ -16,10 +16,10 @@ build/
.env.local
.env.development.local
.env.test.local
-.env.production.local
-apps/mobile/.env.prod
-.secrets
-
+.env.production.local
+apps/mobile/.env.*
+.secrets
+
# Supabase
.supabase/
diff --git a/apps/mobile/app/(app)/_layout.tsx b/apps/mobile/app/(app)/_layout.tsx
index 03174ec..d4fe79f 100755
--- a/apps/mobile/app/(app)/_layout.tsx
+++ b/apps/mobile/app/(app)/_layout.tsx
@@ -43,11 +43,14 @@ function TabBarBackground() {
// The solid rgba background in tabBarStyle provides the visual effect on Android
if (Platform.OS === 'ios') {
return (
-
+ <>
+
+
+ >
);
}
return null;
@@ -435,7 +438,7 @@ export default function AppLayout() {
tabBarBackground: () => ,
tabBarStyle: shouldHideTabBar ? { display: 'none' } : {
position: 'absolute',
- backgroundColor: 'rgba(13, 13, 26, 0.92)',
+ backgroundColor: 'rgba(14, 14, 17, 0.85)',
borderTopColor: 'rgba(233, 69, 96, 0.2)', // primary brand color
borderTopWidth: 1,
paddingTop: 8,
diff --git a/apps/mobile/app/(app)/index.tsx b/apps/mobile/app/(app)/index.tsx
index ff3693e..db51095 100755
--- a/apps/mobile/app/(app)/index.tsx
+++ b/apps/mobile/app/(app)/index.tsx
@@ -4,7 +4,7 @@ import { useFocusEffect } from 'expo-router';
import Animated, { FadeInDown } from 'react-native-reanimated';
import { Ionicons } from '@expo/vector-icons';
import { BlurView } from 'expo-blur';
-import { useAuthStore, usePacksStore } from '../../src/store';
+import { useAuthStore, usePacksStore, useSubscriptionStore } from '../../src/store';
import { GradientBackground } from '../../src/components/ui';
import { Paywall } from '../../src/components/paywall';
import { CompactHeader, ContentRow } from '../../src/components/discovery';
@@ -18,61 +18,63 @@ function groupPacksByCategory(
packs: QuestionPack[],
categories: Category[]
): { category: Category; packs: QuestionPack[] }[] {
- const categoryMap = new Map();
- const uncategorized: QuestionPack[] = [];
-
- // Initialize map with empty arrays for each category
- categories.forEach((cat) => {
- categoryMap.set(cat.id, []);
- });
-
- // Group packs
- packs.forEach((pack) => {
- if (pack.category_id && categoryMap.has(pack.category_id)) {
- categoryMap.get(pack.category_id)!.push(pack);
- } else {
- uncategorized.push(pack);
- }
- });
-
- // Build result array maintaining category sort order
- const result: { category: Category; packs: QuestionPack[] }[] = [];
-
- categories.forEach((cat) => {
- const categoryPacks = categoryMap.get(cat.id) || [];
- if (categoryPacks.length > 0) {
- result.push({ category: cat, packs: categoryPacks });
- }
- });
-
- // Add uncategorized at the end if any
- if (uncategorized.length > 0) {
- result.push({
- category: {
- id: 'uncategorized',
- name: 'More',
- description: null,
- icon: 'ellipsis-horizontal',
- color: null,
- sort_order: 999,
- created_at: '',
- is_public: true,
- },
- packs: uncategorized,
- });
- }
-
- return result;
-}
-
-export default function DiscoveryScreen() {
- const { user, partner, couple } = useAuthStore();
- const { packs, categories, fetchPacks, getPackProgress } = usePacksStore();
+ const categoryMap = new Map();
+ const uncategorized: QuestionPack[] = [];
+
+ // Initialize map with empty arrays for each category
+ categories.forEach((cat) => {
+ categoryMap.set(cat.id, []);
+ });
+
+ // Group packs
+ packs.forEach((pack) => {
+ if (pack.category_id && categoryMap.has(pack.category_id)) {
+ categoryMap.get(pack.category_id)!.push(pack);
+ } else {
+ uncategorized.push(pack);
+ }
+ });
+
+ // Build result array maintaining category sort order
+ const result: { category: Category; packs: QuestionPack[] }[] = [];
+
+ categories.forEach((cat) => {
+ const categoryPacks = categoryMap.get(cat.id) || [];
+ if (categoryPacks.length > 0) {
+ result.push({ category: cat, packs: categoryPacks });
+ }
+ });
+
+ // Add uncategorized at the end if any
+ if (uncategorized.length > 0) {
+ result.push({
+ category: {
+ id: 'uncategorized',
+ name: 'More',
+ description: null,
+ icon: 'ellipsis-horizontal',
+ color: null,
+ sort_order: 999,
+ created_at: '',
+ is_public: true,
+ },
+ packs: uncategorized,
+ });
+ }
+
+ return result;
+}
+
+export default function DiscoveryScreen() {
+ const { user, partner, couple } = useAuthStore();
+ const { packs, categories, fetchPacks, getPackProgress } = usePacksStore();
+ const { subscription } = useSubscriptionStore();
const { width } = useWindowDimensions();
const [showPaywall, setShowPaywall] = useState(false);
const [headerHeight, setHeaderHeight] = useState(130);
- const isPremiumUser = user?.is_premium ?? false;
+ // Check all sources of premium access: user flag, partner flag, or active subscription
+ const isPremiumUser = user?.is_premium || partner?.is_premium || subscription.isProUser;
const isWideScreen = width > MAX_CONTENT_WIDTH;
// Refresh data when screen gains focus
@@ -159,51 +161,51 @@ export default function DiscoveryScreen() {
);
}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- contentContainer: {
- flexGrow: 1,
- paddingBottom: Platform.OS === 'ios' ? 100 : 80,
- },
- contentContainerWide: {
- alignItems: 'center',
- },
- innerContainer: {
- flex: 1,
- width: '100%',
- },
- innerContainerWide: {
- maxWidth: MAX_CONTENT_WIDTH,
- },
- emptyState: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- paddingHorizontal: spacing.xl,
- paddingVertical: spacing.xxl,
- },
- emptyIcon: {
- width: 80,
- height: 80,
- borderRadius: 40,
- backgroundColor: 'rgba(233, 69, 96, 0.1)',
- justifyContent: 'center',
- alignItems: 'center',
- marginBottom: spacing.lg,
- },
- emptyTitle: {
- ...typography.title3,
- color: colors.text,
- marginBottom: spacing.sm,
- },
- emptySubtitle: {
- ...typography.body,
- color: colors.textSecondary,
- textAlign: 'center',
- },
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ contentContainer: {
+ flexGrow: 1,
+ paddingBottom: Platform.OS === 'ios' ? 100 : 80,
+ },
+ contentContainerWide: {
+ alignItems: 'center',
+ },
+ innerContainer: {
+ flex: 1,
+ width: '100%',
+ },
+ innerContainerWide: {
+ maxWidth: MAX_CONTENT_WIDTH,
+ },
+ emptyState: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ paddingHorizontal: spacing.xl,
+ paddingVertical: spacing.xxl,
+ },
+ emptyIcon: {
+ width: 80,
+ height: 80,
+ borderRadius: 40,
+ backgroundColor: 'rgba(233, 69, 96, 0.1)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: spacing.lg,
+ },
+ emptyTitle: {
+ ...typography.title3,
+ color: colors.text,
+ marginBottom: spacing.sm,
+ },
+ emptySubtitle: {
+ ...typography.body,
+ color: colors.textSecondary,
+ textAlign: 'center',
+ },
bottomSpacer: {
height: spacing.lg,
},
diff --git a/apps/mobile/app/(app)/swipe.tsx b/apps/mobile/app/(app)/swipe.tsx
index 3d18a7c..b6e7743 100755
--- a/apps/mobile/app/(app)/swipe.tsx
+++ b/apps/mobile/app/(app)/swipe.tsx
@@ -1267,8 +1267,6 @@ export default function SwipeScreen() {
- {/* Spacer to balance header when back button is shown */}
- {(packId || mode === 'pending') && }
@@ -1370,11 +1368,9 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
backButton: {
+ position: 'absolute',
+ left: 0,
padding: spacing.sm,
- marginRight: spacing.sm,
- },
- headerSpacer: {
- width: 40, // Match back button width for centering
},
progressContainer: {
alignItems: "center",