Skip to content

Flush auto-save before publishing card on Cmd (Ctrl) + Enter#2812

Open
diogovernier wants to merge 1 commit intobasecamp:mainfrom
diogovernier:fix-card-title-sync
Open

Flush auto-save before publishing card on Cmd (Ctrl) + Enter#2812
diogovernier wants to merge 1 commit intobasecamp:mainfrom
diogovernier:fix-card-title-sync

Conversation

@diogovernier
Copy link
Copy Markdown

Fixes #2778

Typing a card title quickly and hitting Cmd (Ctrl) + Enter could publish the card before auto-save finished, showing a stale title on the board (correct after reload).

Cmd+Enter fires two concurrent async handlers: auto-save#submit starts the PATCH, and clicker#click waits one animation frame (~16ms) then clicks the publish button. The publish redirect renders the board before the save round-trip completes.

Solution: wire the clicker to the auto-save controller via a Stimulus outlet so it awaits the pending save before clicking publish.

Before:

before_fix.mp4

After:

after_fix.mp4

Copilot AI review requested due to automatic review settings April 8, 2026 13:39
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a race where using Cmd/Ctrl+Enter could publish a card before the title auto-save PATCH completed, causing the board to render with a stale title until reload. It does this by having the publish “clicker” await the auto-save controller before triggering the publish click.

Changes:

  • Add a Stimulus outlet from clickerauto-save on the publish buttons so clicker#click can await pending saves.
  • Update clicker_controller to call autoSaveOutlet.submit() before clicking.
  • Update auto_save_controller to track an in-flight save promise so external callers can await completion.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
app/views/cards/container/footer/_create.html.erb Wires publish buttons’ clicker controller to the #card_form auto-save controller via an outlet.
app/javascript/controllers/clicker_controller.js Awaits auto-save completion (when connected) before clicking publish.
app/javascript/controllers/auto_save_controller.js Adds tracking for an in-flight save promise so callers can await ongoing saves.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +40 to +44
this.#savePromise = submitForm(this.element)
try {
await this.#savePromise
} finally {
this.#savePromise = null
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#save() overwrites #savePromise unconditionally. If a save is already in-flight (high latency) and another save is triggered (e.g., via change scheduling a new timer and then submit() calling #save()), multiple concurrent PATCHes can be sent and #savePromise will only track the most recent one. That means callers awaiting submit() may return while an earlier request is still in-flight, and responses can apply out of order, potentially persisting stale data last. Consider serializing saves (await/chain any existing #savePromise before starting a new submitForm) and avoid clearing a newer promise in the finally of an older save.

Suggested change
this.#savePromise = submitForm(this.element)
try {
await this.#savePromise
} finally {
this.#savePromise = null
const previousSavePromise = this.#savePromise || Promise.resolve()
const savePromise = previousSavePromise.then(() => submitForm(this.element))
this.#savePromise = savePromise
try {
await savePromise
} finally {
if (this.#savePromise === savePromise) {
this.#savePromise = null
}

Copilot uses AI. Check for mistakes.
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.

Incomplete card title when a new card is saved with Cmd+Enter keyboard shortcut

2 participants