mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 07:42:23 +00:00
fix(cockpit): an application subject's wait for the floor is bounded, a late asynchronous hold is released, and a hold never counts as the user's selection
- A subject with no height at all waits at most COCKPIT_GROUND_WAIT_TIMEOUT_MS for the floor, its HUD updating and reading ACQUIRING SURFACE; then the view ends and the provider gets its subject back (there is no height of its own to fall back to). - A hold that returns a promise is refused as before and released again once it settles, unless that subject is being ridden by then; release must tolerate a second call. - Rail and Transit stamp selectedAtMs only for a user's selection (a click, focusTrain or focusVehicle); a deselection clears it, and a train or vehicle selected only by a hold reads null.
This commit is contained in:
1 parent
1e4060f6ba
commit
4c33552105
13 files changed
+239
-28
No files matched your search
@@ -170,8 +170,10 @@ function refusal(provider, kinds) {
|
||||
* - `candidate()`, `isEntryAllowed(candidate)` (optional), `hold(id)`,
|
||||
* `read(nowMs, ctx)`, `hud(frame, ctx)` and `release(id, {restore})`, all
|
||||
* synchronous (createCockpitSubjectCaller). `isEntryAllowed` allows entry
|
||||
* only by returning `true`. A `hold` that throws is followed by
|
||||
* `release(id, {restore: false})`.
|
||||
* only by returning `true`. A `hold` that throws or returns a promise
|
||||
* refuses entry and is followed by `release(id, {restore: false})`, and by
|
||||
* another once that promise settles; `release` must therefore be harmless
|
||||
* when called again for a subject it already gave back.
|
||||
*
|
||||
* A provider that is not so is left out with one warning naming it.
|
||||
* @param {unknown} list
|
||||
@@ -501,7 +503,9 @@ export function cockpitSubjectHudView(raw) {
|
||||
* Provider methods are synchronous: the Cockpit calls them on its render
|
||||
* cadence and uses the answer at once. One that returns a promise (an async
|
||||
* function, say) breaks that contract: the promise is refused as a throw
|
||||
* would be (its rejection, if any, is swallowed), with one warning.
|
||||
* would be (its rejection, if any, is swallowed), with one warning, and
|
||||
* `onSettled`, when given, runs once the promise has settled, so a caller
|
||||
* can undo work that lands late.
|
||||
* @param {{warn?: (message: string, error: unknown) => void}} [options]
|
||||
*/
|
||||
export function createCockpitSubjectCaller({
|
||||
@@ -517,7 +521,13 @@ export function createCockpitSubjectCaller({
|
||||
error,
|
||||
);
|
||||
};
|
||||
return function call(provider, method, args = [], fallback = null) {
|
||||
return function call(
|
||||
provider,
|
||||
method,
|
||||
args = [],
|
||||
fallback = null,
|
||||
onSettled = null,
|
||||
) {
|
||||
let result;
|
||||
try {
|
||||
result = provider[method](...args);
|
||||
@@ -530,7 +540,11 @@ export function createCockpitSubjectCaller({
|
||||
(typeof result === 'object' || typeof result === 'function') &&
|
||||
typeof result.then === 'function'
|
||||
) {
|
||||
Promise.resolve(result).catch(() => {});
|
||||
// Its work may still land: `onSettled` runs once it has, either way.
|
||||
const settled = () => {
|
||||
if (typeof onSettled === 'function') onSettled();
|
||||
};
|
||||
Promise.resolve(result).then(settled, settled);
|
||||
warnOnce(
|
||||
provider,
|
||||
method,
|
||||
|
||||
Reference in new issue
Block a user