Files
music_library/backlog/tasks/ml-169.10 - Fix-Missing-optimistic-UI-for-delete-operations.md
T
2026-05-20 10:42:35 +01:00

3.6 KiB
Raw Blame History

id, title, status, assignee, created_date, updated_date, labels, dependencies, references, modified_files, parent_task_id, priority, ordinal
id title status assignee created_date updated_date labels dependencies references modified_files parent_task_id priority ordinal
ML-169.10 Fix: Async optimistic UI for index/list delete streams To Do
2026-05-19 11:48 2026-05-20 09:41
perf
fix
ux
backlog/documents/doc-27 - Phase-4-Performance-Audit-Low-Hanging-Fruit-Findings.md
lib/music_library_web/live_helpers/index_actions.ex
lib/music_library_web/live/collection_live/index.ex
lib/music_library_web/live/wishlist_live/index.ex
lib/music_library_web/live/scrobbled_tracks_live/index.ex
ML-169 medium 31000

Description

Add optimistic UI for delete operations only where the item is rendered from a LiveView stream on an index/list page. The item should be removed from the stream immediately, while the database delete runs through LiveView-owned async handling so failures can be reported and rolled back.

Problem

Index/list delete handlers currently wait for the database delete before updating the UI. stream_delete is used after the delete succeeds, so the interaction can feel slower than necessary.

This task is intentionally scoped to stream-backed list views only:

  • Collection index and wishlist index record streams via IndexActions.handle_delete/2
  • Scrobbled tracks index stream

Show-page deletes are out of scope. CollectionLive.Show and WishlistLive.Show navigate away after delete and do not have a list stream to optimistically update. Their failure and rollback behavior should remain synchronous unless a separate navigation-specific design is created.

Files

  • lib/music_library_web/live_helpers/index_actions.ex — remove record from :records immediately and start a LiveView async delete operation
  • lib/music_library_web/live/collection_live/index.ex — handle async record delete success/failure for collection index
  • lib/music_library_web/live/wishlist_live/index.ex — handle async record delete success/failure for wishlist index
  • lib/music_library_web/live/scrobbled_tracks_live/index.ex — remove track from :tracks immediately and handle async track delete success/failure

Fix

Use LiveView-owned async handling (start_async/3 plus handle_async/3, or an equivalent pattern that sends results back to the LiveView process). Do not use bare Task.start/1, because it cannot update the socket, reinsert the stream item, or show an error toast.

Expected behavior:

  1. Fetch the item needed for rollback.
  2. Immediately call stream_delete/3 on the relevant stream.
  3. Start an async delete operation owned by the LiveView.
  4. On success, leave the stream as-is and optionally broadcast/refresh any cross-view state the existing design requires.
  5. On failure or async exit, reinsert the original item into the stream and show a user-facing error toast.

For error text, use the projects existing user-facing error conventions (ErrorMessages.friendly_message/1 where an error reason is shown).

Acceptance Criteria

  • #1 Index/list delete operations remove the item from the relevant stream before waiting for the database delete
  • #2 Database delete still executes through LiveView-owned async handling, not bare Task.start/1
  • #3 Async delete failure or exit reinserts the original item into the stream and shows an error toast
  • #4 Existing delete confirmation prompts still work correctly
  • #5 Show-page delete handlers are not changed as part of this task
  • #6 Collection and wishlist index delete behavior remains shared through IndexActions where practical