Commit Graph

16 Commits

Author SHA1 Message Date
Trey t
c5f2bee83f Harden iOS app: fix concurrency, animations, formatters, privacy, and logging
- Eliminate NumberFormatters shared singleton data race; use local formatters
- Add reduceMotion checks to empty-state animations in 3 list views
- Wrap 68+ print() statements in #if DEBUG across push notification code
- Remove redundant .receive(on: DispatchQueue.main) in SubscriptionCache
- Remove redundant initializeLookups() call from iOSApp.init()
- Clean up StoreKitManager Task capture in listenForTransactions()
- Add memory warning observer to AuthenticatedImage cache
- Cache parseContent result in UpgradePromptView init
- Add DiskSpace and FileTimestamp API declarations to Privacy Manifest
- Add FIXME for analytics debug/production API key separation
- Use static formatter in PropertyHeaderCard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:15:42 -06:00
Trey t
7444f73b46 Close all 25 codex audit findings across KMP, iOS, and Android
Remediate all P0-S priority findings from cross-platform architecture audit:
- Harden token storage with EncryptedSharedPreferences (Android) and Keychain (iOS)
- Add SSL pinning and certificate validation to API clients
- Fix subscription cache race conditions and add thread-safe access
- Add input validation for document uploads and file type restrictions
- Refactor DocumentApi to use proper multipart upload flow
- Add rate limiting awareness and retry logic to API layer
- Harden subscription tier enforcement in SubscriptionHelper
- Add biometric prompt for sensitive actions (Login, Onboarding)
- Fix notification permission handling and device registration
- Add UI test infrastructure (page objects, fixtures, smoke tests)
- Add CI workflow for mobile builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:15:34 -06:00
Trey t
2fc4a48fc9 Replace PostHog integration with AnalyticsManager architecture
Remove old PostHogAnalytics singleton and replace with guide-based
two-file architecture: AnalyticsManager (singleton wrapper with super
properties, session replay, opt-out, subscription funnel) and
AnalyticsEvent (type-safe enum with associated values).

Key changes:
- New API key, self-hosted analytics endpoint
- All 19 events ported to type-safe AnalyticsEvent enum
- Screen tracking via AnalyticsManager.Screen enum + SwiftUI modifier
- Remove all identify() calls — fully anonymous analytics
- Add lifecycle hooks: flush on background, update super properties on foreground
- Add privacy opt-out toggle in Settings
- Subscription funnel methods ready for IAP integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 09:48:49 -06:00
Trey t
556b187508 Add background task for overnight widget data refresh
- Create BackgroundTaskManager that schedules refresh at random time
  between 12:00 AM - 4:00 AM local time
- Fetches tasks from API, writes to DataManager and shared App Group
- Reloads widget timelines after refresh
- Register task in AppDelegate, schedule when app goes to background
- Add BGTaskSchedulerPermittedIdentifiers and fetch/processing modes to Info.plist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 20:36:17 -06:00
Trey t
cbe073aa21 Add push notification deep linking and sharing subscription checks
- Add deep link navigation from push notifications to specific task column on kanban board
- Fix subscription check in push notification handler to allow navigation when limitations disabled
- Add pendingNavigationTaskId to handle notifications when app isn't ready
- Add ScrollViewReader to AllTasksView for programmatic scrolling to task column
- Add canShareResidence() and canShareContractor() subscription checks (iOS & Android)
- Add test APNS file for simulator push notification testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 23:17:28 -06:00
Trey t
2965ec4031 Add actionable push notifications for iOS and Android
iOS:
- Add notification categories with action buttons (complete, view, cancel, etc.)
- Handle notification actions in AppDelegate with API calls
- Add navigation to specific task from notification tap
- Register UNNotificationCategory for each task state

Android:
- Add NotificationActionReceiver BroadcastReceiver for handling actions
- Update MyFirebaseMessagingService to show action buttons
- Add deep link handling in MainActivity for task navigation
- Register receiver in AndroidManifest.xml

