Raycast: find a file, then keep its next action within reach
Raycast is a desktop launcher and command tool for frequent computer users. It connects finding apps and files with their related actions, turning everyday operations into familiar keyboard paths.
Break down the problem and try your own design and implementation first. Then explore the reasoning to check states, edge cases, trade-offs, and ways to test your approach. The guide offers a reasoning path, not a complete implementation.
How can an asynchronous command panel execute the intended action only once?
Scenario
Design a state model for a command panel in your own web file tool. Selecting a file starts an asynchronous load of its available actions. People may switch files, close the panel or use a Chinese input method while searching actions. Discuss client state and event routing only; do not write a complete component.
Inputs and terms
- Each file has a stable, unique
itemId. Opening the panel creates an increasingsessionId, identifying this opening rather than the file. Closing and reopening the same file creates a new session; selecting another file inside the panel also creates a new session and loads its actions. Each action has a uniqueactionIdand anenabledvalue. Success returns an ordered action list; failure returns an error. - The network layer returns
{sessionId, itemId, requestId}unchanged with either success or failure. Every request, including a retry, has a differentrequestId. Responses may arrive in any order, and cancellation is best effort. You need not implement networking or server writes. - An adapter normalizes key events to
{key, composing, repeat}.composing=truemeans the key belongs to input-method composition;repeat=truemeans holding a key generated an automatic repeat. Handle only Enter and Escape; do not implement browser input-method compatibility. execute(itemId, actionId)synchronously hands a command request to an external executor. Check only its target and dispatch count, not server completion. One valid dispatch closes the panel. Reopening allows the same action again; no cross-session business deduplication is required.
Behavior requirements
- Accept a response only when it matches the currently open session, current object and latest request. Neither stale success nor stale failure may change state. Execution is disabled while loading or failed.
- After filtering, retain selection by
actionId. If the old selection is hidden or disabled, select the first visible, enabled action, or nothing if none exists. Reordering must not substitute a target using an old array index. - Return composing Enter/Escape to the adapter: this panel neither executes nor closes. Outside composition, repeated Enter must not dispatch. Ordinary Enter dispatches once and closes only when ready and the current selection remains visible and enabled. Escape closes; late responses must not reopen the panel.
- No DOM, styling or complete code is required. Explain state, response acceptance, selection repair after filtering and the dispatch boundary.
Trace these events
Open A: session 1, request r1. Switch to B: session 2, request r2. r2 succeeds first with [open, copy]; the user selects copy. r1 then fails. Reorder the list to [copy, open], receive a composing Enter, an ordinary Enter and finally a repeated Enter. Record state and dispatched commands after each event.
Also trace a retry r3 followed by an old r2 callback in the same session; closing B and reopening B before an old session succeeds; and filtering that leaves every action unavailable.
Deliverables
Provide a state-transition table, expected outcomes for the sequences, at least three invariants and the limits of client-only guarantees. For n actions, explain the time and space costs of filtering and selection repair. Do not provide a complete implementation or line-by-line pseudocode.
Explore the reasoning
- Keep the three identities separate. The file identifies the target, the session identifies this opening and the request identifies this load or retry. Compare responses with the current triple. Even a correct response after closing cannot restore the panel.
- Select by ID and check again before dispatch. Reordering changes position, not copy's identity. Repair selection against the current visible, enabled actions after filtering or availability changes. Recheck at dispatch rather than using an old index or enabled value captured in a closure.
- Handle input context before actions. Composing Enter is not an execution command, and composing Escape does not belong to this panel's close logic. Exclude repeat for ordinary Enter. In one synchronous event, record the closed state before handing off the command; later repeats then see a closed panel and cannot dispatch again.
- Check the trace by hand. copy stays selected after r2 succeeds. Ignore r1's failure; reordering retains copy. Composing Enter does nothing to the panel. Ordinary Enter dispatches only
execute(B, copy)and closes; repeated Enter adds no command. Ignore r2 after a newer retry and old-session responses after reopening B. With no available action, selection is empty and execution is disabled. - State the guarantee precisely. At most one dispatch per session is not network-write idempotency. Executor retries and unknown outcomes are outside this problem. Scanning n actions takes O(n) time; a new visible array takes O(n) extra space, while the selected ID itself takes O(1). Count input-method adaptation, rendering and networking separately.