@parhelia/core 0.1.12601 → 0.1.12602
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 +99 -191
- 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 +63 -37
- 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 +5 -6
- 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 +572 -2508
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AgentTerminalStatusBar.d.ts +4 -9
- package/dist/editor/ai/AgentTerminalStatusBar.js +56 -481
- package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
- package/dist/editor/ai/Agents.js +113 -161
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.d.ts +1 -10
- package/dist/editor/ai/AiResponseMessage.js +26 -267
- 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/EditOperationsPanel.d.ts +2 -3
- package/dist/editor/ai/EditOperationsPanel.js +78 -21
- package/dist/editor/ai/EditOperationsPanel.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 +202 -614
- 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 -117
- 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 +100 -90
- 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 +258 -853
- 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 +15 -73
- 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.d.ts +1 -2
- package/dist/editor/reviews/Comment.js +15 -92
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +5 -70
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.d.ts +1 -3
- package/dist/editor/reviews/CommentView.js +6 -26
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.js +75 -140
- 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 +3 -4
- package/dist/editor/reviews/useReviews.js +32 -21
- package/dist/editor/reviews/useReviews.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +5 -240
- package/dist/editor/services/agentService.js +39 -299
- 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/IndexOverview.js +1 -3
- package/dist/editor/settings/IndexOverview.js.map +1 -1
- 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 -23
- 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 -324
- 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 +6 -67
- package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
- package/dist/editor/settings/panels/StatusPanel.js +2 -7
- package/dist/editor/settings/panels/StatusPanel.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 -24
- 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 +14 -48
- package/dist/setup/services/setupWizardService.js +17 -52
- 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 -46
- 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 -70
- package/package.json +15 -19
- package/styles.css +10 -39
|
@@ -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();
|
|
@@ -322,7 +307,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
322
307
|
const [ignoreBlur, setIgnoreBlur] = useState(false);
|
|
323
308
|
const [currentItemDescriptor, setCurrentItemDescriptor] = useState();
|
|
324
309
|
const currentItemDescriptorRef = useRef(undefined);
|
|
325
|
-
const latestGlobalLoadKeyRef = useRef(null);
|
|
326
310
|
const [editorSlots, setEditorSlots] = useState(() => {
|
|
327
311
|
// Always start with empty slots - don't persist the number of slots
|
|
328
312
|
return [];
|
|
@@ -342,29 +326,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
342
326
|
activeSlotIdRef.current = activeSlotId;
|
|
343
327
|
}, [activeSlotId]);
|
|
344
328
|
const [slotContexts, setSlotContexts] = useState(() => new Map());
|
|
345
|
-
const promptSessionReconnect = useCallback((reason) => {
|
|
346
|
-
const description = reason && reason !== "session-revoked"
|
|
347
|
-
? `${reason}. Click reconnect to continue in this browser.`
|
|
348
|
-
: "You were disconnected because this account is active in another browser.";
|
|
349
|
-
toast.error("Session disconnected", {
|
|
350
|
-
id: "session-revoked",
|
|
351
|
-
description,
|
|
352
|
-
action: {
|
|
353
|
-
label: "Reconnect",
|
|
354
|
-
onClick: async () => {
|
|
355
|
-
const result = await reconnectSession(sessionId);
|
|
356
|
-
if (result.type === "success") {
|
|
357
|
-
window.location.reload();
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
toast.error("Reconnect failed", {
|
|
361
|
-
description: "Could not claim this browser session. Try again.",
|
|
362
|
-
});
|
|
363
|
-
},
|
|
364
|
-
},
|
|
365
|
-
duration: Infinity,
|
|
366
|
-
});
|
|
367
|
-
}, [sessionId]);
|
|
368
329
|
// Track previous item ID to detect actual navigation between pages
|
|
369
330
|
const previousItemIdRef = useRef(undefined);
|
|
370
331
|
useEffect(() => {
|
|
@@ -393,18 +354,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
393
354
|
// Ref to track when we're handling a popstate event (browser back/forward)
|
|
394
355
|
// This prevents the URL sync effect from pushing new history entries during back navigation
|
|
395
356
|
const isHandlingPopStateRef = useRef(false);
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
// Uses pathname+search (not full href) so comparisons are consistent with the
|
|
401
|
-
// relative URLs produced by the URL sync effect and updateUrl.
|
|
402
|
-
const lastUrlRef = useRef(typeof window !== "undefined"
|
|
403
|
-
? `${window.location.pathname}${window.location.search}`
|
|
404
|
-
: "");
|
|
405
|
-
// The very first URL sync after initial load should replaceState (not pushState)
|
|
406
|
-
// so the initial bare URL isn't left as a dead-end history entry.
|
|
407
|
-
const isFirstUrlSyncRef = useRef(true);
|
|
357
|
+
// Ref to track the last known URL for the popstate handler
|
|
358
|
+
// This is updated both when the popstate handler runs AND when the URL sync effect pushes a new URL
|
|
359
|
+
// Without this, the popstate handler would have a stale lastUrl value after pushState calls
|
|
360
|
+
const lastUrlRef = useRef(typeof window !== "undefined" ? window.location.href : "");
|
|
408
361
|
const [inlineEditingFieldElement, setInlineEditingFieldElement] = useState();
|
|
409
362
|
const [lockedField, setLockedField] = useState();
|
|
410
363
|
const [itemLanguages, setItemLanguages] = useState([]);
|
|
@@ -417,16 +370,26 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
417
370
|
const [showSuggestedEditsDiff, setShowSuggestedEditsDiff] = useState(false);
|
|
418
371
|
const [availableCommentTags, setAvailableCommentTags] = useState([]);
|
|
419
372
|
const [showComments, setShowComments] = useState(() => {
|
|
420
|
-
|
|
373
|
+
const savedShowComments = typeof window !== "undefined"
|
|
374
|
+
? localStorage.getItem("editor.showComments")
|
|
375
|
+
: null;
|
|
376
|
+
return savedShowComments ? JSON.parse(savedShowComments) : true;
|
|
421
377
|
});
|
|
422
378
|
useEffect(() => {
|
|
423
|
-
|
|
379
|
+
if (typeof window !== "undefined") {
|
|
380
|
+
localStorage.setItem("editor.showComments", JSON.stringify(showComments));
|
|
381
|
+
}
|
|
424
382
|
}, [showComments]);
|
|
425
383
|
const [showResolvedComments, setShowResolvedComments] = useState(() => {
|
|
426
|
-
|
|
384
|
+
const saved = typeof window !== "undefined"
|
|
385
|
+
? localStorage.getItem("editor.showResolvedComments")
|
|
386
|
+
: null;
|
|
387
|
+
return saved ? JSON.parse(saved) : false;
|
|
427
388
|
});
|
|
428
389
|
useEffect(() => {
|
|
429
|
-
|
|
390
|
+
if (typeof window !== "undefined") {
|
|
391
|
+
localStorage.setItem("editor.showResolvedComments", JSON.stringify(showResolvedComments));
|
|
392
|
+
}
|
|
430
393
|
}, [showResolvedComments]);
|
|
431
394
|
const [selectedComment, setSelectedComment] = useState();
|
|
432
395
|
const [browseHistory, setBrowseHistory] = useState(() => {
|
|
@@ -445,12 +408,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
445
408
|
visitedAt: entry.visitedAt,
|
|
446
409
|
}));
|
|
447
410
|
});
|
|
448
|
-
// Navigation history for browser history (
|
|
411
|
+
// Navigation history for browser history (view + item combinations)
|
|
449
412
|
const [navigationHistory, setNavigationHistory] = useState(() => {
|
|
450
|
-
// Initialize from browse history with
|
|
413
|
+
// Initialize from browse history with current view
|
|
451
414
|
if (!userInfo.browseHistory)
|
|
452
415
|
return [];
|
|
453
416
|
const defaultWorkspaceId = searchParams.get("workspace") ??
|
|
417
|
+
searchParams.get("view") ??
|
|
454
418
|
configuration.editor.defaultWorkspace ??
|
|
455
419
|
configuration.editor.workspaces?.[0]?.id ??
|
|
456
420
|
"editor";
|
|
@@ -482,43 +446,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
482
446
|
const [statusMessage, setStatusMessage] = useState("");
|
|
483
447
|
const [focusFieldComponentId, setFocusFieldComponentId] = useState();
|
|
484
448
|
const [enableCompletions, setEnableCompletions] = useState(false);
|
|
485
|
-
const [
|
|
486
|
-
const [slotComponentNavigatorVisibility, setSlotComponentNavigatorVisibility] = useState({});
|
|
487
|
-
useEffect(() => {
|
|
488
|
-
setSlotComponentNavigatorVisibility((prev) => {
|
|
489
|
-
const next = {};
|
|
490
|
-
let changed = false;
|
|
491
|
-
for (const slot of editorSlots) {
|
|
492
|
-
if (Object.prototype.hasOwnProperty.call(prev, slot.slotId)) {
|
|
493
|
-
next[slot.slotId] = prev[slot.slotId];
|
|
494
|
-
}
|
|
495
|
-
else {
|
|
496
|
-
next[slot.slotId] = showComponentNavigatorDefault;
|
|
497
|
-
changed = true;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
if (Object.keys(prev).length !== editorSlots.length) {
|
|
501
|
-
changed = true;
|
|
502
|
-
}
|
|
503
|
-
return changed ? next : prev;
|
|
504
|
-
});
|
|
505
|
-
}, [editorSlots, showComponentNavigatorDefault]);
|
|
449
|
+
const [showComponentNavigator, setShowComponentNavigator] = useState(userPreferences.showComponentNavigator ?? false);
|
|
506
450
|
const [showAgentsPanel, setShowAgentsPanel] = useState(userPreferences.showAgentsPanel ?? false);
|
|
507
451
|
const [showMinimap, setShowMinimap] = useState(userPreferences.showMinimap ?? true);
|
|
508
452
|
const [showHelpTerminal, setShowHelpTerminal] = useState(false);
|
|
509
453
|
const [helpTerminalInitialPrompt, setHelpTerminalInitialPrompt] = useState(undefined);
|
|
510
454
|
const [helpTerminalProfileName, setHelpTerminalProfileName] = useState(undefined);
|
|
511
455
|
const [helpTerminalActiveTab, setHelpTerminalActiveTab] = useState(undefined);
|
|
512
|
-
const [
|
|
513
|
-
const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(false);
|
|
514
|
-
const [selectedAgentsWorkspaceAgentId, setSelectedAgentsWorkspaceAgentId] = useState(null);
|
|
456
|
+
const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(true);
|
|
515
457
|
const [activeEditorTab, setActiveEditorTab] = useState(null);
|
|
516
458
|
const [showLayoutComponents, setShowLayoutComponents] = useState(userPreferences.showLayoutComponents ?? false);
|
|
517
459
|
const { quotaInfo, setQuotaInfo, isQuotaExceeded, getQuotaWarningMessage } = useQuota({
|
|
518
460
|
showError: ({ summary, details }) => showErrorToast({ summary, details }),
|
|
519
461
|
});
|
|
520
462
|
const [webSocketMessages, setWebSocketMessages] = useState([]);
|
|
521
|
-
const [socketDiagnostics, setSocketDiagnostics] = useState(() => createEditorSocketDiagnostics(sessionId));
|
|
522
463
|
const [favorites, setFavorites] = useState([]);
|
|
523
464
|
// Quick item switcher state
|
|
524
465
|
const [quickSwitcherVisible, setQuickSwitcherVisible] = useState(false);
|
|
@@ -536,12 +477,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
536
477
|
if (!startupChecks.hasBlockingIssues)
|
|
537
478
|
return;
|
|
538
479
|
// Don't redirect if already in settings workspace - let user navigate freely within settings
|
|
539
|
-
const currentWorkspace = searchParams.get("workspace");
|
|
480
|
+
const currentWorkspace = searchParams.get("workspace") ?? searchParams.get("view");
|
|
540
481
|
if (currentWorkspace === "settings")
|
|
541
482
|
return;
|
|
542
483
|
// Redirect to the status panel (where user can see all issues and navigate to fixes)
|
|
543
484
|
const url = new URL(window.location.href);
|
|
544
485
|
url.searchParams.set("workspace", "settings");
|
|
486
|
+
url.searchParams.delete("view"); // Remove legacy param
|
|
545
487
|
url.searchParams.set("ccpanel", "status");
|
|
546
488
|
router.push(url.toString(), { scroll: false });
|
|
547
489
|
}, [
|
|
@@ -559,16 +501,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
559
501
|
setMode(queryMode);
|
|
560
502
|
}
|
|
561
503
|
}, [searchParams, isInitialLoad]);
|
|
562
|
-
useEffect(() => {
|
|
563
|
-
if (!isInitialLoad)
|
|
564
|
-
return;
|
|
565
|
-
const helpParam = searchParams.get("help");
|
|
566
|
-
if (helpParam) {
|
|
567
|
-
setHelpTerminalActiveTab("manual");
|
|
568
|
-
setShowHelpTerminal(true);
|
|
569
|
-
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true" ? null : helpParam);
|
|
570
|
-
}
|
|
571
|
-
}, [searchParams, isInitialLoad]);
|
|
572
504
|
useEffect(() => {
|
|
573
505
|
if (mode === "suggestions") {
|
|
574
506
|
// Ensure we're in the editor workspace and open the feedback sidebar
|
|
@@ -615,19 +547,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
615
547
|
setSlotContexts((prev) => {
|
|
616
548
|
if (!prev.has(slotId))
|
|
617
549
|
return prev;
|
|
618
|
-
if (slotId === activeSlotIdRef.current) {
|
|
619
|
-
const activeCtx = prev.get(slotId);
|
|
620
|
-
if (activeCtx) {
|
|
621
|
-
lastActiveSlotContextRef.current = activeCtx;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
550
|
const next = new Map(prev);
|
|
625
551
|
next.delete(slotId);
|
|
626
552
|
return next;
|
|
627
553
|
});
|
|
628
554
|
}, []);
|
|
629
555
|
const slotContextsRef = useRef(slotContexts);
|
|
630
|
-
const lastActiveSlotContextRef = useRef(null);
|
|
631
556
|
useEffect(() => {
|
|
632
557
|
slotContextsRef.current = slotContexts;
|
|
633
558
|
}, [slotContexts]);
|
|
@@ -653,12 +578,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
653
578
|
const activeSlotContext = activeSlotId
|
|
654
579
|
? slotContexts.get(activeSlotId)
|
|
655
580
|
: undefined;
|
|
656
|
-
const isComponentNavigatorOpenForSlot = useCallback((slotId) => {
|
|
657
|
-
if (!slotId)
|
|
658
|
-
return showComponentNavigatorDefault;
|
|
659
|
-
return (slotComponentNavigatorVisibility[slotId] ?? showComponentNavigatorDefault);
|
|
660
|
-
}, [slotComponentNavigatorVisibility, showComponentNavigatorDefault]);
|
|
661
|
-
const showComponentNavigator = isComponentNavigatorOpenForSlot(activeSlotId);
|
|
662
581
|
// Sync global compareMode from the active slot's compareMode for URL syncing
|
|
663
582
|
useEffect(() => {
|
|
664
583
|
if (activeSlotContext && activeSlotContext.compareMode !== compareMode) {
|
|
@@ -706,9 +625,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
706
625
|
const isItemUsedInCurrentPage = useCallback((item) => pageItemsSetRef.current.has(makeItemKey(item)), [makeItemKey]);
|
|
707
626
|
const socketMessageListeners = useRef(new Set());
|
|
708
627
|
const [socketConnectionVersion, setSocketConnectionVersion] = useState(0);
|
|
709
|
-
useEffect(() => {
|
|
710
|
-
setSocketDiagnostics(createEditorSocketDiagnostics(sessionId));
|
|
711
|
-
}, [sessionId]);
|
|
712
628
|
const addSocketMessageListener = useCallback((callback) => {
|
|
713
629
|
socketMessageListeners.current.add(callback);
|
|
714
630
|
return () => socketMessageListeners.current.delete(callback);
|
|
@@ -754,11 +670,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
754
670
|
catch { }
|
|
755
671
|
};
|
|
756
672
|
}, [addSocketMessageListener]);
|
|
757
|
-
const shouldLoadReviews = openSidebars.includes("reviews") ||
|
|
758
|
-
workspaceId === "reviews" ||
|
|
759
|
-
workspaceId === "comments";
|
|
760
673
|
const reviews = useReviews({
|
|
761
|
-
enabled: shouldLoadReviews,
|
|
762
674
|
currentItemDescriptor,
|
|
763
675
|
addSocketMessageListener: addSocketMessageListener,
|
|
764
676
|
});
|
|
@@ -797,13 +709,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
797
709
|
console.error(`No workspace found for id: ${workspaceId}`);
|
|
798
710
|
return null;
|
|
799
711
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
return (configuration.commands.keyboardCommands ?? []).filter((command) => activeCommandIds.has(command.id));
|
|
803
|
-
}, [
|
|
804
|
-
currentWorkspace.keyboardCommandIds,
|
|
805
|
-
configuration.commands.keyboardCommands,
|
|
806
|
-
]);
|
|
712
|
+
// Legacy alias for backwards compatibility
|
|
713
|
+
const currentView = currentWorkspace;
|
|
807
714
|
useEffect(() => {
|
|
808
715
|
if (currentWorkspace?.component) {
|
|
809
716
|
setCenterPanelView(currentWorkspace.component);
|
|
@@ -831,45 +738,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
831
738
|
const sendClientInfo = useCallback(() => {
|
|
832
739
|
debouncedSendClientInfo();
|
|
833
740
|
}, [debouncedSendClientInfo]);
|
|
834
|
-
const getCurrentHistoryState = useCallback(() => {
|
|
835
|
-
if (typeof window === "undefined") {
|
|
836
|
-
return null;
|
|
837
|
-
}
|
|
838
|
-
return window.history.state;
|
|
839
|
-
}, []);
|
|
840
|
-
useEffect(() => {
|
|
841
|
-
if (isInitialLoad) {
|
|
842
|
-
return;
|
|
843
|
-
}
|
|
844
|
-
const itemid = searchParams.get("itemid");
|
|
845
|
-
const language = searchParams.get("lang") ?? searchParams.get("language");
|
|
846
|
-
const versionParam = searchParams.get("version");
|
|
847
|
-
const version = versionParam ? parseInt(versionParam, 10) : 0;
|
|
848
|
-
const itemId = cleanId(itemid ?? undefined);
|
|
849
|
-
if (!itemId || !language) {
|
|
850
|
-
return;
|
|
851
|
-
}
|
|
852
|
-
const currentDescriptor = currentItemDescriptorRef.current;
|
|
853
|
-
const matchesCurrentDescriptor = currentDescriptor?.id === itemId &&
|
|
854
|
-
currentDescriptor?.language === language &&
|
|
855
|
-
(!version || currentDescriptor?.version === version);
|
|
856
|
-
if (matchesCurrentDescriptor) {
|
|
857
|
-
return;
|
|
858
|
-
}
|
|
859
|
-
isHandlingPopStateRef.current = true;
|
|
860
|
-
loadItemRef
|
|
861
|
-
.current({
|
|
862
|
-
id: itemId,
|
|
863
|
-
language,
|
|
864
|
-
version,
|
|
865
|
-
}, {
|
|
866
|
-
addToBrowseHistory: false,
|
|
867
|
-
skipViewChange: true,
|
|
868
|
-
})
|
|
869
|
-
.finally(() => {
|
|
870
|
-
isHandlingPopStateRef.current = false;
|
|
871
|
-
});
|
|
872
|
-
}, [isInitialLoad, searchParams]);
|
|
873
741
|
const startTour = useCallback(() => {
|
|
874
742
|
setIsTourActive(true);
|
|
875
743
|
// Persist tour state to URL so it survives navigation/remounts
|
|
@@ -877,61 +745,32 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
877
745
|
const params = new URLSearchParams(window.location.search);
|
|
878
746
|
params.set("tour", "active");
|
|
879
747
|
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
880
|
-
window.history.replaceState(
|
|
748
|
+
window.history.replaceState(null, "", newUrl);
|
|
881
749
|
}, [setIsTourActive]);
|
|
882
|
-
const isMobile = useMediaQuery("(max-width:
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
if (isMobile) {
|
|
887
|
-
setLockedSidebars([]);
|
|
888
|
-
const current = openSidebarsRef.current;
|
|
889
|
-
const lastSidebar = current[current.length - 1];
|
|
890
|
-
if (current.length > 1 && lastSidebar) {
|
|
891
|
-
const trimmed = [lastSidebar];
|
|
892
|
-
openSidebarsRef.current = trimmed;
|
|
893
|
-
setOpenSidebars(trimmed);
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
}, [isMobile]);
|
|
897
|
-
const setComponentNavigatorOpenForSlot = useCallback((slotId, value) => {
|
|
898
|
-
const previousValue = isComponentNavigatorOpenForSlot(slotId);
|
|
899
|
-
const newValue = typeof value === "function" ? value(previousValue) : value;
|
|
900
|
-
if (slotId) {
|
|
901
|
-
setSlotComponentNavigatorVisibility((prev) => {
|
|
902
|
-
const currentValue = prev[slotId] ?? showComponentNavigatorDefault;
|
|
903
|
-
if (currentValue === newValue && prev[slotId] !== undefined) {
|
|
904
|
-
return prev;
|
|
905
|
-
}
|
|
906
|
-
return {
|
|
907
|
-
...prev,
|
|
908
|
-
[slotId]: newValue,
|
|
909
|
-
};
|
|
910
|
-
});
|
|
911
|
-
}
|
|
912
|
-
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);
|
|
913
754
|
setUserPreferences({ showComponentNavigator: newValue });
|
|
755
|
+
// On mobile, close Agents Panel when opening Component Navigator
|
|
914
756
|
if (isMobile && newValue) {
|
|
915
757
|
setShowAgentsPanel(false);
|
|
916
758
|
setUserPreferences({ showAgentsPanel: false });
|
|
917
759
|
}
|
|
918
760
|
}, [
|
|
919
|
-
|
|
920
|
-
|
|
761
|
+
showComponentNavigator,
|
|
762
|
+
setShowComponentNavigator,
|
|
921
763
|
setUserPreferences,
|
|
922
764
|
isMobile,
|
|
923
765
|
setShowAgentsPanel,
|
|
924
766
|
]);
|
|
925
|
-
const handleSetShowComponentNavigator = useCallback((value) => {
|
|
926
|
-
setComponentNavigatorOpenForSlot(activeSlotIdRef.current, value);
|
|
927
|
-
}, [setComponentNavigatorOpenForSlot]);
|
|
928
767
|
const handleSetShowAgentsPanel = useCallback((value) => {
|
|
929
768
|
const newValue = typeof value === "function" ? value(showAgentsPanel) : value;
|
|
930
769
|
setShowAgentsPanel(newValue);
|
|
931
770
|
setUserPreferences({ showAgentsPanel: newValue });
|
|
932
771
|
// On mobile, close Component Navigator when opening Agents Panel
|
|
933
772
|
if (isMobile && newValue) {
|
|
934
|
-
|
|
773
|
+
setShowComponentNavigator(false);
|
|
935
774
|
setUserPreferences({ showComponentNavigator: false });
|
|
936
775
|
}
|
|
937
776
|
}, [
|
|
@@ -939,40 +778,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
939
778
|
setShowAgentsPanel,
|
|
940
779
|
setUserPreferences,
|
|
941
780
|
isMobile,
|
|
942
|
-
|
|
781
|
+
setShowComponentNavigator,
|
|
943
782
|
]);
|
|
944
|
-
// Mobile editor panel state (EditorForm shown in bottom panel on mobile)
|
|
945
|
-
const [mobileEditorPanelOpen, setMobileEditorPanelOpenRaw] = useState(false);
|
|
946
|
-
const [dismissedMobilePanelToken, setDismissedMobilePanelToken] = useState(null);
|
|
947
|
-
const previousActiveSlotIdRef = useRef(null);
|
|
948
|
-
const mobilePanelDismissToken = useMemo(() => {
|
|
949
|
-
const selectionKey = selection.join(",");
|
|
950
|
-
return [
|
|
951
|
-
activeSlotId || "no-slot",
|
|
952
|
-
selectionKey,
|
|
953
|
-
insertMode ? "insert" : "browse",
|
|
954
|
-
].join("|");
|
|
955
|
-
}, [activeSlotId, insertMode, selection]);
|
|
956
|
-
useEffect(() => {
|
|
957
|
-
const previousActiveSlotId = previousActiveSlotIdRef.current;
|
|
958
|
-
if (previousActiveSlotId !== activeSlotId) {
|
|
959
|
-
setDismissedMobilePanelToken(null);
|
|
960
|
-
}
|
|
961
|
-
previousActiveSlotIdRef.current = activeSlotId;
|
|
962
|
-
}, [activeSlotId]);
|
|
963
|
-
const handleSetMobileEditorPanelOpen = useCallback((open) => {
|
|
964
|
-
setMobileEditorPanelOpenRaw(open);
|
|
965
|
-
if (!open) {
|
|
966
|
-
setDismissedMobilePanelToken(mobilePanelDismissToken);
|
|
967
|
-
return;
|
|
968
|
-
}
|
|
969
|
-
setDismissedMobilePanelToken(null);
|
|
970
|
-
if (open && isMobile) {
|
|
971
|
-
// Close all sidebars when opening the editor panel on mobile
|
|
972
|
-
openSidebarsRef.current = [];
|
|
973
|
-
setOpenSidebars([]);
|
|
974
|
-
}
|
|
975
|
-
}, [isMobile, mobilePanelDismissToken]);
|
|
976
783
|
const handleSetShowMinimap = useCallback((value) => {
|
|
977
784
|
const newValue = typeof value === "function" ? value(showMinimap) : value;
|
|
978
785
|
setShowMinimap(newValue);
|
|
@@ -986,7 +793,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
986
793
|
setHelpTerminalInitialPrompt(undefined);
|
|
987
794
|
setHelpTerminalProfileName(undefined);
|
|
988
795
|
setHelpTerminalActiveTab(undefined);
|
|
989
|
-
setSelectedHelpSectionId(null);
|
|
990
796
|
}
|
|
991
797
|
}, [showHelpTerminal]);
|
|
992
798
|
const toggleHelpTerminal = useCallback((options) => {
|
|
@@ -1029,27 +835,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1029
835
|
setOpenSidebars(newOrder);
|
|
1030
836
|
setSidebarStacks((prev) => normalizeSidebarStacks(newOrder, prev));
|
|
1031
837
|
}, []);
|
|
1032
|
-
const ensureSidebarPinned = useCallback((sidebarId) => {
|
|
1033
|
-
const currentPinnedSidebars = pinnedSidebarsRef.current;
|
|
1034
|
-
if (currentPinnedSidebars.includes(sidebarId)) {
|
|
1035
|
-
return;
|
|
1036
|
-
}
|
|
1037
|
-
const newPinnedSidebars = [...currentPinnedSidebars, sidebarId];
|
|
1038
|
-
pinnedSidebarsRef.current = newPinnedSidebars;
|
|
1039
|
-
setPinnedSidebars(newPinnedSidebars);
|
|
1040
|
-
setUserPreferences({ pinnedSidebars: newPinnedSidebars });
|
|
1041
|
-
}, [setUserPreferences]);
|
|
1042
838
|
// messageHandler is defined after loadItem/loadHistory declarations to avoid temporal dead zones
|
|
1043
839
|
const user = activeSessions.find((x) => x.sessionId === sessionId)?.user ||
|
|
1044
840
|
userInfo.user;
|
|
1045
|
-
// Self-heal if our session disappears (e.g., after HMR)
|
|
1046
|
-
// 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)
|
|
1047
842
|
const missingSessionRecoveryTimerRef = useRef(null);
|
|
1048
843
|
const missingSessionRecoveryAttemptsRef = useRef(0);
|
|
1049
|
-
const concurrentUserLimitErrorRef = useRef(null);
|
|
1050
844
|
useEffect(() => {
|
|
1051
|
-
if (concurrentUserLimitErrorRef.current !== null)
|
|
1052
|
-
return;
|
|
1053
845
|
const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
|
|
1054
846
|
if (hasMySession) {
|
|
1055
847
|
// Reset recovery state when we see ourselves again
|
|
@@ -1065,6 +857,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1065
857
|
return;
|
|
1066
858
|
const attempt = missingSessionRecoveryAttemptsRef.current + 1;
|
|
1067
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...`);
|
|
1068
861
|
missingSessionRecoveryTimerRef.current = setTimeout(() => {
|
|
1069
862
|
missingSessionRecoveryTimerRef.current = null;
|
|
1070
863
|
missingSessionRecoveryAttemptsRef.current = attempt;
|
|
@@ -1073,7 +866,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1073
866
|
}
|
|
1074
867
|
else {
|
|
1075
868
|
// Force a reconnect to refresh presence after several failed nudges
|
|
1076
|
-
console.warn("Session presence did not recover after retries. Forcing reconnect.");
|
|
1077
869
|
try {
|
|
1078
870
|
globalThis.editorSocket?.close(4000, "recover-presence");
|
|
1079
871
|
}
|
|
@@ -1093,15 +885,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1093
885
|
// Initialize lastUrlRef to current URL on mount
|
|
1094
886
|
lastUrlRef.current = window.location.href;
|
|
1095
887
|
const keepAliveUrl = "/parhelia/keepalive";
|
|
1096
|
-
const
|
|
888
|
+
const interval = setInterval(() => {
|
|
1097
889
|
fetch(keepAliveUrl + "?ts=" + Date.now())
|
|
1098
890
|
.then((response) => {
|
|
1099
|
-
if (response.headers.get("X-Parhelia-Session-Revoked") === "true") {
|
|
1100
|
-
window.dispatchEvent(new CustomEvent("parhelia:session-revoked", {
|
|
1101
|
-
detail: { reason: "session-revoked" },
|
|
1102
|
-
}));
|
|
1103
|
-
return;
|
|
1104
|
-
}
|
|
1105
891
|
if (response.status === 401 || response.status === 403) {
|
|
1106
892
|
toast.error("Your session has expired", {
|
|
1107
893
|
description: "Please login again to continue editing.",
|
|
@@ -1114,24 +900,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1114
900
|
}
|
|
1115
901
|
})
|
|
1116
902
|
.catch((error) => console.error("Keep Alive error:", error));
|
|
1117
|
-
};
|
|
1118
|
-
const keepaliveIntervalMs = (() => {
|
|
1119
|
-
const param = new URLSearchParams(window.location.search).get("keepaliveIntervalMs");
|
|
1120
|
-
if (!param)
|
|
1121
|
-
return 5 * 60 * 1000;
|
|
1122
|
-
const ms = parseInt(param, 10);
|
|
1123
|
-
return Number.isFinite(ms) && ms >= 2000 && ms <= 60000
|
|
1124
|
-
? ms
|
|
1125
|
-
: 5 * 60 * 1000;
|
|
1126
|
-
})();
|
|
1127
|
-
const interval = setInterval(() => {
|
|
1128
|
-
runSessionCheck();
|
|
1129
|
-
}, keepaliveIntervalMs);
|
|
1130
|
-
const handleVisibilityChange = () => {
|
|
1131
|
-
if (document.visibilityState === "visible") {
|
|
1132
|
-
runSessionCheck();
|
|
1133
|
-
}
|
|
1134
|
-
};
|
|
903
|
+
}, 5 * 60 * 1000);
|
|
1135
904
|
const handleMessage = (event) => {
|
|
1136
905
|
if (event.data.type === "componentsSelected") {
|
|
1137
906
|
setSelection(event.data.componentIds);
|
|
@@ -1139,44 +908,35 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1139
908
|
};
|
|
1140
909
|
// Listen for browser navigation events (back/forward buttons)
|
|
1141
910
|
const handlePopState = (event) => {
|
|
1142
|
-
const newUrl =
|
|
911
|
+
const newUrl = window.location.href;
|
|
1143
912
|
if (newUrl !== lastUrlRef.current) {
|
|
1144
913
|
lastUrlRef.current = newUrl;
|
|
1145
914
|
// Mark that we're handling a popstate to prevent URL sync from pushing to history
|
|
1146
915
|
isHandlingPopStateRef.current = true;
|
|
1147
916
|
// Sync URL parameters back to component state for browser navigation
|
|
1148
917
|
const urlParams = new URLSearchParams(window.location.search);
|
|
1149
|
-
|
|
1150
|
-
|
|
918
|
+
// Handle workspace changes (with legacy view fallback)
|
|
919
|
+
const urlWorkspace = urlParams.get("workspace") ?? urlParams.get("view");
|
|
920
|
+
if (urlWorkspace && urlWorkspace !== viewNameRef.current) {
|
|
1151
921
|
setWorkspaceId(urlWorkspace);
|
|
1152
922
|
}
|
|
1153
|
-
// Handle sidebar changes
|
|
923
|
+
// Handle sidebar changes
|
|
1154
924
|
const sidebarParam = urlParams.get("sidebar");
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
925
|
+
if (sidebarParam !== null) {
|
|
926
|
+
const newSidebars = sidebarParam.split(",").filter(Boolean);
|
|
927
|
+
setOpenSidebars(newSidebars);
|
|
928
|
+
}
|
|
1159
929
|
// Handle wizard ID changes
|
|
1160
930
|
const wizardId = urlParams.get("wizardid");
|
|
1161
931
|
setCurrentWizardId(wizardId);
|
|
1162
|
-
// Handle compare mode changes
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
const helpParam = urlParams.get("help");
|
|
1167
|
-
if (helpParam) {
|
|
1168
|
-
setHelpTerminalActiveTab("manual");
|
|
1169
|
-
setShowHelpTerminal(true);
|
|
1170
|
-
setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true"
|
|
1171
|
-
? null
|
|
1172
|
-
: helpParam);
|
|
1173
|
-
}
|
|
1174
|
-
else {
|
|
1175
|
-
handleSetShowHelpTerminal(false);
|
|
932
|
+
// Handle compare mode changes
|
|
933
|
+
const compareValue = urlParams.get("compare") === "true";
|
|
934
|
+
if (compareValue !== compareMode) {
|
|
935
|
+
setCompareMode(compareValue);
|
|
1176
936
|
}
|
|
1177
|
-
// Handle mode changes
|
|
937
|
+
// Handle mode changes
|
|
1178
938
|
const urlMode = urlParams.get("mode");
|
|
1179
|
-
if (urlMode) {
|
|
939
|
+
if (urlMode && urlMode !== mode) {
|
|
1180
940
|
setMode(urlMode);
|
|
1181
941
|
}
|
|
1182
942
|
// Handle fullscreen changes (shell-level state)
|
|
@@ -1229,11 +989,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1229
989
|
};
|
|
1230
990
|
window.addEventListener("message", handleMessage);
|
|
1231
991
|
window.addEventListener("popstate", handlePopState);
|
|
1232
|
-
window.addEventListener("visibilitychange", handleVisibilityChange);
|
|
1233
992
|
return () => {
|
|
1234
993
|
window.removeEventListener("message", handleMessage);
|
|
1235
994
|
window.removeEventListener("popstate", handlePopState);
|
|
1236
|
-
window.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1237
995
|
clearInterval(interval);
|
|
1238
996
|
};
|
|
1239
997
|
}, []);
|
|
@@ -1243,34 +1001,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1243
1001
|
if (searchParams.get("noTour") !== null) {
|
|
1244
1002
|
return;
|
|
1245
1003
|
}
|
|
1246
|
-
// Don't start tour when there are setup errors (user is or will be on system status page)
|
|
1247
|
-
if (startupChecks.state === "complete" && startupChecks.hasBlockingIssues) {
|
|
1248
|
-
return;
|
|
1249
|
-
}
|
|
1250
|
-
// Don't start tour when already on settings system status page
|
|
1251
|
-
if (viewName === "settings" && searchParams.get("ccpanel") === "status") {
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
// Wait for startup checks so we know whether we'll redirect to status
|
|
1255
|
-
if (startupChecks.state !== "complete") {
|
|
1256
|
-
return;
|
|
1257
|
-
}
|
|
1258
1004
|
const tour = configuration.activeTour;
|
|
1259
1005
|
const key = tour === "default" ? "editor.tourShown" : "editor.tourShown." + tour;
|
|
1260
|
-
const tourShown =
|
|
1006
|
+
const tourShown = localStorage.getItem(key);
|
|
1261
1007
|
if (!tourShown) {
|
|
1262
1008
|
startTour();
|
|
1263
|
-
|
|
1009
|
+
localStorage.setItem(key, "true");
|
|
1264
1010
|
}
|
|
1265
|
-
}, [
|
|
1266
|
-
user,
|
|
1267
|
-
startupChecks.state,
|
|
1268
|
-
startupChecks.hasBlockingIssues,
|
|
1269
|
-
viewName,
|
|
1270
|
-
searchParams,
|
|
1271
|
-
configuration.activeTour,
|
|
1272
|
-
startTour,
|
|
1273
|
-
]);
|
|
1011
|
+
}, [user]);
|
|
1274
1012
|
// WebSocket initialization is performed after messageHandler is defined
|
|
1275
1013
|
// Defer URL sync until loadItem is defined below
|
|
1276
1014
|
// Mark end of initial load phase
|
|
@@ -1402,8 +1140,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1402
1140
|
const loadComments = useCallback(async () => {
|
|
1403
1141
|
if (!currentItemDescriptor)
|
|
1404
1142
|
return;
|
|
1405
|
-
const
|
|
1406
|
-
const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version, reviewId ?? undefined);
|
|
1143
|
+
const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version);
|
|
1407
1144
|
if (handleErrorResult(result, ui, state))
|
|
1408
1145
|
return;
|
|
1409
1146
|
setComments((x) => {
|
|
@@ -1416,7 +1153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1416
1153
|
allComments.sort((a, b) => a.position - b.position);
|
|
1417
1154
|
return allComments;
|
|
1418
1155
|
});
|
|
1419
|
-
}, [currentItemDescriptor
|
|
1156
|
+
}, [currentItemDescriptor]);
|
|
1420
1157
|
// Assuming currentItemDescriptor, ui, state, handleErrorResult, and setSuggestedEdits
|
|
1421
1158
|
// are available in your component context.
|
|
1422
1159
|
const loadSuggestedEdits = useCallback(async () => {
|
|
@@ -1425,8 +1162,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1425
1162
|
const result = await getSuggestedEdits(item.descriptor.id, item.descriptor.language, item.descriptor.version);
|
|
1426
1163
|
if (handleErrorResult(result, ui, state))
|
|
1427
1164
|
return;
|
|
1428
|
-
|
|
1429
|
-
setSuggestedEdits(edits);
|
|
1165
|
+
setSuggestedEdits(result.data || []);
|
|
1430
1166
|
}, [item]);
|
|
1431
1167
|
const loadFavorites = useCallback(async () => {
|
|
1432
1168
|
try {
|
|
@@ -1500,25 +1236,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1500
1236
|
return idB.localeCompare(idA);
|
|
1501
1237
|
});
|
|
1502
1238
|
}, []);
|
|
1503
|
-
const normalizeEditHistoryPayload = useCallback((value) => {
|
|
1504
|
-
if (Array.isArray(value)) {
|
|
1505
|
-
return value;
|
|
1506
|
-
}
|
|
1507
|
-
if (value && typeof value === "object") {
|
|
1508
|
-
const payload = value;
|
|
1509
|
-
const candidates = [
|
|
1510
|
-
payload.operations,
|
|
1511
|
-
payload.history,
|
|
1512
|
-
payload.items,
|
|
1513
|
-
payload.data,
|
|
1514
|
-
];
|
|
1515
|
-
const firstArray = candidates.find((candidate) => Array.isArray(candidate));
|
|
1516
|
-
if (Array.isArray(firstArray)) {
|
|
1517
|
-
return firstArray;
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
return [];
|
|
1521
|
-
}, []);
|
|
1522
1239
|
useEffect(() => {
|
|
1523
1240
|
// Read fresh page from the mutable slot context ref chain.
|
|
1524
1241
|
// The slot context uses a stable ref that is mutated in-place (see editorSlotContext.ts),
|
|
@@ -1541,7 +1258,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1541
1258
|
if (handleErrorResult(result, ui, state))
|
|
1542
1259
|
return;
|
|
1543
1260
|
setEditHistory((prev) => {
|
|
1544
|
-
const next =
|
|
1261
|
+
const next = result.data || [];
|
|
1545
1262
|
if (!prev.length)
|
|
1546
1263
|
return sortEditHistoryByDateDesc(next);
|
|
1547
1264
|
if (!next.length)
|
|
@@ -1600,8 +1317,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1600
1317
|
const shouldFilterByLanguage = filterByLanguage !== undefined
|
|
1601
1318
|
? filterByLanguage
|
|
1602
1319
|
: filterByCurrentLanguage;
|
|
1603
|
-
const trimmedHistoryQuery = historySearchQuery.trim();
|
|
1604
|
-
const historyQuery = trimmedHistoryQuery.length > 0 ? trimmedHistoryQuery : undefined;
|
|
1605
1320
|
if (currentMode === "global") {
|
|
1606
1321
|
// Global mode: optionally filter by session and/or language
|
|
1607
1322
|
const currentLanguage = item?.descriptor?.language || currentItemDescriptor?.language;
|
|
@@ -1611,14 +1326,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1611
1326
|
language: shouldFilterByLanguage && currentLanguage
|
|
1612
1327
|
? currentLanguage
|
|
1613
1328
|
: undefined,
|
|
1614
|
-
query: historyQuery,
|
|
1615
1329
|
});
|
|
1616
1330
|
if (handleErrorResult(result, ui, state)) {
|
|
1617
1331
|
console.error("[EditorShell] Failed to load history:", result);
|
|
1618
1332
|
return;
|
|
1619
1333
|
}
|
|
1620
1334
|
setEditHistory((prev) => {
|
|
1621
|
-
const next =
|
|
1335
|
+
const next = result.data || [];
|
|
1622
1336
|
const scope = {
|
|
1623
1337
|
mode: currentMode,
|
|
1624
1338
|
filterBySession: shouldFilterBySession,
|
|
@@ -1629,12 +1343,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1629
1343
|
};
|
|
1630
1344
|
if (!prev.length)
|
|
1631
1345
|
return sortEditHistoryByDateDesc(next.filter((op) => matchesHistoryScope(op, scope)));
|
|
1632
|
-
if (!next.length)
|
|
1633
|
-
// When searching, respect the empty result — don't fall back to previous items
|
|
1634
|
-
if (historyQuery)
|
|
1635
|
-
return [];
|
|
1346
|
+
if (!next.length)
|
|
1636
1347
|
return sortEditHistoryByDateDesc(prev.filter((op) => matchesHistoryScope(op, scope)));
|
|
1637
|
-
}
|
|
1638
1348
|
const prevById = new Map(prev.map((x) => [x.id, x]));
|
|
1639
1349
|
const nextById = new Set(next.map((x) => x.id));
|
|
1640
1350
|
const merged = next
|
|
@@ -1670,12 +1380,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1670
1380
|
return mergedOp;
|
|
1671
1381
|
});
|
|
1672
1382
|
// Preserve operations that arrived via WebSocket during the fetch window
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1677
|
-
merged.push(priorOp);
|
|
1678
|
-
}
|
|
1383
|
+
for (const [id, priorOp] of prevById) {
|
|
1384
|
+
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1385
|
+
merged.push(priorOp);
|
|
1679
1386
|
}
|
|
1680
1387
|
}
|
|
1681
1388
|
return sortEditHistoryByDateDesc(merged);
|
|
@@ -1698,13 +1405,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1698
1405
|
const result = await getEditHistory({
|
|
1699
1406
|
item: itemFilter,
|
|
1700
1407
|
sessionId: shouldFilterBySession ? sessionId : undefined,
|
|
1701
|
-
query: historyQuery,
|
|
1702
1408
|
});
|
|
1703
1409
|
if (handleErrorResult(result, ui, state)) {
|
|
1704
1410
|
console.error("[EditorShell] Failed to load item history:", result);
|
|
1705
1411
|
return;
|
|
1706
1412
|
}
|
|
1707
|
-
let operations =
|
|
1413
|
+
let operations = result.data || [];
|
|
1708
1414
|
// Client-side version filtering for current-version mode
|
|
1709
1415
|
if (currentMode === "current-version") {
|
|
1710
1416
|
// Defensive filter: only include operations for the current version
|
|
@@ -1727,11 +1433,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1727
1433
|
};
|
|
1728
1434
|
if (!prev.length)
|
|
1729
1435
|
return sortEditHistoryByDateDesc(operations.filter((op) => matchesHistoryScope(op, scope)));
|
|
1730
|
-
if (!operations.length)
|
|
1731
|
-
if (historyQuery)
|
|
1732
|
-
return [];
|
|
1436
|
+
if (!operations.length)
|
|
1733
1437
|
return sortEditHistoryByDateDesc(prev.filter((op) => matchesHistoryScope(op, scope)));
|
|
1734
|
-
}
|
|
1735
1438
|
const prevById = new Map(prev.map((x) => [x.id, x]));
|
|
1736
1439
|
const nextById = new Set(operations.map((x) => x.id));
|
|
1737
1440
|
const merged = operations
|
|
@@ -1767,12 +1470,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1767
1470
|
return mergedOp;
|
|
1768
1471
|
});
|
|
1769
1472
|
// Preserve operations that arrived via WebSocket during the fetch window
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1774
|
-
merged.push(priorOp);
|
|
1775
|
-
}
|
|
1473
|
+
for (const [id, priorOp] of prevById) {
|
|
1474
|
+
if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
|
|
1475
|
+
merged.push(priorOp);
|
|
1776
1476
|
}
|
|
1777
1477
|
}
|
|
1778
1478
|
return sortEditHistoryByDateDesc(merged);
|
|
@@ -1783,11 +1483,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1783
1483
|
historyMode,
|
|
1784
1484
|
showOnlyMyChanges,
|
|
1785
1485
|
filterByCurrentLanguage,
|
|
1786
|
-
historySearchQuery,
|
|
1787
1486
|
item,
|
|
1788
1487
|
currentItemDescriptor,
|
|
1789
1488
|
matchesHistoryScope,
|
|
1790
|
-
normalizeEditHistoryPayload,
|
|
1791
1489
|
sortEditHistoryByDateDesc,
|
|
1792
1490
|
]);
|
|
1793
1491
|
// Debounced history refresh to avoid hammering `/parhelia/editHistory` on rapid UI changes.
|
|
@@ -1853,14 +1551,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1853
1551
|
}
|
|
1854
1552
|
}
|
|
1855
1553
|
else if (historyMode !== "global" && currentItemDescriptor) {
|
|
1856
|
-
// Always load immediately for page-centric/current-version/timeline so we don't show
|
|
1857
|
-
// an empty history list for the debounce window (e.g. 600ms). The effect only runs on
|
|
1858
|
-
// mode or item id/lang/version change, not on every keystroke, so this avoids flaky
|
|
1859
|
-
// undo/redo tests and improves UX when switching to page-centric.
|
|
1860
1554
|
if (!historyInitialLoadDoneRef.current) {
|
|
1861
1555
|
historyInitialLoadDoneRef.current = true;
|
|
1556
|
+
refreshHistoryRef.current(historyMode);
|
|
1557
|
+
}
|
|
1558
|
+
else {
|
|
1559
|
+
debouncedRefreshHistoryRef.current(historyMode);
|
|
1862
1560
|
}
|
|
1863
|
-
refreshHistoryRef.current(historyMode);
|
|
1864
1561
|
}
|
|
1865
1562
|
else if (historyMode !== "global" && !currentItemDescriptor) {
|
|
1866
1563
|
// Clear history if no item loaded in page-centric modes
|
|
@@ -1873,7 +1570,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1873
1570
|
historyMode,
|
|
1874
1571
|
showOnlyMyChanges,
|
|
1875
1572
|
filterByCurrentLanguage,
|
|
1876
|
-
historySearchQuery,
|
|
1877
1573
|
currentItemDescriptor?.id,
|
|
1878
1574
|
currentItemDescriptor?.language,
|
|
1879
1575
|
currentItemDescriptor?.version,
|
|
@@ -1938,9 +1634,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1938
1634
|
if (isInitialLoad)
|
|
1939
1635
|
return;
|
|
1940
1636
|
const current = new URLSearchParams(window.location.search);
|
|
1941
|
-
const urlWorkspace = current.get("workspace");
|
|
1942
|
-
const urlView = current.get("view");
|
|
1943
|
-
const isWorkspaceTransitioning = !!urlWorkspace && urlWorkspace !== viewName;
|
|
1944
1637
|
// Sync item-related parameters only when an item is selected
|
|
1945
1638
|
if (currentItemDescriptor) {
|
|
1946
1639
|
if (current.get("itemid") !== currentItemDescriptor.id) {
|
|
@@ -1971,9 +1664,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1971
1664
|
// If reviewId or urlItemId exists, preserve itemid/lang/version from URL
|
|
1972
1665
|
}
|
|
1973
1666
|
// Always sync workspace-related parameters regardless of item selection
|
|
1974
|
-
if (
|
|
1667
|
+
if (current.get("workspace") !== viewName) {
|
|
1975
1668
|
current.set("workspace", viewName);
|
|
1976
1669
|
}
|
|
1670
|
+
current.delete("view"); // Remove legacy view param
|
|
1977
1671
|
// Sync sidebar state
|
|
1978
1672
|
const currentSidebars = current.get("sidebar") ?? "";
|
|
1979
1673
|
const newSidebars = openSidebars.join(",");
|
|
@@ -1985,12 +1679,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
1985
1679
|
current.delete("sidebar");
|
|
1986
1680
|
}
|
|
1987
1681
|
}
|
|
1988
|
-
if (showHelpTerminal) {
|
|
1989
|
-
current.set("help", selectedHelpSectionId ?? "contents");
|
|
1990
|
-
}
|
|
1991
|
-
else {
|
|
1992
|
-
current.delete("help");
|
|
1993
|
-
}
|
|
1994
1682
|
if (!compareMode) {
|
|
1995
1683
|
current.delete("compare");
|
|
1996
1684
|
current.delete("compareLanguage");
|
|
@@ -2015,15 +1703,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2015
1703
|
else {
|
|
2016
1704
|
current.delete("wizardid");
|
|
2017
1705
|
}
|
|
2018
|
-
//
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
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 {
|
|
2024
1714
|
current.delete("ccpanel");
|
|
2025
|
-
current.delete("providerId");
|
|
2026
|
-
current.delete("modelId");
|
|
2027
1715
|
}
|
|
2028
1716
|
// Preserve reviewId parameter if it exists (for review links)
|
|
2029
1717
|
// This ensures review links don't lose the reviewId when URL is synced
|
|
@@ -2036,42 +1724,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2036
1724
|
const browserPathname = typeof window !== "undefined" ? window.location.pathname : pathname;
|
|
2037
1725
|
const newUrl = `${browserPathname}?${current.toString()}`;
|
|
2038
1726
|
const oldUrl = `${browserPathname}${window.location.search}`;
|
|
2039
|
-
const isRestoringLastSyncedUrl = newUrl === lastUrlRef.current;
|
|
2040
1727
|
// Skip pushing to history if we're handling a popstate event (browser back/forward)
|
|
2041
1728
|
// This prevents the URL sync from overwriting the history during back navigation
|
|
2042
1729
|
if (isHandlingPopStateRef.current) {
|
|
2043
1730
|
return;
|
|
2044
1731
|
}
|
|
2045
1732
|
if (newUrl !== oldUrl) {
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
window.history.replaceState(getCurrentHistoryState(), "", newUrl);
|
|
2050
|
-
isFirstUrlSyncRef.current = false;
|
|
2051
|
-
switchWorkspacePushedRef.current = false;
|
|
2052
|
-
}
|
|
2053
|
-
else {
|
|
2054
|
-
window.history.pushState(getCurrentHistoryState(), "", newUrl);
|
|
2055
|
-
}
|
|
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
|
|
2056
1736
|
lastUrlRef.current = newUrl;
|
|
2057
1737
|
}
|
|
2058
|
-
else {
|
|
2059
|
-
// Even when the first sync is a no-op (URL already matches state), consume
|
|
2060
|
-
// the first-sync flag. Otherwise the *next* real change (e.g. user selecting
|
|
2061
|
-
// a different item) would hit the replaceState branch and overwrite the
|
|
2062
|
-
// landing history entry — eating the "back" target and making browser back
|
|
2063
|
-
// skip past the initial page.
|
|
2064
|
-
if (isFirstUrlSyncRef.current) {
|
|
2065
|
-
isFirstUrlSyncRef.current = false;
|
|
2066
|
-
lastUrlRef.current = newUrl;
|
|
2067
|
-
}
|
|
2068
|
-
if (switchWorkspacePushedRef.current) {
|
|
2069
|
-
// A workspace change may already have pushed the exact target URL. If we leave
|
|
2070
|
-
// this flag set, the next unrelated item navigation will incorrectly replace
|
|
2071
|
-
// history instead of pushing a new entry, which breaks browser back/forward.
|
|
2072
|
-
switchWorkspacePushedRef.current = false;
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
1738
|
}, [
|
|
2076
1739
|
currentItemDescriptor,
|
|
2077
1740
|
viewName,
|
|
@@ -2083,8 +1746,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2083
1746
|
fullscreen,
|
|
2084
1747
|
currentWizardId,
|
|
2085
1748
|
openSidebars,
|
|
2086
|
-
showHelpTerminal,
|
|
2087
|
-
selectedHelpSectionId,
|
|
2088
1749
|
]);
|
|
2089
1750
|
useEffect(() => {
|
|
2090
1751
|
async function load() {
|
|
@@ -2181,9 +1842,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2181
1842
|
"en",
|
|
2182
1843
|
version: 0,
|
|
2183
1844
|
};
|
|
1845
|
+
const loadedItem = await itemsRepository.getItem(itemToLoad);
|
|
1846
|
+
if (!loadedItem) {
|
|
1847
|
+
return undefined;
|
|
1848
|
+
}
|
|
2184
1849
|
// ensure this is object has no additional properties
|
|
2185
1850
|
itemToLoad = getItemDescriptor(itemToLoad);
|
|
2186
|
-
const requestedItemKey = makeItemKey(itemToLoad);
|
|
2187
1851
|
// Check if item is already open in any slot - if so, reuse that slot instead of creating a new one
|
|
2188
1852
|
const existingSlotForItem = editorSlots.find((s) => s.itemDescriptor.id === itemToLoad.id &&
|
|
2189
1853
|
s.itemDescriptor.language === itemToLoad.language &&
|
|
@@ -2194,17 +1858,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2194
1858
|
!options?.openInNewSlot &&
|
|
2195
1859
|
!options?.targetSlotId) {
|
|
2196
1860
|
const isExistingSlotActive = existingSlotForItem.slotId === activeSlotIdRef.current;
|
|
2197
|
-
if (isExistingSlotActive) {
|
|
2198
|
-
latestGlobalLoadKeyRef.current = requestedItemKey;
|
|
2199
|
-
}
|
|
2200
|
-
const loadedItem = await itemsRepository.getItem(itemToLoad);
|
|
2201
|
-
if (!loadedItem) {
|
|
2202
|
-
return undefined;
|
|
2203
|
-
}
|
|
2204
|
-
if (isExistingSlotActive &&
|
|
2205
|
-
latestGlobalLoadKeyRef.current !== requestedItemKey) {
|
|
2206
|
-
return loadedItem;
|
|
2207
|
-
}
|
|
2208
1861
|
// If forceRefresh is true, update the slot with a new refreshToken to trigger a reload
|
|
2209
1862
|
if (options?.forceRefresh) {
|
|
2210
1863
|
setEditorSlots((prev) => {
|
|
@@ -2275,30 +1928,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2275
1928
|
return next;
|
|
2276
1929
|
});
|
|
2277
1930
|
// Decide whether this load should update the global "current item" state.
|
|
2278
|
-
// - If we're loading into an inactive slot
|
|
2279
|
-
// - If the slot is active
|
|
2280
|
-
// slot the caller explicitly opened, do update.
|
|
1931
|
+
// - If we're loading into an inactive slot (e.g. openInNewSlot), do NOT update URL/tree/controls.
|
|
1932
|
+
// - If the slot is active (or is becoming active as the first slot), do update.
|
|
2281
1933
|
const isFirstSlot = editorSlots.length === 0;
|
|
2282
|
-
const
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
targetSlotId === activeSlotIdRef.current;
|
|
2286
|
-
if (shouldUpdateGlobalCurrentItem) {
|
|
2287
|
-
latestGlobalLoadKeyRef.current = requestedItemKey;
|
|
2288
|
-
}
|
|
2289
|
-
const loadedItem = await itemsRepository.getItem(itemToLoad);
|
|
2290
|
-
if (!loadedItem) {
|
|
2291
|
-
return undefined;
|
|
2292
|
-
}
|
|
2293
|
-
if (shouldUpdateGlobalCurrentItem &&
|
|
2294
|
-
latestGlobalLoadKeyRef.current !== requestedItemKey) {
|
|
2295
|
-
return loadedItem;
|
|
2296
|
-
}
|
|
2297
|
-
// Activate the new slot when this is either the initial first slot, or the
|
|
2298
|
-
// caller explicitly opened the item in a new slot — focus follows the action so
|
|
2299
|
-
// the user immediately sees what they just opened. Beyond that, slot focus is
|
|
2300
|
-
// driven by mouse hover/click.
|
|
2301
|
-
if (isFirstSlot || isExplicitNewSlot) {
|
|
1934
|
+
const shouldUpdateGlobalCurrentItem = isFirstSlot || targetSlotId === activeSlotIdRef.current;
|
|
1935
|
+
// Active slot is controlled ONLY by mouse hover - only activate the first slot on initial load
|
|
1936
|
+
if (isFirstSlot) {
|
|
2302
1937
|
activeSlotIdRef.current = targetSlotId;
|
|
2303
1938
|
setActiveSlotId(targetSlotId);
|
|
2304
1939
|
}
|
|
@@ -2404,10 +2039,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2404
2039
|
useEffect(() => {
|
|
2405
2040
|
if (fullscreen &&
|
|
2406
2041
|
!searchParams.get("fullscreen") &&
|
|
2407
|
-
!configuration.forceFullscreen
|
|
2408
|
-
!isMobile)
|
|
2042
|
+
!configuration.forceFullscreen)
|
|
2409
2043
|
setShowFullscreenHint(true);
|
|
2410
|
-
}, [fullscreen, configuration.forceFullscreen, searchParams
|
|
2044
|
+
}, [fullscreen, configuration.forceFullscreen, searchParams]);
|
|
2411
2045
|
const state = {
|
|
2412
2046
|
page,
|
|
2413
2047
|
configuration,
|
|
@@ -2506,35 +2140,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2506
2140
|
? existingOp.progress
|
|
2507
2141
|
: op.progress;
|
|
2508
2142
|
// IMPORTANT: Once canUndo becomes true, never downgrade it to false,
|
|
2509
|
-
// UNLESS this update indicates the operation was undone.
|
|
2510
|
-
//
|
|
2511
|
-
//
|
|
2512
|
-
|
|
2513
|
-
// without explicit undone/canRedo flags yet.
|
|
2514
|
-
const isExplicitUndoUpdate = op.undone === true || op.canRedo === true;
|
|
2515
|
-
const isInferredUndoCompletion = existingOp.executionStatus === "executing" &&
|
|
2516
|
-
op.executionStatus === "completed" &&
|
|
2517
|
-
existingOp.canUndo === true &&
|
|
2518
|
-
op.canUndo === false;
|
|
2519
|
-
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;
|
|
2520
2147
|
const mergedCanUndo = isUndoUpdate
|
|
2521
2148
|
? false
|
|
2522
2149
|
: existingOp.canUndo === true
|
|
2523
2150
|
? true
|
|
2524
2151
|
: op.canUndo;
|
|
2525
|
-
const mergedCanRedo = isUndoUpdate
|
|
2526
|
-
? true
|
|
2527
|
-
: op.canRedo ?? existingOp.canRedo;
|
|
2528
|
-
const mergedUndone = isUndoUpdate
|
|
2529
|
-
? true
|
|
2530
|
-
: op.undone ?? existingOp.undone;
|
|
2531
2152
|
const mergedOp = {
|
|
2532
2153
|
...existingOp,
|
|
2533
2154
|
...op,
|
|
2534
2155
|
progress: mergedProgress,
|
|
2535
2156
|
canUndo: mergedCanUndo,
|
|
2536
|
-
canRedo: mergedCanRedo,
|
|
2537
|
-
undone: mergedUndone,
|
|
2538
2157
|
};
|
|
2539
2158
|
// Ensure undone operations always have canRedo: true.
|
|
2540
2159
|
if (mergedOp.undone && !mergedOp.canRedo) {
|
|
@@ -2588,6 +2207,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2588
2207
|
});
|
|
2589
2208
|
// Ref for markOperationComplete callback (needed because operationsContext is created later)
|
|
2590
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([]);
|
|
2591
2214
|
// WebSocket message handler and connection
|
|
2592
2215
|
const messageHandler = useSocketMessageHandler({
|
|
2593
2216
|
sessionId,
|
|
@@ -2613,31 +2236,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2613
2236
|
markOperationCompleteRef.current?.(operationId);
|
|
2614
2237
|
},
|
|
2615
2238
|
});
|
|
2616
|
-
// Concurrent user limit error state
|
|
2617
|
-
const [concurrentUserLimitError, setConcurrentUserLimitError] = useState(null);
|
|
2618
|
-
concurrentUserLimitErrorRef.current = concurrentUserLimitError;
|
|
2619
|
-
const handleRetryConnection = useCallback(() => {
|
|
2620
|
-
setConcurrentUserLimitError(null);
|
|
2621
|
-
// Force reconnection by triggering a new connection attempt
|
|
2622
|
-
// The useEditorWebSocket hook will check availability again
|
|
2623
|
-
const socket = globalThis.editorSocket;
|
|
2624
|
-
if (socket) {
|
|
2625
|
-
socket.close();
|
|
2626
|
-
delete globalThis.editorSocket;
|
|
2627
|
-
}
|
|
2628
|
-
// The hook will automatically attempt to reconnect
|
|
2629
|
-
}, []);
|
|
2630
2239
|
const { socketRef: socketInstanceRef } = useEditorWebSocket({
|
|
2631
2240
|
sessionId,
|
|
2632
2241
|
onMessage: messageHandler,
|
|
2633
2242
|
onOpen: async () => {
|
|
2634
|
-
// Clear concurrent user limit error on successful connection
|
|
2635
|
-
setConcurrentUserLimitError(null);
|
|
2636
|
-
// Startup WebSocket probe may have failed with a blocking error while seats were full;
|
|
2637
|
-
// re-run status checks quietly so "1 error" does not stick after a successful connect.
|
|
2638
|
-
void startupChecks.recheckQuiet();
|
|
2639
2243
|
// Increment socket connection version to trigger re-subscriptions
|
|
2640
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
|
+
}
|
|
2641
2261
|
// Fetch any running operations on (re)connect for auto-resume
|
|
2642
2262
|
// This ensures the UI shows operations that are still executing
|
|
2643
2263
|
try {
|
|
@@ -2653,37 +2273,24 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2653
2273
|
}
|
|
2654
2274
|
},
|
|
2655
2275
|
onError: (error) => console.error("WebSocket error:", error),
|
|
2656
|
-
onConcurrentUserLimit: (error) => {
|
|
2657
|
-
setConcurrentUserLimitError(error);
|
|
2658
|
-
},
|
|
2659
|
-
onSessionRevoked: () => promptSessionReconnect("session-revoked"),
|
|
2660
2276
|
connectSocket,
|
|
2661
2277
|
requestQuota,
|
|
2662
2278
|
sendClientInfo,
|
|
2663
|
-
setSocketDiagnostics,
|
|
2664
2279
|
});
|
|
2665
|
-
useEffect(() => {
|
|
2666
|
-
const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
|
|
2667
|
-
if (hasMySession &&
|
|
2668
|
-
socketInstanceRef.current?.readyState === WebSocket.OPEN) {
|
|
2669
|
-
toast.dismiss("session-revoked");
|
|
2670
|
-
}
|
|
2671
|
-
}, [activeSessions, sessionId, socketConnectionVersion, socketInstanceRef]);
|
|
2672
|
-
useEffect(() => {
|
|
2673
|
-
const handleRevoked = (event) => {
|
|
2674
|
-
const customEvent = event;
|
|
2675
|
-
promptSessionReconnect(customEvent?.detail?.reason);
|
|
2676
|
-
};
|
|
2677
|
-
window.addEventListener("parhelia:session-revoked", handleRevoked);
|
|
2678
|
-
return () => {
|
|
2679
|
-
window.removeEventListener("parhelia:session-revoked", handleRevoked);
|
|
2680
|
-
};
|
|
2681
|
-
}, [promptSessionReconnect]);
|
|
2682
2280
|
const sendSocketMessage = useCallback((message) => {
|
|
2683
2281
|
if (socketInstanceRef.current &&
|
|
2684
2282
|
socketInstanceRef.current.readyState === WebSocket.OPEN) {
|
|
2685
2283
|
socketInstanceRef.current.send(JSON.stringify(message));
|
|
2686
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
|
+
}
|
|
2687
2294
|
}, [socketInstanceRef]);
|
|
2688
2295
|
// URL update helper - defined early so it can be used by workspace/sidebar functions
|
|
2689
2296
|
const updateUrl = useCallback((params) => {
|
|
@@ -2702,8 +2309,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2702
2309
|
? `${browserPathname}?${queryString}`
|
|
2703
2310
|
: browserPathname;
|
|
2704
2311
|
if (typeof window !== "undefined") {
|
|
2705
|
-
window.history.pushState(
|
|
2706
|
-
lastUrlRef.current = newUrl;
|
|
2312
|
+
window.history.pushState(null, "", newUrl);
|
|
2707
2313
|
}
|
|
2708
2314
|
else {
|
|
2709
2315
|
router.push(newUrl, { scroll: false });
|
|
@@ -2728,13 +2334,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2728
2334
|
if (!options?.skipNavigationHistory) {
|
|
2729
2335
|
addNavigationEntry(targetWorkspaceId, item);
|
|
2730
2336
|
}
|
|
2731
|
-
//
|
|
2732
|
-
|
|
2733
|
-
switchWorkspacePushedRef.current = true;
|
|
2734
|
-
updateUrl({
|
|
2735
|
-
workspace: targetWorkspaceId,
|
|
2736
|
-
...options?.urlParams,
|
|
2737
|
-
});
|
|
2337
|
+
// Update URL
|
|
2338
|
+
updateUrl({ workspace: targetWorkspaceId });
|
|
2738
2339
|
if (typeof document.startViewTransition === "function") {
|
|
2739
2340
|
document.startViewTransition(() => {
|
|
2740
2341
|
flushSync(() => {
|
|
@@ -2754,6 +2355,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2754
2355
|
updateUrl,
|
|
2755
2356
|
handleSetShowAgentsPanel,
|
|
2756
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]);
|
|
2757
2366
|
// Helper: get all sidebar IDs that should be preserved (locked sidebars + their stack mates)
|
|
2758
2367
|
const getPreservedSidebarIds = useCallback(() => {
|
|
2759
2368
|
const lockedSet = new Set(lockedSidebarsRef.current);
|
|
@@ -2791,9 +2400,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2791
2400
|
setOpenSidebars(newSidebars);
|
|
2792
2401
|
setLockedSidebars((locked) => locked.filter((id) => id !== sidebarId));
|
|
2793
2402
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2794
|
-
if (sidebarId === "agents-panel") {
|
|
2795
|
-
setUserPreferences({ showAgentsPanel: false });
|
|
2796
|
-
}
|
|
2797
2403
|
startTransition(() => {
|
|
2798
2404
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2799
2405
|
});
|
|
@@ -2808,69 +2414,34 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2808
2414
|
];
|
|
2809
2415
|
openSidebarsRef.current = newSidebars;
|
|
2810
2416
|
setOpenSidebars(newSidebars);
|
|
2811
|
-
ensureSidebarPinned(sidebarId);
|
|
2812
2417
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2813
|
-
if (sidebarId === "agents-panel") {
|
|
2814
|
-
setUserPreferences({ showAgentsPanel: true });
|
|
2815
|
-
}
|
|
2816
|
-
// On mobile, close the editor form panel when opening a sidebar
|
|
2817
|
-
if (isMobile) {
|
|
2818
|
-
setMobileEditorPanelOpenRaw(false);
|
|
2819
|
-
}
|
|
2820
2418
|
startTransition(() => {
|
|
2821
2419
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2822
2420
|
});
|
|
2823
|
-
}, [
|
|
2824
|
-
updateUrl,
|
|
2825
|
-
getPreservedSidebarIds,
|
|
2826
|
-
normalizeSidebarStacks,
|
|
2827
|
-
ensureSidebarPinned,
|
|
2828
|
-
setUserPreferences,
|
|
2829
|
-
isMobile,
|
|
2830
|
-
]);
|
|
2421
|
+
}, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
|
|
2831
2422
|
// Ensure a sidebar is open (without toggling it closed if already open)
|
|
2832
|
-
const openSidebar = useCallback((sidebarId
|
|
2423
|
+
const openSidebar = useCallback((sidebarId) => {
|
|
2833
2424
|
const currentOpenSidebars = openSidebarsRef.current;
|
|
2834
2425
|
if (currentOpenSidebars.includes(sidebarId)) {
|
|
2835
2426
|
// Already open, nothing to do
|
|
2836
2427
|
return;
|
|
2837
2428
|
}
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
...currentOpenSidebars.filter((id) => preservedSet?.has(id)),
|
|
2845
|
-
sidebarId,
|
|
2846
|
-
];
|
|
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
|
+
];
|
|
2847
2435
|
openSidebarsRef.current = newSidebars;
|
|
2848
2436
|
setOpenSidebars(newSidebars);
|
|
2849
|
-
ensureSidebarPinned(sidebarId);
|
|
2850
2437
|
setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
|
|
2851
|
-
if (sidebarId === "agents-panel") {
|
|
2852
|
-
setUserPreferences({ showAgentsPanel: true });
|
|
2853
|
-
}
|
|
2854
|
-
// On mobile, close the editor form panel when opening a sidebar
|
|
2855
|
-
if (isMobile) {
|
|
2856
|
-
setMobileEditorPanelOpenRaw(false);
|
|
2857
|
-
}
|
|
2858
2438
|
startTransition(() => {
|
|
2859
2439
|
updateUrl({ sidebar: newSidebars.join(",") || undefined });
|
|
2860
2440
|
});
|
|
2861
|
-
}, [
|
|
2862
|
-
updateUrl,
|
|
2863
|
-
getPreservedSidebarIds,
|
|
2864
|
-
normalizeSidebarStacks,
|
|
2865
|
-
ensureSidebarPinned,
|
|
2866
|
-
setUserPreferences,
|
|
2867
|
-
isMobile,
|
|
2868
|
-
]);
|
|
2441
|
+
}, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
|
|
2869
2442
|
// Toggle lock state for a sidebar stack (keeps it visible when selecting another)
|
|
2870
2443
|
// When toggling any sidebar, we toggle the entire stack it belongs to
|
|
2871
2444
|
const toggleSidebarLock = useCallback((sidebarId) => {
|
|
2872
|
-
if (isMobile)
|
|
2873
|
-
return;
|
|
2874
2445
|
const currentStacks = sidebarStacksRef.current;
|
|
2875
2446
|
const stackContainingSidebar = currentStacks.find((stack) => stack.includes(sidebarId));
|
|
2876
2447
|
const sidebarIdsToToggle = stackContainingSidebar || [sidebarId];
|
|
@@ -2888,7 +2459,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2888
2459
|
];
|
|
2889
2460
|
}
|
|
2890
2461
|
});
|
|
2891
|
-
}, [
|
|
2462
|
+
}, []);
|
|
2892
2463
|
const stackSidebar = useCallback((sidebarId, targetSidebarId, position = "after") => {
|
|
2893
2464
|
if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId)
|
|
2894
2465
|
return;
|
|
@@ -2920,38 +2491,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2920
2491
|
return normalizeSidebarStacks(openIds, next);
|
|
2921
2492
|
});
|
|
2922
2493
|
}, [normalizeSidebarStacks]);
|
|
2923
|
-
const moveSidebarToColumn = useCallback((sidebarId, targetSidebarId, position = "after") => {
|
|
2924
|
-
if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId) {
|
|
2925
|
-
return;
|
|
2926
|
-
}
|
|
2927
|
-
const currentOpen = openSidebarsRef.current;
|
|
2928
|
-
const baseOpen = currentOpen.filter((id) => id !== sidebarId);
|
|
2929
|
-
const targetIndex = baseOpen.indexOf(targetSidebarId);
|
|
2930
|
-
if (targetIndex === -1) {
|
|
2931
|
-
return;
|
|
2932
|
-
}
|
|
2933
|
-
const insertIndex = position === "before" ? targetIndex : targetIndex + 1;
|
|
2934
|
-
const nextOpen = [...baseOpen];
|
|
2935
|
-
nextOpen.splice(insertIndex, 0, sidebarId);
|
|
2936
|
-
openSidebarsRef.current = nextOpen;
|
|
2937
|
-
setOpenSidebars(nextOpen);
|
|
2938
|
-
startTransition(() => {
|
|
2939
|
-
updateUrl({ sidebar: nextOpen.join(",") || undefined });
|
|
2940
|
-
});
|
|
2941
|
-
setSidebarStacks((prev) => {
|
|
2942
|
-
const normalized = normalizeSidebarStacks(nextOpen, prev);
|
|
2943
|
-
const next = normalized
|
|
2944
|
-
.map((stack) => stack.filter((id) => id !== sidebarId))
|
|
2945
|
-
.filter((stack) => stack.length > 0);
|
|
2946
|
-
const targetStackIndex = next.findIndex((stack) => stack.includes(targetSidebarId));
|
|
2947
|
-
if (targetStackIndex === -1) {
|
|
2948
|
-
next.push([sidebarId]);
|
|
2949
|
-
return normalizeSidebarStacks(nextOpen, next);
|
|
2950
|
-
}
|
|
2951
|
-
next.splice(position === "before" ? targetStackIndex : targetStackIndex + 1, 0, [sidebarId]);
|
|
2952
|
-
return normalizeSidebarStacks(nextOpen, next);
|
|
2953
|
-
});
|
|
2954
|
-
}, [normalizeSidebarStacks, updateUrl]);
|
|
2955
2494
|
const unstackSidebar = useCallback((sidebarId) => {
|
|
2956
2495
|
setSidebarStacks((prev) => {
|
|
2957
2496
|
const openIds = openSidebarsRef.current;
|
|
@@ -2997,34 +2536,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
2997
2536
|
// Get resolved sidebar (with panels materialized)
|
|
2998
2537
|
// Note: This is defined as a function that will be called later when editContext is available
|
|
2999
2538
|
const sidebars = configuration.editor.sidebars ?? [];
|
|
3000
|
-
const taskboardSidebarIds = new Set([
|
|
3001
|
-
"taskboard-project-list",
|
|
3002
|
-
"taskboard-my-tasks",
|
|
3003
|
-
]);
|
|
3004
|
-
const getSidebarsForWorkspace = useCallback((targetWorkspaceId) => {
|
|
3005
|
-
const isTaskboardWorkspace = targetWorkspaceId === "taskboard";
|
|
3006
|
-
const workspaceAllowedSidebarIds = userInfo.workspaces?.find((w) => w.id === targetWorkspaceId)
|
|
3007
|
-
?.sidebars ?? [];
|
|
3008
|
-
return sidebars.filter((s) => {
|
|
3009
|
-
const isTaskboardSidebar = taskboardSidebarIds.has(s.id);
|
|
3010
|
-
if (isTaskboardWorkspace && !isTaskboardSidebar)
|
|
3011
|
-
return false;
|
|
3012
|
-
if (!isTaskboardWorkspace && isTaskboardSidebar)
|
|
3013
|
-
return false;
|
|
3014
|
-
// Always show agents-panel regardless of workspace settings.
|
|
3015
|
-
if (s.id === "agents-panel") {
|
|
3016
|
-
return true;
|
|
3017
|
-
}
|
|
3018
|
-
// If no workspace settings or no sidebars defined for current workspace, show all.
|
|
3019
|
-
if (workspaceAllowedSidebarIds.length === 0) {
|
|
3020
|
-
return true;
|
|
3021
|
-
}
|
|
3022
|
-
// Only show sidebars that are in the allowed list for the current workspace.
|
|
3023
|
-
return workspaceAllowedSidebarIds.includes(s.id);
|
|
3024
|
-
});
|
|
3025
|
-
}, [sidebars, userInfo.workspaces]);
|
|
3026
2539
|
const getResolvedSidebar = useCallback((sidebarId) => {
|
|
3027
|
-
const sidebar =
|
|
2540
|
+
const sidebar = sidebars.find((s) => s.id === sidebarId);
|
|
3028
2541
|
if (!sidebar)
|
|
3029
2542
|
return undefined;
|
|
3030
2543
|
// Resolve panel factories using editContextRef to avoid circular dependency
|
|
@@ -3038,35 +2551,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3038
2551
|
...sidebar,
|
|
3039
2552
|
panels: resolvedPanels,
|
|
3040
2553
|
};
|
|
3041
|
-
}, [
|
|
3042
|
-
useEffect(() => {
|
|
3043
|
-
if (!currentWorkspace.supportsSidebars) {
|
|
3044
|
-
return;
|
|
3045
|
-
}
|
|
3046
|
-
const allowedIds = new Set(getSidebarsForWorkspace(workspaceId).map((sidebar) => sidebar.id));
|
|
3047
|
-
const currentOpen = openSidebarsRef.current;
|
|
3048
|
-
let nextOpen = currentOpen.filter((id) => allowedIds.has(id));
|
|
3049
|
-
if (nextOpen.length === 0 && currentWorkspace.defaultSidebars?.length) {
|
|
3050
|
-
nextOpen = currentWorkspace.defaultSidebars.filter((id) => allowedIds.has(id));
|
|
3051
|
-
}
|
|
3052
|
-
const unchanged = nextOpen.length === currentOpen.length &&
|
|
3053
|
-
nextOpen.every((id, index) => id === currentOpen[index]);
|
|
3054
|
-
if (unchanged) {
|
|
3055
|
-
return;
|
|
3056
|
-
}
|
|
3057
|
-
openSidebarsRef.current = nextOpen;
|
|
3058
|
-
setOpenSidebars(nextOpen);
|
|
3059
|
-
setSidebarStacks((prev) => normalizeSidebarStacks(nextOpen, prev));
|
|
3060
|
-
startTransition(() => {
|
|
3061
|
-
updateUrl({ sidebar: nextOpen.join(",") || undefined });
|
|
3062
|
-
});
|
|
3063
|
-
}, [
|
|
3064
|
-
currentWorkspace,
|
|
3065
|
-
getSidebarsForWorkspace,
|
|
3066
|
-
normalizeSidebarStacks,
|
|
3067
|
-
updateUrl,
|
|
3068
|
-
workspaceId,
|
|
3069
|
-
]);
|
|
2554
|
+
}, [sidebars]);
|
|
3070
2555
|
// Listen for switch-workspace and open-sidebar commands from agents via websocket
|
|
3071
2556
|
useEffect(() => {
|
|
3072
2557
|
const handleAgentMessage = (message) => {
|
|
@@ -3280,45 +2765,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3280
2765
|
}
|
|
3281
2766
|
return true;
|
|
3282
2767
|
}, [operations, ignoreBlur, sessionId]);
|
|
3283
|
-
const quickSwitcherEntries = useMemo(() => {
|
|
3284
|
-
const entries = [];
|
|
3285
|
-
const seen = new Set();
|
|
3286
|
-
const pushEntry = (entry) => {
|
|
3287
|
-
const key = entry.item
|
|
3288
|
-
? `${entry.workspaceId}:${entry.item.id}:${entry.item.language}:${entry.item.version}`
|
|
3289
|
-
: `${entry.workspaceId}:no-item`;
|
|
3290
|
-
if (seen.has(key))
|
|
3291
|
-
return;
|
|
3292
|
-
seen.add(key);
|
|
3293
|
-
entries.push(entry);
|
|
3294
|
-
};
|
|
3295
|
-
for (const entry of navigationHistory) {
|
|
3296
|
-
pushEntry(entry);
|
|
3297
|
-
}
|
|
3298
|
-
for (const entry of browseHistory) {
|
|
3299
|
-
if (!entry.id || !entry.language)
|
|
3300
|
-
continue;
|
|
3301
|
-
pushEntry({
|
|
3302
|
-
workspaceId,
|
|
3303
|
-
item: {
|
|
3304
|
-
id: entry.id,
|
|
3305
|
-
language: entry.language,
|
|
3306
|
-
version: entry.version ?? 0,
|
|
3307
|
-
},
|
|
3308
|
-
timestamp: entry.visitedAt
|
|
3309
|
-
? new Date(entry.visitedAt).getTime()
|
|
3310
|
-
: Date.now(),
|
|
3311
|
-
displayName: entry.name || workspaceId,
|
|
3312
|
-
itemName: entry.name,
|
|
3313
|
-
itemPath: entry.path,
|
|
3314
|
-
itemIcon: entry.icon,
|
|
3315
|
-
});
|
|
3316
|
-
}
|
|
3317
|
-
return entries.slice(0, 25);
|
|
3318
|
-
}, [navigationHistory, browseHistory, workspaceId]);
|
|
3319
2768
|
// Quick switcher handlers
|
|
3320
2769
|
const showQuickSwitcher = useCallback((show) => {
|
|
3321
|
-
if (show &&
|
|
2770
|
+
if (show && navigationHistory.length > 1) {
|
|
3322
2771
|
setQuickSwitcherVisible(true);
|
|
3323
2772
|
// Start with index 1 (second entry - previous entry) for quick switching
|
|
3324
2773
|
setQuickSwitcherSelectedIndex(1);
|
|
@@ -3326,11 +2775,11 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3326
2775
|
else {
|
|
3327
2776
|
setQuickSwitcherVisible(false);
|
|
3328
2777
|
}
|
|
3329
|
-
}, [
|
|
2778
|
+
}, [navigationHistory]);
|
|
3330
2779
|
const cycleQuickSwitcher = useCallback((direction) => {
|
|
3331
2780
|
if (!quickSwitcherVisible)
|
|
3332
2781
|
return;
|
|
3333
|
-
const maxItems = Math.min(5,
|
|
2782
|
+
const maxItems = Math.min(5, navigationHistory.length);
|
|
3334
2783
|
setQuickSwitcherSelectedIndex((current) => {
|
|
3335
2784
|
let newIndex = current;
|
|
3336
2785
|
// Determine grid layout (responsive columns)
|
|
@@ -3375,9 +2824,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3375
2824
|
}
|
|
3376
2825
|
return newIndex;
|
|
3377
2826
|
});
|
|
3378
|
-
}, [quickSwitcherVisible,
|
|
2827
|
+
}, [quickSwitcherVisible, navigationHistory]);
|
|
3379
2828
|
const handleQuickSwitcherSelect = useCallback((index) => {
|
|
3380
|
-
const selectedEntry =
|
|
2829
|
+
const selectedEntry = navigationHistory[index];
|
|
3381
2830
|
if (selectedEntry) {
|
|
3382
2831
|
// Determine target workspace: entries with items should go to "editor" workspace
|
|
3383
2832
|
// (fixes issue where browse history entries initialized with wrong workspaceId)
|
|
@@ -3429,46 +2878,23 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3429
2878
|
}
|
|
3430
2879
|
setQuickSwitcherVisible(false);
|
|
3431
2880
|
}, [
|
|
3432
|
-
|
|
2881
|
+
navigationHistory,
|
|
3433
2882
|
loadItem,
|
|
3434
2883
|
switchWorkspace,
|
|
3435
2884
|
workspaceId,
|
|
3436
2885
|
item,
|
|
3437
2886
|
setNavigationHistory,
|
|
3438
2887
|
]);
|
|
3439
|
-
useEffect(() => {
|
|
3440
|
-
if (typeof window === "undefined" ||
|
|
3441
|
-
process.env.PARHELIA_DEV_MODE !== "true") {
|
|
3442
|
-
return;
|
|
3443
|
-
}
|
|
3444
|
-
window.__parheliaQuickSwitcherTestApi = {
|
|
3445
|
-
open: () => showQuickSwitcher(true),
|
|
3446
|
-
cycle: (direction = "next") => cycleQuickSwitcher(direction),
|
|
3447
|
-
closeWithoutSelection: () => setQuickSwitcherVisible(false),
|
|
3448
|
-
selectCurrent: () => handleQuickSwitcherSelect(quickSwitcherSelectedIndex),
|
|
3449
|
-
getState: () => ({
|
|
3450
|
-
visible: quickSwitcherVisible,
|
|
3451
|
-
selectedIndex: quickSwitcherSelectedIndex,
|
|
3452
|
-
entryCount: quickSwitcherEntries.length,
|
|
3453
|
-
entries: quickSwitcherEntries.map((entry) => ({
|
|
3454
|
-
workspaceId: entry.workspaceId,
|
|
3455
|
-
itemId: entry.item?.id,
|
|
3456
|
-
displayName: entry.displayName,
|
|
3457
|
-
})),
|
|
3458
|
-
}),
|
|
3459
|
-
};
|
|
3460
|
-
return () => {
|
|
3461
|
-
delete window.__parheliaQuickSwitcherTestApi;
|
|
3462
|
-
};
|
|
3463
|
-
}, [
|
|
3464
|
-
showQuickSwitcher,
|
|
3465
|
-
cycleQuickSwitcher,
|
|
3466
|
-
handleQuickSwitcherSelect,
|
|
3467
|
-
quickSwitcherSelectedIndex,
|
|
3468
|
-
]);
|
|
3469
2888
|
const { handleKeyDown } = useKeyboardNavigation({
|
|
3470
2889
|
editContextRef,
|
|
3471
|
-
|
|
2890
|
+
operations,
|
|
2891
|
+
pageViewContext: activePageViewContext,
|
|
2892
|
+
configuration,
|
|
2893
|
+
item,
|
|
2894
|
+
browseHistory,
|
|
2895
|
+
loadItem,
|
|
2896
|
+
showInfoToast,
|
|
2897
|
+
showErrorToast,
|
|
3472
2898
|
executeCommand,
|
|
3473
2899
|
showQuickSwitcher,
|
|
3474
2900
|
cycleQuickSwitcher,
|
|
@@ -3588,19 +3014,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3588
3014
|
}
|
|
3589
3015
|
return null;
|
|
3590
3016
|
};
|
|
3591
|
-
let modifierWasPressedOnMouseDown = false;
|
|
3592
|
-
const handleMouseDown = (event) => {
|
|
3593
|
-
modifierWasPressedOnMouseDown = event.ctrlKey || event.metaKey;
|
|
3594
|
-
};
|
|
3595
3017
|
const handleCtrlClick = async (event) => {
|
|
3596
|
-
// Only proceed if Ctrl
|
|
3597
|
-
// This avoids accidental navigation when users press Ctrl after selecting text to copy.
|
|
3598
|
-
if (!modifierWasPressedOnMouseDown)
|
|
3599
|
-
return;
|
|
3600
|
-
// Also require the modifier to still be held for the final click event.
|
|
3018
|
+
// Only proceed if Ctrl (or Cmd on Mac) is pressed
|
|
3601
3019
|
if (!event.ctrlKey && !event.metaKey)
|
|
3602
3020
|
return;
|
|
3603
|
-
modifierWasPressedOnMouseDown = false;
|
|
3604
3021
|
const target = event.target;
|
|
3605
3022
|
const text = getTextFromElement(target);
|
|
3606
3023
|
if (text && isGuid(text)) {
|
|
@@ -3615,7 +3032,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3615
3032
|
skipViewChange: true,
|
|
3616
3033
|
});
|
|
3617
3034
|
if (item) {
|
|
3618
|
-
|
|
3035
|
+
// Switch to the editor view
|
|
3036
|
+
switchView("editor", {
|
|
3619
3037
|
skipNavigationHistory: true,
|
|
3620
3038
|
});
|
|
3621
3039
|
showInfoToast({
|
|
@@ -3641,14 +3059,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3641
3059
|
}
|
|
3642
3060
|
};
|
|
3643
3061
|
if (typeof document !== "undefined") {
|
|
3644
|
-
document.addEventListener("mousedown", handleMouseDown, true);
|
|
3645
3062
|
document.addEventListener("click", handleCtrlClick, true);
|
|
3646
3063
|
return () => {
|
|
3647
|
-
document.removeEventListener("mousedown", handleMouseDown, true);
|
|
3648
3064
|
document.removeEventListener("click", handleCtrlClick, true);
|
|
3649
3065
|
};
|
|
3650
3066
|
}
|
|
3651
|
-
}, [loadItem,
|
|
3067
|
+
}, [loadItem, switchView, showInfoToast, showErrorToast]);
|
|
3652
3068
|
useEffect(() => {
|
|
3653
3069
|
const handleGlobalBlur = () => {
|
|
3654
3070
|
operations.onFieldBlur?.();
|
|
@@ -3686,6 +3102,21 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3686
3102
|
// Otherwise, only show workspaces that are in the settings
|
|
3687
3103
|
return workspaceIdsFromSettings.includes(w.id) && !w.visible;
|
|
3688
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));
|
|
3689
3120
|
// Handle initial mode setup from URL (only on initial load)
|
|
3690
3121
|
useEffect(() => {
|
|
3691
3122
|
if (!isInitialLoad)
|
|
@@ -3730,7 +3161,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3730
3161
|
// This is especially important when called from the tour, where the current workspace
|
|
3731
3162
|
// might be the editor and URL-only navigation would get "corrected" back.
|
|
3732
3163
|
try {
|
|
3733
|
-
|
|
3164
|
+
switchView("home", {
|
|
3734
3165
|
skipConfirmation: true,
|
|
3735
3166
|
skipNavigationHistory: true,
|
|
3736
3167
|
});
|
|
@@ -3777,6 +3208,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
3777
3208
|
const current = new URLSearchParams(searchParams.toString());
|
|
3778
3209
|
current.delete("version");
|
|
3779
3210
|
current.delete("itemid");
|
|
3211
|
+
current.delete("view"); // Remove legacy param
|
|
3780
3212
|
current.delete("workspace"); // Clear workspace
|
|
3781
3213
|
current.set("create", "1");
|
|
3782
3214
|
const newUrl = `${pathname}?${current.toString()}`;
|
|
@@ -4056,8 +3488,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4056
3488
|
setShowOnlyMyChanges,
|
|
4057
3489
|
filterByCurrentLanguage,
|
|
4058
3490
|
setFilterByCurrentLanguage,
|
|
4059
|
-
historySearchQuery,
|
|
4060
|
-
setHistorySearchQuery,
|
|
4061
3491
|
refreshHistory,
|
|
4062
3492
|
isRefreshing,
|
|
4063
3493
|
activeSessions,
|
|
@@ -4095,8 +3525,19 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4095
3525
|
workspaceId,
|
|
4096
3526
|
previousWorkspaceId,
|
|
4097
3527
|
switchWorkspace,
|
|
4098
|
-
// Sidebar state
|
|
4099
|
-
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
|
+
}),
|
|
4100
3541
|
openSidebars,
|
|
4101
3542
|
pinnedSidebars,
|
|
4102
3543
|
lockedSidebars,
|
|
@@ -4106,12 +3547,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4106
3547
|
toggleSidebarPin,
|
|
4107
3548
|
toggleSidebarLock,
|
|
4108
3549
|
stackSidebar,
|
|
4109
|
-
moveSidebarToColumn,
|
|
4110
3550
|
unstackSidebar,
|
|
4111
3551
|
reorderSidebarInStack,
|
|
4112
3552
|
reorderPinnedSidebars,
|
|
4113
3553
|
reorderOpenSidebars,
|
|
4114
3554
|
getResolvedSidebar,
|
|
3555
|
+
// Legacy compatibility (deprecated)
|
|
3556
|
+
viewName,
|
|
3557
|
+
previousViewName,
|
|
3558
|
+
switchView,
|
|
3559
|
+
view: currentView,
|
|
3560
|
+
visibleViews,
|
|
4115
3561
|
compareMode,
|
|
4116
3562
|
setCompareMode,
|
|
4117
3563
|
fullscreen,
|
|
@@ -4151,7 +3597,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4151
3597
|
addSocketMessageListener,
|
|
4152
3598
|
sendSocketMessage,
|
|
4153
3599
|
socketConnectionVersion,
|
|
4154
|
-
socketDiagnostics,
|
|
4155
3600
|
currentItemDescriptor,
|
|
4156
3601
|
editorSlots,
|
|
4157
3602
|
activeSlotId,
|
|
@@ -4164,7 +3609,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4164
3609
|
setActiveSlot,
|
|
4165
3610
|
revision,
|
|
4166
3611
|
notifyPageModelReady,
|
|
4167
|
-
pageModelReadyToken,
|
|
4168
3612
|
selectedComment,
|
|
4169
3613
|
setSelectedComment,
|
|
4170
3614
|
comments,
|
|
@@ -4243,8 +3687,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4243
3687
|
setEnableCompletions,
|
|
4244
3688
|
showComponentNavigator,
|
|
4245
3689
|
setShowComponentNavigator: handleSetShowComponentNavigator,
|
|
4246
|
-
isComponentNavigatorOpenForSlot,
|
|
4247
|
-
setComponentNavigatorOpenForSlot,
|
|
4248
3690
|
showAgentsPanel,
|
|
4249
3691
|
setShowAgentsPanel: handleSetShowAgentsPanel,
|
|
4250
3692
|
showMinimap,
|
|
@@ -4256,12 +3698,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4256
3698
|
helpTerminalProfileName,
|
|
4257
3699
|
helpTerminalActiveTab,
|
|
4258
3700
|
setHelpTerminalActiveTab,
|
|
4259
|
-
selectedHelpSectionId,
|
|
4260
|
-
setSelectedHelpSectionId,
|
|
4261
3701
|
showAgentsWorkspaceEditor,
|
|
4262
3702
|
setShowAgentsWorkspaceEditor: handleSetShowAgentsWorkspaceEditor,
|
|
4263
|
-
selectedAgentsWorkspaceAgentId,
|
|
4264
|
-
setSelectedAgentsWorkspaceAgentId,
|
|
4265
3703
|
activeEditorTab,
|
|
4266
3704
|
setActiveEditorTab,
|
|
4267
3705
|
showLayoutComponents,
|
|
@@ -4270,8 +3708,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4270
3708
|
isQuotaExceeded: isQuotaExceeded(),
|
|
4271
3709
|
getQuotaWarningMessage,
|
|
4272
3710
|
isMobile,
|
|
4273
|
-
mobileEditorPanelOpen,
|
|
4274
|
-
setMobileEditorPanelOpen: handleSetMobileEditorPanelOpen,
|
|
4275
3711
|
openDialog,
|
|
4276
3712
|
webSocketMessages,
|
|
4277
3713
|
clearWebSocketMessages: () => setWebSocketMessages([]),
|
|
@@ -4310,6 +3746,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4310
3746
|
configuration,
|
|
4311
3747
|
updateUrl,
|
|
4312
3748
|
workspaceId,
|
|
3749
|
+
switchView,
|
|
4313
3750
|
pathname,
|
|
4314
3751
|
router,
|
|
4315
3752
|
item,
|
|
@@ -4339,6 +3776,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4339
3776
|
currentWorkspace,
|
|
4340
3777
|
previousWorkspaceId,
|
|
4341
3778
|
switchWorkspace,
|
|
3779
|
+
allowedSidebarIds,
|
|
4342
3780
|
openSidebars,
|
|
4343
3781
|
pinnedSidebars,
|
|
4344
3782
|
lockedSidebars,
|
|
@@ -4350,6 +3788,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4350
3788
|
reorderOpenSidebars,
|
|
4351
3789
|
getResolvedSidebar,
|
|
4352
3790
|
viewName,
|
|
3791
|
+
previousViewName,
|
|
3792
|
+
currentView,
|
|
3793
|
+
visibleViews,
|
|
4353
3794
|
compareMode,
|
|
4354
3795
|
// Important: in multi-slot mode the active PageViewContext can change
|
|
4355
3796
|
// without the base `pageViewContext` identity changing (e.g. switching slots).
|
|
@@ -4374,7 +3815,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4374
3815
|
currentItemDescriptor,
|
|
4375
3816
|
revision,
|
|
4376
3817
|
notifyPageModelReady,
|
|
4377
|
-
pageModelReadyToken,
|
|
4378
3818
|
selectedComment,
|
|
4379
3819
|
comments,
|
|
4380
3820
|
availableCommentTags,
|
|
@@ -4393,7 +3833,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4393
3833
|
quickSwitcherSelectedIndex,
|
|
4394
3834
|
handleQuickSwitcherSelect,
|
|
4395
3835
|
webSocketMessages,
|
|
4396
|
-
socketDiagnostics,
|
|
4397
3836
|
factoriesRef,
|
|
4398
3837
|
user,
|
|
4399
3838
|
statusMessage,
|
|
@@ -4402,11 +3841,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4402
3841
|
isQuotaExceeded,
|
|
4403
3842
|
getQuotaWarningMessage,
|
|
4404
3843
|
isMobile,
|
|
4405
|
-
mobileEditorPanelOpen,
|
|
4406
|
-
handleSetMobileEditorPanelOpen,
|
|
4407
3844
|
showComponentNavigator,
|
|
4408
|
-
isComponentNavigatorOpenForSlot,
|
|
4409
|
-
setComponentNavigatorOpenForSlot,
|
|
4410
3845
|
handleSetShowComponentNavigator,
|
|
4411
3846
|
showAgentsPanel,
|
|
4412
3847
|
handleSetShowAgentsPanel,
|
|
@@ -4418,9 +3853,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4418
3853
|
helpTerminalProfileName,
|
|
4419
3854
|
helpTerminalActiveTab,
|
|
4420
3855
|
setHelpTerminalActiveTab,
|
|
4421
|
-
selectedHelpSectionId,
|
|
4422
3856
|
showAgentsWorkspaceEditor,
|
|
4423
|
-
selectedAgentsWorkspaceAgentId,
|
|
4424
3857
|
activeEditorTab,
|
|
4425
3858
|
showLayoutComponents,
|
|
4426
3859
|
openDialog,
|
|
@@ -4665,40 +4098,18 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4665
4098
|
// prevDependencies.current = currentDependencies;
|
|
4666
4099
|
// editContextRef.current = editContext;
|
|
4667
4100
|
// }, [editContext]);
|
|
4668
|
-
// Auto-open the mobile editor panel for new selection/intent changes, but
|
|
4669
|
-
// keep a manual close sticky for the exact same context.
|
|
4670
|
-
useEffect(() => {
|
|
4671
|
-
if (!isMobile || workspaceId !== "editor")
|
|
4672
|
-
return;
|
|
4673
|
-
if (activeEditorTab) {
|
|
4674
|
-
handleSetMobileEditorPanelOpen(true);
|
|
4675
|
-
return;
|
|
4676
|
-
}
|
|
4677
|
-
if (!(selection.length > 0 || insertMode))
|
|
4678
|
-
return;
|
|
4679
|
-
if (dismissedMobilePanelToken === mobilePanelDismissToken)
|
|
4680
|
-
return;
|
|
4681
|
-
handleSetMobileEditorPanelOpen(true);
|
|
4682
|
-
}, [
|
|
4683
|
-
activeEditorTab,
|
|
4684
|
-
dismissedMobilePanelToken,
|
|
4685
|
-
handleSetMobileEditorPanelOpen,
|
|
4686
|
-
insertMode,
|
|
4687
|
-
isMobile,
|
|
4688
|
-
mobilePanelDismissToken,
|
|
4689
|
-
selection,
|
|
4690
|
-
workspaceId,
|
|
4691
|
-
]);
|
|
4692
4101
|
useEffect(() => {
|
|
4693
4102
|
fieldsEditContext.clearModifiedFields();
|
|
4694
4103
|
}, [currentItemDescriptor]);
|
|
4695
|
-
if (!
|
|
4104
|
+
if (!currentView)
|
|
4696
4105
|
return null;
|
|
4697
|
-
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: () => {
|
|
4698
4107
|
setTimeout(() => {
|
|
4699
4108
|
setShowFullscreenHint(false);
|
|
4700
4109
|
}, 600);
|
|
4701
|
-
}, "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: () => {
|
|
4702
4113
|
setIsTourActive(false);
|
|
4703
4114
|
// Remove tour state from URL
|
|
4704
4115
|
// Use history.replaceState instead of router.replace to avoid triggering React navigation
|
|
@@ -4708,14 +4119,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
|
|
|
4708
4119
|
const newUrl = queryString
|
|
4709
4120
|
? `${window.location.pathname}?${queryString}`
|
|
4710
4121
|
: window.location.pathname;
|
|
4711
|
-
window.history.replaceState(
|
|
4712
|
-
}, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(
|
|
4713
|
-
return (_jsx(
|
|
4714
|
-
currentWorkspace.id === "taskboard") &&
|
|
4715
|
-
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) => {
|
|
4716
|
-
if (!open) {
|
|
4717
|
-
setConcurrentUserLimitError(null);
|
|
4718
|
-
}
|
|
4719
|
-
}, 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, {})] }) }) }) }) }));
|
|
4122
|
+
window.history.replaceState(null, "", newUrl);
|
|
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 })] }) }) }) }));
|
|
4720
4125
|
}
|
|
4721
4126
|
//# sourceMappingURL=EditorShell.js.map
|