Skip to content

Conversation

@gmarkley-VI
Copy link

Summary

  • Fixes issue where deleted conversations lose their deleted status after device reboot
  • Preserves deleted status during message sync while still allowing restoration when new messages arrive
  • Refactors parameter naming for better code clarity

Problem

When the device reboots, the app performs a message sync that was not preserving the deleted status of conversations. This caused all deleted conversations to reappear in the main inbox instead of staying in the deleted state until either:

  1. The auto-delete timer expires
  2. A new message arrives (which should restore the conversation)

Solution

The fix involves three main changes:

  1. Added deleted conversation tracking to SyncManager

    • Added mDeletedConversations HashSet to cache deleted conversation IDs
    • Added isDeleted() method to check if a conversation is deleted
    • Modified getOrCreateConversation() to detect and cache deleted conversations
  2. Added database query method

    • Added isConversationDeleted() method to BugleDatabaseOperations to check deleted status in database
  3. Modified sync logic to preserve deleted status

    • Updated SyncMessageBatch.updateConversations() to check both archived AND deleted status
    • Ensures deleted conversations maintain their state during sync
  4. Improved code clarity

    • Renamed keepArchived parameter to preserveSpecialStatus throughout the codebase
    • Better reflects that it preserves both archived and deleted states

Test Plan

  • Mark a conversation as deleted
  • Reboot the device
  • Verify deleted conversation remains in deleted state
  • Send a new message to the deleted conversation
  • Verify conversation is restored to inbox when new message arrives
  • Verify auto-delete still works at scheduled time

gmarkley-VI and others added 30 commits August 10, 2025 17:33
GitHub Actions v3 artifact actions will be deprecated on January 30, 2025.
Updated to v4 which provides improved upload/download speeds up to 98% faster.
The app was crashing with AssertionError when swiping right to delete
because showSnackBarWithCustomAction required a non-null action parameter.
Changed the action parameter to @nullable and removed the assertion check,
allowing the SnackBar to display without an action button when action is null.
Implements a new "Deleted" view for managing deleted conversations, similar to the existing Archive functionality:

- Added "Deleted" menu option to main conversation list menu
- Created DeletedConversationListActivity to display deleted conversations
- Updated ConversationListFragment to support deleted mode
- Added UI navigation methods in UIIntents/UIIntentsImpl
- Added necessary string resources for deleted view UI
- Registered new activity in AndroidManifest.xml

The deleted view follows the same pattern as archived conversations and provides a foundation for managing deleted messages.
Add database support for marking conversations as deleted instead of permanently removing them:

- Add deleted_status column to conversations table with database migration to version 3
- Create UpdateConversationDeletedStatusAction to handle marking conversations as deleted/undeleted
- Add DeletedConversationListData to filter and display only deleted conversations
- Update ConversationListData to exclude deleted conversations from normal view
- Update ConversationListItemData to include deleted status in projection and data model
- Add BugleDatabaseOperations method for updating deleted status in transactions
- Update ConversationListFragment to support deleted mode using the new data class

This provides the backend infrastructure for soft-deleting conversations, allowing them to be recovered from the deleted view similar to how archived conversations work.
Modified DeleteConversationAction to implement a two-stage deletion process:
- First delete: Marks conversation as deleted (soft delete) and moves it to Deleted view
- Second delete: Permanently removes conversation from database (hard delete)

This allows users to recover accidentally deleted conversations from the Deleted view, similar to how email clients handle trash folders. The implementation checks the deleted_status before deciding whether to soft delete or hard delete.

All delete operations (swipe-to-delete, multi-select delete, individual delete) now use this two-stage process automatically through the updated DeleteConversationAction.
- Add deleted_timestamp column to track when conversations were deleted
- Create settings preference for retention period (default 14 days, max 999)
- Implement AutoDeleteOldConversationsAction to permanently delete old messages
- Schedule daily cleanup at 00:05 with AlarmManager
- Run auto-delete on app startup to catch missed scheduled deletions
- Update deleted view to show retention period in empty state message
- Add AutoDeleteDaysPreference custom EditTextPreference for number input
This adds a configurable retention period for deleted messages with special
handling for immediate deletion when set to 0 days.

Key changes:
- Add "Recently deleted retention" setting in Advanced preferences
- Store preference as integer instead of string for efficiency
- 0 days = immediate permanent deletion (skip trash)
- Positive days = soft delete with auto-cleanup after retention period
- Negative days = disable auto-delete (for future use)
- Default retention period: 14 days

Behavior:
- Manual delete: Respects retention setting (0 = immediate delete)
- Auto-delete job: Runs daily at 00:05 to clean up expired messages
- Swipe to delete: Now enabled by default (safe with soft delete)

UI improvements:
- Clear descriptions: "Keep recently deleted messages for X days"
- Special case for 0: "Don't keep deleted messages - remove immediately"
- Settings located in Advanced section

Technical improvements:
- Single source of truth for default value (constants.xml)
- Preference stored as integer to avoid string conversions
- Consistent error handling between manual and auto delete
- Proper resource cleanup and null checks
…Action

Fixed control flow issue where retention=0 case was falling into an
else-if block without a return statement. Restructured the code to have
the permanent deletion logic execute for both cases:
- When conversation is already deleted (existing behavior)
- When retention is 0 (immediate delete)

This ensures proper control flow and all code paths return a value.
- Fixed SQL query to use <= instead of < to include messages at exact cutoff time
- Fixed zero-day retention to properly delete all deleted conversations
- Added auto-delete trigger on boot to ensure cleanup happens even if device was off
- Boot receiver now triggers auto-delete and alarm is rescheduled on app start
- Display days remaining until auto-delete for each deleted conversation
- Shows "Deleting today" in red for last day, "Deleting tomorrow" in red for 1 day
- Shows "Deleting in X days" for 2+ days remaining in normal text color
- Added DELETED_TIMESTAMP to conversation list data projection
- Countdown only visible when auto-delete is enabled and conversation is deleted
Only show auto-delete countdown, not the original timestamp
- Moved auto-delete preference from per-subscription to application-wide settings
- Fixed type mismatch in ConversationListFragment (was reading as String, now as int)
- Preference now saves to and reads from the same SharedPreferences (bugle)
- Setting changes now immediately reflect in deleted conversations countdown
Move isDefaultSmsApp declaration outside if-else block to fix undefined variable error
- Fixed countdown calculation to show actual remaining days based on deletion timestamp
- Fixed auto-delete action to use consistent day-based logic matching the countdown display
- Both now calculate days since deletion and compare to retention period
- Ensures countdown decreases daily and items are deleted when showing "0 days"
Problem: Deleted conversations were losing their deleted status after device
reboot due to message sync not preserving the deleted state.

Solution:
- Added deleted conversation tracking to SyncManager with mDeletedConversations cache
- Added isConversationDeleted() method to check database deleted status
- Modified sync to preserve deleted status along with archived status
- Renamed keepArchived parameter to preserveSpecialStatus for clarity

This ensures deleted conversations maintain their state across reboots while
still allowing them to be restored when new messages arrive.
@gmarkley-VI gmarkley-VI deleted the wip branch September 18, 2025 00:06
@gmarkley-VI gmarkley-VI restored the wip branch September 18, 2025 00:06
@gmarkley-VI gmarkley-VI changed the title Fix deleted conversations losing status after reboot -Mistake in PR -Fix deleted conversations losing status after reboot Sep 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant