codex-overleaf-link 2.4.0 → 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 +27 -24
- package/README.zh-CN.md +27 -24
- package/extension/src/content/contentRuntime.js +74 -73
- package/extension/src/content/generated/content.bundle.js +657 -445
- package/extension/src/content/generated/content.bundle.meta.json +3 -3
- package/extension/src/content/panelMaintenance.js +8 -4
- package/extension/src/content/recentProjects.js +354 -355
- package/extension/src/content/runTimelineView.js +8 -10
- package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
- package/extension/src/content/scopedPersistencePanelState.js +45 -2
- package/extension/src/content/sessionPersistence.js +4 -1
- package/extension/src/content/settingsPanel.js +16 -2
- package/extension/src/page/saveState.js +44 -1
- package/extension/src/page/trackedChangesLifecycle.js +4 -1
- package/extension/src/page/treeOperations.js +10 -27
- package/extension/src/page/writebackRouter.js +1 -1
- package/extension/src/pageBridge.js +3 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/i18n.js +94 -40
- package/extension/src/shared/storageDb.js +1 -0
- package/extension/src/shared/storageRunActions.js +44 -0
- package/extension/styles/panel.css +199 -395
- 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/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
if (typeof document !== 'undefined' && document.documentElement) document.documentElement.setAttribute('data-codex-overleaf-source-digest', "
|
|
1
|
+
if (typeof document !== 'undefined' && document.documentElement) document.documentElement.setAttribute('data-codex-overleaf-source-digest', "b19a018ab6eb9c7bdca8cfad8ff6efcc4a30e80f81c3c0a2e89a7f78b6361d97");
|
|
2
2
|
(() => {
|
|
3
3
|
// extension/entries/content-entry.mjs
|
|
4
4
|
(function runClassicContentModule(module, exports, require2) {
|
|
@@ -4583,14 +4583,39 @@ ${block}`;
|
|
|
4583
4583
|
failureReason_editor_project_id_unavailable_next: "Refresh the Overleaf tab and retry; if it persists, reload the extension.",
|
|
4584
4584
|
// Welcome-panel + write-guard: Recent-projects
|
|
4585
4585
|
// variant copy. Spec §5.3–§5.5, §5.8, §5.10 are the source of truth.
|
|
4586
|
-
recentProjects_welcome: "
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4586
|
+
recentProjects_welcome: "Continue working",
|
|
4587
|
+
recentProjects_focusEyebrow: "Last conversation",
|
|
4588
|
+
recentProjects_historyHeading: "Other recent conversations",
|
|
4589
|
+
recentProjects_historyHint: "Select to continue",
|
|
4590
|
+
recentProjects_projectConversations: "View this project's conversations",
|
|
4591
|
+
recentProjects_allProjects: "All projects",
|
|
4592
|
+
recentProjects_showAllConversations: "View all {count} conversations",
|
|
4593
|
+
recentProjects_unstarted: "Not started \xB7 {count}",
|
|
4594
|
+
recentProjects_unstartedHint: "Empty conversations are kept here, without deleting their records.",
|
|
4595
|
+
recentProjects_noStarted: "No conversation has been started yet. Empty conversations are available below.",
|
|
4596
|
+
recentProjects_savedDraft: "Saved draft, ready to continue.",
|
|
4597
|
+
recentProjects_attention: "Needs attention",
|
|
4598
|
+
recentProjects_unavailableRecords: "Records with unavailable project links",
|
|
4599
|
+
recentProjects_loadingHistory: "Loading conversations...",
|
|
4600
|
+
recentProjects_loadFailed: "Conversation history could not be read. Please retry.",
|
|
4601
|
+
recentProjects_continueHint: "Open this conversation without automatically starting a task.",
|
|
4602
|
+
recentProjects_more: "More options",
|
|
4603
|
+
recentProjects_continue: "Continue",
|
|
4604
|
+
recentProjects_openProject: "Open project",
|
|
4605
|
+
recentProjects_loadingConversation: "Loading conversation...",
|
|
4606
|
+
recentProjects_noConversation: "No saved conversation",
|
|
4607
|
+
recentProjects_noRuns: "No runs yet",
|
|
4608
|
+
recentProjects_previewUnavailable: "Conversation unavailable",
|
|
4609
|
+
recentProjects_previewUnavailableHint: "Saved conversation could not be loaded.",
|
|
4610
|
+
recentProjects_conversationGone: "This conversation is no longer available. Choose another conversation from the refreshed list.",
|
|
4611
|
+
recentProjects_continueFailed: "Could not open the conversation. Please try again.",
|
|
4612
|
+
recentProjects_welcome_subtitle: "Conversations saved in this browser",
|
|
4613
|
+
recentProjects_empty: "No conversations saved in this browser yet. Open an Overleaf project and start a Codex conversation.",
|
|
4614
|
+
recentProjects_sessions_empty: "No saved conversations in this project",
|
|
4615
|
+
recentProjects_sessions_toggle: "Show or manage this project's conversations",
|
|
4616
|
+
recentProjects_sessions_action: "All conversations",
|
|
4617
|
+
recentProjects_sessions_action_open: "Hide conversations",
|
|
4618
|
+
recentProjects_clearProject: "Delete this project's conversations",
|
|
4594
4619
|
recentProjects_clearProject_title: "Delete all Codex sessions for {project}?",
|
|
4595
4620
|
recentProjects_clearProject_message: "This permanently deletes all {count} plugin sessions, run history, and matching plugin-local Codex thread history for {project}. It will not modify Overleaf files or global Codex history.",
|
|
4596
4621
|
recentProjects_clearProject_confirm: "Delete all",
|
|
@@ -4606,15 +4631,17 @@ ${block}`;
|
|
|
4606
4631
|
recentProjects_degraded: "Sign in to Overleaf to see your recent Codex projects.",
|
|
4607
4632
|
recentProjects_row_projectLinkUnavailable: "Project link unavailable.",
|
|
4608
4633
|
recentProjects_settings_entry: "Settings & Diagnostics",
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4634
|
+
recentProjects_settingsTitle: "General Settings",
|
|
4635
|
+
recentProjects_settingsSubtitle: "Manage Codex preferences and local history across all projects.",
|
|
4636
|
+
recentProjects_badge_pending: "Last run pending",
|
|
4637
|
+
recentProjects_badge_accepted: "Last changes accepted",
|
|
4638
|
+
recentProjects_badge_rejected: "Last changes undone",
|
|
4639
|
+
recentProjects_badge_needs_review: "Last run needs review",
|
|
4640
|
+
recentProjects_badge_running: "Last recorded as running",
|
|
4641
|
+
recentProjects_badge_completed: "Last run completed",
|
|
4642
|
+
recentProjects_badge_failed: "Last run failed",
|
|
4643
|
+
recentProjects_badge_interrupted: "Last run may have been interrupted",
|
|
4644
|
+
recentProjects_badge_stale: "Last run status unconfirmed",
|
|
4618
4645
|
recentProjects_unnamed: "Project \xB7 {prefix}",
|
|
4619
4646
|
recentProjects_zombieRunningNote: "Marked as running, but it may be a leftover from an interrupted run.",
|
|
4620
4647
|
recentProjects_zombieDeleteConfirm: "This session is marked as running. If no other tab is actually running it, you can delete it anyway.",
|
|
@@ -4622,9 +4649,9 @@ ${block}`;
|
|
|
4622
4649
|
recentProjects_degraded_hint: "Could not identify the Overleaf account on this page, so the project list is hidden to avoid mixing accounts. This usually resolves on a reload.",
|
|
4623
4650
|
recentProjects_sessionsCount: "{count} session(s)",
|
|
4624
4651
|
recentProjects_welcome_stats: "{projects} projects \xB7 {sessions} Codex sessions",
|
|
4625
|
-
recentProjects_badge_background_completed: "completed in background",
|
|
4626
|
-
recentProjects_badge_needs_review_after_navigation: "
|
|
4627
|
-
recentProjects_badge_abandoned_after_navigation: "
|
|
4652
|
+
recentProjects_badge_background_completed: "Last run completed in background",
|
|
4653
|
+
recentProjects_badge_needs_review_after_navigation: "Last run needs review",
|
|
4654
|
+
recentProjects_badge_abandoned_after_navigation: "Last run stopped after navigation"
|
|
4628
4655
|
},
|
|
4629
4656
|
zh: {
|
|
4630
4657
|
resizePanel: "\u62D6\u52A8\u8C03\u6574 Codex \u9762\u677F\u5BBD\u5EA6\uFF0C\u53CC\u51FB\u6062\u590D\u9ED8\u8BA4\u5BBD\u5EA6",
|
|
@@ -5122,14 +5149,39 @@ ${block}`;
|
|
|
5122
5149
|
failureReason_editor_project_id_unavailable_next: "\u8BF7\u5237\u65B0 Overleaf \u9875\u9762\u540E\u91CD\u8BD5\uFF1B\u5982\u679C\u4ECD\u7136\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55\u3002",
|
|
5123
5150
|
// Welcome-panel + write-guard: Recent-projects
|
|
5124
5151
|
// variant copy. 见 spec §5.3–§5.5、§5.8、§5.10。
|
|
5125
|
-
recentProjects_welcome: "
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5152
|
+
recentProjects_welcome: "\u7EE7\u7EED\u5DE5\u4F5C",
|
|
5153
|
+
recentProjects_focusEyebrow: "\u4E0A\u6B21\u5BF9\u8BDD",
|
|
5154
|
+
recentProjects_historyHeading: "\u5176\u4ED6\u6700\u8FD1\u5BF9\u8BDD",
|
|
5155
|
+
recentProjects_historyHint: "\u70B9\u51FB\u6761\u76EE\u7EE7\u7EED",
|
|
5156
|
+
recentProjects_projectConversations: "\u67E5\u770B\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u5BF9\u8BDD",
|
|
5157
|
+
recentProjects_allProjects: "\u6240\u6709\u9879\u76EE",
|
|
5158
|
+
recentProjects_showAllConversations: "\u67E5\u770B\u5168\u90E8 {count} \u6BB5\u5BF9\u8BDD",
|
|
5159
|
+
recentProjects_unstarted: "\u672A\u5F00\u59CB \xB7 {count}",
|
|
5160
|
+
recentProjects_unstartedHint: "\u7A7A\u767D\u5BF9\u8BDD\u6536\u7EB3\u5728\u8FD9\u91CC\uFF0C\u8BB0\u5F55\u4E0D\u4F1A\u88AB\u5220\u9664\u3002",
|
|
5161
|
+
recentProjects_noStarted: "\u5C1A\u65E0\u5DF2\u5F00\u59CB\u7684\u5BF9\u8BDD\uFF0C\u7A7A\u767D\u5BF9\u8BDD\u53EF\u5728\u4E0B\u65B9\u5C55\u5F00\u3002",
|
|
5162
|
+
recentProjects_savedDraft: "\u8349\u7A3F\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u7EE7\u7EED\u8865\u5145\u3002",
|
|
5163
|
+
recentProjects_attention: "\u9700\u8981\u67E5\u770B",
|
|
5164
|
+
recentProjects_unavailableRecords: "\u9879\u76EE\u94FE\u63A5\u4E0D\u53EF\u7528\u7684\u8BB0\u5F55",
|
|
5165
|
+
recentProjects_loadingHistory: "\u6B63\u5728\u52A0\u8F7D\u5BF9\u8BDD\u2026",
|
|
5166
|
+
recentProjects_loadFailed: "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u5BF9\u8BDD\u5386\u53F2\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
5167
|
+
recentProjects_continueHint: "\u4EC5\u6253\u5F00\u8FD9\u6BB5\u5BF9\u8BDD\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u542F\u52A8\u4EFB\u52A1\u3002",
|
|
5168
|
+
recentProjects_more: "\u66F4\u591A\u9009\u9879",
|
|
5169
|
+
recentProjects_continue: "\u7EE7\u7EED",
|
|
5170
|
+
recentProjects_openProject: "\u6253\u5F00\u9879\u76EE",
|
|
5171
|
+
recentProjects_loadingConversation: "\u6B63\u5728\u52A0\u8F7D\u5BF9\u8BDD\u2026",
|
|
5172
|
+
recentProjects_noConversation: "\u6682\u65E0\u4FDD\u5B58\u7684\u5BF9\u8BDD",
|
|
5173
|
+
recentProjects_noRuns: "\u5C1A\u672A\u8FD0\u884C\u4EFB\u52A1",
|
|
5174
|
+
recentProjects_previewUnavailable: "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u5BF9\u8BDD",
|
|
5175
|
+
recentProjects_previewUnavailableHint: "\u5DF2\u4FDD\u5B58\u7684\u5BF9\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002",
|
|
5176
|
+
recentProjects_conversationGone: "\u8BE5\u5BF9\u8BDD\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u4ECE\u66F4\u65B0\u540E\u7684\u5217\u8868\u4E2D\u9009\u62E9\u5176\u4ED6\u5BF9\u8BDD\u3002",
|
|
5177
|
+
recentProjects_continueFailed: "\u6682\u65F6\u65E0\u6CD5\u6253\u5F00\u5BF9\u8BDD\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
5178
|
+
recentProjects_welcome_subtitle: "\u5F53\u524D\u6D4F\u89C8\u5668\u4FDD\u5B58\u7684\u5BF9\u8BDD",
|
|
5179
|
+
recentProjects_empty: "\u5F53\u524D\u6D4F\u89C8\u5668\u8FD8\u6CA1\u6709\u4FDD\u5B58\u7684\u5BF9\u8BDD\u3002\u6253\u5F00\u4E00\u4E2A Overleaf \u9879\u76EE\uFF0C\u4E0E Codex \u5F00\u59CB\u5BF9\u8BDD\u5373\u53EF\u3002",
|
|
5180
|
+
recentProjects_sessions_empty: "\u8BE5\u9879\u76EE\u8FD8\u6CA1\u6709\u4FDD\u5B58\u7684\u5BF9\u8BDD",
|
|
5181
|
+
recentProjects_sessions_toggle: "\u67E5\u770B\u6216\u7BA1\u7406\u8BE5\u9879\u76EE\u7684\u5BF9\u8BDD",
|
|
5182
|
+
recentProjects_sessions_action: "\u5168\u90E8\u5BF9\u8BDD",
|
|
5183
|
+
recentProjects_sessions_action_open: "\u6536\u8D77\u5BF9\u8BDD",
|
|
5184
|
+
recentProjects_clearProject: "\u5220\u9664\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u5BF9\u8BDD",
|
|
5133
5185
|
recentProjects_clearProject_title: "\u5220\u9664 {project} \u7684\u5168\u90E8 Codex \u4F1A\u8BDD\uFF1F",
|
|
5134
5186
|
recentProjects_clearProject_message: "\u8FD9\u4F1A\u6C38\u4E45\u5220\u9664 {project} \u7684\u5168\u90E8 {count} \u4E2A\u63D2\u4EF6\u4F1A\u8BDD\u3001\u8FD0\u884C\u5386\u53F2\u53CA\u5BF9\u5E94\u7684\u63D2\u4EF6\u672C\u5730 Codex \u7EBF\u7A0B\u5386\u53F2\u3002\u4E0D\u4F1A\u4FEE\u6539 Overleaf \u6587\u4EF6\u6216\u5168\u5C40 Codex \u5386\u53F2\u3002",
|
|
5135
5187
|
recentProjects_clearProject_confirm: "\u5168\u90E8\u5220\u9664",
|
|
@@ -5145,15 +5197,17 @@ ${block}`;
|
|
|
5145
5197
|
recentProjects_degraded: "\u8BF7\u767B\u5F55 Overleaf \u540E\u67E5\u770B\u4F60\u6700\u8FD1\u7684 Codex \u9879\u76EE\u3002",
|
|
5146
5198
|
recentProjects_row_projectLinkUnavailable: "\u9879\u76EE\u94FE\u63A5\u4E0D\u53EF\u7528\u3002",
|
|
5147
5199
|
recentProjects_settings_entry: "\u8BBE\u7F6E\u4E0E\u8BCA\u65AD",
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5200
|
+
recentProjects_settingsTitle: "\u901A\u7528\u8BBE\u7F6E",
|
|
5201
|
+
recentProjects_settingsSubtitle: "\u7BA1\u7406\u9002\u7528\u4E8E\u6240\u6709\u9879\u76EE\u7684 Codex \u504F\u597D\u8BBE\u7F6E\u4E0E\u672C\u5730\u5386\u53F2\u8BB0\u5F55\u3002",
|
|
5202
|
+
recentProjects_badge_pending: "\u4E0A\u6B21\u8FD0\u884C\u5F85\u5904\u7406",
|
|
5203
|
+
recentProjects_badge_accepted: "\u4E0A\u6B21\u4FEE\u6539\u5DF2\u63A5\u53D7",
|
|
5204
|
+
recentProjects_badge_rejected: "\u4E0A\u6B21\u4FEE\u6539\u5DF2\u64A4\u56DE",
|
|
5205
|
+
recentProjects_badge_needs_review: "\u4E0A\u6B21\u8FD0\u884C\u9700\u8981\u68C0\u67E5",
|
|
5206
|
+
recentProjects_badge_running: "\u4E0A\u6B21\u8BB0\u5F55\u4E3A\u8FD0\u884C\u4E2D",
|
|
5207
|
+
recentProjects_badge_completed: "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u5B8C\u6210",
|
|
5208
|
+
recentProjects_badge_failed: "\u4E0A\u6B21\u8FD0\u884C\u5931\u8D25",
|
|
5209
|
+
recentProjects_badge_interrupted: "\u4E0A\u6B21\u8FD0\u884C\u53EF\u80FD\u5DF2\u4E2D\u65AD",
|
|
5210
|
+
recentProjects_badge_stale: "\u4E0A\u6B21\u8FD0\u884C\u72B6\u6001\u672A\u786E\u8BA4",
|
|
5157
5211
|
recentProjects_unnamed: "\u9879\u76EE \xB7 {prefix}",
|
|
5158
5212
|
recentProjects_zombieRunningNote: "\u6807\u8BB0\u4E3A\u8FD0\u884C\u4E2D\uFF0C\u4F46\u53EF\u80FD\u662F\u88AB\u4E2D\u65AD\u540E\u7684\u6B8B\u7559\u3002",
|
|
5159
5213
|
recentProjects_zombieDeleteConfirm: "\u8BE5\u4F1A\u8BDD\u6807\u8BB0\u4E3A\u8FD0\u884C\u4E2D\u3002\u5982\u679C\u786E\u8BA4\u6CA1\u6709\u5176\u4ED6\u6807\u7B7E\u9875\u5728\u8FD0\u884C\u5B83\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5220\u9664\u3002",
|
|
@@ -5161,9 +5215,9 @@ ${block}`;
|
|
|
5161
5215
|
recentProjects_degraded_hint: "\u65E0\u6CD5\u8BC6\u522B\u672C\u9875\u7684 Overleaf \u8D26\u53F7\uFF0C\u4E3A\u907F\u514D\u8D26\u53F7\u95F4\u4E32\u6570\u636E\u5DF2\u9690\u85CF\u9879\u76EE\u5217\u8868\u3002\u901A\u5E38\u5237\u65B0\u5373\u53EF\u6062\u590D\u3002",
|
|
5162
5216
|
recentProjects_sessionsCount: "{count} \u4E2A\u4F1A\u8BDD",
|
|
5163
5217
|
recentProjects_welcome_stats: "{projects} \u4E2A\u9879\u76EE \xB7 {sessions} \u4E2A Codex \u4F1A\u8BDD",
|
|
5164
|
-
recentProjects_badge_background_completed: "\u540E\u53F0\
|
|
5165
|
-
recentProjects_badge_needs_review_after_navigation: "\
|
|
5166
|
-
recentProjects_badge_abandoned_after_navigation: "\u5DF2\
|
|
5218
|
+
recentProjects_badge_background_completed: "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u5728\u540E\u53F0\u5B8C\u6210",
|
|
5219
|
+
recentProjects_badge_needs_review_after_navigation: "\u4E0A\u6B21\u8FD0\u884C\u9700\u8981\u68C0\u67E5",
|
|
5220
|
+
recentProjects_badge_abandoned_after_navigation: "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u5728\u79BB\u5F00\u9875\u9762\u540E\u505C\u6B62"
|
|
5167
5221
|
}
|
|
5168
5222
|
};
|
|
5169
5223
|
function normalizeLocale(value) {
|
|
@@ -9904,6 +9958,56 @@ ${block}`;
|
|
|
9904
9958
|
}
|
|
9905
9959
|
return out;
|
|
9906
9960
|
}
|
|
9961
|
+
function mergeSessionReviewState(incoming, existing, reviewRunIds) {
|
|
9962
|
+
if (!existing || incoming.id !== existing.id || incoming.projectId !== existing.projectId || !incoming.accountScopeId || incoming.accountScopeId !== existing.accountScopeId) return incoming;
|
|
9963
|
+
var terminal = (run) => ["accepted", "rejected"].includes(run?.trackedChangeStatus);
|
|
9964
|
+
var incomingRuns = new Map((incoming.runs || []).map((run) => [run.id, run]));
|
|
9965
|
+
var existingRuns = new Map((existing.runs || []).map((run) => [run.id, run]));
|
|
9966
|
+
var requestedIds = new Set(reviewRunIds || []);
|
|
9967
|
+
var explicitReview = Array.from(requestedIds).some((id) => ["accepted", "rejected", "needs_review"].includes(incomingRuns.get(id)?.trackedChangeStatus));
|
|
9968
|
+
var newer = (Date.parse(incoming.updatedAt) || 0) >= (Date.parse(existing.updatedAt) || 0);
|
|
9969
|
+
if (!newer && !explicitReview) return incoming;
|
|
9970
|
+
var base = newer ? incoming : existing;
|
|
9971
|
+
var fields = [
|
|
9972
|
+
"trackedChangeStatus",
|
|
9973
|
+
"undoStatus",
|
|
9974
|
+
"undoTrackedChanges",
|
|
9975
|
+
"undoExpectedFiles",
|
|
9976
|
+
"undoOperations",
|
|
9977
|
+
"undoBaseFiles",
|
|
9978
|
+
"appliedOperations",
|
|
9979
|
+
"trackedChangeCaptures",
|
|
9980
|
+
"settlement",
|
|
9981
|
+
"settlementFacts"
|
|
9982
|
+
];
|
|
9983
|
+
var changed = false;
|
|
9984
|
+
var runs = (base.runs || []).map(function(run) {
|
|
9985
|
+
var previous = existingRuns.get(run.id), candidate = incomingRuns.get(run.id);
|
|
9986
|
+
var source = terminal(previous) ? previous : explicitReview && requestedIds.has(run.id) ? candidate : null;
|
|
9987
|
+
if (!source || source === run) return run;
|
|
9988
|
+
if (source.runProjectId && source.runProjectId !== incoming.projectId) return run;
|
|
9989
|
+
var merged2 = { ...run };
|
|
9990
|
+
for (var field of fields) {
|
|
9991
|
+
if (Object.prototype.hasOwnProperty.call(source, field)) {
|
|
9992
|
+
merged2[field] = JSON.parse(JSON.stringify(source[field]));
|
|
9993
|
+
} else {
|
|
9994
|
+
delete merged2[field];
|
|
9995
|
+
}
|
|
9996
|
+
}
|
|
9997
|
+
changed = true;
|
|
9998
|
+
return merged2;
|
|
9999
|
+
});
|
|
10000
|
+
if (!changed) return base;
|
|
10001
|
+
var merged = { ...base, runs };
|
|
10002
|
+
if (explicitReview && !newer) {
|
|
10003
|
+
merged.updatedAt = new Date(Math.max(
|
|
10004
|
+
Date.now(),
|
|
10005
|
+
Date.parse(existing.updatedAt) || 0,
|
|
10006
|
+
Date.parse(incoming.updatedAt) || 0
|
|
10007
|
+
) + 1).toISOString();
|
|
10008
|
+
}
|
|
10009
|
+
return merged;
|
|
10010
|
+
}
|
|
9907
10011
|
function hashString(value) {
|
|
9908
10012
|
var hash = 2166136261;
|
|
9909
10013
|
var text = String(value || "");
|
|
@@ -9915,6 +10019,7 @@ ${block}`;
|
|
|
9915
10019
|
}
|
|
9916
10020
|
return {
|
|
9917
10021
|
compactStructuredEventValue,
|
|
10022
|
+
mergeSessionReviewState,
|
|
9918
10023
|
compactRunsForStorage,
|
|
9919
10024
|
compactRunActionPayload,
|
|
9920
10025
|
compactProviderSnapshot,
|
|
@@ -11203,6 +11308,7 @@ ${block}`;
|
|
|
11203
11308
|
clearStore,
|
|
11204
11309
|
clearAllStores,
|
|
11205
11310
|
buildSessionRecord,
|
|
11311
|
+
mergeSessionReviewState: StorageRunActions.mergeSessionReviewState,
|
|
11206
11312
|
buildTurnRecord,
|
|
11207
11313
|
buildEventRecord,
|
|
11208
11314
|
buildArtifactRecord,
|
|
@@ -11829,7 +11935,7 @@ ${block}`;
|
|
|
11829
11935
|
const MIN_NATIVE_VERSION = "1.0.0";
|
|
11830
11936
|
const MIN_COMPATIBLE_NATIVE_VERSION = "1.0.0";
|
|
11831
11937
|
const MIN_COMPATIBLE_EXTENSION_VERSION = "1.0.0";
|
|
11832
|
-
const BUILD_TARGET_VERSION = "2.4.
|
|
11938
|
+
const BUILD_TARGET_VERSION = "2.4.1";
|
|
11833
11939
|
const DEFAULT_CHROME_EXTENSION_ID = "illdpneeeopfffmiepaejglgmhpmdhdc";
|
|
11834
11940
|
const REQUIRED_CAPABILITIES = Object.freeze([
|
|
11835
11941
|
"bridgePing",
|
|
@@ -18059,8 +18165,8 @@ ${block}`;
|
|
|
18059
18165
|
<div class="codex-custom-instructions-head">
|
|
18060
18166
|
<button type="button" data-settings-back title="Back" aria-label="Back">\u2039</button>
|
|
18061
18167
|
<div>
|
|
18062
|
-
<div class="codex-custom-instructions-title" data-i18n="projectSettingsTitle">Project Settings</div>
|
|
18063
|
-
<div class="codex-custom-instructions-subtitle" data-i18n="projectSettingsSubtitle">Customize how Codex behaves in this and all projects.</div>
|
|
18168
|
+
<div class="codex-custom-instructions-title" data-settings-title data-i18n="projectSettingsTitle">Project Settings</div>
|
|
18169
|
+
<div class="codex-custom-instructions-subtitle" data-settings-subtitle data-i18n="projectSettingsSubtitle">Customize how Codex behaves in this and all projects.</div>
|
|
18064
18170
|
</div>
|
|
18065
18171
|
</div>
|
|
18066
18172
|
<div class="codex-project-settings-status" data-project-settings-status></div>
|
|
@@ -18318,6 +18424,7 @@ ${block}`;
|
|
|
18318
18424
|
if (!root) {
|
|
18319
18425
|
return;
|
|
18320
18426
|
}
|
|
18427
|
+
refreshSettingsScope(instance, root);
|
|
18321
18428
|
const button = getButton(instance);
|
|
18322
18429
|
if (button) {
|
|
18323
18430
|
button.dataset.active = "true";
|
|
@@ -18325,6 +18432,17 @@ ${block}`;
|
|
|
18325
18432
|
}
|
|
18326
18433
|
root.querySelector("[data-custom-instructions-input]")?.focus?.();
|
|
18327
18434
|
}
|
|
18435
|
+
function refreshSettingsScope(instance, root) {
|
|
18436
|
+
const accountScope = instance.container?.closest?.("[data-settings-scope]")?.dataset?.settingsScope === "account";
|
|
18437
|
+
const prefix = accountScope ? "recentProjects_settings" : "projectSettings";
|
|
18438
|
+
for (const [selector, suffix] of [["[data-settings-title]", "Title"], ["[data-settings-subtitle]", "Subtitle"]]) {
|
|
18439
|
+
const label = root.querySelector(selector);
|
|
18440
|
+
if (!label) continue;
|
|
18441
|
+
const key = prefix + suffix;
|
|
18442
|
+
label.setAttribute("data-i18n", key);
|
|
18443
|
+
label.textContent = t(instance, key);
|
|
18444
|
+
}
|
|
18445
|
+
}
|
|
18328
18446
|
function hide(target) {
|
|
18329
18447
|
const instance = target?._instance || target;
|
|
18330
18448
|
const root = getRoot(instance);
|
|
@@ -18352,6 +18470,7 @@ ${block}`;
|
|
|
18352
18470
|
if (!root) {
|
|
18353
18471
|
return;
|
|
18354
18472
|
}
|
|
18473
|
+
refreshSettingsScope(instance, root);
|
|
18355
18474
|
if (Object.prototype.hasOwnProperty.call(state, "customInstructions")) {
|
|
18356
18475
|
const input = root.querySelector("[data-custom-instructions-input]");
|
|
18357
18476
|
if (input) {
|
|
@@ -20215,7 +20334,12 @@ ${block}`;
|
|
|
20215
20334
|
await Promise.all(deletedExisting.map((record) => StorageDb.deleteRecord("sessions", record.id)));
|
|
20216
20335
|
}
|
|
20217
20336
|
const existingById = new Map(existingSessions.filter((record) => !deleted.has(record.id)).map((record) => [record.id, record]));
|
|
20218
|
-
const
|
|
20337
|
+
const mergedRecords = sessionRecords.map((record) => StorageDb.mergeSessionReviewState?.(
|
|
20338
|
+
record,
|
|
20339
|
+
existingById.get(record.id),
|
|
20340
|
+
options2.reviewRunIds
|
|
20341
|
+
) || record);
|
|
20342
|
+
const writable = mergedRecords.filter((record) => {
|
|
20219
20343
|
const existing = existingById.get(record.id);
|
|
20220
20344
|
if (!existing) return true;
|
|
20221
20345
|
return (Date.parse(record.updatedAt || "") || 0) >= (Date.parse(existing.updatedAt || "") || 0);
|
|
@@ -20271,6 +20395,41 @@ ${block}`;
|
|
|
20271
20395
|
}
|
|
20272
20396
|
return JSON.parse(JSON.stringify(value));
|
|
20273
20397
|
}
|
|
20398
|
+
async function applyReviewTransition({ getState, runId, transition, persist }) {
|
|
20399
|
+
const targets = () => Array.from(/* @__PURE__ */ new Set([
|
|
20400
|
+
...getState().runs || [],
|
|
20401
|
+
...(getState().sessions || []).flatMap((session) => session.runs || [])
|
|
20402
|
+
])).filter((run) => run.id === runId);
|
|
20403
|
+
const records = targets();
|
|
20404
|
+
const sessions = (getState().sessions || []).filter((session) => (session.runs || []).some((run) => run.id === runId));
|
|
20405
|
+
if (!records.length || !sessions.length) throw reviewPersistenceError();
|
|
20406
|
+
const previous = cloneSnapshot(records[0]);
|
|
20407
|
+
for (const record of records) Object.assign(record, cloneSnapshot(transition));
|
|
20408
|
+
for (const session of sessions) {
|
|
20409
|
+
session.updatedAt = new Date(Math.max(
|
|
20410
|
+
Date.now(),
|
|
20411
|
+
(Date.parse(session.updatedAt) || 0) + 1,
|
|
20412
|
+
(Date.parse(session.lastActivityAt) || 0) + 1
|
|
20413
|
+
)).toISOString();
|
|
20414
|
+
session.lastActivityAt = session.updatedAt;
|
|
20415
|
+
}
|
|
20416
|
+
try {
|
|
20417
|
+
await persist({ preserveRunActionPayload: true, reviewRunIds: [runId] });
|
|
20418
|
+
} catch (error) {
|
|
20419
|
+
for (const record of targets()) {
|
|
20420
|
+
Object.assign(record, cloneSnapshot(previous), { trackedChangeStatus: "needs_review" });
|
|
20421
|
+
for (const field of ["settlement", "settlementFacts"]) {
|
|
20422
|
+
if (!Object.prototype.hasOwnProperty.call(previous, field)) delete record[field];
|
|
20423
|
+
}
|
|
20424
|
+
}
|
|
20425
|
+
throw error;
|
|
20426
|
+
}
|
|
20427
|
+
}
|
|
20428
|
+
function reviewPersistenceError() {
|
|
20429
|
+
return Object.assign(new Error("The review outcome was not durably saved. Check Overleaf before retrying."), {
|
|
20430
|
+
code: "review_state_not_persisted"
|
|
20431
|
+
});
|
|
20432
|
+
}
|
|
20274
20433
|
async function persistPanelState(input) {
|
|
20275
20434
|
var state = cloneSnapshot(input.state || {});
|
|
20276
20435
|
var compactState = cloneSnapshot(input.compactState || {});
|
|
@@ -20289,6 +20448,8 @@ ${block}`;
|
|
|
20289
20448
|
code: "stale_view"
|
|
20290
20449
|
});
|
|
20291
20450
|
}
|
|
20451
|
+
var reviewRuns = (input.reviewRunIds || []).map((id) => (state.sessions || []).flatMap((session) => session.runs || []).find((run) => run.id === id));
|
|
20452
|
+
if (reviewRuns.some((run) => !run)) throw reviewPersistenceError();
|
|
20292
20453
|
var latestPrefs = typeof Migration.loadPrefs === "function" ? await Migration.loadPrefs(accountScopeId, projectId) : {};
|
|
20293
20454
|
var prefs = Object.assign(
|
|
20294
20455
|
{},
|
|
@@ -20344,19 +20505,23 @@ ${block}`;
|
|
|
20344
20505
|
})
|
|
20345
20506
|
}), { preserveRunActionPayload: true });
|
|
20346
20507
|
});
|
|
20347
|
-
await input.SessionPersistence.writeSessions({
|
|
20508
|
+
var written = await input.SessionPersistence.writeSessions({
|
|
20348
20509
|
Migration,
|
|
20349
20510
|
StorageDb,
|
|
20350
20511
|
projectId,
|
|
20351
20512
|
accountScopeId,
|
|
20352
20513
|
deletedSessionIds,
|
|
20353
20514
|
sessionRecords,
|
|
20515
|
+
reviewRunIds: input.reviewRunIds,
|
|
20354
20516
|
queueClaims: persistenceMeta.queueClaims || {},
|
|
20355
20517
|
queueTombstones,
|
|
20356
20518
|
writerId: input.persistenceContext?.writerId || ""
|
|
20357
20519
|
});
|
|
20520
|
+
if (!reviewRuns.every((reviewRun) => (written || []).some((session) => (session.runs || []).some(
|
|
20521
|
+
(run) => run.id === reviewRun.id && run.trackedChangeStatus === reviewRun.trackedChangeStatus
|
|
20522
|
+
)))) throw reviewPersistenceError();
|
|
20358
20523
|
}
|
|
20359
|
-
return Object.freeze({ persistPanelState });
|
|
20524
|
+
return Object.freeze({ persistPanelState, applyReviewTransition });
|
|
20360
20525
|
});
|
|
20361
20526
|
}).call(globalThis, void 0, void 0, void 0);
|
|
20362
20527
|
(function runClassicContentModule63(module, exports, require2) {
|
|
@@ -20495,7 +20660,8 @@ ${block}`;
|
|
|
20495
20660
|
}
|
|
20496
20661
|
return Object.freeze({
|
|
20497
20662
|
createController,
|
|
20498
|
-
persistPanelState: PanelState?.persistPanelState || null
|
|
20663
|
+
persistPanelState: PanelState?.persistPanelState || null,
|
|
20664
|
+
applyReviewTransition: PanelState?.applyReviewTransition || null
|
|
20499
20665
|
});
|
|
20500
20666
|
});
|
|
20501
20667
|
}).call(globalThis, void 0, void 0, void 0);
|
|
@@ -30808,11 +30974,11 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30808
30974
|
}
|
|
30809
30975
|
function configureLifecycleUndoButton(button, run) {
|
|
30810
30976
|
const status = run.trackedChangeStatus || "";
|
|
30977
|
+
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30811
30978
|
const projection = projectRunSettlement(run);
|
|
30812
30979
|
if (status === "needs_review") {
|
|
30813
|
-
const inFlight2 = trackedChangeInFlight.get(run.id);
|
|
30814
30980
|
button.hidden = false;
|
|
30815
|
-
button.disabled = !projection.canUndo ||
|
|
30981
|
+
button.disabled = !projection.canUndo || inFlight === "reject" || inFlight === "accept";
|
|
30816
30982
|
button.textContent = tr("undoRun");
|
|
30817
30983
|
button.title = tr("undoRunTitle");
|
|
30818
30984
|
button.addEventListener("click", (event) => {
|
|
@@ -30821,25 +30987,24 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30821
30987
|
});
|
|
30822
30988
|
return;
|
|
30823
30989
|
}
|
|
30824
|
-
if (status === "rejected") {
|
|
30990
|
+
if (status === "rejected" && !inFlight) {
|
|
30825
30991
|
button.hidden = false;
|
|
30826
30992
|
button.disabled = true;
|
|
30827
30993
|
button.textContent = tr("undoApplied");
|
|
30828
30994
|
button.title = tr("undoAppliedTitle");
|
|
30829
30995
|
return;
|
|
30830
30996
|
}
|
|
30831
|
-
if (status === "accepted") {
|
|
30997
|
+
if (status === "accepted" && !inFlight) {
|
|
30832
30998
|
button.hidden = false;
|
|
30833
30999
|
button.disabled = true;
|
|
30834
31000
|
button.textContent = tr("undoRun");
|
|
30835
31001
|
button.title = tr("undoRunTitle");
|
|
30836
31002
|
return;
|
|
30837
31003
|
}
|
|
30838
|
-
if (status !== "pending") {
|
|
31004
|
+
if (status !== "pending" && !inFlight) {
|
|
30839
31005
|
button.hidden = true;
|
|
30840
31006
|
return;
|
|
30841
31007
|
}
|
|
30842
|
-
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30843
31008
|
button.hidden = false;
|
|
30844
31009
|
button.disabled = !projection.canUndo || inFlight === "reject" || inFlight === "accept";
|
|
30845
31010
|
button.textContent = tr("undoRun");
|
|
@@ -30865,12 +31030,12 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30865
31030
|
return;
|
|
30866
31031
|
}
|
|
30867
31032
|
const status = run.trackedChangeStatus || "";
|
|
31033
|
+
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30868
31034
|
const projection = projectRunSettlement(run);
|
|
30869
31035
|
if (status === "needs_review") {
|
|
30870
|
-
const inFlight2 = trackedChangeInFlight.get(run.id);
|
|
30871
31036
|
button.hidden = false;
|
|
30872
|
-
button.disabled = !projection.canAccept ||
|
|
30873
|
-
if (
|
|
31037
|
+
button.disabled = !projection.canAccept || inFlight === "accept" || inFlight === "reject";
|
|
31038
|
+
if (inFlight === "accept") {
|
|
30874
31039
|
button.textContent = tr("runAcceptTrackedConfirming");
|
|
30875
31040
|
button.title = tr("runAcceptTrackedConfirming");
|
|
30876
31041
|
return;
|
|
@@ -30880,25 +31045,24 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30880
31045
|
wireAcceptInlineConfirm(button, run.id);
|
|
30881
31046
|
return;
|
|
30882
31047
|
}
|
|
30883
|
-
if (status === "accepted") {
|
|
31048
|
+
if (status === "accepted" && !inFlight) {
|
|
30884
31049
|
button.hidden = false;
|
|
30885
31050
|
button.disabled = true;
|
|
30886
31051
|
button.textContent = tr("runAcceptTrackedDone");
|
|
30887
31052
|
button.title = tr("runAcceptTrackedDoneTitle");
|
|
30888
31053
|
return;
|
|
30889
31054
|
}
|
|
30890
|
-
if (status === "rejected") {
|
|
31055
|
+
if (status === "rejected" && !inFlight) {
|
|
30891
31056
|
button.hidden = false;
|
|
30892
31057
|
button.disabled = true;
|
|
30893
31058
|
button.textContent = tr("runAcceptTracked");
|
|
30894
31059
|
button.title = tr("runAcceptTrackedTitle");
|
|
30895
31060
|
return;
|
|
30896
31061
|
}
|
|
30897
|
-
if (status !== "pending") {
|
|
31062
|
+
if (status !== "pending" && !inFlight) {
|
|
30898
31063
|
button.hidden = true;
|
|
30899
31064
|
return;
|
|
30900
31065
|
}
|
|
30901
|
-
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30902
31066
|
button.hidden = false;
|
|
30903
31067
|
button.disabled = !projection.canAccept || inFlight === "accept" || inFlight === "reject";
|
|
30904
31068
|
if (inFlight === "accept") {
|
|
@@ -32991,6 +33155,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32991
33155
|
});
|
|
32992
33156
|
const PROJECT_NAME_CACHE_STORAGE_KEY = "projectNameCacheByAccount";
|
|
32993
33157
|
let projectNameCacheMirror = {};
|
|
33158
|
+
let dashboardRenderGeneration = 0;
|
|
32994
33159
|
function loadProjectNameCacheFromStorage() {
|
|
32995
33160
|
return new Promise(function(resolve) {
|
|
32996
33161
|
try {
|
|
@@ -33074,7 +33239,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33074
33239
|
await persistProjectNameCacheToStorage();
|
|
33075
33240
|
var visibleList = getPanel() && getPanel().querySelector("[data-recent-projects-list]");
|
|
33076
33241
|
if (visibleList) {
|
|
33077
|
-
var rows = visibleList.querySelectorAll("[data-
|
|
33242
|
+
var rows = visibleList.querySelectorAll("[data-project-id]");
|
|
33078
33243
|
for (var k = 0; k < rows.length; k++) {
|
|
33079
33244
|
var row = rows[k];
|
|
33080
33245
|
var rowPid = row.getAttribute("data-project-id");
|
|
@@ -33083,6 +33248,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33083
33248
|
var cached = lookupProjectName(rowPid);
|
|
33084
33249
|
if (cached) {
|
|
33085
33250
|
nameEl.textContent = cached;
|
|
33251
|
+
nameEl.title = cached;
|
|
33086
33252
|
}
|
|
33087
33253
|
}
|
|
33088
33254
|
}
|
|
@@ -33151,54 +33317,47 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33151
33317
|
var hr = Math.round(min / 60);
|
|
33152
33318
|
if (hr < 24) return tx(hr + " hr ago", hr + " \u5C0F\u65F6\u524D");
|
|
33153
33319
|
var day = Math.round(hr / 24);
|
|
33154
|
-
if (day < 30) return tx(day + " day ago", day + " \u5929\u524D");
|
|
33320
|
+
if (day < 30) return tx(day + (day === 1 ? " day ago" : " days ago"), day + " \u5929\u524D");
|
|
33155
33321
|
var month = Math.round(day / 30);
|
|
33156
33322
|
if (month < 12) return tx(month + " mo ago", month + " \u4E2A\u6708\u524D");
|
|
33157
33323
|
var year = Math.round(month / 12);
|
|
33158
33324
|
return tx(year + " yr ago", year + " \u5E74\u524D");
|
|
33159
33325
|
}
|
|
33160
|
-
function
|
|
33161
|
-
var el = document.createElement(
|
|
33162
|
-
if (className)
|
|
33163
|
-
|
|
33164
|
-
}
|
|
33165
|
-
el.textContent = text == null ? "" : String(text);
|
|
33326
|
+
function createViewElement(tag, className, text) {
|
|
33327
|
+
var el = document.createElement(tag);
|
|
33328
|
+
if (className) el.className = className;
|
|
33329
|
+
if (text !== void 0) el.textContent = text;
|
|
33166
33330
|
return el;
|
|
33167
33331
|
}
|
|
33168
|
-
function
|
|
33169
|
-
var
|
|
33170
|
-
|
|
33332
|
+
function createViewButton(label, onClick, attribute, className) {
|
|
33333
|
+
var button = createViewElement("button", className, label);
|
|
33334
|
+
button.type = "button";
|
|
33335
|
+
if (attribute) button.setAttribute(attribute, "");
|
|
33336
|
+
if (onClick) button.addEventListener("click", onClick);
|
|
33337
|
+
return button;
|
|
33338
|
+
}
|
|
33339
|
+
function textNode(text, className) {
|
|
33340
|
+
return createViewElement("span", className, text == null ? "" : String(text));
|
|
33341
|
+
}
|
|
33342
|
+
function renderWelcomeHeader() {
|
|
33343
|
+
var el = createViewElement("div", "recent-projects-welcome");
|
|
33171
33344
|
el.setAttribute("data-recent-projects-welcome", "");
|
|
33172
|
-
|
|
33173
|
-
|
|
33174
|
-
|
|
33175
|
-
var subtitle = document.createElement("div");
|
|
33176
|
-
subtitle.className = "recent-projects-welcome-subtitle";
|
|
33177
|
-
subtitle.textContent = stats && stats.projectCount ? tr("recentProjects_welcome_stats", { projects: stats.projectCount, sessions: stats.sessionTotal }) : tr("recentProjects_welcome_subtitle");
|
|
33178
|
-
el.appendChild(title);
|
|
33179
|
-
el.appendChild(subtitle);
|
|
33345
|
+
el.appendChild(textNode("CODEX", "recent-projects-eyebrow"));
|
|
33346
|
+
el.appendChild(textNode(tr("recentProjects_welcome"), "recent-projects-welcome-title"));
|
|
33347
|
+
el.appendChild(textNode(tr("recentProjects_welcome_subtitle"), "recent-projects-welcome-subtitle"));
|
|
33180
33348
|
return el;
|
|
33181
33349
|
}
|
|
33182
33350
|
function renderEmptyState() {
|
|
33183
|
-
var el =
|
|
33184
|
-
el.className = "recent-projects-empty";
|
|
33351
|
+
var el = createViewElement("div", "recent-projects-empty", tr("recentProjects_empty"));
|
|
33185
33352
|
el.setAttribute("data-recent-projects-empty", "");
|
|
33186
|
-
el.textContent = tr("recentProjects_empty");
|
|
33187
33353
|
return el;
|
|
33188
33354
|
}
|
|
33189
33355
|
function renderDegradedState() {
|
|
33190
|
-
var el =
|
|
33191
|
-
el.className = "recent-projects-degraded";
|
|
33356
|
+
var el = createViewElement("div", "recent-projects-degraded");
|
|
33192
33357
|
el.setAttribute("data-recent-projects-degraded", "");
|
|
33193
|
-
var hint =
|
|
33194
|
-
hint.textContent = tr("recentProjects_degraded_hint");
|
|
33358
|
+
var hint = createViewElement("div", "", tr("recentProjects_degraded_hint"));
|
|
33195
33359
|
el.appendChild(hint);
|
|
33196
|
-
var retry =
|
|
33197
|
-
retry.type = "button";
|
|
33198
|
-
retry.className = "recent-projects-show-all";
|
|
33199
|
-
retry.setAttribute("data-recent-projects-retry", "");
|
|
33200
|
-
retry.textContent = tr("recentProjects_retryScope");
|
|
33201
|
-
retry.addEventListener("click", function() {
|
|
33360
|
+
var retry = createViewButton(tr("recentProjects_retryScope"), function() {
|
|
33202
33361
|
if (typeof refreshAccountScopeId === "function") {
|
|
33203
33362
|
Promise.resolve(refreshAccountScopeId()).then(function() {
|
|
33204
33363
|
return renderRecentProjectsVariant();
|
|
@@ -33207,24 +33366,17 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33207
33366
|
} else {
|
|
33208
33367
|
renderRecentProjectsVariant();
|
|
33209
33368
|
}
|
|
33210
|
-
});
|
|
33369
|
+
}, "data-recent-projects-retry", "recent-projects-show-all");
|
|
33211
33370
|
el.appendChild(retry);
|
|
33212
33371
|
return el;
|
|
33213
33372
|
}
|
|
33214
33373
|
function renderSettingsEntry(options2) {
|
|
33215
33374
|
var scope = options2 && options2.scope === "account" ? "account" : "project";
|
|
33216
|
-
var entry =
|
|
33217
|
-
entry.type = "button";
|
|
33218
|
-
entry.className = "recent-projects-settings-entry";
|
|
33219
|
-
entry.setAttribute("data-recent-projects-settings-entry", "");
|
|
33220
|
-
entry.setAttribute("data-settings-scope", scope);
|
|
33221
|
-
var label = document.createElement("span");
|
|
33222
|
-
label.className = "recent-projects-settings-entry-label";
|
|
33223
|
-
label.textContent = tr("recentProjects_settings_entry");
|
|
33224
|
-
entry.appendChild(label);
|
|
33225
|
-
entry.addEventListener("click", function() {
|
|
33375
|
+
var entry = createViewButton(void 0, function() {
|
|
33226
33376
|
openSettingsInScope(scope);
|
|
33227
|
-
});
|
|
33377
|
+
}, "data-recent-projects-settings-entry", "recent-projects-settings-entry");
|
|
33378
|
+
entry.setAttribute("data-settings-scope", scope);
|
|
33379
|
+
entry.appendChild(textNode(tr("recentProjects_settings_entry"), "recent-projects-settings-entry-label"));
|
|
33228
33380
|
return entry;
|
|
33229
33381
|
}
|
|
33230
33382
|
function openSettingsInScope(scope) {
|
|
@@ -33247,10 +33399,8 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33247
33399
|
function renderStatusBadge(status) {
|
|
33248
33400
|
var safeStatus = typeof status === "string" && STATUS_BADGE_CLASS[status] ? status : "pending";
|
|
33249
33401
|
var cls = STATUS_BADGE_CLASS[safeStatus];
|
|
33250
|
-
var el =
|
|
33251
|
-
el.className = "recent-projects-row-badge " + cls;
|
|
33402
|
+
var el = textNode(tr("recentProjects_badge_" + safeStatus), "recent-projects-row-badge " + cls);
|
|
33252
33403
|
el.setAttribute("data-status", safeStatus);
|
|
33253
|
-
el.textContent = tr("recentProjects_badge_" + safeStatus);
|
|
33254
33404
|
return el;
|
|
33255
33405
|
}
|
|
33256
33406
|
function isValidProjectId(id) {
|
|
@@ -33262,121 +33412,137 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33262
33412
|
}
|
|
33263
33413
|
window.location.assign("https://www.overleaf.com/project/" + encodeURIComponent(projectId));
|
|
33264
33414
|
}
|
|
33415
|
+
function renderActionsMenu(buttons) {
|
|
33416
|
+
var menu = createViewElement("details", "recent-projects-menu");
|
|
33417
|
+
var trigger = createViewElement("summary", "", "\u22EF");
|
|
33418
|
+
trigger.title = tr("recentProjects_more");
|
|
33419
|
+
trigger.setAttribute("aria-label", tr("recentProjects_more"));
|
|
33420
|
+
var actions = document.createElement("div");
|
|
33421
|
+
actions.setAttribute("data-recent-menu-actions", "");
|
|
33422
|
+
buttons.forEach(function(button) {
|
|
33423
|
+
actions.appendChild(button);
|
|
33424
|
+
});
|
|
33425
|
+
actions.addEventListener("click", function(event) {
|
|
33426
|
+
if (event.target.closest("button")) {
|
|
33427
|
+
menu.open = false;
|
|
33428
|
+
trigger.focus();
|
|
33429
|
+
}
|
|
33430
|
+
}, true);
|
|
33431
|
+
menu.appendChild(trigger);
|
|
33432
|
+
menu.appendChild(actions);
|
|
33433
|
+
menu.addEventListener("keydown", function(event) {
|
|
33434
|
+
if (event.key === "Escape") {
|
|
33435
|
+
event.preventDefault();
|
|
33436
|
+
event.stopPropagation();
|
|
33437
|
+
menu.open = false;
|
|
33438
|
+
trigger.focus();
|
|
33439
|
+
}
|
|
33440
|
+
});
|
|
33441
|
+
menu.addEventListener("focusout", function(event) {
|
|
33442
|
+
if (event.relatedTarget && !menu.contains(event.relatedTarget)) menu.open = false;
|
|
33443
|
+
});
|
|
33444
|
+
return menu;
|
|
33445
|
+
}
|
|
33446
|
+
function conversationActivity(record) {
|
|
33447
|
+
return String(record && (record.lastActivityAt || record.updatedAt || record.createdAt) || "");
|
|
33448
|
+
}
|
|
33449
|
+
function conversationHasContent(record) {
|
|
33450
|
+
return ["runs", "history", "pendingInputs"].some(function(key) {
|
|
33451
|
+
return Array.isArray(record[key]) && record[key].length > 0;
|
|
33452
|
+
}) || ["task", "safeTaskSummary", "codexThreadId"].some(function(key) {
|
|
33453
|
+
return typeof record[key] === "string" && Boolean(record[key].trim());
|
|
33454
|
+
}) || record.titleSource === "manual" && typeof record.title === "string" && Boolean(record.title.trim());
|
|
33455
|
+
}
|
|
33456
|
+
function conversationStatus(record) {
|
|
33457
|
+
if (!StorageDb || !Array.isArray(record.runs) || !record.runs.length) return "";
|
|
33458
|
+
return settleDashboardRunStatus(StorageDb.derivePrimaryStatusBadge(record), conversationActivity(record));
|
|
33459
|
+
}
|
|
33460
|
+
function projectDisplayName(projectId) {
|
|
33461
|
+
return lookupProjectName(projectId) || (isValidProjectId(projectId) ? tr("recentProjects_unnamed", { prefix: projectId.slice(0, 8) }) : tr("recentProjects_row_projectLinkUnavailable"));
|
|
33462
|
+
}
|
|
33463
|
+
async function loadDashboardConversations(scope) {
|
|
33464
|
+
if (!scope || !StorageDb) throw new Error("Conversation storage is unavailable.");
|
|
33465
|
+
var results = await Promise.all([StorageDb.getAllSessions(), SessionPersistence.loadTombstones()]);
|
|
33466
|
+
var records = results[0];
|
|
33467
|
+
var deletedByProject = results[1] || {};
|
|
33468
|
+
if (!Array.isArray(records)) throw new Error("Conversation history could not be read.");
|
|
33469
|
+
return records.filter(function(record) {
|
|
33470
|
+
if (!record || typeof record.id !== "string" || !record.id || record.accountScopeUnavailable === true) return false;
|
|
33471
|
+
var deletedIds = Object.prototype.hasOwnProperty.call(deletedByProject, record.projectId) ? deletedByProject[record.projectId] : [];
|
|
33472
|
+
return SessionPersistence.isVisibleRecord(record, Array.isArray(deletedIds) ? deletedIds : [], scope);
|
|
33473
|
+
}).sort(function(a, b) {
|
|
33474
|
+
var aTime = Date.parse(conversationActivity(a)) || 0;
|
|
33475
|
+
var bTime = Date.parse(conversationActivity(b)) || 0;
|
|
33476
|
+
return bTime - aTime || String(a.id).localeCompare(String(b.id));
|
|
33477
|
+
});
|
|
33478
|
+
}
|
|
33479
|
+
function dashboardViewOptions() {
|
|
33480
|
+
var root = getPanel() && getPanel().querySelector("[data-recent-projects-root]");
|
|
33481
|
+
var drafts = root && root.querySelector("[data-unstarted-conversations]");
|
|
33482
|
+
return {
|
|
33483
|
+
accountScopeId: root && root.dataset.accountScopeId || "",
|
|
33484
|
+
projectFilter: root && root.dataset.projectFilter || "",
|
|
33485
|
+
showAll: Boolean(root && root.dataset.showAll === "true"),
|
|
33486
|
+
draftsOpen: Boolean(drafts && drafts.open),
|
|
33487
|
+
restoreScrollTop: root ? root.scrollTop : 0
|
|
33488
|
+
};
|
|
33489
|
+
}
|
|
33490
|
+
async function refreshDashboardView() {
|
|
33491
|
+
var panelEl = getPanel();
|
|
33492
|
+
if (panelEl && panelEl.dataset.view === "recent-projects") {
|
|
33493
|
+
await renderRecentProjectsVariant(dashboardViewOptions());
|
|
33494
|
+
}
|
|
33495
|
+
}
|
|
33496
|
+
async function openDashboardConversation(projectId, record, row) {
|
|
33497
|
+
var scope = record.accountScopeId;
|
|
33498
|
+
var panelEl = getPanel();
|
|
33499
|
+
if (!scope || scope !== getCachedAccountScopeId() || !isValidProjectId(projectId) || !panelEl || panelEl.dataset.view !== "recent-projects" || row.getAttribute("aria-busy") === "true") return;
|
|
33500
|
+
row.setAttribute("aria-busy", "true");
|
|
33501
|
+
var resume = row.querySelector("[data-session-resume]");
|
|
33502
|
+
if (resume) resume.disabled = true;
|
|
33503
|
+
try {
|
|
33504
|
+
var records = await loadProjectSessionRecords(projectId);
|
|
33505
|
+
if (scope !== getCachedAccountScopeId() || panelEl !== getPanel() || panelEl.dataset.view !== "recent-projects" || row.isConnected === false) return;
|
|
33506
|
+
var selected = records.find(function(candidate) {
|
|
33507
|
+
return candidate.id === record.id;
|
|
33508
|
+
});
|
|
33509
|
+
if (!selected) {
|
|
33510
|
+
await refreshDashboardView();
|
|
33511
|
+
showPluginToast(tr("recentProjects_conversationGone"), { status: "warning" });
|
|
33512
|
+
return;
|
|
33513
|
+
}
|
|
33514
|
+
await activateSessionAndOpenProject(projectId, selected);
|
|
33515
|
+
} catch (_error) {
|
|
33516
|
+
if (scope === getCachedAccountScopeId() && row.isConnected !== false) {
|
|
33517
|
+
showPluginToast(tr("recentProjects_continueFailed"), { status: "warning" });
|
|
33518
|
+
}
|
|
33519
|
+
} finally {
|
|
33520
|
+
row.removeAttribute("aria-busy");
|
|
33521
|
+
if (resume) resume.disabled = false;
|
|
33522
|
+
}
|
|
33523
|
+
}
|
|
33265
33524
|
function renderRecentProjectRow(row) {
|
|
33266
33525
|
var projectId = row && row.projectId;
|
|
33267
33526
|
var valid = isValidProjectId(projectId);
|
|
33268
|
-
var
|
|
33269
|
-
|
|
33270
|
-
|
|
33271
|
-
|
|
33272
|
-
|
|
33273
|
-
|
|
33274
|
-
|
|
33275
|
-
|
|
33276
|
-
}
|
|
33277
|
-
var
|
|
33278
|
-
|
|
33279
|
-
name = isValidProjectId(projectId) ? tr("recentProjects_unnamed", { prefix: projectId.slice(0, 8) }) : tr("recentProjects_row_projectLinkUnavailable");
|
|
33280
|
-
}
|
|
33281
|
-
var nameNode = textNode(name, "recent-projects-row-name");
|
|
33282
|
-
nameNode.title = name;
|
|
33283
|
-
el.appendChild(nameNode);
|
|
33284
|
-
var rowTime = textNode(formatRelativeTime(row && row.lastActivityAt), "recent-projects-row-time");
|
|
33285
|
-
rowTime.setAttribute("data-rel-time", String(row && row.lastActivityAt || ""));
|
|
33286
|
-
el.appendChild(rowTime);
|
|
33287
|
-
var sessionCount = Number(row && row.sessionCount) || 0;
|
|
33288
|
-
if (sessionCount > 1) {
|
|
33289
|
-
el.appendChild(textNode(tr("recentProjects_sessionsCount", { count: sessionCount }), "recent-projects-row-sessions"));
|
|
33290
|
-
}
|
|
33291
|
-
el.appendChild(renderStatusBadge(settleDashboardRunStatus(row && row.primaryStatusBadge, row && row.lastActivityAt)));
|
|
33292
|
-
if (valid) {
|
|
33293
|
-
el.addEventListener("click", function() {
|
|
33294
|
-
openProjectFromRow(projectId);
|
|
33295
|
-
});
|
|
33296
|
-
} else {
|
|
33297
|
-
el.appendChild(textNode(tr("recentProjects_row_projectLinkUnavailable"), "recent-projects-row-warning"));
|
|
33298
|
-
}
|
|
33299
|
-
if (!valid) {
|
|
33300
|
-
var deadWrap = document.createElement("div");
|
|
33301
|
-
deadWrap.className = "recent-projects-row-wrap";
|
|
33302
|
-
var deadHead = document.createElement("div");
|
|
33303
|
-
deadHead.className = "recent-projects-row-head";
|
|
33304
|
-
var cleanup = document.createElement("button");
|
|
33305
|
-
cleanup.type = "button";
|
|
33306
|
-
cleanup.className = "recent-projects-row-cleanup";
|
|
33307
|
-
cleanup.setAttribute("data-row-cleanup", "");
|
|
33308
|
-
cleanup.title = tr("recentProjects_cleanup");
|
|
33309
|
-
cleanup.setAttribute("aria-label", tr("recentProjects_cleanup"));
|
|
33310
|
-
cleanup.textContent = "\xD7";
|
|
33311
|
-
cleanup.addEventListener("click", function() {
|
|
33312
|
-
cleanupDeadProjectEntry(projectId).catch(function() {
|
|
33313
|
-
});
|
|
33527
|
+
var wrap = createViewElement("div", "recent-projects-row-wrap recent-projects-unavailable-row");
|
|
33528
|
+
wrap.setAttribute("data-project-id", projectId || "");
|
|
33529
|
+
var link = createViewButton(void 0, null, "data-recent-projects-row", "recent-projects-row");
|
|
33530
|
+
link.setAttribute("data-project-id", projectId || "");
|
|
33531
|
+
link.disabled = !valid;
|
|
33532
|
+
link.appendChild(textNode(projectDisplayName(projectId), "recent-projects-row-name"));
|
|
33533
|
+
if (valid) link.addEventListener("click", function() {
|
|
33534
|
+
openProjectFromRow(projectId);
|
|
33535
|
+
});
|
|
33536
|
+
var cleanup = createViewButton(tr(valid ? "recentProjects_clearProject" : "recentProjects_cleanup"), function() {
|
|
33537
|
+
if (valid) projectSessionCleanup.clearProjectSessions(projectId, projectDisplayName(projectId)).catch(function() {
|
|
33314
33538
|
});
|
|
33315
|
-
|
|
33316
|
-
deadHead.appendChild(cleanup);
|
|
33317
|
-
deadWrap.appendChild(deadHead);
|
|
33318
|
-
return deadWrap;
|
|
33319
|
-
}
|
|
33320
|
-
var wrap = document.createElement("div");
|
|
33321
|
-
wrap.className = "recent-projects-row-wrap";
|
|
33322
|
-
wrap.setAttribute("data-project-row-wrap", projectId);
|
|
33323
|
-
var expand = document.createElement("button");
|
|
33324
|
-
expand.type = "button";
|
|
33325
|
-
expand.className = "recent-projects-row-expand";
|
|
33326
|
-
expand.setAttribute("data-row-expand", "");
|
|
33327
|
-
expand.setAttribute("aria-expanded", "false");
|
|
33328
|
-
var sessionsElId = "codex-project-sessions-" + String(projectId || "").slice(0, 24);
|
|
33329
|
-
expand.setAttribute("aria-controls", sessionsElId);
|
|
33330
|
-
expand.title = tr("recentProjects_sessions_toggle");
|
|
33331
|
-
expand.setAttribute("aria-label", tr("recentProjects_sessions_toggle"));
|
|
33332
|
-
expand.textContent = tr("recentProjects_sessions_action");
|
|
33333
|
-
var head = document.createElement("div");
|
|
33334
|
-
head.className = "recent-projects-row-head";
|
|
33335
|
-
var clear = document.createElement("button");
|
|
33336
|
-
clear.type = "button";
|
|
33337
|
-
clear.className = "recent-projects-row-clear";
|
|
33338
|
-
clear.setAttribute("data-project-clear", "");
|
|
33339
|
-
clear.title = tr("recentProjects_clearProject");
|
|
33340
|
-
clear.setAttribute("aria-label", tr("recentProjects_clearProject"));
|
|
33341
|
-
clear.textContent = "\xD7";
|
|
33342
|
-
clear.addEventListener("click", function(event) {
|
|
33343
|
-
event.stopPropagation();
|
|
33344
|
-
projectSessionCleanup.clearProjectSessions(projectId, name).catch(function() {
|
|
33539
|
+
else cleanupDeadProjectEntry(projectId).catch(function() {
|
|
33345
33540
|
});
|
|
33346
|
-
});
|
|
33347
|
-
|
|
33348
|
-
|
|
33349
|
-
head.appendChild(clear);
|
|
33350
|
-
var sessionsEl = document.createElement("div");
|
|
33351
|
-
sessionsEl.className = "recent-projects-sessions";
|
|
33352
|
-
sessionsEl.setAttribute("data-project-sessions", "");
|
|
33353
|
-
sessionsEl.id = sessionsElId;
|
|
33354
|
-
sessionsEl.setAttribute("role", "region");
|
|
33355
|
-
sessionsEl.setAttribute("aria-label", tr("recentProjects_sessions_toggle"));
|
|
33356
|
-
sessionsEl.hidden = true;
|
|
33357
|
-
expand.addEventListener("click", function() {
|
|
33358
|
-
toggleProjectSessions(wrap, projectId);
|
|
33359
|
-
});
|
|
33360
|
-
wrap.appendChild(head);
|
|
33361
|
-
wrap.appendChild(sessionsEl);
|
|
33541
|
+
}, valid ? "data-project-clear" : "data-row-cleanup");
|
|
33542
|
+
wrap.appendChild(link);
|
|
33543
|
+
wrap.appendChild(renderActionsMenu([cleanup]));
|
|
33362
33544
|
return wrap;
|
|
33363
33545
|
}
|
|
33364
|
-
function toggleProjectSessions(wrap, projectId) {
|
|
33365
|
-
var sessionsEl = wrap.querySelector("[data-project-sessions]");
|
|
33366
|
-
var expand = wrap.querySelector("[data-row-expand]");
|
|
33367
|
-
if (!sessionsEl || !expand) {
|
|
33368
|
-
return;
|
|
33369
|
-
}
|
|
33370
|
-
var opening = sessionsEl.hidden;
|
|
33371
|
-
sessionsEl.hidden = !opening;
|
|
33372
|
-
expand.setAttribute("aria-expanded", opening ? "true" : "false");
|
|
33373
|
-
expand.textContent = tr(opening ? "recentProjects_sessions_action_open" : "recentProjects_sessions_action");
|
|
33374
|
-
wrap.setAttribute("data-expanded", opening ? "true" : "false");
|
|
33375
|
-
if (opening) {
|
|
33376
|
-
renderProjectSessions(sessionsEl, projectId).catch(function() {
|
|
33377
|
-
});
|
|
33378
|
-
}
|
|
33379
|
-
}
|
|
33380
33546
|
function sessionRecordDisplayTitle(record) {
|
|
33381
33547
|
if (record && typeof record.title === "string" && record.title.trim()) {
|
|
33382
33548
|
return record.title.trim();
|
|
@@ -33398,87 +33564,90 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33398
33564
|
return String(b.updatedAt || b.createdAt || "").localeCompare(String(a.updatedAt || a.createdAt || ""));
|
|
33399
33565
|
});
|
|
33400
33566
|
}
|
|
33401
|
-
|
|
33402
|
-
|
|
33403
|
-
var sessionsLoading = document.createElement("div");
|
|
33404
|
-
sessionsLoading.className = "recent-projects-loading";
|
|
33405
|
-
sessionsLoading.textContent = tx("Loading sessions\u2026", "\u6B63\u5728\u52A0\u8F7D\u4F1A\u8BDD\u2026");
|
|
33406
|
-
sessionsEl.appendChild(sessionsLoading);
|
|
33407
|
-
var records = [];
|
|
33408
|
-
try {
|
|
33409
|
-
records = await loadProjectSessionRecords(projectId);
|
|
33410
|
-
} catch (_error) {
|
|
33411
|
-
records = [];
|
|
33412
|
-
}
|
|
33413
|
-
sessionsLoading.remove();
|
|
33414
|
-
if (!records.length) {
|
|
33415
|
-
sessionsEl.appendChild(textNode(tr("recentProjects_sessions_empty"), "recent-projects-sessions-empty"));
|
|
33416
|
-
return;
|
|
33417
|
-
}
|
|
33418
|
-
for (var i = 0; i < records.length; i++) {
|
|
33419
|
-
sessionsEl.appendChild(renderProjectSessionRow(sessionsEl, projectId, records[i]));
|
|
33420
|
-
}
|
|
33421
|
-
}
|
|
33422
|
-
function renderProjectSessionRow(sessionsEl, projectId, record) {
|
|
33567
|
+
function renderProjectSessionRow(sessionsEl, projectId, record, options2) {
|
|
33568
|
+
var featured = Boolean(options2 && options2.featured);
|
|
33423
33569
|
var running = Boolean(StorageDb) && settleDashboardRunStatus(StorageDb.derivePrimaryStatusBadge(record), record.updatedAt || record.lastActivityAt) === "running";
|
|
33424
|
-
var row =
|
|
33425
|
-
row.className = "recent-projects-session-row";
|
|
33570
|
+
var row = createViewElement("div", "recent-projects-session-row" + (featured ? " recent-projects-focus" : ""));
|
|
33426
33571
|
row.setAttribute("data-project-session-row", record.id);
|
|
33427
|
-
|
|
33428
|
-
|
|
33429
|
-
}
|
|
33572
|
+
row.setAttribute("data-project-id", projectId);
|
|
33573
|
+
if (running) row.setAttribute("data-running", "true");
|
|
33430
33574
|
var title = textNode(sessionRecordDisplayTitle(record), "recent-projects-session-title");
|
|
33431
|
-
title.title =
|
|
33432
|
-
var
|
|
33433
|
-
|
|
33434
|
-
var
|
|
33435
|
-
|
|
33436
|
-
|
|
33437
|
-
|
|
33438
|
-
|
|
33439
|
-
|
|
33440
|
-
|
|
33441
|
-
var
|
|
33442
|
-
|
|
33443
|
-
|
|
33444
|
-
|
|
33445
|
-
|
|
33446
|
-
|
|
33447
|
-
|
|
33448
|
-
|
|
33449
|
-
|
|
33450
|
-
|
|
33575
|
+
title.title = title.textContent;
|
|
33576
|
+
var copy = createViewElement("div", "recent-projects-session-copy");
|
|
33577
|
+
var meta = createViewElement("div", "recent-projects-session-meta");
|
|
33578
|
+
var project = textNode(projectDisplayName(projectId), "recent-projects-row-name");
|
|
33579
|
+
project.title = project.textContent;
|
|
33580
|
+
meta.appendChild(project);
|
|
33581
|
+
var time = textNode(formatRelativeTime(conversationActivity(record)), "recent-projects-session-time");
|
|
33582
|
+
time.setAttribute("data-rel-time", conversationActivity(record));
|
|
33583
|
+
time.title = conversationActivity(record);
|
|
33584
|
+
var status = conversationStatus(record);
|
|
33585
|
+
var footer = featured ? createViewElement("div", "recent-projects-focus-footer") : null;
|
|
33586
|
+
if (featured) {
|
|
33587
|
+
meta.insertBefore(textNode(tr("recentProjects_focusEyebrow"), "recent-projects-focus-eyebrow"), project);
|
|
33588
|
+
copy.appendChild(meta);
|
|
33589
|
+
copy.appendChild(title);
|
|
33590
|
+
footer.appendChild(status ? renderStatusBadge(status) : textNode(tr("recentProjects_savedDraft"), "recent-projects-row-badge"));
|
|
33591
|
+
} else {
|
|
33592
|
+
copy.appendChild(title);
|
|
33593
|
+
copy.appendChild(meta);
|
|
33594
|
+
if (["failed", "needs_review", "interrupted", "stale", "needs_review_after_navigation", "abandoned_after_navigation"].indexOf(status) !== -1) {
|
|
33595
|
+
var attention = textNode(tr("recentProjects_attention"), "recent-projects-session-attention");
|
|
33596
|
+
attention.title = tr("recentProjects_badge_" + status);
|
|
33597
|
+
meta.appendChild(attention);
|
|
33598
|
+
}
|
|
33451
33599
|
}
|
|
33452
|
-
|
|
33600
|
+
meta.appendChild(time);
|
|
33601
|
+
row.appendChild(copy);
|
|
33602
|
+
var rename = createViewButton(tr("renameSession"), function() {
|
|
33453
33603
|
beginDashboardSessionRename(sessionsEl, projectId, record, row, title);
|
|
33454
|
-
});
|
|
33455
|
-
|
|
33604
|
+
}, "data-session-rename-dash");
|
|
33605
|
+
rename.title = rename.textContent;
|
|
33606
|
+
rename.setAttribute("aria-label", rename.textContent);
|
|
33607
|
+
if (running) rename.disabled = true;
|
|
33608
|
+
var del = createViewButton(tr("deleteSession"), function() {
|
|
33456
33609
|
deleteDashboardSession(sessionsEl, projectId, record).catch(function() {
|
|
33457
33610
|
});
|
|
33611
|
+
}, "data-session-delete-dash");
|
|
33612
|
+
del.title = running ? tr("recentProjects_zombieRunningNote") : del.textContent;
|
|
33613
|
+
del.setAttribute("aria-label", del.textContent);
|
|
33614
|
+
var projectConversations = createViewButton(tr("recentProjects_projectConversations"), function() {
|
|
33615
|
+
renderRecentProjectsVariant({ projectFilter: projectId, showAll: true, restoreScrollTop: 0 }).catch(function() {
|
|
33616
|
+
});
|
|
33617
|
+
}, "data-project-conversations");
|
|
33618
|
+
var openProject = createViewButton(tr("recentProjects_openProject"), function() {
|
|
33619
|
+
openProjectFromRow(projectId);
|
|
33458
33620
|
});
|
|
33459
|
-
|
|
33460
|
-
|
|
33461
|
-
|
|
33462
|
-
|
|
33463
|
-
row.
|
|
33464
|
-
row.setAttribute("role", "button");
|
|
33465
|
-
row.tabIndex = 0;
|
|
33621
|
+
var clear = createViewButton(tr("recentProjects_clearProject"), function() {
|
|
33622
|
+
projectSessionCleanup.clearProjectSessions(projectId, projectDisplayName(projectId)).catch(function() {
|
|
33623
|
+
});
|
|
33624
|
+
}, "data-project-clear");
|
|
33625
|
+
row.appendChild(renderActionsMenu([rename, del, projectConversations, openProject, clear]));
|
|
33466
33626
|
var activate = function() {
|
|
33467
|
-
|
|
33627
|
+
openDashboardConversation(projectId, record, row).catch(function() {
|
|
33468
33628
|
});
|
|
33469
33629
|
};
|
|
33470
|
-
|
|
33471
|
-
|
|
33472
|
-
|
|
33473
|
-
|
|
33474
|
-
|
|
33475
|
-
|
|
33476
|
-
|
|
33477
|
-
|
|
33478
|
-
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
|
|
33630
|
+
if (featured) {
|
|
33631
|
+
row.setAttribute("role", "group");
|
|
33632
|
+
row.setAttribute("aria-label", tr("recentProjects_focusEyebrow"));
|
|
33633
|
+
var resume = createViewButton(tr("recentProjects_continue"), activate, "data-session-resume", "recent-projects-continue");
|
|
33634
|
+
resume.title = tr("recentProjects_continueHint");
|
|
33635
|
+
footer.appendChild(resume);
|
|
33636
|
+
row.appendChild(footer);
|
|
33637
|
+
} else {
|
|
33638
|
+
row.classList.add("recent-projects-session-row--linked");
|
|
33639
|
+
row.setAttribute("role", "button");
|
|
33640
|
+
row.tabIndex = 0;
|
|
33641
|
+
row.addEventListener("click", function(event) {
|
|
33642
|
+
if (!event.target.closest("button, input, details")) activate();
|
|
33643
|
+
});
|
|
33644
|
+
row.addEventListener("keydown", function(event) {
|
|
33645
|
+
if (event.target === row && (event.key === "Enter" || event.key === " ")) {
|
|
33646
|
+
event.preventDefault();
|
|
33647
|
+
activate();
|
|
33648
|
+
}
|
|
33649
|
+
});
|
|
33650
|
+
}
|
|
33482
33651
|
return row;
|
|
33483
33652
|
}
|
|
33484
33653
|
async function activateSessionAndOpenProject(projectId, record) {
|
|
@@ -33609,11 +33778,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33609
33778
|
} catch (error) {
|
|
33610
33779
|
showPluginToast(tr("deleteSessionHistoryFailedToast", { message: error.message }), { status: "warning", sticky: true });
|
|
33611
33780
|
}
|
|
33612
|
-
|
|
33613
|
-
await renderRecentProjectsVariant({
|
|
33614
|
-
expandProjectId: projectId,
|
|
33615
|
-
restoreScrollTop: rootForScroll ? rootForScroll.scrollTop : void 0
|
|
33616
|
-
});
|
|
33781
|
+
await refreshDashboardView();
|
|
33617
33782
|
}
|
|
33618
33783
|
function beginDashboardSessionRename(sessionsEl, projectId, record, row, titleEl) {
|
|
33619
33784
|
if (row.querySelector("input")) {
|
|
@@ -33626,7 +33791,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33626
33791
|
input.className = "recent-projects-session-rename-input";
|
|
33627
33792
|
input.value = seed;
|
|
33628
33793
|
titleEl.hidden = true;
|
|
33629
|
-
|
|
33794
|
+
titleEl.parentElement.insertBefore(input, titleEl);
|
|
33630
33795
|
input.focus();
|
|
33631
33796
|
input.select();
|
|
33632
33797
|
var settled = false;
|
|
@@ -33688,7 +33853,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33688
33853
|
}
|
|
33689
33854
|
} catch (_error) {
|
|
33690
33855
|
}
|
|
33691
|
-
await
|
|
33856
|
+
await refreshDashboardView();
|
|
33692
33857
|
}
|
|
33693
33858
|
function ensureRecentProjectsRoot() {
|
|
33694
33859
|
if (!getPanel()) {
|
|
@@ -33698,9 +33863,13 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33698
33863
|
if (existing) {
|
|
33699
33864
|
return existing;
|
|
33700
33865
|
}
|
|
33701
|
-
var rootEl =
|
|
33702
|
-
rootEl.className = "recent-projects-root";
|
|
33866
|
+
var rootEl = createViewElement("section", "recent-projects-root");
|
|
33703
33867
|
rootEl.setAttribute("data-recent-projects-root", "");
|
|
33868
|
+
rootEl.addEventListener("click", function(event) {
|
|
33869
|
+
rootEl.querySelectorAll(".recent-projects-menu[open]").forEach(function(menu) {
|
|
33870
|
+
if (!menu.contains(event.target)) menu.open = false;
|
|
33871
|
+
});
|
|
33872
|
+
});
|
|
33704
33873
|
getPanel().appendChild(rootEl);
|
|
33705
33874
|
return rootEl;
|
|
33706
33875
|
}
|
|
@@ -33737,116 +33906,152 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33737
33906
|
return;
|
|
33738
33907
|
}
|
|
33739
33908
|
rootEl.appendChild(renderWelcomeHeader());
|
|
33740
|
-
var loading =
|
|
33741
|
-
loading.className = "recent-projects-loading";
|
|
33742
|
-
loading.textContent = tx("Loading projects\u2026", "\u6B63\u5728\u52A0\u8F7D\u9879\u76EE\u2026");
|
|
33909
|
+
var loading = createViewElement("div", "recent-projects-loading", tx("Loading projects\u2026", "\u6B63\u5728\u52A0\u8F7D\u9879\u76EE\u2026"));
|
|
33743
33910
|
rootEl.appendChild(loading);
|
|
33744
33911
|
}
|
|
33745
33912
|
async function renderRecentProjectsVariant(options2) {
|
|
33746
|
-
|
|
33747
|
-
|
|
33748
|
-
|
|
33749
|
-
|
|
33913
|
+
var panelEl = getPanel();
|
|
33914
|
+
var editorMatch = String(window.location && window.location.pathname || "").match(/^\/project\/([a-f0-9]{24})(?:\/|$)/);
|
|
33915
|
+
if (!panelEl || editorMatch && isValidProjectId(editorMatch[1])) return;
|
|
33916
|
+
var previous = dashboardViewOptions();
|
|
33917
|
+
options2 = Object.assign({}, previous, options2 || {});
|
|
33918
|
+
var generation = ++dashboardRenderGeneration;
|
|
33919
|
+
panelEl.dataset.view = "recent-projects";
|
|
33750
33920
|
startRelativeTimeTicker();
|
|
33751
33921
|
var rootEl = ensureRecentProjectsRoot();
|
|
33752
|
-
if (!rootEl)
|
|
33753
|
-
return;
|
|
33754
|
-
}
|
|
33755
|
-
rootEl.innerHTML = "";
|
|
33756
|
-
rootEl.appendChild(renderWelcomeHeader());
|
|
33922
|
+
if (!rootEl) return;
|
|
33757
33923
|
var accountScopeId = (window.codexOverleafDeriveAccountScopeId || function() {
|
|
33758
33924
|
return null;
|
|
33759
33925
|
})();
|
|
33926
|
+
if (previous.accountScopeId !== accountScopeId) {
|
|
33927
|
+
options2.projectFilter = "";
|
|
33928
|
+
options2.showAll = options2.draftsOpen = false;
|
|
33929
|
+
}
|
|
33930
|
+
var projectFilter = isValidProjectId(options2.projectFilter) ? options2.projectFilter : "";
|
|
33931
|
+
rootEl.dataset.accountScopeId = accountScopeId || "";
|
|
33932
|
+
rootEl.dataset.projectFilter = projectFilter;
|
|
33933
|
+
rootEl.dataset.showAll = options2.showAll ? "true" : "false";
|
|
33934
|
+
rootEl.innerHTML = "";
|
|
33935
|
+
rootEl.appendChild(renderWelcomeHeader());
|
|
33760
33936
|
if (!accountScopeId) {
|
|
33761
33937
|
rootEl.appendChild(renderDegradedState());
|
|
33762
33938
|
rootEl.appendChild(renderSettingsEntry({ scope: "account" }));
|
|
33763
|
-
opportunisticEnrichmentFromDom().catch(function() {
|
|
33764
|
-
});
|
|
33765
33939
|
return;
|
|
33766
33940
|
}
|
|
33767
|
-
|
|
33768
|
-
|
|
33941
|
+
if (projectFilter) {
|
|
33942
|
+
var filterBar = createViewElement("div", "recent-projects-filter");
|
|
33943
|
+
var back = createViewButton(tr("recentProjects_allProjects"), function() {
|
|
33944
|
+
renderRecentProjectsVariant({ projectFilter: "", showAll: false, restoreScrollTop: 0 }).catch(function() {
|
|
33945
|
+
});
|
|
33946
|
+
});
|
|
33947
|
+
filterBar.appendChild(back);
|
|
33948
|
+
var filterName = textNode(projectDisplayName(projectFilter));
|
|
33949
|
+
filterName.title = filterName.textContent;
|
|
33950
|
+
filterBar.appendChild(filterName);
|
|
33951
|
+
rootEl.appendChild(filterBar);
|
|
33952
|
+
}
|
|
33953
|
+
var listContainer = createViewElement("div", "recent-projects-list");
|
|
33769
33954
|
listContainer.setAttribute("data-recent-projects-list", "");
|
|
33770
33955
|
rootEl.appendChild(listContainer);
|
|
33771
|
-
var
|
|
33772
|
-
|
|
33773
|
-
|
|
33774
|
-
|
|
33956
|
+
var loading = textNode(tr("recentProjects_loadingHistory"), "recent-projects-loading");
|
|
33957
|
+
listContainer.appendChild(loading);
|
|
33958
|
+
function stillCurrent() {
|
|
33959
|
+
return generation === dashboardRenderGeneration && getPanel() === panelEl && panelEl.dataset.view === "recent-projects" && rootEl.isConnected !== false && getCachedAccountScopeId() === accountScopeId;
|
|
33960
|
+
}
|
|
33961
|
+
var records;
|
|
33775
33962
|
try {
|
|
33776
33963
|
await loadProjectNameCacheFromStorage();
|
|
33964
|
+
records = await loadDashboardConversations(accountScopeId);
|
|
33777
33965
|
} catch (_error) {
|
|
33966
|
+
if (!stillCurrent()) return;
|
|
33967
|
+
loading.textContent = tr("recentProjects_loadFailed");
|
|
33968
|
+
var retry = createViewButton(tr("recentProjects_retryScope"), function() {
|
|
33969
|
+
renderRecentProjectsVariant(options2).catch(function() {
|
|
33970
|
+
});
|
|
33971
|
+
}, null, "recent-projects-show-all");
|
|
33972
|
+
listContainer.appendChild(retry);
|
|
33973
|
+
rootEl.appendChild(renderSettingsEntry({ scope: "account" }));
|
|
33974
|
+
return;
|
|
33778
33975
|
}
|
|
33779
|
-
|
|
33780
|
-
|
|
33781
|
-
var
|
|
33782
|
-
|
|
33783
|
-
|
|
33784
|
-
|
|
33785
|
-
|
|
33786
|
-
|
|
33787
|
-
|
|
33788
|
-
|
|
33976
|
+
if (!stillCurrent()) return;
|
|
33977
|
+
loading.remove();
|
|
33978
|
+
var validRecords = records.filter(function(record) {
|
|
33979
|
+
return isValidProjectId(record.projectId) && (!projectFilter || record.projectId === projectFilter);
|
|
33980
|
+
});
|
|
33981
|
+
var started = validRecords.filter(conversationHasContent);
|
|
33982
|
+
var unstarted = validRecords.filter(function(record) {
|
|
33983
|
+
return !conversationHasContent(record);
|
|
33984
|
+
});
|
|
33985
|
+
if (started.length) {
|
|
33986
|
+
listContainer.appendChild(renderProjectSessionRow(listContainer, started[0].projectId, started[0], { featured: true }));
|
|
33987
|
+
if (started.length > 1) {
|
|
33988
|
+
var heading = createViewElement("div", "recent-projects-history-heading");
|
|
33989
|
+
heading.appendChild(textNode(tr("recentProjects_historyHeading")));
|
|
33990
|
+
heading.appendChild(textNode(tr("recentProjects_historyHint")));
|
|
33991
|
+
listContainer.appendChild(heading);
|
|
33992
|
+
var historyList = createViewElement("div", "recent-projects-history-list");
|
|
33993
|
+
var history = options2.showAll ? started.slice(1) : started.slice(1, 10);
|
|
33994
|
+
history.forEach(function(record) {
|
|
33995
|
+
historyList.appendChild(renderProjectSessionRow(historyList, record.projectId, record));
|
|
33789
33996
|
});
|
|
33997
|
+
listContainer.appendChild(historyList);
|
|
33998
|
+
if (!options2.showAll && started.length > 10) {
|
|
33999
|
+
var more = createViewButton(tr("recentProjects_showAllConversations", { count: started.length }), function() {
|
|
34000
|
+
renderRecentProjectsVariant({ showAll: true }).catch(function() {
|
|
34001
|
+
});
|
|
34002
|
+
}, "data-recent-projects-show-all", "recent-projects-show-all");
|
|
34003
|
+
listContainer.appendChild(more);
|
|
34004
|
+
}
|
|
33790
34005
|
}
|
|
33791
|
-
} catch (_error) {
|
|
33792
|
-
rows = [];
|
|
33793
|
-
}
|
|
33794
|
-
listLoading.remove();
|
|
33795
|
-
var restoreExpanded = Array.isArray(options2 && options2.restoreExpanded) ? options2.restoreExpanded : [];
|
|
33796
|
-
var welcomeSubtitle = rootEl.querySelector(".recent-projects-welcome-subtitle");
|
|
33797
|
-
if (welcomeSubtitle && rows && rows.length) {
|
|
33798
|
-
var sessionTotal = 0;
|
|
33799
|
-
for (var st = 0; st < rows.length; st++) {
|
|
33800
|
-
sessionTotal += Number(rows[st].sessionCount) || 1;
|
|
33801
|
-
}
|
|
33802
|
-
welcomeSubtitle.textContent = tr("recentProjects_welcome_stats", {
|
|
33803
|
-
projects: rows.length,
|
|
33804
|
-
sessions: sessionTotal
|
|
33805
|
-
});
|
|
33806
|
-
}
|
|
33807
|
-
var hasMore = !showAll && rows && rows.length > pageLimit;
|
|
33808
|
-
var visibleRows = hasMore ? rows.slice(0, pageLimit) : rows;
|
|
33809
|
-
if (!visibleRows || !visibleRows.length) {
|
|
33810
|
-
listContainer.appendChild(renderEmptyState());
|
|
33811
34006
|
} else {
|
|
33812
|
-
|
|
33813
|
-
|
|
33814
|
-
|
|
33815
|
-
}
|
|
33816
|
-
if (
|
|
33817
|
-
|
|
33818
|
-
|
|
33819
|
-
|
|
33820
|
-
|
|
33821
|
-
|
|
33822
|
-
|
|
33823
|
-
|
|
34007
|
+
var empty = renderEmptyState();
|
|
34008
|
+
if (unstarted.length) empty.textContent = tr("recentProjects_noStarted");
|
|
34009
|
+
listContainer.appendChild(empty);
|
|
34010
|
+
}
|
|
34011
|
+
if (unstarted.length) {
|
|
34012
|
+
let populateDrafts = function() {
|
|
34013
|
+
if (draftsBuilt || !stillCurrent()) return;
|
|
34014
|
+
draftsBuilt = true;
|
|
34015
|
+
drafts.appendChild(textNode(tr("recentProjects_unstartedHint"), "recent-projects-drafts-hint"));
|
|
34016
|
+
unstarted.forEach(function(record) {
|
|
34017
|
+
drafts.appendChild(renderProjectSessionRow(drafts, record.projectId, record));
|
|
34018
|
+
});
|
|
34019
|
+
};
|
|
34020
|
+
var drafts = createViewElement("details", "recent-projects-drafts");
|
|
34021
|
+
drafts.setAttribute("data-unstarted-conversations", "");
|
|
34022
|
+
var summary = createViewElement("summary", "", tr("recentProjects_unstarted", { count: unstarted.length }));
|
|
34023
|
+
drafts.appendChild(summary);
|
|
34024
|
+
var draftsBuilt = false;
|
|
34025
|
+
drafts.addEventListener("toggle", function() {
|
|
34026
|
+
if (drafts.open) populateDrafts();
|
|
33824
34027
|
});
|
|
33825
|
-
listContainer.appendChild(
|
|
33826
|
-
|
|
33827
|
-
|
|
33828
|
-
|
|
33829
|
-
var toReopen = restoreExpanded.slice();
|
|
33830
|
-
if (expandProjectId && toReopen.indexOf(expandProjectId) === -1) {
|
|
33831
|
-
toReopen.push(expandProjectId);
|
|
33832
|
-
}
|
|
33833
|
-
for (var reopenIndex = 0; reopenIndex < toReopen.length; reopenIndex++) {
|
|
33834
|
-
var wrap = listContainer.querySelector('[data-project-row-wrap="' + toReopen[reopenIndex] + '"]');
|
|
33835
|
-
if (wrap) {
|
|
33836
|
-
toggleProjectSessions(wrap, toReopen[reopenIndex]);
|
|
34028
|
+
listContainer.appendChild(drafts);
|
|
34029
|
+
if (options2.draftsOpen) {
|
|
34030
|
+
drafts.open = true;
|
|
34031
|
+
populateDrafts();
|
|
33837
34032
|
}
|
|
33838
34033
|
}
|
|
33839
|
-
if (
|
|
33840
|
-
|
|
33841
|
-
|
|
33842
|
-
|
|
33843
|
-
|
|
33844
|
-
|
|
34034
|
+
if (!projectFilter) {
|
|
34035
|
+
var invalid = records.filter(function(record) {
|
|
34036
|
+
return !isValidProjectId(record.projectId);
|
|
34037
|
+
});
|
|
34038
|
+
var invalidIds = /* @__PURE__ */ new Set();
|
|
34039
|
+
if (invalid.length) listContainer.appendChild(textNode(tr("recentProjects_unavailableRecords"), "recent-projects-history-heading"));
|
|
34040
|
+
invalid.forEach(function(record) {
|
|
34041
|
+
var id = String(record.projectId || "");
|
|
34042
|
+
if (!invalidIds.has(id)) {
|
|
34043
|
+
invalidIds.add(id);
|
|
34044
|
+
listContainer.appendChild(renderRecentProjectRow({ projectId: record.projectId }));
|
|
34045
|
+
}
|
|
34046
|
+
});
|
|
33845
34047
|
}
|
|
34048
|
+
rootEl.appendChild(renderSettingsEntry({ scope: "account" }));
|
|
34049
|
+
if (Number.isFinite(options2.restoreScrollTop)) rootEl.scrollTop = options2.restoreScrollTop;
|
|
33846
34050
|
opportunisticEnrichmentFromDom().catch(function() {
|
|
33847
34051
|
});
|
|
33848
34052
|
}
|
|
33849
34053
|
function renderPerProjectVariant() {
|
|
34054
|
+
dashboardRenderGeneration++;
|
|
33850
34055
|
if (!getPanel()) {
|
|
33851
34056
|
return;
|
|
33852
34057
|
}
|
|
@@ -35956,11 +36161,12 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35956
36161
|
}
|
|
35957
36162
|
const requestId = ++storageUsageRequestId;
|
|
35958
36163
|
const projectId = getCurrentProjectId?.();
|
|
35959
|
-
const
|
|
36164
|
+
const settingsScope = getPanel?.()?.dataset?.settingsScope;
|
|
36165
|
+
const isCurrent = () => requestId === storageUsageRequestId && projectId === getCurrentProjectId?.() && settingsScope === getPanel?.()?.dataset?.settingsScope && getSettingsPanelInstance()?.container?.querySelector("[data-storage-usage]") === node;
|
|
35960
36166
|
const current = getState();
|
|
35961
36167
|
const sessionCount = Array.isArray(current?.sessions) ? current.sessions.length : 0;
|
|
35962
36168
|
const runCount = Array.isArray(current?.runs) ? current.runs.length : 0;
|
|
35963
|
-
const counts = tx(
|
|
36169
|
+
const counts = settingsScope === "account" ? tx("All projects in this browser", "\u5F53\u524D\u6D4F\u89C8\u5668\u4E2D\u7684\u6240\u6709\u9879\u76EE") : tx(
|
|
35964
36170
|
`${sessionCount} loaded session(s) in this project \xB7 ${runCount} run(s) in the active session`,
|
|
35965
36171
|
`\u5F53\u524D\u9879\u76EE\u5DF2\u52A0\u8F7D ${sessionCount} \u4E2A\u4F1A\u8BDD \xB7 \u5F53\u524D\u4F1A\u8BDD ${runCount} \u8F6E\u8FD0\u884C`
|
|
35966
36172
|
);
|
|
@@ -41583,6 +41789,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41583
41789
|
const urlProjectId = getCurrentProjectId();
|
|
41584
41790
|
const projectId = projectIdOverride || urlProjectId;
|
|
41585
41791
|
if (!projectId) {
|
|
41792
|
+
if (options2?.reviewRunIds?.length) throw new Error("Review persistence lost its project.");
|
|
41586
41793
|
return;
|
|
41587
41794
|
}
|
|
41588
41795
|
const liveRunView = readLiveRunViewForSaveStateGuard();
|
|
@@ -41591,6 +41798,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41591
41798
|
"Skipped saveState: run is in flight on a different project than the current URL; settlement owns persistence.",
|
|
41592
41799
|
"\u5DF2\u8DF3\u8FC7 saveState\uFF1A\u672C\u6B21\u8FD0\u884C\u6240\u5C5E\u9879\u76EE\u4E0E\u5F53\u524D URL \u4E0D\u4E00\u81F4\uFF0C\u5199\u56DE\u7531 settlement \u8D1F\u8D23\u3002"
|
|
41593
41800
|
));
|
|
41801
|
+
if (options2?.reviewRunIds?.length) throw new Error("Review persistence project changed.");
|
|
41594
41802
|
return;
|
|
41595
41803
|
}
|
|
41596
41804
|
const compactState = prepareStateForStorage(state, { onAggressive: notifyAggressiveCompactionOnce });
|
|
@@ -41608,6 +41816,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41608
41816
|
compactState: compactStateSnapshot,
|
|
41609
41817
|
projectId,
|
|
41610
41818
|
deletedSessionIds: options2?.deletedSessionIds,
|
|
41819
|
+
reviewRunIds: options2?.reviewRunIds,
|
|
41611
41820
|
Migration,
|
|
41612
41821
|
StorageDb,
|
|
41613
41822
|
SessionPersistence: Modules.SessionPersistence,
|
|
@@ -41633,17 +41842,17 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41633
41842
|
},
|
|
41634
41843
|
persistScopedState
|
|
41635
41844
|
);
|
|
41636
|
-
if (!committed.ok && (options2?.queueMutation || options2?.queueMutations?.length || committed.reason !== "stale_view")) {
|
|
41845
|
+
if (!committed.ok && (options2?.reviewRunIds?.length || options2?.queueMutation || options2?.queueMutations?.length || committed.reason !== "stale_view")) {
|
|
41637
41846
|
throw Object.assign(new Error(`Scoped persistence failed: ${committed.reason}`), {
|
|
41638
41847
|
code: committed.reason
|
|
41639
41848
|
});
|
|
41640
41849
|
}
|
|
41641
41850
|
}
|
|
41642
41851
|
} catch (error) {
|
|
41643
|
-
if (error?.code === "account_scope_unavailable" && !options2?.queueMutation && !(Array.isArray(options2?.queueMutations) && options2.queueMutations.length)) {
|
|
41852
|
+
if (error?.code === "account_scope_unavailable" && !options2?.reviewRunIds?.length && !options2?.queueMutation && !(Array.isArray(options2?.queueMutations) && options2.queueMutations.length)) {
|
|
41644
41853
|
return;
|
|
41645
41854
|
}
|
|
41646
|
-
if (options2?.queueMutation || options2?.queueMutations?.length) {
|
|
41855
|
+
if (options2?.reviewRunIds?.length || options2?.queueMutation || options2?.queueMutations?.length) {
|
|
41647
41856
|
throw error;
|
|
41648
41857
|
}
|
|
41649
41858
|
let fallbackError = null;
|
|
@@ -41742,6 +41951,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41742
41951
|
if (isStorageQuotaError(error)) {
|
|
41743
41952
|
emitStorageQuotaFailure(error, null);
|
|
41744
41953
|
}
|
|
41954
|
+
if (persistenceOptions?.reviewRunIds?.length) throw error;
|
|
41745
41955
|
appendPlainLog(tx(`Failed to save session state: ${formatStateSaveError(error)}`, `\u4FDD\u5B58\u4F1A\u8BDD\u72B6\u6001\u5931\u8D25\uFF1A${formatStateSaveError(error)}`));
|
|
41746
41956
|
}).finally(() => {
|
|
41747
41957
|
if (saveStateInFlightPromise === runPromise) {
|
|
@@ -41788,6 +41998,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41788
41998
|
...current || {},
|
|
41789
41999
|
...incoming,
|
|
41790
42000
|
queueMutation: void 0,
|
|
42001
|
+
reviewRunIds: Array.from(/* @__PURE__ */ new Set([...current?.reviewRunIds || [], ...incoming?.reviewRunIds || []])),
|
|
41791
42002
|
queueMutations,
|
|
41792
42003
|
deletedSessionIds: Array.from(/* @__PURE__ */ new Set([
|
|
41793
42004
|
...current?.deletedSessionIds || [],
|
|
@@ -42654,11 +42865,9 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42654
42865
|
status: "running",
|
|
42655
42866
|
detail: { [tr("detailWillUndo")]: trackedUndo ? formatTrackedChangeFiles(run.undoTrackedChanges) : formatTrackedUndoFiles(run) }
|
|
42656
42867
|
});
|
|
42657
|
-
let result;
|
|
42658
|
-
let trackedUndoPostFilesAtDispatch;
|
|
42659
42868
|
try {
|
|
42660
|
-
trackedUndoPostFilesAtDispatch = buildTrackedUndoPostFiles(run);
|
|
42661
|
-
result = await callPageBridge("rejectTrackedChanges", {
|
|
42869
|
+
const trackedUndoPostFilesAtDispatch = buildTrackedUndoPostFiles(run);
|
|
42870
|
+
const result = await callPageBridge("rejectTrackedChanges", {
|
|
42662
42871
|
trackedChanges: run.undoTrackedChanges || [],
|
|
42663
42872
|
expectedFiles: run.undoExpectedFiles || [],
|
|
42664
42873
|
postFiles: trackedUndoPostFilesAtDispatch,
|
|
@@ -42669,36 +42878,37 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42669
42878
|
// `aborted_project_changed` and the document is left untouched.
|
|
42670
42879
|
runProjectId: getRunProjectIdForWriteback(run)
|
|
42671
42880
|
});
|
|
42881
|
+
writebackOrchestrator.invalidateMirrorAfterUndo(runId, getRunProjectIdForWriteback(run), result);
|
|
42882
|
+
appendRunRecordEvent(runId, {
|
|
42883
|
+
title: trackedUndo ? tr("undoTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }) : tr("undoNativeResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42884
|
+
status: result.skipped?.length ? "failed" : "completed",
|
|
42885
|
+
detail: {
|
|
42886
|
+
[trackedUndo ? tr("detailRejected") : tr("detailUndone")]: (result.applied || []).map((item) => ({
|
|
42887
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42888
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42889
|
+
})),
|
|
42890
|
+
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42891
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42892
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42893
|
+
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42894
|
+
}))
|
|
42895
|
+
}
|
|
42896
|
+
});
|
|
42897
|
+
if (lifecycleReject) {
|
|
42898
|
+
WritebackSettlement.attachUndoNotVerifiedFailure(run, result, {
|
|
42899
|
+
buildFailure: buildContentFailure,
|
|
42900
|
+
postFiles: trackedUndoPostFilesAtDispatch
|
|
42901
|
+
});
|
|
42902
|
+
await applyTrackedChangeSettlement(runId, "reject", result);
|
|
42903
|
+
return;
|
|
42904
|
+
}
|
|
42905
|
+
applyLegacyUndoSettlement(runId, result.skipped?.length ? "partial" : "applied", result);
|
|
42672
42906
|
} finally {
|
|
42673
42907
|
if (lifecycleReject) {
|
|
42674
42908
|
trackedChangeInFlight.delete(runId);
|
|
42909
|
+
refreshRunCardControls(runId);
|
|
42675
42910
|
}
|
|
42676
42911
|
}
|
|
42677
|
-
writebackOrchestrator.invalidateMirrorAfterUndo(runId, getRunProjectIdForWriteback(run), result);
|
|
42678
|
-
appendRunRecordEvent(runId, {
|
|
42679
|
-
title: trackedUndo ? tr("undoTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }) : tr("undoNativeResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42680
|
-
status: result.skipped?.length ? "failed" : "completed",
|
|
42681
|
-
detail: {
|
|
42682
|
-
[trackedUndo ? tr("detailRejected") : tr("detailUndone")]: (result.applied || []).map((item) => ({
|
|
42683
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42684
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42685
|
-
})),
|
|
42686
|
-
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42687
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42688
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42689
|
-
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42690
|
-
}))
|
|
42691
|
-
}
|
|
42692
|
-
});
|
|
42693
|
-
if (lifecycleReject) {
|
|
42694
|
-
WritebackSettlement.attachUndoNotVerifiedFailure(run, result, {
|
|
42695
|
-
buildFailure: buildContentFailure,
|
|
42696
|
-
postFiles: trackedUndoPostFilesAtDispatch
|
|
42697
|
-
});
|
|
42698
|
-
applyTrackedChangeSettlement(runId, "reject", result);
|
|
42699
|
-
return;
|
|
42700
|
-
}
|
|
42701
|
-
applyLegacyUndoSettlement(runId, result.skipped?.length ? "partial" : "applied", result);
|
|
42702
42912
|
}
|
|
42703
42913
|
async function acceptRun(runId) {
|
|
42704
42914
|
const run = findRunRecord(runId);
|
|
@@ -42722,50 +42932,50 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42722
42932
|
status: "running",
|
|
42723
42933
|
detail: { [tr("detailAccepted")]: formatTrackedChangeFiles(run.undoTrackedChanges) }
|
|
42724
42934
|
});
|
|
42725
|
-
let result;
|
|
42726
42935
|
try {
|
|
42727
|
-
result = await callPageBridge("acceptTrackedChanges", {
|
|
42936
|
+
const result = await callPageBridge("acceptTrackedChanges", {
|
|
42728
42937
|
trackedChanges: run.undoTrackedChanges || [],
|
|
42729
42938
|
expectedFiles: run.undoExpectedFiles || [],
|
|
42730
42939
|
postFiles: buildTrackedUndoPostFiles(run),
|
|
42731
42940
|
appliedOperations: Array.isArray(run.appliedOperations) ? run.appliedOperations : [],
|
|
42732
42941
|
runProjectId: getRunProjectIdForWriteback(run)
|
|
42733
42942
|
});
|
|
42734
|
-
|
|
42735
|
-
trackedChangeInFlight.delete(runId);
|
|
42736
|
-
}
|
|
42737
|
-
appendAcceptDiagnosticEvents(runId, Array.isArray(result.diagnostics) ? result.diagnostics : []);
|
|
42738
|
-
appendRunRecordEvent(runId, {
|
|
42739
|
-
title: tr("runAcceptTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42740
|
-
status: result.skipped?.length ? "failed" : "completed",
|
|
42741
|
-
detail: {
|
|
42742
|
-
[tr("detailAccepted")]: (result.applied || []).map((item) => ({
|
|
42743
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42744
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42745
|
-
})),
|
|
42746
|
-
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42747
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42748
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42749
|
-
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42750
|
-
}))
|
|
42751
|
-
}
|
|
42752
|
-
});
|
|
42753
|
-
if (result.ok === false) {
|
|
42943
|
+
appendAcceptDiagnosticEvents(runId, Array.isArray(result.diagnostics) ? result.diagnostics : []);
|
|
42754
42944
|
appendRunRecordEvent(runId, {
|
|
42755
|
-
title: tr("
|
|
42756
|
-
status: "failed",
|
|
42945
|
+
title: tr("runAcceptTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42946
|
+
status: result.skipped?.length ? "failed" : "completed",
|
|
42757
42947
|
detail: {
|
|
42758
|
-
[tr("
|
|
42948
|
+
[tr("detailAccepted")]: (result.applied || []).map((item) => ({
|
|
42949
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42950
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42951
|
+
})),
|
|
42952
|
+
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42953
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42954
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42955
|
+
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42956
|
+
}))
|
|
42759
42957
|
}
|
|
42760
42958
|
});
|
|
42761
|
-
if (
|
|
42762
|
-
|
|
42959
|
+
if (result.ok === false) {
|
|
42960
|
+
appendRunRecordEvent(runId, {
|
|
42961
|
+
title: tr("runAcceptTrackedFailed"),
|
|
42962
|
+
status: "failed",
|
|
42963
|
+
detail: {
|
|
42964
|
+
[tr("detailReason")]: tr("runAcceptTrackedFailedReason")
|
|
42965
|
+
}
|
|
42966
|
+
});
|
|
42967
|
+
if (!WritebackSettlement.isSuccessfulTrackedChangeSettlement(result)) {
|
|
42968
|
+
refreshRunCardControls(runId);
|
|
42969
|
+
}
|
|
42763
42970
|
}
|
|
42971
|
+
WritebackSettlement.attachAcceptNotVerifiedFailure(run, result, {
|
|
42972
|
+
buildFailure: buildContentFailure
|
|
42973
|
+
});
|
|
42974
|
+
await applyTrackedChangeSettlement(runId, "accept", result);
|
|
42975
|
+
} finally {
|
|
42976
|
+
trackedChangeInFlight.delete(runId);
|
|
42977
|
+
refreshRunCardControls(runId);
|
|
42764
42978
|
}
|
|
42765
|
-
WritebackSettlement.attachAcceptNotVerifiedFailure(run, result, {
|
|
42766
|
-
buildFailure: buildContentFailure
|
|
42767
|
-
});
|
|
42768
|
-
applyTrackedChangeSettlement(runId, "accept", result);
|
|
42769
42979
|
}
|
|
42770
42980
|
function getRunProjectIdForWriteback(run) {
|
|
42771
42981
|
return typeof run?.runProjectId === "string" && run.runProjectId ? run.runProjectId : "";
|
|
@@ -42796,7 +43006,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42796
43006
|
FailureReasons
|
|
42797
43007
|
);
|
|
42798
43008
|
}
|
|
42799
|
-
function applyTrackedChangeSettlement(runId, kind, result) {
|
|
43009
|
+
async function applyTrackedChangeSettlement(runId, kind, result) {
|
|
42800
43010
|
const run = findRunRecord(runId);
|
|
42801
43011
|
const settlement = WritebackSettlement.settleTrackedChangeLifecycle({
|
|
42802
43012
|
kind,
|
|
@@ -42805,12 +43015,14 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42805
43015
|
failureReasons: FailureReasons
|
|
42806
43016
|
});
|
|
42807
43017
|
if (settlement.decision === "blocked") {
|
|
42808
|
-
refreshRunCardControls(runId);
|
|
42809
43018
|
return;
|
|
42810
43019
|
}
|
|
42811
|
-
|
|
42812
|
-
|
|
42813
|
-
|
|
43020
|
+
await Modules.ScopedPersistenceCoordinator.applyReviewTransition({
|
|
43021
|
+
getState: () => state,
|
|
43022
|
+
runId,
|
|
43023
|
+
transition: WritebackSettlement.applySettlementTransition(run, settlement),
|
|
43024
|
+
persist: flushQueuedSaveState
|
|
43025
|
+
});
|
|
42814
43026
|
}
|
|
42815
43027
|
function getRunUndoCount(run) {
|
|
42816
43028
|
if (!run) {
|