[feat](trx-frontend-http): rebuild the general radio controls row
Mode was a full-width select: 483px of the row to display "FM". The modes are three or four characters and there are at most twelve, so they become a segmented group like the Unit and Step Scale pickers beside them — a third of the width, and one click instead of two. The <select> stays as the mode's value. A dozen call sites and several plugins read #mode.value, so replacing it outright would have reached much further than a layout change should; it is hidden from sight and from assistive tech, the buttons write to it, and everything downstream runs unchanged. Every writer re-syncs the buttons, the plugins through a new trxCore.syncModePicker. The row itself was a grid with a track per column, but the WFM, SAM and transmit columns are hidden on most rigs, so it ended in some 500px of hole. It packs left now. Same fault one level down: the power buttons sat in three fixed tracks, so a rig with neither transmit nor lock kept two empty ones and left its label chip stranded at the far edge. Unit and Step Scale move out of the frequency row and in beside the wheel and the +/- they modify, which were some 600px away. Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -29,7 +29,7 @@ class ElementFixture {
|
||||
// Mirrors the `window.trx` host contract published by app.ts. The plugin is a
|
||||
// separate bundle, so every application service it uses arrives this way.
|
||||
function hostFixture(overrides = {}) {
|
||||
const calls = { postPath: [], setRigFrequency: [], armOptimisticFrequency: [], applyLocalTunedFrequency: [], syncBandwidthInput: [], scheduleSpectrumDraw: 0 };
|
||||
const calls = { postPath: [], setRigFrequency: [], armOptimisticFrequency: [], applyLocalTunedFrequency: [], syncBandwidthInput: [], scheduleSpectrumDraw: 0, syncModePicker: 0 };
|
||||
const state = {
|
||||
authEnabled: false,
|
||||
authRole: "control",
|
||||
@@ -50,6 +50,7 @@ function hostFixture(overrides = {}) {
|
||||
armOptimisticFrequency: (hz) => { calls.armOptimisticFrequency.push(hz); },
|
||||
syncBandwidthInput: (hz) => { calls.syncBandwidthInput.push(hz); },
|
||||
scheduleSpectrumDraw: () => { calls.scheduleSpectrumDraw += 1; },
|
||||
syncModePicker: () => { calls.syncModePicker += 1; },
|
||||
onDecoderRegistryReady: () => {},
|
||||
};
|
||||
return { window: { trx: { state, core, modules: {} }, trxUi: { confirm: async () => true } }, calls };
|
||||
|
||||
@@ -23,6 +23,32 @@ try {
|
||||
await page.locator("summary", { hasText: "Audio controls" }).click();
|
||||
assert.equal(await page.locator("#rx-audio-btn").count(), 1);
|
||||
|
||||
// Mode is a button group over a hidden <select>, which stays the value a
|
||||
// dozen call sites and several plugins read. The click has to reach it, and
|
||||
// the select must not take part in layout while it does.
|
||||
const modeBefore = await page.evaluate(() => ({
|
||||
buttons: document.querySelectorAll("#mode-picker button").length,
|
||||
value: document.getElementById("mode").value,
|
||||
active: document.querySelector("#mode-picker button.active")?.dataset.mode,
|
||||
}));
|
||||
assert.ok(modeBefore.buttons > 1, `mode picker rendered ${modeBefore.buttons} buttons`);
|
||||
assert.equal(modeBefore.active, modeBefore.value, "mode picker disagrees with the select");
|
||||
const target = await page.evaluate(() => {
|
||||
const other = [...document.querySelectorAll("#mode-picker button")]
|
||||
.find((btn) => btn.dataset.mode !== document.getElementById("mode").value);
|
||||
return other?.dataset.mode;
|
||||
});
|
||||
await page.locator(`#mode-picker button[data-mode="${target}"]`).click();
|
||||
await page.waitForTimeout(200);
|
||||
const modeAfter = await page.evaluate(() => ({
|
||||
value: document.getElementById("mode").value,
|
||||
active: document.querySelector("#mode-picker button.active")?.dataset.mode,
|
||||
selectWidth: Math.round(document.getElementById("mode").getBoundingClientRect().width),
|
||||
}));
|
||||
assert.equal(modeAfter.value, target, `clicking ${target} left the select at ${modeAfter.value}`);
|
||||
assert.equal(modeAfter.active, target, "the clicked mode is not the marked one");
|
||||
assert.ok(modeAfter.selectWidth <= 2, `the hidden select still occupies ${modeAfter.selectWidth}px`);
|
||||
|
||||
// Scheduler controls read left to right: step, hand back, then the entry on
|
||||
// air. The separator is drawn by the current-entry block, so it can only sit
|
||||
// in the right place if that block is last.
|
||||
|
||||
@@ -57,6 +57,7 @@ export function createHost({ state = {}, core = {}, modules = {} } = {}) {
|
||||
setRigFrequency: record("setRigFrequency"),
|
||||
syncBandwidthInput: record("syncBandwidthInput"),
|
||||
scheduleSpectrumDraw: record("scheduleSpectrumDraw"),
|
||||
syncModePicker: record("syncModePicker"),
|
||||
onDecoderRegistryReady: record("onDecoderRegistryReady"),
|
||||
...core,
|
||||
},
|
||||
|
||||
@@ -63,6 +63,7 @@ function assetPath(urlPath) {
|
||||
*/
|
||||
export async function startWebFixture({
|
||||
spectrum = false,
|
||||
tx = false,
|
||||
bookmarks = [],
|
||||
bandplan = {},
|
||||
bandplanEnabled = false,
|
||||
@@ -73,7 +74,7 @@ export async function startWebFixture({
|
||||
manufacturer: "Smoke",
|
||||
model: "Fixture",
|
||||
supported_modes: ["FM"],
|
||||
tx: false,
|
||||
tx,
|
||||
filter_controls: spectrum,
|
||||
initialized: true,
|
||||
latitude: null,
|
||||
@@ -92,17 +93,17 @@ export async function startWebFixture({
|
||||
capabilities: {
|
||||
min_freq_step_hz: 1,
|
||||
supported_bands: [],
|
||||
supported_modes: ["FM"],
|
||||
supported_modes: ["LSB", "USB", "CW", "CWR", "AM", "SAM", "WFM", "FM", "AIS", "VDES", "DIG", "PKT"],
|
||||
num_vfos: 1,
|
||||
lock: false,
|
||||
lockable: false,
|
||||
lockable: tx,
|
||||
attenuator: false,
|
||||
preamp: false,
|
||||
rit: false,
|
||||
rpt: false,
|
||||
split: false,
|
||||
tx: false,
|
||||
tx_limit: false,
|
||||
tx,
|
||||
tx_limit: tx,
|
||||
vfo_switch: false,
|
||||
filter_controls: spectrum,
|
||||
signal_meter: spectrum,
|
||||
|
||||
Reference in New Issue
Block a user