Shared:
- Add navigateToTaskId parameter to App for cross-platform navigation
- Add notification observers in MainTabView/AllTasksView for refresh

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 14:23:25 -06:00
Trey t
70d46da14a Add smart device token caching for push notification registration
Cache device token in UserDefaults and only register with backend when
token changes. Also registers when app returns from background if token
differs from cached value, reducing unnecessary API calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 20:18:08 -06:00
Trey t
c748f792d0 Add notification preferences UI and subscription verification on launch
- Add NotificationPreferencesScreen (Android) and NotificationPreferencesView (iOS)
- Add NotificationPreferencesViewModel for shared business logic
- Wire up notification preferences from ProfileScreen on both platforms
- Add subscription verification on app launch for iOS (StoreKit) and Android (Google Play Billing)
- Update SubscriptionApi to match Go backend endpoints (/subscription/purchase/)
- Update StoreKit Configuration with correct product IDs and pricing ($2.99/month, $27.99/year)
- Update Android placeholder prices to match App Store pricing
- Fix NotificationPreference model to match Go backend schema

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 14:01:35 -06:00
Trey t
ce1ca0f0ce Optimize subscription tier management and empty state logic
Changes:
- Make currentTier a computed property from StoreKit instead of stored value
- Initialize StoreKit at app launch and refresh on foreground for ready subscription status
- Fix empty state logic: show empty state when limit > 0, upgrade prompt when limit = 0
- Add subscription status display in Profile screen (iOS/Android)
- Add upgrade prompts to Residences and Tasks screens for free tier users
- Improve SubscriptionHelper with better tier checking logic

iOS:
- SubscriptionCache: currentTier now computed from StoreKit.purchasedProductIDs
- StoreKitManager: add refreshSubscriptionStatus() method
- AppDelegate: initialize StoreKit at launch and refresh on app active
- ContractorsListView: use shouldShowUpgradePrompt(currentCount:limitKey:)
- WarrantiesTabContent/DocumentsTabContent: same empty state fix
- ProfileTabView: display current tier and limitations status
- ResidencesListView/ResidenceDetailView: add upgrade prompts for free users
- AllTasksView: add upgrade prompt for free users

Android:
- ContractorsScreen/DocumentsScreen: fix empty state logic
- ProfileScreen: display subscription status and limits
- ResidencesScreen/ResidenceDetailScreen: add upgrade prompts
- UpgradeFeatureScreen: improve UI layout

Shared:
- APILayer: add getSubscriptionStatus() method
- SubscriptionHelper: add hasAccessToFeature() utility
- Remove duplicate subscription checking logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:59:09 -06:00
Trey t
b2c3fac3f9 Update warranty status to use backend calculation and add comprehensive tests
Client-Side Changes:
- Add WarrantyStatus data class to Document model for backend-calculated status
- Update WarrantyCard to display backend status (statusText, statusColor) with client fallback
- Fix document list refresh: call loadDocuments() after create/update operations

Testing:
- Add ComprehensiveDocumentWarrantyTests with 25+ XCUITest cases
- Test document creation, update, delete, image upload
- Test warranty-specific fields and property selection
- Test both general documents and warranties
- Includes helper methods for form interaction and cleanup

Other:
- Update ApiConfig and PushNotificationManager

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 13:09:55 -06:00
Trey t
a2de0f3454 Migrate iOS app to system colors and improve UI/UX
- Remove AppColors struct, migrate to iOS system colors throughout
- Redesign ContractorFormSheet to use native SwiftUI Form components
- Add color-coded icons to contractor form sections
- Improve dark mode contrast for task cards
- Add background colors to document detail fields
- Fix text alignment issues in ContractorDetailView
- Make task completion lists expandable/collapsible by default
- Clear app badge on launch and when app becomes active
- Update button styling with proper gradients and shadows
- Improve form field focus states and accessibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 22:22:52 -06:00
Trey t
ff390a85c2 ios push notifications 2025-11-13 16:13:36 -06:00
Trey t
2b95c3b9c1 Refactor iOS forms and integrate notification API with APILayer
- Refactored ContractorFormSheet to follow SwiftUI best practices
  - Moved Field enum outside struct and renamed to ContractorFormField
  - Extracted body into computed properties for better readability
  - Replaced deprecated NavigationView with NavigationStack
  - Fixed input field contrast in light mode by adding borders
  - Fixed force cast in loadContractorSpecialties

- Refactored TaskFormView to eliminate screen flickering
  - Moved Field enum outside struct and renamed to TaskFormField
  - Fixed conditional view structure that caused flicker on load
  - Used ZStack with overlay instead of if/else for loading state
  - Changed to .task modifier for proper async initialization
  - Made loadLookups properly async and fixed force casts
  - Replaced deprecated NavigationView with NavigationStack

