Published to Google Play Store.
- Detail screen: prev/next bottom nav bar, delete navigates to next item with undo snackbar
- Delete auto-fires app's Delete action button if available (like Gmail delete)
- New app_actions table: captures notification action buttons per app (DB migration 7→8)
- Filter rule editor: shows known action buttons for selected app (excluding reply actions)
- Filter rule editor: dynamic placeholder text based on match field, auto-fill from source notification
- Filter rule editor: "Create filter" button added to detail screen
- Filter UX: renamed "tap" → "hit" action button, clearer dropdown labels throughout
- Filter UX: long text auto-shortened for patterns, URL-safe sentence detection
- Filter UX: frequency limiter now supports up to 24 hours
- Bookmark icon: orange badge style, visible on both items and collapsed group headers
- Read/unread: Gmail-style — bold text + dot + tinted background for unread, normal for read
- Pro mode defaults to true on debug builds
- Rule name auto-generates on save (app name + action + pattern)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-action filter rules (EXECUTE_ACTION):
- New filter action that automatically taps notification action buttons
- Finds target button by label (e.g. "Delete", "Archive") on incoming notifications
- Executes PendingIntent if found, logs failure note if button missing
- "Also delete from list" option when action succeeds
- Full UI in filter rule editor with button label field and checkbox
Deletion reason tracking:
- New deletion_reason column (DB v6→v7 migration)
- Tracks why each notification was deleted: USER, USER_BULK, AUTO_ACTION, RETENTION
- Auto-action success/failure details stored with rule name and action label
- Detail screen shows colored status banner for auto-action results
- Deletion reason visible in Info for Nerds section
Test notification broadcast (dev flavor only):
- SEND_NOTIFICATION posts real Android notifications via NotificationManager
- Supports action buttons, reply actions with RemoteInput
- Notification styles: messaging, bigpicture, bigtext, inbox
- Generated test bitmaps for sticker/image testing
- Action confirmation notifications show reply text in timeline
- POST_NOTIFICATIONS permission added to dev manifest only
Detail screen improvements:
- Icons on live action chips (Delete→trash, Archive→box, Like→heart, etc.)
- Reply dialog auto-focuses text field and opens keyboard
- Taller reply text field (3 lines)
Code quality:
- Renamed CLAUDE_TEST tag to CLAUDE_SNI_TEST across all files
- Fixed deprecated Icons.Default.OpenInNew → AutoMirrored in DetailScreen + SwipeableNotificationItem
- Fixed deprecated Icons.Default.Backspace → AutoMirrored in LockScreen
- Fixed deprecated fallbackToDestructiveMigration() → added dropAllTables param
- Wrapped BitmapFactory.decodeFile() in runCatching to prevent crashes on corrupt files
- Removed unused Notifications icon import
- Added translations for all new strings (ES, FR, DE, CA, SV)
Published as internal test on Google Play Store.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Capture notification media (stickers, images) from BigPictureStyle and
MessagingStyle data URIs, saved to internal storage with path in iconUri
- Reply actions with RemoteInput: detect actions with text input, show
reply dialog, bundle text via RemoteInput before sending PendingIntent
- Media & Storage settings: replace fake toggles with two real ones
(shared photos, chat media) wired to capture code; add media retention
dropdown capped by notification retention
- Theme: default to Warm Gold, add surfaceContainer hierarchy to all
themes, soften backgrounds, colored primaryContainer top app bars
- Dark mode toggle: Follow system / Light / Dark preference in settings
- System nav bar synced to surfaceContainer color with proper light/dark
icon appearance
- Bottom nav bar uses semi-transparent surfaceContainer for content
scroll-through
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Soft-delete with deleted_at column: notifications are marked deleted instead of
hard-deleted, enabling undo by clearing the timestamp. All queries filter deleted_at IS NULL.
DB migrations 4→5 (add column) and 5→6 (add index).
- Media & Storage settings screen: master toggle (on by default), per-type toggles
(images, stickers, GIFs, thumbnails), storage usage display, date-based clear dialog
capped by retention period.
- Retention cleanup: RetentionCleanupUseCase runs on service connect, enforces retention
period on both notifications and media files. Immediate cleanup when retention reduced
with confirmation dialog showing affected count.
- Permission banner: edge-to-edge red bar when notification access revoked, tappable to
open system settings. Fixed caching bug with direct Settings.Secure read.
- Sticky day headers in timeline, group swipe with both directions and undo support,
selectable text in detail screen, compact nav bar for small devices, manifest
default_filter_types for Android 13+, backup rules, negative padding crash fix.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reusable ADB script to populate the app with varied test data across
9 app sources (WhatsApp, Gmail, Telegram, Instagram, Slack, Messages,
X, Calendar, System) spanning multiple days for UI/UX stress testing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Execute live notification actions (reply, delete, etc.) from detail screen when notification is still active
- Configurable swipe actions in Settings (delete, bookmark, mark read/unread, none) per direction
- App icon caching with LRU + disk fallback for uninstalled/invisible apps
- Add <queries> manifest for Android 11+ package visibility (Play Store safe)
- Detail screen: add delete button, toggle read/unread button, bookmark color highlight
- Settings rows with switches now clickable on the whole row
- Aggressive ProGuard obfuscation for release builds (no source files, repackaged classes)
- Bidirectional swipe-to-delete with direction-aware background
- Clean up debug logs
- Move category, priority, ID, and removal info into collapsible "Info for Nerds" section
- Remove "Possibly deleted" badge from timeline and detail (data still captured)
- Dismiss notifications from system status bar when deleted from app
- Fix app icon alias crash: ensure correct icon on startup after reinstall
- Add fallbackToDestructiveMigration for Room schema mismatches during beta
- Add ProGuard rules for Google Tink (EncryptedSharedPreferences)
- Clean up stale translated strings
Security:
- AppLockManager uses EncryptedSharedPreferences with AES256 (fallback to plain)
- PII logging gated behind BuildConfig.TEST_INSTRUMENTED
- MainActivity set to exported=false (activity-aliases handle launcher intent)
- Release builds now enable R8 minification and resource shrinking
Architecture:
- Remove direct DAO access from TimelineViewModel, SettingsViewModel, NotificationCaptureService
- Route all data access through NotificationRepository (8 new interface methods)
- Extract file I/O from ExportViewModel into FileExporter data-layer class
- Extract shared copy/share/open logic into NotificationActions utility
Room & Performance:
- FTS MATCH replaces LIKE scan for search with input sanitization
- Fix null tag comparison in findPrevious() using IS operator
- Remove orphan KeywordAlertEntity (no DAO existed)
- Add LRU regex cache with Result wrapper in FilterRuleEngine
- Add CSV/JSON field escaping in ExportNotificationsUseCase
Code quality:
- Eliminate all !! operators across codebase
- Fix unchecked casts in FilterRuleEditorSheet with safe as? casts
- Consolidate DAY_BOUNDARY_HOUR to single source
- Remove dead code: unused colors, groupByTimeBlock, KEY_GROUP_BY_APP, TODO
- Fix deprecated LocalLifecycleOwner import
- Remove duplicate RadioButton import
Localization:
- Move ~200 hardcoded strings to strings.xml
- All user-visible text now uses stringResource() or getString()
- Timeout labels, filter options, theme names use resource IDs
File structure:
- Split TimelineScreen (772→610 lines): extract FilterBottomSheet, ConsecutiveAppGroupHeader
- Split FilterRuleEditorSheet (746→471 lines): extract AppPickerSheet, FilterRuleHelpers
- All files now under 700-line limit
Major changes in this commit:
- Rename app from NotiSaver to Alert Vault (package: com.roundingmobile.alertvault)
- Natural language filter rule editor (Thunderbird/BuzzKill-style sentence builder)
- Compound AND/OR conditions for filter rules (Pro-gated)
- 6 filter actions: don't save, save & dismiss, block, save as read, cooldown, alert
- App picker with 4 sections (any app, notification apps, installed apps, manual entry)
- Pro status provider with dev toggle in Settings
- Premium gate dialog for pro features
- Auto-dismiss from notification shade via cancelNotification
- Cooldown tracker (in-memory, per-rule per-app)
- Blue Steel (default) and Gold Vault (premium) app icons with activity-alias switching
- DB migration v3→v4: compound conditions JSON, condition operator, action params
- Remove pro flavor, rename free to prod; two flavors: prod + dev
- Add PremiumManager for runtime premium gating (billing integration later)
- Rename APK output to rmt-notisaver.<flavor>.v<version>.<date>.apk
- Fix app lock: use BiometricPrompt with DEVICE_CREDENTIAL, persist background
time, add configurable lock timeout (immediately → 30 min) in Settings
- Add is_read field to notifications (DB migration v3), mark read on detail view
- Unread dot indicator + bold text on timeline items, "X unread · Y new" chip
- Mark as unread button in detail screen
- Preserve day/app group expand state in ViewModel (survives navigation)
- Add date/time received to detail screen header
- Use LocalDateFormatter CompositionLocal for user-selected date/time format
- Show BuildConfig.VERSION_NAME in About section
- BackHandler closes search before exiting app