@parhelia/core 0.1.12534 → 0.1.12555
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/dist/agents-view/AgentCard.d.ts +4 -6
- package/dist/agents-view/AgentCard.js +24 -143
- package/dist/agents-view/AgentCard.js.map +1 -1
- package/dist/agents-view/AgentsInbox.d.ts +1 -1
- package/dist/agents-view/AgentsInbox.js +92 -7
- package/dist/agents-view/AgentsInbox.js.map +1 -1
- package/dist/agents-view/AgentsTitlebar.js +2 -3
- package/dist/agents-view/AgentsTitlebar.js.map +1 -1
- package/dist/agents-view/AgentsView.d.ts +7 -6
- package/dist/agents-view/AgentsView.js +97 -186
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/AgentsWorkspaceView.d.ts +6 -2
- package/dist/agents-view/AgentsWorkspaceView.js +113 -266
- package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
- package/dist/agents-view/ProfileAgentsGroup.d.ts +1 -2
- package/dist/agents-view/ProfileAgentsGroup.js +3 -4
- package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
- package/dist/components/ActionButton.d.ts +1 -1
- package/dist/components/ActionButton.js.map +1 -1
- package/dist/components/FilterInput.d.ts +1 -1
- package/dist/components/FilterInput.js +1 -1
- package/dist/components/FilterInput.js.map +1 -1
- package/dist/components/ui/LanguageSelector.js +4 -2
- package/dist/components/ui/LanguageSelector.js.map +1 -1
- package/dist/components/ui/PlaceholderInput.js +3 -3
- package/dist/components/ui/PlaceholderInput.js.map +1 -1
- package/dist/components/ui/PlaceholderInputTypes.js +1 -1
- package/dist/components/ui/PlaceholderInputTypes.js.map +1 -1
- package/dist/components/ui/alert-dialog.d.ts +1 -1
- package/dist/components/ui/alert-dialog.js +10 -6
- package/dist/components/ui/alert-dialog.js.map +1 -1
- package/dist/components/ui/button.d.ts +4 -4
- package/dist/components/ui/button.js +1 -4
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/context-menu.d.ts +1 -1
- package/dist/components/ui/context-menu.js +4 -12
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/components/ui/copy-button.d.ts +1 -2
- package/dist/components/ui/copy-button.js +2 -2
- package/dist/components/ui/copy-button.js.map +1 -1
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/dialog.js +126 -21
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/input.d.ts +1 -1
- package/dist/components/ui/input.js +3 -5
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/paste-button.d.ts +1 -2
- package/dist/components/ui/paste-button.js +2 -2
- package/dist/components/ui/paste-button.js.map +1 -1
- package/dist/components/ui/popover.js +9 -1
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/styled-dialog-title.js +1 -1
- package/dist/components/ui/styled-dialog-title.js.map +1 -1
- package/dist/components/ui/tabs.d.ts +1 -1
- package/dist/components/ui/tabs.js +11 -4
- package/dist/components/ui/tabs.js.map +1 -1
- package/dist/config/config.d.ts +2 -2
- package/dist/config/config.js +70 -215
- package/dist/config/config.js.map +1 -1
- package/dist/config/types/workspace.d.ts +0 -6
- package/dist/config/types.d.ts +12 -58
- package/dist/config/types.js.map +1 -1
- package/dist/editor/ComponentInfo.d.ts +4 -0
- package/dist/editor/ComponentInfo.js +41 -0
- package/dist/editor/ComponentInfo.js.map +1 -0
- package/dist/editor/ConfirmationDialog.js +4 -20
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/ContentTree.d.ts +1 -2
- package/dist/editor/ContentTree.js +32 -93
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/Editor.js +18 -72
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/FieldHistory.js +36 -84
- package/dist/editor/FieldHistory.js.map +1 -1
- package/dist/editor/FieldListField.js +9 -21
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/FieldListFieldWithFallbacks.js +2 -23
- package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
- package/dist/editor/GlobalMenuBar.js +2 -29
- package/dist/editor/GlobalMenuBar.js.map +1 -1
- package/dist/editor/ItemInfo.js +1 -36
- package/dist/editor/ItemInfo.js.map +1 -1
- package/dist/editor/LinkEditorDialog.js +0 -3
- package/dist/editor/LinkEditorDialog.js.map +1 -1
- package/dist/editor/MainLayout.d.ts +2 -0
- package/dist/editor/MainLayout.js +5 -4
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/MigrationsView.js +5 -29
- package/dist/editor/MigrationsView.js.map +1 -1
- package/dist/editor/MobileLayout.js +12 -37
- package/dist/editor/MobileLayout.js.map +1 -1
- package/dist/editor/PictureCropper.js +45 -54
- package/dist/editor/PictureCropper.js.map +1 -1
- package/dist/editor/PictureEditor.js +13 -12
- package/dist/editor/PictureEditor.js.map +1 -1
- package/dist/editor/QuickItemSwitcher.js +21 -21
- package/dist/editor/QuickItemSwitcher.js.map +1 -1
- package/dist/editor/SetupWizard.js +12 -52
- package/dist/editor/SetupWizard.js.map +1 -1
- package/dist/editor/Titlebar.js +2 -7
- package/dist/editor/Titlebar.js.map +1 -1
- package/dist/editor/ai/AgentCostDisplay.d.ts +0 -1
- package/dist/editor/ai/AgentCostDisplay.js +1 -1
- package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
- package/dist/editor/ai/AgentDocumentList.js +14 -32
- package/dist/editor/ai/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/AgentGreeting.js +2 -3
- package/dist/editor/ai/AgentGreeting.js.map +1 -1
- package/dist/editor/ai/AgentProfileSelector.js +1 -2
- package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
- package/dist/editor/ai/AgentStatusBadge.d.ts +5 -0
- package/dist/editor/ai/AgentStatusBadge.js +65 -67
- package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.d.ts +2 -14
- package/dist/editor/ai/AgentTerminal.js +482 -2350
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AgentTerminalStatusBar.d.ts +3 -8
- package/dist/editor/ai/AgentTerminalStatusBar.js +56 -460
- package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
- package/dist/editor/ai/Agents.js +101 -91
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.d.ts +1 -10
- package/dist/editor/ai/AiResponseMessage.js +23 -238
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/ContextInfoBar.d.ts +3 -2
- package/dist/editor/ai/ContextInfoBar.js +7 -64
- package/dist/editor/ai/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/GuidanceOverlay.js +11 -17
- package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
- package/dist/editor/ai/HelpTerminal.d.ts +5 -0
- package/dist/editor/ai/HelpTerminal.js +166 -0
- package/dist/editor/ai/HelpTerminal.js.map +1 -0
- package/dist/editor/ai/InlineAiDialog.d.ts +1 -1
- package/dist/editor/ai/InlineAiDialog.js +192 -514
- package/dist/editor/ai/InlineAiDialog.js.map +1 -1
- package/dist/editor/ai/InlineAiTrigger.js +12 -115
- package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
- package/dist/editor/ai/MediaImage.js +8 -40
- package/dist/editor/ai/MediaImage.js.map +1 -1
- package/dist/editor/ai/SpawnedAgentsPanel.js +12 -10
- package/dist/editor/ai/SpawnedAgentsPanel.js.map +1 -1
- package/dist/editor/ai/ToolCallDisplay.d.ts +2 -22
- package/dist/editor/ai/ToolCallDisplay.js +147 -518
- package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
- package/dist/editor/ai/dialogs/AgentDialogHandler.d.ts +8 -1
- package/dist/editor/ai/dialogs/AgentDialogHandler.js +42 -379
- package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
- package/dist/editor/ai/dialogs/QuestionnaireInline.d.ts +1 -5
- package/dist/editor/ai/dialogs/QuestionnaireInline.js +60 -628
- package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
- package/dist/editor/ai/dialogs/agentDialogTypes.d.ts +0 -115
- package/dist/editor/ai/dialogs/agentDialogTypes.js +0 -2
- package/dist/editor/ai/dialogs/agentDialogTypes.js.map +1 -1
- package/dist/editor/ai/types.d.ts +1 -3
- package/dist/editor/ai/useAgentStatus.d.ts +0 -1
- package/dist/editor/ai/useAgentStatus.js +96 -79
- package/dist/editor/ai/useAgentStatus.js.map +1 -1
- package/dist/editor/ai/useInlineAiPosition.js +5 -45
- package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
- package/dist/editor/client/AboutDialog.js +2 -4
- package/dist/editor/client/AboutDialog.js.map +1 -1
- package/dist/editor/client/EditorShell.js +212 -581
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +19 -28
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/helpers.js +0 -6
- package/dist/editor/client/helpers.js.map +1 -1
- package/dist/editor/client/hooks/useEditorUrlSync.js +2 -1
- package/dist/editor/client/hooks/useEditorUrlSync.js.map +1 -1
- package/dist/editor/client/hooks/useEditorWebSocket.d.ts +0 -10
- package/dist/editor/client/hooks/useEditorWebSocket.js +14 -209
- package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
- package/dist/editor/client/hooks/useQuota.d.ts +0 -8
- package/dist/editor/client/hooks/useQuota.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +7 -68
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +6 -10
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/navigation.d.ts +21 -0
- package/dist/editor/client/navigation.js +98 -0
- package/dist/editor/client/navigation.js.map +1 -0
- package/dist/editor/client/operations.d.ts +3 -6
- package/dist/editor/client/operations.js +30 -208
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.js +31 -4
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.d.ts +6 -0
- package/dist/editor/client/ui/EditorChrome.js +72 -55
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/client/ui/FullscreenControls.js +3 -5
- package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
- package/dist/editor/commands/commands.d.ts +1 -11
- package/dist/editor/commands/commands.js +1 -12
- package/dist/editor/commands/commands.js.map +1 -1
- package/dist/editor/commands/componentCommands.js +55 -109
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/commands/customCommandConverter.d.ts +1 -8
- package/dist/editor/commands/customCommandConverter.js +5 -35
- package/dist/editor/commands/customCommandConverter.js.map +1 -1
- package/dist/editor/commands/handlers/agentHandler.js +1 -2
- package/dist/editor/commands/handlers/agentHandler.js.map +1 -1
- package/dist/editor/commands/handlers/uiActionHandlers.js +3 -4
- package/dist/editor/commands/handlers/uiActionHandlers.js.map +1 -1
- package/dist/editor/commands/itemCommands.d.ts +0 -3
- package/dist/editor/commands/itemCommands.js +10 -93
- package/dist/editor/commands/itemCommands.js.map +1 -1
- package/dist/editor/commands/undo.d.ts +15 -9
- package/dist/editor/commands/undo.js +0 -24
- package/dist/editor/commands/undo.js.map +1 -1
- package/dist/editor/context-menu/InsertMenu.js +39 -83
- package/dist/editor/context-menu/InsertMenu.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +1 -1
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +1 -1
- package/dist/editor/field-types/ReactQuill.d.ts +125 -0
- package/dist/editor/field-types/ReactQuill.js +385 -0
- package/dist/editor/field-types/ReactQuill.js.map +1 -0
- package/dist/editor/field-types/RichTextEditor.js +2 -4
- package/dist/editor/field-types/RichTextEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +3 -37
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +1 -1
- package/dist/editor/field-types/TreeListEditor.js +2 -3
- package/dist/editor/field-types/TreeListEditor.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.css +5 -23
- package/dist/editor/field-types/richtext/components/ReactSlate.d.ts +0 -2
- package/dist/editor/field-types/richtext/components/ReactSlate.js +4 -28
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ToolbarButton.js +2 -4
- package/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +0 -13
- package/dist/editor/field-types/richtext/contextMenuFactory.js +22 -177
- package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
- package/dist/editor/field-types/richtext/types.d.ts +0 -2
- package/dist/editor/field-types/richtext/types.js.map +1 -1
- package/dist/editor/field-types/richtext/utils/plugins.js +0 -4
- package/dist/editor/field-types/richtext/utils/plugins.js.map +1 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js +1 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
- package/dist/editor/media-selector/MediaSelector.js +1 -7
- package/dist/editor/media-selector/MediaSelector.js.map +1 -1
- package/dist/editor/media-selector/TreeSelector.js +35 -40
- package/dist/editor/media-selector/TreeSelector.js.map +1 -1
- package/dist/editor/menubar/ActiveUsers.js +1 -1
- package/dist/editor/menubar/ActiveUsers.js.map +1 -1
- package/dist/editor/menubar/GenericToolbar.js +2 -4
- package/dist/editor/menubar/GenericToolbar.js.map +1 -1
- package/dist/editor/menubar/ItemLanguageVersion.js +2 -2
- package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
- package/dist/editor/menubar/PageSelector.js +147 -26
- package/dist/editor/menubar/PageSelector.js.map +1 -1
- package/dist/editor/menubar/Separator.js +1 -1
- package/dist/editor/menubar/VersionSelector.js +4 -2
- package/dist/editor/menubar/VersionSelector.js.map +1 -1
- package/dist/editor/menubar/WorkflowButton.js +12 -39
- package/dist/editor/menubar/WorkflowButton.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js +36 -7
- package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/EditControls.js +3 -3
- package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/HelpButton.js +0 -1
- package/dist/editor/menubar/toolbar-sections/HelpButton.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +10 -6
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +219 -500
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +1 -10
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js +1 -42
- package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +48 -97
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +17 -38
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +11 -17
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js +298 -283
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
- package/dist/editor/page-viewer/EditorForm.js +11 -69
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/MiniMap.d.ts +4 -2
- package/dist/editor/page-viewer/MiniMap.js +28 -91
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.d.ts +1 -3
- package/dist/editor/page-viewer/PageViewer.js +19 -92
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.d.ts +1 -2
- package/dist/editor/page-viewer/PageViewerFrame.js +109 -292
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/RenderingParametersSection.js +3 -2
- package/dist/editor/page-viewer/RenderingParametersSection.js.map +1 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +49 -114
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
- package/dist/editor/page-viewer/pageViewContext.d.ts +0 -1
- package/dist/editor/page-viewer/pageViewContext.js +14 -51
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/pageModel.d.ts +1 -14
- package/dist/editor/reviews/Comment.js +11 -23
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +4 -4
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +4 -19
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.js +72 -89
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/CreateReviewDialog.js +177 -281
- package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
- package/dist/editor/reviews/DecisionsMatrix.js +25 -96
- package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
- package/dist/editor/reviews/DiffView.js +14 -7
- package/dist/editor/reviews/DiffView.js.map +1 -1
- package/dist/editor/reviews/EditReviewSettingsDialog.js +4 -6
- package/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -1
- package/dist/editor/reviews/MultiReviewManager.js +3 -25
- package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
- package/dist/editor/reviews/PagesPanel.js +15 -31
- package/dist/editor/reviews/PagesPanel.js.map +1 -1
- package/dist/editor/reviews/PreviewInfo.js +4 -1
- package/dist/editor/reviews/PreviewInfo.js.map +1 -1
- package/dist/editor/reviews/ReviewCard.js +7 -13
- package/dist/editor/reviews/ReviewCard.js.map +1 -1
- package/dist/editor/reviews/ReviewDetail.js +2 -3
- package/dist/editor/reviews/ReviewDetail.js.map +1 -1
- package/dist/editor/reviews/ReviewsList.js +3 -7
- package/dist/editor/reviews/ReviewsList.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +3 -34
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +5 -31
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/commentAi.js +6 -21
- package/dist/editor/reviews/commentAi.js.map +1 -1
- package/dist/editor/reviews/reviewCommands.js +1 -4
- package/dist/editor/reviews/reviewCommands.js.map +1 -1
- package/dist/editor/reviews/useMultiReview.js +2 -2
- package/dist/editor/reviews/useMultiReview.js.map +1 -1
- package/dist/editor/reviews/useReviews.d.ts +2 -2
- package/dist/editor/reviews/useReviews.js +30 -12
- package/dist/editor/reviews/useReviews.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +5 -229
- package/dist/editor/services/agentService.js +39 -292
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +1 -57
- package/dist/editor/services/aiService.js +6 -79
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/services/contentService.d.ts +3 -6
- package/dist/editor/services/contentService.js +12 -13
- package/dist/editor/services/contentService.js.map +1 -1
- package/dist/editor/services/editService.d.ts +1 -50
- package/dist/editor/services/editService.js +2 -91
- package/dist/editor/services/editService.js.map +1 -1
- package/dist/editor/services/indexService.js +1 -1
- package/dist/editor/services/indexService.js.map +1 -1
- package/dist/editor/services/reviewsService.d.ts +6 -3
- package/dist/editor/services/reviewsService.js +11 -2
- package/dist/editor/services/reviewsService.js.map +1 -1
- package/dist/editor/services/serviceHelper.d.ts +1 -2
- package/dist/editor/services/serviceHelper.js +20 -112
- package/dist/editor/services/serviceHelper.js.map +1 -1
- package/dist/editor/services/systemService.d.ts +1 -2
- package/dist/editor/services/systemService.js +0 -3
- package/dist/editor/services/systemService.js.map +1 -1
- package/dist/editor/services-server/graphQL.d.ts +29 -0
- package/dist/editor/services-server/graphQL.js +53 -0
- package/dist/editor/services-server/graphQL.js.map +1 -0
- package/dist/editor/settings/About.js +3 -317
- package/dist/editor/settings/About.js.map +1 -1
- package/dist/editor/settings/AllAgentsPanel.d.ts +5 -0
- package/dist/editor/settings/AllAgentsPanel.js +139 -0
- package/dist/editor/settings/AllAgentsPanel.js.map +1 -0
- package/dist/editor/settings/LatestFeedback.d.ts +1 -0
- package/dist/editor/settings/LatestFeedback.js +136 -0
- package/dist/editor/settings/LatestFeedback.js.map +1 -0
- package/dist/editor/settings/QuotaInfo.js +4 -210
- package/dist/editor/settings/QuotaInfo.js.map +1 -1
- package/dist/editor/settings/SettingsView.js +21 -23
- package/dist/editor/settings/SettingsView.js.map +1 -1
- package/dist/editor/settings/Setup.d.ts +1 -0
- package/dist/editor/settings/Setup.js +211 -0
- package/dist/editor/settings/Setup.js.map +1 -0
- package/dist/editor/settings/Status.js +4 -5
- package/dist/editor/settings/Status.js.map +1 -1
- package/dist/editor/settings/index/useIndexStatus.js +22 -20
- package/dist/editor/settings/index/useIndexStatus.js.map +1 -1
- package/dist/editor/settings/panels/AgentsPanel.d.ts +4 -0
- package/dist/editor/settings/panels/AgentsPanel.js +121 -95
- package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
- package/dist/editor/settings/panels/DatabasePanel.d.ts +6 -0
- package/dist/editor/settings/panels/DatabasePanel.js +50 -0
- package/dist/editor/settings/panels/DatabasePanel.js.map +1 -0
- package/dist/editor/settings/panels/ModelsPanel.js +108 -329
- package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.d.ts +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.js +59 -86
- package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
- package/dist/editor/settings/panels/SearchConfigPanel.js +4 -4
- package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
- package/dist/editor/settings/panels/index.d.ts +2 -3
- package/dist/editor/settings/panels/index.js +2 -3
- package/dist/editor/settings/panels/index.js.map +1 -1
- package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +2 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js +195 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/index.d.ts +2 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/index.js +21 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/index.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js +233 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +15 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js +14 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +94 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/types.d.ts +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/types.js +2 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/types.js.map +1 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/utils.d.ts +5 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/utils.js +44 -0
- package/dist/editor/settings/setup-steps/AiSetupStep/utils.js.map +1 -0
- package/dist/editor/settings/setup-steps/IndexSetupStep.d.ts +2 -0
- package/dist/editor/settings/setup-steps/IndexSetupStep.js +36 -0
- package/dist/editor/settings/setup-steps/IndexSetupStep.js.map +1 -0
- package/dist/editor/settings/setup-steps/SettingsSetupStep.d.ts +2 -0
- package/dist/editor/settings/setup-steps/SettingsSetupStep.js +111 -0
- package/dist/editor/settings/setup-steps/SettingsSetupStep.js.map +1 -0
- package/dist/editor/settings/setup-steps/SetupOverview.d.ts +14 -0
- package/dist/editor/settings/setup-steps/SetupOverview.js +38 -0
- package/dist/editor/settings/setup-steps/SetupOverview.js.map +1 -0
- package/dist/editor/settings/status/coreStatusChecks.js +19 -124
- package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
- package/dist/editor/settings/status/useStartupChecks.d.ts +1 -3
- package/dist/editor/settings/status/useStartupChecks.js +5 -9
- package/dist/editor/settings/status/useStartupChecks.js.map +1 -1
- package/dist/editor/setup-wizard/steps/CompleteStep.d.ts +1 -2
- package/dist/editor/setup-wizard/steps/CompleteStep.js +1 -2
- package/dist/editor/setup-wizard/steps/CompleteStep.js.map +1 -1
- package/dist/editor/sidebar/ComponentPalette.js +1 -2
- package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.d.ts +1 -8
- package/dist/editor/sidebar/ComponentTree.js +69 -216
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/Debug.d.ts +1 -0
- package/dist/editor/sidebar/Debug.js +70 -0
- package/dist/editor/sidebar/Debug.js.map +1 -0
- package/dist/editor/sidebar/EditHistory.js +46 -7
- package/dist/editor/sidebar/EditHistory.js.map +1 -1
- package/dist/editor/sidebar/Favorites.js +8 -4
- package/dist/editor/sidebar/Favorites.js.map +1 -1
- package/dist/editor/sidebar/GraphQL.d.ts +2 -0
- package/dist/editor/sidebar/GraphQL.js +234 -0
- package/dist/editor/sidebar/GraphQL.js.map +1 -0
- package/dist/editor/sidebar/LeftToolbar.d.ts +1 -0
- package/dist/editor/sidebar/LeftToolbar.js +12 -0
- package/dist/editor/sidebar/LeftToolbar.js.map +1 -0
- package/dist/editor/sidebar/MainContentTree.js +3 -4
- package/dist/editor/sidebar/MainContentTree.js.map +1 -1
- package/dist/editor/sidebar/NavigationPanelItem.js +1 -1
- package/dist/editor/sidebar/NavigationPanelItem.js.map +1 -1
- package/dist/editor/sidebar/NavigationSidebar.d.ts +4 -0
- package/dist/editor/sidebar/NavigationSidebar.js +254 -0
- package/dist/editor/sidebar/NavigationSidebar.js.map +1 -0
- package/dist/editor/sidebar/OperationItem.js +6 -20
- package/dist/editor/sidebar/OperationItem.js.map +1 -1
- package/dist/editor/sidebar/SidebarPanel.js +7 -30
- package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
- package/dist/editor/sidebar/SidebarStack.js +0 -1
- package/dist/editor/sidebar/SidebarStack.js.map +1 -1
- package/dist/editor/sidebar/Validation.js +12 -22
- package/dist/editor/sidebar/Validation.js.map +1 -1
- package/dist/editor/sidebar/Workbox.js +3 -53
- package/dist/editor/sidebar/Workbox.js.map +1 -1
- package/dist/editor/sidebar/WorkspaceRail.d.ts +1 -0
- package/dist/editor/sidebar/WorkspaceRail.js +167 -56
- package/dist/editor/sidebar/WorkspaceRail.js.map +1 -1
- package/dist/editor/template-wizard/TemplateStructureInlineEditor.js +10 -3
- package/dist/editor/template-wizard/TemplateStructureInlineEditor.js.map +1 -1
- package/dist/editor/tree-indicators/GutterColumns.d.ts +1 -3
- package/dist/editor/tree-indicators/GutterColumns.js +5 -26
- package/dist/editor/tree-indicators/GutterColumns.js.map +1 -1
- package/dist/editor/tree-indicators/GutterContext.d.ts +0 -4
- package/dist/editor/tree-indicators/GutterContext.js +0 -23
- package/dist/editor/tree-indicators/GutterContext.js.map +1 -1
- package/dist/editor/tree-indicators/GutterSelector.d.ts +5 -0
- package/dist/editor/tree-indicators/GutterSelector.js +91 -0
- package/dist/editor/tree-indicators/GutterSelector.js.map +1 -0
- package/dist/editor/tree-indicators/index.d.ts +1 -0
- package/dist/editor/tree-indicators/index.js +1 -0
- package/dist/editor/tree-indicators/index.js.map +1 -1
- package/dist/editor/tree-indicators/types.d.ts +1 -12
- package/dist/editor/ui/CopyMoveTargetSelectorDialog.js +1 -1
- package/dist/editor/ui/CopyMoveTargetSelectorDialog.js.map +1 -1
- package/dist/editor/ui/Icons.js +1 -1
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/ItemNameDialogNew.d.ts +0 -2
- package/dist/editor/ui/ItemNameDialogNew.js +17 -33
- package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
- package/dist/editor/ui/ItemSearch.js +11 -7
- package/dist/editor/ui/ItemSearch.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.js +1 -1
- package/dist/editor/ui/SimpleIconButton.js.map +1 -1
- package/dist/editor/ui/SimpleTabs.d.ts +0 -1
- package/dist/editor/ui/SimpleTabs.js +25 -45
- package/dist/editor/ui/SimpleTabs.js.map +1 -1
- package/dist/editor/ui/Splitter.d.ts +0 -1
- package/dist/editor/ui/Splitter.js +86 -102
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/ui/TemplateSelectorDialog.js +4 -4
- package/dist/editor/ui/TemplateSelectorDialog.js.map +1 -1
- package/dist/editor/ui/TreeListSelector.d.ts +1 -6
- package/dist/editor/ui/TreeListSelector.js +2 -2
- package/dist/editor/ui/TreeListSelector.js.map +1 -1
- package/dist/editor/utils/keyboardNavigation.d.ts +20 -6
- package/dist/editor/utils/keyboardNavigation.js +139 -48
- package/dist/editor/utils/keyboardNavigation.js.map +1 -1
- package/dist/editor/utils.js +9 -19
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/views/CompareView.d.ts +1 -3
- package/dist/editor/views/CompareView.js +4 -6
- package/dist/editor/views/CompareView.js.map +1 -1
- package/dist/editor/views/EditView.js +1 -1
- package/dist/editor/views/EditView.js.map +1 -1
- package/dist/editor/views/EditorSlot.js +34 -27
- package/dist/editor/views/EditorSlot.js.map +1 -1
- package/dist/editor/views/ItemEditor.js +3 -7
- package/dist/editor/views/ItemEditor.js.map +1 -1
- package/dist/editor/views/MediaFolderEditView.js +1 -1
- package/dist/editor/views/MediaFolderEditView.js.map +1 -1
- package/dist/editor/views/ParheliaView.js +6 -5
- package/dist/editor/views/ParheliaView.js.map +1 -1
- package/dist/editor/views/SingleEditView.d.ts +1 -2
- package/dist/editor/views/SingleEditView.js +8 -10
- package/dist/editor/views/SingleEditView.js.map +1 -1
- package/dist/editor/views/editorSlotContext.js +6 -35
- package/dist/editor/views/editorSlotContext.js.map +1 -1
- package/dist/index.d.ts +2 -14
- package/dist/index.js +0 -10
- package/dist/index.js.map +1 -1
- package/dist/licensing/LicenseContext.d.ts +3 -1
- package/dist/licensing/LicenseContext.js +55 -38
- package/dist/licensing/LicenseContext.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/setup/services/setupWizardService.d.ts +13 -40
- package/dist/setup/services/setupWizardService.js +17 -32
- package/dist/setup/services/setupWizardService.js.map +1 -1
- package/dist/setup/wizard/steps/AddModelDialog.js +3 -12
- package/dist/setup/wizard/steps/AddModelDialog.js.map +1 -1
- package/dist/setup/wizard/steps/ImportModelDialog.js +22 -39
- package/dist/setup/wizard/steps/ImportModelDialog.js.map +1 -1
- package/dist/splash-screen/ModernSplashScreen.js +32 -110
- package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
- package/dist/splash-screen/NewPage.js +50 -33
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +6 -2
- package/dist/splash-screen/OpenPage.js.map +1 -1
- package/dist/splash-screen/ParheliaAssistantChat.js +29 -12
- package/dist/splash-screen/ParheliaAssistantChat.js.map +1 -1
- package/dist/splash-screen/ParheliaLogo.js +37 -87
- package/dist/splash-screen/ParheliaLogo.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +3 -3
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/task-board/TaskBoardWorkspace.js +34 -6
- package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
- package/dist/task-board/components/AssignAgentDialog.js +13 -1
- package/dist/task-board/components/AssignAgentDialog.js.map +1 -1
- package/dist/task-board/components/TaskAgentPanel.js +11 -1
- package/dist/task-board/components/TaskAgentPanel.js.map +1 -1
- package/dist/task-board/components/TaskAssigneePicker.js +14 -4
- package/dist/task-board/components/TaskAssigneePicker.js.map +1 -1
- package/dist/task-board/components/WizardCommunicationCenter.js +18 -9
- package/dist/task-board/components/WizardCommunicationCenter.js.map +1 -1
- package/dist/tour/Tour.d.ts +1 -2
- package/dist/tour/Tour.js +75 -256
- package/dist/tour/Tour.js.map +1 -1
- package/dist/tour/default-tour.js +96 -222
- package/dist/tour/default-tour.js.map +1 -1
- package/dist/types.d.ts +29 -63
- package/package.json +13 -17
- package/styles.css +10 -14
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import React, { useState, useEffect, useRef, useCallback, useSyncExternalStore, useMemo, startTransition, } from "react";
|
|
4
4
|
import { toast } from "sonner";
|
|
5
|
-
import { EditContextProvider, FieldsEditContextProvider, OperationsContextProvider,
|
|
5
|
+
import { EditContextProvider, FieldsEditContextProvider, OperationsContextProvider, } from "./editContext";
|
|
6
6
|
import { fieldModificationStore } from "./fieldModificationStore";
|
|
7
7
|
import { useRouter, useSearchParams, usePathname } from "next/navigation";
|
|
8
8
|
import { findComponent, getComponentById } from "../componentTreeHelper";
|
|
9
9
|
import { getOperationsContext } from "./operations";
|
|
10
10
|
import { handleErrorResult } from "./helpers";
|
|
11
|
-
import { executeFieldAction as executeFieldServerAction, connectSocket, getEditHistory, getRunningOperations,
|
|
11
|
+
import { executeFieldAction as executeFieldServerAction, connectSocket, getEditHistory, getRunningOperations, releaseFieldLocks, validateItems, } from "../services/editService";
|
|
12
12
|
import { useEditorWebSocket } from "./hooks/useEditorWebSocket";
|
|
13
|
-
import { createEditorSocketDiagnostics, } from "./socketDiagnostics";
|
|
14
|
-
import { localStorageService } from "../services/localStorageService";
|
|
15
13
|
import { useSocketMessageHandler } from "./hooks/useSocketMessageHandler";
|
|
16
14
|
import "react-json-view-lite/dist/index.css";
|
|
17
15
|
import { MediaSelector, } from "../media-selector/MediaSelector";
|
|
@@ -22,7 +20,6 @@ import { getItemDescriptor } from "../utils";
|
|
|
22
20
|
import { EditContextMenu } from "../ContextMenu";
|
|
23
21
|
import { InlineAiTrigger } from "../ai/InlineAiTrigger";
|
|
24
22
|
import { FieldEditorPopup } from "../FieldEditorPopup";
|
|
25
|
-
import { ConcurrentUserLimitDialog } from "../ConcurrentUserLimitDialog";
|
|
26
23
|
import { post } from "../services/serviceHelper";
|
|
27
24
|
import { PageViewerFrame } from "../page-viewer/PageViewerFrame";
|
|
28
25
|
import { useItemsRepository } from "./itemsRepository";
|
|
@@ -36,7 +33,6 @@ import { GuidanceOverlay } from "../ai/GuidanceOverlay";
|
|
|
36
33
|
import { AgentDialogHandler } from "../ai/dialogs";
|
|
37
34
|
import { usePageViewContext, } from "../page-viewer/pageViewContext";
|
|
38
35
|
import { QuickItemSwitcher } from "../QuickItemSwitcher";
|
|
39
|
-
import { useEditorSlotContext, } from "../views/editorSlotContext";
|
|
40
36
|
import { getComments, getAvailableCommentTags, } from "../services/reviewsService";
|
|
41
37
|
import { useReviews } from "../reviews/useReviews";
|
|
42
38
|
import uuid from "react-uuid";
|
|
@@ -53,32 +49,6 @@ import { useWorkbox } from "./hooks/useWorkbox";
|
|
|
53
49
|
import { useMediaSelector } from "./hooks/useMediaSelector";
|
|
54
50
|
import { useGlobalEditorKeyDown } from "./hooks/useGlobalEditorKeyDown";
|
|
55
51
|
import { useStartupChecks } from "../settings/status/index";
|
|
56
|
-
import { LicenseProvider, LicenseOverlay } from "../../licensing";
|
|
57
|
-
function AgentsSlotContextBridge({ slot }) {
|
|
58
|
-
const editContext = useEditContext();
|
|
59
|
-
const slotContext = useEditorSlotContext({
|
|
60
|
-
slotId: slot.slotId,
|
|
61
|
-
itemDescriptor: slot.itemDescriptor,
|
|
62
|
-
refreshToken: slot.refreshToken,
|
|
63
|
-
});
|
|
64
|
-
if (!editContext || !slotContext)
|
|
65
|
-
return null;
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
editContext.registerSlotContext(slot.slotId, slotContext);
|
|
68
|
-
return () => {
|
|
69
|
-
editContext.unregisterSlotContext(slot.slotId);
|
|
70
|
-
};
|
|
71
|
-
}, [
|
|
72
|
-
slot.slotId,
|
|
73
|
-
slotContext,
|
|
74
|
-
editContext.registerSlotContext,
|
|
75
|
-
editContext.unregisterSlotContext,
|
|
76
|
-
]);
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
function AgentsSlotContextBridgeHost({ slots }) {
|
|
80
|
-
return (_jsx(_Fragment, { children: slots.map((slot) => (_jsx(AgentsSlotContextBridge, { slot: slot }, `agents-slot-bridge-${slot.slotId}`))) }));
|
|
81
|
-
}
|
|
82
52
|
export function EditorShell({ configuration, className, item: loadItemDescriptor, sessionId, userInfo, userPreferences, parheliaSettings, setUserPreferences, children, }) {
|
|
83
53
|
const router = useRouter();
|
|
84
54
|
const pathname = usePathname();
|
|
@@ -154,14 +124,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
154
124
|
if (typeof window !== "undefined")
|
|
155
125
|
sessionStorage?.setItem("sessionId", sessionId);
|
|
156
126
|
// Workspace state
|
|
157
|
-
// Note: "reviews" is a sidebar, not a workspace. If workspace=reviews, we should
|
|
127
|
+
// Note: "reviews" is a sidebar, not a workspace. If view/workspace=reviews, we should
|
|
158
128
|
// set workspace to "editor" and open the reviews sidebar instead.
|
|
159
129
|
// Memoize searchParams reads to avoid triggering Router state updates during render
|
|
160
130
|
// (Next.js App Router uses startTransition internally for URL changes)
|
|
161
|
-
const rawWorkspace = useMemo(() => searchParams.get("workspace"), [searchParams]);
|
|
131
|
+
const rawWorkspace = useMemo(() => searchParams.get("workspace") ?? searchParams.get("view"), [searchParams]);
|
|
162
132
|
const isReviewsSidebarRequest = rawWorkspace === "reviews";
|
|
163
133
|
const [workspaceId, setWorkspaceId] = useState(
|
|
164
|
-
// If
|
|
134
|
+
// If view=reviews, use "editor" workspace (reviews is a sidebar, not a workspace)
|
|
165
135
|
isReviewsSidebarRequest
|
|
166
136
|
? "editor"
|
|
167
137
|
: (rawWorkspace ??
|
|
@@ -183,7 +153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
183
153
|
else {
|
|
184
154
|
sidebars = [...(configuration.editor.defaultOpenSidebars ?? [])];
|
|
185
155
|
}
|
|
186
|
-
// If workspace=reviews was requested, ensure reviews sidebar is open
|
|
156
|
+
// If view/workspace=reviews was requested, ensure reviews sidebar is open
|
|
187
157
|
if (isReviewsSidebarRequest && !sidebars.includes("reviews")) {
|
|
188
158
|
sidebars.push("reviews");
|
|
189
159
|
}
|
|
@@ -191,11 +161,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
191
161
|
});
|
|
192
162
|
// Toolbar pinned sidebars - icons always visible in toolbar (defined early so callbacks can access)
|
|
193
163
|
const [pinnedSidebars, setPinnedSidebars] = useState(userInfo.preferences?.pinnedSidebars || []);
|
|
194
|
-
const pinnedSidebarsRef = useRef(pinnedSidebars);
|
|
195
164
|
// Locked sidebars - open panels that stay visible when selecting another sidebar
|
|
196
165
|
const [lockedSidebars, setLockedSidebars] = useState(() => {
|
|
166
|
+
if (typeof window === "undefined") {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
197
169
|
try {
|
|
198
|
-
const
|
|
170
|
+
const stored = window.localStorage.getItem("editor.lockedSidebars");
|
|
171
|
+
if (!stored) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
const parsed = JSON.parse(stored);
|
|
199
175
|
if (!Array.isArray(parsed) ||
|
|
200
176
|
!parsed.every((id) => typeof id === "string")) {
|
|
201
177
|
return [];
|
|
@@ -211,9 +187,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
211
187
|
useEffect(() => {
|
|
212
188
|
lockedSidebarsRef.current = lockedSidebars;
|
|
213
189
|
}, [lockedSidebars]);
|
|
214
|
-
useEffect(() => {
|
|
215
|
-
pinnedSidebarsRef.current = pinnedSidebars;
|
|
216
|
-
}, [pinnedSidebars]);
|
|
217
190
|
// Filter locked sidebars to only include currently open sidebars
|
|
218
191
|
useEffect(() => {
|
|
219
192
|
const openSet = new Set(openSidebars);
|
|
@@ -275,11 +248,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
275
248
|
// Group open sidebars into vertical stacks (each stack shares one left column).
|
|
276
249
|
const [sidebarStacks, setSidebarStacks] = useState(() => {
|
|
277
250
|
const defaultStacks = openSidebars.map((id) => [id]);
|
|
251
|
+
if (typeof window === "undefined") {
|
|
252
|
+
return normalizeSidebarStacks(openSidebars, defaultStacks);
|
|
253
|
+
}
|
|
278
254
|
try {
|
|
279
|
-
const
|
|
280
|
-
if (!
|
|
255
|
+
const stored = window.localStorage.getItem("editor.sidebarStacks");
|
|
256
|
+
if (!stored) {
|
|
281
257
|
return normalizeSidebarStacks(openSidebars, defaultStacks);
|
|
282
258
|
}
|
|
259
|
+
const parsed = JSON.parse(stored);
|
|
283
260
|
if (!Array.isArray(parsed) ||
|
|
284
261
|
!parsed.every((x) => Array.isArray(x) && x.every((id) => typeof id === "string"))) {
|
|
285
262
|
return normalizeSidebarStacks(openSidebars, defaultStacks);
|
|
@@ -301,19 +278,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
301
278
|
}, [openSidebars, normalizeSidebarStacks]);
|
|
302
279
|
// Persist stacks independently of the URL (user layout preference).
|
|
303
280
|
useEffect(() => {
|
|
281
|
+
if (typeof window === "undefined")
|
|
282
|
+
return;
|
|
304
283
|
try {
|
|
305
|
-
|
|
284
|
+
window.localStorage.setItem("editor.sidebarStacks", JSON.stringify(sidebarStacks));
|
|
306
285
|
}
|
|
307
286
|
catch { }
|
|
308
287
|
}, [sidebarStacks]);
|
|
309
288
|
// Persist locked sidebars to localStorage.
|
|
310
289
|
useEffect(() => {
|
|
290
|
+
if (typeof window === "undefined")
|
|
291
|
+
return;
|
|
311
292
|
try {
|
|
312
|
-
|
|
293
|
+
window.localStorage.setItem("editor.lockedSidebars", JSON.stringify(lockedSidebars));
|
|
313
294
|
}
|
|
314
295
|
catch { }
|
|
315
296
|
}, [lockedSidebars]);
|
|
297
|
+
// Legacy aliases for backwards compatibility
|
|
316
298
|
const viewName = workspaceId;
|
|
299
|
+
const setViewName = setWorkspaceId;
|
|
300
|
+
const viewNameRef = workspaceIdRef;
|
|
301
|
+
const previousViewName = previousWorkspaceId;
|
|
302
|
+
const setPreviousViewName = setPreviousWorkspaceId;
|
|
317
303
|
const [compareMode, setCompareModeState] = useState(false);
|
|
318
304
|
const [componentDesignerComponent, setComponentDesignerComponent] = useState();
|
|
319
305
|
const [componentDesignerRendering, setComponentDesignerRendering] = useState();
|
|
@@ -340,29 +326,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
340
326
|
activeSlotIdRef.current = activeSlotId;
|
|
341
327
|
}, [activeSlotId]);
|
|
342
328
|
const [slotContexts, setSlotContexts] = useState(() => new Map());
|
|
343
|
-
const promptSessionReconnect = useCallback((reason) => {
|
|
344
|
-
const description = reason && reason !== "session-revoked"
|
|
345
|
-
? `${reason}. Click reconnect to continue in this browser.`
|
|
346
|
-
: "You were disconnected because this account is active in another browser.";
|
|
347
|
-
toast.error("Session disconnected", {
|
|
348
|
-
id: "session-revoked",
|
|
349
|
-
description,
|
|
350
|
-
action: {
|
|
351
|
-
label: "Reconnect",
|
|
352
|
-
onClick: async () => {
|
|
353
|
-
const result = await reconnectSession(sessionId);
|
|
354
|
-
if (result.type === "success") {
|
|
355
|
-
window.location.reload();
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
toast.error("Reconnect failed", {
|
|
359
|
-
description: "Could not claim this browser session. Try again.",
|
|
360
|
-
});
|
|
361
|
-
},
|
|
362
|
-
},
|
|
363
|
-
duration: Infinity,
|
|
364
|
-
});
|
|
365
|
-
}, [sessionId]);
|
|
366
329
|
// Track previous item ID to detect actual navigation between pages
|
|
367
330
|
const previousItemIdRef = useRef(undefined);
|
|
368
331
|
useEffect(() => {
|
|
@@ -391,9 +354,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
391
354
|
// Ref to track when we're handling a popstate event (browser back/forward)
|
|
392
355
|
// This prevents the URL sync effect from pushing new history entries during back navigation
|
|
393
356
|
const isHandlingPopStateRef = useRef(false);
|
|
394
|
-
// When switchWorkspace already pushed a URL entry, the follow-up URL sync
|
|
395
|
-
// effect should only *replace* that entry (not push a second one).
|
|
396
|
-
const switchWorkspacePushedRef = useRef(false);
|
|
397
357
|
// Ref to track the last known URL for the popstate handler
|
|
398
358
|
// This is updated both when the popstate handler runs AND when the URL sync effect pushes a new URL
|
|
399
359
|
// Without this, the popstate handler would have a stale lastUrl value after pushState calls
|
|
@@ -410,16 +370,26 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
410
370
|
const [showSuggestedEditsDiff, setShowSuggestedEditsDiff] = useState(false);
|
|
411
371
|
const [availableCommentTags, setAvailableCommentTags] = useState([]);
|
|
412
372
|
const [showComments, setShowComments] = useState(() => {
|
|
413
|
-
|
|
373
|
+
const savedShowComments = typeof window !== "undefined"
|
|
374
|
+
? localStorage.getItem("editor.showComments")
|
|
375
|
+
: null;
|
|
376
|
+
return savedShowComments ? JSON.parse(savedShowComments) : true;
|
|
414
377
|
});
|
|
415
378
|
useEffect(() => {
|
|
416
|
-
|
|
379
|
+
if (typeof window !== "undefined") {
|
|
380
|
+
localStorage.setItem("editor.showComments", JSON.stringify(showComments));
|
|
381
|
+
}
|
|
417
382
|
}, [showComments]);
|
|
418
383
|
const [showResolvedComments, setShowResolvedComments] = useState(() => {
|
|
419
|
-
|
|
384
|
+
const saved = typeof window !== "undefined"
|
|
385
|
+
? localStorage.getItem("editor.showResolvedComments")
|
|
386
|
+
: null;
|
|
387
|
+
return saved ? JSON.parse(saved) : false;
|
|
420
388
|
});
|
|
421
389
|
useEffect(() => {
|
|
422
|
-
|
|
390
|
+
if (typeof window !== "undefined") {
|
|
391
|
+
localStorage.setItem("editor.showResolvedComments", JSON.stringify(showResolvedComments));
|
|
392
|
+
}
|
|
423
393
|
}, [showResolvedComments]);
|
|
424
394
|
const [selectedComment, setSelectedComment] = useState();
|
|
425
395
|
const [browseHistory, setBrowseHistory] = useState(() => {
|
|
@@ -438,12 +408,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
438
408
|
visitedAt: entry.visitedAt,
|
|
439
409
|
}));
|
|
440
410
|
});
|
|
441
|
-
// Navigation history for browser history (
|
|
411
|
+
// Navigation history for browser history (view + item combinations)
|
|
442
412
|
const [navigationHistory, setNavigationHistory] = useState(() => {
|
|
443
|
-
// Initialize from browse history with
|
|
413
|
+
// Initialize from browse history with current view
|
|
444
414
|
if (!userInfo.browseHistory)
|
|
445
415
|
return [];
|
|
446
416
|
const defaultWorkspaceId = searchParams.get("workspace") ??
|
|
417
|
+
searchParams.get("view") ??
|
|
447
418
|
configuration.editor.defaultWorkspace ??
|
|
448
419
|
configuration.editor.workspaces?.[0]?.id ??
|
|
449
420
|
"editor";
|
|
@@ -475,43 +446,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
475
446
|
const [statusMessage, setStatusMessage] = useState("");
|
|
476
447
|
const [focusFieldComponentId, setFocusFieldComponentId] = useState();
|
|
477
448
|
const [enableCompletions, setEnableCompletions] = useState(false);
|
|
478
|
-
const [
|
|
479
|
-
const [slotComponentNavigatorVisibility, setSlotComponentNavigatorVisibility] = useState({});
|
|
480
|
-
useEffect(() => {
|
|
481
|
-
setSlotComponentNavigatorVisibility((prev) => {
|
|
482
|
-
const next = {};
|
|
483
|
-
let changed = false;
|
|
484
|
-
for (const slot of editorSlots) {
|
|
485
|
-
if (Object.prototype.hasOwnProperty.call(prev, slot.slotId)) {
|
|
486
|
-
next[slot.slotId] = prev[slot.slotId];
|
|
487
|
-
}
|
|
488
|
-
else {
|
|
489
|
-
next[slot.slotId] = showComponentNavigatorDefault;
|
|
490
|
-
changed = true;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
if (Object.keys(prev).length !== editorSlots.length) {
|
|
494
|
-
changed = true;
|
|
495
|
-
}
|
|
496
|
-
return changed ? next : prev;
|
|
497
|
-
});
|
|
498
|
-
}, [editorSlots, showComponentNavigatorDefault]);
|
|
449
|
+
const [showComponentNavigator, setShowComponentNavigator] = useState(userPreferences.showComponentNavigator ?? false);
|
|
499
450
|
const [showAgentsPanel, setShowAgentsPanel] = useState(userPreferences.showAgentsPanel ?? false);
|
|
500
451
|
const [showMinimap, setShowMinimap] = useState(userPreferences.showMinimap ?? true);
|
|
501
452
|
const [showHelpTerminal, setShowHelpTerminal] = useState(false);
|
|
502
453
|
const [helpTerminalInitialPrompt, setHelpTerminalInitialPrompt] = useState(undefined);
|
|
503
454
|
const [helpTerminalProfileName, setHelpTerminalProfileName] = useState(undefined);
|
|
504
455
|
const [helpTerminalActiveTab, setHelpTerminalActiveTab] = useState(undefined);
|
|
505
|
-
const [
|
|
506
|
-
const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(false);
|
|
507
|
-
const [selectedAgentsWorkspaceAgentId, setSelectedAgentsWorkspaceAgentId] = useState(null);
|
|
456
|
+
const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(true);
|
|
508
457
|
const [activeEditorTab, setActiveEditorTab] = useState(null);
|
|
509
458
|
const [showLayoutComponents, setShowLayoutComponents] = useState(userPreferences.showLayoutComponents ?? false);
|
|
510
459
|
const { quotaInfo, setQuotaInfo, isQuotaExceeded, getQuotaWarningMessage } = useQuota({
|
|
511
460
|
showError: ({ summary, details }) => showErrorToast({ summary, details }),
|
|
512
461
|
});
|
|
513
462
|
const [webSocketMessages, setWebSocketMessages] = useState([]);
|
|
514
|
-
const [socketDiagnostics, setSocketDiagnostics] = useState(() => createEditorSocketDiagnostics(sessionId));
|
|
515
463
|
const [favorites, setFavorites] = useState([]);
|
|
516
464
|
// Quick item switcher state
|
|
517
465
|
const [quickSwitcherVisible, setQuickSwitcherVisible] = useState(false);
|
|
@@ -529,12 +477,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
529
477
|
if (!startupChecks.hasBlockingIssues)
|
|
530
478
|
return;
|
|
531
479
|
// Don't redirect if already in settings workspace - let user navigate freely within settings
|
|
532
|
-
const currentWorkspace = searchParams.get("workspace");
|
|
480
|
+
const currentWorkspace = searchParams.get("workspace") ?? searchParams.get("view");
|
|
533
481
|
if (currentWorkspace === "settings")
|
|
534
482
|
return;
|
|
535
483
|
// Redirect to the status panel (where user can see all issues and navigate to fixes)
|
|
536
484
|
const url = new URL(window.location.href);
|
|
537
485
|
url.searchParams.set("workspace", "settings");
|
|
486
|
+
url.searchParams.delete("view"); // Remove legacy param
|
|
538
487
|
url.searchParams.set("ccpanel", "status");
|
|
539
488
|
router.push(url.toString(), { scroll: false });
|
|
540
489
|
}, [
|
|
@@ -552,16 +501,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
552
501
|
setMode(queryMode);
|
|
553
502
|
}
|
|
554
503
|
}, [searchParams, isInitialLoad]);
|
|
555
|
-
useEffect(() => {
|
|
556
|
-
if (!isInitialLoad)
|
|
557
|
-
return;
|
|
558
|
-
const helpParam = searchParams.get("help");
|
|
559
|
-
if (helpParam) {
|
|
560
|
-
setHelpTerminalActiveTab("manual");
|
|
561
|
-
setShowHelpTerminal(true);
|
|
562
|
-
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true" ? null : helpParam);
|
|
563
|
-
}
|
|
564
|
-
}, [searchParams, isInitialLoad]);
|
|
565
504
|
useEffect(() => {
|
|
566
505
|
if (mode === "suggestions") {
|
|
567
506
|
// Ensure we're in the editor workspace and open the feedback sidebar
|
|
@@ -608,19 +547,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
608
547
|
setSlotContexts((prev) => {
|
|
609
548
|
if (!prev.has(slotId))
|
|
610
549
|
return prev;
|
|
611
|
-
if (slotId === activeSlotIdRef.current) {
|
|
612
|
-
const activeCtx = prev.get(slotId);
|
|
613
|
-
if (activeCtx) {
|
|
614
|
-
lastActiveSlotContextRef.current = activeCtx;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
550
|
const next = new Map(prev);
|
|
618
551
|
next.delete(slotId);
|
|
619
552
|
return next;
|
|
620
553
|
});
|
|
621
554
|
}, []);
|
|
622
555
|
const slotContextsRef = useRef(slotContexts);
|
|
623
|
-
const lastActiveSlotContextRef = useRef(null);
|
|
624
556
|
useEffect(() => {
|
|
625
557
|
slotContextsRef.current = slotContexts;
|
|
626
558
|
}, [slotContexts]);
|
|
@@ -646,12 +578,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
646
578
|
const activeSlotContext = activeSlotId
|
|
647
579
|
? slotContexts.get(activeSlotId)
|
|
648
580
|
: undefined;
|
|
649
|
-
const isComponentNavigatorOpenForSlot = useCallback((slotId) => {
|
|
650
|
-
if (!slotId)
|
|
651
|
-
return showComponentNavigatorDefault;
|
|
652
|
-
return (slotComponentNavigatorVisibility[slotId] ?? showComponentNavigatorDefault);
|
|
653
|
-
}, [slotComponentNavigatorVisibility, showComponentNavigatorDefault]);
|
|
654
|
-
const showComponentNavigator = isComponentNavigatorOpenForSlot(activeSlotId);
|
|
655
581
|
// Sync global compareMode from the active slot's compareMode for URL syncing
|
|
656
582
|
useEffect(() => {
|
|
657
583
|
if (activeSlotContext && activeSlotContext.compareMode !== compareMode) {
|
|
@@ -699,9 +625,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
699
625
|
const isItemUsedInCurrentPage = useCallback((item) => pageItemsSetRef.current.has(makeItemKey(item)), [makeItemKey]);
|
|
700
626
|
const socketMessageListeners = useRef(new Set());
|
|
701
627
|
const [socketConnectionVersion, setSocketConnectionVersion] = useState(0);
|
|
702
|
-
useEffect(() => {
|
|
703
|
-
setSocketDiagnostics(createEditorSocketDiagnostics(sessionId));
|
|
704
|
-
}, [sessionId]);
|
|
705
628
|
const addSocketMessageListener = useCallback((callback) => {
|
|
706
629
|
socketMessageListeners.current.add(callback);
|
|
707
630
|
return () => socketMessageListeners.current.delete(callback);
|
|
@@ -786,13 +709,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
786
709
|
console.error(`No workspace found for id: ${workspaceId}`);
|
|
787
710
|
return null;
|
|
788
711
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
return (configuration.commands.keyboardCommands ?? []).filter((command) => activeCommandIds.has(command.id));
|
|
792
|
-
}, [
|
|
793
|
-
currentWorkspace.keyboardCommandIds,
|
|
794
|
-
configuration.commands.keyboardCommands,
|
|
795
|
-
]);
|
|
712
|
+
// Legacy alias for backwards compatibility
|
|
713
|
+
const currentView = currentWorkspace;
|
|
796
714
|
useEffect(() => {
|
|
797
715
|
if (currentWorkspace?.component) {
|
|
798
716
|
setCenterPanelView(currentWorkspace.component);
|
|
@@ -829,59 +747,30 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
829
747
|
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
830
748
|
window.history.replaceState(null, "", newUrl);
|
|
831
749
|
}, [setIsTourActive]);
|
|
832
|
-
const isMobile = useMediaQuery("(max-width:
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
if (isMobile) {
|
|
837
|
-
setLockedSidebars([]);
|
|
838
|
-
const current = openSidebarsRef.current;
|
|
839
|
-
const lastSidebar = current[current.length - 1];
|
|
840
|
-
if (current.length > 1 && lastSidebar) {
|
|
841
|
-
const trimmed = [lastSidebar];
|
|
842
|
-
openSidebarsRef.current = trimmed;
|
|
843
|
-
setOpenSidebars(trimmed);
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
}, [isMobile]);
|
|
847
|
-
const setComponentNavigatorOpenForSlot = useCallback((slotId, value) => {
|
|
848
|
-
const previousValue = isComponentNavigatorOpenForSlot(slotId);
|
|
849
|
-
const newValue = typeof value === "function" ? value(previousValue) : value;
|
|
850
|
-
if (slotId) {
|
|
851
|
-
setSlotComponentNavigatorVisibility((prev) => {
|
|
852
|
-
const currentValue = prev[slotId] ?? showComponentNavigatorDefault;
|
|
853
|
-
if (currentValue === newValue && prev[slotId] !== undefined) {
|
|
854
|
-
return prev;
|
|
855
|
-
}
|
|
856
|
-
return {
|
|
857
|
-
...prev,
|
|
858
|
-
[slotId]: newValue,
|
|
859
|
-
};
|
|
860
|
-
});
|
|
861
|
-
}
|
|
862
|
-
setShowComponentNavigatorDefault(newValue);
|
|
750
|
+
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
751
|
+
const handleSetShowComponentNavigator = useCallback((value) => {
|
|
752
|
+
const newValue = typeof value === "function" ? value(showComponentNavigator) : value;
|
|
753
|
+
setShowComponentNavigator(newValue);
|
|
863
754
|
setUserPreferences({ showComponentNavigator: newValue });
|
|
755
|
+
// On mobile, close Agents Panel when opening Component Navigator
|
|
864
756
|
if (isMobile && newValue) {
|
|
865
757
|
setShowAgentsPanel(false);
|
|
866
758
|
setUserPreferences({ showAgentsPanel: false });
|
|
867
759
|
}
|
|
868
760
|
}, [
|
|
869
|
-
|
|
870
|
-
|
|
761
|
+
showComponentNavigator,
|
|
762
|
+
setShowComponentNavigator,
|
|
871
763
|
setUserPreferences,
|
|
872
764
|
isMobile,
|
|
873
765
|
setShowAgentsPanel,
|
|
874
766
|
]);
|
|
875
|
-
const handleSetShowComponentNavigator = useCallback((value) => {
|
|
876
|
-
setComponentNavigatorOpenForSlot(activeSlotIdRef.current, value);
|
|
877
|
-
}, [setComponentNavigatorOpenForSlot]);
|
|
878
767
|
const handleSetShowAgentsPanel = useCallback((value) => {
|
|
879
768
|
const newValue = typeof value === "function" ? value(showAgentsPanel) : value;
|
|
880
769
|
setShowAgentsPanel(newValue);
|
|
881
770
|
setUserPreferences({ showAgentsPanel: newValue });
|
|
882
771
|
// On mobile, close Component Navigator when opening Agents Panel
|
|
883
772
|
if (isMobile && newValue) {
|
|
884
|
-
|
|
773
|
+
setShowComponentNavigator(false);
|
|
885
774
|
setUserPreferences({ showComponentNavigator: false });
|
|
886
775
|
}
|
|
887
776
|
}, [
|
|
@@ -889,40 +778,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
889
778
|
setShowAgentsPanel,
|
|
890
779
|
setUserPreferences,
|
|
891
780
|
isMobile,
|
|
892
|
-
|
|
781
|
+
setShowComponentNavigator,
|
|
893
782
|
]);
|
|
894
|
-
// Mobile editor panel state (EditorForm shown in bottom panel on mobile)
|
|
895
|
-
const [mobileEditorPanelOpen, setMobileEditorPanelOpenRaw] = useState(false);
|
|
896
|
-
const [dismissedMobilePanelToken, setDismissedMobilePanelToken] = useState(null);
|
|
897
|
-
const previousActiveSlotIdRef = useRef(null);
|
|
898
|
-
const mobilePanelDismissToken = useMemo(() => {
|
|
899
|
-
const selectionKey = selection.join(",");
|
|
900
|
-
return [
|
|
901
|
-
activeSlotId || "no-slot",
|
|
902
|
-
selectionKey,
|
|
903
|
-
insertMode ? "insert" : "browse",
|
|
904
|
-
].join("|");
|
|
905
|
-
}, [activeSlotId, insertMode, selection]);
|
|
906
|
-
useEffect(() => {
|
|
907
|
-
const previousActiveSlotId = previousActiveSlotIdRef.current;
|
|
908
|
-
if (previousActiveSlotId !== activeSlotId) {
|
|
909
|
-
setDismissedMobilePanelToken(null);
|
|
910
|
-
}
|
|
911
|
-
previousActiveSlotIdRef.current = activeSlotId;
|
|
912
|
-
}, [activeSlotId]);
|
|
913
|
-
const handleSetMobileEditorPanelOpen = useCallback((open) => {
|
|
914
|
-
setMobileEditorPanelOpenRaw(open);
|
|
915
|
-
if (!open) {
|
|
916
|
-
setDismissedMobilePanelToken(mobilePanelDismissToken);
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
setDismissedMobilePanelToken(null);
|
|
920
|
-
if (open && isMobile) {
|
|
921
|
-
// Close all sidebars when opening the editor panel on mobile
|
|
922
|
-
openSidebarsRef.current = [];
|
|
923
|
-
setOpenSidebars([]);
|
|
924
|
-
}
|
|
925
|
-
}, [isMobile, mobilePanelDismissToken]);
|
|
926
783
|
const handleSetShowMinimap = useCallback((value) => {
|
|
927
784
|
const newValue = typeof value === "function" ? value(showMinimap) : value;
|
|
928
785
|
setShowMinimap(newValue);
|
|
@@ -936,7 +793,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
936
793
|
setHelpTerminalInitialPrompt(undefined);
|
|
937
794
|
setHelpTerminalProfileName(undefined);
|
|
938
795
|
setHelpTerminalActiveTab(undefined);
|
|
939
|
-
setSelectedHelpSectionId(null);
|
|
940
796
|
}
|
|
941
797
|
}, [showHelpTerminal]);
|
|
942
798
|
const toggleHelpTerminal = useCallback((options) => {
|
|
@@ -979,27 +835,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
979
835
|
setOpenSidebars(newOrder);
|
|
980
836
|
setSidebarStacks((prev) => normalizeSidebarStacks(newOrder, prev));
|
|
981
837
|
}, []);
|
|
982
|
-
const ensureSidebarPinned = useCallback((sidebarId) => {
|
|
983
|
-
const currentPinnedSidebars = pinnedSidebarsRef.current;
|
|
984
|
-
if (currentPinnedSidebars.includes(sidebarId)) {
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
|
-
const newPinnedSidebars = [...currentPinnedSidebars, sidebarId];
|
|
988
|
-
pinnedSidebarsRef.current = newPinnedSidebars;
|
|
989
|
-
setPinnedSidebars(newPinnedSidebars);
|
|
990
|
-
setUserPreferences({ pinnedSidebars: newPinnedSidebars });
|
|
991
|
-
}, [setUserPreferences]);
|
|
992
838
|
// messageHandler is defined after loadItem/loadHistory declarations to avoid temporal dead zones
|
|
993
839
|
const user = activeSessions.find((x) => x.sessionId === sessionId)?.user ||
|
|
994
840
|
userInfo.user;
|
|
995
|
-
// Self-heal if our session disappears (e.g., after HMR)
|
|
996
|
-
// is showing so we don't spam recovery attempts when the connection was rejected.
|
|
841
|
+
// Self-heal if our session disappears (e.g., after HMR)
|
|
997
842
|
const missingSessionRecoveryTimerRef = useRef(null);
|
|
998
843
|
const missingSessionRecoveryAttemptsRef = useRef(0);
|
|
999
|
-
const concurrentUserLimitErrorRef = useRef(null);
|
|
1000
844
|
useEffect(() => {
|
|
1001
|
-
if (concurrentUserLimitErrorRef.current !== null)
|
|
1002
|
-
return;
|
|
1003
845
|
const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
|
|
1004
846
|
if (hasMySession) {
|
|
1005
847
|
// Reset recovery state when we see ourselves again
|
|
@@ -1015,6 +857,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1015
857
|
return;
|
|
1016
858
|
const attempt = missingSessionRecoveryAttemptsRef.current + 1;
|
|
1017
859
|
const delay = Math.min(250 * Math.pow(2, attempt - 1), 2000);
|
|
860
|
+
console.warn(`⚠️ Current session not present in active sessions. Recovery attempt ${attempt} in ${delay}ms...`);
|
|
1018
861
|
missingSessionRecoveryTimerRef.current = setTimeout(() => {
|
|
1019
862
|
missingSessionRecoveryTimerRef.current = null;
|
|
1020
863
|
missingSessionRecoveryAttemptsRef.current = attempt;
|
|
@@ -1023,7 +866,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1023
866
|
}
|
|
1024
867
|
else {
|
|
1025
868
|
// Force a reconnect to refresh presence after several failed nudges
|
|
1026
|
-
console.warn("Session presence did not recover after retries. Forcing reconnect.");
|
|
1027
869
|
try {
|
|
1028
870
|
globalThis.editorSocket?.close(4000, "recover-presence");
|
|
1029
871
|
}
|
|
@@ -1043,15 +885,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1043
885
|
// Initialize lastUrlRef to current URL on mount
|
|
1044
886
|
lastUrlRef.current = window.location.href;
|
|
1045
887
|
const keepAliveUrl = "/parhelia/keepalive";
|
|
1046
|
-
const
|
|
888
|
+
const interval = setInterval(() => {
|
|
1047
889
|
fetch(keepAliveUrl + "?ts=" + Date.now())
|
|
1048
890
|
.then((response) => {
|
|
1049
|
-
if (response.headers.get("X-Parhelia-Session-Revoked") === "true") {
|
|
1050
|
-
window.dispatchEvent(new CustomEvent("parhelia:session-revoked", {
|
|
1051
|
-
detail: { reason: "session-revoked" },
|
|
1052
|
-
}));
|
|
1053
|
-
return;
|
|
1054
|
-
}
|
|
1055
891
|
if (response.status === 401 || response.status === 403) {
|
|
1056
892
|
toast.error("Your session has expired", {
|
|
1057
893
|
description: "Please login again to continue editing.",
|
|
@@ -1064,24 +900,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1064
900
|
}
|
|
1065
901
|
})
|
|
1066
902
|
.catch((error) => console.error("Keep Alive error:", error));
|
|
1067
|
-
};
|
|
1068
|
-
const keepaliveIntervalMs = (() => {
|
|
1069
|
-
const param = new URLSearchParams(window.location.search).get("keepaliveIntervalMs");
|
|
1070
|
-
if (!param)
|
|
1071
|
-
return 5 * 60 * 1000;
|
|
1072
|
-
const ms = parseInt(param, 10);
|
|
1073
|
-
return Number.isFinite(ms) && ms >= 2000 && ms <= 60000
|
|
1074
|
-
? ms
|
|
1075
|
-
: 5 * 60 * 1000;
|
|
1076
|
-
})();
|
|
1077
|
-
const interval = setInterval(() => {
|
|
1078
|
-
runSessionCheck();
|
|
1079
|
-
}, keepaliveIntervalMs);
|
|
1080
|
-
const handleVisibilityChange = () => {
|
|
1081
|
-
if (document.visibilityState === "visible") {
|
|
1082
|
-
runSessionCheck();
|
|
1083
|
-
}
|
|
1084
|
-
};
|
|
903
|
+
}, 5 * 60 * 1000);
|
|
1085
904
|
const handleMessage = (event) => {
|
|
1086
905
|
if (event.data.type === "componentsSelected") {
|
|
1087
906
|
setSelection(event.data.componentIds);
|
|
@@ -1096,8 +915,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1096
915
|
isHandlingPopStateRef.current = true;
|
|
1097
916
|
// Sync URL parameters back to component state for browser navigation
|
|
1098
917
|
const urlParams = new URLSearchParams(window.location.search);
|
|
1099
|
-
|
|
1100
|
-
|
|
918
|
+
// Handle workspace changes (with legacy view fallback)
|
|
919
|
+
const urlWorkspace = urlParams.get("workspace") ?? urlParams.get("view");
|
|
920
|
+
if (urlWorkspace && urlWorkspace !== viewNameRef.current) {
|
|
1101
921
|
setWorkspaceId(urlWorkspace);
|
|
1102
922
|
}
|
|
1103
923
|
// Handle sidebar changes
|
|
@@ -1114,18 +934,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1114
934
|
if (compareValue !== compareMode) {
|
|
1115
935
|
setCompareMode(compareValue);
|
|
1116
936
|
}
|
|
1117
|
-
// Handle help panel changes
|
|
1118
|
-
const helpParam = urlParams.get("help");
|
|
1119
|
-
if (helpParam) {
|
|
1120
|
-
setHelpTerminalActiveTab("manual");
|
|
1121
|
-
setShowHelpTerminal(true);
|
|
1122
|
-
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true"
|
|
1123
|
-
? null
|
|
1124
|
-
: helpParam);
|
|
1125
|
-
}
|
|
1126
|
-
else {
|
|
1127
|
-
handleSetShowHelpTerminal(false);
|
|
1128
|
-
}
|
|
1129
937
|
// Handle mode changes
|
|
1130
938
|
const urlMode = urlParams.get("mode");
|
|
1131
939
|
if (urlMode && urlMode !== mode) {
|
|
@@ -1181,11 +989,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1181
989
|
};
|
|
1182
990
|
window.addEventListener("message", handleMessage);
|
|
1183
991
|
window.addEventListener("popstate", handlePopState);
|
|
1184
|
-
window.addEventListener("visibilitychange", handleVisibilityChange);
|
|
1185
992
|
return () => {
|
|
1186
993
|
window.removeEventListener("message", handleMessage);
|
|
1187
994
|
window.removeEventListener("popstate", handlePopState);
|
|
1188
|
-
window.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1189
995
|
clearInterval(interval);
|
|
1190
996
|
};
|
|
1191
997
|
}, []);
|
|
@@ -1195,34 +1001,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1195
1001
|
if (searchParams.get("noTour") !== null) {
|
|
1196
1002
|
return;
|
|
1197
1003
|
}
|
|
1198
|
-
// Don't start tour when there are setup errors (user is or will be on system status page)
|
|
1199
|
-
if (startupChecks.state === "complete" && startupChecks.hasBlockingIssues) {
|
|
1200
|
-
return;
|
|
1201
|
-
}
|
|
1202
|
-
// Don't start tour when already on settings system status page
|
|
1203
|
-
if (viewName === "settings" && searchParams.get("ccpanel") === "status") {
|
|
1204
|
-
return;
|
|
1205
|
-
}
|
|
1206
|
-
// Wait for startup checks so we know whether we'll redirect to status
|
|
1207
|
-
if (startupChecks.state !== "complete") {
|
|
1208
|
-
return;
|
|
1209
|
-
}
|
|
1210
1004
|
const tour = configuration.activeTour;
|
|
1211
1005
|
const key = tour === "default" ? "editor.tourShown" : "editor.tourShown." + tour;
|
|
1212
|
-
const tourShown =
|
|
1006
|
+
const tourShown = localStorage.getItem(key);
|
|
1213
1007
|
if (!tourShown) {
|
|
1214
1008
|
startTour();
|
|
1215
|
-
|
|
1009
|
+
localStorage.setItem(key, "true");
|
|
1216
1010
|
}
|
|
1217
|
-
}, [
|
|
1218
|
-
user,
|
|
1219
|
-
startupChecks.state,
|
|
1220
|
-
startupChecks.hasBlockingIssues,
|
|
1221
|
-
viewName,
|
|
1222
|
-
searchParams,
|
|
1223
|
-
configuration.activeTour,
|
|
1224
|
-
startTour,
|
|
1225
|
-
]);
|
|
1011
|
+
}, [user]);
|
|
1226
1012
|
// WebSocket initialization is performed after messageHandler is defined
|
|
1227
1013
|
// Defer URL sync until loadItem is defined below
|
|
1228
1014
|
// Mark end of initial load phase
|
|
@@ -1354,8 +1140,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1354
1140
|
const loadComments = useCallback(async () => {
|
|
1355
1141
|
if (!currentItemDescriptor)
|
|
1356
1142
|
return;
|
|
1357
|
-
const
|
|
1358
|
-
const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version, reviewId ?? undefined);
|
|
1143
|
+
const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version);
|
|
1359
1144
|
if (handleErrorResult(result, ui, state))
|
|
1360
1145
|
return;
|
|
1361
1146
|
setComments((x) => {
|
|
@@ -1368,7 +1153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1368
1153
|
allComments.sort((a, b) => a.position - b.position);
|
|
1369
1154
|
return allComments;
|
|
1370
1155
|
});
|
|
1371
|
-
}, [currentItemDescriptor
|
|
1156
|
+
}, [currentItemDescriptor]);
|
|
1372
1157
|
// Assuming currentItemDescriptor, ui, state, handleErrorResult, and setSuggestedEdits
|
|
1373
1158
|
// are available in your component context.
|
|
1374
1159
|
const loadSuggestedEdits = useCallback(async () => {
|
|
@@ -1377,8 +1162,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1377
1162
|
const result = await getSuggestedEdits(item.descriptor.id, item.descriptor.language, item.descriptor.version);
|
|
1378
1163
|
if (handleErrorResult(result, ui, state))
|
|
1379
1164
|
return;
|
|
1380
|
-
|
|
1381
|
-
setSuggestedEdits(edits);
|
|
1165
|
+
setSuggestedEdits(result.data || []);
|
|
1382
1166
|
}, [item]);
|
|
1383
1167
|
const loadFavorites = useCallback(async () => {
|
|
1384
1168
|
try {
|
|
@@ -1452,25 +1236,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1452
1236
|
return idB.localeCompare(idA);
|
|
1453
1237
|
});
|
|
1454
1238
|
}, []);
|
|
1455
|
-
const normalizeEditHistoryPayload = useCallback((value) => {
|
|
1456
|
-
if (Array.isArray(value)) {
|
|
1457
|
-
return value;
|
|
1458
|
-
}
|
|
1459
|
-
if (value && typeof value === "object") {
|
|
1460
|
-
const payload = value;
|
|
1461
|
-
const candidates = [
|
|
1462
|
-
payload.operations,
|
|
1463
|
-
payload.history,
|
|
1464
|
-
payload.items,
|
|
1465
|
-
payload.data,
|
|
1466
|
-
];
|
|
1467
|
-
const firstArray = candidates.find((candidate) => Array.isArray(candidate));
|
|
1468
|
-
if (Array.isArray(firstArray)) {
|
|
1469
|
-
return firstArray;
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
return [];
|
|
1473
|
-
}, []);
|
|
1474
1239
|
useEffect(() => {
|
|
1475
1240
|
// Read fresh page from the mutable slot context ref chain.
|
|
1476
1241
|
// The slot context uses a stable ref that is mutated in-place (see editorSlotContext.ts),
|
|
@@ -1493,7 +1258,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1493
1258
|
if (handleErrorResult(result, ui, state))
|
|
1494
1259
|
return;
|
|
1495
1260
|
setEditHistory((prev) => {
|
|
1496
|
-
const next =
|
|
1261
|
+
const next = result.data || [];
|
|
1497
1262
|
if (!prev.length)
|
|
1498
1263
|
return sortEditHistoryByDateDesc(next);
|
|
1499
1264
|
if (!next.length)
|
|
@@ -1567,7 +1332,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1567
1332
|
return;
|
|
1568
1333
|
}
|
|
1569
1334
|
setEditHistory((prev) => {
|
|
1570
|
-
const next =
|
|
1335
|
+
const next = result.data || [];
|
|
1571
1336
|
const scope = {
|
|
1572
1337
|
mode: currentMode,
|
|
1573
1338
|
filterBySession: shouldFilterBySession,
|
|
@@ -1645,7 +1410,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1645
1410
|
console.error("[EditorShell] Failed to load item history:", result);
|
|
1646
1411
|
return;
|
|
1647
1412
|
}
|
|
1648
|
-
let operations =
|
|
1413
|
+
let operations = result.data || [];
|
|
1649
1414
|
// Client-side version filtering for current-version mode
|
|
1650
1415
|
if (currentMode === "current-version") {
|
|
1651
1416
|
// Defensive filter: only include operations for the current version
|
|
@@ -1721,7 +1486,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1721
1486
|
item,
|
|
1722
1487
|
currentItemDescriptor,
|
|
1723
1488
|
matchesHistoryScope,
|
|
1724
|
-
normalizeEditHistoryPayload,
|
|
1725
1489
|
sortEditHistoryByDateDesc,
|
|
1726
1490
|
]);
|
|
1727
1491
|
// Debounced history refresh to avoid hammering `/parhelia/editHistory` on rapid UI changes.
|
|
@@ -1787,14 +1551,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1787
1551
|
}
|
|
1788
1552
|
}
|
|
1789
1553
|
else if (historyMode !== "global" && currentItemDescriptor) {
|
|
1790
|
-
// Always load immediately for page-centric/current-version/timeline so we don't show
|
|
1791
|
-
// an empty history list for the debounce window (e.g. 600ms). The effect only runs on
|
|
1792
|
-
// mode or item id/lang/version change, not on every keystroke, so this avoids flaky
|
|
1793
|
-
// undo/redo tests and improves UX when switching to page-centric.
|
|
1794
1554
|
if (!historyInitialLoadDoneRef.current) {
|
|
1795
1555
|
historyInitialLoadDoneRef.current = true;
|
|
1556
|
+
refreshHistoryRef.current(historyMode);
|
|
1557
|
+
}
|
|
1558
|
+
else {
|
|
1559
|
+
debouncedRefreshHistoryRef.current(historyMode);
|
|
1796
1560
|
}
|
|
1797
|
-
refreshHistoryRef.current(historyMode);
|
|
1798
1561
|
}
|
|
1799
1562
|
else if (historyMode !== "global" && !currentItemDescriptor) {
|
|
1800
1563
|
// Clear history if no item loaded in page-centric modes
|
|
@@ -1904,6 +1667,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1904
1667
|
if (current.get("workspace") !== viewName) {
|
|
1905
1668
|
current.set("workspace", viewName);
|
|
1906
1669
|
}
|
|
1670
|
+
current.delete("view"); // Remove legacy view param
|
|
1907
1671
|
// Sync sidebar state
|
|
1908
1672
|
const currentSidebars = current.get("sidebar") ?? "";
|
|
1909
1673
|
const newSidebars = openSidebars.join(",");
|
|
@@ -1915,12 +1679,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1915
1679
|
current.delete("sidebar");
|
|
1916
1680
|
}
|
|
1917
1681
|
}
|
|
1918
|
-
if (showHelpTerminal) {
|
|
1919
|
-
current.set("help", selectedHelpSectionId ?? "contents");
|
|
1920
|
-
}
|
|
1921
|
-
else {
|
|
1922
|
-
current.delete("help");
|
|
1923
|
-
}
|
|
1924
1682
|
if (!compareMode) {
|
|
1925
1683
|
current.delete("compare");
|
|
1926
1684
|
current.delete("compareLanguage");
|
|
@@ -1945,11 +1703,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1945
1703
|
else {
|
|
1946
1704
|
current.delete("wizardid");
|
|
1947
1705
|
}
|
|
1948
|
-
// Only preserve
|
|
1949
|
-
if (viewName
|
|
1706
|
+
// Only preserve ccpanel parameter when on settings view, remove it otherwise
|
|
1707
|
+
if (viewName === "settings") {
|
|
1708
|
+
const ccpanel = current.get("ccpanel");
|
|
1709
|
+
if (ccpanel) {
|
|
1710
|
+
current.set("ccpanel", ccpanel);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
else {
|
|
1950
1714
|
current.delete("ccpanel");
|
|
1951
|
-
current.delete("providerId");
|
|
1952
|
-
current.delete("modelId");
|
|
1953
1715
|
}
|
|
1954
1716
|
// Preserve reviewId parameter if it exists (for review links)
|
|
1955
1717
|
// This ensures review links don't lose the reviewId when URL is synced
|
|
@@ -1968,13 +1730,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1968
1730
|
return;
|
|
1969
1731
|
}
|
|
1970
1732
|
if (newUrl !== oldUrl) {
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
}
|
|
1975
|
-
else {
|
|
1976
|
-
window.history.pushState(null, "", newUrl);
|
|
1977
|
-
}
|
|
1733
|
+
window.history.pushState(null, "", newUrl);
|
|
1734
|
+
// Update lastUrlRef so the popstate handler knows the current URL
|
|
1735
|
+
// This fixes the issue where goBack() wouldn't work because lastUrl was stale
|
|
1978
1736
|
lastUrlRef.current = newUrl;
|
|
1979
1737
|
}
|
|
1980
1738
|
}, [
|
|
@@ -1988,8 +1746,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1988
1746
|
fullscreen,
|
|
1989
1747
|
currentWizardId,
|
|
1990
1748
|
openSidebars,
|
|
1991
|
-
showHelpTerminal,
|
|
1992
|
-
selectedHelpSectionId,
|
|
1993
1749
|
]);
|
|
1994
1750
|
useEffect(() => {
|
|
1995
1751
|
async function load() {
|
|
@@ -2283,10 +2039,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2283
2039
|
useEffect(() => {
|
|
2284
2040
|
if (fullscreen &&
|
|
2285
2041
|
!searchParams.get("fullscreen") &&
|
|
2286
|
-
!configuration.forceFullscreen
|
|
2287
|
-
!isMobile)
|
|
2042
|
+
!configuration.forceFullscreen)
|
|
2288
2043
|
setShowFullscreenHint(true);
|
|
2289
|
-
}, [fullscreen, configuration.forceFullscreen, searchParams
|
|
2044
|
+
}, [fullscreen, configuration.forceFullscreen, searchParams]);
|
|
2290
2045
|
const state = {
|
|
2291
2046
|
page,
|
|
2292
2047
|
configuration,
|
|
@@ -2385,35 +2140,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2385
2140
|
? existingOp.progress
|
|
2386
2141
|
: op.progress;
|
|
2387
2142
|
// IMPORTANT: Once canUndo becomes true, never downgrade it to false,
|
|
2388
|
-
// UNLESS this update indicates the operation was undone.
|
|
2389
|
-
//
|
|
2390
|
-
//
|
|
2391
|
-
|
|
2392
|
-
// without explicit undone/canRedo flags yet.
|
|
2393
|
-
const isExplicitUndoUpdate = op.undone === true || op.canRedo === true;
|
|
2394
|
-
const isInferredUndoCompletion = existingOp.executionStatus === "executing" &&
|
|
2395
|
-
op.executionStatus === "completed" &&
|
|
2396
|
-
existingOp.canUndo === true &&
|
|
2397
|
-
op.canUndo === false;
|
|
2398
|
-
const isUndoUpdate = isExplicitUndoUpdate || isInferredUndoCompletion;
|
|
2143
|
+
// UNLESS this update indicates the operation was undone. When an undo
|
|
2144
|
+
// completes, the server sends canUndo: false and canRedo: true (or undone: true).
|
|
2145
|
+
// We must respect that transition so the UI reflects the undo.
|
|
2146
|
+
const isUndoUpdate = op.undone === true || op.canRedo === true;
|
|
2399
2147
|
const mergedCanUndo = isUndoUpdate
|
|
2400
2148
|
? false
|
|
2401
2149
|
: existingOp.canUndo === true
|
|
2402
2150
|
? true
|
|
2403
2151
|
: op.canUndo;
|
|
2404
|
-
const mergedCanRedo = isUndoUpdate
|
|
2405
|
-
? true
|
|
2406
|
-
: op.canRedo ?? existingOp.canRedo;
|
|
2407
|
-
const mergedUndone = isUndoUpdate
|
|
2408
|
-
? true
|
|
2409
|
-
: op.undone ?? existingOp.undone;
|
|
2410
2152
|
const mergedOp = {
|
|
2411
2153
|
...existingOp,
|
|
2412
2154
|
...op,
|
|
2413
2155
|
progress: mergedProgress,
|
|
2414
2156
|
canUndo: mergedCanUndo,
|
|
2415
|
-
canRedo: mergedCanRedo,
|
|
2416
|
-
undone: mergedUndone,
|
|
2417
2157
|
};
|
|
2418
2158
|
// Ensure undone operations always have canRedo: true.
|
|
2419
2159
|
if (mergedOp.undone && !mergedOp.canRedo) {
|
|
@@ -2467,6 +2207,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2467
2207
|
});
|
|
2468
2208
|
// Ref for markOperationComplete callback (needed because operationsContext is created later)
|
|
2469
2209
|
const markOperationCompleteRef = useRef(null);
|
|
2210
|
+
// When the websocket is reconnecting, we can briefly lose the ability to send messages.
|
|
2211
|
+
// Agent dialog responses (e.g. questionnaire cancel/submit) must not be dropped, otherwise
|
|
2212
|
+
// the backend tool call can remain pending and tests/users will hang.
|
|
2213
|
+
const pendingAgentDialogResponsesRef = useRef([]);
|
|
2470
2214
|
// WebSocket message handler and connection
|
|
2471
2215
|
const messageHandler = useSocketMessageHandler({
|
|
2472
2216
|
sessionId,
|
|
@@ -2492,31 +2236,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2492
2236
|
markOperationCompleteRef.current?.(operationId);
|
|
2493
2237
|
},
|
|
2494
2238
|
});
|
|
2495
|
-
// Concurrent user limit error state
|
|
2496
|
-
const [concurrentUserLimitError, setConcurrentUserLimitError] = useState(null);
|
|
2497
|
-
concurrentUserLimitErrorRef.current = concurrentUserLimitError;
|
|
2498
|
-
const handleRetryConnection = useCallback(() => {
|
|
2499
|
-
setConcurrentUserLimitError(null);
|
|
2500
|
-
// Force reconnection by triggering a new connection attempt
|
|
2501
|
-
// The useEditorWebSocket hook will check availability again
|
|
2502
|
-
const socket = globalThis.editorSocket;
|
|
2503
|
-
if (socket) {
|
|
2504
|
-
socket.close();
|
|
2505
|
-
delete globalThis.editorSocket;
|
|
2506
|
-
}
|
|
2507
|
-
// The hook will automatically attempt to reconnect
|
|
2508
|
-
}, []);
|
|
2509
2239
|
const { socketRef: socketInstanceRef } = useEditorWebSocket({
|
|
2510
2240
|
sessionId,
|
|
2511
2241
|
onMessage: messageHandler,
|
|
2512
2242
|
onOpen: async () => {
|
|
2513
|
-
// Clear concurrent user limit error on successful connection
|
|
2514
|
-
setConcurrentUserLimitError(null);
|
|
2515
|
-
// Startup WebSocket probe may have failed with a blocking error while seats were full;
|
|
2516
|
-
// re-run status checks quietly so "1 error" does not stick after a successful connect.
|
|
2517
|
-
void startupChecks.recheckQuiet();
|
|
2518
2243
|
// Increment socket connection version to trigger re-subscriptions
|
|
2519
2244
|
setSocketConnectionVersion((v) => v + 1);
|
|
2245
|
+
// Flush any queued agent dialog responses now that the socket is open.
|
|
2246
|
+
// Keep this early so pending tool calls unblock ASAP.
|
|
2247
|
+
try {
|
|
2248
|
+
if (socketInstanceRef.current &&
|
|
2249
|
+
socketInstanceRef.current.readyState === WebSocket.OPEN &&
|
|
2250
|
+
pendingAgentDialogResponsesRef.current.length > 0) {
|
|
2251
|
+
// FIFO flush
|
|
2252
|
+
while (pendingAgentDialogResponsesRef.current.length > 0) {
|
|
2253
|
+
const queued = pendingAgentDialogResponsesRef.current.shift();
|
|
2254
|
+
socketInstanceRef.current.send(JSON.stringify(queued));
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
catch (e) {
|
|
2259
|
+
console.error("Failed to flush queued agent dialog responses:", e);
|
|
2260
|
+
}
|
|
2520
2261
|
// Fetch any running operations on (re)connect for auto-resume
|
|
2521
2262
|
// This ensures the UI shows operations that are still executing
|
|
2522
2263
|
try {
|
|
@@ -2532,37 +2273,24 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2532
2273
|
}
|
|
2533
2274
|
},
|
|
2534
2275
|
onError: (error) => console.error("WebSocket error:", error),
|
|
2535
|
-
onConcurrentUserLimit: (error) => {
|
|
2536
|
-
setConcurrentUserLimitError(error);
|
|
2537
|
-
},
|
|
2538
|
-
onSessionRevoked: () => promptSessionReconnect("session-revoked"),
|
|
2539
2276
|
connectSocket,
|
|
2540
2277
|
requestQuota,
|
|
2541
2278
|
sendClientInfo,
|
|
2542
|
-
setSocketDiagnostics,
|
|
2543
2279
|
});
|
|
2544
|
-
useEffect(() => {
|
|
2545
|
-
const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
|
|
2546
|
-
if (hasMySession &&
|
|
2547
|
-
socketInstanceRef.current?.readyState === WebSocket.OPEN) {
|
|
2548
|
-
toast.dismiss("session-revoked");
|
|
2549
|
-
}
|
|
2550
|
-
}, [activeSessions, sessionId, socketConnectionVersion, socketInstanceRef]);
|
|
2551
|
-
useEffect(() => {
|
|
2552
|
-
const handleRevoked = (event) => {
|
|
2553
|
-
const customEvent = event;
|
|
2554
|
-
promptSessionReconnect(customEvent?.detail?.reason);
|
|
2555
|
-
};
|
|
2556
|
-
window.addEventListener("parhelia:session-revoked", handleRevoked);
|
|
2557
|
-
return () => {
|
|
2558
|
-
window.removeEventListener("parhelia:session-revoked", handleRevoked);
|
|
2559
|
-
};
|
|
2560
|
-
}, [promptSessionReconnect]);
|
|
2561
2280
|
const sendSocketMessage = useCallback((message) => {
|
|
2562
2281
|
if (socketInstanceRef.current &&
|
|
2563
2282
|
socketInstanceRef.current.readyState === WebSocket.OPEN) {
|
|
2564
2283
|
socketInstanceRef.current.send(JSON.stringify(message));
|
|
2565
2284
|
}
|
|
2285
|
+
else if (message.type === "agent-dialog-response") {
|
|
2286
|
+
// Queue dialog responses to avoid losing them during reconnects.
|
|
2287
|
+
pendingAgentDialogResponsesRef.current.push(message);
|
|
2288
|
+
// Prevent unbounded growth in pathological scenarios.
|
|
2289
|
+
if (pendingAgentDialogResponsesRef.current.length > 50) {
|
|
2290
|
+
pendingAgentDialogResponsesRef.current =
|
|
2291
|
+
pendingAgentDialogResponsesRef.current.slice(-50);
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2566
2294
|
}, [socketInstanceRef]);
|
|
2567
2295
|
// URL update helper - defined early so it can be used by workspace/sidebar functions
|
|
2568
2296
|
const updateUrl = useCallback((params) => {
|
|
@@ -2606,9 +2334,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2606
2334
|
if (!options?.skipNavigationHistory) {
|
|
2607
2335
|
addNavigationEntry(targetWorkspaceId, item);
|
|
2608
2336
|
}
|
|
2609
|
-
//
|
|
2610
|
-
// will replaceState instead of pushing a second history entry.
|
|
2611
|
-
switchWorkspacePushedRef.current = true;
|
|
2337
|
+
// Update URL
|
|
2612
2338
|
updateUrl({ workspace: targetWorkspaceId });
|
|
2613
2339
|
if (typeof document.startViewTransition === "function") {
|
|
2614
2340
|
document.startViewTransition(() => {
|
|
@@ -2629,6 +2355,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2629
2355
|
updateUrl,
|
|
2630
2356
|
handleSetShowAgentsPanel,
|
|
2631
2357
|
]);
|
|
2358
|
+
// Legacy alias for backwards compatibility
|
|
2359
|
+
const switchView = useCallback((viewName, options) => {
|
|
2360
|
+
// Handle ccpanel for settings workspace
|
|
2361
|
+
if (options?.ccpanel) {
|
|
2362
|
+
updateUrl({ ccpanel: options.ccpanel, workspace: viewName });
|
|
2363
|
+
}
|
|
2364
|
+
switchWorkspace(viewName, options);
|
|
2365
|
+
}, [switchWorkspace, updateUrl]);
|
|
2632
2366
|
// Helper: get all sidebar IDs that should be preserved (locked sidebars + their stack mates)
|
|
2633
2367
|
const getPreservedSidebarIds = useCallback(() => {
|
|
2634
2368
|
const lockedSet = new Set(lockedSidebarsRef.current);
|
|
@@ -2666,9 +2400,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2666
2400
|
setOpenSidebars(newSidebars);
|
|
2667
2401
|
setLockedSidebars((locked) => locked.filter((id) => id !== sidebarId));
|
|
2668
2402
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2669
|
-
if (sidebarId === "agents-panel") {
|
|
2670
|
-
setUserPreferences({ showAgentsPanel: false });
|
|
2671
|
-
}
|
|
2672
2403
|
startTransition(() => {
|
|
2673
2404
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2674
2405
|
});
|
|
@@ -2683,69 +2414,34 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2683
2414
|
];
|
|
2684
2415
|
openSidebarsRef.current = newSidebars;
|
|
2685
2416
|
setOpenSidebars(newSidebars);
|
|
2686
|
-
ensureSidebarPinned(sidebarId);
|
|
2687
2417
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2688
|
-
if (sidebarId === "agents-panel") {
|
|
2689
|
-
setUserPreferences({ showAgentsPanel: true });
|
|
2690
|
-
}
|
|
2691
|
-
// On mobile, close the editor form panel when opening a sidebar
|
|
2692
|
-
if (isMobile) {
|
|
2693
|
-
setMobileEditorPanelOpenRaw(false);
|
|
2694
|
-
}
|
|
2695
2418
|
startTransition(() => {
|
|
2696
2419
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2697
2420
|
});
|
|
2698
|
-
}, [
|
|
2699
|
-
updateUrl,
|
|
2700
|
-
getPreservedSidebarIds,
|
|
2701
|
-
normalizeSidebarStacks,
|
|
2702
|
-
ensureSidebarPinned,
|
|
2703
|
-
setUserPreferences,
|
|
2704
|
-
isMobile,
|
|
2705
|
-
]);
|
|
2421
|
+
}, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
|
|
2706
2422
|
// Ensure a sidebar is open (without toggling it closed if already open)
|
|
2707
|
-
const openSidebar = useCallback((sidebarId
|
|
2423
|
+
const openSidebar = useCallback((sidebarId) => {
|
|
2708
2424
|
const currentOpenSidebars = openSidebarsRef.current;
|
|
2709
2425
|
if (currentOpenSidebars.includes(sidebarId)) {
|
|
2710
2426
|
// Already open, nothing to do
|
|
2711
2427
|
return;
|
|
2712
2428
|
}
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
...currentOpenSidebars.filter((id) => preservedSet?.has(id)),
|
|
2720
|
-
sidebarId,
|
|
2721
|
-
];
|
|
2429
|
+
// Keep sidebars that are locked OR in a stack with a locked sidebar
|
|
2430
|
+
const preservedSet = getPreservedSidebarIds();
|
|
2431
|
+
const newSidebars = [
|
|
2432
|
+
...currentOpenSidebars.filter((id) => preservedSet.has(id)), // Keep locked stacks
|
|
2433
|
+
sidebarId, // Add the new one
|
|
2434
|
+
];
|
|
2722
2435
|
openSidebarsRef.current = newSidebars;
|
|
2723
2436
|
setOpenSidebars(newSidebars);
|
|
2724
|
-
ensureSidebarPinned(sidebarId);
|
|
2725
2437
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2726
|
-
if (sidebarId === "agents-panel") {
|
|
2727
|
-
setUserPreferences({ showAgentsPanel: true });
|
|
2728
|
-
}
|
|
2729
|
-
// On mobile, close the editor form panel when opening a sidebar
|
|
2730
|
-
if (isMobile) {
|
|
2731
|
-
setMobileEditorPanelOpenRaw(false);
|
|
2732
|
-
}
|
|
2733
2438
|
startTransition(() => {
|
|
2734
2439
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2735
2440
|
});
|
|
2736
|
-
}, [
|
|
2737
|
-
updateUrl,
|
|
2738
|
-
getPreservedSidebarIds,
|
|
2739
|
-
normalizeSidebarStacks,
|
|
2740
|
-
ensureSidebarPinned,
|
|
2741
|
-
setUserPreferences,
|
|
2742
|
-
isMobile,
|
|
2743
|
-
]);
|
|
2441
|
+
}, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
|
|
2744
2442
|
// Toggle lock state for a sidebar stack (keeps it visible when selecting another)
|
|
2745
2443
|
// When toggling any sidebar, we toggle the entire stack it belongs to
|
|
2746
2444
|
const toggleSidebarLock = useCallback((sidebarId) => {
|
|
2747
|
-
if (isMobile)
|
|
2748
|
-
return;
|
|
2749
2445
|
const currentStacks = sidebarStacksRef.current;
|
|
2750
2446
|
const stackContainingSidebar = currentStacks.find((stack) => stack.includes(sidebarId));
|
|
2751
2447
|
const sidebarIdsToToggle = stackContainingSidebar || [sidebarId];
|
|
@@ -2763,7 +2459,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2763
2459
|
];
|
|
2764
2460
|
}
|
|
2765
2461
|
});
|
|
2766
|
-
}, [
|
|
2462
|
+
}, []);
|
|
2767
2463
|
const stackSidebar = useCallback((sidebarId, targetSidebarId, position = "after") => {
|
|
2768
2464
|
if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId)
|
|
2769
2465
|
return;
|
|
@@ -2840,34 +2536,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2840
2536
|
// Get resolved sidebar (with panels materialized)
|
|
2841
2537
|
// Note: This is defined as a function that will be called later when editContext is available
|
|
2842
2538
|
const sidebars = configuration.editor.sidebars ?? [];
|
|
2843
|
-
const taskboardSidebarIds = new Set([
|
|
2844
|
-
"taskboard-project-list",
|
|
2845
|
-
"taskboard-my-tasks",
|
|
2846
|
-
]);
|
|
2847
|
-
const getSidebarsForWorkspace = useCallback((targetWorkspaceId) => {
|
|
2848
|
-
const isTaskboardWorkspace = targetWorkspaceId === "taskboard";
|
|
2849
|
-
const workspaceAllowedSidebarIds = userInfo.workspaces?.find((w) => w.id === targetWorkspaceId)
|
|
2850
|
-
?.sidebars ?? [];
|
|
2851
|
-
return sidebars.filter((s) => {
|
|
2852
|
-
const isTaskboardSidebar = taskboardSidebarIds.has(s.id);
|
|
2853
|
-
if (isTaskboardWorkspace && !isTaskboardSidebar)
|
|
2854
|
-
return false;
|
|
2855
|
-
if (!isTaskboardWorkspace && isTaskboardSidebar)
|
|
2856
|
-
return false;
|
|
2857
|
-
// Always show agents-panel regardless of workspace settings.
|
|
2858
|
-
if (s.id === "agents-panel") {
|
|
2859
|
-
return true;
|
|
2860
|
-
}
|
|
2861
|
-
// If no workspace settings or no sidebars defined for current workspace, show all.
|
|
2862
|
-
if (workspaceAllowedSidebarIds.length === 0) {
|
|
2863
|
-
return true;
|
|
2864
|
-
}
|
|
2865
|
-
// Only show sidebars that are in the allowed list for the current workspace.
|
|
2866
|
-
return workspaceAllowedSidebarIds.includes(s.id);
|
|
2867
|
-
});
|
|
2868
|
-
}, [sidebars, userInfo.workspaces]);
|
|
2869
2539
|
const getResolvedSidebar = useCallback((sidebarId) => {
|
|
2870
|
-
const sidebar =
|
|
2540
|
+
const sidebar = sidebars.find((s) => s.id === sidebarId);
|
|
2871
2541
|
if (!sidebar)
|
|
2872
2542
|
return undefined;
|
|
2873
2543
|
// Resolve panel factories using editContextRef to avoid circular dependency
|
|
@@ -2881,35 +2551,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2881
2551
|
...sidebar,
|
|
2882
2552
|
panels: resolvedPanels,
|
|
2883
2553
|
};
|
|
2884
|
-
}, [
|
|
2885
|
-
useEffect(() => {
|
|
2886
|
-
if (!currentWorkspace.supportsSidebars) {
|
|
2887
|
-
return;
|
|
2888
|
-
}
|
|
2889
|
-
const allowedIds = new Set(getSidebarsForWorkspace(workspaceId).map((sidebar) => sidebar.id));
|
|
2890
|
-
const currentOpen = openSidebarsRef.current;
|
|
2891
|
-
let nextOpen = currentOpen.filter((id) => allowedIds.has(id));
|
|
2892
|
-
if (nextOpen.length === 0 && currentWorkspace.defaultSidebars?.length) {
|
|
2893
|
-
nextOpen = currentWorkspace.defaultSidebars.filter((id) => allowedIds.has(id));
|
|
2894
|
-
}
|
|
2895
|
-
const unchanged = nextOpen.length === currentOpen.length &&
|
|
2896
|
-
nextOpen.every((id, index) => id === currentOpen[index]);
|
|
2897
|
-
if (unchanged) {
|
|
2898
|
-
return;
|
|
2899
|
-
}
|
|
2900
|
-
openSidebarsRef.current = nextOpen;
|
|
2901
|
-
setOpenSidebars(nextOpen);
|
|
2902
|
-
setSidebarStacks((prev) => normalizeSidebarStacks(nextOpen, prev));
|
|
2903
|
-
startTransition(() => {
|
|
2904
|
-
updateUrl({ sidebar: nextOpen.join(",") || undefined });
|
|
2905
|
-
});
|
|
2906
|
-
}, [
|
|
2907
|
-
currentWorkspace,
|
|
2908
|
-
getSidebarsForWorkspace,
|
|
2909
|
-
normalizeSidebarStacks,
|
|
2910
|
-
updateUrl,
|
|
2911
|
-
workspaceId,
|
|
2912
|
-
]);
|
|
2554
|
+
}, [sidebars]);
|
|
2913
2555
|
// Listen for switch-workspace and open-sidebar commands from agents via websocket
|
|
2914
2556
|
useEffect(() => {
|
|
2915
2557
|
const handleAgentMessage = (message) => {
|
|
@@ -3245,7 +2887,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3245
2887
|
]);
|
|
3246
2888
|
const { handleKeyDown } = useKeyboardNavigation({
|
|
3247
2889
|
editContextRef,
|
|
3248
|
-
|
|
2890
|
+
operations,
|
|
2891
|
+
pageViewContext: activePageViewContext,
|
|
2892
|
+
configuration,
|
|
2893
|
+
item,
|
|
2894
|
+
browseHistory,
|
|
2895
|
+
loadItem,
|
|
2896
|
+
showInfoToast,
|
|
2897
|
+
showErrorToast,
|
|
3249
2898
|
executeCommand,
|
|
3250
2899
|
showQuickSwitcher,
|
|
3251
2900
|
cycleQuickSwitcher,
|
|
@@ -3365,19 +3014,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3365
3014
|
}
|
|
3366
3015
|
return null;
|
|
3367
3016
|
};
|
|
3368
|
-
let modifierWasPressedOnMouseDown = false;
|
|
3369
|
-
const handleMouseDown = (event) => {
|
|
3370
|
-
modifierWasPressedOnMouseDown = event.ctrlKey || event.metaKey;
|
|
3371
|
-
};
|
|
3372
3017
|
const handleCtrlClick = async (event) => {
|
|
3373
|
-
// Only proceed if Ctrl
|
|
3374
|
-
// This avoids accidental navigation when users press Ctrl after selecting text to copy.
|
|
3375
|
-
if (!modifierWasPressedOnMouseDown)
|
|
3376
|
-
return;
|
|
3377
|
-
// Also require the modifier to still be held for the final click event.
|
|
3018
|
+
// Only proceed if Ctrl (or Cmd on Mac) is pressed
|
|
3378
3019
|
if (!event.ctrlKey && !event.metaKey)
|
|
3379
3020
|
return;
|
|
3380
|
-
modifierWasPressedOnMouseDown = false;
|
|
3381
3021
|
const target = event.target;
|
|
3382
3022
|
const text = getTextFromElement(target);
|
|
3383
3023
|
if (text && isGuid(text)) {
|
|
@@ -3392,7 +3032,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3392
3032
|
skipViewChange: true,
|
|
3393
3033
|
});
|
|
3394
3034
|
if (item) {
|
|
3395
|
-
|
|
3035
|
+
// Switch to the editor view
|
|
3036
|
+
switchView("editor", {
|
|
3396
3037
|
skipNavigationHistory: true,
|
|
3397
3038
|
});
|
|
3398
3039
|
showInfoToast({
|
|
@@ -3418,14 +3059,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3418
3059
|
}
|
|
3419
3060
|
};
|
|
3420
3061
|
if (typeof document !== "undefined") {
|
|
3421
|
-
document.addEventListener("mousedown", handleMouseDown, true);
|
|
3422
3062
|
document.addEventListener("click", handleCtrlClick, true);
|
|
3423
3063
|
return () => {
|
|
3424
|
-
document.removeEventListener("mousedown", handleMouseDown, true);
|
|
3425
3064
|
document.removeEventListener("click", handleCtrlClick, true);
|
|
3426
3065
|
};
|
|
3427
3066
|
}
|
|
3428
|
-
}, [loadItem,
|
|
3067
|
+
}, [loadItem, switchView, showInfoToast, showErrorToast]);
|
|
3429
3068
|
useEffect(() => {
|
|
3430
3069
|
const handleGlobalBlur = () => {
|
|
3431
3070
|
operations.onFieldBlur?.();
|
|
@@ -3463,6 +3102,21 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3463
3102
|
// Otherwise, only show workspaces that are in the settings
|
|
3464
3103
|
return workspaceIdsFromSettings.includes(w.id) && !w.visible;
|
|
3465
3104
|
});
|
|
3105
|
+
// Get sidebars allowed for the current workspace from settings
|
|
3106
|
+
const currentWorkspaceSettings = userInfo.workspaces?.find((w) => w.id === workspaceId);
|
|
3107
|
+
const allowedSidebarIds = currentWorkspaceSettings?.sidebars ?? [];
|
|
3108
|
+
// Legacy: Calculate visible views for backwards compatibility
|
|
3109
|
+
const allViews = (configuration.editor.views ?? [])
|
|
3110
|
+
.filter((x) => {
|
|
3111
|
+
return !x.visible && !x.hidden;
|
|
3112
|
+
})
|
|
3113
|
+
.filter((x) => !userInfo.views ||
|
|
3114
|
+
userInfo.views.map((view) => view.name).includes(x.name));
|
|
3115
|
+
const pinnedViews = userInfo.preferences?.pinnedViews ||
|
|
3116
|
+
configuration.editor.defaultPinnedViews ||
|
|
3117
|
+
[];
|
|
3118
|
+
// Legacy visibleViews for backwards compatibility
|
|
3119
|
+
const visibleViews = allViews.filter((view) => view.name === viewName || pinnedViews.includes(view.name));
|
|
3466
3120
|
// Handle initial mode setup from URL (only on initial load)
|
|
3467
3121
|
useEffect(() => {
|
|
3468
3122
|
if (!isInitialLoad)
|
|
@@ -3507,7 +3161,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3507
3161
|
// This is especially important when called from the tour, where the current workspace
|
|
3508
3162
|
// might be the editor and URL-only navigation would get "corrected" back.
|
|
3509
3163
|
try {
|
|
3510
|
-
|
|
3164
|
+
switchView("home", {
|
|
3511
3165
|
skipConfirmation: true,
|
|
3512
3166
|
skipNavigationHistory: true,
|
|
3513
3167
|
});
|
|
@@ -3554,6 +3208,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3554
3208
|
const current = new URLSearchParams(searchParams.toString());
|
|
3555
3209
|
current.delete("version");
|
|
3556
3210
|
current.delete("itemid");
|
|
3211
|
+
current.delete("view"); // Remove legacy param
|
|
3557
3212
|
current.delete("workspace"); // Clear workspace
|
|
3558
3213
|
current.set("create", "1");
|
|
3559
3214
|
const newUrl = `${pathname}?${current.toString()}`;
|
|
@@ -3870,8 +3525,19 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3870
3525
|
workspaceId,
|
|
3871
3526
|
previousWorkspaceId,
|
|
3872
3527
|
switchWorkspace,
|
|
3873
|
-
// Sidebar state
|
|
3874
|
-
availableSidebars:
|
|
3528
|
+
// Sidebar state - filter by workspace settings if available
|
|
3529
|
+
availableSidebars: (configuration.editor.sidebars ?? []).filter((s) => {
|
|
3530
|
+
// Always show agents-panel regardless of workspace settings
|
|
3531
|
+
if (s.id === "agents-panel") {
|
|
3532
|
+
return true;
|
|
3533
|
+
}
|
|
3534
|
+
// If no workspace settings or no sidebars defined for current workspace, show all
|
|
3535
|
+
if (!allowedSidebarIds || allowedSidebarIds.length === 0) {
|
|
3536
|
+
return true;
|
|
3537
|
+
}
|
|
3538
|
+
// Only show sidebars that are in the allowed list for the current workspace
|
|
3539
|
+
return allowedSidebarIds.includes(s.id);
|
|
3540
|
+
}),
|
|
3875
3541
|
openSidebars,
|
|
3876
3542
|
pinnedSidebars,
|
|
3877
3543
|
lockedSidebars,
|
|
@@ -3886,6 +3552,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3886
3552
|
reorderPinnedSidebars,
|
|
3887
3553
|
reorderOpenSidebars,
|
|
3888
3554
|
getResolvedSidebar,
|
|
3555
|
+
// Legacy compatibility (deprecated)
|
|
3556
|
+
viewName,
|
|
3557
|
+
previousViewName,
|
|
3558
|
+
switchView,
|
|
3559
|
+
view: currentView,
|
|
3560
|
+
visibleViews,
|
|
3889
3561
|
compareMode,
|
|
3890
3562
|
setCompareMode,
|
|
3891
3563
|
fullscreen,
|
|
@@ -3925,7 +3597,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3925
3597
|
addSocketMessageListener,
|
|
3926
3598
|
sendSocketMessage,
|
|
3927
3599
|
socketConnectionVersion,
|
|
3928
|
-
socketDiagnostics,
|
|
3929
3600
|
currentItemDescriptor,
|
|
3930
3601
|
editorSlots,
|
|
3931
3602
|
activeSlotId,
|
|
@@ -3938,7 +3609,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3938
3609
|
setActiveSlot,
|
|
3939
3610
|
revision,
|
|
3940
3611
|
notifyPageModelReady,
|
|
3941
|
-
pageModelReadyToken,
|
|
3942
3612
|
selectedComment,
|
|
3943
3613
|
setSelectedComment,
|
|
3944
3614
|
comments,
|
|
@@ -4017,8 +3687,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4017
3687
|
setEnableCompletions,
|
|
4018
3688
|
showComponentNavigator,
|
|
4019
3689
|
setShowComponentNavigator: handleSetShowComponentNavigator,
|
|
4020
|
-
isComponentNavigatorOpenForSlot,
|
|
4021
|
-
setComponentNavigatorOpenForSlot,
|
|
4022
3690
|
showAgentsPanel,
|
|
4023
3691
|
setShowAgentsPanel: handleSetShowAgentsPanel,
|
|
4024
3692
|
showMinimap,
|
|
@@ -4030,12 +3698,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4030
3698
|
helpTerminalProfileName,
|
|
4031
3699
|
helpTerminalActiveTab,
|
|
4032
3700
|
setHelpTerminalActiveTab,
|
|
4033
|
-
selectedHelpSectionId,
|
|
4034
|
-
setSelectedHelpSectionId,
|
|
4035
3701
|
showAgentsWorkspaceEditor,
|
|
4036
3702
|
setShowAgentsWorkspaceEditor: handleSetShowAgentsWorkspaceEditor,
|
|
4037
|
-
selectedAgentsWorkspaceAgentId,
|
|
4038
|
-
setSelectedAgentsWorkspaceAgentId,
|
|
4039
3703
|
activeEditorTab,
|
|
4040
3704
|
setActiveEditorTab,
|
|
4041
3705
|
showLayoutComponents,
|
|
@@ -4044,8 +3708,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4044
3708
|
isQuotaExceeded: isQuotaExceeded(),
|
|
4045
3709
|
getQuotaWarningMessage,
|
|
4046
3710
|
isMobile,
|
|
4047
|
-
mobileEditorPanelOpen,
|
|
4048
|
-
setMobileEditorPanelOpen: handleSetMobileEditorPanelOpen,
|
|
4049
3711
|
openDialog,
|
|
4050
3712
|
webSocketMessages,
|
|
4051
3713
|
clearWebSocketMessages: () => setWebSocketMessages([]),
|
|
@@ -4084,6 +3746,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4084
3746
|
configuration,
|
|
4085
3747
|
updateUrl,
|
|
4086
3748
|
workspaceId,
|
|
3749
|
+
switchView,
|
|
4087
3750
|
pathname,
|
|
4088
3751
|
router,
|
|
4089
3752
|
item,
|
|
@@ -4113,6 +3776,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4113
3776
|
currentWorkspace,
|
|
4114
3777
|
previousWorkspaceId,
|
|
4115
3778
|
switchWorkspace,
|
|
3779
|
+
allowedSidebarIds,
|
|
4116
3780
|
openSidebars,
|
|
4117
3781
|
pinnedSidebars,
|
|
4118
3782
|
lockedSidebars,
|
|
@@ -4124,6 +3788,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4124
3788
|
reorderOpenSidebars,
|
|
4125
3789
|
getResolvedSidebar,
|
|
4126
3790
|
viewName,
|
|
3791
|
+
previousViewName,
|
|
3792
|
+
currentView,
|
|
3793
|
+
visibleViews,
|
|
4127
3794
|
compareMode,
|
|
4128
3795
|
// Important: in multi-slot mode the active PageViewContext can change
|
|
4129
3796
|
// without the base `pageViewContext` identity changing (e.g. switching slots).
|
|
@@ -4148,7 +3815,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4148
3815
|
currentItemDescriptor,
|
|
4149
3816
|
revision,
|
|
4150
3817
|
notifyPageModelReady,
|
|
4151
|
-
pageModelReadyToken,
|
|
4152
3818
|
selectedComment,
|
|
4153
3819
|
comments,
|
|
4154
3820
|
availableCommentTags,
|
|
@@ -4167,7 +3833,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4167
3833
|
quickSwitcherSelectedIndex,
|
|
4168
3834
|
handleQuickSwitcherSelect,
|
|
4169
3835
|
webSocketMessages,
|
|
4170
|
-
socketDiagnostics,
|
|
4171
3836
|
factoriesRef,
|
|
4172
3837
|
user,
|
|
4173
3838
|
statusMessage,
|
|
@@ -4176,11 +3841,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4176
3841
|
isQuotaExceeded,
|
|
4177
3842
|
getQuotaWarningMessage,
|
|
4178
3843
|
isMobile,
|
|
4179
|
-
mobileEditorPanelOpen,
|
|
4180
|
-
handleSetMobileEditorPanelOpen,
|
|
4181
3844
|
showComponentNavigator,
|
|
4182
|
-
isComponentNavigatorOpenForSlot,
|
|
4183
|
-
setComponentNavigatorOpenForSlot,
|
|
4184
3845
|
handleSetShowComponentNavigator,
|
|
4185
3846
|
showAgentsPanel,
|
|
4186
3847
|
handleSetShowAgentsPanel,
|
|
@@ -4192,9 +3853,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4192
3853
|
helpTerminalProfileName,
|
|
4193
3854
|
helpTerminalActiveTab,
|
|
4194
3855
|
setHelpTerminalActiveTab,
|
|
4195
|
-
selectedHelpSectionId,
|
|
4196
3856
|
showAgentsWorkspaceEditor,
|
|
4197
|
-
selectedAgentsWorkspaceAgentId,
|
|
4198
3857
|
activeEditorTab,
|
|
4199
3858
|
showLayoutComponents,
|
|
4200
3859
|
openDialog,
|
|
@@ -4439,40 +4098,18 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4439
4098
|
// prevDependencies.current = currentDependencies;
|
|
4440
4099
|
// editContextRef.current = editContext;
|
|
4441
4100
|
// }, [editContext]);
|
|
4442
|
-
// Auto-open the mobile editor panel for new selection/intent changes, but
|
|
4443
|
-
// keep a manual close sticky for the exact same context.
|
|
4444
|
-
useEffect(() => {
|
|
4445
|
-
if (!isMobile || workspaceId !== "editor")
|
|
4446
|
-
return;
|
|
4447
|
-
if (activeEditorTab) {
|
|
4448
|
-
handleSetMobileEditorPanelOpen(true);
|
|
4449
|
-
return;
|
|
4450
|
-
}
|
|
4451
|
-
if (!(selection.length > 0 || insertMode))
|
|
4452
|
-
return;
|
|
4453
|
-
if (dismissedMobilePanelToken === mobilePanelDismissToken)
|
|
4454
|
-
return;
|
|
4455
|
-
handleSetMobileEditorPanelOpen(true);
|
|
4456
|
-
}, [
|
|
4457
|
-
activeEditorTab,
|
|
4458
|
-
dismissedMobilePanelToken,
|
|
4459
|
-
handleSetMobileEditorPanelOpen,
|
|
4460
|
-
insertMode,
|
|
4461
|
-
isMobile,
|
|
4462
|
-
mobilePanelDismissToken,
|
|
4463
|
-
selection,
|
|
4464
|
-
workspaceId,
|
|
4465
|
-
]);
|
|
4466
4101
|
useEffect(() => {
|
|
4467
4102
|
fieldsEditContext.clearModifiedFields();
|
|
4468
4103
|
}, [currentItemDescriptor]);
|
|
4469
|
-
if (!
|
|
4104
|
+
if (!currentView)
|
|
4470
4105
|
return null;
|
|
4471
|
-
const editorUi = fullscreen ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "fixed inset-0 flex", children: [_jsx(PageViewerFrame, { compareView: compareMode, pageViewContext: activePageViewContext }), _jsx(FullscreenControls, { device: activePageViewContext.device, setDevice: (d) => activePageViewContext.setDevice(d), canExit: !configuration.forceFullscreen, onExit: () => setFullscreen(false), firstMobileDeviceName: configuration.devices[0]?.name })] }), showFullscreenHint && !configuration.forceFullscreen &&
|
|
4106
|
+
const editorUi = fullscreen ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "fixed inset-0 flex", children: [_jsx(PageViewerFrame, { compareView: compareMode, pageViewContext: activePageViewContext }), _jsx(FullscreenControls, { device: activePageViewContext.device, setDevice: (d) => activePageViewContext.setDevice(d), canExit: !configuration.forceFullscreen, onExit: () => setFullscreen(false), firstMobileDeviceName: configuration.devices[0]?.name })] }), showFullscreenHint && !configuration.forceFullscreen && (_jsx("div", { className: "fixed inset-0", onMouseMoveCapture: () => {
|
|
4472
4107
|
setTimeout(() => {
|
|
4473
4108
|
setShowFullscreenHint(false);
|
|
4474
4109
|
}, 600);
|
|
4475
|
-
}, "data-testid": "fullscreen-hint-overlay", children: _jsxs("div", { className: "fixed top-6 left-1/2 -translate-x-1/2 transform rounded-full bg-black/60 px-6 py-2.5 text-sm font-medium text-white shadow-2xl backdrop-blur-md transition-all duration-500", children: ["Press", " ", _jsx("kbd", { className: "mx-1 rounded bg-white/20 px-1.5 py-0.5 text-xs font-semibold", children: "Ctrl + F11" }), " ", "to exit fullscreen"] }) }))] })) : (_jsxs(_Fragment, { children: [_jsx(EditorChrome, { className: className, currentWorkspace: currentWorkspace, centerPanelView: centerPanelView, editContext: editContext, showAgentsPanel: showAgentsPanel, handleSetShowAgentsPanel: handleSetShowAgentsPanel, workspaceId: workspaceId
|
|
4110
|
+
}, "data-testid": "fullscreen-hint-overlay", children: _jsxs("div", { className: "fixed top-6 left-1/2 -translate-x-1/2 transform rounded-full bg-black/60 px-6 py-2.5 text-sm font-medium text-white shadow-2xl backdrop-blur-md transition-all duration-500", children: ["Press", " ", _jsx("kbd", { className: "mx-1 rounded bg-white/20 px-1.5 py-0.5 text-xs font-semibold", children: "Ctrl + F11" }), " ", "to exit fullscreen"] }) }))] })) : (_jsxs(_Fragment, { children: [_jsx(EditorChrome, { className: className, currentWorkspace: currentWorkspace, centerPanelView: centerPanelView, editContext: editContext, showComponentNavigator: showComponentNavigator, handleSetShowComponentNavigator: handleSetShowComponentNavigator, showAgentsPanel: showAgentsPanel, handleSetShowAgentsPanel: handleSetShowAgentsPanel, workspaceId: workspaceId,
|
|
4111
|
+
// Legacy props for backwards compatibility
|
|
4112
|
+
currentView: currentView, viewName: viewName }), isTourActive && (_jsx(Tour, { tourStopCallback: () => {
|
|
4476
4113
|
setIsTourActive(false);
|
|
4477
4114
|
// Remove tour state from URL
|
|
4478
4115
|
// Use history.replaceState instead of router.replace to avoid triggering React navigation
|
|
@@ -4483,13 +4120,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4483
4120
|
? `${window.location.pathname}?${queryString}`
|
|
4484
4121
|
: window.location.pathname;
|
|
4485
4122
|
window.history.replaceState(null, "", newUrl);
|
|
4486
|
-
}, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(GuidanceOverlay, {}), _jsx(AgentDialogHandler, {})] }));
|
|
4487
|
-
return (_jsx(
|
|
4488
|
-
currentWorkspace.id === "taskboard") &&
|
|
4489
|
-
showAgentsWorkspaceEditor && (_jsx(AgentsSlotContextBridgeHost, { slots: editorSlots })), startupChecks.state !== "loading" && (children || editorUi), startupChecks.state !== "loading" && dialog, _jsx(Toaster, { position: "top-center" }), " ", _jsx(ConfirmationDialog, { ref: confirmationDialogRef }), _jsx(ConcurrentUserLimitDialog, { open: concurrentUserLimitError !== null, onOpenChange: (open) => {
|
|
4490
|
-
if (!open) {
|
|
4491
|
-
setConcurrentUserLimitError(null);
|
|
4492
|
-
}
|
|
4493
|
-
}, sessionId: sessionId, currentUsers: concurrentUserLimitError?.currentUsers ?? 0, maxUsers: concurrentUserLimitError?.maxUsers ?? 0, message: concurrentUserLimitError?.message ?? "", onRetry: handleRetryConnection, isAdministrator: userInfo.user.isAdministrator === true }), _jsx(QuickItemSwitcher, { visible: quickSwitcherVisible, entries: navigationHistory.slice(0, 5), selectedIndex: quickSwitcherSelectedIndex, onSelect: handleQuickSwitcherSelect, onClose: () => setQuickSwitcherVisible(false) }), _jsx(EditContextMenu, { ref: contextMenuRef }), _jsx(InlineAiTrigger, {}), media.mediaSelectorVisible && (_jsx(MediaSelector, { language: editContext.currentItemDescriptor.language, visible: media.mediaSelectorVisible, onHide: media.handleHide, onMediaSelected: media.onMediaSelect, selectedIdPath: media.selectedMediaIdPath, mode: media.mediaSelectorMode, initialSearchTerm: media.initialSearchTerm })), _jsx(FieldEditorPopup, { ref: fieldEditorPopupRef }), _jsx(LicenseOverlay, {})] }) }) }) }) }));
|
|
4123
|
+
}, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(GuidanceOverlay, {}), _jsx(AgentDialogHandler, { sendWebSocketMessage: (type, payload) => sendSocketMessage({ type, payload }) })] }));
|
|
4124
|
+
return (_jsx("div", { className: `editor h-full w-full`, children: _jsx(OperationsContextProvider, { value: operationsContext.context, children: _jsx(FieldsEditContextProvider, { value: fieldsEditContext, children: _jsxs(EditContextProvider, { value: editContext, children: [_jsx(DevModeIndicator, {}), startupChecks.state === "loading" && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-white/70 backdrop-blur-[1px]", children: _jsx("div", { className: "flex items-center gap-3 rounded-md border border-gray-200 bg-white px-4 py-3 text-gray-700 shadow-sm", children: _jsx(Spinner, { size: "xl" }) }) })), editContext.isRefreshing && (_jsx("div", { className: "pointer-events-none fixed right-0 bottom-0 flex h-24 w-24 items-center justify-center text-gray-600 opacity-50 select-none", children: _jsx(Spinner, {}) })), children || editorUi, dialog, _jsx(Toaster, { position: "top-center" }), " ", _jsx(ConfirmationDialog, { ref: confirmationDialogRef }), _jsx(QuickItemSwitcher, { visible: quickSwitcherVisible, entries: navigationHistory.slice(0, 5), selectedIndex: quickSwitcherSelectedIndex, onSelect: handleQuickSwitcherSelect, onClose: () => setQuickSwitcherVisible(false) }), _jsx(EditContextMenu, { ref: contextMenuRef }), _jsx(InlineAiTrigger, {}), media.mediaSelectorVisible && (_jsx(MediaSelector, { language: editContext.currentItemDescriptor.language, visible: media.mediaSelectorVisible, onHide: media.handleHide, onMediaSelected: media.onMediaSelect, selectedIdPath: media.selectedMediaIdPath, mode: media.mediaSelectorMode, initialSearchTerm: media.initialSearchTerm })), _jsx(FieldEditorPopup, { ref: fieldEditorPopupRef })] }) }) }) }));
|
|
4494
4125
|
}
|
|
4495
4126
|
//# sourceMappingURL=EditorShell.js.map
|