diff --git a/app/javascript/controllers/terminal_controller.js b/app/javascript/controllers/terminal_controller.js index 38a65a20a..0e43293aa 100644 --- a/app/javascript/controllers/terminal_controller.js +++ b/app/javascript/controllers/terminal_controller.js @@ -5,6 +5,10 @@ export default class extends Controller { static targets = [ "input", "form", "confirmation" ] static classes = [ "error", "confirmation", "help" ] + disconnect() { + if (this.waitingForConfirmation) { this.#reset() } + } + // Actions focus() { @@ -26,6 +30,13 @@ export default class extends Controller { this.element.classList.remove(this.helpClass) } + handleKeyPress(event) { + if (this.waitingForConfirmation) { + this.#handleConfirmationKey(event.key.toLowerCase()) + event.preventDefault() + } + } + handleCommandResponse(event) { if (event.detail.success) { this.#reset() @@ -74,6 +85,8 @@ export default class extends Controller { this.formTarget.reset() this.inputTarget.value = inputValue this.confirmationTarget.value = "" + this.waitingForConfirmation = false + this.originalInputValue = null this.element.classList.remove(this.errorClass) this.element.classList.remove(this.confirmationClass) @@ -84,35 +97,23 @@ export default class extends Controller { } async #requestConfirmation(message) { - const originalInputValue = this.inputTarget.value + this.originalInputValue = this.inputTarget.value this.element.classList.add(this.confirmationClass) this.inputTarget.value = `${message}? [Y/n] ` - try { - await this.#waitForConfirmation() - this.#submitWithConfirmation(originalInputValue) - } catch { - this.#reset(originalInputValue) + this.waitingForConfirmation = true + } + + #handleConfirmationKey(key) { + if (key === "enter" || key === "y") { + this.#submitWithConfirmation() + } else if (key === "escape" || key === "n") { + this.#reset(this.originalInputValue) } } - #waitForConfirmation() { - return new Promise((resolve, reject) => { - this.inputTarget.addEventListener("keydown", (event) => { - event.preventDefault() - const key = event.key.toLowerCase() - - if (key === "enter" || key === "y") { - resolve() - } else { - reject() - } - }, { once: true }) - }) - } - - #submitWithConfirmation(inputValue) { - this.inputTarget.value = inputValue + #submitWithConfirmation() { + this.inputTarget.value = this.originalInputValue this.confirmationTarget.value = "confirmed" this.formTarget.requestSubmit() } diff --git a/app/views/commands/_form.html.erb b/app/views/commands/_form.html.erb index a2f979c9c..40d04fa56 100644 --- a/app/views/commands/_form.html.erb +++ b/app/views/commands/_form.html.erb @@ -4,6 +4,7 @@ data: { controller: "form", terminal_target: "form", + turbo_permanent: true, action: "turbo:submit-end->terminal#focus keydown.meta+k@document->terminal#focus keydown.enter->terminal#executeCommand keydown.esc->terminal#hideHelpMenu turbo:submit-end->terminal#handleCommandResponse" } do %> @@ -15,8 +16,7 @@ class: "terminal__input input fill-transparent unpad", data: { terminal_target: "input", - action: "keydown.up->toggle-class#add:prevent keydown.up->navigable-list#selectCurrentOrLast terminal#hideError", - turbo_permanent: true + action: "keydown.up->toggle-class#add:prevent keydown.up->navigable-list#selectCurrentOrLast terminal#hideError" }, placeholder: "Press ⌘+K to search or type commands…", spellcheck: "false" %> diff --git a/app/views/commands/_terminal.html.erb b/app/views/commands/_terminal.html.erb index 642d3bd07..62bd7ecbf 100644 --- a/app/views/commands/_terminal.html.erb +++ b/app/views/commands/_terminal.html.erb @@ -4,7 +4,7 @@ terminal_confirmation_class: "terminal--confirmation", terminal_help_class: "terminal--showing-help", toggle_class_toggle_class: "terminal--open", - action: "keydown->navigable-list#navigate focusin->navigable-list#select keydown.esc->toggle-class#remove:stop keydown.esc->terminal#focus keydown.esc->navigable-list#selectLast" } do %> + action: "keydown->terminal#handleKeyPress keydown->navigable-list#navigate focusin->navigable-list#select keydown.esc->toggle-class#remove:stop keydown.esc->terminal#focus keydown.esc->navigable-list#selectLast" } do %> <%= turbo_frame_tag :recent_commands, src: commands_path, refresh: "morph" %> <%= render "commands/form" %>