Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ import AppNavigator from './src/navigation/AppNavigator';
import { setupNotificationNavigation } from './src/navigation/linking';
import { apiClient } from './src/services/api';
import { crashReportingService } from './src/services/cashReporting';
import { featureCapabilities } from './src/services/featureCapabilities';
import { mobileAuthService } from './src/services/mobileAuth';
import {
addNotificationReceivedListener,
getLastNotificationResponse,
removeNotificationListener,
addNotificationReceivedListener,
getLastNotificationResponse,
removeNotificationListener,
} from './src/services/pushNotifications';
import { requestQueue } from './src/services/requestQueue';
import socketService from './src/services/socket';
import syncService from './src/services/syncService';
import { useAppStore } from './src/store';
import { useDegradationStore } from './src/store/degradationStore';
import { handleCacheVersionUpdate } from './src/utils/cacheVersioning';
import { requireEnvVariables } from './src/utils/env';
import { appLogger } from './src/utils/logger';
Expand Down Expand Up @@ -120,6 +122,28 @@ const App = () => {
// Connect to socket when app starts
socketService.connect();

// Initialize feature capability detection (non-blocking)
// This determines which features are available and updates degradation state
featureCapabilities.checkAllCapabilities()
.then(capabilities => {
const degradationStore = useDegradationStore.getState();
appLogger.infoSync('[App] Feature capabilities checked', {
camera: capabilities.camera.status,
notifications: capabilities.pushNotifications.status,
location: capabilities.location.status,
});
// Update degradation store with current feature statuses
Object.entries(capabilities).forEach(([feature, info]) => {
if (feature !== 'checkedAt' && 'status' in info) {
degradationStore.setFeatureStatus(feature as any, info.status);
}
});
})
.catch(error => {
appLogger.errorSync('[App] Error checking feature capabilities', error instanceof Error ? error : new Error(String(error)));
// Continue app startup - degradation will be detected on-demand
});

// Initialize push notifications: request permissions and get device token
registerForPushNotifications().then(async (token) => {
if (token) {
Expand Down
37 changes: 37 additions & 0 deletions docs/GRACEFUL_DEGRADATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Graceful Degradation Strategy

This document outlines TeachLink Mobile's approach to graceful degradation when device features or permissions are unavailable.

## Goals

- Avoid crashes when hardware or permissions are missing.
- Provide clear user feedback and fallback UX.
- Maintain core app functionality with degraded capabilities.

## Features Covered

- Camera (photo capture & gallery)
- Push Notifications
- Location

## Strategy

1. Detect capabilities at startup using `src/services/featureCapabilities.ts`.
2. Persist degradation state in `src/store/degradationStore.ts`.
3. Provide hooks with fallbacks: `src/hooks/useCamera.ts`, `src/hooks/useLocation.ts`.
4. Provide UI components to inform users: `src/components/DegradationBanner.tsx`.
5. Use `locationService` to attempt GPS, then cached, then manual entry.
6. Use in-app notifications when push notifications unavailable.

## Developer Notes

- When adding new features that require hardware or permissions, update `featureCapabilities` and `degradationStore` accordingly.
- Use `degradationStore.addNotification()` to notify users about degraded features.
- Prefer non-blocking initialization; detect capabilities asynchronously.

## Testing

- Test on simulator to verify push notification degradation behavior.
- Deny permissions to test camera fallback to library and manual location entry.
- Test devices without GPS to ensure manual flow works.

Loading
Loading