From ecef4832fc700c0604dfa1593bc903f0646cc835 Mon Sep 17 00:00:00 2001 From: Jage9 Date: Sun, 22 Feb 2026 20:50:04 -0500 Subject: [PATCH] Suppress duplicate property row echo after quick adjust --- client/public/version.js | 2 +- client/src/items/itemPropertyEditor.ts | 4 ++++ client/src/main.ts | 5 +++++ client/src/network/messageHandlers.ts | 3 ++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/client/public/version.js b/client/public/version.js index 36bc4fb..8d94eff 100644 --- a/client/public/version.js +++ b/client/public/version.js @@ -1,5 +1,5 @@ // Maintainer-controlled web client version. // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) -window.CHGRID_WEB_VERSION = "2026.02.22 R187"; +window.CHGRID_WEB_VERSION = "2026.02.22 R188"; // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. window.CHGRID_TIME_ZONE = "America/Detroit"; diff --git a/client/src/items/itemPropertyEditor.ts b/client/src/items/itemPropertyEditor.ts index b76a662..ff8bcb2 100644 --- a/client/src/items/itemPropertyEditor.ts +++ b/client/src/items/itemPropertyEditor.ts @@ -38,6 +38,7 @@ type EditorDeps = { effectSequenceIdsCsv: string; applyTextInputEdit: (code: string, key: string, maxLength: number, ctrlKey?: boolean, allowReplaceOnNextType?: boolean) => void; setReplaceTextOnNextType: (value: boolean) => void; + suppressItemPropertyEchoMs: (ms: number) => void; updateStatus: (message: string) => void; sfxUiBlip: () => void; sfxUiCancel: () => void; @@ -102,6 +103,7 @@ export function createItemPropertyEditor(deps: EditorDeps): { const delta = code === 'ArrowRight' ? 1 : -1; const nextIndex = (currentIndex + delta + options.length) % options.length; const nextValue = options[nextIndex]; + deps.suppressItemPropertyEchoMs(600); deps.signalingSend({ type: 'item_update', itemId, params: { [selectedKey]: nextValue } }); deps.updateStatus(nextValue); deps.sfxUiBlip(); @@ -114,6 +116,7 @@ export function createItemPropertyEditor(deps: EditorDeps): { current = selectedKey === 'enabled' ? item.params.enabled !== false : item.params[selectedKey] === true; } const nextValue = !current; + deps.suppressItemPropertyEchoMs(600); deps.signalingSend({ type: 'item_update', itemId, params: { [selectedKey]: nextValue } }); deps.updateStatus(nextValue ? 'on' : 'off'); deps.sfxUiBlip(); @@ -136,6 +139,7 @@ export function createItemPropertyEditor(deps: EditorDeps): { let nextValue = attempted; if (Number.isFinite(min)) nextValue = Math.max(min, nextValue); if (Number.isFinite(max)) nextValue = Math.min(max, nextValue); + deps.suppressItemPropertyEchoMs(600); deps.signalingSend({ type: 'item_update', itemId, params: { [selectedKey]: nextValue } }); deps.updateStatus(formatSteppedNumber(nextValue, step)); if (Math.abs(nextValue - currentValue) < 1e-9 || Math.abs(nextValue - attempted) > 1e-9) { diff --git a/client/src/main.ts b/client/src/main.ts index eab0036..ee1c3e6 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -221,6 +221,7 @@ let lastSubscriptionRefreshTileX = Math.round(state.player.x); let lastSubscriptionRefreshTileY = Math.round(state.player.y); let subscriptionRefreshInFlight = false; let subscriptionRefreshPending = false; +let suppressItemPropertyEchoUntilMs = 0; let activeTeleportLoopStop: (() => void) | null = null; let activeTeleportLoopToken = 0; let activeTeleport: @@ -1491,6 +1492,7 @@ const onAppMessage = createOnMessageHandler({ itemPropertyLabel, getItemPropertyValue, getItemById: (itemId) => state.items.get(itemId), + shouldAnnounceItemPropertyEcho: () => Date.now() >= suppressItemPropertyEchoUntilMs, playLocateToneAt: (x, y) => audio.sfxLocate({ x: x - state.player.x, y: y - state.player.y }), resolveIncomingSoundUrl, playIncomingItemUseSound: (url, x, y) => { @@ -2251,6 +2253,9 @@ const itemPropertyEditor = createItemPropertyEditor({ setReplaceTextOnNextType: (value) => { replaceTextOnNextType = value; }, + suppressItemPropertyEchoMs: (ms) => { + suppressItemPropertyEchoUntilMs = Math.max(suppressItemPropertyEchoUntilMs, Date.now() + Math.max(0, ms)); + }, updateStatus, sfxUiBlip: () => audio.sfxUiBlip(), sfxUiCancel: () => audio.sfxUiCancel(), diff --git a/client/src/network/messageHandlers.ts b/client/src/network/messageHandlers.ts index b746a55..043bb0e 100644 --- a/client/src/network/messageHandlers.ts +++ b/client/src/network/messageHandlers.ts @@ -62,6 +62,7 @@ type MessageHandlerDeps = { itemPropertyLabel: (key: string) => string; getItemPropertyValue: (item: WorldItem, key: string) => string; getItemById: (itemId: string) => WorldItem | undefined; + shouldAnnounceItemPropertyEcho: () => boolean; playLocateToneAt: (x: number, y: number) => void; resolveIncomingSoundUrl: (url: string) => string; playIncomingItemUseSound: (url: string, x: number, y: number) => void; @@ -204,7 +205,7 @@ export function createOnMessageHandler(deps: MessageHandlerDeps): (message: Inco deps.state.carriedItemId = deps.getCarriedItemId(); if (deps.state.mode === 'itemProperties' && deps.state.selectedItemId === message.item.id) { const key = deps.state.itemPropertyKeys[deps.state.itemPropertyIndex]; - if (key) { + if (key && deps.shouldAnnounceItemPropertyEcho()) { deps.updateStatus(`${deps.itemPropertyLabel(key)}: ${deps.getItemPropertyValue(message.item, key)}`); } }