diff --git a/app.json b/app.json
new file mode 100644
index 0000000..743a26a
--- /dev/null
+++ b/app.json
@@ -0,0 +1,10 @@
+{
+ "expo": {
+ "extra": {
+ "eas": {
+ "projectId": "807ca0af-e9bd-40e8-a658-f3382072c724"
+ }
+ },
+ "owner": "jjbrunton-apps"
+ }
+}
diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle
index a25b7fa..a37a7eb 100644
--- a/apps/mobile/android/app/build.gradle
+++ b/apps/mobile/android/app/build.gradle
@@ -94,7 +94,7 @@ android {
applicationId 'com.sauci.app'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 3
+ versionCode 1
versionName "1.0.0"
}
signingConfigs {
diff --git a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp
index e91bfd8..a97edd8 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp and b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
index dd7418b..7fb057d 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp and b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
index 658f2c1..cf7a6da 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp
index e202285..60af425 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp and b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
index 9c62968..2f241ff 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp and b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
index 9bfe4a5..2606d3c 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
index 5f78705..282629c 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and b/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
index 69e29f7..e83a632 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp and b/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
index e249752..8f28e36 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and b/apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
index cf1b62e..9f8b66d 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
index 6288d36..9cb3660 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp and b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
index 4bccefd..6312379 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
index 6bcfbcf..56aec77 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
index 4802994..f110bfc 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp and b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ
diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
index 9abd05e..783f21f 100644
Binary files a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/apps/mobile/app.json b/apps/mobile/app.json
index 27146df..de8a716 100644
--- a/apps/mobile/app.json
+++ b/apps/mobile/app.json
@@ -26,7 +26,7 @@
},
"android": {
"adaptiveIcon": {
- "foregroundImage": "./assets/splash-icon.png",
+ "foregroundImage": "./assets/adaptive-icon-foreground.png",
"backgroundColor": "#1a1a2e"
},
"package": "com.sauci.app",
diff --git a/apps/mobile/app/(app)/_layout.tsx b/apps/mobile/app/(app)/_layout.tsx
index 226ec61..6e94418 100755
--- a/apps/mobile/app/(app)/_layout.tsx
+++ b/apps/mobile/app/(app)/_layout.tsx
@@ -149,12 +149,10 @@ export default function AppLayout() {
router.push('/(app)/swipe');
break;
case 'dares':
- // TODO: Navigate to dares screen
- console.log('Dares pressed - not yet implemented');
+ router.push('/(app)/dares');
break;
case 'quiz':
- // TODO: Navigate to quiz screen
- console.log('Quiz pressed - not yet implemented');
+ router.push('/(app)/quiz');
break;
}
}, [router, closeRadialMenu]);
@@ -609,6 +607,18 @@ export default function AppLayout() {
href: null, // Hide from tab bar
}}
/>
+
+
{/* Radial Menu Overlay */}
diff --git a/apps/mobile/app/(app)/dares.tsx b/apps/mobile/app/(app)/dares.tsx
new file mode 100644
index 0000000..e0fa202
--- /dev/null
+++ b/apps/mobile/app/(app)/dares.tsx
@@ -0,0 +1,170 @@
+import { View, Text, StyleSheet, Platform } from "react-native";
+import { Ionicons } from "@expo/vector-icons";
+import Animated, { FadeInDown, FadeIn } from "react-native-reanimated";
+import { GradientBackground } from "../../src/components/ui";
+import { colors, spacing, radius, typography } from "../../src/theme";
+
+const ACCENT_COLOR = colors.premium.gold;
+
+export default function DaresScreen() {
+ return (
+
+
+
+ {/* Icon */}
+
+
+
+
+ {/* Title section */}
+ ADVENTURE
+ Dares
+
+ {/* Decorative separator */}
+
+
+
+
+
+
+ {/* Coming soon badge */}
+
+ ARRIVING SOON
+
+
+ {/* Description */}
+
+ Push your boundaries together with tantalising challenges designed to ignite passion and create unforgettable moments.
+
+
+ {/* Feature hints */}
+
+
+
+ Provocative challenges
+
+
+
+ Multiple intensity levels
+
+
+
+ Designed for two
+
+
+
+ {/* Bottom teaser */}
+ Are you ready to play?
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ paddingHorizontal: spacing.lg,
+ paddingTop: Platform.OS === 'ios' ? 60 : 40,
+ paddingBottom: Platform.OS === 'ios' ? 120 : 100,
+ },
+ content: {
+ width: '100%',
+ alignItems: 'center',
+ paddingHorizontal: spacing.md,
+ },
+ iconContainer: {
+ width: 72,
+ height: 72,
+ borderRadius: 36,
+ backgroundColor: 'rgba(212, 175, 55, 0.1)',
+ borderWidth: 1,
+ borderColor: 'rgba(212, 175, 55, 0.2)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: spacing.xl,
+ },
+ label: {
+ ...typography.caption1,
+ fontWeight: '600',
+ letterSpacing: 3,
+ color: ACCENT_COLOR,
+ textAlign: 'center',
+ marginBottom: spacing.xs,
+ },
+ title: {
+ ...typography.largeTitle,
+ color: colors.text,
+ textAlign: 'center',
+ },
+ separator: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginVertical: spacing.lg,
+ width: 140,
+ },
+ separatorLine: {
+ flex: 1,
+ height: 1,
+ backgroundColor: 'rgba(212, 175, 55, 0.3)',
+ },
+ separatorDiamond: {
+ width: 6,
+ height: 6,
+ backgroundColor: ACCENT_COLOR,
+ transform: [{ rotate: '45deg' }],
+ marginHorizontal: spacing.md,
+ opacity: 0.6,
+ },
+ badge: {
+ backgroundColor: 'rgba(212, 175, 55, 0.1)',
+ paddingHorizontal: spacing.lg,
+ paddingVertical: spacing.sm,
+ borderRadius: radius.full,
+ borderWidth: 1,
+ borderColor: 'rgba(212, 175, 55, 0.2)',
+ marginBottom: spacing.xl,
+ },
+ badgeText: {
+ ...typography.caption2,
+ fontWeight: '600',
+ letterSpacing: 2,
+ color: ACCENT_COLOR,
+ },
+ description: {
+ ...typography.body,
+ color: colors.textSecondary,
+ textAlign: 'center',
+ marginBottom: spacing.xl,
+ paddingHorizontal: spacing.md,
+ },
+ features: {
+ marginBottom: spacing.xl,
+ },
+ featureItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: spacing.sm,
+ },
+ featureText: {
+ ...typography.subhead,
+ color: colors.text,
+ marginLeft: spacing.sm,
+ },
+ teaser: {
+ ...typography.footnote,
+ fontStyle: 'italic',
+ color: colors.textTertiary,
+ textAlign: 'center',
+ },
+});
diff --git a/apps/mobile/app/(app)/quiz.tsx b/apps/mobile/app/(app)/quiz.tsx
new file mode 100644
index 0000000..82cdad0
--- /dev/null
+++ b/apps/mobile/app/(app)/quiz.tsx
@@ -0,0 +1,170 @@
+import { View, Text, StyleSheet, Platform } from "react-native";
+import { Ionicons } from "@expo/vector-icons";
+import Animated, { FadeInDown, FadeIn } from "react-native-reanimated";
+import { GradientBackground } from "../../src/components/ui";
+import { colors, spacing, radius, typography } from "../../src/theme";
+
+const ACCENT_COLOR = colors.premium.rose;
+
+export default function QuizScreen() {
+ return (
+
+
+
+ {/* Icon */}
+
+
+
+
+ {/* Title section */}
+ INTIMACY
+ Quiz
+
+ {/* Decorative separator */}
+
+
+
+
+
+
+ {/* Coming soon badge */}
+
+ ARRIVING SOON
+
+
+ {/* Description */}
+
+ Discover the depths of your connection through carefully crafted questions that reveal how well you truly know each other.
+
+
+ {/* Feature hints */}
+
+
+
+ Uncover hidden desires
+
+
+
+ Deepen your bond
+
+
+
+ Track your journey
+
+
+
+ {/* Bottom teaser */}
+ Something special is being crafted for you
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ paddingHorizontal: spacing.lg,
+ paddingTop: Platform.OS === 'ios' ? 60 : 40,
+ paddingBottom: Platform.OS === 'ios' ? 120 : 100,
+ },
+ content: {
+ width: '100%',
+ alignItems: 'center',
+ paddingHorizontal: spacing.md,
+ },
+ iconContainer: {
+ width: 72,
+ height: 72,
+ borderRadius: 36,
+ backgroundColor: 'rgba(232, 164, 174, 0.1)',
+ borderWidth: 1,
+ borderColor: 'rgba(232, 164, 174, 0.2)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: spacing.xl,
+ },
+ label: {
+ ...typography.caption1,
+ fontWeight: '600',
+ letterSpacing: 3,
+ color: ACCENT_COLOR,
+ textAlign: 'center',
+ marginBottom: spacing.xs,
+ },
+ title: {
+ ...typography.largeTitle,
+ color: colors.text,
+ textAlign: 'center',
+ },
+ separator: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginVertical: spacing.lg,
+ width: 140,
+ },
+ separatorLine: {
+ flex: 1,
+ height: 1,
+ backgroundColor: 'rgba(232, 164, 174, 0.3)',
+ },
+ separatorDiamond: {
+ width: 6,
+ height: 6,
+ backgroundColor: ACCENT_COLOR,
+ transform: [{ rotate: '45deg' }],
+ marginHorizontal: spacing.md,
+ opacity: 0.6,
+ },
+ badge: {
+ backgroundColor: 'rgba(232, 164, 174, 0.1)',
+ paddingHorizontal: spacing.lg,
+ paddingVertical: spacing.sm,
+ borderRadius: radius.full,
+ borderWidth: 1,
+ borderColor: 'rgba(232, 164, 174, 0.2)',
+ marginBottom: spacing.xl,
+ },
+ badgeText: {
+ ...typography.caption2,
+ fontWeight: '600',
+ letterSpacing: 2,
+ color: ACCENT_COLOR,
+ },
+ description: {
+ ...typography.body,
+ color: colors.textSecondary,
+ textAlign: 'center',
+ marginBottom: spacing.xl,
+ paddingHorizontal: spacing.md,
+ },
+ features: {
+ marginBottom: spacing.xl,
+ },
+ featureItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: spacing.sm,
+ },
+ featureText: {
+ ...typography.subhead,
+ color: colors.text,
+ marginLeft: spacing.sm,
+ },
+ teaser: {
+ ...typography.footnote,
+ fontStyle: 'italic',
+ color: colors.textTertiary,
+ textAlign: 'center',
+ },
+});
diff --git a/apps/mobile/app/(app)/swipe.tsx b/apps/mobile/app/(app)/swipe.tsx
index 7502d5b..5471840 100755
--- a/apps/mobile/app/(app)/swipe.tsx
+++ b/apps/mobile/app/(app)/swipe.tsx
@@ -270,34 +270,68 @@ export default function SwipeScreen() {
// Show "pair with partner" prompt when user doesn't have a partner yet
if (!partner) {
+ const PAIR_ACCENT = colors.premium.rose;
return (
-
+
-
+
+
+
+ {/* Title section */}
+ {couple ? "ALMOST THERE" : "CONNECT"}
+ {couple ? "Waiting" : "Pair Up"}
+
+ {/* Decorative separator */}
+
+
+
+
+
+
+ {/* Status badge */}
+
-
-
-
- {couple ? "Waiting for your partner" : "Pair with your partner"}
-
-
+ {couple ? "INVITE SENT" : "MADE FOR TWO"}
+
+
+ {/* Description */}
+
{couple
? "Share your invite code so they can join you. Once paired, you'll both answer questions and discover what you agree on!"
: "Sauci is made for two! Connect with your partner to start answering questions together and discover what you have in common."
}
+
+ {/* Feature hints */}
+
+
+
+ Private and secure
+
+
+
+ Discover hidden desires
+
+
+
+ Chat about your matches
+
+
+
+ {/* Bottom teaser */}
+ {couple ? "Your partner is just a code away" : "Begin your intimate journey together"}
+
router.push("/pairing")}
- style={{ marginTop: spacing.xl }}
- size="lg"
+ style={{ marginTop: spacing.lg }}
>
{couple ? "View Invite Code" : "Pair Now"}
@@ -309,27 +343,62 @@ export default function SwipeScreen() {
// Show "waiting for partner" message when user is too far ahead
if (isBlocked && gapInfo) {
+ const WAITING_ACCENT = colors.premium.rose;
return (
-
+
-
+
+
+
+ {/* Title section */}
+ PATIENCE
+ Waiting
+
+ {/* Decorative separator */}
+
+
+
+
+
+
+ {/* Status badge */}
+
-
-
-
- Waiting for your partner
-
-
- You've answered {gapInfo.unanswered} questions that your partner hasn't seen yet. Give them some time to catch up!
+ {gapInfo.unanswered} UNANSWERED
+
+
+ {/* Description */}
+
+ You're ahead by {gapInfo.unanswered} questions. Give your partner some time to catch up so you can discover matches together.
+
+ {/* Feature hints */}
+
+
+
+ Matches happen together
+
+
+
+ We'll notify your partner
+
+
+
+ Check back anytime
+
+
+
+ {/* Bottom teaser */}
+ Good things come to those who wait
+
+
-
-
+ {/* Icon */}
+
+
- No packs enabled
-
- Enable at least one question pack to start playing.
+
+ {/* Title section */}
+ GET STARTED
+ Choose Packs
+
+ {/* Decorative separator */}
+
+
+
+
+
+
+ {/* Status badge */}
+
+ NO PACKS ENABLED
+
+
+ {/* Description */}
+
+ Select the question packs that interest you and your partner. Each pack explores different aspects of your relationship.
+
+ {/* Feature hints */}
+
+
+
+ From playful to passionate
+
+
+
+ Safe space to explore
+
+
+
+ New packs added regularly
+
+
+
+ {/* Bottom teaser */}
+ Your journey of discovery awaits
+
router.push("/packs")}
style={{ marginTop: spacing.lg }}
@@ -372,20 +483,62 @@ export default function SwipeScreen() {
}
if (currentIndex >= questions.length) {
+ const CAUGHT_UP_ACCENT = colors.premium.rose;
return (
-
+
-
-
+ {/* Icon */}
+
+
- All caught up!
-
- Check back later for more questions or try a different pack.
+
+ {/* Title section */}
+ COMPLETE
+ All Caught Up
+
+ {/* Decorative separator */}
+
+
+
+
+
+
+ {/* Status badge */}
+
+ YOU'RE AHEAD
+
+
+ {/* Description */}
+
+ You've answered all available questions. New questions are added regularly, or explore different packs.
+
+ {/* Feature hints */}
+
+
+
+ New questions weekly
+
+
+
+ Try different packs
+
+
+
+ Chat about your matches
+
+
+
+ {/* Bottom teaser */}
+ More ways to connect are on the way
+
{
}
}
+/**
+ * Get Expo push token with retry logic for Android.
+ * On Android, Firebase may not be initialized immediately on app start,
+ * so we retry a few times with increasing delays.
+ */
+async function getExpoPushTokenWithRetry(
+ projectId: string,
+ maxRetries = 5
+): Promise {
+ console.log(`[Push] Getting token for project: ${projectId}, platform: ${Platform.OS}`);
+
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
+ try {
+ console.log(`[Push] Attempt ${attempt + 1}/${maxRetries} to get push token...`);
+ const tokenData = await Notifications.getExpoPushTokenAsync({ projectId });
+ console.log(`[Push] Successfully got token: ${tokenData.data}`);
+ return tokenData.data;
+ } catch (error) {
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ console.log(`[Push] Attempt ${attempt + 1} failed: ${errorMessage}`);
+
+ // Retry for any Firebase-related errors on Android
+ const isFirebaseError =
+ error instanceof Error &&
+ (error.message.includes("Firebase") ||
+ error.message.includes("FCM") ||
+ error.message.includes("Google Play"));
+
+ if (Platform.OS === "android" && attempt < maxRetries - 1) {
+ const delay = (attempt + 1) * 1000;
+ console.log(`[Push] Retrying in ${delay}ms...`);
+ await new Promise((resolve) => setTimeout(resolve, delay));
+ continue;
+ }
+
+ throw error;
+ }
+ }
+ return null;
+}
+
/**
* Check if current device needs to register for push notifications.
* This handles the case where a user onboarded on one device (e.g., iOS)
@@ -110,32 +151,44 @@ export async function clearPushToken(userId: string): Promise {
* Returns true if a new token was registered.
*/
export async function checkAndRegisterPushToken(userId: string): Promise {
+ console.log(`[Push] checkAndRegisterPushToken called for user: ${userId}`);
+
if (Platform.OS === "web") {
+ console.log("[Push] Skipping - web platform");
return false;
}
try {
// First check if permissions are already granted
const { status } = await Notifications.getPermissionsAsync();
+ console.log(`[Push] Current permission status: ${status}`);
// If permissions not granted, we need to prompt the user
// But only do this if we don't already have a token for this device
if (status !== "granted") {
- // Request permissions
+ console.log("[Push] Requesting permissions...");
const { status: newStatus } = await Notifications.requestPermissionsAsync();
+ console.log(`[Push] New permission status: ${newStatus}`);
if (newStatus !== "granted") {
+ console.log("[Push] Permission denied");
return false;
}
}
// Get the current device's push token
const projectId = Constants.expoConfig?.extra?.eas?.projectId;
+ console.log(`[Push] Project ID: ${projectId}`);
if (!projectId) {
+ console.log("[Push] No project ID configured");
return false;
}
- const tokenData = await Notifications.getExpoPushTokenAsync({ projectId });
- const currentToken = tokenData.data;
+ const currentToken = await getExpoPushTokenWithRetry(projectId);
+ console.log(`[Push] Current token: ${currentToken}`);
+ if (!currentToken) {
+ console.log("[Push] Failed to get token");
+ return false;
+ }
// Fetch the stored token from the database
const { data: profile } = await supabase
@@ -144,16 +197,20 @@ export async function checkAndRegisterPushToken(userId: string): Promise= 16.28.0",
+ "appVersionSource": "remote"
+ },
+ "build": {
+ "development": {
+ "developmentClient": true,
+ "distribution": "internal"
+ },
+ "preview": {
+ "distribution": "internal"
+ },
+ "production": {
+ "autoIncrement": true
+ }
+ },
+ "submit": {
+ "production": {}
+ }
+}