6.4 KiB
6.4 KiB
38. Android App — Dashboard and Service Screens
meta: id: shieldai-unified-restructure-38 feature: shieldai-unified-restructure priority: P1 depends_on: [shieldai-unified-restructure-34, shieldai-unified-restructure-35, shieldai-unified-restructure-36, shieldai-unified-restructure-37] tags: [android, jetpack-compose, dashboard, services, mobile]
objective:
- Build the main dashboard and all service-specific screens for the Android app. These should mirror the web app's functionality while using native Android UI patterns (lists, cards, bottom sheets, charts).
deliverables:
android/app/src/main/java/com/shieldai/android/ui/screens/dashboard/— Dashboard:DashboardScreen.kt— Main dashboard with scrollable content:- Threat score circular gauge (custom Canvas composable)
- Recent alerts list (top 5)
- Service summary cards in horizontal scroll or grid
- Quick action FABs or chips
- Pull-to-refresh with
PullRefreshIndicator
AlertDetailScreen.kt— Alert detail with correlated alerts
android/app/src/main/java/com/shieldai/android/ui/screens/services/— Service screens:DarkWatchScreen.kt— Watchlist and exposuresVoicePrintScreen.kt— Enrollments and analysis historySpamShieldScreen.kt— Stats, rules, number checkHomeTitleScreen.kt— Properties, map, changesRemoveBrokersScreen.kt— Broker registry, requests
android/app/src/main/java/com/shieldai/android/ui/screens/settings/— Settings:SettingsScreen.kt— Account, preferences, family, logout
android/app/src/main/java/com/shieldai/android/viewmodel/— ViewModels:DashboardViewModel.kt,DarkWatchViewModel.kt,VoicePrintViewModel.kt, etc.- Each exposes
StateFlow<UiState>with Loading, Success, Error states
steps:
- Create screen directories:
dashboard/,services/,settings/. - DashboardScreen:
LazyColumnfor scrollable content- Threat score: custom
Canvascomposable drawing circular arc with gradient - Alerts section:
LazyRowor vertical list ofShieldCarditems - Service cards:
LazyHorizontalGridorRowof compact cards - Quick actions:
FloatingActionButtonorRowof icon buttons PullRefreshIndicatorwithrememberPullRefreshState
- AlertDetailScreen:
Columnwith sections- Severity
ShieldBadgeat top - Description and metadata
- Correlated alerts in nested list
- Action buttons: "Mark Resolved", "False Positive"
- DarkWatchScreen:
LazyColumnwith sticky headers for sections- Watchlist items: swipe-to-delete with
SwipeToDismissBox - Add button → bottom sheet with form
- Exposures: tap to navigate to detail
- VoicePrintScreen:
- Enrollments section with audio playback (ExoPlayer or MediaPlayer)
- "Enroll" FAB → bottom sheet with recording UI
- Analysis list with verdict color coding
- Recording UI: real-time waveform using
Canvas+AudioRecord
- SpamShieldScreen:
- Stats cards at top in
Row - Rules list with toggle switches
- Number check:
ShieldTextField+ check button → result card - "Report spam" FAB
- Stats cards at top in
- HomeTitleScreen:
- Properties list with addresses
- Add property: address search with geocoding
- Property detail: Google Maps Compose or static map image
- Snapshot history and changes list
- RemoveBrokersScreen:
- Broker registry with search and category chips
- Request list with status badges and progress bars
- Start removal: bottom sheet with broker selection and form
- SettingsScreen:
LazyColumnwith sections usingListItemor custom rows- Account info with avatar
- Subscription card with upgrade button
- Notification toggles
- Theme selection dropdown
- Biometric auth toggle
- Family group management
- Logout button with confirmation dialog
- ViewModels:
- Each screen has a
ViewModelwithStateFlow<UiState> UiStatesealed class:Loading,Success(data),Error(message)- Call repository methods, handle errors, expose state
- Use
viewModelScope.launchfor coroutines
- Each screen has a
- Wire navigation in
AppNavigation.kt:- Bottom nav routes to dashboard and services
- Settings accessible from bottom nav or profile menu
- Service screens accessible from dashboard or bottom nav submenu
steps:
- Unit: Each ViewModel emits correct states for loading/success/error
- Unit: DashboardViewModel aggregates data from multiple repositories
- Visual: All screens use theme tokens and adapt to dark mode
- E2E: Navigate through all service screens and verify data loads
- E2E: Perform CRUD operations (add watchlist item, delete enrollment, create rule)
acceptance_criteria:
- Dashboard displays threat score, alerts, service summaries, and quick actions
- All 5 service screens (DarkWatch, VoicePrint, SpamShield, HomeTitle, RemoveBrokers) load and display data
- Each service screen supports core CRUD operations
- Alert detail shows full information and correlation group
- Settings screen allows managing account, preferences, and family
- Pull-to-refresh updates dashboard data
- All screens show loading skeletons and empty states appropriately
- Navigation between screens works with native Android transitions
validation:
- Launch app, login, and verify dashboard renders with real data
- Tap each service tab and verify screen loads
- Add a watchlist item in DarkWatch and verify it appears in list
- Delete a voice enrollment and verify it disappears
- Create a spam rule and verify it applies
- Toggle settings and verify preferences persist
- Run
./gradlew testfor unit tests
notes:
- Use native Android patterns:
LazyColumn/LazyRowfor lists,BottomSheetfor modals,FloatingActionButtonfor primary actions,Chipfor filters. - For the threat score gauge, draw an arc on
CanvasusingdrawArcwith aSweepGradientbrush. - The map in HomeTitle can use Google Maps Compose (
com.google.maps.android:maps-compose) or OpenStreetMap. - Voice recording requires microphone permission. Add
RECORD_AUDIOpermission to manifest and request at runtime. - Keep ViewModels separate from UI for testability. ViewModels should own the state and business logic.
- Consider using
Paging 3(androidx.paging:paging-compose) for large lists (e.g., alert history, exposure list). - For image loading in lists, use Coil (
io.coil-kt:coil-compose).