From 12982de8596a7063ce1a164067944be854dfea83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Dec 2025 05:00:37 +0000 Subject: [PATCH 1/4] Initial plan From 42dc407c3f2d7d27d45126a4b52b8f274b60b22a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Dec 2025 05:07:06 +0000 Subject: [PATCH 2/4] Fix ping controls unlocking prematurely before API post completes - Add state.pingInProgress flag to track full ping lifecycle - Lock ping controls when ping operation starts (after validation) - Unlock controls only after API post completes in postApiAndRefreshMap - Add unlock logic for error paths and edge cases - Add debug logging for control lock/unlock events - Ensure controls remain locked during: ping send, RX listening, finalizing repeats, and API posting Co-authored-by: MrAlders0n <55921894+MrAlders0n@users.noreply.github.com> --- content/wardrive.js | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/content/wardrive.js b/content/wardrive.js index dddca09..0bbbec4 100644 --- a/content/wardrive.js +++ b/content/wardrive.js @@ -130,6 +130,7 @@ const state = { capturedPingCoords: null, // { lat, lon, accuracy } captured at ping time, used for API post after 7s delay devicePublicKey: null, // Hex string of device's public key (used for capacity check) disconnectReason: null, // Tracks the reason for disconnection (e.g., "app_down", "capacity_full", "error", "normal") + pingInProgress: false, // Flag to track if a ping operation (including API post) is in progress repeaterTracking: { isListening: false, // Whether we're currently listening for echoes sentTimestamp: null, // Timestamp when the ping was sent @@ -425,8 +426,10 @@ function startCooldown() { function updateControlsForCooldown() { const connected = !!state.connection; const inCooldown = isInCooldown(); - sendPingBtn.disabled = !connected || inCooldown; - autoToggleBtn.disabled = !connected || inCooldown; + const pingInProgress = state.pingInProgress; + debugLog(`updateControlsForCooldown: connected=${connected}, inCooldown=${inCooldown}, pingInProgress=${pingInProgress}`); + sendPingBtn.disabled = !connected || inCooldown || pingInProgress; + autoToggleBtn.disabled = !connected || inCooldown || pingInProgress; } // Timer cleanup @@ -461,6 +464,9 @@ function cleanupAllTimers() { // Clear captured ping coordinates state.capturedPingCoords = null; + // Clear ping in progress flag + state.pingInProgress = false; + // Clear device public key state.devicePublicKey = null; } @@ -1190,6 +1196,11 @@ async function postApiAndRefreshMap(lat, lon, accuracy, heardRepeats) { debugLog(`Skipping map refresh (accuracy ${accuracy}m exceeds threshold)`); } + // Unlock ping controls now that API post is complete + state.pingInProgress = false; + updateControlsForCooldown(); + debugLog("Ping controls unlocked (pingInProgress=false) after API post completion"); + // Update status based on current mode if (state.connection) { if (state.running) { @@ -1834,6 +1845,11 @@ async function sendPing(manual = false) { // Both validations passed - execute ping operation (Mesh + API) debugLog("All validations passed, executing ping operation"); + // Lock ping controls for the entire ping lifecycle (until API post completes) + state.pingInProgress = true; + updateControlsForCooldown(); + debugLog("Ping controls locked (pingInProgress=true)"); + const payload = buildPayload(lat, lon); debugLog(`Sending ping to channel: "${payload}"`); @@ -1904,6 +1920,11 @@ async function sendPing(manual = false) { // This should never happen as coordinates are always captured before ping debugError(`CRITICAL: No captured ping coordinates available for API post - this indicates a logic error`); debugError(`Skipping API post to avoid posting incorrect coordinates`); + + // Unlock ping controls since API post is being skipped + state.pingInProgress = false; + updateControlsForCooldown(); + debugLog("Ping controls unlocked (pingInProgress=false) after skipping API post due to missing coordinates"); } // Clear captured coordinates after API post completes (always, regardless of path) @@ -1919,6 +1940,11 @@ async function sendPing(manual = false) { } catch (e) { debugError(`Ping operation failed: ${e.message}`, e); setStatus(e.message || "Ping failed", STATUS_COLORS.error); + + // Unlock ping controls on error + state.pingInProgress = false; + updateControlsForCooldown(); + debugLog("Ping controls unlocked (pingInProgress=false) after error"); } } From f9547778ed8e5143c42259f954740c874106ff36 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Dec 2025 05:08:06 +0000 Subject: [PATCH 3/4] Update CONNECTION_WORKFLOW.md to document ping control locking behavior - Add details about control locking during entire ping lifecycle - Document when controls lock/unlock relative to API posting - Clarify that controls remain locked through all phases including API post Co-authored-by: MrAlders0n <55921894+MrAlders0n@users.noreply.github.com> --- docs/CONNECTION_WORKFLOW.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/CONNECTION_WORKFLOW.md b/docs/CONNECTION_WORKFLOW.md index 288a144..9e6f97c 100644 --- a/docs/CONNECTION_WORKFLOW.md +++ b/docs/CONNECTION_WORKFLOW.md @@ -523,6 +523,10 @@ stateDiagram-v2 ### Auto-Ping Interactions - **Manual during auto**: auto pauses, resumes after - **7s cooldown**: prevents rapid-fire pings +- **Control locking**: "Send Ping" and "Start Auto Ping" buttons remain locked for entire ping lifecycle: + - Locked when: ping sent → listening for repeats (7s) → finalizing repeats → posting to API (3s + API time) + - Unlocked when: API post completes or error occurs + - Prevents starting new pings while previous ping is still processing - **Page hidden**: auto stops, must restart manually - **Cooldown bypass**: only on disconnect From d12735ffcd6e51f948be600ad1856d848b944e33 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Dec 2025 05:09:59 +0000 Subject: [PATCH 4/4] Refactor ping control unlocking to use helper function - Create unlockPingControls(reason) helper to eliminate code duplication - Remove redundant pingInProgress variable in updateControlsForCooldown - Use helper function in all unlock paths for consistency - Improves maintainability and ensures consistent behavior Co-authored-by: MrAlders0n <55921894+MrAlders0n@users.noreply.github.com> --- content/wardrive.js | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/content/wardrive.js b/content/wardrive.js index 0bbbec4..8a4ecb7 100644 --- a/content/wardrive.js +++ b/content/wardrive.js @@ -426,10 +426,19 @@ function startCooldown() { function updateControlsForCooldown() { const connected = !!state.connection; const inCooldown = isInCooldown(); - const pingInProgress = state.pingInProgress; - debugLog(`updateControlsForCooldown: connected=${connected}, inCooldown=${inCooldown}, pingInProgress=${pingInProgress}`); - sendPingBtn.disabled = !connected || inCooldown || pingInProgress; - autoToggleBtn.disabled = !connected || inCooldown || pingInProgress; + debugLog(`updateControlsForCooldown: connected=${connected}, inCooldown=${inCooldown}, pingInProgress=${state.pingInProgress}`); + sendPingBtn.disabled = !connected || inCooldown || state.pingInProgress; + autoToggleBtn.disabled = !connected || inCooldown || state.pingInProgress; +} + +/** + * Helper function to unlock ping controls after ping operation completes + * @param {string} reason - Debug reason for unlocking controls + */ +function unlockPingControls(reason) { + state.pingInProgress = false; + updateControlsForCooldown(); + debugLog(`Ping controls unlocked (pingInProgress=false) ${reason}`); } // Timer cleanup @@ -1197,9 +1206,7 @@ async function postApiAndRefreshMap(lat, lon, accuracy, heardRepeats) { } // Unlock ping controls now that API post is complete - state.pingInProgress = false; - updateControlsForCooldown(); - debugLog("Ping controls unlocked (pingInProgress=false) after API post completion"); + unlockPingControls("after API post completion"); // Update status based on current mode if (state.connection) { @@ -1922,9 +1929,7 @@ async function sendPing(manual = false) { debugError(`Skipping API post to avoid posting incorrect coordinates`); // Unlock ping controls since API post is being skipped - state.pingInProgress = false; - updateControlsForCooldown(); - debugLog("Ping controls unlocked (pingInProgress=false) after skipping API post due to missing coordinates"); + unlockPingControls("after skipping API post due to missing coordinates"); } // Clear captured coordinates after API post completes (always, regardless of path) @@ -1942,9 +1947,7 @@ async function sendPing(manual = false) { setStatus(e.message || "Ping failed", STATUS_COLORS.error); // Unlock ping controls on error - state.pingInProgress = false; - updateControlsForCooldown(); - debugLog("Ping controls unlocked (pingInProgress=false) after error"); + unlockPingControls("after error"); } }