- Integrated PushNotificationManager with APILayer
  - Updated registerDeviceWithBackend to use APILayer.shared.registerDevice()
  - Updated updateNotificationPreferences to use APILayer
  - Updated getNotificationPreferences to use APILayer
  - Added proper error handling with try-catch pattern

- Added notification operations to APILayer
  - Added NotificationApi instance
  - Implemented registerDevice, unregisterDevice
  - Implemented getNotificationPreferences, updateNotificationPreferences
  - Implemented getNotificationHistory, markNotificationAsRead
  - Implemented markAllNotificationsAsRead, getUnreadCount
  - All methods follow consistent pattern with auth token handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 13:12:54 -06:00
Trey t
a61cada072 Implement unified network layer with APILayer and migrate iOS ViewModels
Major architectural improvements:
- Created APILayer as single entry point for all network operations
- Integrated cache-first reads with automatic cache updates on mutations
- Migrated all shared Kotlin ViewModels to use APILayer instead of direct API calls
- Migrated iOS ViewModels to wrap shared Kotlin ViewModels with StateFlow observation
- Replaced LookupsManager with DataCache for centralized lookup data management
- Added password reset methods to AuthViewModel
- Added task completion and update methods to APILayer
- Added residence user management methods to APILayer

iOS specific changes:
- Updated LoginViewModel, RegisterViewModel, ProfileViewModel to use shared AuthViewModel
- Updated ContractorViewModel, DocumentViewModel to use shared ViewModels
- Updated ResidenceViewModel to use shared ViewModel and APILayer
- Updated TaskViewModel to wrap shared ViewModel with callback-based interface
- Migrated PasswordResetViewModel and VerifyEmailViewModel to shared AuthViewModel
- Migrated AllTasksView, CompleteTaskView, EditTaskView to use APILayer
- Migrated ManageUsersView, ResidenceDetailView to use APILayer
- Migrated JoinResidenceView to use async/await pattern with APILayer
- Removed LookupsManager.swift in favor of DataCache
- Fixed PushNotificationManager @MainActor issue
- Converted all direct API calls to use async/await with proper error handling

Benefits:
- Reduced code duplication between iOS and Android
- Consistent error handling across platforms
- Automatic cache management for better performance
- Centralized network layer for easier testing and maintenance
- Net reduction of ~700 lines of code through shared logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-12 20:29:42 -06:00
Trey t
b888315e0c Complete iOS document form implementation and improve login error handling
This commit completes the DRY refactoring by implementing the missing document form functionality and enhancing user experience with better error messages.

## iOS Document Forms
- Implemented complete createDocument() method in DocumentViewModel:
  - Support for all warranty-specific fields (itemName, modelNumber, serialNumber, provider, etc.)
  - Multiple image uploads with JPEG compression
  - Proper UIImage to KotlinByteArray conversion
  - Async completion handlers
- Implemented updateDocument() method with full field support
- Completed DocumentFormView submitForm() implementation with proper API calls
- Fixed type conversion issues (Bool/KotlinBoolean, Int32/KotlinInt)
- Added proper error handling and user feedback

## iOS Login Error Handling
- Enhanced error messages to be user-friendly and concise
- Added specific messages for common HTTP error codes (400, 401, 403, 404, 500+)
- Implemented cleanErrorMessage() helper to remove technical jargon
- Added network-specific error handling (connection, timeout)
- Fixed MainActor isolation warnings with proper Task wrapping

## Code Quality
- Removed ~4,086 lines of duplicate code through form consolidation
- Added 429 lines of new shared form components
- Fixed Swift compiler performance issues
- Ensured both iOS and Android builds succeed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-12 11:35:41 -06:00
Trey t
ec7c01e92d Add push notification support for Android and iOS
- Integrated Firebase Cloud Messaging (FCM) for Android
- Integrated Apple Push Notification Service (APNs) for iOS
- Created shared notification models and API client
- Added device registration and token management
- Added notification permission handling for Android
- Created PushNotificationManager for iOS with AppDelegate
- Added placeholder google-services.json (needs to be replaced with actual config)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 22:39:39 -06:00