@umituz/react-native-firebase 1.7.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-firebase",
3
- "version": "1.7.4",
3
+ "version": "1.8.0",
4
4
  "description": "Unified Firebase package for React Native apps - Centralized initialization and core services (Analytics, Crashlytics).",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -33,8 +33,13 @@
33
33
  "react-native": ">=0.74.0"
34
34
  },
35
35
  "devDependencies": {
36
+ "@react-native-firebase/analytics": "^23.7.0",
37
+ "@react-native-firebase/app": "^23.7.0",
38
+ "@react-native-firebase/crashlytics": "^23.7.0",
39
+ "@react-navigation/native": "^7.1.26",
36
40
  "@types/react": "~19.1.0",
37
41
  "firebase": "^12.6.0",
42
+ "react-native": "^0.83.1",
38
43
  "typescript": "~5.9.2"
39
44
  },
40
45
  "publishConfig": {
@@ -14,6 +14,7 @@ export { performanceTracker } from './infrastructure/services/PerformanceTracker
14
14
  export { useScreenView } from './presentation/hooks/useScreenView';
15
15
  export { useScreenTime } from './presentation/hooks/useScreenTime';
16
16
  export { useNavigationTracking } from './presentation/hooks/useNavigationTracking';
17
+ export { useNavigationAnalytics } from './presentation/hooks/useNavigationAnalytics';
17
18
 
18
19
  // Utility Functions
19
20
  export { trackButtonClick, trackCRUDOperation } from './presentation/utils/analyticsUtils';
@@ -38,22 +38,6 @@ class FirebaseAnalyticsService implements IAnalyticsService {
38
38
 
39
39
  // Explicitly enable analytics collection to ensure it's active
40
40
  await this.setAnalyticsCollectionEnabled(true);
41
-
42
- /* eslint-disable-next-line no-console */
43
- if (__DEV__) {
44
- console.log('✅ Firebase Analytics initialized successfully', {
45
- platform: this.analyticsInstance.platform,
46
- userId: userId || 'guest',
47
- });
48
- }
49
- } else {
50
- /* eslint-disable-next-line no-console */
51
- if (__DEV__) {
52
- console.warn('⚠️ Firebase Analytics: Initialization returned null instance', {
53
- reason: 'Native module not available or web analytics not supported',
54
- note: 'Events will be logged to console but not sent to Firebase',
55
- });
56
- }
57
41
  }
58
42
  } catch (_error) {
59
43
  // Analytics is non-critical, fail silently
@@ -103,12 +87,6 @@ class FirebaseAnalyticsService implements IAnalyticsService {
103
87
  params?: Record<string, string | number | boolean | null>,
104
88
  ): Promise<void> {
105
89
  if (!this.isInitialized) {
106
- /* eslint-disable-next-line no-console */
107
- if (__DEV__) {
108
- console.warn('⚠️ Firebase Analytics: Cannot log event - Service not initialized', {
109
- eventName,
110
- });
111
- }
112
90
  return;
113
91
  }
114
92
  await analyticsEventService.logEvent(this.analyticsInstance, eventName, params);
@@ -61,11 +61,10 @@ export class AnalyticsInitializerService {
61
61
  }
62
62
 
63
63
  // Try to get Firebase App instance to check if it's initialized
64
- let firebaseApp: any = null;
65
64
  try {
66
65
  // eslint-disable-next-line @typescript-eslint/no-require-imports
67
66
  const firebaseAppModule = require('@react-native-firebase/app');
68
- firebaseApp = firebaseAppModule.app();
67
+ firebaseAppModule.app();
69
68
  } catch (appError: any) {
70
69
  /* eslint-disable-next-line no-console */
71
70
  if (__DEV__) {
@@ -57,6 +57,7 @@ export function TrackOperation(
57
57
  operation: operationName,
58
58
  method: propertyKey,
59
59
  success: false,
60
+ errorType,
60
61
  duration_ms: Date.now() - startTime,
61
62
  });
62
63
 
@@ -0,0 +1,118 @@
1
+ /**
2
+ * useNavigationAnalytics Hook
3
+ *
4
+ * Tracks navigation analytics at app level for NavigationContainer
5
+ * Migrated to Firebase modular SDK (v22+)
6
+ *
7
+ * Features:
8
+ * - Screen view tracking
9
+ * - Screen time measurement
10
+ * - Navigation flow analytics
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { useNavigationAnalytics } from '@umituz/react-native-firebase';
15
+ *
16
+ * function App() {
17
+ * const { handleNavigationReady, handleNavigationStateChange } = useNavigationAnalytics();
18
+ *
19
+ * return (
20
+ * <NavigationContainer
21
+ * onReady={() => handleNavigationReady(navigationRef)}
22
+ * onStateChange={() => handleNavigationStateChange(navigationRef)}
23
+ * >
24
+ * <AppNavigator />
25
+ * </NavigationContainer>
26
+ * );
27
+ * }
28
+ * ```
29
+ */
30
+
31
+ import { useRef } from "react";
32
+ import { firebaseAnalyticsService } from "../../infrastructure/services/FirebaseAnalyticsService";
33
+
34
+ export const useNavigationAnalytics = () => {
35
+ const routeNameRef = useRef<string | undefined>(undefined);
36
+ const screenStartTimeRef = useRef<number | undefined>(undefined);
37
+
38
+ const getActiveRouteName = (state: any): string | undefined => {
39
+ if (!state || !state.routes) return undefined;
40
+ const route = state.routes[state.index];
41
+ if (route.state) {
42
+ return getActiveRouteName(route.state);
43
+ }
44
+ return route.name;
45
+ };
46
+
47
+ const handleNavigationReady = (navigationRef: any) => {
48
+ const currentRouteName = getActiveRouteName(
49
+ navigationRef.current?.getRootState(),
50
+ );
51
+ routeNameRef.current = currentRouteName;
52
+ screenStartTimeRef.current = Date.now();
53
+
54
+ if (currentRouteName) {
55
+ firebaseAnalyticsService
56
+ .logScreenView({
57
+ screen_name: currentRouteName,
58
+ screen_class: currentRouteName,
59
+ })
60
+ .catch(() => {
61
+ // Silent fail - analytics is non-critical
62
+ });
63
+ }
64
+ };
65
+
66
+ const handleNavigationStateChange = async (navigationRef: any) => {
67
+ const previousRouteName = routeNameRef.current;
68
+ const currentRouteName = getActiveRouteName(
69
+ navigationRef.current?.getRootState(),
70
+ );
71
+
72
+ if (previousRouteName !== currentRouteName && currentRouteName) {
73
+ if (previousRouteName && screenStartTimeRef.current) {
74
+ const timeSpent = Math.round(
75
+ (Date.now() - screenStartTimeRef.current) / 1000,
76
+ );
77
+ await firebaseAnalyticsService
78
+ .logScreenTime({
79
+ screen_name: previousRouteName,
80
+ screen_class: previousRouteName,
81
+ time_spent_seconds: timeSpent,
82
+ })
83
+ .catch(() => {
84
+ // Silent fail - analytics is non-critical
85
+ });
86
+ }
87
+
88
+ await firebaseAnalyticsService
89
+ .logScreenView({
90
+ screen_name: currentRouteName,
91
+ screen_class: currentRouteName,
92
+ })
93
+ .catch(() => {
94
+ // Silent fail - analytics is non-critical
95
+ });
96
+
97
+ if (previousRouteName) {
98
+ await firebaseAnalyticsService
99
+ .logNavigation({
100
+ from_screen: previousRouteName,
101
+ to_screen: currentRouteName,
102
+ screen_class: currentRouteName,
103
+ })
104
+ .catch(() => {
105
+ // Silent fail - analytics is non-critical
106
+ });
107
+ }
108
+
109
+ routeNameRef.current = currentRouteName;
110
+ screenStartTimeRef.current = Date.now();
111
+ }
112
+ };
113
+
114
+ return {
115
+ handleNavigationReady,
116
+ handleNavigationStateChange,
117
+ };
118
+ };
@@ -44,14 +44,6 @@ export function useNavigationTracking(
44
44
 
45
45
  // Log navigation if coming from another screen
46
46
  if (previousScreenRef.current && previousScreenRef.current !== screenName) {
47
- /* eslint-disable-next-line no-console */
48
- if (__DEV__) {
49
- console.log("📊 Navigation tracked:", {
50
- from: previousScreenRef.current,
51
- to: screenName,
52
- });
53
- }
54
-
55
47
  firebaseAnalyticsService
56
48
  .logNavigation({
57
49
  from_screen: previousScreenRef.current,
@@ -19,8 +19,6 @@ export interface ICrashlyticsService {
19
19
  }
20
20
 
21
21
  class FirebaseCrashlyticsService implements ICrashlyticsService {
22
- private isInitialized = false;
23
- private userId: string | null = null;
24
22
  private attributes: Record<string, string> = {};
25
23
  private crashlytics: CrashlyticsInstance | null = null;
26
24
  private isDestroyed = false;
@@ -39,10 +37,9 @@ class FirebaseCrashlyticsService implements ICrashlyticsService {
39
37
 
40
38
  if (this.crashlytics) {
41
39
  if (userId) {
42
- this.userId = userId;
43
40
  await crashlyticsUserService.setUserId(this.crashlytics, userId);
44
41
  }
45
-
42
+
46
43
  if (attributes) {
47
44
  await this.setAttributes(attributes);
48
45
  }
@@ -53,7 +50,6 @@ class FirebaseCrashlyticsService implements ICrashlyticsService {
53
50
  console.warn('[Crashlytics] Init failed:', err);
54
51
  }
55
52
  } finally {
56
- this.isInitialized = true;
57
53
  }
58
54
  }
59
55
 
@@ -82,14 +78,12 @@ class FirebaseCrashlyticsService implements ICrashlyticsService {
82
78
  async clearUserData(): Promise<void> {
83
79
  if (this.isDestroyed) return;
84
80
  await crashlyticsUserService.clearUserData(this.crashlytics);
85
- this.userId = null;
86
81
  this.attributes = {};
87
- this.isInitialized = false;
88
82
  }
89
83
 
90
84
  async destroy(): Promise<void> {
91
85
  if (this.isDestroyed) return;
92
-
86
+
93
87
  await this.clearUserData();
94
88
  this.crashlytics = null;
95
89
  this.isDestroyed = true;