fix(rail): focusTrain refuses a train the layer does not draw

A ride let go with restore focuses its train again. When the train's
category was turned off during the ride, or for a copy another feed draws,
focusTrain selected and followed a train with no marker. It now returns
false for a train in a category turned off or hidden as another feed's
copy, and leaves the selection and the camera as they are.
This commit is contained in:
Denis Groshev committed 2026-11-12 17:00:12 +01:00
1 parent 4ae67fcb35
commit feaf59776c
2 files changed
+28 -2

No files matched your search

+4 -2
View File
@@ -299,10 +299,12 @@ export function createRailCockpitSubject({
/**
* Select the train `key` and hand it the camera, as a click on it does.
* @param {string} key
* @returns {boolean} False for a train the layer does not show.
* @returns {boolean} False for a train the layer does not show: gone, in
* a category turned off, or a copy another feed draws (dedupe.js).
*/
focusTrain(key) {
if (!state._trains.has(key)) return false;
const entry = state._trains.get(key);
if (!entry || !parts.rendering.categoryShown(entry)) return false;
parts.selection.selectAndFocusTrain(key);
return true;
},
+24
View File
@@ -290,6 +290,9 @@ test('a held train stays the copy drawn when another feed’s copy outranks it,
1,
'its card',
);
// The copy hidden is not focused: the selection stays on the one drawn.
assert.equal(app.layer.focusTrain(a), false);
assert.equal(app.state()._selectedKey, b);
// A hold of the copy hidden draws it at once, in place of the other.
assert.equal(app.layer.setCockpitSubject(a), true);
@@ -343,6 +346,27 @@ test('a held train keeps the selection and moves, hidden, when its category is t
assert.ok(app.state()._moving.has(app.entry(T1)), 'playing again');
});
test('a ride let go with restore does not focus a train its category hides', async (t) => {
const app = await onTheLine(t);
// The documented provider: hold on entry; on exit, release, then focus
// the train again when asked to restore.
assert.equal(app.layer.setCockpitSubject(T1), true);
app.layer.setParams({ regional: false });
app.layer.setCockpitSubject(null);
assert.equal(app.layer.focusTrain(T1), false, 'not drawn');
assert.equal(app.state()._selectedKey, null, 'not selected');
assert.equal(app.parts().follow.stats(), null, 'not followed');
assert.equal(app.viewer.trackedEntity, undefined);
assert.equal(app.focusRequests.length, 0, 'not flown to');
assert.equal(app.entry(T1).marker.show, false);
// Shown again, it focuses as before.
app.layer.setParams({ regional: true });
assert.equal(app.layer.focusTrain(T1), true);
assert.equal(app.state()._selectedKey, T1);
assert.ok(app.parts().follow.isFollowing(T1), 'the camera is handed to it');
});
test('a held train that goes takes the hold with it; focusTrain selects', async (t) => {
const app = await onTheLine(t);
app.layer.setCockpitSubject(T1);