File: //tmp/bm_upload_cancel_patch.cjs
const fs = require('fs');
function replaceExact(file, from, to) {
let s = fs.readFileSync(file, 'utf8');
if (!s.includes(from)) throw new Error(`Missing expected text in ${file}: ${from.slice(0,160)}`);
s = s.replace(from, to);
fs.writeFileSync(file, s, 'utf8');
}
replaceExact('web/src/modules/photos/UploadPage.jsx',
` const pendingPickerRef = useRef(null);
const seenPickerSurfacesRef = useRef(new Set());`,
` const pendingPickerRef = useRef(null);
const pickerCancelTimerRef = useRef(null);
const seenPickerSurfacesRef = useRef(new Set());`);
replaceExact('web/src/modules/photos/UploadPage.jsx',
` const pending = pendingPickerRef.current;
if (!pending) return false;
pendingPickerRef.current = null;
void trackEvent('upload_file_picker_cancel', {`,
` const pending = pendingPickerRef.current;
if (!pending) return false;
if (pickerCancelTimerRef.current) {
window.clearTimeout(pickerCancelTimerRef.current);
pickerCancelTimerRef.current = null;
}
pendingPickerRef.current = null;
void trackEvent('upload_file_picker_cancel', {`);
replaceExact('web/src/modules/photos/UploadPage.jsx',
` const actualSurface = file ? 'replace_photo' : surface;
pendingPickerRef.current = { surface: actualSurface, at: Date.now() };
void trackEvent('upload_file_picker_click', {`,
` const actualSurface = file ? 'replace_photo' : surface;
if (pickerCancelTimerRef.current) window.clearTimeout(pickerCancelTimerRef.current);
const pendingAt = Date.now();
pendingPickerRef.current = { surface: actualSurface, at: pendingAt };
pickerCancelTimerRef.current = window.setTimeout(() => {
const stillPending = pendingPickerRef.current;
const inputHasFile = Boolean(inputRef.current?.files?.length);
if (!stillPending || stillPending.at !== pendingAt || inputHasFile) return;
recordPickerCancel('timeout_no_selection');
}, 12000);
void trackEvent('upload_file_picker_click', {`);
replaceExact('web/src/modules/photos/UploadPage.jsx',
` if (!f) return;
pendingPickerRef.current = null;
const normalizedType = String(f.type || '').toLowerCase();`,
` if (!f) return;
if (pickerCancelTimerRef.current) {
window.clearTimeout(pickerCancelTimerRef.current);
pickerCancelTimerRef.current = null;
}
pendingPickerRef.current = null;
const normalizedType = String(f.type || '').toLowerCase();`);
replaceExact('web/src/modules/photos/UploadPage.jsx',
` window.removeEventListener('focus', recordFocusCancel);
document.removeEventListener('visibilitychange', recordVisibilityCancel);
input?.removeEventListener?.('cancel', recordNativeCancel);
};`,
` window.removeEventListener('focus', recordFocusCancel);
document.removeEventListener('visibilitychange', recordVisibilityCancel);
input?.removeEventListener?.('cancel', recordNativeCancel);
if (pickerCancelTimerRef.current) {
window.clearTimeout(pickerCancelTimerRef.current);
pickerCancelTimerRef.current = null;
}
};`);
for (const file of ['scripts/growth-smoke-check.mjs', 'scripts/growth-journey-smoke-check.mjs']) {
let s = fs.readFileSync(file, 'utf8');
if (!s.includes('timeout_no_selection')) {
s = s.replaceAll("'upload_file_picker_click'", "'upload_file_picker_click', 'upload_file_picker_cancel', 'pickerCancelTimerRef', 'timeout_no_selection'");
}
fs.writeFileSync(file, s, 'utf8');
}