mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-11-02 18:19:44 +00:00
Compare commits
2
Commits
e671ae9d1c
...
1911f8f058
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1911f8f058 | ||
|
|
23e24aa4c2 |
No files matched your search
@@ -331,7 +331,7 @@ export function UserDetailPage() {
|
|||||||
expires_at: expiresAt,
|
expires_at: expiresAt,
|
||||||
});
|
});
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
const { data: updatedProfile } = await supabase.from('profiles').select('*').eq('id', userId).single();
|
const { data: updatedProfile } = await supabase.rpc('get_profile_with_auth_info', { user_id: userId }).single();
|
||||||
if (updatedProfile) setProfile(updatedProfile);
|
if (updatedProfile) setProfile(updatedProfile);
|
||||||
setUpgradeOpen(false);
|
setUpgradeOpen(false);
|
||||||
alert('User upgraded to premium successfully!');
|
alert('User upgraded to premium successfully!');
|
||||||
@@ -347,7 +347,7 @@ export function UserDetailPage() {
|
|||||||
if (!userId) return;
|
if (!userId) return;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data: profileData } = await supabase.from('profiles').select('*').eq('id', userId).single();
|
const { data: profileData } = await supabase.rpc('get_profile_with_auth_info', { user_id: userId }).single();
|
||||||
setProfile(profileData);
|
setProfile(profileData);
|
||||||
|
|
||||||
// Fetch feature interests for the user
|
// Fetch feature interests for the user
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>IS_ADS_ENABLED</key>
|
<key>IS_ADS_ENABLED</key>
|
||||||
<false></false>
|
<false></false>
|
||||||
<key>IS_ANALYTICS_ENABLED</key>
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
<false></false>
|
<true></true>
|
||||||
<key>IS_APPINVITE_ENABLED</key>
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
<true></true>
|
<true></true>
|
||||||
<key>IS_GCM_ENABLED</key>
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ android {
|
|||||||
applicationId 'com.sauci.app'
|
applicationId 'com.sauci.app'
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 22
|
versionCode 24
|
||||||
versionName "1.0.1"
|
versionName "1.0.2"
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
debug {
|
debug {
|
||||||
|
|||||||
@@ -57,3 +57,6 @@ expo.useLegacyPackaging=false
|
|||||||
|
|
||||||
android.targetSdkVersion=35
|
android.targetSdkVersion=35
|
||||||
android.extraMavenRepos=[]
|
android.extraMavenRepos=[]
|
||||||
|
|
||||||
|
# Enable 16 KB page size support (required by Google Play for API 35+)
|
||||||
|
android.bundle.pageAlignment=16kb
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"expo": {
|
"expo": {
|
||||||
"name": "Sauci",
|
"name": "Sauci",
|
||||||
"slug": "sauci",
|
"slug": "sauci",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"scheme": "app.sauci",
|
"scheme": "app.sauci",
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"bundleIdentifier": "com.sauci.app",
|
"bundleIdentifier": "com.sauci.app",
|
||||||
"buildNumber": "30",
|
"buildNumber": "30",
|
||||||
"usesAppleSignIn": true,
|
"usesAppleSignIn": true,
|
||||||
|
"googleServicesFile": "./GoogleService-Info.plist",
|
||||||
"infoPlist": {
|
"infoPlist": {
|
||||||
"UIBackgroundModes": [
|
"UIBackgroundModes": [
|
||||||
"remote-notification"
|
"remote-notification"
|
||||||
@@ -176,7 +177,7 @@
|
|||||||
"backgroundColor": "#1a1a2e"
|
"backgroundColor": "#1a1a2e"
|
||||||
},
|
},
|
||||||
"package": "com.sauci.app",
|
"package": "com.sauci.app",
|
||||||
"versionCode": 22,
|
"versionCode": 24,
|
||||||
"googleServicesFile": "./google-services.json",
|
"googleServicesFile": "./google-services.json",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"RECEIVE_BOOT_COMPLETED",
|
"RECEIVE_BOOT_COMPLETED",
|
||||||
@@ -197,6 +198,9 @@
|
|||||||
{
|
{
|
||||||
"android": {
|
"android": {
|
||||||
"targetSdkVersion": 35
|
"targetSdkVersion": 35
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"useFrameworks": "static"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -331,7 +331,6 @@ PODS:
|
|||||||
- libavif/core
|
- libavif/core
|
||||||
- libdav1d (>= 0.6.0)
|
- libdav1d (>= 0.6.0)
|
||||||
- libdav1d (1.2.0)
|
- libdav1d (1.2.0)
|
||||||
- OpenSSL-Universal (3.3.3001)
|
|
||||||
- PromisesObjC (2.4.0)
|
- PromisesObjC (2.4.0)
|
||||||
- PurchasesHybridCommon (17.25.0):
|
- PurchasesHybridCommon (17.25.0):
|
||||||
- RevenueCat (= 5.51.1)
|
- RevenueCat (= 5.51.1)
|
||||||
@@ -1634,29 +1633,6 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- react-native-quick-crypto (0.7.17):
|
|
||||||
- DoubleConversion
|
|
||||||
- glog
|
|
||||||
- hermes-engine
|
|
||||||
- OpenSSL-Universal
|
|
||||||
- RCT-Folly (= 2024.10.14.00)
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React
|
|
||||||
- React-Core
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- Yoga
|
|
||||||
- react-native-safe-area-context (4.12.0):
|
- react-native-safe-area-context (4.12.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- React-nativeconfig (0.76.9)
|
- React-nativeconfig (0.76.9)
|
||||||
@@ -2176,7 +2152,6 @@ DEPENDENCIES:
|
|||||||
- React-Mapbuffer (from `../../../node_modules/react-native/ReactCommon`)
|
- React-Mapbuffer (from `../../../node_modules/react-native/ReactCommon`)
|
||||||
- React-microtasksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
|
- React-microtasksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
|
||||||
- react-native-compressor (from `../../../node_modules/react-native-compressor`)
|
- react-native-compressor (from `../../../node_modules/react-native-compressor`)
|
||||||
- react-native-quick-crypto (from `../../../node_modules/react-native-quick-crypto`)
|
|
||||||
- react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`)
|
- react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`)
|
||||||
- React-nativeconfig (from `../../../node_modules/react-native/ReactCommon`)
|
- React-nativeconfig (from `../../../node_modules/react-native/ReactCommon`)
|
||||||
- React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
- React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||||
@@ -2224,7 +2199,6 @@ SPEC REPOS:
|
|||||||
- GTMSessionFetcher
|
- GTMSessionFetcher
|
||||||
- libavif
|
- libavif
|
||||||
- libdav1d
|
- libdav1d
|
||||||
- OpenSSL-Universal
|
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
- PurchasesHybridCommon
|
- PurchasesHybridCommon
|
||||||
- RevenueCat
|
- RevenueCat
|
||||||
@@ -2372,8 +2346,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
|
:path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
|
||||||
react-native-compressor:
|
react-native-compressor:
|
||||||
:path: "../../../node_modules/react-native-compressor"
|
:path: "../../../node_modules/react-native-compressor"
|
||||||
react-native-quick-crypto:
|
|
||||||
:path: "../../../node_modules/react-native-quick-crypto"
|
|
||||||
react-native-safe-area-context:
|
react-native-safe-area-context:
|
||||||
:path: "../../../node_modules/react-native-safe-area-context"
|
:path: "../../../node_modules/react-native-safe-area-context"
|
||||||
React-nativeconfig:
|
React-nativeconfig:
|
||||||
@@ -2494,7 +2466,6 @@ SPEC CHECKSUMS:
|
|||||||
hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11
|
hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11
|
||||||
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
||||||
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
||||||
OpenSSL-Universal: 6082b0bf950e5636fe0d78def171184e2b3899c2
|
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
PurchasesHybridCommon: 6a79a873ab52f777bfa36e9516f3fcd84d3b3428
|
PurchasesHybridCommon: 6a79a873ab52f777bfa36e9516f3fcd84d3b3428
|
||||||
RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17
|
RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17
|
||||||
@@ -2527,7 +2498,6 @@ SPEC CHECKSUMS:
|
|||||||
React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de
|
React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de
|
||||||
React-microtasksnativemodule: 5c3d795318c22ab8df55100e50b151384a4a60b3
|
React-microtasksnativemodule: 5c3d795318c22ab8df55100e50b151384a4a60b3
|
||||||
react-native-compressor: 2c3a41768bdd367f6e121f555dff9d3eda1810e5
|
react-native-compressor: 2c3a41768bdd367f6e121f555dff9d3eda1810e5
|
||||||
react-native-quick-crypto: 7bb26af9b3705dbb9277c09305104d37ede74916
|
|
||||||
react-native-safe-area-context: 8b8404e70b0cbf2a56428a17017c14c1dcc16448
|
react-native-safe-area-context: 8b8404e70b0cbf2a56428a17017c14c1dcc16448
|
||||||
React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678
|
React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678
|
||||||
React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e
|
React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e
|
||||||
|
|||||||
@@ -352,12 +352,10 @@
|
|||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Sauci/Pods-Sauci-frameworks.sh",
|
"${PODS_ROOT}/Target Support Files/Pods-Sauci/Pods-Sauci-frameworks.sh",
|
||||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL",
|
|
||||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
|
||||||
);
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework",
|
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -410,11 +408,11 @@
|
|||||||
);
|
);
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.sauci.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sauci.app;
|
||||||
PRODUCT_NAME = "Sauci";
|
PRODUCT_NAME = Sauci;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Sauci/Sauci-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Sauci/Sauci-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1";
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -442,10 +440,10 @@
|
|||||||
);
|
);
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.sauci.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.sauci.app;
|
||||||
PRODUCT_NAME = "Sauci";
|
PRODUCT_NAME = Sauci;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Sauci/Sauci-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Sauci/Sauci-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1";
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
"@expo/ngrok": "^4.1.0",
|
"@expo/ngrok": "^4.1.0",
|
||||||
"@expo/vector-icons": "~14.0.4",
|
"@expo/vector-icons": "~14.0.4",
|
||||||
"@react-native-async-storage/async-storage": "1.23.1",
|
"@react-native-async-storage/async-storage": "1.23.1",
|
||||||
|
"@react-native-firebase/analytics": "^23.8.2",
|
||||||
|
"@react-native-firebase/app": "^23.8.2",
|
||||||
"@react-native-google-signin/google-signin": "^16.1.1",
|
"@react-native-google-signin/google-signin": "^16.1.1",
|
||||||
"@react-navigation/bottom-tabs": "^7.0.0",
|
"@react-navigation/bottom-tabs": "^7.0.0",
|
||||||
"@react-navigation/native": "^7.0.0",
|
"@react-navigation/native": "^7.0.0",
|
||||||
@@ -53,7 +55,6 @@
|
|||||||
"expo-router": "~4.0.0",
|
"expo-router": "~4.0.0",
|
||||||
"expo-secure-store": "~14.0.0",
|
"expo-secure-store": "~14.0.0",
|
||||||
"expo-status-bar": "~2.0.0",
|
"expo-status-bar": "~2.0.0",
|
||||||
"posthog-react-native": "^4.17.1",
|
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-native": "0.76.9",
|
"react-native": "0.76.9",
|
||||||
|
|||||||
@@ -1,7 +1,31 @@
|
|||||||
import PostHog from "posthog-react-native";
|
import { getApp } from "@react-native-firebase/app";
|
||||||
|
import {
|
||||||
|
getAnalytics,
|
||||||
|
logEvent as firebaseLogEvent,
|
||||||
|
setUserId as firebaseSetUserId,
|
||||||
|
setUserProperty,
|
||||||
|
setAnalyticsCollectionEnabled,
|
||||||
|
resetAnalyticsData,
|
||||||
|
FirebaseAnalyticsTypes,
|
||||||
|
} from "@react-native-firebase/analytics";
|
||||||
|
|
||||||
let posthog: PostHog | null = null;
|
|
||||||
let isInitialized = false;
|
let isInitialized = false;
|
||||||
|
let analyticsInstance: FirebaseAnalyticsTypes.Module | null = null;
|
||||||
|
|
||||||
|
function getAnalyticsInstance(): FirebaseAnalyticsTypes.Module | null {
|
||||||
|
if (analyticsInstance) {
|
||||||
|
return analyticsInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const app = getApp();
|
||||||
|
analyticsInstance = getAnalytics(app);
|
||||||
|
return analyticsInstance;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("[Analytics] Failed to get analytics instance:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function initAnalytics() {
|
export async function initAnalytics() {
|
||||||
if (isInitialized) {
|
if (isInitialized) {
|
||||||
@@ -9,30 +33,19 @@ export async function initAnalytics() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip initialization in non-RN environments (e.g., during tsc/Node.js)
|
// Skip initialization in non-RN environments (e.g., during tsc/Node.js)
|
||||||
// AsyncStorage requires window to be defined
|
|
||||||
if (typeof window === "undefined" && typeof global !== "undefined" && !("__BUNDLE_START_TIME__" in global)) {
|
if (typeof window === "undefined" && typeof global !== "undefined" && !("__BUNDLE_START_TIME__" in global)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiKey = process.env.EXPO_PUBLIC_POSTHOG_API_KEY;
|
|
||||||
const host = process.env.EXPO_PUBLIC_POSTHOG_HOST || "https://us.i.posthog.com";
|
|
||||||
|
|
||||||
if (!apiKey) {
|
|
||||||
console.warn("[Analytics] PostHog API key not configured");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
posthog = new PostHog(apiKey, {
|
const analytics = getAnalyticsInstance();
|
||||||
host,
|
if (analytics) {
|
||||||
// Disable automatic capture in production for privacy
|
await setAnalyticsCollectionEnabled(analytics, true);
|
||||||
captureAppLifecycleEvents: true,
|
isInitialized = true;
|
||||||
});
|
console.log("[Analytics] Firebase Analytics initialized");
|
||||||
|
}
|
||||||
isInitialized = true;
|
|
||||||
console.log("[Analytics] PostHog initialized");
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[Analytics] Failed to initialize PostHog:", error);
|
console.warn("[Analytics] Failed to initialize Firebase Analytics:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +56,10 @@ export function logEvent(
|
|||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (__DEV__) console.log("[Analytics] Event:", name, params);
|
if (__DEV__) console.log("[Analytics] Event:", name, params);
|
||||||
posthog?.capture(name, params);
|
const analytics = getAnalyticsInstance();
|
||||||
|
if (analytics) {
|
||||||
|
firebaseLogEvent(analytics, name, params);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[Analytics] Failed to log event:", error);
|
console.warn("[Analytics] Failed to log event:", error);
|
||||||
}
|
}
|
||||||
@@ -53,7 +69,10 @@ export function logEvent(
|
|||||||
export function setUserId(userId: string) {
|
export function setUserId(userId: string) {
|
||||||
try {
|
try {
|
||||||
if (__DEV__) console.log("[Analytics] Set user ID:", userId);
|
if (__DEV__) console.log("[Analytics] Set user ID:", userId);
|
||||||
posthog?.identify(userId);
|
const analytics = getAnalyticsInstance();
|
||||||
|
if (analytics) {
|
||||||
|
firebaseSetUserId(analytics, userId);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[Analytics] Failed to set user ID:", error);
|
console.warn("[Analytics] Failed to set user ID:", error);
|
||||||
}
|
}
|
||||||
@@ -63,7 +82,11 @@ export function setUserId(userId: string) {
|
|||||||
export function clearUserId() {
|
export function clearUserId() {
|
||||||
try {
|
try {
|
||||||
if (__DEV__) console.log("[Analytics] Cleared user ID");
|
if (__DEV__) console.log("[Analytics] Cleared user ID");
|
||||||
posthog?.reset();
|
const analytics = getAnalyticsInstance();
|
||||||
|
if (analytics) {
|
||||||
|
firebaseSetUserId(analytics, null);
|
||||||
|
resetAnalyticsData(analytics);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[Analytics] Failed to clear user ID:", error);
|
console.warn("[Analytics] Failed to clear user ID:", error);
|
||||||
}
|
}
|
||||||
@@ -75,14 +98,13 @@ export function setUserProperties(
|
|||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (__DEV__) console.log("[Analytics] Set user properties:", properties);
|
if (__DEV__) console.log("[Analytics] Set user properties:", properties);
|
||||||
// Filter out null values for PostHog
|
const analytics = getAnalyticsInstance();
|
||||||
const filteredProps: Record<string, string> = {};
|
if (analytics) {
|
||||||
for (const [key, value] of Object.entries(properties)) {
|
// Firebase Analytics requires setting user properties one at a time
|
||||||
if (value !== null) {
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
filteredProps[key] = value;
|
setUserProperty(analytics, key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
posthog?.capture("$set", { $set: filteredProps });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[Analytics] Failed to set user properties:", error);
|
console.warn("[Analytics] Failed to set user properties:", error);
|
||||||
}
|
}
|
||||||
@@ -92,7 +114,13 @@ export function setUserProperties(
|
|||||||
export function logScreenView(screenName: string, screenClass?: string) {
|
export function logScreenView(screenName: string, screenClass?: string) {
|
||||||
try {
|
try {
|
||||||
if (__DEV__) console.log("[Analytics] Screen view:", screenName);
|
if (__DEV__) console.log("[Analytics] Screen view:", screenName);
|
||||||
posthog?.screen(screenName, { screen_class: screenClass ?? screenName });
|
const analytics = getAnalyticsInstance();
|
||||||
|
if (analytics) {
|
||||||
|
firebaseLogEvent(analytics, "screen_view", {
|
||||||
|
screen_name: screenName,
|
||||||
|
screen_class: screenClass ?? screenName,
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[Analytics] Failed to log screen view:", error);
|
console.warn("[Analytics] Failed to log screen view:", error);
|
||||||
}
|
}
|
||||||
@@ -100,11 +128,9 @@ export function logScreenView(screenName: string, screenClass?: string) {
|
|||||||
|
|
||||||
// Flush events (useful before app backgrounding)
|
// Flush events (useful before app backgrounding)
|
||||||
export function flush() {
|
export function flush() {
|
||||||
try {
|
// Firebase Analytics batches and sends events automatically
|
||||||
posthog?.flush();
|
// No manual flush needed, but we keep the function for API compatibility
|
||||||
} catch (error) {
|
if (__DEV__) console.log("[Analytics] Flush called (no-op for Firebase)");
|
||||||
console.warn("[Analytics] Failed to flush:", error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-defined event helpers for common actions
|
// Pre-defined event helpers for common actions
|
||||||
|
|||||||
@@ -120,16 +120,15 @@ jest.mock('base64-arraybuffer', () => ({
|
|||||||
decode: jest.fn(() => new ArrayBuffer(0)),
|
decode: jest.fn(() => new ArrayBuffer(0)),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('posthog-react-native', () => {
|
jest.mock('@react-native-firebase/app', () => ({
|
||||||
return class PostHog {
|
getApp: jest.fn(() => ({})),
|
||||||
capture = jest.fn();
|
}));
|
||||||
identify = jest.fn();
|
|
||||||
reset = jest.fn();
|
|
||||||
screen = jest.fn();
|
|
||||||
flush = jest.fn();
|
|
||||||
|
|
||||||
constructor() {
|
jest.mock('@react-native-firebase/analytics', () => ({
|
||||||
// no-op
|
getAnalytics: jest.fn(() => ({})),
|
||||||
}
|
logEvent: jest.fn(),
|
||||||
};
|
setUserId: jest.fn(),
|
||||||
});
|
setUserProperty: jest.fn(),
|
||||||
|
setAnalyticsCollectionEnabled: jest.fn(() => Promise.resolve()),
|
||||||
|
resetAnalyticsData: jest.fn(),
|
||||||
|
}));
|
||||||
Generated
+896
-223
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user