release: v4.8.8 file transfer consent fix
Complete the mandatory receiver-consent gate that was wired in the backend but never connected to the UI callback chain: - Add the missing onIncomingFileRequest (4th) callback to setFileTransferCallbacks in app.jsx — its absence caused handleFileTransferStart to auto-reject every incoming file. - Remove independent callback registration from FileTransferComponent; the component was overwriting app-level callbacks on mount and nulling all four on unmount, silently breaking progress/received/ error handlers whenever the panel was hidden. - Lift pendingIncomingFiles state to the root component so consent prompts are shown regardless of panel visibility; auto-open the panel on incoming request. - Add getReceivedFileObjectURL / revokeReceivedFileObjectURL on EnhancedSecureWebRTCManager for download buttons in the panel. - Update file-transfer-ui-cleanup regression test to match the new single-owner callback architecture. - All 14 tests pass; clean production build. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,18 +58,26 @@ const manager = {
|
||||
isVerified: false
|
||||
};
|
||||
|
||||
context.window.FileTransferComponent({ webrtcManager: manager, isConnected: false });
|
||||
// Component no longer manages callbacks — consent is handled by the parent (app.jsx).
|
||||
// pendingIncomingFiles and onIncomingDecision are passed as props.
|
||||
context.window.FileTransferComponent({ webrtcManager: manager, isConnected: false, pendingIncomingFiles: [], onIncomingDecision: null });
|
||||
const cleanups = effects.map(effect => effect()).filter(Boolean);
|
||||
|
||||
assert.ok(setterCalls.some(call => call.index === 2 && Array.isArray(call.value) && call.value.length === 0));
|
||||
assert.ok(setterCalls.some(call => call.index === 3 && Array.isArray(call.value) && call.value.length === 0));
|
||||
// State index 0 = dragOver, index 1 = transfers.
|
||||
// Transfers state should be reset to empty on disconnect.
|
||||
assert.ok(setterCalls.some(call => call.index === 1 && call.value.sending.length === 0 && call.value.receiving.length === 0));
|
||||
|
||||
// Component must NOT call setFileTransferCallbacks — that is the parent's responsibility.
|
||||
assert.equal(callbackCalls.length, 0, 'FileTransferComponent must not register its own callbacks');
|
||||
|
||||
// Cleanup effects must not null-out the manager's callbacks either.
|
||||
cleanups.forEach(cleanup => cleanup());
|
||||
assert.deepEqual(callbackCalls.at(-1), [null, null, null, null]);
|
||||
assert.equal(manager.fileTransferSystem.onProgress, null);
|
||||
assert.equal(manager.fileTransferSystem.onFileReceived, null);
|
||||
assert.equal(manager.fileTransferSystem.onError, null);
|
||||
assert.equal(manager.fileTransferSystem.onIncomingFileRequest, null);
|
||||
assert.equal(callbackCalls.length, 0, 'cleanup must not call setFileTransferCallbacks');
|
||||
|
||||
// fileTransferSystem callbacks are untouched by the component.
|
||||
assert.equal(typeof manager.fileTransferSystem.onProgress, 'function');
|
||||
assert.equal(typeof manager.fileTransferSystem.onFileReceived, 'function');
|
||||
assert.equal(typeof manager.fileTransferSystem.onError, 'function');
|
||||
assert.equal(typeof manager.fileTransferSystem.onIncomingFileRequest, 'function');
|
||||
|
||||
console.log('File transfer UI cleanup tests passed');
|
||||
|
||||
Reference in New Issue
Block a user