From f29f2878b01bed2450346def558398fe6159521a Mon Sep 17 00:00:00 2001 From: Shawn Jackson Date: Mon, 29 Sep 2025 17:52:42 -0700 Subject: [PATCH 1/2] CU-868frkzum Fixed issue with broken onboarding screens. --- ANALYTICS_MIGRATION.md | 107 -------------------------- src/app/__tests__/onboarding.test.tsx | 2 +- src/app/onboarding.tsx | 69 ++++++++++++----- src/components/ui/index.tsx | 7 +- 4 files changed, 56 insertions(+), 129 deletions(-) delete mode 100644 ANALYTICS_MIGRATION.md diff --git a/ANALYTICS_MIGRATION.md b/ANALYTICS_MIGRATION.md deleted file mode 100644 index 6a4bdab..0000000 --- a/ANALYTICS_MIGRATION.md +++ /dev/null @@ -1,107 +0,0 @@ -# Analytics Migration: Aptabase to Countly - -## Overview -Successfully migrated the project from Aptabase analytics to Countly with minimal disruption to the codebase. - -## What Was Changed - -### 1. Dependencies -- ❌ **Removed**: `@aptabase/react-native` -- ✅ **Added**: `countly-sdk-react-native-bridge@25.4.0` - -### 2. Analytics Service (`src/services/analytics.service.ts`) -- **Completely rewritten** to use Countly SDK -- **Maintained same interface** for components (same method names and signatures) -- **Enhanced error handling** with retry logic and graceful degradation -- **Added comprehensive session management** (start, end, extend) -- **Proper user properties support** -- **Environment-driven initialization** with fallback configuration - -#### Key Features: -- ✅ Event tracking with properties -- ✅ User properties management -- ✅ Session lifecycle management -- ✅ Error handling with retry mechanism -- ✅ Service status monitoring -- ✅ Graceful degradation on failures - -### 3. Hook Integration (`src/hooks/use-analytics.ts`) -- **Updated** to use new `analyticsService` instead of `aptabaseService` -- **Interface unchanged** - components continue working without modifications -- **Performance optimized** with `useCallback` - -### 4. Environment Configuration -- **Updated** `env.js` to support Countly variables: - - `RESPOND_COUNTLY_APP_KEY` (replaces `RESPOND_APTABASE_APP_KEY`) - - `RESPOND_COUNTLY_URL` (replaces `RESPOND_APTABASE_URL`) -- **Updated** `.env.development` with new variable names - -### 5. App Initialization -- **Integrated** analytics service into `AppInitializationService` -- **Automatic initialization** during app startup -- **Proper error handling** - analytics failures don't break app startup -- **Environment-based configuration** - uses env vars automatically - -### 6. Removed Components -- ❌ **Deleted**: `src/components/common/aptabase-provider.tsx` -- ❌ **Removed**: All references to `AptabaseProviderWrapper` in `_layout.tsx` -- ❌ **Cleaned up**: Old Aptabase mocks in test files - -### 7. Test Coverage -- ✅ **New comprehensive test suite** for `analytics.service.ts` (23 passing tests) -- ✅ **Updated hook tests** to use new service -- ✅ **Cleaned up** old Aptabase references in component tests -- ✅ **All tests passing** for analytics-related code - -## Migration Benefits - -### ✅ Minimal Disruption -- **Zero changes** required in components using analytics -- **Same API interface** maintained across the migration -- **Existing analytics calls** continue working unchanged - -### ✅ Enhanced Reliability -- **Better error handling** with exponential backoff retry logic -- **Graceful degradation** when analytics fails -- **Service status monitoring** with automatic recovery -- **Proper session management** - -### ✅ Improved Architecture -- **Centralized initialization** through AppInitializationService -- **Environment-driven configuration** -- **Comprehensive test coverage** -- **Better logging and debugging** - -## Configuration Required - -To complete the setup, you need to configure the environment variables: - -```bash -# In your .env files (development, staging, production) -RESPOND_COUNTLY_APP_KEY=your_countly_app_key_here -RESPOND_COUNTLY_URL=https://your-countly-server.com -``` - -## Testing Status - -✅ **All analytics tests passing**: -- `src/services/__tests__/analytics.service.test.ts` - 23 tests ✅ -- `src/hooks/__tests__/use-analytics.test.ts` - All tests ✅ -- Component integration tests working ✅ - -## Next Steps - -1. **Configure Countly server credentials** in environment files -2. **Test in development environment** to verify data flow -3. **Deploy to staging** for validation -4. **Monitor analytics data** to ensure proper tracking - -## Rollback Plan (if needed) - -If rollback is required: -1. Reinstall: `yarn add @aptabase/react-native` -2. Restore: `src/services/aptabase.service.ts` from git history -3. Revert: Environment variable changes -4. Restore: `AptabaseProviderWrapper` in `_layout.tsx` - -However, the migration maintains full API compatibility, so rollback should not be necessary. diff --git a/src/app/__tests__/onboarding.test.tsx b/src/app/__tests__/onboarding.test.tsx index e3f7584..7b21fe7 100644 --- a/src/app/__tests__/onboarding.test.tsx +++ b/src/app/__tests__/onboarding.test.tsx @@ -213,7 +213,7 @@ describe('Onboarding Component', () => { expect(getByTestId('onboarding-flatlist')).toBeTruthy(); expect(getByText('Skip')).toBeTruthy(); - // The FlatList content might not render immediately in tests, + // The FlashList content might not render immediately in tests, // so we verify the component renders without crashing expect(getByTestId('onboarding-flatlist')).toBeTruthy(); }); diff --git a/src/app/onboarding.tsx b/src/app/onboarding.tsx index a4393e0..ff00185 100644 --- a/src/app/onboarding.tsx +++ b/src/app/onboarding.tsx @@ -3,7 +3,7 @@ import { FlashList } from '@shopify/flash-list'; import { useRouter } from 'expo-router'; import { Bell, ChevronRight, MapPin, Users } from 'lucide-react-native'; import { useColorScheme } from 'nativewind'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useRef, useState } from 'react'; import { Dimensions, Image } from 'react-native'; import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'; @@ -42,11 +42,40 @@ const onboardingData: OnboardingItemProps[] = [ ]; const OnboardingItem: React.FC = ({ title, description, icon }) => { + const { colorScheme } = useColorScheme(); + return ( - - {icon} - {title} - {description} + + {icon} + + {title} + + + {description} + ); }; @@ -140,19 +169,23 @@ export default function Onboarding() { - } - horizontal - showsHorizontalScrollIndicator={false} - pagingEnabled - bounces={false} - keyExtractor={(item: OnboardingItemProps) => item.title} - onScroll={handleScroll} - scrollEventThrottle={16} - testID="onboarding-flatlist" - /> + + } + horizontal + showsHorizontalScrollIndicator={false} + pagingEnabled + bounces={false} + keyExtractor={(item: OnboardingItemProps) => item.title} + onScroll={handleScroll} + scrollEventThrottle={16} + estimatedItemSize={width} + getItemType={() => 'onboarding-item'} + testID="onboarding-flatlist" + /> + diff --git a/src/components/ui/index.tsx b/src/components/ui/index.tsx index 4847d9e..ff38aec 100644 --- a/src/components/ui/index.tsx +++ b/src/components/ui/index.tsx @@ -1,7 +1,7 @@ import { cssInterop } from 'nativewind'; import Svg from 'react-native-svg'; -//export * from './button'; +export * from './button'; export * from './checkbox'; export * from './cover'; export * from './focus-aware-status-bar'; @@ -9,13 +9,14 @@ export * from './focus-aware-status-bar'; //export * from './input'; //export * from './list'; //export * from './modal'; +export * from './pressable'; //export * from './progress-bar'; //export * from './select'; -//export * from './text'; +export * from './text'; //export * from './utils'; // export base components from react-native -export { ActivityIndicator, Pressable, ScrollView, TouchableOpacity, View } from 'react-native'; +export { ActivityIndicator, ScrollView, TouchableOpacity, View } from 'react-native'; export { SafeAreaView } from 'react-native-safe-area-context'; //Apply cssInterop to Svg to resolve className string into style From e7e5018e83b087304f339e1318ce82abce317bc3 Mon Sep 17 00:00:00 2001 From: Shawn Jackson Date: Mon, 29 Sep 2025 18:12:09 -0700 Subject: [PATCH 2/2] CU-868frkzum PR#78 fixes. --- src/app/onboarding.tsx | 100 ++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/src/app/onboarding.tsx b/src/app/onboarding.tsx index ff00185..8414f39 100644 --- a/src/app/onboarding.tsx +++ b/src/app/onboarding.tsx @@ -3,8 +3,8 @@ import { FlashList } from '@shopify/flash-list'; import { useRouter } from 'expo-router'; import { Bell, ChevronRight, MapPin, Users } from 'lucide-react-native'; import { useColorScheme } from 'nativewind'; -import React, { useCallback, useRef, useState } from 'react'; -import { Dimensions, Image } from 'react-native'; +import React, { useCallback, useMemo, useRef, useState } from 'react'; +import { Dimensions, Image, StyleSheet } from 'react-native'; import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'; import { FocusAwareStatusBar, SafeAreaView, View } from '@/components/ui'; @@ -17,6 +17,50 @@ import { useIsFirstTime } from '@/lib/storage'; const { width } = Dimensions.get('window'); +// Color constants +const COLORS = { + primary: '#FF7B1A', + text: { + light: { + primary: '#1f2937', + secondary: '#6b7280', + }, + dark: { + primary: '#ffffff', + secondary: '#d1d5db', + }, + }, +}; + +// Static styles +const styles = StyleSheet.create({ + onboardingContainer: { + height: 400, + justifyContent: 'center', + alignItems: 'center', + paddingHorizontal: 32, + }, + iconContainer: { + marginBottom: 32, + alignItems: 'center', + }, + title: { + fontSize: 28, + fontWeight: 'bold', + textAlign: 'center', + marginBottom: 16, + }, + description: { + fontSize: 16, + textAlign: 'center', + lineHeight: 24, + }, + flexContainer: { + flex: 1, + minHeight: 400, + }, +}); + type OnboardingItemProps = { title: string; description: string; @@ -27,55 +71,37 @@ const onboardingData: OnboardingItemProps[] = [ { title: 'Resgrid Responder', description: 'Manage your status, staffing, and interact with your organization in real-time', - icon: , + icon: , }, { title: 'Instant Notifications', description: 'Receive immediate alerts for emergencies and important updates from your department', - icon: , + icon: , }, { title: 'Interact with Calls', description: 'Seamlessly view call information and interact with your team members for efficient emergency response', - icon: , + icon: , }, ]; const OnboardingItem: React.FC = ({ title, description, icon }) => { const { colorScheme } = useColorScheme(); + // Compute dynamic colors once using useMemo + const textColors = useMemo(() => { + const isDark = colorScheme === 'dark'; + return { + title: isDark ? COLORS.text.dark.primary : COLORS.text.light.primary, + description: isDark ? COLORS.text.dark.secondary : COLORS.text.light.secondary, + }; + }, [colorScheme]); + return ( - - {icon} - - {title} - - - {description} - + + {icon} + {title} + {description} ); }; @@ -169,7 +195,7 @@ export default function Onboarding() { - +