Skip to content

Cleanup: surface an in-place Cancel on the "Cleaning up…" state #15

Description

@samkeen

Context

Split out from GH #12. The substantive half of #12 — a maxTokens cap so a runaway cleanup decode self-terminates — shipped (CleanupTokenBudget + MLXLanguageModel.clean sets parameters.maxTokens). This issue tracks #12's optional second checkbox: a Cancel affordance.

Want

A Cancel button on NoteDetailView's "Cleaning up…" spinner state, mirroring the download Cancel in CleanupModelSection, so the user can stop an in-flight cleanup in place. Today the only escape is navigating away, which triggers cleaner.evict() on onDisappear — there's no stop-in-place affordance.

Why it was deferred (not just dropped)

  • The cap is the load-bearing safety belt; Cancel is a UX nicety on top.
  • A real cancel must interrupt the in-flight generation inside MLXLanguageModel.clean (ChatSession.respond). That needs cooperative Task cancellation to actually stop the GPU decode — which can't be validated on the simulator (MLX-gating convention). Shipping a button that may not truly interrupt the decode is worse than not shipping it.

Implementation notes

  • Verify MLXLMCommon.ChatSession.respond(to:) honors Task.isCancelled mid-decode. If it doesn't stop promptly, the Cancel path may need to additionally evict() to free the model and break the loop.
  • runCleanup already wraps the work in a Task; hold a handle so a Cancel button can call .cancel().
  • Map a cancelled run to no error UI (silent return to the pre-cleanup state), not the "Couldn't clean up" alert.
  • Related: ReTranscriber shares the same no-explicit-bound shape, but over fixed audio (lower risk) — could grow the same Cancel treatment as a stretch.

References

  • Relay Notes/Views/NoteDetailView.swiftrunCleanup / cleanUpControl (the spinner state).
  • Relay Notes/Enrichment/MLXLanguageModel.swiftclean(_:).
  • CleanupModelSection — existing download Cancel pattern to mirror.

Extracted from GH #12 while shipping the cleanup token cap, 2026-06-15.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions