actually fix volume selection
This commit is contained in:
@@ -3684,6 +3684,48 @@ function handlePeerData(data, topicId, peer) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Intercept volumes responses and route them to active volume handlers
|
||||
// This ensures volumes responses are never lost, even if handler was replaced
|
||||
if (response && response.success === true && Array.isArray(response.volumes)) {
|
||||
console.log('[DEBUG] ===== Volumes response intercepted in app.js =====');
|
||||
console.log('[DEBUG] Response:', JSON.stringify(response).substring(0, 200));
|
||||
|
||||
// Check if there are active volume handlers
|
||||
if (window.activeVolumeHandlers && window.activeVolumeHandlers.size > 0) {
|
||||
console.log('[DEBUG] Found', window.activeVolumeHandlers.size, 'active volume handler(s)');
|
||||
|
||||
// Route to all active volume handlers
|
||||
// Also check for handlers that timed out but should still process late responses
|
||||
let routed = false;
|
||||
for (const [volumeId, handlerInfo] of window.activeVolumeHandlers.entries()) {
|
||||
const state = handlerInfo?.state;
|
||||
// Process if not received yet, even if it timed out (late response)
|
||||
if (state && !state.volumesReceived) {
|
||||
console.log('[DEBUG] Routing volumes response to handler for volumeId:', volumeId);
|
||||
console.log('[DEBUG] Handler timed out?', state.timedOut);
|
||||
if (handlerInfo.protectedHandler && typeof handlerInfo.protectedHandler === 'function') {
|
||||
handlerInfo.protectedHandler(response);
|
||||
routed = true;
|
||||
} else if (handlerInfo.handler && typeof handlerInfo.handler === 'function') {
|
||||
handlerInfo.handler(response);
|
||||
routed = true;
|
||||
}
|
||||
} else if (state && state.volumesReceived) {
|
||||
console.log('[DEBUG] Handler for volumeId', volumeId, 'already received volumes, skipping');
|
||||
}
|
||||
}
|
||||
|
||||
if (routed) {
|
||||
console.log('[DEBUG] Volumes response routed to volume handler(s), skipping window.handlePeerResponse');
|
||||
return; // Don't pass to window.handlePeerResponse if we routed it
|
||||
} else {
|
||||
console.log('[DEBUG] No active handlers needed this response, passing to window.handlePeerResponse');
|
||||
}
|
||||
} else {
|
||||
console.log('[DEBUG] No active volume handlers found, passing to window.handlePeerResponse');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle peer response callback if defined
|
||||
// This allows custom handlers (like directory browser) to process responses
|
||||
if (typeof window.handlePeerResponse === 'function') {
|
||||
|
||||
+120
-29
@@ -1083,6 +1083,8 @@ const volumeDataCache = new Map();
|
||||
|
||||
// Store active volume handlers to prevent them from being replaced
|
||||
const activeVolumeHandlers = new Map();
|
||||
// Expose to window for app.js to access
|
||||
window.activeVolumeHandlers = activeVolumeHandlers;
|
||||
|
||||
// Load volumes for named volume select
|
||||
async function loadVolumesForSelect(volumeId) {
|
||||
@@ -1138,13 +1140,28 @@ async function loadVolumesForSelect(volumeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store original handler
|
||||
const originalHandler = window.handlePeerResponse;
|
||||
let volumesReceived = false;
|
||||
// Store original handler - create no-op if undefined
|
||||
let originalHandler = window.handlePeerResponse;
|
||||
if (typeof originalHandler !== 'function') {
|
||||
console.log('[DEBUG] Original handler is undefined/null, creating no-op function');
|
||||
originalHandler = () => {
|
||||
// No-op: just log that we received a response that wasn't handled
|
||||
console.log('[DEBUG] No-op handler received response (no original handler was set)');
|
||||
};
|
||||
}
|
||||
|
||||
const requestId = `volumes_${Date.now()}_${Math.random()}`;
|
||||
const startTime = Date.now();
|
||||
let responseCount = 0;
|
||||
|
||||
// Create a shared state object that both handlers can access
|
||||
const handlerState = {
|
||||
volumesReceived: false,
|
||||
volumeId: volumeId,
|
||||
requestId: requestId,
|
||||
startTime: startTime
|
||||
};
|
||||
|
||||
console.log('[DEBUG] ===== Setting up volume handler =====');
|
||||
console.log('[DEBUG] Request ID:', requestId);
|
||||
console.log('[DEBUG] Volume ID:', volumeId);
|
||||
@@ -1164,7 +1181,7 @@ async function loadVolumesForSelect(volumeId) {
|
||||
console.log('[DEBUG] Response volumes:', response?.volumes);
|
||||
console.log('[DEBUG] Response type:', response?.type);
|
||||
console.log('[DEBUG] Is volumes array?', Array.isArray(response?.volumes));
|
||||
console.log('[DEBUG] Volumes received flag:', volumesReceived);
|
||||
console.log('[DEBUG] Volumes received flag:', handlerState.volumesReceived);
|
||||
|
||||
// Log ALL responses to help debug
|
||||
if (elapsed < 100) {
|
||||
@@ -1192,7 +1209,7 @@ async function loadVolumesForSelect(volumeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (volumesReceived) {
|
||||
if (handlerState.volumesReceived) {
|
||||
// Already processed, pass to original handler
|
||||
console.log('[DEBUG] Already processed volumes response, passing to original handler');
|
||||
if (typeof originalHandler === 'function' && originalHandler !== volumeHandler) {
|
||||
@@ -1202,6 +1219,13 @@ async function loadVolumesForSelect(volumeId) {
|
||||
}
|
||||
|
||||
console.log('[DEBUG] ===== Processing volumes response =====');
|
||||
console.log('[DEBUG] Handler state at processing time:');
|
||||
console.log('[DEBUG] - volumesReceived:', handlerState.volumesReceived);
|
||||
console.log('[DEBUG] - volumeId:', handlerState.volumeId);
|
||||
console.log('[DEBUG] - requestId:', handlerState.requestId);
|
||||
console.log('[DEBUG] - elapsed time:', Date.now() - handlerState.startTime, 'ms');
|
||||
console.log('[DEBUG] Active handlers count:', activeVolumeHandlers.size);
|
||||
console.log('[DEBUG] Handler still in activeVolumeHandlers:', activeVolumeHandlers.has(volumeId));
|
||||
|
||||
// Handle success response - check multiple formats
|
||||
let volumesArray = null;
|
||||
@@ -1227,7 +1251,7 @@ async function loadVolumesForSelect(volumeId) {
|
||||
|
||||
if (volumesArray !== null) {
|
||||
console.log('[DEBUG] Successfully extracted volumes array, count:', volumesArray.length);
|
||||
volumesReceived = true;
|
||||
handlerState.volumesReceived = true;
|
||||
|
||||
// Remove this handler from active handlers
|
||||
activeVolumeHandlers.delete(volumeId);
|
||||
@@ -1382,7 +1406,7 @@ async function loadVolumesForSelect(volumeId) {
|
||||
else if (response && response.error) {
|
||||
console.error('[ERROR] ===== Volumes request returned error =====');
|
||||
console.error('[ERROR] Error message:', response.error);
|
||||
volumesReceived = true;
|
||||
handlerState.volumesReceived = true;
|
||||
activeVolumeHandlers.delete(volumeId);
|
||||
|
||||
if (window.handlePeerResponse === volumeHandler) {
|
||||
@@ -1406,7 +1430,7 @@ async function loadVolumesForSelect(volumeId) {
|
||||
console.warn('[WARN] ===== Unexpected volumes response format =====');
|
||||
console.warn('[WARN] Response:', JSON.stringify(response));
|
||||
if (response && response.volumes !== undefined) {
|
||||
volumesReceived = true;
|
||||
handlerState.volumesReceived = true;
|
||||
activeVolumeHandlers.delete(volumeId);
|
||||
|
||||
const handlerInfo = activeVolumeHandlers.get(volumeId);
|
||||
@@ -1446,14 +1470,69 @@ async function loadVolumesForSelect(volumeId) {
|
||||
|
||||
// Create a wrapper that checks if this handler is still active
|
||||
const protectedHandler = (response) => {
|
||||
// First check if this is a volumes response - use same detection logic as volumeHandler
|
||||
const isVolumesResponse =
|
||||
(response && response.success === true && Array.isArray(response.volumes)) ||
|
||||
(response && response.success === true && response.volumes !== undefined) ||
|
||||
(response && response.error && (response.error.includes('volume') || response.error.includes('Volume'))) ||
|
||||
(response && !response.type && Array.isArray(response.volumes)) ||
|
||||
(response && response.type === 'volumes' && response.data) ||
|
||||
(response && response.volumes && typeof response.volumes === 'object' && !Array.isArray(response.volumes) && response.volumes.Volumes);
|
||||
|
||||
// Get handler info - but also use closure's handlerState as fallback
|
||||
const handlerInfo = activeVolumeHandlers.get(volumeId);
|
||||
// Use handlerState from closure if handlerInfo was removed
|
||||
// Prefer handlerInfo.state if it exists, otherwise use closure's handlerState
|
||||
const state = handlerInfo?.state || handlerState;
|
||||
|
||||
console.log('[DEBUG] Protected handler called');
|
||||
console.log('[DEBUG] isVolumesResponse:', isVolumesResponse);
|
||||
console.log('[DEBUG] volumesReceived (from state):', state?.volumesReceived);
|
||||
console.log('[DEBUG] volumesReceived (from closure):', handlerState.volumesReceived);
|
||||
console.log('[DEBUG] handlerInfo exists:', !!handlerInfo);
|
||||
console.log('[DEBUG] volumeId:', volumeId);
|
||||
console.log('[DEBUG] timedOut:', state?.timedOut);
|
||||
|
||||
// If it's a volumes response, ALWAYS try to process it if we haven't actually processed one yet
|
||||
// This handles cases where handler info was removed but response arrives late
|
||||
// Also handles cases where timeout occurred but response arrives late
|
||||
// Also handles cases where volumesReceived flag is incorrectly set
|
||||
if (isVolumesResponse) {
|
||||
// Check if we should process it
|
||||
// Process if: volumesReceived is false, OR handlerInfo was removed (late response)
|
||||
const shouldProcess = !state?.volumesReceived || !handlerInfo;
|
||||
|
||||
if (shouldProcess) {
|
||||
console.log('[DEBUG] Protected handler: Volumes response detected, processing with volumeHandler');
|
||||
console.log('[DEBUG] Using handlerState from:', handlerInfo ? 'activeVolumeHandlers' : 'closure');
|
||||
console.log('[DEBUG] Handler timed out?', state?.timedOut);
|
||||
console.log('[DEBUG] Handler info exists:', !!handlerInfo);
|
||||
console.log('[DEBUG] volumesReceived flag:', state?.volumesReceived);
|
||||
console.log('[DEBUG] Processing because:', !handlerInfo ? 'handlerInfo was removed (late response)' : 'volumesReceived is false');
|
||||
// Process it even if it timed out or handlerInfo was removed - the response is here now!
|
||||
volumeHandler(response);
|
||||
return; // Don't pass to original handler
|
||||
} else {
|
||||
console.log('[DEBUG] Protected handler: Volumes response already processed, passing to original handler');
|
||||
console.log('[DEBUG] volumesReceived:', state?.volumesReceived);
|
||||
console.log('[DEBUG] handlerInfo exists:', !!handlerInfo);
|
||||
// Already processed, pass to original handler
|
||||
if (typeof originalHandler === 'function' && originalHandler !== volumeHandler && originalHandler !== protectedHandler) {
|
||||
originalHandler(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a volumes response - check if handler is still active
|
||||
if (handlerInfo && handlerInfo.handler === volumeHandler) {
|
||||
// Handler is still active, process the response
|
||||
// Handler is still active, process it (for non-volumes responses)
|
||||
console.log('[DEBUG] Protected handler: Handler still active, processing non-volumes response');
|
||||
volumeHandler(response);
|
||||
} else {
|
||||
// Handler was replaced, pass to original handler
|
||||
console.log('[DEBUG] Handler was replaced, passing response to original handler');
|
||||
if (typeof originalHandler === 'function' && originalHandler !== volumeHandler) {
|
||||
// Handler was replaced or not a volumes response, pass to original handler
|
||||
console.log('[DEBUG] Protected handler: Handler was replaced or inactive, passing to original handler');
|
||||
if (typeof originalHandler === 'function' && originalHandler !== volumeHandler && originalHandler !== protectedHandler) {
|
||||
originalHandler(response);
|
||||
}
|
||||
}
|
||||
@@ -1465,7 +1544,8 @@ async function loadVolumesForSelect(volumeId) {
|
||||
protectedHandler: protectedHandler,
|
||||
requestId: requestId,
|
||||
startTime: startTime,
|
||||
originalHandler: originalHandler
|
||||
originalHandler: originalHandler,
|
||||
state: handlerState
|
||||
});
|
||||
|
||||
// Set the protected handler BEFORE sending command
|
||||
@@ -1473,6 +1553,16 @@ async function loadVolumesForSelect(volumeId) {
|
||||
console.log('[DEBUG] ===== Volume handler installed =====');
|
||||
console.log('[DEBUG] Handler stored in activeVolumeHandlers:', activeVolumeHandlers.has(volumeId));
|
||||
console.log('[DEBUG] window.handlePeerResponse === volumeHandler:', window.handlePeerResponse === volumeHandler);
|
||||
console.log('[DEBUG] window.handlePeerResponse === protectedHandler:', window.handlePeerResponse === protectedHandler);
|
||||
console.log('[DEBUG] window.handlePeerResponse type:', typeof window.handlePeerResponse);
|
||||
|
||||
// Verify handler is set synchronously
|
||||
if (window.handlePeerResponse !== protectedHandler) {
|
||||
console.error('[ERROR] Handler verification failed! window.handlePeerResponse !== protectedHandler');
|
||||
console.error('[ERROR] This should never happen - handler was not set correctly');
|
||||
} else {
|
||||
console.log('[DEBUG] Handler verification passed - protectedHandler is correctly set');
|
||||
}
|
||||
|
||||
// Send the command - always fetch fresh from server
|
||||
console.log('[DEBUG] ===== Sending listVolumes command =====');
|
||||
@@ -1480,6 +1570,15 @@ async function loadVolumesForSelect(volumeId) {
|
||||
window.sendCommand('listVolumes');
|
||||
console.log('[DEBUG] listVolumes command sent successfully');
|
||||
console.log('[DEBUG] Waiting for response...');
|
||||
|
||||
// Verify handler is still set after sending command
|
||||
if (window.handlePeerResponse !== protectedHandler) {
|
||||
console.warn('[WARN] Handler was replaced immediately after sending command!');
|
||||
console.warn('[WARN] Current handler:', typeof window.handlePeerResponse);
|
||||
// Restore it
|
||||
window.handlePeerResponse = protectedHandler;
|
||||
console.log('[DEBUG] Handler restored');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[ERROR] Failed to send listVolumes command:', error);
|
||||
activeVolumeHandlers.delete(volumeId);
|
||||
@@ -1501,28 +1600,20 @@ async function loadVolumesForSelect(volumeId) {
|
||||
console.warn('[WARN] ===== Volumes list request TIMED OUT =====');
|
||||
console.warn('[WARN] Elapsed time:', elapsed, 'ms');
|
||||
console.warn('[WARN] Request ID:', requestId);
|
||||
console.warn('[WARN] Volumes received:', volumesReceived);
|
||||
console.warn('[WARN] Volumes received:', handlerState.volumesReceived);
|
||||
console.warn('[WARN] Handler still active:', window.handlePeerResponse === volumeHandler);
|
||||
console.warn('[WARN] Current handler type:', typeof window.handlePeerResponse);
|
||||
console.warn('[WARN] Response count received:', responseCount);
|
||||
console.warn('[WARN] Active handlers:', Array.from(activeVolumeHandlers.keys()));
|
||||
|
||||
if (!volumesReceived) {
|
||||
// Remove from active handlers
|
||||
activeVolumeHandlers.delete(volumeId);
|
||||
if (!handlerState.volumesReceived) {
|
||||
// Don't remove from active handlers yet - keep it so late-arriving responses can be processed
|
||||
// Just mark that we've timed out
|
||||
handlerState.timedOut = true;
|
||||
console.warn('[WARN] Marked handler as timed out, but keeping in activeVolumeHandlers for late responses');
|
||||
|
||||
// Only restore original handler if current handler is still our protected handler
|
||||
const handlerInfo = activeVolumeHandlers.get(volumeId);
|
||||
if (handlerInfo && window.handlePeerResponse === handlerInfo.protectedHandler) {
|
||||
window.handlePeerResponse = originalHandler;
|
||||
console.warn('[WARN] Restored original handler after timeout');
|
||||
} else {
|
||||
console.warn('[WARN] Handler was already replaced before timeout');
|
||||
console.warn('[WARN] Current handler:', typeof window.handlePeerResponse);
|
||||
console.warn('[WARN] Expected handler:', typeof handlerInfo?.protectedHandler);
|
||||
}
|
||||
|
||||
volumesReceived = true; // Mark as received to prevent double handling
|
||||
// Don't restore original handler yet - keep protected handler active to catch late responses
|
||||
// Only restore if we're sure no response will arrive
|
||||
volumeLoadingStates.delete(volumeId);
|
||||
|
||||
const currentSelect = document.querySelector(`[data-volume-named="${volumeId}"]`);
|
||||
|
||||
Reference in New Issue
Block a user