Skip to content

Persist conversation drafts - #144

Merged
torlando-tech merged 16 commits into
mainfrom
fix/ios-draft-messages
Aug 5, 2026
Merged

Persist conversation drafts#144
torlando-tech merged 16 commits into
mainfrom
fix/ios-draft-messages

Conversation

@torlando-tech

Copy link
Copy Markdown
Owner

Summary

  • persist exact text drafts per conversation in the identity-scoped message database
  • restore and autosave composer text with race-safe debounce, lifecycle flushes, and send-time clearing
  • show committed drafts in Chats with an Android-style Draft: preview
  • preserve message ordering for attachment-only conversations and include drafted conversations beyond the normal first page
  • cascade draft deletion with conversation deletion

Fixes #143

Verification

  • static contracts: 224 passed, 1 skipped
  • fresh focused draft tests: 37 passed, 0 failed
  • full shipping XCTest target: 234 passed, 0 failed
  • shipping Columba build: passed
  • Columba-ModelB compile build: passed
  • project reconciler: two-pass idempotent
  • exact-head specification audit: passed
  • exact-head code-quality audit: approved with no findings
  • signed exact-head iPhone build, install, launch, and physical draft smoke test: passed

Scope

Draft persistence is text-only. Attachments, images, files, and reply context are intentionally not stored as part of drafts.

Risk and rollback

The schema addition is app-owned and idempotent, with no change to the pinned LXMF package migration chain. Reverting this PR leaves the draft table unused; existing message and conversation data remain unchanged.

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds identity-scoped, per-conversation text draft persistence and integrates restoration, debounced autosaving, lifecycle flushes, send-time clearing, chat-list previews, and deletion cleanup.

  • Adds the draft schema and repository operations, including explicit orphan cleanup after canonical conversation deletion.
  • Adds a serialized autosave pipeline and composer lifecycle integration.
  • Projects committed drafts into the chat list, including conversations beyond the normal first page.
  • Adds focused persistence, ordering, lifecycle, notification, and deletion-race tests.

Confidence Score: 5/5

The PR appears safe to merge.

The previously reported orphan-draft issue is addressed by explicit post-delete cleanup, while the conditional parent check preserves drafts belonging to a concurrently recreated conversation; no blocking failure remains.

Important Files Changed

Filename Overview
Sources/ColumbaApp/Services/MessageRepository.swift Adds draft storage, retrieval, notifications, draft-aware queries, and explicit race-safe cleanup after conversation deletion.
Sources/ColumbaApp/ViewModels/DraftAutosaveController.swift Adds a main-actor debounce controller and serialized mutation pipeline for autosave, flush, and clear operations.
Sources/ColumbaApp/ViewModels/ChatsViewModel.swift Loads committed drafts with their parent conversations and projects draft previews while preserving message-based ordering.
Sources/ColumbaApp/Views/Messaging/MessagingView.swift Restores drafts before publishing the composer and connects edits, lifecycle boundaries, and sends to persistence.
Tests/ColumbaAppTests/DraftMessageTests.swift Adds extensive coverage for persistence, mutation ordering, lifecycle behavior, list projection, and conversation deletion races.
Columba.xcodeproj/project.pbxproj Includes the autosave controller and draft test suite in the appropriate application and test targets.

Sequence Diagram

sequenceDiagram
    participant User
    participant Composer as MessagingView
    participant Autosave as DraftAutosaveController
    participant Repo as MessageRepository
    participant DB as Identity-scoped SQLite
    participant Chats as ChatsViewModel

    User->>Composer: Edit text
    Composer->>Autosave: textChanged(text)
    Autosave->>Repo: saveDraft(text, conversationHash)
    Repo->>DB: Upsert draft
    Repo-->>Chats: draftChanged notification
    Chats->>Repo: Reload conversations and drafts
    Repo-->>Chats: Draft-aware snapshot

    User->>Composer: Send message
    Composer->>Autosave: clearImmediately()
    Autosave->>Repo: clearDraft(conversationHash)
    Repo->>DB: Delete draft

    User->>Chats: Delete conversation
    Chats->>Repo: deleteConversation(hash)
    Repo->>DB: Delete canonical conversation and messages
    Repo->>DB: Delete draft only if parent remains absent
Loading

Reviews (2): Last reviewed commit: "fix: preserve recreated conversation dra..." | Re-trigger Greptile

Comment thread Sources/ColumbaApp/Services/MessageRepository.swift
@torlando-tech
torlando-tech merged commit 36db4dc into main Aug 5, 2026
4 checks passed
@torlando-tech
torlando-tech deleted the fix/ios-draft-messages branch August 5, 2026 02:40
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.

android parity: draft messages

1 participant