Add Recursive Message Deletion Feature (Delete Thread) #142

Closed
opened 2025-12-23 17:58:27 +00:00 by rwachters · 0 comments
rwachters commented 2025-12-23 17:58:27 +00:00 (Migrated from github.com)

Summary

Add support for recursive message deletion ("Delete Thread") alongside existing single message deletion. Use Ktor Resources with declarative query parameters for compile-time validation and wire the feature through UI, API, and repository layers.

Motivation

Users need a safe and discoverable way to delete entire message threads (a message and all its replies). This feature adds a "Delete Thread" action, stronger confirmation, and backend support while keeping existing single-message deletion intact.

Proposed Implementation Steps

  1. Add DeleteMode enum
  • Create file: common/src/commonMain/kotlin/eu/torvian/chatbot/common/api/enums/DeleteMode.kt
  • Add enum values: SINGLE, RECURSIVE
  1. Update MessageResource to accept a typed query parameter
  • Update MessageResource.ById in MessageResource.kt to include mode: DeleteMode = DeleteMode.SINGLE as a declarative query parameter (Ktor Resources) so the mode is validated at compile time instead of manually parsing query params.
  1. Use the typed mode in routes
  • Update configureMessageRoutes.kt to read the typed mode parameter from MessageResource.ById and call either messageService.deleteMessage(sessionId, messageId) or messageService.deleteMessageRecursively(sessionId, messageId) depending on the mode value.
  1. Add an onDeleteThread callback to the UI actions
  • Update MessageActions (MessageActions.kt) to include a new onDeleteThread: (ChatMessage) -> Unit callback alongside existing onDeleteMessage.
  1. Add "More" actions menu in message UI
  • Modify MessageActionRow.kt to add a "More" dropdown/popup menu containing the new "Delete Thread" action using the "Delete Sweep" icon (or similar) and the theme's error color. Position this after the existing Delete button in the hover actions so users can choose single-delete quickly and access thread-delete from the menu.
  1. Extend client API and repository
  • Add deleteMessageRecursively(sessionId: Long, messageId: Long) to the client API interface (ChatApi) and implement it in KtorChatApiClient.kt by passing mode=DeleteMode.RECURSIVE in the Ktor resources call.
  • Add deleteMessageRecursively(sessionId: Long, messageId: Long) to SessionRepository and implement in DefaultSessionRepository to call the new API client method.
  1. Wire through use case and ViewModel
  • Update DeleteMessageUseCase (DeleteMessageUseCase.kt) to accept recursive: Boolean = false and call the appropriate repository method based on this flag.
  • Add requestDeleteMessageRecursively(message: ChatMessage) in ChatViewModel that triggers the recursive delete flow (show confirmation dialog and invoke use case when confirmed).
  • Ensure ChatScreen actions and ChatArea compose wiring pass through onDeleteThread to the ViewModel method.
  1. UI confirmation dialog
  • Add ChatAreaDialogState.DeleteMessageRecursively to ChatAreaDialogState.kt with a stronger confirmation copy, e.g., "This will delete the message and all replies in this thread. This action cannot be undone."
  • Ensure dialog rendering shows this explicit warning and uses the error visual treatment.
  1. Testing and verification
  • Add unit tests for:
    • DeleteMode parsing and default value behavior (if applicable)
    • configureMessageRoutes behavior for both modes (unit test route handler or integration test)
    • KtorChatApiClient request formation for RECURSIVE mode
    • DefaultSessionRepository mapping to client
    • DeleteMessageUseCase branching for recursive=true/false
    • ChatViewModel methods to ensure correct use case invocation
  • Add UI tests or a manual verification checklist for:
    • Hover actions show both Delete and More -> Delete Thread
    • Delete Thread shows the stronger confirmation dialog
    • After confirmation, thread is removed from UI and repository/server

Acceptance criteria

  • A compile-time validated mode query parameter is used for message deletion APIs.
  • UI provides both single-message delete (quick action) and Delete Thread (in More menu).
  • Back-end route and client pass DeleteMode.RECURSIVE to server.
  • Recursive deletion uses messageService.deleteMessageRecursively(...) on the server.
  • Dialog warns the user clearly and requires confirmation.
  • Tests cover core behavior and request formation.

Notes and considerations

  • Prefer adding the enum in the shared common module so both client and server can reference it.
  • Keep default behavior as SINGLE to avoid breaking existing clients.
  • Consider rate limits or large-thread deletion performance; if threads can be large, consider server-side safeguards and background processing with progress/events.

