codex-overleaf-link 2.4.0 → 2.5.0
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 +272 -311
- package/README.zh-CN.md +287 -326
- package/extension/bootstrap/background.js +47 -10
- package/extension/bootstrap/manifest.template.json +9 -4
- package/extension/bootstrap/popup.html +10 -16
- package/extension/bootstrap/update.js +25 -2
- package/extension/runtime-manifest.json +3 -1
- package/extension/src/background.js +28 -3
- package/extension/src/backgroundSharedSessions.js +380 -0
- package/extension/src/backgroundUpdateCoordinator.js +442 -379
- package/extension/src/content/activeTurnControl.js +8 -0
- package/extension/src/content/assetTransferBroker.js +186 -12
- package/extension/src/content/changeHistoryView.js +175 -0
- package/extension/src/content/composerAttachments.js +24 -22
- package/extension/src/content/composerPanel.js +23 -8
- package/extension/src/content/contentRuntime.js +572 -571
- package/extension/src/content/diagnosticsController.js +1 -2
- package/extension/src/content/diagnosticsExport.js +222 -0
- package/extension/src/content/diagnosticsPanel.js +48 -19
- package/extension/src/content/diffReviewPanel.js +8 -5
- package/extension/src/content/generated/content.bundle.js +8974 -1781
- package/extension/src/content/generated/content.bundle.meta.json +22 -3
- package/extension/src/content/legacyGlobalRegistry.js +19 -1
- package/extension/src/content/localSkillsPanel.js +42 -7
- package/extension/src/content/markdownDomRenderer.js +9 -4
- package/extension/src/content/modelPicker.js +1 -1
- package/extension/src/content/pageBridgeClient.js +18 -3
- package/extension/src/content/panelMaintenance.js +51 -120
- package/extension/src/content/panelRenderer.js +4 -0
- package/extension/src/content/pendingInputView.js +109 -76
- package/extension/src/content/providerSettingsCoordinator.js +17 -6
- package/extension/src/content/providerSettingsDialog.js +661 -108
- package/extension/src/content/recentProjects.js +364 -356
- package/extension/src/content/runActivitySummary.js +631 -0
- package/extension/src/content/runController.js +3 -1
- package/extension/src/content/runFailureNotice.js +14 -1
- package/extension/src/content/runGuidanceController.js +4 -3
- package/extension/src/content/runPresence.js +306 -0
- package/extension/src/content/runQueueScheduler.js +2 -1
- package/extension/src/content/runResultActions.js +123 -3
- package/extension/src/content/runTimelineView.js +194 -164
- package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
- package/extension/src/content/scopedPersistencePanelState.js +45 -2
- package/extension/src/content/selectionContextView.js +300 -0
- package/extension/src/content/sessionPersistence.js +10 -2
- package/extension/src/content/settingsPanel.js +93 -54
- package/extension/src/content/settingsWorkbench.js +374 -0
- package/extension/src/content/sharedSessionViewSync.js +72 -0
- package/extension/src/content/subagentActivityView.js +195 -0
- package/extension/src/content/trackedChangeCaptureController.js +7 -3
- package/extension/src/content/updateNotice.js +121 -50
- package/extension/src/content/writebackController.js +257 -0
- package/extension/src/content/writebackOrchestrator.js +146 -141
- package/extension/src/content/writebackPlan.js +231 -0
- package/extension/src/content/writebackRecovery.js +122 -0
- package/extension/src/content/writingStyleSettings.js +576 -0
- package/extension/src/content/writtenChangesView.js +152 -0
- package/extension/src/page/binaryAssetUploader.js +97 -19
- package/extension/src/page/overleafProjectSnapshot.js +1 -0
- package/extension/src/page/referenceProjects.js +148 -0
- package/extension/src/page/saveState.js +58 -3
- package/extension/src/page/snapshotRouter.js +44 -13
- package/extension/src/page/textCoordinates.js +102 -0
- package/extension/src/page/textFileCreator.js +350 -59
- package/extension/src/page/trackedChangeCapture.js +42 -56
- package/extension/src/page/trackedChangeOwnership.js +198 -0
- package/extension/src/page/trackedChangeReplay.js +164 -0
- package/extension/src/page/trackedChangesLifecycle.js +139 -150
- package/extension/src/page/treeOperations.js +36 -29
- package/extension/src/page/writebackReceiptJournal.js +112 -0
- package/extension/src/page/writebackRouter.js +176 -136
- package/extension/src/pageBridge.js +59 -101
- package/extension/src/popup.js +203 -59
- package/extension/src/shared/agentTranscript.js +18 -4
- package/extension/src/shared/auditRecords.js +71 -0
- package/extension/src/shared/changeHistoryModel.js +94 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/compileAdapter.js +42 -0
- package/extension/src/shared/failureReasons.js +20 -0
- package/extension/src/shared/globalPreferences.js +1 -1
- package/extension/src/shared/i18n.js +187 -65
- package/extension/src/shared/managedUpdateProjection.js +6 -3
- package/extension/src/shared/pageRpcContract.js +7 -1
- package/extension/src/shared/providerProfiles.js +109 -0
- package/extension/src/shared/runActivityModel.js +361 -0
- package/extension/src/shared/runExecutionSnapshot.js +8 -2
- package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
- package/extension/src/shared/selectionContext.js +28 -0
- package/extension/src/shared/sessionState.js +97 -6
- package/extension/src/shared/sharedSessionBridge.js +288 -0
- package/extension/src/shared/storageDb.js +23 -55
- package/extension/src/shared/storageMigration.js +3 -0
- package/extension/src/shared/storageRunActions.js +54 -4
- package/extension/src/shared/storageValuePruning.js +40 -0
- package/extension/src/shared/subagentActivityModel.js +174 -0
- package/extension/src/shared/undoOperations.js +87 -0
- package/extension/src/shared/updateConsent.js +37 -8
- package/extension/src/shared/writebackIntent.js +62 -0
- package/extension/src/shared/writebackSettlement.js +29 -10
- package/extension/src/shared/writingStyle.js +33 -0
- package/extension/styles/panel.css +2136 -744
- package/extension/styles/popup.css +110 -0
- package/native-host/src/anthropicBridgeRequest.js +2 -1
- package/native-host/src/codexModelRecovery.js +107 -0
- package/native-host/src/codexPromptAssembly.js +2 -0
- package/native-host/src/codexProviderLaunch.js +3 -3
- package/native-host/src/codexRuntimeIdentity.js +1 -0
- package/native-host/src/codexSessionRunner.js +146 -177
- package/native-host/src/codexSessionTiming.js +71 -0
- package/native-host/src/managedInstall.js +5 -4
- package/native-host/src/nativeEnvironment.js +70 -0
- package/native-host/src/nativeQuotas.js +15 -8
- package/native-host/src/overleafWorkspaceRules.js +16 -0
- package/native-host/src/processStopBarrier.js +80 -0
- package/native-host/src/providerModelCatalog.js +4 -3
- package/native-host/src/providerProfile.js +13 -1
- package/native-host/src/providerReasoning.js +9 -5
- package/native-host/src/providerStore.js +4 -0
- package/native-host/src/readProgressGuard.js +84 -17
- package/native-host/src/releaseTransport.js +14 -5
- package/native-host/src/selectionScope.js +58 -0
- package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
- package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
- package/native-host/src/subagentBroker.js +102 -98
- package/native-host/src/subagentTelemetry.js +316 -0
- package/native-host/src/subagentWorkspace.js +103 -0
- package/native-host/src/subagentWorkspacePath.js +31 -0
- package/native-host/src/taskRunnerRuntime.js +55 -5
- package/native-host/src/turnAttachments.js +113 -0
- package/native-host/src/updateManager.js +122 -12
- package/native-host/src/updateNetworkControl.js +75 -0
- package/native-host/src/updateTrust.js +21 -2
- package/native-host/src/vendor/pdfjs/LICENSE +177 -0
- package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
- package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
- package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/native-host/src/writingStyleEvidence.js +102 -0
- package/native-host/src/writingStylePdfWorker.js +35 -0
- package/native-host/src/writingStyleProfile.js +165 -0
- package/native-host/src/writingStyleRuntime.js +447 -0
- package/package.json +1 -1
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
// (the row renderer is sync). The async loader populates this on panel
|
|
35
35
|
// mount and on each opportunistic enrichment call.
|
|
36
36
|
let projectNameCacheMirror = {};
|
|
37
|
+
let dashboardRenderGeneration = 0;
|
|
37
38
|
|
|
38
39
|
function loadProjectNameCacheFromStorage() {
|
|
39
40
|
return new Promise(function (resolve) {
|
|
@@ -140,7 +141,7 @@
|
|
|
140
141
|
// If the variant is currently visible, refresh row names in place.
|
|
141
142
|
var visibleList = getPanel() && getPanel().querySelector('[data-recent-projects-list]');
|
|
142
143
|
if (visibleList) {
|
|
143
|
-
var rows = visibleList.querySelectorAll('[data-
|
|
144
|
+
var rows = visibleList.querySelectorAll('[data-project-id]');
|
|
144
145
|
for (var k = 0; k < rows.length; k++) {
|
|
145
146
|
var row = rows[k];
|
|
146
147
|
var rowPid = row.getAttribute('data-project-id');
|
|
@@ -149,6 +150,7 @@
|
|
|
149
150
|
var cached = lookupProjectName(rowPid);
|
|
150
151
|
if (cached) {
|
|
151
152
|
nameEl.textContent = cached;
|
|
153
|
+
nameEl.title = cached;
|
|
152
154
|
}
|
|
153
155
|
}
|
|
154
156
|
}
|
|
@@ -229,64 +231,55 @@
|
|
|
229
231
|
var hr = Math.round(min / 60);
|
|
230
232
|
if (hr < 24) return tx(hr + ' hr ago', hr + ' 小时前');
|
|
231
233
|
var day = Math.round(hr / 24);
|
|
232
|
-
if (day < 30) return tx(day + ' day ago', day + ' 天前');
|
|
234
|
+
if (day < 30) return tx(day + (day === 1 ? ' day ago' : ' days ago'), day + ' 天前');
|
|
233
235
|
var month = Math.round(day / 30);
|
|
234
236
|
if (month < 12) return tx(month + ' mo ago', month + ' 个月前');
|
|
235
237
|
var year = Math.round(month / 12);
|
|
236
238
|
return tx(year + ' yr ago', year + ' 年前');
|
|
237
239
|
}
|
|
238
240
|
|
|
239
|
-
function
|
|
240
|
-
var el = document.createElement(
|
|
241
|
-
if (className)
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
el.textContent = text == null ? '' : String(text);
|
|
241
|
+
function createViewElement(tag, className, text) {
|
|
242
|
+
var el = document.createElement(tag);
|
|
243
|
+
if (className) el.className = className;
|
|
244
|
+
if (text !== undefined) el.textContent = text;
|
|
245
245
|
return el;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
function
|
|
249
|
-
var
|
|
250
|
-
|
|
248
|
+
function createViewButton(label, onClick, attribute, className) {
|
|
249
|
+
var button = createViewElement('button', className, label);
|
|
250
|
+
button.type = 'button';
|
|
251
|
+
if (attribute) button.setAttribute(attribute, '');
|
|
252
|
+
if (onClick) button.addEventListener('click', onClick);
|
|
253
|
+
return button;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function textNode(text, className) {
|
|
257
|
+
return createViewElement('span', className, text == null ? '' : String(text));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function renderWelcomeHeader() {
|
|
261
|
+
var el = createViewElement('div', 'recent-projects-welcome');
|
|
251
262
|
el.setAttribute('data-recent-projects-welcome', '');
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
var subtitle = document.createElement('div');
|
|
256
|
-
subtitle.className = 'recent-projects-welcome-subtitle';
|
|
257
|
-
// v1.8.1: the most expensive spot on the first screen now carries a
|
|
258
|
-
// glanceable summary instead of boilerplate once the rows are known.
|
|
259
|
-
subtitle.textContent = stats && stats.projectCount
|
|
260
|
-
? tr('recentProjects_welcome_stats', { projects: stats.projectCount, sessions: stats.sessionTotal })
|
|
261
|
-
: tr('recentProjects_welcome_subtitle');
|
|
262
|
-
el.appendChild(title);
|
|
263
|
-
el.appendChild(subtitle);
|
|
263
|
+
el.appendChild(textNode('CODEX', 'recent-projects-eyebrow'));
|
|
264
|
+
el.appendChild(textNode(tr('recentProjects_welcome'), 'recent-projects-welcome-title'));
|
|
265
|
+
el.appendChild(textNode(tr('recentProjects_welcome_subtitle'), 'recent-projects-welcome-subtitle'));
|
|
264
266
|
return el;
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
function renderEmptyState() {
|
|
268
|
-
var el =
|
|
269
|
-
el.className = 'recent-projects-empty';
|
|
270
|
+
var el = createViewElement('div', 'recent-projects-empty', tr('recentProjects_empty'));
|
|
270
271
|
el.setAttribute('data-recent-projects-empty', '');
|
|
271
|
-
el.textContent = tr('recentProjects_empty');
|
|
272
272
|
return el;
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
function renderDegradedState() {
|
|
276
|
-
var el =
|
|
277
|
-
el.className = 'recent-projects-degraded';
|
|
276
|
+
var el = createViewElement('div', 'recent-projects-degraded');
|
|
278
277
|
el.setAttribute('data-recent-projects-degraded', '');
|
|
279
278
|
// v1.8.1: the user IS signed in on /project — telling them to sign in
|
|
280
279
|
// was a dead end. Explain the real condition and offer a retry.
|
|
281
|
-
var hint =
|
|
282
|
-
hint.textContent = tr('recentProjects_degraded_hint');
|
|
280
|
+
var hint = createViewElement('div', '', tr('recentProjects_degraded_hint'));
|
|
283
281
|
el.appendChild(hint);
|
|
284
|
-
var retry =
|
|
285
|
-
retry.type = 'button';
|
|
286
|
-
retry.className = 'recent-projects-show-all';
|
|
287
|
-
retry.setAttribute('data-recent-projects-retry', '');
|
|
288
|
-
retry.textContent = tr('recentProjects_retryScope');
|
|
289
|
-
retry.addEventListener('click', function () {
|
|
282
|
+
var retry = createViewButton(tr('recentProjects_retryScope'), function () {
|
|
290
283
|
if (typeof refreshAccountScopeId === 'function') {
|
|
291
284
|
Promise.resolve(refreshAccountScopeId())
|
|
292
285
|
.then(function () { return renderRecentProjectsVariant(); })
|
|
@@ -294,7 +287,7 @@
|
|
|
294
287
|
} else {
|
|
295
288
|
renderRecentProjectsVariant();
|
|
296
289
|
}
|
|
297
|
-
});
|
|
290
|
+
}, 'data-recent-projects-retry', 'recent-projects-show-all');
|
|
298
291
|
el.appendChild(retry);
|
|
299
292
|
return el;
|
|
300
293
|
}
|
|
@@ -304,18 +297,11 @@
|
|
|
304
297
|
// skills tied to projects, custom instructions, project diagnostics).
|
|
305
298
|
function renderSettingsEntry(options) {
|
|
306
299
|
var scope = options && options.scope === 'account' ? 'account' : 'project';
|
|
307
|
-
var entry =
|
|
308
|
-
entry.type = 'button';
|
|
309
|
-
entry.className = 'recent-projects-settings-entry';
|
|
310
|
-
entry.setAttribute('data-recent-projects-settings-entry', '');
|
|
311
|
-
entry.setAttribute('data-settings-scope', scope);
|
|
312
|
-
var label = document.createElement('span');
|
|
313
|
-
label.className = 'recent-projects-settings-entry-label';
|
|
314
|
-
label.textContent = tr('recentProjects_settings_entry');
|
|
315
|
-
entry.appendChild(label);
|
|
316
|
-
entry.addEventListener('click', function () {
|
|
300
|
+
var entry = createViewButton(undefined, function () {
|
|
317
301
|
openSettingsInScope(scope);
|
|
318
|
-
});
|
|
302
|
+
}, 'data-recent-projects-settings-entry', 'recent-projects-settings-entry');
|
|
303
|
+
entry.setAttribute('data-settings-scope', scope);
|
|
304
|
+
entry.appendChild(textNode(tr('recentProjects_settings_entry'), 'recent-projects-settings-entry-label'));
|
|
319
305
|
return entry;
|
|
320
306
|
}
|
|
321
307
|
|
|
@@ -360,10 +346,8 @@
|
|
|
360
346
|
? status
|
|
361
347
|
: 'pending';
|
|
362
348
|
var cls = STATUS_BADGE_CLASS[safeStatus];
|
|
363
|
-
var el =
|
|
364
|
-
el.className = 'recent-projects-row-badge ' + cls;
|
|
349
|
+
var el = textNode(tr('recentProjects_badge_' + safeStatus), 'recent-projects-row-badge ' + cls);
|
|
365
350
|
el.setAttribute('data-status', safeStatus);
|
|
366
|
-
el.textContent = tr('recentProjects_badge_' + safeStatus);
|
|
367
351
|
return el;
|
|
368
352
|
}
|
|
369
353
|
|
|
@@ -375,128 +359,156 @@
|
|
|
375
359
|
if (!isValidProjectId(projectId)) {
|
|
376
360
|
return;
|
|
377
361
|
}
|
|
378
|
-
|
|
362
|
+
var origin = 'https://www.overleaf.com';
|
|
363
|
+
try {
|
|
364
|
+
var current = new URL(window.location.href);
|
|
365
|
+
if (current.protocol === 'https:' && !current.port
|
|
366
|
+
&& ['overleaf.com', 'www.overleaf.com', 'cn.overleaf.com'].includes(current.hostname)) {
|
|
367
|
+
origin = current.origin;
|
|
368
|
+
}
|
|
369
|
+
} catch (_error) { /* Non-page callers retain the canonical fallback. */ }
|
|
370
|
+
window.location.assign(origin + '/project/' + encodeURIComponent(projectId));
|
|
379
371
|
}
|
|
380
372
|
|
|
381
|
-
function
|
|
382
|
-
var
|
|
383
|
-
var
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
el.appendChild(rowTime);
|
|
405
|
-
// v1.8.2: the session count lives in the row meta, matching its type
|
|
406
|
-
// scale, instead of inflating the expand toggle.
|
|
407
|
-
var sessionCount = Number(row && row.sessionCount) || 0;
|
|
408
|
-
if (sessionCount > 1) {
|
|
409
|
-
el.appendChild(textNode(tr('recentProjects_sessionsCount', { count: sessionCount }), 'recent-projects-row-sessions'));
|
|
410
|
-
}
|
|
411
|
-
el.appendChild(renderStatusBadge(settleDashboardRunStatus(row && row.primaryStatusBadge, row && row.lastActivityAt)));
|
|
412
|
-
if (valid) {
|
|
413
|
-
el.addEventListener('click', function () {
|
|
414
|
-
openProjectFromRow(projectId);
|
|
415
|
-
});
|
|
416
|
-
} else {
|
|
417
|
-
el.appendChild(textNode(tr('recentProjects_row_projectLinkUnavailable'), 'recent-projects-row-warning'));
|
|
418
|
-
}
|
|
419
|
-
if (!valid) {
|
|
420
|
-
var deadWrap = document.createElement('div');
|
|
421
|
-
deadWrap.className = 'recent-projects-row-wrap';
|
|
422
|
-
var deadHead = document.createElement('div');
|
|
423
|
-
deadHead.className = 'recent-projects-row-head';
|
|
424
|
-
var cleanup = document.createElement('button');
|
|
425
|
-
cleanup.type = 'button';
|
|
426
|
-
cleanup.className = 'recent-projects-row-cleanup';
|
|
427
|
-
cleanup.setAttribute('data-row-cleanup', '');
|
|
428
|
-
cleanup.title = tr('recentProjects_cleanup');
|
|
429
|
-
cleanup.setAttribute('aria-label', tr('recentProjects_cleanup'));
|
|
430
|
-
cleanup.textContent = '×';
|
|
431
|
-
cleanup.addEventListener('click', function () {
|
|
432
|
-
cleanupDeadProjectEntry(projectId).catch(function () { /* swallow */ });
|
|
433
|
-
});
|
|
434
|
-
deadHead.appendChild(el);
|
|
435
|
-
deadHead.appendChild(cleanup);
|
|
436
|
-
deadWrap.appendChild(deadHead);
|
|
437
|
-
return deadWrap;
|
|
438
|
-
}
|
|
439
|
-
var wrap = document.createElement('div');
|
|
440
|
-
wrap.className = 'recent-projects-row-wrap';
|
|
441
|
-
wrap.setAttribute('data-project-row-wrap', projectId);
|
|
442
|
-
var expand = document.createElement('button');
|
|
443
|
-
expand.type = 'button';
|
|
444
|
-
expand.className = 'recent-projects-row-expand';
|
|
445
|
-
expand.setAttribute('data-row-expand', '');
|
|
446
|
-
expand.setAttribute('aria-expanded', 'false');
|
|
447
|
-
// v1.8.1 a11y: tie the toggle to the container it reveals.
|
|
448
|
-
var sessionsElId = 'codex-project-sessions-' + String(projectId || '').slice(0, 24);
|
|
449
|
-
expand.setAttribute('aria-controls', sessionsElId);
|
|
450
|
-
expand.title = tr('recentProjects_sessions_toggle');
|
|
451
|
-
expand.setAttribute('aria-label', tr('recentProjects_sessions_toggle'));
|
|
452
|
-
expand.textContent = tr('recentProjects_sessions_action');
|
|
453
|
-
var head = document.createElement('div');
|
|
454
|
-
head.className = 'recent-projects-row-head';
|
|
455
|
-
var clear = document.createElement('button');
|
|
456
|
-
clear.type = 'button';
|
|
457
|
-
clear.className = 'recent-projects-row-clear';
|
|
458
|
-
clear.setAttribute('data-project-clear', '');
|
|
459
|
-
clear.title = tr('recentProjects_clearProject');
|
|
460
|
-
clear.setAttribute('aria-label', tr('recentProjects_clearProject'));
|
|
461
|
-
clear.textContent = '×';
|
|
462
|
-
clear.addEventListener('click', function (event) {
|
|
463
|
-
event.stopPropagation();
|
|
464
|
-
projectSessionCleanup.clearProjectSessions(projectId, name).catch(function () { /* surfaced by the action */ });
|
|
373
|
+
function renderActionsMenu(buttons) {
|
|
374
|
+
var menu = createViewElement('details', 'recent-projects-menu');
|
|
375
|
+
var trigger = createViewElement('summary', '', '\u22ef');
|
|
376
|
+
trigger.title = tr('recentProjects_more');
|
|
377
|
+
trigger.setAttribute('aria-label', tr('recentProjects_more'));
|
|
378
|
+
var actions = document.createElement('div');
|
|
379
|
+
actions.setAttribute('data-recent-menu-actions', '');
|
|
380
|
+
buttons.forEach(function (button) { actions.appendChild(button); });
|
|
381
|
+
actions.addEventListener('click', function (event) {
|
|
382
|
+
if (event.target.closest('button')) {
|
|
383
|
+
menu.open = false;
|
|
384
|
+
trigger.focus();
|
|
385
|
+
}
|
|
386
|
+
}, true);
|
|
387
|
+
menu.appendChild(trigger);
|
|
388
|
+
menu.appendChild(actions);
|
|
389
|
+
menu.addEventListener('keydown', function (event) {
|
|
390
|
+
if (event.key === 'Escape') {
|
|
391
|
+
event.preventDefault();
|
|
392
|
+
event.stopPropagation();
|
|
393
|
+
menu.open = false;
|
|
394
|
+
trigger.focus();
|
|
395
|
+
}
|
|
465
396
|
});
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
head.appendChild(clear);
|
|
469
|
-
var sessionsEl = document.createElement('div');
|
|
470
|
-
sessionsEl.className = 'recent-projects-sessions';
|
|
471
|
-
sessionsEl.setAttribute('data-project-sessions', '');
|
|
472
|
-
sessionsEl.id = sessionsElId;
|
|
473
|
-
sessionsEl.setAttribute('role', 'region');
|
|
474
|
-
sessionsEl.setAttribute('aria-label', tr('recentProjects_sessions_toggle'));
|
|
475
|
-
sessionsEl.hidden = true;
|
|
476
|
-
expand.addEventListener('click', function () {
|
|
477
|
-
toggleProjectSessions(wrap, projectId);
|
|
397
|
+
menu.addEventListener('focusout', function (event) {
|
|
398
|
+
if (event.relatedTarget && !menu.contains(event.relatedTarget)) menu.open = false;
|
|
478
399
|
});
|
|
479
|
-
|
|
480
|
-
wrap.appendChild(sessionsEl);
|
|
481
|
-
return wrap;
|
|
400
|
+
return menu;
|
|
482
401
|
}
|
|
483
402
|
|
|
484
|
-
function
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
403
|
+
function conversationActivity(record) {
|
|
404
|
+
return String(record && (record.lastActivityAt || record.updatedAt || record.createdAt) || '');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function conversationHasContent(record) {
|
|
408
|
+
return ['runs', 'history', 'pendingInputs'].some(function (key) {
|
|
409
|
+
return Array.isArray(record[key]) && record[key].length > 0;
|
|
410
|
+
}) || ['task', 'safeTaskSummary', 'codexThreadId'].some(function (key) {
|
|
411
|
+
return typeof record[key] === 'string' && Boolean(record[key].trim());
|
|
412
|
+
}) || (record.titleSource === 'manual' && typeof record.title === 'string' && Boolean(record.title.trim()));
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function conversationStatus(record) {
|
|
416
|
+
if (!StorageDb || !Array.isArray(record.runs) || !record.runs.length) return '';
|
|
417
|
+
return settleDashboardRunStatus(StorageDb.derivePrimaryStatusBadge(record), conversationActivity(record));
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function projectDisplayName(projectId) {
|
|
421
|
+
return lookupProjectName(projectId) || (isValidProjectId(projectId)
|
|
422
|
+
? tr('recentProjects_unnamed', { prefix: projectId.slice(0, 8) })
|
|
423
|
+
: tr('recentProjects_row_projectLinkUnavailable'));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
async function loadDashboardConversations(scope) {
|
|
427
|
+
if (!scope || !StorageDb) throw new Error('Conversation storage is unavailable.');
|
|
428
|
+
var results = await Promise.all([StorageDb.getAllSessions(), SessionPersistence.loadTombstones()]);
|
|
429
|
+
var records = results[0];
|
|
430
|
+
var deletedByProject = results[1] || {};
|
|
431
|
+
if (!Array.isArray(records)) throw new Error('Conversation history could not be read.');
|
|
432
|
+
return records.filter(function (record) {
|
|
433
|
+
if (!record || typeof record.id !== 'string' || !record.id || record.accountScopeUnavailable === true) return false;
|
|
434
|
+
var deletedIds = Object.prototype.hasOwnProperty.call(deletedByProject, record.projectId)
|
|
435
|
+
? deletedByProject[record.projectId] : [];
|
|
436
|
+
return SessionPersistence.isVisibleRecord(record, Array.isArray(deletedIds) ? deletedIds : [], scope);
|
|
437
|
+
}).sort(function (a, b) {
|
|
438
|
+
var aTime = Date.parse(conversationActivity(a)) || 0;
|
|
439
|
+
var bTime = Date.parse(conversationActivity(b)) || 0;
|
|
440
|
+
return bTime - aTime || String(a.id).localeCompare(String(b.id));
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function dashboardViewOptions() {
|
|
445
|
+
var root = getPanel() && getPanel().querySelector('[data-recent-projects-root]');
|
|
446
|
+
var drafts = root && root.querySelector('[data-unstarted-conversations]');
|
|
447
|
+
return {
|
|
448
|
+
accountScopeId: root && root.dataset.accountScopeId || '',
|
|
449
|
+
projectFilter: root && root.dataset.projectFilter || '',
|
|
450
|
+
showAll: Boolean(root && root.dataset.showAll === 'true'),
|
|
451
|
+
draftsOpen: Boolean(drafts && drafts.open),
|
|
452
|
+
restoreScrollTop: root ? root.scrollTop : 0
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async function refreshDashboardView() {
|
|
457
|
+
var panelEl = getPanel();
|
|
458
|
+
if (panelEl && panelEl.dataset.view === 'recent-projects') {
|
|
459
|
+
await renderRecentProjectsVariant(dashboardViewOptions());
|
|
489
460
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
if (
|
|
496
|
-
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
async function openDashboardConversation(projectId, record, row) {
|
|
464
|
+
var scope = record.accountScopeId;
|
|
465
|
+
var panelEl = getPanel();
|
|
466
|
+
if (!scope || scope !== getCachedAccountScopeId() || !isValidProjectId(projectId)
|
|
467
|
+
|| !panelEl || panelEl.dataset.view !== 'recent-projects' || row.getAttribute('aria-busy') === 'true') return;
|
|
468
|
+
row.setAttribute('aria-busy', 'true');
|
|
469
|
+
var resume = row.querySelector('[data-session-resume]');
|
|
470
|
+
if (resume) resume.disabled = true;
|
|
471
|
+
try {
|
|
472
|
+
var records = await loadProjectSessionRecords(projectId);
|
|
473
|
+
if (scope !== getCachedAccountScopeId() || panelEl !== getPanel()
|
|
474
|
+
|| panelEl.dataset.view !== 'recent-projects' || row.isConnected === false) return;
|
|
475
|
+
var selected = records.find(function (candidate) { return candidate.id === record.id; });
|
|
476
|
+
if (!selected) {
|
|
477
|
+
await refreshDashboardView();
|
|
478
|
+
showPluginToast(tr('recentProjects_conversationGone'), { status: 'warning' });
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
await activateSessionAndOpenProject(projectId, selected);
|
|
482
|
+
} catch (_error) {
|
|
483
|
+
if (scope === getCachedAccountScopeId() && row.isConnected !== false) {
|
|
484
|
+
showPluginToast(tr('recentProjects_continueFailed'), { status: 'warning' });
|
|
485
|
+
}
|
|
486
|
+
} finally {
|
|
487
|
+
row.removeAttribute('aria-busy');
|
|
488
|
+
if (resume) resume.disabled = false;
|
|
497
489
|
}
|
|
498
490
|
}
|
|
499
491
|
|
|
492
|
+
// Kept as a compatibility entry point and as the recovery path for invalid project links.
|
|
493
|
+
function renderRecentProjectRow(row) {
|
|
494
|
+
var projectId = row && row.projectId;
|
|
495
|
+
var valid = isValidProjectId(projectId);
|
|
496
|
+
var wrap = createViewElement('div', 'recent-projects-row-wrap recent-projects-unavailable-row');
|
|
497
|
+
wrap.setAttribute('data-project-id', projectId || '');
|
|
498
|
+
var link = createViewButton(undefined, null, 'data-recent-projects-row', 'recent-projects-row');
|
|
499
|
+
link.setAttribute('data-project-id', projectId || '');
|
|
500
|
+
link.disabled = !valid;
|
|
501
|
+
link.appendChild(textNode(projectDisplayName(projectId), 'recent-projects-row-name'));
|
|
502
|
+
if (valid) link.addEventListener('click', function () { openProjectFromRow(projectId); });
|
|
503
|
+
var cleanup = createViewButton(tr(valid ? 'recentProjects_clearProject' : 'recentProjects_cleanup'), function () {
|
|
504
|
+
if (valid) projectSessionCleanup.clearProjectSessions(projectId, projectDisplayName(projectId)).catch(function () {});
|
|
505
|
+
else cleanupDeadProjectEntry(projectId).catch(function () {});
|
|
506
|
+
}, valid ? 'data-project-clear' : 'data-row-cleanup');
|
|
507
|
+
wrap.appendChild(link);
|
|
508
|
+
wrap.appendChild(renderActionsMenu([cleanup]));
|
|
509
|
+
return wrap;
|
|
510
|
+
}
|
|
511
|
+
|
|
500
512
|
function sessionRecordDisplayTitle(record) {
|
|
501
513
|
if (record && typeof record.title === 'string' && record.title.trim()) {
|
|
502
514
|
return record.title.trim();
|
|
@@ -520,94 +532,86 @@
|
|
|
520
532
|
});
|
|
521
533
|
}
|
|
522
534
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
var sessionsLoading = document.createElement('div');
|
|
526
|
-
sessionsLoading.className = 'recent-projects-loading';
|
|
527
|
-
sessionsLoading.textContent = tx('Loading sessions…', '正在加载会话…');
|
|
528
|
-
sessionsEl.appendChild(sessionsLoading);
|
|
529
|
-
var records = [];
|
|
530
|
-
try {
|
|
531
|
-
records = await loadProjectSessionRecords(projectId);
|
|
532
|
-
} catch (_error) {
|
|
533
|
-
records = [];
|
|
534
|
-
}
|
|
535
|
-
sessionsLoading.remove();
|
|
536
|
-
if (!records.length) {
|
|
537
|
-
sessionsEl.appendChild(textNode(tr('recentProjects_sessions_empty'), 'recent-projects-sessions-empty'));
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
for (var i = 0; i < records.length; i++) {
|
|
541
|
-
sessionsEl.appendChild(renderProjectSessionRow(sessionsEl, projectId, records[i]));
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
function renderProjectSessionRow(sessionsEl, projectId, record) {
|
|
535
|
+
function renderProjectSessionRow(sessionsEl, projectId, record, options) {
|
|
536
|
+
var featured = Boolean(options && options.featured);
|
|
546
537
|
var running = Boolean(StorageDb)
|
|
547
538
|
&& settleDashboardRunStatus(StorageDb.derivePrimaryStatusBadge(record), record.updatedAt || record.lastActivityAt) === 'running';
|
|
548
|
-
var row =
|
|
549
|
-
row.className = 'recent-projects-session-row';
|
|
539
|
+
var row = createViewElement('div', 'recent-projects-session-row' + (featured ? ' recent-projects-focus' : ''));
|
|
550
540
|
row.setAttribute('data-project-session-row', record.id);
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
541
|
+
row.setAttribute('data-project-id', projectId);
|
|
542
|
+
if (running) row.setAttribute('data-running', 'true');
|
|
554
543
|
var title = textNode(sessionRecordDisplayTitle(record), 'recent-projects-session-title');
|
|
555
|
-
title.title =
|
|
556
|
-
var
|
|
557
|
-
|
|
558
|
-
var
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
var
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
544
|
+
title.title = title.textContent;
|
|
545
|
+
var copy = createViewElement('div', 'recent-projects-session-copy');
|
|
546
|
+
var meta = createViewElement('div', 'recent-projects-session-meta');
|
|
547
|
+
var project = textNode(projectDisplayName(projectId), 'recent-projects-row-name');
|
|
548
|
+
project.title = project.textContent;
|
|
549
|
+
meta.appendChild(project);
|
|
550
|
+
var time = textNode(formatRelativeTime(conversationActivity(record)), 'recent-projects-session-time');
|
|
551
|
+
time.setAttribute('data-rel-time', conversationActivity(record));
|
|
552
|
+
time.title = conversationActivity(record);
|
|
553
|
+
var status = conversationStatus(record);
|
|
554
|
+
var footer = featured ? createViewElement('div', 'recent-projects-focus-footer') : null;
|
|
555
|
+
if (featured) {
|
|
556
|
+
meta.insertBefore(textNode(tr('recentProjects_focusEyebrow'), 'recent-projects-focus-eyebrow'), project);
|
|
557
|
+
copy.appendChild(meta);
|
|
558
|
+
copy.appendChild(title);
|
|
559
|
+
footer.appendChild(status ? renderStatusBadge(status)
|
|
560
|
+
: textNode(tr('recentProjects_savedDraft'), 'recent-projects-row-badge'));
|
|
561
|
+
} else {
|
|
562
|
+
copy.appendChild(title);
|
|
563
|
+
copy.appendChild(meta);
|
|
564
|
+
if (['failed', 'needs_review', 'interrupted', 'stale', 'needs_review_after_navigation', 'abandoned_after_navigation'].indexOf(status) !== -1) {
|
|
565
|
+
var attention = textNode(tr('recentProjects_attention'), 'recent-projects-session-attention');
|
|
566
|
+
attention.title = tr('recentProjects_badge_' + status);
|
|
567
|
+
meta.appendChild(attention);
|
|
568
|
+
}
|
|
579
569
|
}
|
|
580
|
-
|
|
570
|
+
meta.appendChild(time);
|
|
571
|
+
row.appendChild(copy);
|
|
572
|
+
|
|
573
|
+
var rename = createViewButton(tr('renameSession'), function () {
|
|
581
574
|
beginDashboardSessionRename(sessionsEl, projectId, record, row, title);
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
575
|
+
}, 'data-session-rename-dash');
|
|
576
|
+
rename.title = rename.textContent;
|
|
577
|
+
rename.setAttribute('aria-label', rename.textContent);
|
|
578
|
+
if (running) rename.disabled = true;
|
|
579
|
+
var del = createViewButton(tr('deleteSession'), function () {
|
|
580
|
+
deleteDashboardSession(sessionsEl, projectId, record).catch(function () {});
|
|
581
|
+
}, 'data-session-delete-dash');
|
|
582
|
+
del.title = running ? tr('recentProjects_zombieRunningNote') : del.textContent;
|
|
583
|
+
del.setAttribute('aria-label', del.textContent);
|
|
584
|
+
var projectConversations = createViewButton(tr('recentProjects_projectConversations'), function () {
|
|
585
|
+
renderRecentProjectsVariant({ projectFilter: projectId, showAll: true, restoreScrollTop: 0 }).catch(function () {});
|
|
586
|
+
}, 'data-project-conversations');
|
|
587
|
+
var openProject = createViewButton(tr('recentProjects_openProject'), function () { openProjectFromRow(projectId); });
|
|
588
|
+
var clear = createViewButton(tr('recentProjects_clearProject'), function () {
|
|
589
|
+
projectSessionCleanup.clearProjectSessions(projectId, projectDisplayName(projectId)).catch(function () {});
|
|
590
|
+
}, 'data-project-clear');
|
|
591
|
+
row.appendChild(renderActionsMenu([rename, del, projectConversations, openProject, clear]));
|
|
592
|
+
|
|
593
|
+
var activate = function () { openDashboardConversation(projectId, record, row).catch(function () {}); };
|
|
594
|
+
if (featured) {
|
|
595
|
+
row.setAttribute('role', 'group');
|
|
596
|
+
row.setAttribute('aria-label', tr('recentProjects_focusEyebrow'));
|
|
597
|
+
var resume = createViewButton(tr('recentProjects_continue'), activate, 'data-session-resume', 'recent-projects-continue');
|
|
598
|
+
resume.title = tr('recentProjects_continueHint');
|
|
599
|
+
footer.appendChild(resume);
|
|
600
|
+
row.appendChild(footer);
|
|
601
|
+
} else {
|
|
602
|
+
row.classList.add('recent-projects-session-row--linked');
|
|
603
|
+
row.setAttribute('role', 'button');
|
|
604
|
+
row.tabIndex = 0;
|
|
605
|
+
row.addEventListener('click', function (event) {
|
|
606
|
+
if (!event.target.closest('button, input, details')) activate();
|
|
607
|
+
});
|
|
608
|
+
row.addEventListener('keydown', function (event) {
|
|
609
|
+
if (event.target === row && (event.key === 'Enter' || event.key === ' ')) {
|
|
610
|
+
event.preventDefault();
|
|
611
|
+
activate();
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
}
|
|
611
615
|
return row;
|
|
612
616
|
}
|
|
613
617
|
|
|
@@ -757,16 +761,7 @@
|
|
|
757
761
|
} catch (error) {
|
|
758
762
|
showPluginToast(tr('deleteSessionHistoryFailedToast', { message: error.message }), { status: 'warning', sticky: true });
|
|
759
763
|
}
|
|
760
|
-
|
|
761
|
-
// deletion, then restore this project's expanded session list.
|
|
762
|
-
// v1.8.1: refresh the whole variant so the row's session count, badge,
|
|
763
|
-
// summary and the welcome stats all stay fresh — but restore the scroll
|
|
764
|
-
// position and this project's expanded list so the delete feels in-place.
|
|
765
|
-
var rootForScroll = getPanel() && getPanel().querySelector('[data-recent-projects-root]');
|
|
766
|
-
await renderRecentProjectsVariant({
|
|
767
|
-
expandProjectId: projectId,
|
|
768
|
-
restoreScrollTop: rootForScroll ? rootForScroll.scrollTop : undefined
|
|
769
|
-
});
|
|
764
|
+
await refreshDashboardView();
|
|
770
765
|
}
|
|
771
766
|
|
|
772
767
|
function beginDashboardSessionRename(sessionsEl, projectId, record, row, titleEl) {
|
|
@@ -780,7 +775,7 @@
|
|
|
780
775
|
input.className = 'recent-projects-session-rename-input';
|
|
781
776
|
input.value = seed;
|
|
782
777
|
titleEl.hidden = true;
|
|
783
|
-
|
|
778
|
+
titleEl.parentElement.insertBefore(input, titleEl);
|
|
784
779
|
input.focus();
|
|
785
780
|
input.select();
|
|
786
781
|
var settled = false;
|
|
@@ -839,7 +834,7 @@
|
|
|
839
834
|
})));
|
|
840
835
|
}
|
|
841
836
|
} catch (_error) { /* swallow */ }
|
|
842
|
-
await
|
|
837
|
+
await refreshDashboardView();
|
|
843
838
|
}
|
|
844
839
|
|
|
845
840
|
function ensureRecentProjectsRoot() {
|
|
@@ -850,9 +845,13 @@
|
|
|
850
845
|
if (existing) {
|
|
851
846
|
return existing;
|
|
852
847
|
}
|
|
853
|
-
var rootEl =
|
|
854
|
-
rootEl.className = 'recent-projects-root';
|
|
848
|
+
var rootEl = createViewElement('section', 'recent-projects-root');
|
|
855
849
|
rootEl.setAttribute('data-recent-projects-root', '');
|
|
850
|
+
rootEl.addEventListener('click', function (event) {
|
|
851
|
+
rootEl.querySelectorAll('.recent-projects-menu[open]').forEach(function (menu) {
|
|
852
|
+
if (!menu.contains(event.target)) menu.open = false;
|
|
853
|
+
});
|
|
854
|
+
});
|
|
856
855
|
// Insert as a sibling of the existing per-project main / composer slots
|
|
857
856
|
// so the variant lives inside the panel root (page-scoped) and the
|
|
858
857
|
// existing data-view CSS rules can hide it when the per-project view is
|
|
@@ -901,133 +900,141 @@
|
|
|
901
900
|
return;
|
|
902
901
|
}
|
|
903
902
|
rootEl.appendChild(renderWelcomeHeader());
|
|
904
|
-
var loading =
|
|
905
|
-
loading.className = 'recent-projects-loading';
|
|
906
|
-
loading.textContent = tx('Loading projects\u2026', '正在加载项目…');
|
|
903
|
+
var loading = createViewElement('div', 'recent-projects-loading', tx('Loading projects\u2026', '正在加载项目…'));
|
|
907
904
|
rootEl.appendChild(loading);
|
|
908
905
|
}
|
|
909
906
|
|
|
910
907
|
async function renderRecentProjectsVariant(options) {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
908
|
+
var panelEl = getPanel();
|
|
909
|
+
var editorMatch = String(window.location && window.location.pathname || '').match(/^\/project\/([a-f0-9]{24})(?:\/|$)/);
|
|
910
|
+
if (!panelEl || (editorMatch && isValidProjectId(editorMatch[1]))) return;
|
|
911
|
+
var previous = dashboardViewOptions();
|
|
912
|
+
options = Object.assign({}, previous, options || {});
|
|
913
|
+
var generation = ++dashboardRenderGeneration;
|
|
914
|
+
panelEl.dataset.view = 'recent-projects';
|
|
918
915
|
startRelativeTimeTicker();
|
|
919
916
|
var rootEl = ensureRecentProjectsRoot();
|
|
920
|
-
if (!rootEl)
|
|
921
|
-
|
|
917
|
+
if (!rootEl) return;
|
|
918
|
+
var accountScopeId = (window.codexOverleafDeriveAccountScopeId || function () { return null; })();
|
|
919
|
+
if (previous.accountScopeId !== accountScopeId) {
|
|
920
|
+
options.projectFilter = '';
|
|
921
|
+
options.showAll = options.draftsOpen = false;
|
|
922
922
|
}
|
|
923
|
+
var projectFilter = isValidProjectId(options.projectFilter) ? options.projectFilter : '';
|
|
924
|
+
rootEl.dataset.accountScopeId = accountScopeId || '';
|
|
925
|
+
rootEl.dataset.projectFilter = projectFilter;
|
|
926
|
+
rootEl.dataset.showAll = options.showAll ? 'true' : 'false';
|
|
923
927
|
rootEl.innerHTML = '';
|
|
924
928
|
rootEl.appendChild(renderWelcomeHeader());
|
|
925
|
-
|
|
926
|
-
var accountScopeId = (window.codexOverleafDeriveAccountScopeId || function () { return null; })();
|
|
927
929
|
if (!accountScopeId) {
|
|
928
930
|
rootEl.appendChild(renderDegradedState());
|
|
929
931
|
rootEl.appendChild(renderSettingsEntry({ scope: 'account' }));
|
|
930
|
-
opportunisticEnrichmentFromDom().catch(function () { /* swallow */ });
|
|
931
932
|
return;
|
|
932
933
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
934
|
+
if (projectFilter) {
|
|
935
|
+
var filterBar = createViewElement('div', 'recent-projects-filter');
|
|
936
|
+
var back = createViewButton(tr('recentProjects_allProjects'), function () {
|
|
937
|
+
renderRecentProjectsVariant({ projectFilter: '', showAll: false, restoreScrollTop: 0 }).catch(function () {});
|
|
938
|
+
});
|
|
939
|
+
filterBar.appendChild(back);
|
|
940
|
+
var filterName = textNode(projectDisplayName(projectFilter));
|
|
941
|
+
filterName.title = filterName.textContent;
|
|
942
|
+
filterBar.appendChild(filterName);
|
|
943
|
+
rootEl.appendChild(filterBar);
|
|
944
|
+
}
|
|
945
|
+
var listContainer = createViewElement('div', 'recent-projects-list');
|
|
936
946
|
listContainer.setAttribute('data-recent-projects-list', '');
|
|
937
947
|
rootEl.appendChild(listContainer);
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
// Pre-warm the project-name cache mirror so the synchronous
|
|
947
|
-
// `lookupProjectName` calls inside `renderRecentProjectRow` see the
|
|
948
|
-
// latest data the first time the variant renders.
|
|
948
|
+
var loading = textNode(tr('recentProjects_loadingHistory'), 'recent-projects-loading');
|
|
949
|
+
listContainer.appendChild(loading);
|
|
950
|
+
function stillCurrent() {
|
|
951
|
+
return generation === dashboardRenderGeneration && getPanel() === panelEl
|
|
952
|
+
&& panelEl.dataset.view === 'recent-projects' && rootEl.isConnected !== false
|
|
953
|
+
&& getCachedAccountScopeId() === accountScopeId;
|
|
954
|
+
}
|
|
955
|
+
var records;
|
|
949
956
|
try {
|
|
950
957
|
await loadProjectNameCacheFromStorage();
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
var rows = [];
|
|
954
|
-
var showAll = Boolean(options && options.showAll);
|
|
955
|
-
// Fetch one extra row beyond the fold so "show all" only renders when
|
|
956
|
-
// there really is more than one page of projects.
|
|
957
|
-
var pageLimit = 10;
|
|
958
|
-
try {
|
|
959
|
-
if (StorageDb) {
|
|
960
|
-
var deletedSessionIdsByProject = await SessionPersistence.loadTombstones();
|
|
961
|
-
rows = await StorageDb.listRecentProjectsAcrossAccount({
|
|
962
|
-
accountScopeId: accountScopeId,
|
|
963
|
-
limit: showAll ? 500 : pageLimit + 1,
|
|
964
|
-
deletedSessionIdsByProject: deletedSessionIdsByProject
|
|
965
|
-
});
|
|
966
|
-
}
|
|
958
|
+
records = await loadDashboardConversations(accountScopeId);
|
|
967
959
|
} catch (_error) {
|
|
968
|
-
|
|
960
|
+
if (!stillCurrent()) return;
|
|
961
|
+
loading.textContent = tr('recentProjects_loadFailed');
|
|
962
|
+
var retry = createViewButton(tr('recentProjects_retryScope'), function () {
|
|
963
|
+
renderRecentProjectsVariant(options).catch(function () {});
|
|
964
|
+
}, null, 'recent-projects-show-all');
|
|
965
|
+
listContainer.appendChild(retry);
|
|
966
|
+
rootEl.appendChild(renderSettingsEntry({ scope: 'account' }));
|
|
967
|
+
return;
|
|
969
968
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
969
|
+
if (!stillCurrent()) return;
|
|
970
|
+
loading.remove();
|
|
971
|
+
var validRecords = records.filter(function (record) {
|
|
972
|
+
return isValidProjectId(record.projectId) && (!projectFilter || record.projectId === projectFilter);
|
|
973
|
+
});
|
|
974
|
+
var started = validRecords.filter(conversationHasContent);
|
|
975
|
+
var unstarted = validRecords.filter(function (record) { return !conversationHasContent(record); });
|
|
976
|
+
if (started.length) {
|
|
977
|
+
listContainer.appendChild(renderProjectSessionRow(listContainer, started[0].projectId, started[0], { featured: true }));
|
|
978
|
+
if (started.length > 1) {
|
|
979
|
+
var heading = createViewElement('div', 'recent-projects-history-heading');
|
|
980
|
+
heading.appendChild(textNode(tr('recentProjects_historyHeading')));
|
|
981
|
+
heading.appendChild(textNode(tr('recentProjects_historyHint')));
|
|
982
|
+
listContainer.appendChild(heading);
|
|
983
|
+
var historyList = createViewElement('div', 'recent-projects-history-list');
|
|
984
|
+
var history = options.showAll ? started.slice(1) : started.slice(1, 10);
|
|
985
|
+
history.forEach(function (record) {
|
|
986
|
+
historyList.appendChild(renderProjectSessionRow(historyList, record.projectId, record));
|
|
987
|
+
});
|
|
988
|
+
listContainer.appendChild(historyList);
|
|
989
|
+
if (!options.showAll && started.length > 10) {
|
|
990
|
+
var more = createViewButton(tr('recentProjects_showAllConversations', { count: started.length }), function () {
|
|
991
|
+
renderRecentProjectsVariant({ showAll: true }).catch(function () {});
|
|
992
|
+
}, 'data-recent-projects-show-all', 'recent-projects-show-all');
|
|
993
|
+
listContainer.appendChild(more);
|
|
994
|
+
}
|
|
982
995
|
}
|
|
983
|
-
welcomeSubtitle.textContent = tr('recentProjects_welcome_stats', {
|
|
984
|
-
projects: rows.length,
|
|
985
|
-
sessions: sessionTotal
|
|
986
|
-
});
|
|
987
|
-
}
|
|
988
|
-
var hasMore = !showAll && rows && rows.length > pageLimit;
|
|
989
|
-
var visibleRows = hasMore ? rows.slice(0, pageLimit) : rows;
|
|
990
|
-
if (!visibleRows || !visibleRows.length) {
|
|
991
|
-
listContainer.appendChild(renderEmptyState());
|
|
992
996
|
} else {
|
|
993
|
-
|
|
994
|
-
|
|
997
|
+
var empty = renderEmptyState();
|
|
998
|
+
if (unstarted.length) empty.textContent = tr('recentProjects_noStarted');
|
|
999
|
+
listContainer.appendChild(empty);
|
|
1000
|
+
}
|
|
1001
|
+
if (unstarted.length) {
|
|
1002
|
+
var drafts = createViewElement('details', 'recent-projects-drafts');
|
|
1003
|
+
drafts.setAttribute('data-unstarted-conversations', '');
|
|
1004
|
+
var summary = createViewElement('summary', '', tr('recentProjects_unstarted', { count: unstarted.length }));
|
|
1005
|
+
drafts.appendChild(summary);
|
|
1006
|
+
var draftsBuilt = false;
|
|
1007
|
+
function populateDrafts() {
|
|
1008
|
+
if (draftsBuilt || !stillCurrent()) return;
|
|
1009
|
+
draftsBuilt = true;
|
|
1010
|
+
drafts.appendChild(textNode(tr('recentProjects_unstartedHint'), 'recent-projects-drafts-hint'));
|
|
1011
|
+
unstarted.forEach(function (record) {
|
|
1012
|
+
drafts.appendChild(renderProjectSessionRow(drafts, record.projectId, record));
|
|
1013
|
+
});
|
|
995
1014
|
}
|
|
1015
|
+
drafts.addEventListener('toggle', function () { if (drafts.open) populateDrafts(); });
|
|
1016
|
+
listContainer.appendChild(drafts);
|
|
1017
|
+
if (options.draftsOpen) { drafts.open = true; populateDrafts(); }
|
|
996
1018
|
}
|
|
997
|
-
if (
|
|
998
|
-
var
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1019
|
+
if (!projectFilter) {
|
|
1020
|
+
var invalid = records.filter(function (record) { return !isValidProjectId(record.projectId); });
|
|
1021
|
+
var invalidIds = new Set();
|
|
1022
|
+
if (invalid.length) listContainer.appendChild(textNode(tr('recentProjects_unavailableRecords'), 'recent-projects-history-heading'));
|
|
1023
|
+
invalid.forEach(function (record) {
|
|
1024
|
+
var id = String(record.projectId || '');
|
|
1025
|
+
if (!invalidIds.has(id)) {
|
|
1026
|
+
invalidIds.add(id);
|
|
1027
|
+
listContainer.appendChild(renderRecentProjectRow({ projectId: record.projectId }));
|
|
1028
|
+
}
|
|
1005
1029
|
});
|
|
1006
|
-
listContainer.appendChild(showAllButton);
|
|
1007
1030
|
}
|
|
1008
1031
|
rootEl.appendChild(renderSettingsEntry({ scope: 'account' }));
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
if (expandProjectId && toReopen.indexOf(expandProjectId) === -1) {
|
|
1012
|
-
toReopen.push(expandProjectId);
|
|
1013
|
-
}
|
|
1014
|
-
for (var reopenIndex = 0; reopenIndex < toReopen.length; reopenIndex++) {
|
|
1015
|
-
var wrap = listContainer.querySelector('[data-project-row-wrap="' + toReopen[reopenIndex] + '"]');
|
|
1016
|
-
if (wrap) {
|
|
1017
|
-
toggleProjectSessions(wrap, toReopen[reopenIndex]);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
if (options && Number.isFinite(options.restoreScrollTop)) {
|
|
1021
|
-
rootEl.scrollTop = options.restoreScrollTop;
|
|
1022
|
-
var scrollerParent = rootEl.parentElement;
|
|
1023
|
-
if (scrollerParent && scrollerParent.scrollHeight > scrollerParent.clientHeight) {
|
|
1024
|
-
scrollerParent.scrollTop = options.restoreScrollTop;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
opportunisticEnrichmentFromDom().catch(function () { /* swallow */ });
|
|
1032
|
+
if (Number.isFinite(options.restoreScrollTop)) rootEl.scrollTop = options.restoreScrollTop;
|
|
1033
|
+
opportunisticEnrichmentFromDom().catch(function () {});
|
|
1028
1034
|
}
|
|
1029
1035
|
|
|
1030
1036
|
function renderPerProjectVariant() {
|
|
1037
|
+
dashboardRenderGeneration++;
|
|
1031
1038
|
// Per-project mount: ensure the panel view attribute is back on the
|
|
1032
1039
|
// session view and the variant root is detached so the per-project DOM
|
|
1033
1040
|
// is the only thing visible. The existing applyStateToPanel path renders
|
|
@@ -1049,6 +1056,7 @@
|
|
|
1049
1056
|
return {
|
|
1050
1057
|
loadProjectNameCacheFromStorage,
|
|
1051
1058
|
rememberCurrentProjectName,
|
|
1059
|
+
readCurrentProjectNameFromDom,
|
|
1052
1060
|
formatRelativeTime,
|
|
1053
1061
|
textNode,
|
|
1054
1062
|
renderStatusBadge,
|