codex-overleaf-link 2.3.6 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -34
- package/README.zh-CN.md +546 -0
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +3 -0
- package/extension/src/content/activeTurnControl.js +1 -0
- package/extension/src/content/assetTransferBroker.js +2 -0
- package/extension/src/content/contentRuntime.js +122 -118
- package/extension/src/content/contextTray.js +4 -0
- package/extension/src/content/diagnosticsController.js +4 -0
- package/extension/src/content/diagnosticsPanel.js +128 -4
- package/extension/src/content/generated/content.bundle.js +1233 -550
- package/extension/src/content/generated/content.bundle.meta.json +4 -3
- package/extension/src/content/legacyGlobalRegistry.js +1 -0
- package/extension/src/content/modelPicker.js +21 -9
- package/extension/src/content/modelPickerSupport.js +38 -1
- package/extension/src/content/nativeCompatibilityController.js +4 -1
- package/extension/src/content/otWarmMirror.js +34 -30
- package/extension/src/content/otWarmMirrorController.js +20 -0
- package/extension/src/content/pageBridgeClient.js +2 -0
- package/extension/src/content/panelMaintenance.js +8 -4
- package/extension/src/content/recentProjects.js +354 -355
- package/extension/src/content/runResultActions.js +16 -1
- package/extension/src/content/runTimelineView.js +9 -11
- package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
- package/extension/src/content/scopedPersistencePanelState.js +45 -2
- package/extension/src/content/sessionForkController.js +20 -11
- package/extension/src/content/sessionPersistence.js +4 -1
- package/extension/src/content/settingsPanel.js +16 -2
- package/extension/src/content/trackedChangeCaptureController.js +153 -0
- package/extension/src/content/writebackOrchestrator.js +31 -0
- package/extension/src/page/binaryAssetUploader.js +101 -29
- package/extension/src/page/overleafRealtimeObserver.js +4 -1
- package/extension/src/page/saveState.js +44 -1
- package/extension/src/page/textFileCreator.js +493 -0
- package/extension/src/page/trackedChangeCapture.js +342 -0
- package/extension/src/page/trackedChangesLifecycle.js +149 -150
- package/extension/src/page/treeOperations.js +40 -29
- package/extension/src/page/writebackRouter.js +95 -49
- package/extension/src/pageBridge.js +65 -25
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/i18n.js +94 -40
- package/extension/src/shared/pageRpcContract.js +2 -1
- package/extension/src/shared/sessionState.js +6 -2
- package/extension/src/shared/storageDb.js +11 -12
- package/extension/src/shared/storageRunActions.js +73 -1
- package/extension/src/shared/writebackSettlement.js +19 -5
- package/extension/styles/panel.css +254 -405
- package/native-host/src/codexSessionRunner.js +41 -38
- package/native-host/src/codexSessionTiming.js +68 -0
- package/native-host/src/readProgressGuard.js +84 -17
- package/native-host/src/taskRunnerRuntime.js +25 -0
- package/package.json +5 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"entry": "extension/entries/content-entry.mjs",
|
|
4
4
|
"output": "extension/src/content/generated/content.bundle.js",
|
|
5
|
-
"sourceDigest": "
|
|
6
|
-
"outputDigest": "
|
|
7
|
-
"byteLength":
|
|
5
|
+
"sourceDigest": "b19a018ab6eb9c7bdca8cfad8ff6efcc4a30e80f81c3c0a2e89a7f78b6361d97",
|
|
6
|
+
"outputDigest": "7640649ee012b3224d696703c2a1ab323d549418a3fcc31e2219bf14399416b5",
|
|
7
|
+
"byteLength": 2422231,
|
|
8
8
|
"inputs": [
|
|
9
9
|
"extension/entries/content-entry.mjs",
|
|
10
10
|
"extension/src/content/activeTurnControl.js",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"extension/src/content/sessionPersistence.js",
|
|
63
63
|
"extension/src/content/settingsPanel.js",
|
|
64
64
|
"extension/src/content/themeController.js",
|
|
65
|
+
"extension/src/content/trackedChangeCaptureController.js",
|
|
65
66
|
"extension/src/content/updateIdle.js",
|
|
66
67
|
"extension/src/content/updateNotice.js",
|
|
67
68
|
"extension/src/content/writebackController.js",
|
|
@@ -134,7 +134,8 @@
|
|
|
134
134
|
return { stale: false, error: response?.error || { code: 'provider_models_unavailable' } };
|
|
135
135
|
}
|
|
136
136
|
const sourceModels = hasDiscoveredModels ? response.result.models : fallbackModels;
|
|
137
|
-
const
|
|
137
|
+
const preserveBuiltin = (selection?.providerId || 'builtin') === 'builtin' && (getState()?.providerId || 'builtin') === 'builtin';
|
|
138
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, currentSelectedModel, { preserveUnavailable: preserveBuiltin });
|
|
138
139
|
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
139
140
|
if (normalized.usedFallback && response.result?.providerId && response.result.providerId !== 'builtin') {
|
|
140
141
|
applyUnavailableModelOptions({ code: 'provider_model_catalog_invalid', message: 'The active provider returned no usable models.' });
|
|
@@ -143,9 +144,12 @@
|
|
|
143
144
|
error: { code: 'provider_model_catalog_invalid', message: 'The active provider returned no usable models.' }
|
|
144
145
|
};
|
|
145
146
|
}
|
|
146
|
-
|
|
147
|
+
const renderedModels = preserveBuiltin
|
|
148
|
+
? Support.preserveSelectedCapabilities(normalized.models, retainedSelectedModel, getState(), !hasDiscoveredModels || response.result?.source === 'fallback')
|
|
149
|
+
: normalized.models;
|
|
150
|
+
renderModelOptions(renderedModels, retainedSelectedModel, { allowUnknownSelected: false });
|
|
147
151
|
modelDiscovery = {
|
|
148
|
-
status: hasDiscoveredModels && !normalized.usedFallback ? 'discovered' : 'fallback',
|
|
152
|
+
status: hasDiscoveredModels && !normalized.usedFallback && response.result?.source !== 'fallback' ? 'discovered' : 'fallback',
|
|
149
153
|
source: hasDiscoveredModels ? response.result?.source || 'unknown' : 'fallback',
|
|
150
154
|
fetchedAt: hasDiscoveredModels ? response.result?.fetchedAt || '' : '',
|
|
151
155
|
errorCode: hasDiscoveredModels ? '' : response?.error?.code || '',
|
|
@@ -172,15 +176,16 @@
|
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
function applyUnavailableModelOptions(error) {
|
|
179
|
+
const selectedModel = resolveSelectedModel();
|
|
175
180
|
const modelSelect = getPanel()?.querySelector('[data-model]');
|
|
176
181
|
if (modelSelect) {
|
|
177
182
|
modelSelect.textContent = '';
|
|
178
183
|
const option = document.createElement('option');
|
|
179
|
-
option.value =
|
|
184
|
+
option.value = selectedModel;
|
|
180
185
|
option.textContent = tx('Models unavailable', '模型不可用');
|
|
181
186
|
option.disabled = true;
|
|
182
187
|
modelSelect.append(option);
|
|
183
|
-
modelSelect.value =
|
|
188
|
+
modelSelect.value = selectedModel;
|
|
184
189
|
modelSelect.disabled = true;
|
|
185
190
|
}
|
|
186
191
|
modelDiscovery = {
|
|
@@ -190,8 +195,15 @@
|
|
|
190
195
|
errorCode: error?.code || '',
|
|
191
196
|
errorMessage: error?.message || (error ? String(error) : '')
|
|
192
197
|
};
|
|
193
|
-
|
|
194
|
-
|
|
198
|
+
const pendingModels = Support.preserveSelectedCapabilities(
|
|
199
|
+
[{ id: selectedModel, unverified: true }], selectedModel, getState(), true
|
|
200
|
+
);
|
|
201
|
+
renderReasoningOptions(pendingModels);
|
|
202
|
+
renderSpeedOptions(pendingModels);
|
|
203
|
+
for (const selector of ['[data-reasoning]', '[data-speed]']) {
|
|
204
|
+
const input = getPanel()?.querySelector(selector);
|
|
205
|
+
if (input) input.disabled = true;
|
|
206
|
+
}
|
|
195
207
|
renderModelConfigChoices();
|
|
196
208
|
updateModelDisplay();
|
|
197
209
|
}
|
|
@@ -200,9 +212,9 @@
|
|
|
200
212
|
const modelCatalog = getModelCatalog();
|
|
201
213
|
const fallbackModels = modelCatalog.FALLBACK_MODELS;
|
|
202
214
|
const sourceModels = fallbackModels;
|
|
203
|
-
const retainedSelectedModel = retainSelectedModel(sourceModels, selectedModel);
|
|
215
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, selectedModel, { preserveUnavailable: (getState()?.providerId || 'builtin') === 'builtin' });
|
|
204
216
|
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
205
|
-
renderModelOptions(normalized.models, retainedSelectedModel);
|
|
217
|
+
renderModelOptions(Support.preserveSelectedCapabilities(normalized.models, retainedSelectedModel, getState(), true), retainedSelectedModel);
|
|
206
218
|
modelDiscovery = {
|
|
207
219
|
status: 'fallback',
|
|
208
220
|
source: 'fallback',
|
|
@@ -29,14 +29,49 @@
|
|
|
29
29
|
return String(label || '').replace(/^gpt[-\s]*/i, '');
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function retainSelectedModel(models, selectedModel) {
|
|
32
|
+
function retainSelectedModel(models, selectedModel, options = {}) {
|
|
33
33
|
const selectedId = normalizeModelOptionId(selectedModel);
|
|
34
34
|
if (!selectedId) return '';
|
|
35
|
+
if (options.preserveUnavailable === true) return selectedId;
|
|
35
36
|
return (Array.isArray(models) ? models : []).some(model => (
|
|
36
37
|
normalizeModelOptionId(typeof model === 'string' ? model : model?.id) === selectedId
|
|
37
38
|
)) ? selectedId : '';
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
// A fallback or missing catalog entry cannot revoke an explicit selection.
|
|
42
|
+
// Keep its saved controls provisional until real capability data arrives.
|
|
43
|
+
function preserveSelectedCapabilities(models, selectedModel, preferences = {}, provisional = false) {
|
|
44
|
+
const selectedId = normalizeModelOptionId(selectedModel);
|
|
45
|
+
const saved = preferences || {};
|
|
46
|
+
return (Array.isArray(models) ? models : []).map(model => {
|
|
47
|
+
if (model.id !== selectedId || (!provisional && !model.unverified)) return model;
|
|
48
|
+
const reasoningEfforts = normalizeReasoningEffortsForSelect([
|
|
49
|
+
...(model.reasoningEfforts || []), saved.reasoningEffort
|
|
50
|
+
]);
|
|
51
|
+
const speedTiers = normalizeSpeedTiersForSelect(model.speedTiers);
|
|
52
|
+
const speed = ['standard', 'fast'].includes(saved.speedTier) ? saved.speedTier : '';
|
|
53
|
+
if (speed && !speedTiers.includes(speed)) speedTiers.push(speed);
|
|
54
|
+
return {
|
|
55
|
+
...model, unverified: true, reasoningEfforts, speedTiers,
|
|
56
|
+
defaultReasoningEffort: reasoningEfforts.includes(saved.reasoningEffort)
|
|
57
|
+
? saved.reasoningEffort : model.defaultReasoningEffort,
|
|
58
|
+
defaultSpeedTier: speed || model.defaultSpeedTier || 'standard'
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getRenderedModelEntries(panel) {
|
|
64
|
+
return Array.from(panel?.querySelector('[data-model]')?.options || []).map(option => ({
|
|
65
|
+
id: option.value,
|
|
66
|
+
label: option.textContent,
|
|
67
|
+
reasoningEfforts: (option.dataset.reasoningEfforts || '').split(',').filter(Boolean),
|
|
68
|
+
defaultReasoningEffort: option.dataset.defaultReasoningEffort || '',
|
|
69
|
+
reasoningPresentation: option.dataset.reasoningPresentation || '',
|
|
70
|
+
speedTiers: (option.dataset.speedTiers || 'standard').split(',').filter(Boolean),
|
|
71
|
+
defaultSpeedTier: option.dataset.defaultSpeedTier || 'standard'
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
40
75
|
function shouldUseBuiltInFallback(response) {
|
|
41
76
|
const providerId = normalizeModelOptionId(response?.result?.providerId);
|
|
42
77
|
return response?.ok === true && (!providerId || providerId === 'builtin');
|
|
@@ -114,6 +149,8 @@
|
|
|
114
149
|
normalizeReasoningEffortsForSelect,
|
|
115
150
|
normalizeSpeedTiersForSelect,
|
|
116
151
|
retainSelectedModel,
|
|
152
|
+
preserveSelectedCapabilities,
|
|
153
|
+
getRenderedModelEntries,
|
|
117
154
|
shouldUseBuiltInFallback
|
|
118
155
|
};
|
|
119
156
|
return api;
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
async function dispatch(payload, channelMethod) {
|
|
24
24
|
const compatibilityGate = await ensureForMethod(payload?.method);
|
|
25
25
|
if (!compatibilityGate.ok) return compatibilityGate.response;
|
|
26
|
-
|
|
26
|
+
// Post-Undo cache bookkeeping must survive the ended run's cancellation.
|
|
27
|
+
if (gatedMethods.has(payload?.method) && payload.method !== 'mirror.invalidate') {
|
|
28
|
+
options.throwIfCancellationRequested?.();
|
|
29
|
+
}
|
|
27
30
|
return nativeChannel[channelMethod](
|
|
28
31
|
attachEvidence(payload, compatibilityGate.compatibility)
|
|
29
32
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
(function initCodexOverleafOtWarmMirror() {
|
|
2
2
|
'use strict';
|
|
3
|
-
|
|
4
3
|
// Experimental OT warm-mirror glue carved out of contentRuntime.js (v1.4.9
|
|
5
4
|
// structural-debt phase 5): the per-project enable toggle flow, the
|
|
6
5
|
// poll/flush timers and patch queue, mirror prefetch, warm-start
|
|
@@ -52,6 +51,7 @@
|
|
|
52
51
|
let currentOtStatus = 'off';
|
|
53
52
|
let otTogglePending = false;
|
|
54
53
|
let otSyncRequestId = 0;
|
|
54
|
+
let otStartRetryCount = 0;
|
|
55
55
|
let otWarmMirrorProjectId = '';
|
|
56
56
|
let lastExperimentalOtProjectId = '';
|
|
57
57
|
let otWarmMirrorState = {
|
|
@@ -226,6 +226,7 @@
|
|
|
226
226
|
const projectId = getCurrentProjectId();
|
|
227
227
|
otWarmMirrorState.failureActive = false;
|
|
228
228
|
lastExperimentalOtProjectId = projectId;
|
|
229
|
+
otStartRetryCount = 0;
|
|
229
230
|
setExperimentalOtEnabledForProject(projectId, checkbox.checked);
|
|
230
231
|
updateExperimentalOtToggleControl(checkbox.checked);
|
|
231
232
|
// Per-card saved feedback, same contract as every other settings card.
|
|
@@ -306,8 +307,10 @@
|
|
|
306
307
|
await pauseOtWarmMirror(pauseAfterStart.reason || 'paused');
|
|
307
308
|
return response;
|
|
308
309
|
}
|
|
309
|
-
|
|
310
|
+
if (status === 'starting') recordOtFailure('missing_active_path', 'start');
|
|
311
|
+
else otWarmMirrorState.failureActive = false;
|
|
310
312
|
updateOtStatusDisplay(status);
|
|
313
|
+
otStartRetryCount = 0;
|
|
311
314
|
scheduleOtEventPolling(projectId, { immediate: true });
|
|
312
315
|
return response;
|
|
313
316
|
}
|
|
@@ -338,21 +341,36 @@
|
|
|
338
341
|
clearOtEventPolling({ clearPatchQueue: true });
|
|
339
342
|
recordOtFailure(readOtBridgeErrorCode(response, 'ot_start_failed'), 'start');
|
|
340
343
|
otWarmMirrorState.suspended = true;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
344
|
+
// Observer availability is transient; only an explicit user action may
|
|
345
|
+
// change the persisted opt-in. A cold editor/bridge must not turn OT off
|
|
346
|
+
// permanently. failureActive/suspended already prohibit cache reuse.
|
|
347
|
+
updateExperimentalOtToggleControl(isExperimentalOtEnabledForProject(projectId));
|
|
346
348
|
updateOtStatusDisplay('unavailable');
|
|
347
|
-
saveStateSoon();
|
|
348
349
|
try { await callPageBridge('stopOtObserver', { projectId }); } catch (_error) { /* preserve the original failure */ }
|
|
350
|
+
scheduleOtStartRetry(projectId, requestId);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function scheduleOtStartRetry(projectId, requestId) {
|
|
354
|
+
const retryDelays = [1000, 3000, 6000];
|
|
355
|
+
const canRetry = () => isCurrentOtSync(requestId, projectId) && getCurrentProjectId() === projectId
|
|
356
|
+
&& isExperimentalOtEnabledForProject(projectId) && !getCurrentRunView();
|
|
357
|
+
if (!canRetry() || otStartRetryCount >= retryDelays.length) return;
|
|
358
|
+
// Use the existing owned timer so disabling OT, changing projects and
|
|
359
|
+
// starting a new observation all cancel pending retries normally.
|
|
360
|
+
const delayMs = retryDelays[otStartRetryCount++];
|
|
361
|
+
otWarmMirrorState.pollTimer = window.setTimeout(() => {
|
|
362
|
+
otWarmMirrorState.pollTimer = null;
|
|
363
|
+
if (!canRetry()) return;
|
|
364
|
+
syncOtWarmMirrorController().catch(() => {
|
|
365
|
+
if (getCurrentProjectId() === projectId && isExperimentalOtEnabledForProject(projectId)) {
|
|
366
|
+
updateOtStatusDisplay('unavailable');
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}, delayMs);
|
|
349
370
|
}
|
|
350
371
|
|
|
351
372
|
function readOtBridgeStatus(response) {
|
|
352
|
-
|
|
353
|
-
return 'unavailable';
|
|
354
|
-
}
|
|
355
|
-
return response.state || response.status || response.result?.state || response.result?.status || 'unavailable';
|
|
373
|
+
return otWarmMirrorController.readOtBridgeStatus(response);
|
|
356
374
|
}
|
|
357
375
|
|
|
358
376
|
function ensureOtWarmMirrorStateProject(projectId) {
|
|
@@ -361,6 +379,7 @@
|
|
|
361
379
|
}
|
|
362
380
|
clearOtEventPolling({ clearPatchQueue: true });
|
|
363
381
|
otWarmMirrorState.projectId = projectId;
|
|
382
|
+
otStartRetryCount = 0;
|
|
364
383
|
otWarmMirrorState.lastPatchAt = 0;
|
|
365
384
|
otWarmMirrorState.lastErrorCode = '';
|
|
366
385
|
otWarmMirrorState.failureActive = false;
|
|
@@ -438,6 +457,7 @@
|
|
|
438
457
|
return statusResponse;
|
|
439
458
|
}
|
|
440
459
|
const status = readOtBridgeStatus(statusResponse);
|
|
460
|
+
if (status === 'observing' && otWarmMirrorState.lastFailure?.phase === 'start') Object.assign(otWarmMirrorState, { failureActive: false, lastErrorCode: '', lastFailure: null });
|
|
441
461
|
if (['unavailable', 'inconsistent'].includes(status)) recordOtFailure(readOtBridgeErrorCode(statusResponse, 'ot_observer_unavailable'), 'observe');
|
|
442
462
|
if (status) {
|
|
443
463
|
updateOtStatusDisplay(status);
|
|
@@ -470,27 +490,11 @@
|
|
|
470
490
|
}
|
|
471
491
|
|
|
472
492
|
function readOtBridgeEvents(response) {
|
|
473
|
-
|
|
474
|
-
return response;
|
|
475
|
-
}
|
|
476
|
-
if (Array.isArray(response?.events)) {
|
|
477
|
-
return response.events;
|
|
478
|
-
}
|
|
479
|
-
if (Array.isArray(response?.result?.events)) {
|
|
480
|
-
return response.result.events;
|
|
481
|
-
}
|
|
482
|
-
return [];
|
|
493
|
+
return otWarmMirrorController.readOtBridgeEvents(response);
|
|
483
494
|
}
|
|
484
|
-
|
|
485
495
|
function readOtBridgeErrorCode(response, fallback) {
|
|
486
|
-
|
|
487
|
-
|| response?.reason
|
|
488
|
-
|| response?.error?.code
|
|
489
|
-
|| response?.error
|
|
490
|
-
|| fallback;
|
|
491
|
-
return typeof value === 'string' ? value : fallback;
|
|
496
|
+
return otWarmMirrorController.readOtBridgeErrorCode(response, fallback);
|
|
492
497
|
}
|
|
493
|
-
|
|
494
498
|
function recordOtFailure(code, phase) {
|
|
495
499
|
code = otWarmMirrorController.normalizeFailureCode(code);
|
|
496
500
|
otWarmMirrorState.lastErrorCode = code;
|
|
@@ -174,6 +174,23 @@
|
|
|
174
174
|
return { ok: true };
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
function readOtBridgeStatus(response) {
|
|
178
|
+
if (!response || response.ok === false) return 'unavailable';
|
|
179
|
+
return response.state || response.status || response.result?.state || response.result?.status || 'unavailable';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function readOtBridgeEvents(response) {
|
|
183
|
+
if (Array.isArray(response)) return response;
|
|
184
|
+
if (Array.isArray(response?.events)) return response.events;
|
|
185
|
+
if (Array.isArray(response?.result?.events)) return response.result.events;
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function readOtBridgeErrorCode(response, fallback) {
|
|
190
|
+
const value = response?.lastErrorCode || response?.reason || response?.error?.code || response?.error || fallback;
|
|
191
|
+
return typeof value === 'string' ? value : fallback;
|
|
192
|
+
}
|
|
193
|
+
|
|
177
194
|
function normalizeFailureCode(value, fallback = 'ot_error') {
|
|
178
195
|
const code = typeof value === 'string' ? value : value?.code;
|
|
179
196
|
if (/^[a-z][a-z0-9_]{0,79}$/.test(code || '')) return code;
|
|
@@ -265,6 +282,9 @@
|
|
|
265
282
|
takePatchBatch,
|
|
266
283
|
validatePatchReceipt,
|
|
267
284
|
normalizeFailureCode,
|
|
285
|
+
readOtBridgeStatus,
|
|
286
|
+
readOtBridgeEvents,
|
|
287
|
+
readOtBridgeErrorCode,
|
|
268
288
|
getFailureMessageKey,
|
|
269
289
|
buildPatchFilesRequest,
|
|
270
290
|
canUseOtWarmStart,
|
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
['src/page/overleafProjectSnapshot.js', 'codex-overleaf-project-snapshot-script'],
|
|
22
22
|
['src/page/pageBridgeCapability.js', 'codex-overleaf-page-bridge-capability-script'],
|
|
23
23
|
['src/page/treeOperations.js', 'codex-overleaf-tree-operations-script', true],
|
|
24
|
+
['src/page/textFileCreator.js', 'codex-overleaf-text-file-creator-script', true],
|
|
24
25
|
['src/page/binaryAssetUploader.js', 'codex-overleaf-binary-asset-uploader-script', true],
|
|
25
26
|
['src/page/snapshotRouter.js', 'codex-overleaf-snapshot-router-script'],
|
|
26
27
|
['src/page/writeGuard.js', 'codex-overleaf-write-guard-script', true],
|
|
28
|
+
['src/page/trackedChangeCapture.js', 'codex-overleaf-tracked-change-capture-script', true],
|
|
27
29
|
['src/page/trackedChangesLifecycle.js', 'codex-overleaf-tracked-changes-lifecycle-script', true],
|
|
28
30
|
['src/page/writebackRouter.js', 'codex-overleaf-writeback-router-script', true],
|
|
29
31
|
['src/pageBridge.js', 'codex-overleaf-page-bridge-script', true]
|
|
@@ -137,15 +137,19 @@
|
|
|
137
137
|
}
|
|
138
138
|
const requestId = ++storageUsageRequestId;
|
|
139
139
|
const projectId = getCurrentProjectId?.();
|
|
140
|
+
const settingsScope = getPanel?.()?.dataset?.settingsScope;
|
|
140
141
|
const isCurrent = () => requestId === storageUsageRequestId && projectId === getCurrentProjectId?.()
|
|
142
|
+
&& settingsScope === getPanel?.()?.dataset?.settingsScope
|
|
141
143
|
&& getSettingsPanelInstance()?.container?.querySelector('[data-storage-usage]') === node;
|
|
142
144
|
const current = getState();
|
|
143
145
|
const sessionCount = Array.isArray(current?.sessions) ? current.sessions.length : 0;
|
|
144
146
|
const runCount = Array.isArray(current?.runs) ? current.runs.length : 0;
|
|
145
|
-
const counts =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
const counts = settingsScope === 'account'
|
|
148
|
+
? tx('All projects in this browser', '当前浏览器中的所有项目')
|
|
149
|
+
: tx(
|
|
150
|
+
`${sessionCount} loaded session(s) in this project · ${runCount} run(s) in the active session`,
|
|
151
|
+
`当前项目已加载 ${sessionCount} 个会话 · 当前会话 ${runCount} 轮运行`
|
|
152
|
+
);
|
|
149
153
|
// Dynamic text belongs to this renderer, not the loading-label translator.
|
|
150
154
|
node.removeAttribute?.('data-i18n');
|
|
151
155
|
node.textContent = counts;
|