Labels

  • enhancement
  • backend
  • frontend

If helpful, I can also open follow-up PRs with the changes described once this issue is accepted.

Summary Add support for recursive message deletion ("Delete Thread") alongside existing single message deletion. Use Ktor Resources with declarative query parameters for compile-time validation and wire the feature through UI, API, and repository layers. Motivation Users need a safe and discoverable way to delete entire message threads (a message and all its replies). This feature adds a "Delete Thread" action, stronger confirmation, and backend support while keeping existing single-message deletion intact. Proposed Implementation Steps 1) Add DeleteMode enum - Create file: common/src/commonMain/kotlin/eu/torvian/chatbot/common/api/enums/DeleteMode.kt - Add enum values: SINGLE, RECURSIVE 2) Update MessageResource to accept a typed query parameter - Update `MessageResource.ById` in `MessageResource.kt` to include `mode: DeleteMode = DeleteMode.SINGLE` as a declarative query parameter (Ktor Resources) so the mode is validated at compile time instead of manually parsing query params. 3) Use the typed mode in routes - Update `configureMessageRoutes.kt` to read the typed `mode` parameter from `MessageResource.ById` and call either `messageService.deleteMessage(sessionId, messageId)` or `messageService.deleteMessageRecursively(sessionId, messageId)` depending on the mode value. 4) Add an onDeleteThread callback to the UI actions - Update `MessageActions` (MessageActions.kt) to include a new `onDeleteThread: (ChatMessage) -> Unit` callback alongside existing `onDeleteMessage`. 5) Add "More" actions menu in message UI - Modify `MessageActionRow.kt` to add a "More" dropdown/popup menu containing the new "Delete Thread" action using the "Delete Sweep" icon (or similar) and the theme's error color. Position this after the existing Delete button in the hover actions so users can choose single-delete quickly and access thread-delete from the menu. 6) Extend client API and repository - Add `deleteMessageRecursively(sessionId: Long, messageId: Long)` to the client API interface (`ChatApi`) and implement it in `KtorChatApiClient.kt` by passing `mode=DeleteMode.RECURSIVE` in the Ktor resources call. - Add `deleteMessageRecursively(sessionId: Long, messageId: Long)` to `SessionRepository` and implement in `DefaultSessionRepository` to call the new API client method. 7) Wire through use case and ViewModel - Update `DeleteMessageUseCase` (`DeleteMessageUseCase.kt`) to accept `recursive: Boolean = false` and call the appropriate repository method based on this flag. - Add `requestDeleteMessageRecursively(message: ChatMessage)` in `ChatViewModel` that triggers the recursive delete flow (show confirmation dialog and invoke use case when confirmed). - Ensure `ChatScreen` actions and `ChatArea` compose wiring pass through `onDeleteThread` to the ViewModel method. 8) UI confirmation dialog - Add `ChatAreaDialogState.DeleteMessageRecursively` to `ChatAreaDialogState.kt` with a stronger confirmation copy, e.g., "This will delete the message and all replies in this thread. This action cannot be undone." - Ensure dialog rendering shows this explicit warning and uses the error visual treatment. 9) Testing and verification - Add unit tests for: - `DeleteMode` parsing and default value behavior (if applicable) - `configureMessageRoutes` behavior for both modes (unit test route handler or integration test) - `KtorChatApiClient` request formation for RECURSIVE mode - `DefaultSessionRepository` mapping to client - `DeleteMessageUseCase` branching for recursive=true/false - `ChatViewModel` methods to ensure correct use case invocation - Add UI tests or a manual verification checklist for: - Hover actions show both Delete and More -> Delete Thread - Delete Thread shows the stronger confirmation dialog - After confirmation, thread is removed from UI and repository/server Acceptance criteria - A compile-time validated `mode` query parameter is used for message deletion APIs. - UI provides both single-message delete (quick action) and Delete Thread (in More menu). - Back-end route and client pass DeleteMode.RECURSIVE to server. - Recursive deletion uses `messageService.deleteMessageRecursively(...)` on the server. - Dialog warns the user clearly and requires confirmation. - Tests cover core behavior and request formation. Notes and considerations - Prefer adding the enum in the shared common module so both client and server can reference it. - Keep default behavior as SINGLE to avoid breaking existing clients. - Consider rate limits or large-thread deletion performance; if threads can be large, consider server-side safeguards and background processing with progress/events. Labels - enhancement - backend - frontend If helpful, I can also open follow-up PRs with the changes described once this issue is accepted.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Torvian.eu/chatbot#142
No description provided.