@parhelia/core 0.1.12554 → 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 +98 -187
- 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 -4
- package/dist/config/config.js +70 -250
- package/dist/config/config.js.map +1 -1
- package/dist/config/types/workspace.d.ts +0 -6
- package/dist/config/types.d.ts +12 -63
- 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 +22 -87
- 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/ImageEditor.js +2 -5
- package/dist/editor/ImageEditor.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 +8 -65
- 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 +15 -17
- 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 +483 -2377
- 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 +113 -150
- 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 +1 -2
- package/dist/editor/ai/useAgentStatus.js +99 -86
- 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.d.ts +1 -4
- package/dist/editor/client/EditorShell.js +230 -730
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +19 -33
- 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/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/DevModeIndicator.js +2 -2
- package/dist/editor/client/ui/DevModeIndicator.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/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 +5 -13
- 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 +24 -181
- 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/field-types/textContextMenuFactory.js +2 -3
- package/dist/editor/field-types/textContextMenuFactory.js.map +1 -1
- package/dist/editor/media-selector/AiImageSearchPrompt.js +2 -4
- package/dist/editor/media-selector/AiImageSearchPrompt.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 +38 -16
- 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 +220 -597
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +2 -13
- 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 +301 -301
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
- package/dist/editor/page-viewer/DeviceToolbar.js +1 -1
- package/dist/editor/page-viewer/DeviceToolbar.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 +115 -348
- package/dist/editor/page-viewer/PageViewerFrame.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 +12 -26
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +5 -7
- 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 -25
- 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 -52
- package/dist/editor/services/editService.js +2 -94
- 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/api.d.ts +2 -1
- package/dist/editor/services-server/api.js +6 -11
- package/dist/editor/services-server/api.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 +23 -25
- 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 +6 -7
- 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/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 -22
- 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/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 +7 -21
- package/dist/editor/sidebar/OperationItem.js.map +1 -1
- package/dist/editor/sidebar/SidebarPanel.d.ts +1 -3
- package/dist/editor/sidebar/SidebarPanel.js +12 -44
- package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
- package/dist/editor/sidebar/SidebarStack.d.ts +1 -2
- package/dist/editor/sidebar/SidebarStack.js +3 -4
- 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/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 +140 -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 +5 -7
- 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 -16
- package/dist/index.js +0 -11
- package/dist/index.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 -112
- 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/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 +15 -19
- 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
|
-
import { useRouter, useSearchParams, usePathname } from "
|
|
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,33 +49,7 @@ 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
|
-
|
|
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
|
-
export function EditorShell({ configuration, className, item: loadItemDescriptor, sessionId, userInfo, userPreferences, initialLicenseStatus, initialLicenseStatusLoaded, parheliaSettings, setUserPreferences, children, }) {
|
|
52
|
+
export function EditorShell({ configuration, className, item: loadItemDescriptor, sessionId, userInfo, userPreferences, parheliaSettings, setUserPreferences, children, }) {
|
|
83
53
|
const router = useRouter();
|
|
84
54
|
const pathname = usePathname();
|
|
85
55
|
const searchParams = useSearchParams();
|
|
@@ -127,7 +97,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
127
97
|
const [historyMode, setHistoryMode] = useState("global");
|
|
128
98
|
const [showOnlyMyChanges, setShowOnlyMyChanges] = useState(true);
|
|
129
99
|
const [filterByCurrentLanguage, setFilterByCurrentLanguage] = useState(true);
|
|
130
|
-
const [historySearchQuery, setHistorySearchQuery] = useState("");
|
|
131
100
|
const [recentEdits, setRecentEdits] = useState([]);
|
|
132
101
|
const addRecentEdit = useCallback((edit) => {
|
|
133
102
|
setRecentEdits((prevEditedFields) => {
|
|
@@ -155,14 +124,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
155
124
|
if (typeof window !== "undefined")
|
|
156
125
|
sessionStorage?.setItem("sessionId", sessionId);
|
|
157
126
|
// Workspace state
|
|
158
|
-
// 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
|
|
159
128
|
// set workspace to "editor" and open the reviews sidebar instead.
|
|
160
129
|
// Memoize searchParams reads to avoid triggering Router state updates during render
|
|
161
130
|
// (Next.js App Router uses startTransition internally for URL changes)
|
|
162
|
-
const rawWorkspace = useMemo(() => searchParams.get("workspace"), [searchParams]);
|
|
131
|
+
const rawWorkspace = useMemo(() => searchParams.get("workspace") ?? searchParams.get("view"), [searchParams]);
|
|
163
132
|
const isReviewsSidebarRequest = rawWorkspace === "reviews";
|
|
164
133
|
const [workspaceId, setWorkspaceId] = useState(
|
|
165
|
-
// If
|
|
134
|
+
// If view=reviews, use "editor" workspace (reviews is a sidebar, not a workspace)
|
|
166
135
|
isReviewsSidebarRequest
|
|
167
136
|
? "editor"
|
|
168
137
|
: (rawWorkspace ??
|
|
@@ -184,7 +153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
184
153
|
else {
|
|
185
154
|
sidebars = [...(configuration.editor.defaultOpenSidebars ?? [])];
|
|
186
155
|
}
|
|
187
|
-
// If workspace=reviews was requested, ensure reviews sidebar is open
|
|
156
|
+
// If view/workspace=reviews was requested, ensure reviews sidebar is open
|
|
188
157
|
if (isReviewsSidebarRequest && !sidebars.includes("reviews")) {
|
|
189
158
|
sidebars.push("reviews");
|
|
190
159
|
}
|
|
@@ -192,11 +161,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
192
161
|
});
|
|
193
162
|
// Toolbar pinned sidebars - icons always visible in toolbar (defined early so callbacks can access)
|
|
194
163
|
const [pinnedSidebars, setPinnedSidebars] = useState(userInfo.preferences?.pinnedSidebars || []);
|
|
195
|
-
const pinnedSidebarsRef = useRef(pinnedSidebars);
|
|
196
164
|
// Locked sidebars - open panels that stay visible when selecting another sidebar
|
|
197
165
|
const [lockedSidebars, setLockedSidebars] = useState(() => {
|
|
166
|
+
if (typeof window === "undefined") {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
198
169
|
try {
|
|
199
|
-
const
|
|
170
|
+
const stored = window.localStorage.getItem("editor.lockedSidebars");
|
|
171
|
+
if (!stored) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
const parsed = JSON.parse(stored);
|
|
200
175
|
if (!Array.isArray(parsed) ||
|
|
201
176
|
!parsed.every((id) => typeof id === "string")) {
|
|
202
177
|
return [];
|
|
@@ -212,9 +187,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
212
187
|
useEffect(() => {
|
|
213
188
|
lockedSidebarsRef.current = lockedSidebars;
|
|
214
189
|
}, [lockedSidebars]);
|
|
215
|
-
useEffect(() => {
|
|
216
|
-
pinnedSidebarsRef.current = pinnedSidebars;
|
|
217
|
-
}, [pinnedSidebars]);
|
|
218
190
|
// Filter locked sidebars to only include currently open sidebars
|
|
219
191
|
useEffect(() => {
|
|
220
192
|
const openSet = new Set(openSidebars);
|
|
@@ -276,11 +248,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
276
248
|
// Group open sidebars into vertical stacks (each stack shares one left column).
|
|
277
249
|
const [sidebarStacks, setSidebarStacks] = useState(() => {
|
|
278
250
|
const defaultStacks = openSidebars.map((id) => [id]);
|
|
251
|
+
if (typeof window === "undefined") {
|
|
252
|
+
return normalizeSidebarStacks(openSidebars, defaultStacks);
|
|
253
|
+
}
|
|
279
254
|
try {
|
|
280
|
-
const
|
|
281
|
-
if (!
|
|
255
|
+
const stored = window.localStorage.getItem("editor.sidebarStacks");
|
|
256
|
+
if (!stored) {
|
|
282
257
|
return normalizeSidebarStacks(openSidebars, defaultStacks);
|
|
283
258
|
}
|
|
259
|
+
const parsed = JSON.parse(stored);
|
|
284
260
|
if (!Array.isArray(parsed) ||
|
|
285
261
|
!parsed.every((x) => Array.isArray(x) && x.every((id) => typeof id === "string"))) {
|
|
286
262
|
return normalizeSidebarStacks(openSidebars, defaultStacks);
|
|
@@ -302,19 +278,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
302
278
|
}, [openSidebars, normalizeSidebarStacks]);
|
|
303
279
|
// Persist stacks independently of the URL (user layout preference).
|
|
304
280
|
useEffect(() => {
|
|
281
|
+
if (typeof window === "undefined")
|
|
282
|
+
return;
|
|
305
283
|
try {
|
|
306
|
-
|
|
284
|
+
window.localStorage.setItem("editor.sidebarStacks", JSON.stringify(sidebarStacks));
|
|
307
285
|
}
|
|
308
286
|
catch { }
|
|
309
287
|
}, [sidebarStacks]);
|
|
310
288
|
// Persist locked sidebars to localStorage.
|
|
311
289
|
useEffect(() => {
|
|
290
|
+
if (typeof window === "undefined")
|
|
291
|
+
return;
|
|
312
292
|
try {
|
|
313
|
-
|
|
293
|
+
window.localStorage.setItem("editor.lockedSidebars", JSON.stringify(lockedSidebars));
|
|
314
294
|
}
|
|
315
295
|
catch { }
|
|
316
296
|
}, [lockedSidebars]);
|
|
297
|
+
// Legacy aliases for backwards compatibility
|
|
317
298
|
const viewName = workspaceId;
|
|
299
|
+
const setViewName = setWorkspaceId;
|
|
300
|
+
const viewNameRef = workspaceIdRef;
|
|
301
|
+
const previousViewName = previousWorkspaceId;
|
|
302
|
+
const setPreviousViewName = setPreviousWorkspaceId;
|
|
318
303
|
const [compareMode, setCompareModeState] = useState(false);
|
|
319
304
|
const [componentDesignerComponent, setComponentDesignerComponent] = useState();
|
|
320
305
|
const [componentDesignerRendering, setComponentDesignerRendering] = useState();
|
|
@@ -341,29 +326,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
341
326
|
activeSlotIdRef.current = activeSlotId;
|
|
342
327
|
}, [activeSlotId]);
|
|
343
328
|
const [slotContexts, setSlotContexts] = useState(() => new Map());
|
|
344
|
-
const promptSessionReconnect = useCallback((reason) => {
|
|
345
|
-
const description = reason && reason !== "session-revoked"
|
|
346
|
-
? `${reason}. Click reconnect to continue in this browser.`
|
|
347
|
-
: "You were disconnected because this account is active in another browser.";
|
|
348
|
-
toast.error("Session disconnected", {
|
|
349
|
-
id: "session-revoked",
|
|
350
|
-
description,
|
|
351
|
-
action: {
|
|
352
|
-
label: "Reconnect",
|
|
353
|
-
onClick: async () => {
|
|
354
|
-
const result = await reconnectSession(sessionId);
|
|
355
|
-
if (result.type === "success") {
|
|
356
|
-
window.location.reload();
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
toast.error("Reconnect failed", {
|
|
360
|
-
description: "Could not claim this browser session. Try again.",
|
|
361
|
-
});
|
|
362
|
-
},
|
|
363
|
-
},
|
|
364
|
-
duration: Infinity,
|
|
365
|
-
});
|
|
366
|
-
}, [sessionId]);
|
|
367
329
|
// Track previous item ID to detect actual navigation between pages
|
|
368
330
|
const previousItemIdRef = useRef(undefined);
|
|
369
331
|
useEffect(() => {
|
|
@@ -392,9 +354,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
392
354
|
// Ref to track when we're handling a popstate event (browser back/forward)
|
|
393
355
|
// This prevents the URL sync effect from pushing new history entries during back navigation
|
|
394
356
|
const isHandlingPopStateRef = useRef(false);
|
|
395
|
-
// When switchWorkspace already pushed a URL entry, the follow-up URL sync
|
|
396
|
-
// effect should only *replace* that entry (not push a second one).
|
|
397
|
-
const switchWorkspacePushedRef = useRef(false);
|
|
398
357
|
// Ref to track the last known URL for the popstate handler
|
|
399
358
|
// This is updated both when the popstate handler runs AND when the URL sync effect pushes a new URL
|
|
400
359
|
// Without this, the popstate handler would have a stale lastUrl value after pushState calls
|
|
@@ -411,16 +370,26 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
411
370
|
const [showSuggestedEditsDiff, setShowSuggestedEditsDiff] = useState(false);
|
|
412
371
|
const [availableCommentTags, setAvailableCommentTags] = useState([]);
|
|
413
372
|
const [showComments, setShowComments] = useState(() => {
|
|
414
|
-
|
|
373
|
+
const savedShowComments = typeof window !== "undefined"
|
|
374
|
+
? localStorage.getItem("editor.showComments")
|
|
375
|
+
: null;
|
|
376
|
+
return savedShowComments ? JSON.parse(savedShowComments) : true;
|
|
415
377
|
});
|
|
416
378
|
useEffect(() => {
|
|
417
|
-
|
|
379
|
+
if (typeof window !== "undefined") {
|
|
380
|
+
localStorage.setItem("editor.showComments", JSON.stringify(showComments));
|
|
381
|
+
}
|
|
418
382
|
}, [showComments]);
|
|
419
383
|
const [showResolvedComments, setShowResolvedComments] = useState(() => {
|
|
420
|
-
|
|
384
|
+
const saved = typeof window !== "undefined"
|
|
385
|
+
? localStorage.getItem("editor.showResolvedComments")
|
|
386
|
+
: null;
|
|
387
|
+
return saved ? JSON.parse(saved) : false;
|
|
421
388
|
});
|
|
422
389
|
useEffect(() => {
|
|
423
|
-
|
|
390
|
+
if (typeof window !== "undefined") {
|
|
391
|
+
localStorage.setItem("editor.showResolvedComments", JSON.stringify(showResolvedComments));
|
|
392
|
+
}
|
|
424
393
|
}, [showResolvedComments]);
|
|
425
394
|
const [selectedComment, setSelectedComment] = useState();
|
|
426
395
|
const [browseHistory, setBrowseHistory] = useState(() => {
|
|
@@ -439,12 +408,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
439
408
|
visitedAt: entry.visitedAt,
|
|
440
409
|
}));
|
|
441
410
|
});
|
|
442
|
-
// Navigation history for browser history (
|
|
411
|
+
// Navigation history for browser history (view + item combinations)
|
|
443
412
|
const [navigationHistory, setNavigationHistory] = useState(() => {
|
|
444
|
-
// Initialize from browse history with
|
|
413
|
+
// Initialize from browse history with current view
|
|
445
414
|
if (!userInfo.browseHistory)
|
|
446
415
|
return [];
|
|
447
416
|
const defaultWorkspaceId = searchParams.get("workspace") ??
|
|
417
|
+
searchParams.get("view") ??
|
|
448
418
|
configuration.editor.defaultWorkspace ??
|
|
449
419
|
configuration.editor.workspaces?.[0]?.id ??
|
|
450
420
|
"editor";
|
|
@@ -476,43 +446,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
476
446
|
const [statusMessage, setStatusMessage] = useState("");
|
|
477
447
|
const [focusFieldComponentId, setFocusFieldComponentId] = useState();
|
|
478
448
|
const [enableCompletions, setEnableCompletions] = useState(false);
|
|
479
|
-
const [
|
|
480
|
-
const [slotComponentNavigatorVisibility, setSlotComponentNavigatorVisibility] = useState({});
|
|
481
|
-
useEffect(() => {
|
|
482
|
-
setSlotComponentNavigatorVisibility((prev) => {
|
|
483
|
-
const next = {};
|
|
484
|
-
let changed = false;
|
|
485
|
-
for (const slot of editorSlots) {
|
|
486
|
-
if (Object.prototype.hasOwnProperty.call(prev, slot.slotId)) {
|
|
487
|
-
next[slot.slotId] = prev[slot.slotId];
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
next[slot.slotId] = showComponentNavigatorDefault;
|
|
491
|
-
changed = true;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
if (Object.keys(prev).length !== editorSlots.length) {
|
|
495
|
-
changed = true;
|
|
496
|
-
}
|
|
497
|
-
return changed ? next : prev;
|
|
498
|
-
});
|
|
499
|
-
}, [editorSlots, showComponentNavigatorDefault]);
|
|
449
|
+
const [showComponentNavigator, setShowComponentNavigator] = useState(userPreferences.showComponentNavigator ?? false);
|
|
500
450
|
const [showAgentsPanel, setShowAgentsPanel] = useState(userPreferences.showAgentsPanel ?? false);
|
|
501
451
|
const [showMinimap, setShowMinimap] = useState(userPreferences.showMinimap ?? true);
|
|
502
452
|
const [showHelpTerminal, setShowHelpTerminal] = useState(false);
|
|
503
453
|
const [helpTerminalInitialPrompt, setHelpTerminalInitialPrompt] = useState(undefined);
|
|
504
454
|
const [helpTerminalProfileName, setHelpTerminalProfileName] = useState(undefined);
|
|
505
455
|
const [helpTerminalActiveTab, setHelpTerminalActiveTab] = useState(undefined);
|
|
506
|
-
const [
|
|
507
|
-
const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(false);
|
|
508
|
-
const [selectedAgentsWorkspaceAgentId, setSelectedAgentsWorkspaceAgentId] = useState(null);
|
|
456
|
+
const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(true);
|
|
509
457
|
const [activeEditorTab, setActiveEditorTab] = useState(null);
|
|
510
458
|
const [showLayoutComponents, setShowLayoutComponents] = useState(userPreferences.showLayoutComponents ?? false);
|
|
511
459
|
const { quotaInfo, setQuotaInfo, isQuotaExceeded, getQuotaWarningMessage } = useQuota({
|
|
512
460
|
showError: ({ summary, details }) => showErrorToast({ summary, details }),
|
|
513
461
|
});
|
|
514
462
|
const [webSocketMessages, setWebSocketMessages] = useState([]);
|
|
515
|
-
const [socketDiagnostics, setSocketDiagnostics] = useState(() => createEditorSocketDiagnostics(sessionId));
|
|
516
463
|
const [favorites, setFavorites] = useState([]);
|
|
517
464
|
// Quick item switcher state
|
|
518
465
|
const [quickSwitcherVisible, setQuickSwitcherVisible] = useState(false);
|
|
@@ -530,12 +477,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
530
477
|
if (!startupChecks.hasBlockingIssues)
|
|
531
478
|
return;
|
|
532
479
|
// Don't redirect if already in settings workspace - let user navigate freely within settings
|
|
533
|
-
const currentWorkspace = searchParams.get("workspace");
|
|
480
|
+
const currentWorkspace = searchParams.get("workspace") ?? searchParams.get("view");
|
|
534
481
|
if (currentWorkspace === "settings")
|
|
535
482
|
return;
|
|
536
483
|
// Redirect to the status panel (where user can see all issues and navigate to fixes)
|
|
537
484
|
const url = new URL(window.location.href);
|
|
538
485
|
url.searchParams.set("workspace", "settings");
|
|
486
|
+
url.searchParams.delete("view"); // Remove legacy param
|
|
539
487
|
url.searchParams.set("ccpanel", "status");
|
|
540
488
|
router.push(url.toString(), { scroll: false });
|
|
541
489
|
}, [
|
|
@@ -553,16 +501,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
553
501
|
setMode(queryMode);
|
|
554
502
|
}
|
|
555
503
|
}, [searchParams, isInitialLoad]);
|
|
556
|
-
useEffect(() => {
|
|
557
|
-
if (!isInitialLoad)
|
|
558
|
-
return;
|
|
559
|
-
const helpParam = searchParams.get("help");
|
|
560
|
-
if (helpParam) {
|
|
561
|
-
setHelpTerminalActiveTab("manual");
|
|
562
|
-
setShowHelpTerminal(true);
|
|
563
|
-
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true" ? null : helpParam);
|
|
564
|
-
}
|
|
565
|
-
}, [searchParams, isInitialLoad]);
|
|
566
504
|
useEffect(() => {
|
|
567
505
|
if (mode === "suggestions") {
|
|
568
506
|
// Ensure we're in the editor workspace and open the feedback sidebar
|
|
@@ -609,19 +547,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
609
547
|
setSlotContexts((prev) => {
|
|
610
548
|
if (!prev.has(slotId))
|
|
611
549
|
return prev;
|
|
612
|
-
if (slotId === activeSlotIdRef.current) {
|
|
613
|
-
const activeCtx = prev.get(slotId);
|
|
614
|
-
if (activeCtx) {
|
|
615
|
-
lastActiveSlotContextRef.current = activeCtx;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
550
|
const next = new Map(prev);
|
|
619
551
|
next.delete(slotId);
|
|
620
552
|
return next;
|
|
621
553
|
});
|
|
622
554
|
}, []);
|
|
623
555
|
const slotContextsRef = useRef(slotContexts);
|
|
624
|
-
const lastActiveSlotContextRef = useRef(null);
|
|
625
556
|
useEffect(() => {
|
|
626
557
|
slotContextsRef.current = slotContexts;
|
|
627
558
|
}, [slotContexts]);
|
|
@@ -647,12 +578,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
647
578
|
const activeSlotContext = activeSlotId
|
|
648
579
|
? slotContexts.get(activeSlotId)
|
|
649
580
|
: undefined;
|
|
650
|
-
const isComponentNavigatorOpenForSlot = useCallback((slotId) => {
|
|
651
|
-
if (!slotId)
|
|
652
|
-
return showComponentNavigatorDefault;
|
|
653
|
-
return (slotComponentNavigatorVisibility[slotId] ?? showComponentNavigatorDefault);
|
|
654
|
-
}, [slotComponentNavigatorVisibility, showComponentNavigatorDefault]);
|
|
655
|
-
const showComponentNavigator = isComponentNavigatorOpenForSlot(activeSlotId);
|
|
656
581
|
// Sync global compareMode from the active slot's compareMode for URL syncing
|
|
657
582
|
useEffect(() => {
|
|
658
583
|
if (activeSlotContext && activeSlotContext.compareMode !== compareMode) {
|
|
@@ -700,9 +625,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
700
625
|
const isItemUsedInCurrentPage = useCallback((item) => pageItemsSetRef.current.has(makeItemKey(item)), [makeItemKey]);
|
|
701
626
|
const socketMessageListeners = useRef(new Set());
|
|
702
627
|
const [socketConnectionVersion, setSocketConnectionVersion] = useState(0);
|
|
703
|
-
useEffect(() => {
|
|
704
|
-
setSocketDiagnostics(createEditorSocketDiagnostics(sessionId));
|
|
705
|
-
}, [sessionId]);
|
|
706
628
|
const addSocketMessageListener = useCallback((callback) => {
|
|
707
629
|
socketMessageListeners.current.add(callback);
|
|
708
630
|
return () => socketMessageListeners.current.delete(callback);
|
|
@@ -787,13 +709,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
787
709
|
console.error(`No workspace found for id: ${workspaceId}`);
|
|
788
710
|
return null;
|
|
789
711
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
return (configuration.commands.keyboardCommands ?? []).filter((command) => activeCommandIds.has(command.id));
|
|
793
|
-
}, [
|
|
794
|
-
currentWorkspace.keyboardCommandIds,
|
|
795
|
-
configuration.commands.keyboardCommands,
|
|
796
|
-
]);
|
|
712
|
+
// Legacy alias for backwards compatibility
|
|
713
|
+
const currentView = currentWorkspace;
|
|
797
714
|
useEffect(() => {
|
|
798
715
|
if (currentWorkspace?.component) {
|
|
799
716
|
setCenterPanelView(currentWorkspace.component);
|
|
@@ -830,59 +747,30 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
830
747
|
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
831
748
|
window.history.replaceState(null, "", newUrl);
|
|
832
749
|
}, [setIsTourActive]);
|
|
833
|
-
const isMobile = useMediaQuery("(max-width:
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
if (isMobile) {
|
|
838
|
-
setLockedSidebars([]);
|
|
839
|
-
const current = openSidebarsRef.current;
|
|
840
|
-
const lastSidebar = current[current.length - 1];
|
|
841
|
-
if (current.length > 1 && lastSidebar) {
|
|
842
|
-
const trimmed = [lastSidebar];
|
|
843
|
-
openSidebarsRef.current = trimmed;
|
|
844
|
-
setOpenSidebars(trimmed);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}, [isMobile]);
|
|
848
|
-
const setComponentNavigatorOpenForSlot = useCallback((slotId, value) => {
|
|
849
|
-
const previousValue = isComponentNavigatorOpenForSlot(slotId);
|
|
850
|
-
const newValue = typeof value === "function" ? value(previousValue) : value;
|
|
851
|
-
if (slotId) {
|
|
852
|
-
setSlotComponentNavigatorVisibility((prev) => {
|
|
853
|
-
const currentValue = prev[slotId] ?? showComponentNavigatorDefault;
|
|
854
|
-
if (currentValue === newValue && prev[slotId] !== undefined) {
|
|
855
|
-
return prev;
|
|
856
|
-
}
|
|
857
|
-
return {
|
|
858
|
-
...prev,
|
|
859
|
-
[slotId]: newValue,
|
|
860
|
-
};
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
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);
|
|
864
754
|
setUserPreferences({ showComponentNavigator: newValue });
|
|
755
|
+
// On mobile, close Agents Panel when opening Component Navigator
|
|
865
756
|
if (isMobile && newValue) {
|
|
866
757
|
setShowAgentsPanel(false);
|
|
867
758
|
setUserPreferences({ showAgentsPanel: false });
|
|
868
759
|
}
|
|
869
760
|
}, [
|
|
870
|
-
|
|
871
|
-
|
|
761
|
+
showComponentNavigator,
|
|
762
|
+
setShowComponentNavigator,
|
|
872
763
|
setUserPreferences,
|
|
873
764
|
isMobile,
|
|
874
765
|
setShowAgentsPanel,
|
|
875
766
|
]);
|
|
876
|
-
const handleSetShowComponentNavigator = useCallback((value) => {
|
|
877
|
-
setComponentNavigatorOpenForSlot(activeSlotIdRef.current, value);
|
|
878
|
-
}, [setComponentNavigatorOpenForSlot]);
|
|
879
767
|
const handleSetShowAgentsPanel = useCallback((value) => {
|
|
880
768
|
const newValue = typeof value === "function" ? value(showAgentsPanel) : value;
|
|
881
769
|
setShowAgentsPanel(newValue);
|
|
882
770
|
setUserPreferences({ showAgentsPanel: newValue });
|
|
883
771
|
// On mobile, close Component Navigator when opening Agents Panel
|
|
884
772
|
if (isMobile && newValue) {
|
|
885
|
-
|
|
773
|
+
setShowComponentNavigator(false);
|
|
886
774
|
setUserPreferences({ showComponentNavigator: false });
|
|
887
775
|
}
|
|
888
776
|
}, [
|
|
@@ -890,40 +778,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
890
778
|
setShowAgentsPanel,
|
|
891
779
|
setUserPreferences,
|
|
892
780
|
isMobile,
|
|
893
|
-
|
|
781
|
+
setShowComponentNavigator,
|
|
894
782
|
]);
|
|
895
|
-
// Mobile editor panel state (EditorForm shown in bottom panel on mobile)
|
|
896
|
-
const [mobileEditorPanelOpen, setMobileEditorPanelOpenRaw] = useState(false);
|
|
897
|
-
const [dismissedMobilePanelToken, setDismissedMobilePanelToken] = useState(null);
|
|
898
|
-
const previousActiveSlotIdRef = useRef(null);
|
|
899
|
-
const mobilePanelDismissToken = useMemo(() => {
|
|
900
|
-
const selectionKey = selection.join(",");
|
|
901
|
-
return [
|
|
902
|
-
activeSlotId || "no-slot",
|
|
903
|
-
selectionKey,
|
|
904
|
-
insertMode ? "insert" : "browse",
|
|
905
|
-
].join("|");
|
|
906
|
-
}, [activeSlotId, insertMode, selection]);
|
|
907
|
-
useEffect(() => {
|
|
908
|
-
const previousActiveSlotId = previousActiveSlotIdRef.current;
|
|
909
|
-
if (previousActiveSlotId !== activeSlotId) {
|
|
910
|
-
setDismissedMobilePanelToken(null);
|
|
911
|
-
}
|
|
912
|
-
previousActiveSlotIdRef.current = activeSlotId;
|
|
913
|
-
}, [activeSlotId]);
|
|
914
|
-
const handleSetMobileEditorPanelOpen = useCallback((open) => {
|
|
915
|
-
setMobileEditorPanelOpenRaw(open);
|
|
916
|
-
if (!open) {
|
|
917
|
-
setDismissedMobilePanelToken(mobilePanelDismissToken);
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
setDismissedMobilePanelToken(null);
|
|
921
|
-
if (open && isMobile) {
|
|
922
|
-
// Close all sidebars when opening the editor panel on mobile
|
|
923
|
-
openSidebarsRef.current = [];
|
|
924
|
-
setOpenSidebars([]);
|
|
925
|
-
}
|
|
926
|
-
}, [isMobile, mobilePanelDismissToken]);
|
|
927
783
|
const handleSetShowMinimap = useCallback((value) => {
|
|
928
784
|
const newValue = typeof value === "function" ? value(showMinimap) : value;
|
|
929
785
|
setShowMinimap(newValue);
|
|
@@ -937,7 +793,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
937
793
|
setHelpTerminalInitialPrompt(undefined);
|
|
938
794
|
setHelpTerminalProfileName(undefined);
|
|
939
795
|
setHelpTerminalActiveTab(undefined);
|
|
940
|
-
setSelectedHelpSectionId(null);
|
|
941
796
|
}
|
|
942
797
|
}, [showHelpTerminal]);
|
|
943
798
|
const toggleHelpTerminal = useCallback((options) => {
|
|
@@ -980,27 +835,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
980
835
|
setOpenSidebars(newOrder);
|
|
981
836
|
setSidebarStacks((prev) => normalizeSidebarStacks(newOrder, prev));
|
|
982
837
|
}, []);
|
|
983
|
-
const ensureSidebarPinned = useCallback((sidebarId) => {
|
|
984
|
-
const currentPinnedSidebars = pinnedSidebarsRef.current;
|
|
985
|
-
if (currentPinnedSidebars.includes(sidebarId)) {
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
const newPinnedSidebars = [...currentPinnedSidebars, sidebarId];
|
|
989
|
-
pinnedSidebarsRef.current = newPinnedSidebars;
|
|
990
|
-
setPinnedSidebars(newPinnedSidebars);
|
|
991
|
-
setUserPreferences({ pinnedSidebars: newPinnedSidebars });
|
|
992
|
-
}, [setUserPreferences]);
|
|
993
838
|
// messageHandler is defined after loadItem/loadHistory declarations to avoid temporal dead zones
|
|
994
839
|
const user = activeSessions.find((x) => x.sessionId === sessionId)?.user ||
|
|
995
840
|
userInfo.user;
|
|
996
|
-
// Self-heal if our session disappears (e.g., after HMR)
|
|
997
|
-
// 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)
|
|
998
842
|
const missingSessionRecoveryTimerRef = useRef(null);
|
|
999
843
|
const missingSessionRecoveryAttemptsRef = useRef(0);
|
|
1000
|
-
const concurrentUserLimitErrorRef = useRef(null);
|
|
1001
844
|
useEffect(() => {
|
|
1002
|
-
if (concurrentUserLimitErrorRef.current !== null)
|
|
1003
|
-
return;
|
|
1004
845
|
const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
|
|
1005
846
|
if (hasMySession) {
|
|
1006
847
|
// Reset recovery state when we see ourselves again
|
|
@@ -1016,6 +857,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1016
857
|
return;
|
|
1017
858
|
const attempt = missingSessionRecoveryAttemptsRef.current + 1;
|
|
1018
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...`);
|
|
1019
861
|
missingSessionRecoveryTimerRef.current = setTimeout(() => {
|
|
1020
862
|
missingSessionRecoveryTimerRef.current = null;
|
|
1021
863
|
missingSessionRecoveryAttemptsRef.current = attempt;
|
|
@@ -1024,7 +866,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1024
866
|
}
|
|
1025
867
|
else {
|
|
1026
868
|
// Force a reconnect to refresh presence after several failed nudges
|
|
1027
|
-
console.warn("Session presence did not recover after retries. Forcing reconnect.");
|
|
1028
869
|
try {
|
|
1029
870
|
globalThis.editorSocket?.close(4000, "recover-presence");
|
|
1030
871
|
}
|
|
@@ -1044,15 +885,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1044
885
|
// Initialize lastUrlRef to current URL on mount
|
|
1045
886
|
lastUrlRef.current = window.location.href;
|
|
1046
887
|
const keepAliveUrl = "/parhelia/keepalive";
|
|
1047
|
-
const
|
|
888
|
+
const interval = setInterval(() => {
|
|
1048
889
|
fetch(keepAliveUrl + "?ts=" + Date.now())
|
|
1049
890
|
.then((response) => {
|
|
1050
|
-
if (response.headers.get("X-Parhelia-Session-Revoked") === "true") {
|
|
1051
|
-
window.dispatchEvent(new CustomEvent("parhelia:session-revoked", {
|
|
1052
|
-
detail: { reason: "session-revoked" },
|
|
1053
|
-
}));
|
|
1054
|
-
return;
|
|
1055
|
-
}
|
|
1056
891
|
if (response.status === 401 || response.status === 403) {
|
|
1057
892
|
toast.error("Your session has expired", {
|
|
1058
893
|
description: "Please login again to continue editing.",
|
|
@@ -1065,24 +900,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1065
900
|
}
|
|
1066
901
|
})
|
|
1067
902
|
.catch((error) => console.error("Keep Alive error:", error));
|
|
1068
|
-
};
|
|
1069
|
-
const keepaliveIntervalMs = (() => {
|
|
1070
|
-
const param = new URLSearchParams(window.location.search).get("keepaliveIntervalMs");
|
|
1071
|
-
if (!param)
|
|
1072
|
-
return 5 * 60 * 1000;
|
|
1073
|
-
const ms = parseInt(param, 10);
|
|
1074
|
-
return Number.isFinite(ms) && ms >= 2000 && ms <= 60000
|
|
1075
|
-
? ms
|
|
1076
|
-
: 5 * 60 * 1000;
|
|
1077
|
-
})();
|
|
1078
|
-
const interval = setInterval(() => {
|
|
1079
|
-
runSessionCheck();
|
|
1080
|
-
}, keepaliveIntervalMs);
|
|
1081
|
-
const handleVisibilityChange = () => {
|
|
1082
|
-
if (document.visibilityState === "visible") {
|
|
1083
|
-
runSessionCheck();
|
|
1084
|
-
}
|
|
1085
|
-
};
|
|
903
|
+
}, 5 * 60 * 1000);
|
|
1086
904
|
const handleMessage = (event) => {
|
|
1087
905
|
if (event.data.type === "componentsSelected") {
|
|
1088
906
|
setSelection(event.data.componentIds);
|
|
@@ -1097,8 +915,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1097
915
|
isHandlingPopStateRef.current = true;
|
|
1098
916
|
// Sync URL parameters back to component state for browser navigation
|
|
1099
917
|
const urlParams = new URLSearchParams(window.location.search);
|
|
1100
|
-
|
|
1101
|
-
|
|
918
|
+
// Handle workspace changes (with legacy view fallback)
|
|
919
|
+
const urlWorkspace = urlParams.get("workspace") ?? urlParams.get("view");
|
|
920
|
+
if (urlWorkspace && urlWorkspace !== viewNameRef.current) {
|
|
1102
921
|
setWorkspaceId(urlWorkspace);
|
|
1103
922
|
}
|
|
1104
923
|
// Handle sidebar changes
|
|
@@ -1115,18 +934,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1115
934
|
if (compareValue !== compareMode) {
|
|
1116
935
|
setCompareMode(compareValue);
|
|
1117
936
|
}
|
|
1118
|
-
// Handle help panel changes
|
|
1119
|
-
const helpParam = urlParams.get("help");
|
|
1120
|
-
if (helpParam) {
|
|
1121
|
-
setHelpTerminalActiveTab("manual");
|
|
1122
|
-
setShowHelpTerminal(true);
|
|
1123
|
-
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true"
|
|
1124
|
-
? null
|
|
1125
|
-
: helpParam);
|
|
1126
|
-
}
|
|
1127
|
-
else {
|
|
1128
|
-
handleSetShowHelpTerminal(false);
|
|
1129
|
-
}
|
|
1130
937
|
// Handle mode changes
|
|
1131
938
|
const urlMode = urlParams.get("mode");
|
|
1132
939
|
if (urlMode && urlMode !== mode) {
|
|
@@ -1182,11 +989,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1182
989
|
};
|
|
1183
990
|
window.addEventListener("message", handleMessage);
|
|
1184
991
|
window.addEventListener("popstate", handlePopState);
|
|
1185
|
-
window.addEventListener("visibilitychange", handleVisibilityChange);
|
|
1186
992
|
return () => {
|
|
1187
993
|
window.removeEventListener("message", handleMessage);
|
|
1188
994
|
window.removeEventListener("popstate", handlePopState);
|
|
1189
|
-
window.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1190
995
|
clearInterval(interval);
|
|
1191
996
|
};
|
|
1192
997
|
}, []);
|
|
@@ -1196,34 +1001,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1196
1001
|
if (searchParams.get("noTour") !== null) {
|
|
1197
1002
|
return;
|
|
1198
1003
|
}
|
|
1199
|
-
// Don't start tour when there are setup errors (user is or will be on system status page)
|
|
1200
|
-
if (startupChecks.state === "complete" && startupChecks.hasBlockingIssues) {
|
|
1201
|
-
return;
|
|
1202
|
-
}
|
|
1203
|
-
// Don't start tour when already on settings system status page
|
|
1204
|
-
if (viewName === "settings" && searchParams.get("ccpanel") === "status") {
|
|
1205
|
-
return;
|
|
1206
|
-
}
|
|
1207
|
-
// Wait for startup checks so we know whether we'll redirect to status
|
|
1208
|
-
if (startupChecks.state !== "complete") {
|
|
1209
|
-
return;
|
|
1210
|
-
}
|
|
1211
1004
|
const tour = configuration.activeTour;
|
|
1212
1005
|
const key = tour === "default" ? "editor.tourShown" : "editor.tourShown." + tour;
|
|
1213
|
-
const tourShown =
|
|
1006
|
+
const tourShown = localStorage.getItem(key);
|
|
1214
1007
|
if (!tourShown) {
|
|
1215
1008
|
startTour();
|
|
1216
|
-
|
|
1009
|
+
localStorage.setItem(key, "true");
|
|
1217
1010
|
}
|
|
1218
|
-
}, [
|
|
1219
|
-
user,
|
|
1220
|
-
startupChecks.state,
|
|
1221
|
-
startupChecks.hasBlockingIssues,
|
|
1222
|
-
viewName,
|
|
1223
|
-
searchParams,
|
|
1224
|
-
configuration.activeTour,
|
|
1225
|
-
startTour,
|
|
1226
|
-
]);
|
|
1011
|
+
}, [user]);
|
|
1227
1012
|
// WebSocket initialization is performed after messageHandler is defined
|
|
1228
1013
|
// Defer URL sync until loadItem is defined below
|
|
1229
1014
|
// Mark end of initial load phase
|
|
@@ -1355,8 +1140,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1355
1140
|
const loadComments = useCallback(async () => {
|
|
1356
1141
|
if (!currentItemDescriptor)
|
|
1357
1142
|
return;
|
|
1358
|
-
const
|
|
1359
|
-
const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version, reviewId ?? undefined);
|
|
1143
|
+
const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version);
|
|
1360
1144
|
if (handleErrorResult(result, ui, state))
|
|
1361
1145
|
return;
|
|
1362
1146
|
setComments((x) => {
|
|
@@ -1369,7 +1153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1369
1153
|
allComments.sort((a, b) => a.position - b.position);
|
|
1370
1154
|
return allComments;
|
|
1371
1155
|
});
|
|
1372
|
-
}, [currentItemDescriptor
|
|
1156
|
+
}, [currentItemDescriptor]);
|
|
1373
1157
|
// Assuming currentItemDescriptor, ui, state, handleErrorResult, and setSuggestedEdits
|
|
1374
1158
|
// are available in your component context.
|
|
1375
1159
|
const loadSuggestedEdits = useCallback(async () => {
|
|
@@ -1378,8 +1162,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1378
1162
|
const result = await getSuggestedEdits(item.descriptor.id, item.descriptor.language, item.descriptor.version);
|
|
1379
1163
|
if (handleErrorResult(result, ui, state))
|
|
1380
1164
|
return;
|
|
1381
|
-
|
|
1382
|
-
setSuggestedEdits(edits);
|
|
1165
|
+
setSuggestedEdits(result.data || []);
|
|
1383
1166
|
}, [item]);
|
|
1384
1167
|
const loadFavorites = useCallback(async () => {
|
|
1385
1168
|
try {
|
|
@@ -1453,25 +1236,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1453
1236
|
return idB.localeCompare(idA);
|
|
1454
1237
|
});
|
|
1455
1238
|
}, []);
|
|
1456
|
-
const normalizeEditHistoryPayload = useCallback((value) => {
|
|
1457
|
-
if (Array.isArray(value)) {
|
|
1458
|
-
return value;
|
|
1459
|
-
}
|
|
1460
|
-
if (value && typeof value === "object") {
|
|
1461
|
-
const payload = value;
|
|
1462
|
-
const candidates = [
|
|
1463
|
-
payload.operations,
|
|
1464
|
-
payload.history,
|
|
1465
|
-
payload.items,
|
|
1466
|
-
payload.data,
|
|
1467
|
-
];
|
|
1468
|
-
const firstArray = candidates.find((candidate) => Array.isArray(candidate));
|
|
1469
|
-
if (Array.isArray(firstArray)) {
|
|
1470
|
-
return firstArray;
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
return [];
|
|
1474
|
-
}, []);
|
|
1475
1239
|
useEffect(() => {
|
|
1476
1240
|
// Read fresh page from the mutable slot context ref chain.
|
|
1477
1241
|
// The slot context uses a stable ref that is mutated in-place (see editorSlotContext.ts),
|
|
@@ -1494,7 +1258,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1494
1258
|
if (handleErrorResult(result, ui, state))
|
|
1495
1259
|
return;
|
|
1496
1260
|
setEditHistory((prev) => {
|
|
1497
|
-
const next =
|
|
1261
|
+
const next = result.data || [];
|
|
1498
1262
|
if (!prev.length)
|
|
1499
1263
|
return sortEditHistoryByDateDesc(next);
|
|
1500
1264
|
if (!next.length)
|
|
@@ -1553,8 +1317,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1553
1317
|
const shouldFilterByLanguage = filterByLanguage !== undefined
|
|
1554
1318
|
? filterByLanguage
|
|
1555
1319
|
: filterByCurrentLanguage;
|
|
1556
|
-
const trimmedHistoryQuery = historySearchQuery.trim();
|
|
1557
|
-
const historyQuery = trimmedHistoryQuery.length > 0 ? trimmedHistoryQuery : undefined;
|
|
1558
1320
|
if (currentMode === "global") {
|
|
1559
1321
|
// Global mode: optionally filter by session and/or language
|
|
1560
1322
|
const currentLanguage = item?.descriptor?.language || currentItemDescriptor?.language;
|
|
@@ -1564,14 +1326,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1564
1326
|
language: shouldFilterByLanguage && currentLanguage
|
|
1565
1327
|
? currentLanguage
|
|
1566
1328
|
: undefined,
|
|
1567
|
-
query: historyQuery,
|
|
1568
1329
|
});
|
|
1569
1330
|
if (handleErrorResult(result, ui, state)) {
|
|
1570
1331
|
console.error("[EditorShell] Failed to load history:", result);
|
|
1571
1332
|
return;
|
|
1572
1333
|
}
|
|
1573
1334
|
setEditHistory((prev) => {
|
|
1574
|
-
const next =
|
|
1335
|
+
const next = result.data || [];
|
|
1575
1336
|
const scope = {
|
|
1576
1337
|
mode: currentMode,
|
|
1577
1338
|
filterBySession: shouldFilterBySession,
|
|
@@ -1582,12 +1343,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1582
1343
|
};
|
|
1583
1344
|
if (!prev.length)
|
|
1584
1345
|
return sortEditHistoryByDateDesc(next.filter((op) => matchesHistoryScope(op, scope)));
|
|
1585
|
-
if (!next.length)
|
|
1586
|
-
// When searching, respect the empty result — don't fall back to previous items
|
|
1587
|
-
if (historyQuery)
|
|
1588
|
-
return [];
|
|
1346
|
+
if (!next.length)
|
|
1589
1347
|
return sortEditHistoryByDateDesc(prev.filter((op) => matchesHistoryScope(op, scope)));
|
|
1590
|
-
}
|
|
1591
1348
|
const prevById = new Map(prev.map((x) => [x.id, x]));
|
|
1592
1349
|
const nextById = new Set(next.map((x) => x.id));
|
|
1593
1350
|
const merged = next
|
|
@@ -1623,12 +1380,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1623
1380
|
return mergedOp;
|
|
1624
1381
|
});
|
|
1625
1382
|
// Preserve operations that arrived via WebSocket during the fetch window
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1630
|
-
merged.push(priorOp);
|
|
1631
|
-
}
|
|
1383
|
+
for (const [id, priorOp] of prevById) {
|
|
1384
|
+
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1385
|
+
merged.push(priorOp);
|
|
1632
1386
|
}
|
|
1633
1387
|
}
|
|
1634
1388
|
return sortEditHistoryByDateDesc(merged);
|
|
@@ -1651,13 +1405,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1651
1405
|
const result = await getEditHistory({
|
|
1652
1406
|
item: itemFilter,
|
|
1653
1407
|
sessionId: shouldFilterBySession ? sessionId : undefined,
|
|
1654
|
-
query: historyQuery,
|
|
1655
1408
|
});
|
|
1656
1409
|
if (handleErrorResult(result, ui, state)) {
|
|
1657
1410
|
console.error("[EditorShell] Failed to load item history:", result);
|
|
1658
1411
|
return;
|
|
1659
1412
|
}
|
|
1660
|
-
let operations =
|
|
1413
|
+
let operations = result.data || [];
|
|
1661
1414
|
// Client-side version filtering for current-version mode
|
|
1662
1415
|
if (currentMode === "current-version") {
|
|
1663
1416
|
// Defensive filter: only include operations for the current version
|
|
@@ -1680,11 +1433,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1680
1433
|
};
|
|
1681
1434
|
if (!prev.length)
|
|
1682
1435
|
return sortEditHistoryByDateDesc(operations.filter((op) => matchesHistoryScope(op, scope)));
|
|
1683
|
-
if (!operations.length)
|
|
1684
|
-
if (historyQuery)
|
|
1685
|
-
return [];
|
|
1436
|
+
if (!operations.length)
|
|
1686
1437
|
return sortEditHistoryByDateDesc(prev.filter((op) => matchesHistoryScope(op, scope)));
|
|
1687
|
-
}
|
|
1688
1438
|
const prevById = new Map(prev.map((x) => [x.id, x]));
|
|
1689
1439
|
const nextById = new Set(operations.map((x) => x.id));
|
|
1690
1440
|
const merged = operations
|
|
@@ -1720,12 +1470,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1720
1470
|
return mergedOp;
|
|
1721
1471
|
});
|
|
1722
1472
|
// Preserve operations that arrived via WebSocket during the fetch window
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1727
|
-
merged.push(priorOp);
|
|
1728
|
-
}
|
|
1473
|
+
for (const [id, priorOp] of prevById) {
|
|
1474
|
+
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1475
|
+
merged.push(priorOp);
|
|
1729
1476
|
}
|
|
1730
1477
|
}
|
|
1731
1478
|
return sortEditHistoryByDateDesc(merged);
|
|
@@ -1736,11 +1483,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1736
1483
|
historyMode,
|
|
1737
1484
|
showOnlyMyChanges,
|
|
1738
1485
|
filterByCurrentLanguage,
|
|
1739
|
-
historySearchQuery,
|
|
1740
1486
|
item,
|
|
1741
1487
|
currentItemDescriptor,
|
|
1742
1488
|
matchesHistoryScope,
|
|
1743
|
-
normalizeEditHistoryPayload,
|
|
1744
1489
|
sortEditHistoryByDateDesc,
|
|
1745
1490
|
]);
|
|
1746
1491
|
// Debounced history refresh to avoid hammering `/parhelia/editHistory` on rapid UI changes.
|
|
@@ -1806,14 +1551,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1806
1551
|
}
|
|
1807
1552
|
}
|
|
1808
1553
|
else if (historyMode !== "global" && currentItemDescriptor) {
|
|
1809
|
-
// Always load immediately for page-centric/current-version/timeline so we don't show
|
|
1810
|
-
// an empty history list for the debounce window (e.g. 600ms). The effect only runs on
|
|
1811
|
-
// mode or item id/lang/version change, not on every keystroke, so this avoids flaky
|
|
1812
|
-
// undo/redo tests and improves UX when switching to page-centric.
|
|
1813
1554
|
if (!historyInitialLoadDoneRef.current) {
|
|
1814
1555
|
historyInitialLoadDoneRef.current = true;
|
|
1556
|
+
refreshHistoryRef.current(historyMode);
|
|
1557
|
+
}
|
|
1558
|
+
else {
|
|
1559
|
+
debouncedRefreshHistoryRef.current(historyMode);
|
|
1815
1560
|
}
|
|
1816
|
-
refreshHistoryRef.current(historyMode);
|
|
1817
1561
|
}
|
|
1818
1562
|
else if (historyMode !== "global" && !currentItemDescriptor) {
|
|
1819
1563
|
// Clear history if no item loaded in page-centric modes
|
|
@@ -1826,7 +1570,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1826
1570
|
historyMode,
|
|
1827
1571
|
showOnlyMyChanges,
|
|
1828
1572
|
filterByCurrentLanguage,
|
|
1829
|
-
historySearchQuery,
|
|
1830
1573
|
currentItemDescriptor?.id,
|
|
1831
1574
|
currentItemDescriptor?.language,
|
|
1832
1575
|
currentItemDescriptor?.version,
|
|
@@ -1891,9 +1634,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1891
1634
|
if (isInitialLoad)
|
|
1892
1635
|
return;
|
|
1893
1636
|
const current = new URLSearchParams(window.location.search);
|
|
1894
|
-
const urlWorkspace = current.get("workspace");
|
|
1895
|
-
const urlView = current.get("view");
|
|
1896
|
-
const isWorkspaceTransitioning = !!urlWorkspace && urlWorkspace !== viewName;
|
|
1897
1637
|
// Sync item-related parameters only when an item is selected
|
|
1898
1638
|
if (currentItemDescriptor) {
|
|
1899
1639
|
if (current.get("itemid") !== currentItemDescriptor.id) {
|
|
@@ -1924,9 +1664,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1924
1664
|
// If reviewId or urlItemId exists, preserve itemid/lang/version from URL
|
|
1925
1665
|
}
|
|
1926
1666
|
// Always sync workspace-related parameters regardless of item selection
|
|
1927
|
-
if (
|
|
1667
|
+
if (current.get("workspace") !== viewName) {
|
|
1928
1668
|
current.set("workspace", viewName);
|
|
1929
1669
|
}
|
|
1670
|
+
current.delete("view"); // Remove legacy view param
|
|
1930
1671
|
// Sync sidebar state
|
|
1931
1672
|
const currentSidebars = current.get("sidebar") ?? "";
|
|
1932
1673
|
const newSidebars = openSidebars.join(",");
|
|
@@ -1938,12 +1679,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1938
1679
|
current.delete("sidebar");
|
|
1939
1680
|
}
|
|
1940
1681
|
}
|
|
1941
|
-
if (showHelpTerminal) {
|
|
1942
|
-
current.set("help", selectedHelpSectionId ?? "contents");
|
|
1943
|
-
}
|
|
1944
|
-
else {
|
|
1945
|
-
current.delete("help");
|
|
1946
|
-
}
|
|
1947
1682
|
if (!compareMode) {
|
|
1948
1683
|
current.delete("compare");
|
|
1949
1684
|
current.delete("compareLanguage");
|
|
@@ -1968,15 +1703,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1968
1703
|
else {
|
|
1969
1704
|
current.delete("wizardid");
|
|
1970
1705
|
}
|
|
1971
|
-
//
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
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 {
|
|
1977
1714
|
current.delete("ccpanel");
|
|
1978
|
-
current.delete("providerId");
|
|
1979
|
-
current.delete("modelId");
|
|
1980
1715
|
}
|
|
1981
1716
|
// Preserve reviewId parameter if it exists (for review links)
|
|
1982
1717
|
// This ensures review links don't lose the reviewId when URL is synced
|
|
@@ -1995,13 +1730,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1995
1730
|
return;
|
|
1996
1731
|
}
|
|
1997
1732
|
if (newUrl !== oldUrl) {
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
}
|
|
2002
|
-
else {
|
|
2003
|
-
window.history.pushState(null, "", newUrl);
|
|
2004
|
-
}
|
|
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
|
|
2005
1736
|
lastUrlRef.current = newUrl;
|
|
2006
1737
|
}
|
|
2007
1738
|
}, [
|
|
@@ -2015,8 +1746,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2015
1746
|
fullscreen,
|
|
2016
1747
|
currentWizardId,
|
|
2017
1748
|
openSidebars,
|
|
2018
|
-
showHelpTerminal,
|
|
2019
|
-
selectedHelpSectionId,
|
|
2020
1749
|
]);
|
|
2021
1750
|
useEffect(() => {
|
|
2022
1751
|
async function load() {
|
|
@@ -2310,10 +2039,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2310
2039
|
useEffect(() => {
|
|
2311
2040
|
if (fullscreen &&
|
|
2312
2041
|
!searchParams.get("fullscreen") &&
|
|
2313
|
-
!configuration.forceFullscreen
|
|
2314
|
-
!isMobile)
|
|
2042
|
+
!configuration.forceFullscreen)
|
|
2315
2043
|
setShowFullscreenHint(true);
|
|
2316
|
-
}, [fullscreen, configuration.forceFullscreen, searchParams
|
|
2044
|
+
}, [fullscreen, configuration.forceFullscreen, searchParams]);
|
|
2317
2045
|
const state = {
|
|
2318
2046
|
page,
|
|
2319
2047
|
configuration,
|
|
@@ -2412,35 +2140,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2412
2140
|
? existingOp.progress
|
|
2413
2141
|
: op.progress;
|
|
2414
2142
|
// IMPORTANT: Once canUndo becomes true, never downgrade it to false,
|
|
2415
|
-
// UNLESS this update indicates the operation was undone.
|
|
2416
|
-
//
|
|
2417
|
-
//
|
|
2418
|
-
|
|
2419
|
-
// without explicit undone/canRedo flags yet.
|
|
2420
|
-
const isExplicitUndoUpdate = op.undone === true || op.canRedo === true;
|
|
2421
|
-
const isInferredUndoCompletion = existingOp.executionStatus === "executing" &&
|
|
2422
|
-
op.executionStatus === "completed" &&
|
|
2423
|
-
existingOp.canUndo === true &&
|
|
2424
|
-
op.canUndo === false;
|
|
2425
|
-
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;
|
|
2426
2147
|
const mergedCanUndo = isUndoUpdate
|
|
2427
2148
|
? false
|
|
2428
2149
|
: existingOp.canUndo === true
|
|
2429
2150
|
? true
|
|
2430
2151
|
: op.canUndo;
|
|
2431
|
-
const mergedCanRedo = isUndoUpdate
|
|
2432
|
-
? true
|
|
2433
|
-
: op.canRedo ?? existingOp.canRedo;
|
|
2434
|
-
const mergedUndone = isUndoUpdate
|
|
2435
|
-
? true
|
|
2436
|
-
: op.undone ?? existingOp.undone;
|
|
2437
2152
|
const mergedOp = {
|
|
2438
2153
|
...existingOp,
|
|
2439
2154
|
...op,
|
|
2440
2155
|
progress: mergedProgress,
|
|
2441
2156
|
canUndo: mergedCanUndo,
|
|
2442
|
-
canRedo: mergedCanRedo,
|
|
2443
|
-
undone: mergedUndone,
|
|
2444
2157
|
};
|
|
2445
2158
|
// Ensure undone operations always have canRedo: true.
|
|
2446
2159
|
if (mergedOp.undone && !mergedOp.canRedo) {
|
|
@@ -2494,6 +2207,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2494
2207
|
});
|
|
2495
2208
|
// Ref for markOperationComplete callback (needed because operationsContext is created later)
|
|
2496
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([]);
|
|
2497
2214
|
// WebSocket message handler and connection
|
|
2498
2215
|
const messageHandler = useSocketMessageHandler({
|
|
2499
2216
|
sessionId,
|
|
@@ -2519,31 +2236,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2519
2236
|
markOperationCompleteRef.current?.(operationId);
|
|
2520
2237
|
},
|
|
2521
2238
|
});
|
|
2522
|
-
// Concurrent user limit error state
|
|
2523
|
-
const [concurrentUserLimitError, setConcurrentUserLimitError] = useState(null);
|
|
2524
|
-
concurrentUserLimitErrorRef.current = concurrentUserLimitError;
|
|
2525
|
-
const handleRetryConnection = useCallback(() => {
|
|
2526
|
-
setConcurrentUserLimitError(null);
|
|
2527
|
-
// Force reconnection by triggering a new connection attempt
|
|
2528
|
-
// The useEditorWebSocket hook will check availability again
|
|
2529
|
-
const socket = globalThis.editorSocket;
|
|
2530
|
-
if (socket) {
|
|
2531
|
-
socket.close();
|
|
2532
|
-
delete globalThis.editorSocket;
|
|
2533
|
-
}
|
|
2534
|
-
// The hook will automatically attempt to reconnect
|
|
2535
|
-
}, []);
|
|
2536
2239
|
const { socketRef: socketInstanceRef } = useEditorWebSocket({
|
|
2537
2240
|
sessionId,
|
|
2538
2241
|
onMessage: messageHandler,
|
|
2539
2242
|
onOpen: async () => {
|
|
2540
|
-
// Clear concurrent user limit error on successful connection
|
|
2541
|
-
setConcurrentUserLimitError(null);
|
|
2542
|
-
// Startup WebSocket probe may have failed with a blocking error while seats were full;
|
|
2543
|
-
// re-run status checks quietly so "1 error" does not stick after a successful connect.
|
|
2544
|
-
void startupChecks.recheckQuiet();
|
|
2545
2243
|
// Increment socket connection version to trigger re-subscriptions
|
|
2546
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
|
+
}
|
|
2547
2261
|
// Fetch any running operations on (re)connect for auto-resume
|
|
2548
2262
|
// This ensures the UI shows operations that are still executing
|
|
2549
2263
|
try {
|
|
@@ -2559,37 +2273,24 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2559
2273
|
}
|
|
2560
2274
|
},
|
|
2561
2275
|
onError: (error) => console.error("WebSocket error:", error),
|
|
2562
|
-
onConcurrentUserLimit: (error) => {
|
|
2563
|
-
setConcurrentUserLimitError(error);
|
|
2564
|
-
},
|
|
2565
|
-
onSessionRevoked: () => promptSessionReconnect("session-revoked"),
|
|
2566
2276
|
connectSocket,
|
|
2567
2277
|
requestQuota,
|
|
2568
2278
|
sendClientInfo,
|
|
2569
|
-
setSocketDiagnostics,
|
|
2570
2279
|
});
|
|
2571
|
-
useEffect(() => {
|
|
2572
|
-
const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
|
|
2573
|
-
if (hasMySession &&
|
|
2574
|
-
socketInstanceRef.current?.readyState === WebSocket.OPEN) {
|
|
2575
|
-
toast.dismiss("session-revoked");
|
|
2576
|
-
}
|
|
2577
|
-
}, [activeSessions, sessionId, socketConnectionVersion, socketInstanceRef]);
|
|
2578
|
-
useEffect(() => {
|
|
2579
|
-
const handleRevoked = (event) => {
|
|
2580
|
-
const customEvent = event;
|
|
2581
|
-
promptSessionReconnect(customEvent?.detail?.reason);
|
|
2582
|
-
};
|
|
2583
|
-
window.addEventListener("parhelia:session-revoked", handleRevoked);
|
|
2584
|
-
return () => {
|
|
2585
|
-
window.removeEventListener("parhelia:session-revoked", handleRevoked);
|
|
2586
|
-
};
|
|
2587
|
-
}, [promptSessionReconnect]);
|
|
2588
2280
|
const sendSocketMessage = useCallback((message) => {
|
|
2589
2281
|
if (socketInstanceRef.current &&
|
|
2590
2282
|
socketInstanceRef.current.readyState === WebSocket.OPEN) {
|
|
2591
2283
|
socketInstanceRef.current.send(JSON.stringify(message));
|
|
2592
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
|
+
}
|
|
2593
2294
|
}, [socketInstanceRef]);
|
|
2594
2295
|
// URL update helper - defined early so it can be used by workspace/sidebar functions
|
|
2595
2296
|
const updateUrl = useCallback((params) => {
|
|
@@ -2633,13 +2334,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2633
2334
|
if (!options?.skipNavigationHistory) {
|
|
2634
2335
|
addNavigationEntry(targetWorkspaceId, item);
|
|
2635
2336
|
}
|
|
2636
|
-
//
|
|
2637
|
-
|
|
2638
|
-
switchWorkspacePushedRef.current = true;
|
|
2639
|
-
updateUrl({
|
|
2640
|
-
workspace: targetWorkspaceId,
|
|
2641
|
-
...options?.urlParams,
|
|
2642
|
-
});
|
|
2337
|
+
// Update URL
|
|
2338
|
+
updateUrl({ workspace: targetWorkspaceId });
|
|
2643
2339
|
if (typeof document.startViewTransition === "function") {
|
|
2644
2340
|
document.startViewTransition(() => {
|
|
2645
2341
|
flushSync(() => {
|
|
@@ -2659,6 +2355,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2659
2355
|
updateUrl,
|
|
2660
2356
|
handleSetShowAgentsPanel,
|
|
2661
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]);
|
|
2662
2366
|
// Helper: get all sidebar IDs that should be preserved (locked sidebars + their stack mates)
|
|
2663
2367
|
const getPreservedSidebarIds = useCallback(() => {
|
|
2664
2368
|
const lockedSet = new Set(lockedSidebarsRef.current);
|
|
@@ -2696,9 +2400,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2696
2400
|
setOpenSidebars(newSidebars);
|
|
2697
2401
|
setLockedSidebars((locked) => locked.filter((id) => id !== sidebarId));
|
|
2698
2402
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2699
|
-
if (sidebarId === "agents-panel") {
|
|
2700
|
-
setUserPreferences({ showAgentsPanel: false });
|
|
2701
|
-
}
|
|
2702
2403
|
startTransition(() => {
|
|
2703
2404
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2704
2405
|
});
|
|
@@ -2713,69 +2414,34 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2713
2414
|
];
|
|
2714
2415
|
openSidebarsRef.current = newSidebars;
|
|
2715
2416
|
setOpenSidebars(newSidebars);
|
|
2716
|
-
ensureSidebarPinned(sidebarId);
|
|
2717
2417
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2718
|
-
if (sidebarId === "agents-panel") {
|
|
2719
|
-
setUserPreferences({ showAgentsPanel: true });
|
|
2720
|
-
}
|
|
2721
|
-
// On mobile, close the editor form panel when opening a sidebar
|
|
2722
|
-
if (isMobile) {
|
|
2723
|
-
setMobileEditorPanelOpenRaw(false);
|
|
2724
|
-
}
|
|
2725
2418
|
startTransition(() => {
|
|
2726
2419
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2727
2420
|
});
|
|
2728
|
-
}, [
|
|
2729
|
-
updateUrl,
|
|
2730
|
-
getPreservedSidebarIds,
|
|
2731
|
-
normalizeSidebarStacks,
|
|
2732
|
-
ensureSidebarPinned,
|
|
2733
|
-
setUserPreferences,
|
|
2734
|
-
isMobile,
|
|
2735
|
-
]);
|
|
2421
|
+
}, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
|
|
2736
2422
|
// Ensure a sidebar is open (without toggling it closed if already open)
|
|
2737
|
-
const openSidebar = useCallback((sidebarId
|
|
2423
|
+
const openSidebar = useCallback((sidebarId) => {
|
|
2738
2424
|
const currentOpenSidebars = openSidebarsRef.current;
|
|
2739
2425
|
if (currentOpenSidebars.includes(sidebarId)) {
|
|
2740
2426
|
// Already open, nothing to do
|
|
2741
2427
|
return;
|
|
2742
2428
|
}
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
...currentOpenSidebars.filter((id) => preservedSet?.has(id)),
|
|
2750
|
-
sidebarId,
|
|
2751
|
-
];
|
|
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
|
+
];
|
|
2752
2435
|
openSidebarsRef.current = newSidebars;
|
|
2753
2436
|
setOpenSidebars(newSidebars);
|
|
2754
|
-
ensureSidebarPinned(sidebarId);
|
|
2755
2437
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2756
|
-
if (sidebarId === "agents-panel") {
|
|
2757
|
-
setUserPreferences({ showAgentsPanel: true });
|
|
2758
|
-
}
|
|
2759
|
-
// On mobile, close the editor form panel when opening a sidebar
|
|
2760
|
-
if (isMobile) {
|
|
2761
|
-
setMobileEditorPanelOpenRaw(false);
|
|
2762
|
-
}
|
|
2763
2438
|
startTransition(() => {
|
|
2764
2439
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2765
2440
|
});
|
|
2766
|
-
}, [
|
|
2767
|
-
updateUrl,
|
|
2768
|
-
getPreservedSidebarIds,
|
|
2769
|
-
normalizeSidebarStacks,
|
|
2770
|
-
ensureSidebarPinned,
|
|
2771
|
-
setUserPreferences,
|
|
2772
|
-
isMobile,
|
|
2773
|
-
]);
|
|
2441
|
+
}, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
|
|
2774
2442
|
// Toggle lock state for a sidebar stack (keeps it visible when selecting another)
|
|
2775
2443
|
// When toggling any sidebar, we toggle the entire stack it belongs to
|
|
2776
2444
|
const toggleSidebarLock = useCallback((sidebarId) => {
|
|
2777
|
-
if (isMobile)
|
|
2778
|
-
return;
|
|
2779
2445
|
const currentStacks = sidebarStacksRef.current;
|
|
2780
2446
|
const stackContainingSidebar = currentStacks.find((stack) => stack.includes(sidebarId));
|
|
2781
2447
|
const sidebarIdsToToggle = stackContainingSidebar || [sidebarId];
|
|
@@ -2793,7 +2459,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2793
2459
|
];
|
|
2794
2460
|
}
|
|
2795
2461
|
});
|
|
2796
|
-
}, [
|
|
2462
|
+
}, []);
|
|
2797
2463
|
const stackSidebar = useCallback((sidebarId, targetSidebarId, position = "after") => {
|
|
2798
2464
|
if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId)
|
|
2799
2465
|
return;
|
|
@@ -2825,38 +2491,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2825
2491
|
return normalizeSidebarStacks(openIds, next);
|
|
2826
2492
|
});
|
|
2827
2493
|
}, [normalizeSidebarStacks]);
|
|
2828
|
-
const moveSidebarToColumn = useCallback((sidebarId, targetSidebarId, position = "after") => {
|
|
2829
|
-
if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId) {
|
|
2830
|
-
return;
|
|
2831
|
-
}
|
|
2832
|
-
const currentOpen = openSidebarsRef.current;
|
|
2833
|
-
const baseOpen = currentOpen.filter((id) => id !== sidebarId);
|
|
2834
|
-
const targetIndex = baseOpen.indexOf(targetSidebarId);
|
|
2835
|
-
if (targetIndex === -1) {
|
|
2836
|
-
return;
|
|
2837
|
-
}
|
|
2838
|
-
const insertIndex = position === "before" ? targetIndex : targetIndex + 1;
|
|
2839
|
-
const nextOpen = [...baseOpen];
|
|
2840
|
-
nextOpen.splice(insertIndex, 0, sidebarId);
|
|
2841
|
-
openSidebarsRef.current = nextOpen;
|
|
2842
|
-
setOpenSidebars(nextOpen);
|
|
2843
|
-
startTransition(() => {
|
|
2844
|
-
updateUrl({ sidebar: nextOpen.join(",") || undefined });
|
|
2845
|
-
});
|
|
2846
|
-
setSidebarStacks((prev) => {
|
|
2847
|
-
const normalized = normalizeSidebarStacks(nextOpen, prev);
|
|
2848
|
-
const next = normalized
|
|
2849
|
-
.map((stack) => stack.filter((id) => id !== sidebarId))
|
|
2850
|
-
.filter((stack) => stack.length > 0);
|
|
2851
|
-
const targetStackIndex = next.findIndex((stack) => stack.includes(targetSidebarId));
|
|
2852
|
-
if (targetStackIndex === -1) {
|
|
2853
|
-
next.push([sidebarId]);
|
|
2854
|
-
return normalizeSidebarStacks(nextOpen, next);
|
|
2855
|
-
}
|
|
2856
|
-
next.splice(position === "before" ? targetStackIndex : targetStackIndex + 1, 0, [sidebarId]);
|
|
2857
|
-
return normalizeSidebarStacks(nextOpen, next);
|
|
2858
|
-
});
|
|
2859
|
-
}, [normalizeSidebarStacks, updateUrl]);
|
|
2860
2494
|
const unstackSidebar = useCallback((sidebarId) => {
|
|
2861
2495
|
setSidebarStacks((prev) => {
|
|
2862
2496
|
const openIds = openSidebarsRef.current;
|
|
@@ -2902,34 +2536,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2902
2536
|
// Get resolved sidebar (with panels materialized)
|
|
2903
2537
|
// Note: This is defined as a function that will be called later when editContext is available
|
|
2904
2538
|
const sidebars = configuration.editor.sidebars ?? [];
|
|
2905
|
-
const taskboardSidebarIds = new Set([
|
|
2906
|
-
"taskboard-project-list",
|
|
2907
|
-
"taskboard-my-tasks",
|
|
2908
|
-
]);
|
|
2909
|
-
const getSidebarsForWorkspace = useCallback((targetWorkspaceId) => {
|
|
2910
|
-
const isTaskboardWorkspace = targetWorkspaceId === "taskboard";
|
|
2911
|
-
const workspaceAllowedSidebarIds = userInfo.workspaces?.find((w) => w.id === targetWorkspaceId)
|
|
2912
|
-
?.sidebars ?? [];
|
|
2913
|
-
return sidebars.filter((s) => {
|
|
2914
|
-
const isTaskboardSidebar = taskboardSidebarIds.has(s.id);
|
|
2915
|
-
if (isTaskboardWorkspace && !isTaskboardSidebar)
|
|
2916
|
-
return false;
|
|
2917
|
-
if (!isTaskboardWorkspace && isTaskboardSidebar)
|
|
2918
|
-
return false;
|
|
2919
|
-
// Always show agents-panel regardless of workspace settings.
|
|
2920
|
-
if (s.id === "agents-panel") {
|
|
2921
|
-
return true;
|
|
2922
|
-
}
|
|
2923
|
-
// If no workspace settings or no sidebars defined for current workspace, show all.
|
|
2924
|
-
if (workspaceAllowedSidebarIds.length === 0) {
|
|
2925
|
-
return true;
|
|
2926
|
-
}
|
|
2927
|
-
// Only show sidebars that are in the allowed list for the current workspace.
|
|
2928
|
-
return workspaceAllowedSidebarIds.includes(s.id);
|
|
2929
|
-
});
|
|
2930
|
-
}, [sidebars, userInfo.workspaces]);
|
|
2931
2539
|
const getResolvedSidebar = useCallback((sidebarId) => {
|
|
2932
|
-
const sidebar =
|
|
2540
|
+
const sidebar = sidebars.find((s) => s.id === sidebarId);
|
|
2933
2541
|
if (!sidebar)
|
|
2934
2542
|
return undefined;
|
|
2935
2543
|
// Resolve panel factories using editContextRef to avoid circular dependency
|
|
@@ -2943,35 +2551,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2943
2551
|
...sidebar,
|
|
2944
2552
|
panels: resolvedPanels,
|
|
2945
2553
|
};
|
|
2946
|
-
}, [
|
|
2947
|
-
useEffect(() => {
|
|
2948
|
-
if (!currentWorkspace.supportsSidebars) {
|
|
2949
|
-
return;
|
|
2950
|
-
}
|
|
2951
|
-
const allowedIds = new Set(getSidebarsForWorkspace(workspaceId).map((sidebar) => sidebar.id));
|
|
2952
|
-
const currentOpen = openSidebarsRef.current;
|
|
2953
|
-
let nextOpen = currentOpen.filter((id) => allowedIds.has(id));
|
|
2954
|
-
if (nextOpen.length === 0 && currentWorkspace.defaultSidebars?.length) {
|
|
2955
|
-
nextOpen = currentWorkspace.defaultSidebars.filter((id) => allowedIds.has(id));
|
|
2956
|
-
}
|
|
2957
|
-
const unchanged = nextOpen.length === currentOpen.length &&
|
|
2958
|
-
nextOpen.every((id, index) => id === currentOpen[index]);
|
|
2959
|
-
if (unchanged) {
|
|
2960
|
-
return;
|
|
2961
|
-
}
|
|
2962
|
-
openSidebarsRef.current = nextOpen;
|
|
2963
|
-
setOpenSidebars(nextOpen);
|
|
2964
|
-
setSidebarStacks((prev) => normalizeSidebarStacks(nextOpen, prev));
|
|
2965
|
-
startTransition(() => {
|
|
2966
|
-
updateUrl({ sidebar: nextOpen.join(",") || undefined });
|
|
2967
|
-
});
|
|
2968
|
-
}, [
|
|
2969
|
-
currentWorkspace,
|
|
2970
|
-
getSidebarsForWorkspace,
|
|
2971
|
-
normalizeSidebarStacks,
|
|
2972
|
-
updateUrl,
|
|
2973
|
-
workspaceId,
|
|
2974
|
-
]);
|
|
2554
|
+
}, [sidebars]);
|
|
2975
2555
|
// Listen for switch-workspace and open-sidebar commands from agents via websocket
|
|
2976
2556
|
useEffect(() => {
|
|
2977
2557
|
const handleAgentMessage = (message) => {
|
|
@@ -3185,45 +2765,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3185
2765
|
}
|
|
3186
2766
|
return true;
|
|
3187
2767
|
}, [operations, ignoreBlur, sessionId]);
|
|
3188
|
-
const quickSwitcherEntries = useMemo(() => {
|
|
3189
|
-
const entries = [];
|
|
3190
|
-
const seen = new Set();
|
|
3191
|
-
const pushEntry = (entry) => {
|
|
3192
|
-
const key = entry.item
|
|
3193
|
-
? `${entry.workspaceId}:${entry.item.id}:${entry.item.language}:${entry.item.version}`
|
|
3194
|
-
: `${entry.workspaceId}:no-item`;
|
|
3195
|
-
if (seen.has(key))
|
|
3196
|
-
return;
|
|
3197
|
-
seen.add(key);
|
|
3198
|
-
entries.push(entry);
|
|
3199
|
-
};
|
|
3200
|
-
for (const entry of navigationHistory) {
|
|
3201
|
-
pushEntry(entry);
|
|
3202
|
-
}
|
|
3203
|
-
for (const entry of browseHistory) {
|
|
3204
|
-
if (!entry.id || !entry.language)
|
|
3205
|
-
continue;
|
|
3206
|
-
pushEntry({
|
|
3207
|
-
workspaceId,
|
|
3208
|
-
item: {
|
|
3209
|
-
id: entry.id,
|
|
3210
|
-
language: entry.language,
|
|
3211
|
-
version: entry.version ?? 0,
|
|
3212
|
-
},
|
|
3213
|
-
timestamp: entry.visitedAt
|
|
3214
|
-
? new Date(entry.visitedAt).getTime()
|
|
3215
|
-
: Date.now(),
|
|
3216
|
-
displayName: entry.name || workspaceId,
|
|
3217
|
-
itemName: entry.name,
|
|
3218
|
-
itemPath: entry.path,
|
|
3219
|
-
itemIcon: entry.icon,
|
|
3220
|
-
});
|
|
3221
|
-
}
|
|
3222
|
-
return entries.slice(0, 25);
|
|
3223
|
-
}, [navigationHistory, browseHistory, workspaceId]);
|
|
3224
2768
|
// Quick switcher handlers
|
|
3225
2769
|
const showQuickSwitcher = useCallback((show) => {
|
|
3226
|
-
if (show &&
|
|
2770
|
+
if (show && navigationHistory.length > 1) {
|
|
3227
2771
|
setQuickSwitcherVisible(true);
|
|
3228
2772
|
// Start with index 1 (second entry - previous entry) for quick switching
|
|
3229
2773
|
setQuickSwitcherSelectedIndex(1);
|
|
@@ -3231,11 +2775,11 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3231
2775
|
else {
|
|
3232
2776
|
setQuickSwitcherVisible(false);
|
|
3233
2777
|
}
|
|
3234
|
-
}, [
|
|
2778
|
+
}, [navigationHistory]);
|
|
3235
2779
|
const cycleQuickSwitcher = useCallback((direction) => {
|
|
3236
2780
|
if (!quickSwitcherVisible)
|
|
3237
2781
|
return;
|
|
3238
|
-
const maxItems = Math.min(5,
|
|
2782
|
+
const maxItems = Math.min(5, navigationHistory.length);
|
|
3239
2783
|
setQuickSwitcherSelectedIndex((current) => {
|
|
3240
2784
|
let newIndex = current;
|
|
3241
2785
|
// Determine grid layout (responsive columns)
|
|
@@ -3280,9 +2824,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3280
2824
|
}
|
|
3281
2825
|
return newIndex;
|
|
3282
2826
|
});
|
|
3283
|
-
}, [quickSwitcherVisible,
|
|
2827
|
+
}, [quickSwitcherVisible, navigationHistory]);
|
|
3284
2828
|
const handleQuickSwitcherSelect = useCallback((index) => {
|
|
3285
|
-
const selectedEntry =
|
|
2829
|
+
const selectedEntry = navigationHistory[index];
|
|
3286
2830
|
if (selectedEntry) {
|
|
3287
2831
|
// Determine target workspace: entries with items should go to "editor" workspace
|
|
3288
2832
|
// (fixes issue where browse history entries initialized with wrong workspaceId)
|
|
@@ -3334,46 +2878,23 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3334
2878
|
}
|
|
3335
2879
|
setQuickSwitcherVisible(false);
|
|
3336
2880
|
}, [
|
|
3337
|
-
|
|
2881
|
+
navigationHistory,
|
|
3338
2882
|
loadItem,
|
|
3339
2883
|
switchWorkspace,
|
|
3340
2884
|
workspaceId,
|
|
3341
2885
|
item,
|
|
3342
2886
|
setNavigationHistory,
|
|
3343
2887
|
]);
|
|
3344
|
-
useEffect(() => {
|
|
3345
|
-
if (typeof window === "undefined" ||
|
|
3346
|
-
process.env.PARHELIA_DEV_MODE !== "true") {
|
|
3347
|
-
return;
|
|
3348
|
-
}
|
|
3349
|
-
window.__parheliaQuickSwitcherTestApi = {
|
|
3350
|
-
open: () => showQuickSwitcher(true),
|
|
3351
|
-
cycle: (direction = "next") => cycleQuickSwitcher(direction),
|
|
3352
|
-
closeWithoutSelection: () => setQuickSwitcherVisible(false),
|
|
3353
|
-
selectCurrent: () => handleQuickSwitcherSelect(quickSwitcherSelectedIndex),
|
|
3354
|
-
getState: () => ({
|
|
3355
|
-
visible: quickSwitcherVisible,
|
|
3356
|
-
selectedIndex: quickSwitcherSelectedIndex,
|
|
3357
|
-
entryCount: quickSwitcherEntries.length,
|
|
3358
|
-
entries: quickSwitcherEntries.map((entry) => ({
|
|
3359
|
-
workspaceId: entry.workspaceId,
|
|
3360
|
-
itemId: entry.item?.id,
|
|
3361
|
-
displayName: entry.displayName,
|
|
3362
|
-
})),
|
|
3363
|
-
}),
|
|
3364
|
-
};
|
|
3365
|
-
return () => {
|
|
3366
|
-
delete window.__parheliaQuickSwitcherTestApi;
|
|
3367
|
-
};
|
|
3368
|
-
}, [
|
|
3369
|
-
showQuickSwitcher,
|
|
3370
|
-
cycleQuickSwitcher,
|
|
3371
|
-
handleQuickSwitcherSelect,
|
|
3372
|
-
quickSwitcherSelectedIndex,
|
|
3373
|
-
]);
|
|
3374
2888
|
const { handleKeyDown } = useKeyboardNavigation({
|
|
3375
2889
|
editContextRef,
|
|
3376
|
-
|
|
2890
|
+
operations,
|
|
2891
|
+
pageViewContext: activePageViewContext,
|
|
2892
|
+
configuration,
|
|
2893
|
+
item,
|
|
2894
|
+
browseHistory,
|
|
2895
|
+
loadItem,
|
|
2896
|
+
showInfoToast,
|
|
2897
|
+
showErrorToast,
|
|
3377
2898
|
executeCommand,
|
|
3378
2899
|
showQuickSwitcher,
|
|
3379
2900
|
cycleQuickSwitcher,
|
|
@@ -3493,19 +3014,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3493
3014
|
}
|
|
3494
3015
|
return null;
|
|
3495
3016
|
};
|
|
3496
|
-
let modifierWasPressedOnMouseDown = false;
|
|
3497
|
-
const handleMouseDown = (event) => {
|
|
3498
|
-
modifierWasPressedOnMouseDown = event.ctrlKey || event.metaKey;
|
|
3499
|
-
};
|
|
3500
3017
|
const handleCtrlClick = async (event) => {
|
|
3501
|
-
// Only proceed if Ctrl
|
|
3502
|
-
// This avoids accidental navigation when users press Ctrl after selecting text to copy.
|
|
3503
|
-
if (!modifierWasPressedOnMouseDown)
|
|
3504
|
-
return;
|
|
3505
|
-
// Also require the modifier to still be held for the final click event.
|
|
3018
|
+
// Only proceed if Ctrl (or Cmd on Mac) is pressed
|
|
3506
3019
|
if (!event.ctrlKey && !event.metaKey)
|
|
3507
3020
|
return;
|
|
3508
|
-
modifierWasPressedOnMouseDown = false;
|
|
3509
3021
|
const target = event.target;
|
|
3510
3022
|
const text = getTextFromElement(target);
|
|
3511
3023
|
if (text && isGuid(text)) {
|
|
@@ -3520,7 +3032,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3520
3032
|
skipViewChange: true,
|
|
3521
3033
|
});
|
|
3522
3034
|
if (item) {
|
|
3523
|
-
|
|
3035
|
+
// Switch to the editor view
|
|
3036
|
+
switchView("editor", {
|
|
3524
3037
|
skipNavigationHistory: true,
|
|
3525
3038
|
});
|
|
3526
3039
|
showInfoToast({
|
|
@@ -3546,14 +3059,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3546
3059
|
}
|
|
3547
3060
|
};
|
|
3548
3061
|
if (typeof document !== "undefined") {
|
|
3549
|
-
document.addEventListener("mousedown", handleMouseDown, true);
|
|
3550
3062
|
document.addEventListener("click", handleCtrlClick, true);
|
|
3551
3063
|
return () => {
|
|
3552
|
-
document.removeEventListener("mousedown", handleMouseDown, true);
|
|
3553
3064
|
document.removeEventListener("click", handleCtrlClick, true);
|
|
3554
3065
|
};
|
|
3555
3066
|
}
|
|
3556
|
-
}, [loadItem,
|
|
3067
|
+
}, [loadItem, switchView, showInfoToast, showErrorToast]);
|
|
3557
3068
|
useEffect(() => {
|
|
3558
3069
|
const handleGlobalBlur = () => {
|
|
3559
3070
|
operations.onFieldBlur?.();
|
|
@@ -3591,6 +3102,21 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3591
3102
|
// Otherwise, only show workspaces that are in the settings
|
|
3592
3103
|
return workspaceIdsFromSettings.includes(w.id) && !w.visible;
|
|
3593
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));
|
|
3594
3120
|
// Handle initial mode setup from URL (only on initial load)
|
|
3595
3121
|
useEffect(() => {
|
|
3596
3122
|
if (!isInitialLoad)
|
|
@@ -3635,7 +3161,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3635
3161
|
// This is especially important when called from the tour, where the current workspace
|
|
3636
3162
|
// might be the editor and URL-only navigation would get "corrected" back.
|
|
3637
3163
|
try {
|
|
3638
|
-
|
|
3164
|
+
switchView("home", {
|
|
3639
3165
|
skipConfirmation: true,
|
|
3640
3166
|
skipNavigationHistory: true,
|
|
3641
3167
|
});
|
|
@@ -3682,6 +3208,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3682
3208
|
const current = new URLSearchParams(searchParams.toString());
|
|
3683
3209
|
current.delete("version");
|
|
3684
3210
|
current.delete("itemid");
|
|
3211
|
+
current.delete("view"); // Remove legacy param
|
|
3685
3212
|
current.delete("workspace"); // Clear workspace
|
|
3686
3213
|
current.set("create", "1");
|
|
3687
3214
|
const newUrl = `${pathname}?${current.toString()}`;
|
|
@@ -3961,8 +3488,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3961
3488
|
setShowOnlyMyChanges,
|
|
3962
3489
|
filterByCurrentLanguage,
|
|
3963
3490
|
setFilterByCurrentLanguage,
|
|
3964
|
-
historySearchQuery,
|
|
3965
|
-
setHistorySearchQuery,
|
|
3966
3491
|
refreshHistory,
|
|
3967
3492
|
isRefreshing,
|
|
3968
3493
|
activeSessions,
|
|
@@ -4000,8 +3525,19 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4000
3525
|
workspaceId,
|
|
4001
3526
|
previousWorkspaceId,
|
|
4002
3527
|
switchWorkspace,
|
|
4003
|
-
// Sidebar state
|
|
4004
|
-
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
|
+
}),
|
|
4005
3541
|
openSidebars,
|
|
4006
3542
|
pinnedSidebars,
|
|
4007
3543
|
lockedSidebars,
|
|
@@ -4011,12 +3547,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4011
3547
|
toggleSidebarPin,
|
|
4012
3548
|
toggleSidebarLock,
|
|
4013
3549
|
stackSidebar,
|
|
4014
|
-
moveSidebarToColumn,
|
|
4015
3550
|
unstackSidebar,
|
|
4016
3551
|
reorderSidebarInStack,
|
|
4017
3552
|
reorderPinnedSidebars,
|
|
4018
3553
|
reorderOpenSidebars,
|
|
4019
3554
|
getResolvedSidebar,
|
|
3555
|
+
// Legacy compatibility (deprecated)
|
|
3556
|
+
viewName,
|
|
3557
|
+
previousViewName,
|
|
3558
|
+
switchView,
|
|
3559
|
+
view: currentView,
|
|
3560
|
+
visibleViews,
|
|
4020
3561
|
compareMode,
|
|
4021
3562
|
setCompareMode,
|
|
4022
3563
|
fullscreen,
|
|
@@ -4056,7 +3597,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4056
3597
|
addSocketMessageListener,
|
|
4057
3598
|
sendSocketMessage,
|
|
4058
3599
|
socketConnectionVersion,
|
|
4059
|
-
socketDiagnostics,
|
|
4060
3600
|
currentItemDescriptor,
|
|
4061
3601
|
editorSlots,
|
|
4062
3602
|
activeSlotId,
|
|
@@ -4069,7 +3609,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4069
3609
|
setActiveSlot,
|
|
4070
3610
|
revision,
|
|
4071
3611
|
notifyPageModelReady,
|
|
4072
|
-
pageModelReadyToken,
|
|
4073
3612
|
selectedComment,
|
|
4074
3613
|
setSelectedComment,
|
|
4075
3614
|
comments,
|
|
@@ -4148,8 +3687,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4148
3687
|
setEnableCompletions,
|
|
4149
3688
|
showComponentNavigator,
|
|
4150
3689
|
setShowComponentNavigator: handleSetShowComponentNavigator,
|
|
4151
|
-
isComponentNavigatorOpenForSlot,
|
|
4152
|
-
setComponentNavigatorOpenForSlot,
|
|
4153
3690
|
showAgentsPanel,
|
|
4154
3691
|
setShowAgentsPanel: handleSetShowAgentsPanel,
|
|
4155
3692
|
showMinimap,
|
|
@@ -4161,12 +3698,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4161
3698
|
helpTerminalProfileName,
|
|
4162
3699
|
helpTerminalActiveTab,
|
|
4163
3700
|
setHelpTerminalActiveTab,
|
|
4164
|
-
selectedHelpSectionId,
|
|
4165
|
-
setSelectedHelpSectionId,
|
|
4166
3701
|
showAgentsWorkspaceEditor,
|
|
4167
3702
|
setShowAgentsWorkspaceEditor: handleSetShowAgentsWorkspaceEditor,
|
|
4168
|
-
selectedAgentsWorkspaceAgentId,
|
|
4169
|
-
setSelectedAgentsWorkspaceAgentId,
|
|
4170
3703
|
activeEditorTab,
|
|
4171
3704
|
setActiveEditorTab,
|
|
4172
3705
|
showLayoutComponents,
|
|
@@ -4175,8 +3708,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4175
3708
|
isQuotaExceeded: isQuotaExceeded(),
|
|
4176
3709
|
getQuotaWarningMessage,
|
|
4177
3710
|
isMobile,
|
|
4178
|
-
mobileEditorPanelOpen,
|
|
4179
|
-
setMobileEditorPanelOpen: handleSetMobileEditorPanelOpen,
|
|
4180
3711
|
openDialog,
|
|
4181
3712
|
webSocketMessages,
|
|
4182
3713
|
clearWebSocketMessages: () => setWebSocketMessages([]),
|
|
@@ -4215,6 +3746,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4215
3746
|
configuration,
|
|
4216
3747
|
updateUrl,
|
|
4217
3748
|
workspaceId,
|
|
3749
|
+
switchView,
|
|
4218
3750
|
pathname,
|
|
4219
3751
|
router,
|
|
4220
3752
|
item,
|
|
@@ -4244,6 +3776,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4244
3776
|
currentWorkspace,
|
|
4245
3777
|
previousWorkspaceId,
|
|
4246
3778
|
switchWorkspace,
|
|
3779
|
+
allowedSidebarIds,
|
|
4247
3780
|
openSidebars,
|
|
4248
3781
|
pinnedSidebars,
|
|
4249
3782
|
lockedSidebars,
|
|
@@ -4255,6 +3788,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4255
3788
|
reorderOpenSidebars,
|
|
4256
3789
|
getResolvedSidebar,
|
|
4257
3790
|
viewName,
|
|
3791
|
+
previousViewName,
|
|
3792
|
+
currentView,
|
|
3793
|
+
visibleViews,
|
|
4258
3794
|
compareMode,
|
|
4259
3795
|
// Important: in multi-slot mode the active PageViewContext can change
|
|
4260
3796
|
// without the base `pageViewContext` identity changing (e.g. switching slots).
|
|
@@ -4279,7 +3815,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4279
3815
|
currentItemDescriptor,
|
|
4280
3816
|
revision,
|
|
4281
3817
|
notifyPageModelReady,
|
|
4282
|
-
pageModelReadyToken,
|
|
4283
3818
|
selectedComment,
|
|
4284
3819
|
comments,
|
|
4285
3820
|
availableCommentTags,
|
|
@@ -4298,7 +3833,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4298
3833
|
quickSwitcherSelectedIndex,
|
|
4299
3834
|
handleQuickSwitcherSelect,
|
|
4300
3835
|
webSocketMessages,
|
|
4301
|
-
socketDiagnostics,
|
|
4302
3836
|
factoriesRef,
|
|
4303
3837
|
user,
|
|
4304
3838
|
statusMessage,
|
|
@@ -4307,11 +3841,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4307
3841
|
isQuotaExceeded,
|
|
4308
3842
|
getQuotaWarningMessage,
|
|
4309
3843
|
isMobile,
|
|
4310
|
-
mobileEditorPanelOpen,
|
|
4311
|
-
handleSetMobileEditorPanelOpen,
|
|
4312
3844
|
showComponentNavigator,
|
|
4313
|
-
isComponentNavigatorOpenForSlot,
|
|
4314
|
-
setComponentNavigatorOpenForSlot,
|
|
4315
3845
|
handleSetShowComponentNavigator,
|
|
4316
3846
|
showAgentsPanel,
|
|
4317
3847
|
handleSetShowAgentsPanel,
|
|
@@ -4323,9 +3853,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4323
3853
|
helpTerminalProfileName,
|
|
4324
3854
|
helpTerminalActiveTab,
|
|
4325
3855
|
setHelpTerminalActiveTab,
|
|
4326
|
-
selectedHelpSectionId,
|
|
4327
3856
|
showAgentsWorkspaceEditor,
|
|
4328
|
-
selectedAgentsWorkspaceAgentId,
|
|
4329
3857
|
activeEditorTab,
|
|
4330
3858
|
showLayoutComponents,
|
|
4331
3859
|
openDialog,
|
|
@@ -4570,40 +4098,18 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4570
4098
|
// prevDependencies.current = currentDependencies;
|
|
4571
4099
|
// editContextRef.current = editContext;
|
|
4572
4100
|
// }, [editContext]);
|
|
4573
|
-
// Auto-open the mobile editor panel for new selection/intent changes, but
|
|
4574
|
-
// keep a manual close sticky for the exact same context.
|
|
4575
|
-
useEffect(() => {
|
|
4576
|
-
if (!isMobile || workspaceId !== "editor")
|
|
4577
|
-
return;
|
|
4578
|
-
if (activeEditorTab) {
|
|
4579
|
-
handleSetMobileEditorPanelOpen(true);
|
|
4580
|
-
return;
|
|
4581
|
-
}
|
|
4582
|
-
if (!(selection.length > 0 || insertMode))
|
|
4583
|
-
return;
|
|
4584
|
-
if (dismissedMobilePanelToken === mobilePanelDismissToken)
|
|
4585
|
-
return;
|
|
4586
|
-
handleSetMobileEditorPanelOpen(true);
|
|
4587
|
-
}, [
|
|
4588
|
-
activeEditorTab,
|
|
4589
|
-
dismissedMobilePanelToken,
|
|
4590
|
-
handleSetMobileEditorPanelOpen,
|
|
4591
|
-
insertMode,
|
|
4592
|
-
isMobile,
|
|
4593
|
-
mobilePanelDismissToken,
|
|
4594
|
-
selection,
|
|
4595
|
-
workspaceId,
|
|
4596
|
-
]);
|
|
4597
4101
|
useEffect(() => {
|
|
4598
4102
|
fieldsEditContext.clearModifiedFields();
|
|
4599
4103
|
}, [currentItemDescriptor]);
|
|
4600
|
-
if (!
|
|
4104
|
+
if (!currentView)
|
|
4601
4105
|
return null;
|
|
4602
|
-
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: () => {
|
|
4603
4107
|
setTimeout(() => {
|
|
4604
4108
|
setShowFullscreenHint(false);
|
|
4605
4109
|
}, 600);
|
|
4606
|
-
}, "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: () => {
|
|
4607
4113
|
setIsTourActive(false);
|
|
4608
4114
|
// Remove tour state from URL
|
|
4609
4115
|
// Use history.replaceState instead of router.replace to avoid triggering React navigation
|
|
@@ -4614,13 +4120,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4614
4120
|
? `${window.location.pathname}?${queryString}`
|
|
4615
4121
|
: window.location.pathname;
|
|
4616
4122
|
window.history.replaceState(null, "", newUrl);
|
|
4617
|
-
}, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(
|
|
4618
|
-
return (_jsx(
|
|
4619
|
-
currentWorkspace.id === "taskboard") &&
|
|
4620
|
-
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) => {
|
|
4621
|
-
if (!open) {
|
|
4622
|
-
setConcurrentUserLimitError(null);
|
|
4623
|
-
}
|
|
4624
|
-
}, 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: quickSwitcherEntries.slice(0, 5), selectedIndex: quickSwitcherSelectedIndex, onSelect: handleQuickSwitcherSelect, onClose: () => setQuickSwitcherVisible(false) }), _jsx(EditContextMenu, { ref: contextMenuRef }), _jsx(FeatureGate, { feature: LicenseFeatures.AI, children: _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 })] }) }) }) }));
|
|
4625
4125
|
}
|
|
4626
4126
|
//# sourceMappingURL=EditorShell.js.map
|