codex-overleaf-link 2.5.1 → 2.6.5
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 +149 -398
- package/README.zh-CN.md +153 -404
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +148 -3
- package/extension/src/backgroundSharedSessions.js +55 -2
- package/extension/src/backgroundUpdateCoordinator.js +128 -12
- package/extension/src/content/activeTurnControl.js +164 -7
- package/extension/src/content/composerAttachments.js +46 -10
- package/extension/src/content/composerPanel.js +92 -12
- package/extension/src/content/contentRuntime.js +1114 -321
- package/extension/src/content/contextTray.js +8 -2
- package/extension/src/content/contextUsageView.js +267 -0
- package/extension/src/content/diagnosticsController.js +77 -34
- package/extension/src/content/diagnosticsExport.js +1 -1
- package/extension/src/content/diagnosticsPanel.js +147 -42
- package/extension/src/content/generated/content.bundle.js +5761 -1237
- package/extension/src/content/generated/content.bundle.meta.json +6 -3
- package/extension/src/content/legacyGlobalRegistry.js +4 -0
- package/extension/src/content/localSkillsPanel.js +6 -4
- package/extension/src/content/markdownDomRenderer.js +5 -3
- package/extension/src/content/markdownText.js +53 -14
- package/extension/src/content/modelPicker.js +29 -19
- package/extension/src/content/nativeCompatibilityController.js +52 -19
- package/extension/src/content/otWarmMirror.js +1 -1
- package/extension/src/content/pageBridgeClient.js +7 -7
- package/extension/src/content/panelMaintenance.js +10 -2
- package/extension/src/content/panelRenderer.js +55 -28
- package/extension/src/content/pendingInputView.js +1 -1
- package/extension/src/content/projectSettingsCoordinator.js +30 -6
- package/extension/src/content/providerSettingsDialog.js +28 -19
- package/extension/src/content/recentProjects.js +30 -19
- package/extension/src/content/runActivitySummary.js +122 -14
- package/extension/src/content/runCompletionMeta.js +194 -6
- package/extension/src/content/runController.js +2 -1
- package/extension/src/content/runFailureNotice.js +8 -1
- package/extension/src/content/runPresence.js +18 -8
- package/extension/src/content/runQueueScheduler.js +27 -13
- package/extension/src/content/runRecoveryActions.js +2 -1
- package/extension/src/content/runResultActions.js +73 -24
- package/extension/src/content/runReviewController.js +102 -37
- package/extension/src/content/runTimelineView.js +224 -25
- package/extension/src/content/scopedPersistencePanelState.js +124 -46
- package/extension/src/content/selectionContextView.js +30 -3
- package/extension/src/content/sensitivePreflight.js +14 -1
- package/extension/src/content/sessionManager.js +49 -3
- package/extension/src/content/sessionMenuView.js +54 -18
- package/extension/src/content/sessionPersistence.js +25 -5
- package/extension/src/content/settingsPanel.js +15 -2
- package/extension/src/content/settingsWorkbench.js +127 -89
- package/extension/src/content/sharedSessionViewSync.js +13 -4
- package/extension/src/content/subagentActivityView.js +23 -7
- package/extension/src/content/updateNotice.js +60 -6
- package/extension/src/content/writebackOrchestrator.js +301 -72
- package/extension/src/content/writingStyleSettings.js +70 -17
- package/extension/src/page/compileBridge.js +193 -180
- package/extension/src/page/overleafCapabilities.js +4 -1
- package/extension/src/page/overleafEditor.js +12 -3
- package/extension/src/page/overleafProjectSnapshot.js +56 -3
- package/extension/src/page/snapshotRouter.js +75 -66
- package/extension/src/page/textCoordinates.js +17 -1
- package/extension/src/page/textFileCreator.js +9 -1
- package/extension/src/page/treeOperations.js +200 -19
- package/extension/src/page/writebackRouter.js +172 -113
- package/extension/src/pageBridge.js +124 -73
- package/extension/src/popup.js +1 -1
- package/extension/src/shared/agentTranscript.js +372 -18
- package/extension/src/shared/auditRecords.js +3 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/compileAdapter.js +58 -17
- package/extension/src/shared/composerAttachmentDraft.js +27 -7
- package/extension/src/shared/contextUsage.js +125 -0
- package/extension/src/shared/failureReasons.js +57 -3
- package/extension/src/shared/i18n.js +315 -29
- package/extension/src/shared/lineReferences.js +38 -31
- package/extension/src/shared/pageRpcContract.js +1 -1
- package/extension/src/shared/panelIcons.js +39 -0
- package/extension/src/shared/projectFiles.js +2 -1
- package/extension/src/shared/reviewing.js +130 -1
- package/extension/src/shared/runActivityModel.js +70 -4
- package/extension/src/shared/runExecutionSnapshot.js +13 -0
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +34 -0
- package/extension/src/shared/sessionState.js +63 -4
- package/extension/src/shared/sessionTitle.js +14 -1
- package/extension/src/shared/sharedSessionBridge.js +81 -13
- package/extension/src/shared/staleGuard.js +130 -63
- package/extension/src/shared/storageDb.js +35 -3
- package/extension/src/shared/storageMigration.js +111 -2
- package/extension/src/shared/storageRunActions.js +62 -8
- package/extension/src/shared/undoOperations.js +126 -28
- package/extension/src/shared/updateRuntimeIdentity.js +16 -2
- package/extension/src/shared/writebackSettlement.js +21 -3
- package/extension/styles/panel.css +1293 -549
- package/native-host/src/bootstrapUpdate.js +52 -16
- package/native-host/src/chatBridgeRequest.js +60 -6
- package/native-host/src/chatBridgeResponse.js +10 -1
- package/native-host/src/chatCompletionsBridge.js +29 -2
- package/native-host/src/codexPromptAssembly.js +86 -118
- package/native-host/src/codexSessionRunner.js +127 -17
- package/native-host/src/debugLog.js +27 -3
- package/native-host/src/index.js +42 -11
- package/native-host/src/localSkills.js +1 -1
- package/native-host/src/mirrorWorkspace.js +47 -3
- package/native-host/src/nativeEnvironment.js +27 -5
- package/native-host/src/providerContextError.js +20 -0
- package/native-host/src/providerRuntime.js +1 -0
- package/native-host/src/skills/reviewer-response/SKILL.md +65 -0
- package/native-host/src/taskRunnerRuntime.js +28 -8
- package/native-host/src/textPatch.js +473 -377
- package/native-host/src/updateManager.js +144 -21
- package/native-host/src/writingStyleRuntime.js +1 -1
- package/package.json +5 -8
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
document,
|
|
59
59
|
getActiveFilePathFromEditorStore,
|
|
60
60
|
getActiveEditorIdentity,
|
|
61
|
+
getCodeMirrorEditorView,
|
|
62
|
+
getCodeMirrorEditorViews: () => codeMirrorEditorViewCandidates().map(([, view]) => view).filter(isCodeMirrorEditorView),
|
|
61
63
|
normalizePath: normalizeSafeProjectPath,
|
|
62
64
|
readActiveEditorText,
|
|
63
65
|
window
|
|
@@ -73,6 +75,7 @@
|
|
|
73
75
|
const textFileCreator = requirePageModule('CodexOverleafTextFileCreator').create({
|
|
74
76
|
window, document, treeOperations, snapshotRouter,
|
|
75
77
|
collectElements, ensureEditing, ensureReviewing, readActiveEditorText, readWriteCancellationSequence,
|
|
78
|
+
findUpgradeModal: () => window.CodexOverleafReviewing.findUpgradeModal(document),
|
|
76
79
|
uploadHelpers: requirePageModule('CodexOverleafBinaryAssetUploader')
|
|
77
80
|
});
|
|
78
81
|
binaryAssetUploader = requirePageModule('CodexOverleafBinaryAssetUploader').create({
|
|
@@ -96,6 +99,11 @@
|
|
|
96
99
|
projectSnapshotBridge = window.CodexOverleafProjectSnapshot.create({
|
|
97
100
|
buildProjectFileList: snapshotRouter.buildProjectFileList,
|
|
98
101
|
buildProjectSnapshot: snapshotRouter.buildProjectSnapshot,
|
|
102
|
+
getSnapshotEditorCaptures: snapshotRouter.getSnapshotEditorCaptures,
|
|
103
|
+
captureEditorDocument: treeOperations.captureEditorDocument,
|
|
104
|
+
isCaptureCurrent: treeOperations.isCaptureCurrent,
|
|
105
|
+
getActiveFilePath,
|
|
106
|
+
getActiveEditorIdentity,
|
|
99
107
|
getProjectId,
|
|
100
108
|
normalizePath: normalizeSafeProjectPath,
|
|
101
109
|
window
|
|
@@ -399,6 +407,11 @@
|
|
|
399
407
|
fallbackUserMessage: 'Target file is active but the editor was not ready before timeout.',
|
|
400
408
|
fallbackNextAction: 'Wait for Overleaf to finish loading, then retry.'
|
|
401
409
|
},
|
|
410
|
+
reviewing_unavailable: {
|
|
411
|
+
stage: 'reviewing', severity: 'blocked', defaultRetryable: false,
|
|
412
|
+
fallbackUserMessage: "Track Changes is unavailable for this project. It depends on the project owner's Overleaf plan.",
|
|
413
|
+
fallbackNextAction: 'Turn off Track in the composer to write without tracked changes. Codex still records each change so you can undo it.'
|
|
414
|
+
},
|
|
402
415
|
reviewing_state_unknown: {
|
|
403
416
|
stage: 'reviewing', severity: 'blocked', defaultRetryable: true,
|
|
404
417
|
fallbackUserMessage: 'Codex could not determine whether Reviewing/Track Changes is enabled.',
|
|
@@ -488,6 +501,8 @@
|
|
|
488
501
|
findFileTreeManager,
|
|
489
502
|
findHistoryObject,
|
|
490
503
|
findReviewingActivationControl,
|
|
504
|
+
findUpgradeModal: () => window.CodexOverleafReviewing.findUpgradeModal(document),
|
|
505
|
+
reviewingConfirmed: isReviewingConfirmedForWrite(getReviewingState()),
|
|
491
506
|
getCodeMirrorEditorView,
|
|
492
507
|
getDeepActiveElement,
|
|
493
508
|
isInsideCodexPanel,
|
|
@@ -497,7 +512,7 @@
|
|
|
497
512
|
|
|
498
513
|
async function ensureReviewing(params = {}) {
|
|
499
514
|
const initial = getReviewingState(params);
|
|
500
|
-
if (isReviewingConfirmedForWrite(initial)) {
|
|
515
|
+
if (isReviewingConfirmedForWrite(initial) && !window.CodexOverleafReviewing.findUpgradeModal(document)) {
|
|
501
516
|
return {
|
|
502
517
|
ok: true,
|
|
503
518
|
activated: false,
|
|
@@ -506,6 +521,7 @@
|
|
|
506
521
|
}
|
|
507
522
|
|
|
508
523
|
const switched = await toggleReviewingMode(true, params);
|
|
524
|
+
if (switched.code === 'reviewing_unavailable') return { ...switched, reason: switched.failure.userMessage };
|
|
509
525
|
if (switched.ok) {
|
|
510
526
|
return {
|
|
511
527
|
ok: true,
|
|
@@ -553,6 +569,7 @@
|
|
|
553
569
|
}
|
|
554
570
|
|
|
555
571
|
const switched = await toggleReviewingMode(false, params);
|
|
572
|
+
if (switched.code === 'reviewing_unavailable') return { ...switched, reason: switched.failure.userMessage };
|
|
556
573
|
if (switched.ok) {
|
|
557
574
|
return {
|
|
558
575
|
ok: true,
|
|
@@ -743,9 +760,16 @@
|
|
|
743
760
|
const activeFileMatches = getActiveFilePath() === filePath;
|
|
744
761
|
const text = readActiveEditorText();
|
|
745
762
|
lastText = text;
|
|
763
|
+
const currentEditorIdentity = getActiveEditorIdentity();
|
|
764
|
+
// A file-tree click can reconfigure or blur the old editor before the
|
|
765
|
+
// target document loads. A new view/state alone does not prove a switch.
|
|
766
|
+
const documentChanged = currentEditorIdentity?.type === 'codemirror-view'
|
|
767
|
+
&& previousEditorIdentity?.type === 'codemirror-view'
|
|
768
|
+
? currentEditorIdentity.doc !== previousEditorIdentity.doc
|
|
769
|
+
: Boolean(currentEditorIdentity) && activeEditorIdentityChanged(previousEditorIdentity);
|
|
746
770
|
if (activeFileMatches
|
|
747
771
|
&& window.CodexOverleafProjectFiles.isUsableProjectFileContent(text)
|
|
748
|
-
&&
|
|
772
|
+
&& documentChanged) {
|
|
749
773
|
return {
|
|
750
774
|
ok: true,
|
|
751
775
|
text
|
|
@@ -871,6 +895,7 @@
|
|
|
871
895
|
}
|
|
872
896
|
|
|
873
897
|
const switched = await toggleReviewingMode(enabled, params);
|
|
898
|
+
if (switched.code === 'reviewing_unavailable') return { ...switched, reason: switched.failure.userMessage };
|
|
874
899
|
if (switched.ok) {
|
|
875
900
|
return {
|
|
876
901
|
ok: true,
|
|
@@ -917,67 +942,23 @@
|
|
|
917
942
|
}
|
|
918
943
|
|
|
919
944
|
async function toggleReviewingMode(enabled, params = {}) {
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
for (const control of attemptedNodes) {
|
|
926
|
-
clickNode(control);
|
|
927
|
-
let after = await waitForReviewingEnabled(enabled, {
|
|
928
|
-
...params,
|
|
929
|
-
waitMs: Math.min(resolveWaitMs(params), 180)
|
|
930
|
-
});
|
|
931
|
-
if (isReviewingTargetStateConfirmed(enabled, after)) {
|
|
932
|
-
return {
|
|
933
|
-
ok: true,
|
|
934
|
-
attempted: true,
|
|
935
|
-
reviewing: after.reviewing
|
|
936
|
-
};
|
|
945
|
+
const sequence = readWriteCancellationSequence();
|
|
946
|
+
const assertCurrent = () => {
|
|
947
|
+
if (sequence !== readWriteCancellationSequence()) {
|
|
948
|
+
throw Object.assign(new Error('Writeback was cancelled.'), { code: 'codex_cancelled' });
|
|
937
949
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
if (modeOption) {
|
|
941
|
-
clickNode(modeOption);
|
|
942
|
-
after = await waitForReviewingEnabled(enabled, params);
|
|
943
|
-
if (isReviewingTargetStateConfirmed(enabled, after)) {
|
|
944
|
-
return {
|
|
945
|
-
ok: true,
|
|
946
|
-
attempted: true,
|
|
947
|
-
reviewing: after.reviewing
|
|
948
|
-
};
|
|
949
|
-
}
|
|
950
|
+
if (params.runProjectId && writeGuard.getEditorProjectIdPageSide(params.runProjectId) !== params.runProjectId) {
|
|
951
|
+
throw Object.assign(new Error('The active project changed.'), { code: 'aborted_project_changed' });
|
|
950
952
|
}
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
const visibleModeOption = findReviewingModeOption(enabled, { requireMenuOption: true });
|
|
954
|
-
if (visibleModeOption) {
|
|
955
|
-
clickNode(visibleModeOption);
|
|
956
|
-
const after = await waitForReviewingEnabled(enabled, params);
|
|
957
|
-
return {
|
|
958
|
-
ok: isReviewingTargetStateConfirmed(enabled, after),
|
|
959
|
-
attempted: true,
|
|
960
|
-
reviewing: after.reviewing
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
const after = getReviewingState(params);
|
|
965
|
-
return {
|
|
966
|
-
ok: false,
|
|
967
|
-
attempted: attemptedNodes.length > 0,
|
|
968
|
-
reviewing: after.reviewing
|
|
969
953
|
};
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
current = getReviewingState(params);
|
|
979
|
-
}
|
|
980
|
-
return current;
|
|
954
|
+
return window.CodexOverleafReviewing.toggleMode(enabled, params, {
|
|
955
|
+
document, assertCurrent, delay,
|
|
956
|
+
getState: () => getReviewingState(params), isConfirmed: isReviewingTargetStateConfirmed,
|
|
957
|
+
click: clickNode,
|
|
958
|
+
findControls: () => findReviewingModeControls(enabled),
|
|
959
|
+
findOption: value => findReviewingModeOption(value, { requireMenuOption: true }),
|
|
960
|
+
buildFailure: buildPageBridgeFailure
|
|
961
|
+
});
|
|
981
962
|
}
|
|
982
963
|
|
|
983
964
|
function resolveWaitMs(params = {}) {
|
|
@@ -1109,7 +1090,72 @@
|
|
|
1109
1090
|
return String(value || '').replace(/\s+/g, ' ').trim();
|
|
1110
1091
|
}
|
|
1111
1092
|
|
|
1093
|
+
function isReviewingModeNodeAvailable(node) {
|
|
1094
|
+
if (!node || node.ownerDocument !== document || !node.isConnected || node.disabled
|
|
1095
|
+
|| node.getAttribute?.('aria-disabled') === 'true' || !node.getClientRects?.().length) return false;
|
|
1096
|
+
for (let ancestor = node; ancestor; ancestor = ancestor.parentElement || ancestor.getRootNode?.().host) {
|
|
1097
|
+
if (isInsideCodexPanel(ancestor) || ancestor.closest?.(
|
|
1098
|
+
'.review-panel, .review-panel-container, .review-panel-header-slot, .review-sidebar, #review-panel, [data-testid="review-panel"]'
|
|
1099
|
+
) || ancestor.hidden || ancestor.getAttribute?.('aria-hidden') === 'true' || ancestor.hasAttribute?.('inert')) return false;
|
|
1100
|
+
const style = window.getComputedStyle?.(ancestor);
|
|
1101
|
+
if (style?.display === 'none' || style?.visibility === 'hidden' || style?.visibility === 'collapse'
|
|
1102
|
+
|| style?.opacity === '0') return false;
|
|
1103
|
+
}
|
|
1104
|
+
return true;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
function findReviewingToolbarControl() {
|
|
1108
|
+
return Array.from(document.querySelectorAll(
|
|
1109
|
+
'.toolbar-editor .review-mode-switcher > .review-mode-switcher-toggle-button'
|
|
1110
|
+
)).find(isReviewingModeNodeAvailable) || null;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
function findReviewingModeControls(enabled) {
|
|
1114
|
+
const toolbarControl = findReviewingToolbarControl();
|
|
1115
|
+
return toolbarControl ? [toolbarControl]
|
|
1116
|
+
: [findReviewingActivationControl(enabled), findReviewingModeMenuControl()];
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
function findReviewingToolbarMenu(control) {
|
|
1120
|
+
const controlledIds = (control.getAttribute('aria-controls') || '').split(/\s+/).filter(Boolean);
|
|
1121
|
+
for (const id of controlledIds) {
|
|
1122
|
+
const menu = document.getElementById(id);
|
|
1123
|
+
if (isReviewingModeNodeAvailable(menu)) return menu;
|
|
1124
|
+
}
|
|
1125
|
+
if (control.getAttribute('aria-expanded') !== 'true') return null;
|
|
1126
|
+
const selector = '[role="menu"], [role="listbox"], .dropdown-menu';
|
|
1127
|
+
// Current Overleaf keeps the menu beside the toggle, inside this switcher.
|
|
1128
|
+
const localMenu = Array.from(control.parentElement?.querySelectorAll(selector) || [])
|
|
1129
|
+
.find(node => node.closest('.review-mode-switcher') === control.parentElement && isReviewingModeNodeAvailable(node));
|
|
1130
|
+
if (localMenu) return localMenu;
|
|
1131
|
+
// A portalled menu must still name this switch, rather than an unrelated dropdown.
|
|
1132
|
+
return control.id ? Array.from(document.querySelectorAll(selector)).find(node =>
|
|
1133
|
+
(node.getAttribute('aria-labelledby') || '').split(/\s+/).includes(control.id)
|
|
1134
|
+
&& isReviewingModeNodeAvailable(node)) || null : null;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
function isReviewingToolbarModeOption(node, enabled) {
|
|
1138
|
+
const mode = enabled ? 'reviewing' : 'editing';
|
|
1139
|
+
const values = [node.value, node.getAttribute('value'), node.getAttribute('data-value'),
|
|
1140
|
+
node.getAttribute('label'), node.getAttribute('aria-label'), ...String(node.className || '').split(/\s+/)];
|
|
1141
|
+
if (values.some(value => normalizeReviewingSignalText(value).toLowerCase() === mode)) return true;
|
|
1142
|
+
// Read a label separately from icon text and the option's explanatory subtitle.
|
|
1143
|
+
return [node, ...node.querySelectorAll('*')].some(label => {
|
|
1144
|
+
if (label.closest('[aria-hidden="true"]')) return false;
|
|
1145
|
+
const directText = Array.from(label.childNodes).filter(child => child.nodeType === 3)
|
|
1146
|
+
.map(child => child.textContent).join(' ');
|
|
1147
|
+
return [label.textContent, directText].some(value => normalizeReviewingSignalText(value).toLowerCase() === mode);
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1112
1151
|
function findReviewingModeOption(enabled, options = {}) {
|
|
1152
|
+
const toolbarControl = findReviewingToolbarControl();
|
|
1153
|
+
if (toolbarControl) {
|
|
1154
|
+
const menu = findReviewingToolbarMenu(toolbarControl);
|
|
1155
|
+
return Array.from(menu?.querySelectorAll(
|
|
1156
|
+
'[role="menuitem"], [role="menuitemradio"], [role="option"], .dropdown-item, button, a, option'
|
|
1157
|
+
) || []).find(node => isReviewingModeNodeAvailable(node) && isReviewingToolbarModeOption(node, enabled)) || null;
|
|
1158
|
+
}
|
|
1113
1159
|
const candidates = collectReviewingModeOptionNodes()
|
|
1114
1160
|
.filter(node => isReviewingModeOptionCandidate(node, enabled, options))
|
|
1115
1161
|
.sort((left, right) => scoreReviewingModeOption(right, enabled) - scoreReviewingModeOption(left, enabled));
|
|
@@ -1145,7 +1191,7 @@
|
|
|
1145
1191
|
}
|
|
1146
1192
|
|
|
1147
1193
|
function isReviewingModeMenuControlCandidate(node) {
|
|
1148
|
-
if (!node || node
|
|
1194
|
+
if (!isReviewingModeNodeAvailable(node) || isMenuLikeModeOption(node)) {
|
|
1149
1195
|
return false;
|
|
1150
1196
|
}
|
|
1151
1197
|
const text = readNodeSignalText(node);
|
|
@@ -1198,7 +1244,7 @@
|
|
|
1198
1244
|
}
|
|
1199
1245
|
|
|
1200
1246
|
function isReviewingModeOptionCandidate(node, enabled, options = {}) {
|
|
1201
|
-
if (!node
|
|
1247
|
+
if (!isReviewingModeNodeAvailable(node)) {
|
|
1202
1248
|
return false;
|
|
1203
1249
|
}
|
|
1204
1250
|
if (options.requireMenuOption && !isMenuLikeModeOption(node)) {
|
|
@@ -1244,10 +1290,10 @@
|
|
|
1244
1290
|
&& !/\bsyntax highlighting\b/i.test(text);
|
|
1245
1291
|
}
|
|
1246
1292
|
|
|
1247
|
-
function findReviewingActivationControl() {
|
|
1293
|
+
function findReviewingActivationControl(enabled = true) {
|
|
1248
1294
|
const nodes = collectReviewingControlNodes();
|
|
1249
1295
|
const candidates = nodes
|
|
1250
|
-
.filter(node => isReviewingActivationCandidate(node))
|
|
1296
|
+
.filter(node => isReviewingActivationCandidate(node, enabled))
|
|
1251
1297
|
.sort((left, right) => scoreReviewingControl(right) - scoreReviewingControl(left));
|
|
1252
1298
|
return candidates[0] || null;
|
|
1253
1299
|
}
|
|
@@ -1271,10 +1317,12 @@
|
|
|
1271
1317
|
]).slice(0, 1500);
|
|
1272
1318
|
}
|
|
1273
1319
|
|
|
1274
|
-
function isReviewingActivationCandidate(node) {
|
|
1275
|
-
if (!node || node
|
|
1320
|
+
function isReviewingActivationCandidate(node, enabled) {
|
|
1321
|
+
if (!isReviewingModeNodeAvailable(node) || isMenuLikeModeOption(node)) {
|
|
1276
1322
|
return false;
|
|
1277
1323
|
}
|
|
1324
|
+
// A standalone Reviewing command enables tracking; it cannot open Editing.
|
|
1325
|
+
if (!enabled && !node.getAttribute?.('aria-haspopup') && !node.hasAttribute?.('aria-expanded')) return false;
|
|
1278
1326
|
const text = readNodeSignalText(node);
|
|
1279
1327
|
return /\breviewing\b|\btrack(?:ed)? changes?\b|\bsuggest(?:ing|ions?)\b/i.test(text)
|
|
1280
1328
|
&& !/\breview panel\b/i.test(text);
|
|
@@ -1634,21 +1682,21 @@
|
|
|
1634
1682
|
return editorAdapter.readActiveEditorText();
|
|
1635
1683
|
}
|
|
1636
1684
|
|
|
1637
|
-
function replaceActiveEditorText(text) {
|
|
1638
|
-
return editorAdapter.replaceActiveEditorText(text);
|
|
1685
|
+
function replaceActiveEditorText(text, options) {
|
|
1686
|
+
return editorAdapter.replaceActiveEditorText(text, options);
|
|
1639
1687
|
}
|
|
1640
1688
|
|
|
1641
|
-
function replaceActiveEditorPatches(patches, nextContent) {
|
|
1642
|
-
return editorAdapter.replaceActiveEditorPatches(patches, nextContent);
|
|
1689
|
+
function replaceActiveEditorPatches(patches, nextContent, options) {
|
|
1690
|
+
return editorAdapter.replaceActiveEditorPatches(patches, nextContent, options);
|
|
1643
1691
|
}
|
|
1644
1692
|
|
|
1645
1693
|
function getCodeMirrorEditorView() {
|
|
1646
1694
|
return findCodeMirrorEditorView()?.view || null;
|
|
1647
1695
|
}
|
|
1648
1696
|
|
|
1649
|
-
function
|
|
1697
|
+
function codeMirrorEditorViewCandidates() {
|
|
1650
1698
|
const store = getOverleafUnstableStore();
|
|
1651
|
-
|
|
1699
|
+
return [
|
|
1652
1700
|
['store:editor.view', readStoreValue(store, 'editor.view')],
|
|
1653
1701
|
['store:editor.view.camel', readStoreValue(store, 'editor.view.camel')],
|
|
1654
1702
|
['store:editor', readStoreValue(store, 'editor').view],
|
|
@@ -1657,7 +1705,10 @@
|
|
|
1657
1705
|
['window._ide.editorView', window._ide?.editorView]
|
|
1658
1706
|
];
|
|
1659
1707
|
|
|
1660
|
-
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
function findCodeMirrorEditorView() {
|
|
1711
|
+
for (const [source, candidate] of codeMirrorEditorViewCandidates()) {
|
|
1661
1712
|
if (isCodeMirrorEditorView(candidate)) {
|
|
1662
1713
|
return {
|
|
1663
1714
|
view: candidate,
|
package/extension/src/popup.js
CHANGED
|
@@ -708,7 +708,7 @@ async function sendConsentAction(action) {
|
|
|
708
708
|
const code = String(state.code || '');
|
|
709
709
|
if (code === 'update_recovery_pending') return utx('The update result is being checked. Recovery has not been confirmed.', '正在确认更新结果,恢复状态尚未确认。');
|
|
710
710
|
if (['update_bootstrap_health_timeout', 'update_bootstrap_reload_failed'].includes(code)) return utx('The updated startup components did not finish restarting and confirming. Check recovery before retrying.', '更新后的启动组件未能完成重启和确认,请先检查恢复状态。');
|
|
711
|
-
if (['update_bootstrap_source_mismatch', 'update_bootstrap_source_version_mismatch'].includes(code)) return utx('The installed startup files do not match a supported update source.
|
|
711
|
+
if (['update_bootstrap_source_mismatch', 'update_bootstrap_source_version_mismatch'].includes(code)) return utx('The installed startup files do not match a supported update source. Restore the previous version in Settings, or reinstall once.', '已安装的启动文件与支持的升级来源不一致。请在设置中恢复到上一版本,或重新安装一次。');
|
|
712
712
|
if (['update_bootstrap_record_missing', 'update_bootstrap_record_invalid', 'update_bootstrap_backup_mismatch', 'update_bootstrap_already_restoring'].includes(code)) return utx('The startup recovery material could not be confirmed. The update result remains unconfirmed.', '尚未确认启动组件的恢复材料有效,更新结果仍待确认。');
|
|
713
713
|
if (['update_bootstrap_confirmation_pending', 'update_bootstrap_native_restart_required'].includes(code)) return utx('Waiting for the updated startup components and Native Host to finish restarting and confirming.', '正在等待更新后的启动组件和本机服务完成重启及确认。');
|
|
714
714
|
if (code === 'update_bootstrap_monitor_unavailable') return utx('The update recovery monitor could not start. Check recovery before retrying.', '更新恢复监护程序未能启动,请先检查恢复状态。');
|