Showing preview only (3,260K chars total). Download the full file or copy to clipboard to get everything.
Repository: graphif/project-graph
Branch: master
Commit: 2359b62de4de
Files: 664
Total size: 3.0 MB
Directory structure:
gitextract_v1_e28b6/
├── .cursor/
│ └── skills/
│ ├── create-keybind/
│ │ └── SKILL.md
│ └── create-setting-item/
│ └── SKILL.md
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── config.yml
│ │ └── no-issues.yml
│ ├── copilot-instructions.md
│ ├── scripts/
│ │ ├── enable-sourcemap.mjs
│ │ ├── generate-changelog.mjs
│ │ ├── generate-pkgbuild.mjs
│ │ ├── set-tauri-features.mjs
│ │ └── set-version.mjs
│ └── workflows/
│ ├── nightly.yml
│ ├── publish.yml
│ ├── release.yml
│ └── render-docs-svg.yml
├── .gitignore
├── .husky/
│ └── pre-commit
├── .lintstagedrc
├── .prettierignore
├── .prettierrc
├── .trae/
│ ├── documents/
│ │ ├── plan_20251223_165257.md
│ │ ├── plan_20260101_170503.md
│ │ ├── 为LineEdge添加虚线形态属性.md
│ │ ├── 为RecentFilesWindow添加独立的隐私模式功能.md
│ │ ├── 优化Tab键和反斜杠键创建节点的字体大小.md
│ │ ├── 优化嫁接操作与添加反向操作.md
│ │ ├── 优化文本节点渲染判断逻辑.md
│ │ ├── 修复Ctrl+T快捷键只能触发一个功能的问题.md
│ │ ├── 修复引用块转换时连线悬空问题.md
│ │ ├── 全局快捷键重构方案.md
│ │ ├── 在快捷键设置页面添加重置所有快捷键按钮.md
│ │ ├── 实现 Section 的 isHidden 属性功能.md
│ │ ├── 实现Section框大标题相机缩放阈值控制.md
│ │ ├── 实现关闭软件前的未保存文件警告.md
│ │ ├── 实现图片节点拖拽缩放功能.md
│ │ ├── 实现引用块节点的精准连线定位.md
│ │ ├── 实现快捷键开关功能.md
│ │ ├── 实现搜索范围选项.md
│ │ ├── 实现背景图片功能和背景管理器.md
│ │ ├── 引用块节点精准连线定位功能问题记录.md
│ │ ├── 文本节点自定义文字大小功能设计方案.md
│ │ ├── 添加大标题遮罩透明度设置.md
│ │ ├── 添加快捷键冲突检测和提醒功能.md
│ │ └── 粘贴bug崩溃报告.txt
│ └── skills/
│ ├── create-keybind/
│ │ └── SKILL.md
│ └── create-setting-item/
│ └── SKILL.md
├── .vscode/
│ ├── extensions.json
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .zed/
│ └── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── TODO.md
├── app/
│ ├── .browserslistrc
│ ├── LICENSE
│ ├── README.md
│ ├── components.json
│ ├── index.html
│ ├── package.json
│ ├── scripts/
│ │ ├── sync-locales.ts
│ │ └── tauri_build.js
│ ├── splash.html
│ ├── src/
│ │ ├── App.tsx
│ │ ├── DropWindowCover.tsx
│ │ ├── ProjectTabs.tsx
│ │ ├── assets/
│ │ │ └── versions.json
│ │ ├── cli.tsx
│ │ ├── components/
│ │ │ ├── context-menu-content.tsx
│ │ │ ├── editor/
│ │ │ │ ├── editor-base-kit.tsx
│ │ │ │ ├── plugins/
│ │ │ │ │ ├── align-base-kit.tsx
│ │ │ │ │ ├── basic-blocks-base-kit.tsx
│ │ │ │ │ ├── basic-blocks-kit.tsx
│ │ │ │ │ ├── basic-marks-base-kit.tsx
│ │ │ │ │ ├── basic-marks-kit.tsx
│ │ │ │ │ ├── callout-base-kit.tsx
│ │ │ │ │ ├── code-block-base-kit.tsx
│ │ │ │ │ ├── code-block-kit.tsx
│ │ │ │ │ ├── column-base-kit.tsx
│ │ │ │ │ ├── comment-base-kit.tsx
│ │ │ │ │ ├── comment-kit.tsx
│ │ │ │ │ ├── date-base-kit.tsx
│ │ │ │ │ ├── discussion-kit.tsx
│ │ │ │ │ ├── fixed-toolbar-kit.tsx
│ │ │ │ │ ├── floating-toolbar-kit.tsx
│ │ │ │ │ ├── font-base-kit.tsx
│ │ │ │ │ ├── font-kit.tsx
│ │ │ │ │ ├── indent-base-kit.tsx
│ │ │ │ │ ├── indent-kit.tsx
│ │ │ │ │ ├── line-height-base-kit.tsx
│ │ │ │ │ ├── link-base-kit.tsx
│ │ │ │ │ ├── link-kit.tsx
│ │ │ │ │ ├── list-base-kit.tsx
│ │ │ │ │ ├── list-kit.tsx
│ │ │ │ │ ├── markdown-kit.tsx
│ │ │ │ │ ├── math-base-kit.tsx
│ │ │ │ │ ├── math-kit.tsx
│ │ │ │ │ ├── media-base-kit.tsx
│ │ │ │ │ ├── mention-base-kit.tsx
│ │ │ │ │ ├── suggestion-base-kit.tsx
│ │ │ │ │ ├── suggestion-kit.tsx
│ │ │ │ │ ├── table-base-kit.tsx
│ │ │ │ │ ├── table-kit.tsx
│ │ │ │ │ ├── toc-base-kit.tsx
│ │ │ │ │ └── toggle-base-kit.tsx
│ │ │ │ └── transforms.ts
│ │ │ ├── key-tooltip.tsx
│ │ │ ├── render-sub-windows.tsx
│ │ │ ├── right-toolbar.tsx
│ │ │ ├── theme-mode-switch.tsx
│ │ │ ├── toolbar-content.tsx
│ │ │ ├── ui/
│ │ │ │ ├── ai-node.tsx
│ │ │ │ ├── ai-toolbar-button.tsx
│ │ │ │ ├── alert-dialog.tsx
│ │ │ │ ├── alert.tsx
│ │ │ │ ├── align-toolbar-button.tsx
│ │ │ │ ├── avatar.tsx
│ │ │ │ ├── block-discussion.tsx
│ │ │ │ ├── block-list-static.tsx
│ │ │ │ ├── block-list.tsx
│ │ │ │ ├── block-selection.tsx
│ │ │ │ ├── block-suggestion.tsx
│ │ │ │ ├── blockquote-node-static.tsx
│ │ │ │ ├── blockquote-node.tsx
│ │ │ │ ├── button.tsx
│ │ │ │ ├── calendar.tsx
│ │ │ │ ├── callout-node-static.tsx
│ │ │ │ ├── callout-node.tsx
│ │ │ │ ├── caption.tsx
│ │ │ │ ├── card.tsx
│ │ │ │ ├── checkbox.tsx
│ │ │ │ ├── code-block-node-static.tsx
│ │ │ │ ├── code-block-node.tsx
│ │ │ │ ├── code-node-static.tsx
│ │ │ │ ├── code-node.tsx
│ │ │ │ ├── collapsible.tsx
│ │ │ │ ├── column-node-static.tsx
│ │ │ │ ├── column-node.tsx
│ │ │ │ ├── command.tsx
│ │ │ │ ├── comment-node-static.tsx
│ │ │ │ ├── comment-node.tsx
│ │ │ │ ├── comment-toolbar-button.tsx
│ │ │ │ ├── comment.tsx
│ │ │ │ ├── context-menu.tsx
│ │ │ │ ├── date-node-static.tsx
│ │ │ │ ├── date-node.tsx
│ │ │ │ ├── dialog.tsx
│ │ │ │ ├── dropdown-menu.tsx
│ │ │ │ ├── editor-static.tsx
│ │ │ │ ├── editor.tsx
│ │ │ │ ├── emoji-node.tsx
│ │ │ │ ├── emoji-toolbar-button.tsx
│ │ │ │ ├── equation-node-static.tsx
│ │ │ │ ├── equation-node.tsx
│ │ │ │ ├── equation-toolbar-button.tsx
│ │ │ │ ├── export-toolbar-button.tsx
│ │ │ │ ├── field.tsx
│ │ │ │ ├── file-chooser.tsx
│ │ │ │ ├── fixed-toolbar-buttons.tsx
│ │ │ │ ├── fixed-toolbar.tsx
│ │ │ │ ├── floating-toolbar-buttons.tsx
│ │ │ │ ├── floating-toolbar.tsx
│ │ │ │ ├── font-color-toolbar-button.tsx
│ │ │ │ ├── font-size-toolbar-button.tsx
│ │ │ │ ├── heading-node-static.tsx
│ │ │ │ ├── heading-node.tsx
│ │ │ │ ├── highlight-node-static.tsx
│ │ │ │ ├── highlight-node.tsx
│ │ │ │ ├── history-toolbar-button.tsx
│ │ │ │ ├── hr-node-static.tsx
│ │ │ │ ├── hr-node.tsx
│ │ │ │ ├── import-toolbar-button.tsx
│ │ │ │ ├── indent-toolbar-button.tsx
│ │ │ │ ├── inline-combobox.tsx
│ │ │ │ ├── input.tsx
│ │ │ │ ├── insert-toolbar-button.tsx
│ │ │ │ ├── kbd-node-static.tsx
│ │ │ │ ├── kbd-node.tsx
│ │ │ │ ├── key-bind.tsx
│ │ │ │ ├── line-height-toolbar-button.tsx
│ │ │ │ ├── link-node-static.tsx
│ │ │ │ ├── link-node.tsx
│ │ │ │ ├── link-toolbar-button.tsx
│ │ │ │ ├── link-toolbar.tsx
│ │ │ │ ├── list-toolbar-button.tsx
│ │ │ │ ├── mark-toolbar-button.tsx
│ │ │ │ ├── markdown.tsx
│ │ │ │ ├── media-audio-node-static.tsx
│ │ │ │ ├── media-audio-node.tsx
│ │ │ │ ├── media-file-node-static.tsx
│ │ │ │ ├── media-file-node.tsx
│ │ │ │ ├── media-image-node-static.tsx
│ │ │ │ ├── media-image-node.tsx
│ │ │ │ ├── media-toolbar-button.tsx
│ │ │ │ ├── media-toolbar.tsx
│ │ │ │ ├── media-video-node-static.tsx
│ │ │ │ ├── media-video-node.tsx
│ │ │ │ ├── mention-node-static.tsx
│ │ │ │ ├── mention-node.tsx
│ │ │ │ ├── menubar.tsx
│ │ │ │ ├── mode-toolbar-button.tsx
│ │ │ │ ├── more-toolbar-button.tsx
│ │ │ │ ├── paragraph-node-static.tsx
│ │ │ │ ├── paragraph-node.tsx
│ │ │ │ ├── popover.tsx
│ │ │ │ ├── progress.tsx
│ │ │ │ ├── resize-handle.tsx
│ │ │ │ ├── select.tsx
│ │ │ │ ├── separator.tsx
│ │ │ │ ├── sheet.tsx
│ │ │ │ ├── sidebar.tsx
│ │ │ │ ├── skeleton.tsx
│ │ │ │ ├── slider.tsx
│ │ │ │ ├── sonner.tsx
│ │ │ │ ├── suggestion-node-static.tsx
│ │ │ │ ├── suggestion-node.tsx
│ │ │ │ ├── suggestion-toolbar-button.tsx
│ │ │ │ ├── switch.tsx
│ │ │ │ ├── table-icons.tsx
│ │ │ │ ├── table-node-static.tsx
│ │ │ │ ├── table-node.tsx
│ │ │ │ ├── table-toolbar-button.tsx
│ │ │ │ ├── tabs.tsx
│ │ │ │ ├── textarea.tsx
│ │ │ │ ├── toc-node-static.tsx
│ │ │ │ ├── toc-node.tsx
│ │ │ │ ├── toggle-node-static.tsx
│ │ │ │ ├── toggle-node.tsx
│ │ │ │ ├── toggle-toolbar-button.tsx
│ │ │ │ ├── toolbar.tsx
│ │ │ │ ├── tooltip.tsx
│ │ │ │ ├── tree.tsx
│ │ │ │ └── turn-into-toolbar-button.tsx
│ │ │ ├── vditor-panel.tsx
│ │ │ └── welcome-page.tsx
│ │ ├── core/
│ │ │ ├── Project.tsx
│ │ │ ├── algorithm/
│ │ │ │ ├── arrayFunctions.tsx
│ │ │ │ ├── geometry/
│ │ │ │ │ ├── README.md
│ │ │ │ │ └── convexHull.tsx
│ │ │ │ ├── numberFunctions.tsx
│ │ │ │ ├── random.tsx
│ │ │ │ └── setFunctions.tsx
│ │ │ ├── fileSystemProvider/
│ │ │ │ ├── FileSystemProviderDraft.tsx
│ │ │ │ └── FileSystemProviderFile.tsx
│ │ │ ├── interfaces/
│ │ │ │ └── Service.tsx
│ │ │ ├── loadAllServices.tsx
│ │ │ ├── plugin/
│ │ │ │ ├── PluginCodeParseData.tsx
│ │ │ │ ├── PluginWorker.tsx
│ │ │ │ ├── README.md
│ │ │ │ ├── UserScriptsManager.tsx
│ │ │ │ ├── apis.tsx
│ │ │ │ └── types.tsx
│ │ │ ├── render/
│ │ │ │ ├── 3d/
│ │ │ │ │ └── README.md
│ │ │ │ ├── canvas2d/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── basicRenderer/
│ │ │ │ │ │ ├── ImageRenderer.tsx
│ │ │ │ │ │ ├── curveRenderer.tsx
│ │ │ │ │ │ ├── shapeRenderer.tsx
│ │ │ │ │ │ ├── svgRenderer.tsx
│ │ │ │ │ │ └── textRenderer.tsx
│ │ │ │ │ ├── controllerRenderer/
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ └── drawingRenderer.tsx
│ │ │ │ │ ├── debugRender.tsx
│ │ │ │ │ ├── entityRenderer/
│ │ │ │ │ │ ├── CollisionBoxRenderer.tsx
│ │ │ │ │ │ ├── EntityDetailsButtonRenderer.tsx
│ │ │ │ │ │ ├── EntityRenderer.tsx
│ │ │ │ │ │ ├── ReferenceBlockRenderer.tsx
│ │ │ │ │ │ ├── edge/
│ │ │ │ │ │ │ ├── EdgeRenderer.tsx
│ │ │ │ │ │ │ ├── EdgeRendererClass.tsx
│ │ │ │ │ │ │ └── concrete/
│ │ │ │ │ │ │ ├── StraightEdgeRenderer.tsx
│ │ │ │ │ │ │ ├── SymmetryCurveEdgeRenderer.tsx
│ │ │ │ │ │ │ └── VerticalPolyEdgeRenderer.tsx
│ │ │ │ │ │ ├── multiTargetUndirectedEdge/
│ │ │ │ │ │ │ └── MultiTargetUndirectedEdgeRenderer.tsx
│ │ │ │ │ │ ├── section/
│ │ │ │ │ │ │ └── SectionRenderer.tsx
│ │ │ │ │ │ ├── svgNode/
│ │ │ │ │ │ │ └── SvgNodeRenderer.tsx
│ │ │ │ │ │ ├── textNode/
│ │ │ │ │ │ │ └── TextNodeRenderer.tsx
│ │ │ │ │ │ └── urlNode/
│ │ │ │ │ │ └── urlNodeRenderer.tsx
│ │ │ │ │ ├── renderer.tsx
│ │ │ │ │ └── utilsRenderer/
│ │ │ │ │ ├── RenderUtils.tsx
│ │ │ │ │ ├── WorldRenderUtils.tsx
│ │ │ │ │ ├── backgroundRenderer.tsx
│ │ │ │ │ ├── globalMaskRenderer.tsx
│ │ │ │ │ └── searchContentHighlightRenderer.tsx
│ │ │ │ ├── domElement/
│ │ │ │ │ ├── RectangleElement.tsx
│ │ │ │ │ └── inputElement.tsx
│ │ │ │ └── svg/
│ │ │ │ ├── README.md
│ │ │ │ └── SvgUtils.tsx
│ │ │ ├── service/
│ │ │ │ ├── AssetsRepository.tsx
│ │ │ │ ├── FeatureFlags.tsx
│ │ │ │ ├── GlobalMenu.tsx
│ │ │ │ ├── QuickSettingsManager.tsx
│ │ │ │ ├── Settings.tsx
│ │ │ │ ├── SettingsIcons.tsx
│ │ │ │ ├── SubWindow.tsx
│ │ │ │ ├── Telemetry.tsx
│ │ │ │ ├── Themes.tsx
│ │ │ │ ├── Tourials.tsx
│ │ │ │ ├── UserState.tsx
│ │ │ │ ├── controlService/
│ │ │ │ │ ├── DirectionKeyUtilsEngine/
│ │ │ │ │ │ └── directionKeyUtilsEngine.tsx
│ │ │ │ │ ├── MouseLocation.tsx
│ │ │ │ │ ├── autoLayoutEngine/
│ │ │ │ │ │ ├── autoLayoutFastTreeMode.tsx
│ │ │ │ │ │ └── mainTick.tsx
│ │ │ │ │ ├── controller/
│ │ │ │ │ │ ├── Controller.tsx
│ │ │ │ │ │ ├── ControllerClass.tsx
│ │ │ │ │ │ └── concrete/
│ │ │ │ │ │ ├── ControllerAssociationReshape.tsx
│ │ │ │ │ │ ├── ControllerCamera/
│ │ │ │ │ │ │ └── mac.tsx
│ │ │ │ │ │ ├── ControllerCamera.tsx
│ │ │ │ │ │ ├── ControllerContextMenu.tsx
│ │ │ │ │ │ ├── ControllerCutting.tsx
│ │ │ │ │ │ ├── ControllerEdgeEdit.tsx
│ │ │ │ │ │ ├── ControllerEntityClickSelectAndMove.tsx
│ │ │ │ │ │ ├── ControllerEntityCreate.tsx
│ │ │ │ │ │ ├── ControllerEntityLayerMoving.tsx
│ │ │ │ │ │ ├── ControllerEntityResize.tsx
│ │ │ │ │ │ ├── ControllerImageScale.tsx
│ │ │ │ │ │ ├── ControllerNodeConnection.tsx
│ │ │ │ │ │ ├── ControllerNodeEdit.tsx
│ │ │ │ │ │ ├── ControllerPenStrokeControl.tsx
│ │ │ │ │ │ ├── ControllerPenStrokeDrawing.tsx
│ │ │ │ │ │ ├── ControllerRectangleSelect.tsx
│ │ │ │ │ │ ├── ControllerSectionEdit.tsx
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ └── utilsControl.tsx
│ │ │ │ │ ├── keyboardOnlyEngine/
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ ├── keyboardOnlyDirectionController.tsx
│ │ │ │ │ │ ├── keyboardOnlyEngine.tsx
│ │ │ │ │ │ ├── keyboardOnlyGraphEngine.tsx
│ │ │ │ │ │ ├── keyboardOnlyTreeEngine.tsx
│ │ │ │ │ │ ├── newTargetLocationSelector.tsx
│ │ │ │ │ │ └── selectChangeEngine.tsx
│ │ │ │ │ ├── rectangleSelectEngine/
│ │ │ │ │ │ └── rectangleSelectEngine.tsx
│ │ │ │ │ ├── shortcutKeysEngine/
│ │ │ │ │ │ ├── GlobalShortcutManager.tsx
│ │ │ │ │ │ ├── KeyBinds.tsx
│ │ │ │ │ │ ├── KeyBindsUI.tsx
│ │ │ │ │ │ ├── ShortcutKeyFixer.tsx
│ │ │ │ │ │ └── shortcutKeysRegister.tsx
│ │ │ │ │ └── stageMouseInteractionCore/
│ │ │ │ │ └── stageMouseInteractionCore.tsx
│ │ │ │ ├── dataFileService/
│ │ │ │ │ ├── AutoSaveBackupService.tsx
│ │ │ │ │ ├── RecentFileManager.tsx
│ │ │ │ │ └── StartFilesManager.tsx
│ │ │ │ ├── dataGenerateService/
│ │ │ │ │ ├── autoComputeEngine/
│ │ │ │ │ │ ├── AutoComputeUtils.tsx
│ │ │ │ │ │ ├── functions/
│ │ │ │ │ │ │ ├── compareLogic.tsx
│ │ │ │ │ │ │ ├── mathLogic.tsx
│ │ │ │ │ │ │ ├── nodeLogic.tsx
│ │ │ │ │ │ │ ├── programLogic.tsx
│ │ │ │ │ │ │ └── stringLogic.tsx
│ │ │ │ │ │ ├── logicNodeNameEnum.tsx
│ │ │ │ │ │ └── mainTick.tsx
│ │ │ │ │ ├── crossFileContentQuery.tsx
│ │ │ │ │ ├── dataTransferEngine/
│ │ │ │ │ │ └── dataTransferEngine.tsx
│ │ │ │ │ ├── generateFromFolderEngine/
│ │ │ │ │ │ └── GenerateFromFolderEngine.tsx
│ │ │ │ │ ├── generateScreenshot.tsx
│ │ │ │ │ ├── stageExportEngine/
│ │ │ │ │ │ ├── BaseExporter.tsx
│ │ │ │ │ │ ├── MarkdownExporter.tsx
│ │ │ │ │ │ ├── MermaidExporter.tsx
│ │ │ │ │ │ ├── PlainTextExporter.tsx
│ │ │ │ │ │ ├── StageExportPng.tsx
│ │ │ │ │ │ ├── StageExportSvg.tsx
│ │ │ │ │ │ ├── TabExporter.tsx
│ │ │ │ │ │ └── stageExportEngine.tsx
│ │ │ │ │ └── stageImportEngine/
│ │ │ │ │ ├── BaseImporter.tsx
│ │ │ │ │ ├── GraphImporter.tsx
│ │ │ │ │ ├── MarkdownImporter.tsx
│ │ │ │ │ ├── MermaidImporter.tsx
│ │ │ │ │ ├── TreeImporter.tsx
│ │ │ │ │ └── stageImportEngine.tsx
│ │ │ │ ├── dataManageService/
│ │ │ │ │ ├── ComplexityDetector.tsx
│ │ │ │ │ ├── aiEngine/
│ │ │ │ │ │ ├── AIEngine.tsx
│ │ │ │ │ │ └── AITools.tsx
│ │ │ │ │ ├── colorSmartTools.tsx
│ │ │ │ │ ├── connectNodeSmartTools.tsx
│ │ │ │ │ ├── contentSearchEngine/
│ │ │ │ │ │ └── contentSearchEngine.tsx
│ │ │ │ │ ├── copyEngine/
│ │ │ │ │ │ ├── VirtualClipboard.tsx
│ │ │ │ │ │ ├── copyEngine.tsx
│ │ │ │ │ │ ├── copyEngineImage.tsx
│ │ │ │ │ │ ├── copyEngineText.tsx
│ │ │ │ │ │ ├── copyEngineUtils.tsx
│ │ │ │ │ │ └── stringValidTools.tsx
│ │ │ │ │ ├── dragFileIntoStageEngine/
│ │ │ │ │ │ └── dragFileIntoStageEngine.tsx
│ │ │ │ │ └── textNodeSmartTools.tsx
│ │ │ │ └── feedbackService/
│ │ │ │ ├── ColorManager.tsx
│ │ │ │ ├── SoundService.tsx
│ │ │ │ ├── effectEngine/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── concrete/
│ │ │ │ │ │ ├── CircleChangeRadiusEffect.tsx
│ │ │ │ │ │ ├── CircleFlameEffect.tsx
│ │ │ │ │ │ ├── EdgeCutEffect.tsx
│ │ │ │ │ │ ├── EntityAlignEffect.tsx
│ │ │ │ │ │ ├── EntityCreateFlashEffect.tsx
│ │ │ │ │ │ ├── EntityDashTipEffect.tsx
│ │ │ │ │ │ ├── EntityJumpMoveEffect.tsx
│ │ │ │ │ │ ├── EntityShakeEffect.tsx
│ │ │ │ │ │ ├── EntityShrinkEffect.tsx
│ │ │ │ │ │ ├── ExplodeDashEffect.tsx
│ │ │ │ │ │ ├── LineCuttingEffect.tsx
│ │ │ │ │ │ ├── LineEffect.tsx
│ │ │ │ │ │ ├── MouseTipFeedbackEffect.tsx
│ │ │ │ │ │ ├── NodeMoveShadowEffect.tsx
│ │ │ │ │ │ ├── PenStrokeDeletedEffect.tsx
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ ├── RectangleLittleNoteEffect.tsx
│ │ │ │ │ │ ├── RectangleNoteEffect.tsx
│ │ │ │ │ │ ├── RectangleNoteReversedEffect.tsx
│ │ │ │ │ │ ├── RectanglePushInEffect.tsx
│ │ │ │ │ │ ├── RectangleRenderEffect.tsx
│ │ │ │ │ │ ├── RectangleSlideEffect.tsx
│ │ │ │ │ │ ├── RectangleSplitTwoPartEffect.tsx
│ │ │ │ │ │ ├── TextRaiseEffectLocated.tsx
│ │ │ │ │ │ ├── ViewFlashEffect.tsx
│ │ │ │ │ │ └── ViewOutlineFlashEffect.tsx
│ │ │ │ │ ├── effectElements/
│ │ │ │ │ │ └── effectParticle.tsx
│ │ │ │ │ ├── effectMachine.tsx
│ │ │ │ │ ├── effectObject.tsx
│ │ │ │ │ └── mathTools/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── animateFunctions.tsx
│ │ │ │ │ ├── easings.tsx
│ │ │ │ │ └── rateFunctions.tsx
│ │ │ │ └── stageStyle/
│ │ │ │ ├── README.md
│ │ │ │ ├── StageStyleManager.tsx
│ │ │ │ └── stageStyle.tsx
│ │ │ └── stage/
│ │ │ ├── Camera.tsx
│ │ │ ├── Canvas.tsx
│ │ │ ├── ProjectUpgrader.tsx
│ │ │ ├── stageManager/
│ │ │ │ ├── StageHistoryManager.tsx
│ │ │ │ ├── StageManager.tsx
│ │ │ │ ├── basicMethods/
│ │ │ │ │ ├── GraphMethods.tsx
│ │ │ │ │ ├── PenStrokeMethods.tsx
│ │ │ │ │ └── SectionMethods.tsx
│ │ │ │ └── concreteMethods/
│ │ │ │ ├── LayoutManager.tsx
│ │ │ │ ├── README.md
│ │ │ │ ├── SectionCollisionSolver.tsx
│ │ │ │ ├── StageAutoAlignManager.tsx
│ │ │ │ ├── StageDeleteManager.tsx
│ │ │ │ ├── StageEntityMoveManager.tsx
│ │ │ │ ├── StageManagerUtils.tsx
│ │ │ │ ├── StageMultiTargetEdgeMove.tsx
│ │ │ │ ├── StageNodeAdder.tsx
│ │ │ │ ├── StageNodeConnector.tsx
│ │ │ │ ├── StageObjectColorManager.tsx
│ │ │ │ ├── StageObjectSelectCounter.tsx
│ │ │ │ ├── StageReferenceManager.tsx
│ │ │ │ ├── StageSectionInOutManager.tsx
│ │ │ │ ├── StageSectionPackManager.tsx
│ │ │ │ ├── StageTagManager.tsx
│ │ │ │ └── stageNodeRotate.tsx
│ │ │ └── stageObject/
│ │ │ ├── README.md
│ │ │ ├── abstract/
│ │ │ │ ├── Association.tsx
│ │ │ │ ├── ConnectableEntity.tsx
│ │ │ │ ├── StageEntity.tsx
│ │ │ │ ├── StageObject.tsx
│ │ │ │ └── StageObjectInterface.tsx
│ │ │ ├── association/
│ │ │ │ ├── CubicCatmullRomSplineEdge.tsx
│ │ │ │ ├── Edge.tsx
│ │ │ │ ├── EdgeCollisionBoxGetter.tsx
│ │ │ │ ├── LineEdge.tsx
│ │ │ │ └── MutiTargetUndirectedEdge.tsx
│ │ │ ├── collisionBox/
│ │ │ │ └── collisionBox.tsx
│ │ │ ├── entity/
│ │ │ │ ├── ConnectPoint.tsx
│ │ │ │ ├── ImageNode.tsx
│ │ │ │ ├── PenStroke.tsx
│ │ │ │ ├── ReferenceBlockNode.tsx
│ │ │ │ ├── Section.tsx
│ │ │ │ ├── SvgNode.tsx
│ │ │ │ ├── TextNode.tsx
│ │ │ │ └── UrlNode.tsx
│ │ │ └── tools/
│ │ │ └── entityDetailsManager.tsx
│ │ ├── css/
│ │ │ ├── index.css
│ │ │ └── markdown.css
│ │ ├── examples/
│ │ │ └── tauri-global-shortcut-guide.md
│ │ ├── hooks/
│ │ │ ├── use-debounce.ts
│ │ │ ├── use-mobile.ts
│ │ │ └── use-mounted.ts
│ │ ├── locales/
│ │ │ ├── README.md
│ │ │ ├── en.yml
│ │ │ ├── id.yml
│ │ │ ├── zh_CN.yml
│ │ │ ├── zh_TW.yml
│ │ │ └── zh_TWC.yml
│ │ ├── main.tsx
│ │ ├── state.tsx
│ │ ├── sub/
│ │ │ ├── AIToolsWindow.tsx
│ │ │ ├── AIWindow.tsx
│ │ │ ├── AttachmentsWindow.tsx
│ │ │ ├── AutoCompleteWindow.tsx
│ │ │ ├── AutoComputeWindow.tsx
│ │ │ ├── BackgroundManagerWindow.tsx
│ │ │ ├── ColorPaletteWindow.tsx
│ │ │ ├── ColorWindow.tsx
│ │ │ ├── ExportPngWindow.tsx
│ │ │ ├── FindWindow.tsx
│ │ │ ├── GenerateNodeWindow.tsx
│ │ │ ├── KeyboardRecentFilesWindow.tsx
│ │ │ ├── LoginWindow.tsx
│ │ │ ├── NewExportPngWindow.tsx
│ │ │ ├── NodeDetailsWindow.tsx
│ │ │ ├── OnboardingWindow.tsx
│ │ │ ├── RecentFilesWindow.tsx
│ │ │ ├── ReferencesWindow.tsx
│ │ │ ├── SettingsWindow/
│ │ │ │ ├── about.tsx
│ │ │ │ ├── appearance/
│ │ │ │ │ ├── effects.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── sounds.tsx
│ │ │ │ ├── assets/
│ │ │ │ │ └── font.css
│ │ │ │ ├── credits.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── keybinds.tsx
│ │ │ │ ├── keybindsGlobal.tsx
│ │ │ │ ├── quick-settings.tsx
│ │ │ │ ├── settings.tsx
│ │ │ │ └── themes/
│ │ │ │ ├── editor.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── TagWindow.tsx
│ │ │ ├── TestWindow.tsx
│ │ │ └── UserWindow.tsx
│ │ ├── themes/
│ │ │ ├── dark-blue.pg-theme
│ │ │ ├── dark.pg-theme
│ │ │ ├── light.pg-theme
│ │ │ ├── macaron.pg-theme
│ │ │ ├── morandi.pg-theme
│ │ │ └── park.pg-theme
│ │ ├── types/
│ │ │ ├── cursors.tsx
│ │ │ ├── directions.tsx
│ │ │ ├── metadata.tsx
│ │ │ └── node.tsx
│ │ ├── utils/
│ │ │ ├── base64.tsx
│ │ │ ├── cn.tsx
│ │ │ ├── dateChecker.tsx
│ │ │ ├── emacs.tsx
│ │ │ ├── externalOpen.tsx
│ │ │ ├── font.tsx
│ │ │ ├── imageExport.tsx
│ │ │ ├── keyboardFunctions.tsx
│ │ │ ├── markdownParse.tsx
│ │ │ ├── otherApi.tsx
│ │ │ ├── path.tsx
│ │ │ ├── pathString.tsx
│ │ │ ├── platform.tsx
│ │ │ ├── sleep.tsx
│ │ │ ├── store.tsx
│ │ │ ├── updater.tsx
│ │ │ ├── xml.tsx
│ │ │ └── yaml.tsx
│ │ └── vite-env.d.ts
│ ├── src-tauri/
│ │ ├── .gitignore
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── capabilities/
│ │ │ ├── default.json
│ │ │ └── desktop.json
│ │ ├── gen/
│ │ │ └── android/
│ │ │ ├── .editorconfig
│ │ │ ├── .gitignore
│ │ │ ├── app/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── build.gradle.kts
│ │ │ │ ├── proguard-rules.pro
│ │ │ │ └── src/
│ │ │ │ └── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── liren/
│ │ │ │ │ └── project_graph/
│ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── res/
│ │ │ │ ├── drawable/
│ │ │ │ │ └── ic_launcher_background.xml
│ │ │ │ ├── drawable-v24/
│ │ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── layout/
│ │ │ │ │ └── activity_main.xml
│ │ │ │ ├── value-night/
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── values/
│ │ │ │ │ ├── colors.xml
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ └── xml/
│ │ │ │ └── file_paths.xml
│ │ │ ├── build.gradle.kts
│ │ │ ├── buildSrc/
│ │ │ │ ├── build.gradle.kts
│ │ │ │ └── src/
│ │ │ │ └── main/
│ │ │ │ └── java/
│ │ │ │ └── liren/
│ │ │ │ └── project_graph/
│ │ │ │ └── kotlin/
│ │ │ │ ├── BuildTask.kt
│ │ │ │ └── RustPlugin.kt
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradle.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ ├── keystore.properties
│ │ │ └── settings.gradle
│ │ ├── icons/
│ │ │ └── icon.icns
│ │ ├── nsis/
│ │ │ └── installer.nsh
│ │ ├── src/
│ │ │ ├── cmd/
│ │ │ │ ├── device.rs
│ │ │ │ ├── fs.rs
│ │ │ │ └── mod.rs
│ │ │ ├── lib.rs
│ │ │ └── main.rs
│ │ └── tauri.conf.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ ├── vite-plugins/
│ │ └── i18n-auto-tw.ts
│ └── vite.config.ts
├── config.xlings
├── docs-pg/
│ ├── Project Graph v2.json
│ ├── ProjectGraph决策日志.json
│ ├── ProjectGraph开发进程图.json
│ ├── ProjectGraph开发进程图.prg
│ ├── ProjectGraph继承体系.json
│ ├── ProjectGraph项目架构.json
│ ├── README_FOR_AI.md
│ ├── issue分类.json
│ └── 服务器.prg
├── eslint.config.js
├── nx.json
├── package.json
├── packages/
│ ├── api/
│ │ ├── .npmignore
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── apis/
│ │ │ │ ├── camera.ts
│ │ │ │ ├── controller.ts
│ │ │ │ └── dialog.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── data-structures/
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── Cache.ts
│ │ │ ├── Color.ts
│ │ │ ├── LimitLengthQueue.ts
│ │ │ ├── MonoStack.ts
│ │ │ ├── ProgressNumber.ts
│ │ │ ├── Queue.ts
│ │ │ ├── Stack.ts
│ │ │ ├── Vector.ts
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ ├── Cache.test.ts
│ │ │ ├── Color.test.ts
│ │ │ ├── LimitLengthQueue.test.ts
│ │ │ ├── MonoStack.test.ts
│ │ │ ├── ProgressNumber.test.ts
│ │ │ ├── Queue.test.ts
│ │ │ ├── Stack.test.ts
│ │ │ └── Vector.test.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── serializer/
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ └── shapes/
│ ├── .gitignore
│ ├── .npmignore
│ ├── LICENSE
│ ├── package.json
│ ├── src/
│ │ ├── Circle.ts
│ │ ├── CubicCatmullRomSpline.ts
│ │ ├── Curve.ts
│ │ ├── Line.ts
│ │ ├── Rectangle.ts
│ │ ├── Shape.ts
│ │ └── index.ts
│ ├── tests/
│ │ ├── Circle.test.ts
│ │ ├── CubicCatmullRomSpline.test.ts
│ │ ├── Curve.test.ts
│ │ ├── Line.test.ts
│ │ └── Rectangle.test.ts
│ ├── tsconfig.json
│ └── tsdown.config.ts
├── patches/
│ └── typescript.patch
├── pnpm-workspace.yaml
├── utils/
│ ├── add-ts-nocheck.ts
│ ├── class2namespace.ts
│ ├── generate-service-docs.sh
│ ├── lines.sh
│ └── relative2alias.ts
├── vitest.config.ts
└── 文本节点功能分析.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .cursor/skills/create-keybind/SKILL.md
================================================
---
name: create-keybind
description: 指导如何在 Project Graph 项目中创建新的快捷键。当用户需要添加新的快捷键、修改快捷键绑定或需要了解快捷键系统的实现方式时使用此技能。
---
# 创建新的快捷键功能
本技能指导如何在 Project Graph 项目中创建新的快捷键。
## 创建快捷键的步骤
创建新快捷键需要完成以下 4 个步骤:
### 1. 在 shortcutKeysRegister.tsx 中注册快捷键
在 `app/src/core/service/controlService/shortcutKeysEngine/shortcutKeysRegister.tsx` 文件的 `allKeyBinds` 数组中添加新的快捷键定义。
**快捷键定义结构:**
```typescript
{
id: "uniqueKeybindId", // 唯一标识符,使用驼峰命名
defaultKey: "A-S-m", // 默认快捷键组合
onPress: (project?: Project) => void, // 按下时的回调函数
onRelease?: (project?: Project) => void, // 松开时的回调函数(可选)
isGlobal?: boolean, // 是否为全局快捷键(可选,默认 false)
isUI?: boolean, // 是否为 UI 级别快捷键(可选,默认 false)
defaultEnabled?: boolean, // 默认是否启用(可选,默认 true)
}
```
**快捷键键位格式:**
- `C-` = Ctrl (Windows/Linux) 或 Command (macOS)
- `A-` = Alt (Windows/Linux) 或 Option (macOS)
- `S-` = Shift
- `M-` = Meta (macOS 上等同于 Command)
- `F11`, `F12` 等 = 功能键
- `arrowup`, `arrowdown`, `arrowleft`, `arrowright` = 方向键
- `home`, `end`, `pageup`, `pagedown` = 导航键
- `space`, `enter`, `escape` = 特殊键
- 普通字母直接写,如 `m`, `t`, `k` 等
- 多个按键用空格分隔,如 `"t t t"` 表示连续按三次 t
**注意:** Mac 系统会自动将 `C-` 和 `M-` 互换,所以不需要手动处理平台差异。
**示例:**
```typescript
{
id: "setWindowToMiniSize",
defaultKey: "A-S-m", // Alt+Shift+M
onPress: async () => {
const window = getCurrentWindow();
// 执行操作
await window.setSize(new LogicalSize(width, height));
},
isUI: true, // UI 级别快捷键,不需要项目上下文
},
```
**快捷键类型说明:**
- **项目级快捷键(默认)**:需要项目上下文,`onPress` 会接收 `project` 参数
- **UI 级别快捷键(`isUI: true`)**:不需要项目上下文,可以在没有打开项目时使用
- **全局快捷键(`isGlobal: true`)**:使用 Tauri 全局快捷键系统,即使应用不在焦点也能触发
**使用 Tauri API 时的类型处理:**
如果快捷键需要使用 Tauri 窗口 API(如 `setSize`),需要导入正确的类型:
```typescript
import { getCurrentWindow } from "@tauri-apps/api/window";
import { LogicalSize } from "@tauri-apps/api/dpi"; // 或 PhysicalSize
// 使用 LogicalSize(推荐,会自动处理 DPI 缩放)
await window.setSize(new LogicalSize(width, height));
// 或使用 PhysicalSize(物理像素)
await window.setSize(new PhysicalSize(width, height));
```
### 2. 将快捷键添加到分组中
在 `app/src/sub/SettingsWindow/keybinds.tsx` 文件的 `shortcutKeysGroups` 数组中,将新快捷键的 `id` 添加到相应的分组数组中。
**分组结构:**
```typescript
export const shortcutKeysGroups: ShortcutKeysGroup[] = [
{
title: "basic", // 分组标识符(对应翻译文件中的 key)
icon: <Keyboard />, // 分组图标
keys: [ // 该分组包含的快捷键 ID 列表
"saveFile",
"openFile",
"undo",
"redo",
// ...
],
},
{
title: "ui", // UI 控制分组
icon: <AppWindow />,
keys: [
"closeAllSubWindows",
"toggleFullscreen",
"setWindowToMiniSize", // 添加新快捷键
// ...
],
},
// ... 其他分组
];
```
**可用分组:**
- `basic` - 基础快捷键(撤销、重做、保存、打开等)
- `camera` - 摄像机控制(移动、缩放、重置视野等)
- `app` - 应用控制(切换项目、切换模式等)
- `ui` - UI 控制(关闭窗口、全屏、窗口大小等)
- `draw` - 涂鸦相关
- `select` - 切换选择
- `moveEntity` - 移动实体
- `generateTextNodeInTree` - 生长节点
- `generateTextNodeRoundedSelectedNode` - 在选中节点周围生成节点
- `aboutTextNode` - 关于文本节点(分割、合并、创建等)
- `section` - Section 框相关
- `edge` - 连线相关
- `color` - 颜色相关
- `node` - 节点相关
**分组选择指南:**
- **UI 控制(`ui`)**:窗口管理、界面切换、全屏、窗口大小等
- **基础快捷键(`basic`)**:文件操作、编辑操作(撤销、重做、复制、粘贴等)
- **摄像机控制(`camera`)**:视野移动、缩放、重置等
- **应用控制(`app`)**:项目切换、模式切换等
- **文本节点相关(`aboutTextNode`)**:节点创建、分割、合并、编辑等
- **其他**:根据功能特性选择最合适的分组
**注意:** 如果快捷键不属于任何现有分组,可以:
1. 添加到最接近的现有分组
2. 创建新的分组(需要同时更新翻译文件)
### 3. 添加翻译文本
在所有语言文件中添加翻译:
- `app/src/locales/zh_CN.yml` - 简体中文
- `app/src/locales/zh_TW.yml` - 繁体中文
- `app/src/locales/en.yml` - 英文
- `app/src/locales/zh_TWC.yml` - 繁体中文(台湾)
- `app/src/locales/id.yml` - 印度尼西亚语
**翻译结构:**
在 `keyBinds` 部分添加:
```yaml
keyBinds:
keybindId:
title: "快捷键标题"
description: |
快捷键的详细描述
可以多行
说明快捷键的功能和使用场景
```
**示例:**
```yaml
keyBinds:
setWindowToMiniSize:
title: 设置窗口为迷你大小
description: |
将窗口大小设置为设置中配置的迷你窗口宽度和高度。
```
**翻译文件位置:**
- 简体中文:`app/src/locales/zh_CN.yml`
- 繁体中文:`app/src/locales/zh_TW.yml`
- 繁体中文(台湾):`app/src/locales/zh_TWC.yml`
- 英文:`app/src/locales/en.yml`
- 印度尼西亚语:`app/src/locales/id.yml`
**注意:**
- 翻译键名(`keybindId`)必须与快捷键定义中的 `id` 完全一致
- 所有语言文件都需要添加翻译,否则会显示默认值或键名
### 4. 更新分组翻译(如果需要创建新分组)
如果创建了新的快捷键分组,需要在所有语言文件的 `keyBindsGroup` 部分添加分组翻译:
```yaml
keyBindsGroup:
newGroupName:
title: "新分组标题"
description: |
分组的详细描述
说明该分组包含哪些类型的快捷键
```
**示例:**
```yaml
keyBindsGroup:
ui:
title: UI控制
description: |
用于控制UI的一些功能
```
## 快捷键类型详解
### 项目级快捷键(默认)
项目级快捷键需要项目上下文,`onPress` 函数会接收 `project` 参数:
```typescript
{
id: "myKeybind",
defaultKey: "C-k",
onPress: (project) => {
if (!project) {
toast.warning("请先打开工程文件");
return;
}
// 使用 project 进行操作
project.stageManager.doSomething();
},
}
```
### UI 级别快捷键
UI 级别快捷键不需要项目上下文,可以在没有打开项目时使用:
```typescript
{
id: "myUIKeybind",
defaultKey: "A-S-m",
onPress: async () => {
// 不需要 project 参数
const window = getCurrentWindow();
await window.setSize(new LogicalSize(300, 300));
},
isUI: true, // 标记为 UI 级别
}
```
### 全局快捷键
全局快捷键使用 Tauri 全局快捷键系统,即使应用不在焦点也能触发:
```typescript
{
id: "myGlobalKeybind",
defaultKey: "CommandOrControl+Shift+G",
onPress: () => {
// 全局快捷键逻辑
},
isGlobal: true, // 标记为全局快捷键
}
```
**注意:** 全局快捷键的键位格式与普通快捷键不同,使用 `CommandOrControl+Shift+G` 格式。
## 访问快捷键配置
在代码中访问快捷键配置:
```typescript
import { KeyBindsUI } from "@/core/service/controlService/shortcutKeysEngine/KeyBindsUI";
// 获取快捷键配置
const config = await KeyBindsUI.get("keybindId");
// 修改快捷键
await KeyBindsUI.changeOneUIKeyBind("keybindId", "new-key-combination");
// 重置所有快捷键
await KeyBindsUI.resetAllKeyBinds();
```
## 注意事项
1. **快捷键 ID 命名规范:** 使用驼峰命名法(camelCase),如 `setWindowToMiniSize`
2. **唯一性:** 快捷键 ID 必须唯一,不能与现有快捷键重复
3. **默认键位:** 选择不冲突的默认键位组合
4. **类型安全:** TypeScript 会自动推断类型,确保类型一致性
5. **翻译键名:** 翻译文件中的键名必须与快捷键的 `id` 完全一致
6. **分组必须:** 所有快捷键都必须添加到 `shortcutKeysGroups` 中的相应分组,否则不会在设置页面中显示
7. **分组选择:** 根据快捷键的功能特性选择合适的分组,保持设置页面的逻辑清晰
8. **Tauri API 类型:** 使用窗口 API 时,需要使用 `LogicalSize` 或 `PhysicalSize` 类型,不能直接使用普通对象
9. **Mac 兼容性:** Mac 系统会自动将 `C-` 和 `M-` 互换,无需手动处理
10. **UI vs 项目级:** 根据快捷键是否需要项目上下文选择合适的类型
## 完整示例
假设要添加一个"设置窗口为迷你大小"的快捷键:
**1. shortcutKeysRegister.tsx - 注册快捷键:**
```typescript
import { getCurrentWindow } from "@tauri-apps/api/window";
import { LogicalSize } from "@tauri-apps/api/dpi";
import { Settings } from "@/core/service/Settings";
export const allKeyBinds: KeyBindItem[] = [
// ... 其他快捷键
{
id: "setWindowToMiniSize",
defaultKey: "A-S-m",
onPress: async () => {
const window = getCurrentWindow();
// 如果当前是最大化状态,先取消最大化
if (await window.isMaximized()) {
await window.unmaximize();
store.set(isWindowMaxsizedAtom, false);
}
// 如果当前是全屏状态,先退出全屏
if (await window.isFullscreen()) {
await window.setFullscreen(false);
}
// 设置窗口大小为设置中的迷你窗口大小
const width = Settings.windowCollapsingWidth;
const height = Settings.windowCollapsingHeight;
await window.setSize(new LogicalSize(width, height));
},
isUI: true,
},
// ... 其他快捷键
];
```
**2. keybinds.tsx - 添加到分组:**
```typescript
export const shortcutKeysGroups: ShortcutKeysGroup[] = [
// ... 其他分组
{
title: "ui",
icon: <AppWindow />,
keys: [
"closeAllSubWindows",
"toggleFullscreen",
"setWindowToMiniSize", // 添加到 UI 控制分组
// ...
],
},
// ... 其他分组
];
```
**3. zh_CN.yml - 添加翻译:**
```yaml
keyBinds:
setWindowToMiniSize:
title: 设置窗口为迷你大小
description: |
将窗口大小设置为设置中配置的迷你窗口宽度和高度。
```
**4. 其他语言文件也需要添加相应翻译**
## 快捷键键位格式参考
**修饰键:**
- `C-` = Ctrl/Command
- `A-` = Alt/Option
- `S-` = Shift
- `M-` = Meta (macOS)
**特殊键:**
- `F1` - `F12` = 功能键
- `arrowup`, `arrowdown`, `arrowleft`, `arrowright` = 方向键
- `home`, `end`, `pageup`, `pagedown` = 导航键
- `space`, `enter`, `escape`, `tab`, `backspace`, `delete` = 特殊键
**组合示例:**
- `"C-s"` = Ctrl+S
- `"A-S-m"` = Alt+Shift+M
- `"C-A-S-t"` = Ctrl+Alt+Shift+T
- `"F11"` = F11
- `"C-F11"` = Ctrl+F11
- `"t t t"` = 连续按三次 T
- `"arrowup"` = 上方向键
- `"S-arrowup"` = Shift+上方向键
## 快捷键设置页面
快捷键添加到分组后,会在设置页面的"快捷键绑定"标签页中自动显示:
1. 用户可以在设置页面查看所有快捷键
2. 用户可以自定义快捷键键位
3. 用户可以启用/禁用快捷键
4. 用户可以重置快捷键为默认值
快捷键会自动保存到 `keybinds2.json` 文件中,并在应用重启后恢复。
================================================
FILE: .cursor/skills/create-setting-item/SKILL.md
================================================
---
name: create-setting-item
description: 指导如何在 Project Graph 项目中创建新的设置项。当用户需要添加新的设置项、配置选项或需要了解设置系统的实现方式时使用此技能。
---
# 创建新的设置项功能
本技能指导如何在 Project Graph 项目中创建新的设置项。
## 创建设置项的步骤
创建新设置项需要完成以下 5 个步骤:
### 1. 在 Settings.tsx 中添加 Schema 定义
在 `app/src/core/service/Settings.tsx` 文件的 `settingsSchema` 对象中添加新的设置项定义。
**支持的 Zod 类型:**
- `z.boolean().default(false)` - 布尔值开关
- `z.number().min(x).max(y).default(z)` - 数字(可添加 `.int()` 限制为整数)
- `z.string().default("")` - 字符串
- `z.union([z.literal("option1"), z.literal("option2")]).default("option1")` - 枚举选择
- `z.tuple([z.number(), z.number(), z.number(), z.number()]).default([0,0,0,0])` - 元组(如颜色 RGBA)
**示例:**
```typescript
// 布尔值设置
enableNewFeature: z.boolean().default(false),
// 数字范围设置(带滑块)
newSliderValue: z.number().min(0).max(100).int().default(50),
// 枚举选择设置
newMode: z.union([z.literal("mode1"), z.literal("mode2")]).default("mode1"),
```
### 2. 在 SettingsIcons.tsx 中添加图标
在 `app/src/core/service/SettingsIcons.tsx` 文件的 `settingsIcons` 对象中添加对应的图标。
**步骤:**
1. 从 `lucide-react` 导入合适的图标组件
2. 在 `settingsIcons` 对象中添加映射:`settingKey: IconComponent`
**示例:**
```typescript
import { NewIcon } from "lucide-react";
export const settingsIcons = {
// ... 其他设置项
enableNewFeature: NewIcon,
};
```
### 3. 添加翻译文本
在所有语言文件中添加翻译:
- `app/src/locales/zh_CN.yml` - 简体中文
- `app/src/locales/zh_TW.yml` - 繁体中文
- `app/src/locales/en.yml` - 英文
- `app/src/locales/zh_TWC.yml` - 接地气繁体中文
- `app/src/locales/id.yml` - 印度尼西亚语
**翻译结构:**
```yaml
settings:
settingKey:
title: "设置项标题"
description: |
设置项的详细描述
可以多行
options: # 仅枚举类型需要
option1: "选项1显示文本"
option2: "选项2显示文本"
```
**示例:**
```yaml
settings:
enableNewFeature:
title: "启用新功能"
description: |
开启后将启用新功能特性。
此功能可能会影响性能。
newMode:
title: "新模式"
description: "选择新的模式选项"
options:
mode1: "模式一"
mode2: "模式二"
```
### 4. 将设置项添加到分组中
在 `app/src/sub/SettingsWindow/settings.tsx` 文件的 `categories` 对象中,将新设置项的键名添加到相应的分组数组中。
**分组结构:**
```typescript
const categories = {
visual: { // 一级分类:视觉
basic: [...], // 二级分组:基础
background: [...], // 二级分组:背景
node: [...], // 二级分组:节点样式
// ...
},
automation: { // 一级分类:自动化
autoNamer: [...],
autoSave: [...],
// ...
},
control: { // 一级分类:控制
mouse: [...],
cameraMove: [...],
// ...
},
performance: { // 一级分类:性能
memory: [...],
cpu: [...],
// ...
},
ai: { // 一级分类:AI
api: [...],
},
};
```
**添加设置项到分组:**
```typescript
const categories = {
visual: {
basic: [
"language",
"isClassroomMode",
"enableNewFeature", // 添加新设置项
// ...
],
},
// ...
};
```
**分组选择指南:**
- **visual(视觉)**:界面显示、主题、背景、节点样式、连线样式等
- `basic`: 基础视觉设置
- `background`: 背景相关设置
- `node`: 节点样式设置
- `edge`: 连线样式设置
- `section`: Section 框的样式设置
- `entityDetails`: 实体详情面板设置
- `debug`: 调试相关设置
- `miniWindow`: 迷你窗口设置
- `experimental`: 实验性视觉功能
- **automation(自动化)**:自动保存、自动备份、自动命名等
- `autoNamer`: 自动命名相关
- `autoSave`: 自动保存相关
- `autoBackup`: 自动备份相关
- `autoImport`: 自动导入相关
- **control(控制)**:鼠标、键盘、触摸板、相机控制等
- `mouse`: 鼠标相关设置
- `touchpad`: 触摸板设置
- `cameraMove`: 相机移动设置
- `cameraZoom`: 相机缩放设置
- `objectSelect`: 对象选择设置
- `textNode`: 文本节点编辑设置
- `edge`: 连线操作设置
- `generateNode`: 节点生成设置
- `gamepad`: 游戏手柄设置
- **performance(性能)**:内存、CPU、渲染性能相关
- `memory`: 内存相关设置
- `cpu`: CPU 相关设置
- `render`: 渲染相关设置
- `experimental`: 实验性性能功能
- **ai(AI)**:AI 相关设置
- `api`: AI API 配置
**注意:** 如果设置项不属于任何现有分组,可以:
1. 添加到最接近的现有分组
2. 在相应分类下创建新的分组(需要同时更新翻译文件中的分类结构)
### 5. 在设置页面中使用 SettingField 组件
设置项添加到分组后,会在设置页面的相应分组中自动显示。如果需要手动渲染或添加额外内容,可以使用 `SettingField` 组件:
**基本用法:**
```tsx
import { SettingField } from "@/components/ui/field";
<SettingField settingKey="enableNewFeature" />;
```
**带额外内容的用法:**
```tsx
<SettingField settingKey="enableNewFeature" extra={<Button>额外按钮</Button>} />
```
**注意:** 大多数情况下,只需要将设置项添加到 `categories` 中即可,设置页面会自动渲染。只有在需要特殊布局或额外功能时才需要手动使用 `SettingField` 组件。
## SettingField 组件的自动类型推断
`SettingField` 组件会根据 schema 定义自动渲染对应的 UI 控件:
- **字符串类型** → `Input` 输入框
- **数字类型(有 min/max)** → `Slider` 滑块 + `Input` 数字输入框
- **数字类型(无范围)** → `Input` 数字输入框
- **布尔类型** → `Switch` 开关
- **枚举类型(Union)** → `Select` 下拉选择框
## 访问设置值
在代码中访问设置值:
```typescript
import { Settings } from "@/core/service/Settings";
// 读取设置值
const value = Settings.enableNewFeature;
// 修改设置值
Settings.enableNewFeature = true;
// 监听设置变化(返回取消监听的函数)
const unsubscribe = Settings.watch("enableNewFeature", (newValue) => {
console.log("设置已更改:", newValue);
});
// React Hook 方式(在组件中使用)
const [value, setValue] = Settings.use("enableNewFeature");
```
## 注意事项
1. **设置项键名命名规范:** 使用驼峰命名法(camelCase),如 `enableNewFeature`
2. **默认值:** 所有设置项都必须提供默认值(`.default()`)
3. **类型安全:** TypeScript 会自动推断类型,确保类型一致性
4. **持久化:** 设置值会自动保存到 `settings.json` 文件中
5. **翻译键名:** 翻译文件中的键名必须与设置项的键名完全一致
6. **图标可选:** 如果不需要图标,可以不在 `settingsIcons` 中添加,组件会使用 Fragment
7. **分组必须:** 所有设置项都必须添加到 `categories` 对象中的相应分组,否则不会在设置页面中显示
8. **分组选择:** 根据设置项的功能特性选择合适的分类和分组,保持设置页面的逻辑清晰
## 完整示例
假设要添加一个"启用暗色模式"的设置项:
**1. Settings.tsx:**
```typescript
export const settingsSchema = z.object({
// ... 其他设置项
enableDarkMode: z.boolean().default(false),
});
```
**2. SettingsIcons.tsx:**
```typescript
import { Moon } from "lucide-react";
export const settingsIcons = {
// ... 其他设置项
enableDarkMode: Moon,
};
```
**3. zh_CN.yml:**
```yaml
settings:
enableDarkMode:
title: "启用暗色模式"
description: "开启后将使用暗色主题界面"
```
**4. settings.tsx - 添加到分组:**
```typescript
const categories = {
visual: {
basic: [
"language",
"isClassroomMode",
"enableDarkMode", // 添加到基础视觉设置分组
// ...
],
// ...
},
// ...
};
```
**5. 设置项会自动显示:**
设置项添加到 `categories` 后,会在设置页面的"视觉 > 基础"分组中自动显示,无需手动使用 `SettingField` 组件。
## 快捷设置栏支持
如果希望设置项出现在快捷设置栏(Quick Settings Toolbar)中,需要:
1. 确保设置项已正确创建(完成上述 4 步)
2. 快捷设置栏会自动显示所有布尔类型的设置项
3. 可以通过 `QuickSettingsManager.addQuickSetting()` 手动添加非布尔类型的设置项
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
- 2y.nz/pgdonate
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
#blank_issues_enabled: false
================================================
FILE: .github/ISSUE_TEMPLATE/no-issues.yml
================================================
name: 不要创建 Issue,请前往 Disscussions!
description: 不要创建issue
body:
- type: checkboxes
attributes:
label: 不要创建 Issue,请前往 Disscussions
description: 鉴于大量低质量和重复的issue,从2025年7月开始,用户不可以自行创建issue
options:
- label: 我希望这个issue被删除
required: true
- label: "[点这里前往Disscussions](https://github.com/graphif/project-graph/discussions/new/choose)"
required: true
================================================
FILE: .github/copilot-instructions.md
================================================
## Project Background
Github Repository: `graphif/project-graph`
Project Graph is a desktop application designed to visualize and manage complex project structures. It allows users to create, edit, and visualize project graphs, making it easier to understand relationships and dependencies within projects.
## Coding guidelines
- Prioritize code correctness and clarity. Speed and efficiency are secondary priorities unless otherwise specified.
- Do not write organizational or comments that summarize the code. Comments should only be written in order to explain "why" the code is written in some way in the case there is a reason that is tricky / non-obvious.
- Prefer implementing functionality in existing files unless it is a new logical component. Avoid creating many small files.
- Never silently discard errors with `catch {}` or `catch (e) { console.error(e) }` on fallible operations. Always handle errors appropriately:
- Don't catch errors, let the calling function to handle them
- If the error should be ignored, show a dialog instead of logging to console. User cannot see logs in the console.
- Ensure errors propagate to the top of DOM (eg. `window`), so `ErrorHandler` component can catch it and show an user-friendly dialog
- Example: avoid `try { something() } catch (e) { console.error(e) }` - use `something()` instead
- Always use `something.tsx` instead of a single `index.tsx` in a directory.
## Tech-stack
- React (TypeScript) + Tauri (Rust)
- Vite + pnpm (monorepo) + turborepo
- Canvas 2D
- shadcn/ui + Tailwind CSS + self-developed sub-window system
- Jotai
## Structure
### Tauri Application, and Frontend
- Frontend Vite project: `/app`
- Rust Project: `/app/src-tauri`
### Fumadocs
- Next.js Project: `/docs`
- Content: `/docs/content/docs`
### Open-source Libraries
They are all in `/packages` directory, and are used in the frontend.
## Trade time for space
Trade time for space, meaning that you should use more **storage** (not memory!) to reduce computation time
## RFCs
The `tasks` the user refers to are **RFCs**. These RFCs are usually tracked in the repository’s Issues and their titles begin with `RFC:`.
A user **cannot** take on tasks that are irrelevant to their own system. For example, a Linux user **cannot** complete a task that exists only on macOS.
When the user asks which tasks remain unfinished, you must
- assign **a unique number** to every task
- sort the list by a combined score of **importance × implementation difficulty**,
so the user can easily tell you to tick the finished items in the corresponding RFCs.
## Commit Message
Use conventional commits
================================================
FILE: .github/scripts/enable-sourcemap.mjs
================================================
import { readFileSync, writeFileSync } from "fs";
const VITE_CONFIG_PATH = "app/vite.config.ts";
const conf = readFileSync(VITE_CONFIG_PATH);
const updated = conf.toString().replace("sourcemap: false", "sourcemap: true");
writeFileSync(VITE_CONFIG_PATH, updated);
console.log(updated);
================================================
FILE: .github/scripts/generate-changelog.mjs
================================================
/* eslint-disable */
import { execSync } from "child_process";
// 获取最近一次发布的标签
const lastRelease = execSync(
"git for-each-ref --sort=-creatordate --format='%(refname:short)' \"refs/tags/v*\" | head -n 1",
)
.toString()
.trim();
// 获取 Git 提交记录
const commits = execSync(`git log ${lastRelease}.. --pretty=format:"%s" --reverse`).toString().trim();
/**
* 生成降级版本的changelog(直接使用commit标题)
* @param {string} commits - commit标题列表,用换行分隔
* @returns {string} 格式化的changelog
*/
function generateFallbackChangelog(commits) {
if (!commits || commits.trim() === "") {
return "## 更新内容\n\n本次更新暂无变更记录。";
}
const commitList = commits
.split("\n")
.filter((line) => line.trim() !== "")
.map((commit) => `- ${commit}`)
.join("\n");
return `## 更新内容
> ⚠️ 注意:由于AI总结更新的内容服务不可用,以下内容为直接提取的commit记录
${commitList}
`;
}
// 定义提示信息
const prompt = `
你是一个专业的软件文档撰写助手,负责将开发团队提供的commit历史记录转换为用户友好的更新日志(Changelog)。用户会提供git历史记录信息。
你的任务是生成一篇清晰、简洁的Changelog,面向最终用户(非技术人员),避免使用技术术语,专注于用户能直接感知的变更。请遵循以下规则:
1. **理解commit类型**:
- \`feat\` / \`feature\`:新功能,归类为“新功能”。
- \`fix\` / \`hotfix\`:问题修复,归类为“问题修复”。
- \`docs\`:文档或内容更新,归类为“文档和内容更新”。
- \`chore\`:界面优化、配置调整或内部改进,归类为“改进和优化”(重点描述用户可见的变化)。
- 其他类型根据描述推断,确保归类合理。
2. **组织Changelog结构**:
- 按类别分组commit(如“问题修复”、“文档和内容更新”、“改进和优化”等),每个类别使用子标题。
- 每个类别下用项目符号列表描述变更,语言口语化、正面积极(例如:用“修复了...问题”而非“修复bug”)。
- 如果多个commit相似,可合并描述以提高可读性。
3. **输出格式**:
- 使用中文。
- 保持段落清晰,无需编号,但使用标题和项目符号。
- 开头不要有 \`## 更新日志\`,直接开始更新内容。
- 从二级标题开始(例如:\`## 新功能\`)。
请直接输出Changelog内容,无需额外解释。
## Example
\`\`\`
## 新功能
增加穿透点击功能,全局快捷键Alt+2可以开关窗口穿透,穿透点击开启后,副作用是会自动将透明度设置为0.2且自动打开窗口置顶
标签面板可以正常打开了,且增加标签管理器UI分裂功能,每一个标签都能分裂成一个可拖拽与改变大小的独立子窗口,且点击能够对准对应的节点
rua时,可以输入自定义连接符,如果输入了换行符作为连接,则rua出来的节点的换行策略会自动变为手动调整宽度模式
增加手动保存时是否自动清理历史记录的设置项
完成自动保存功能
完成自动备份功能
## 操作优化
修复最后一个实体跳出框时,框附带移动到实体附近的bug
section中最后一个节点跳出框时,自动变为文本节点
## 视觉/交互优化
alt跳入框时,显示框会变大多少的虚线边缘
右键菜单中增加文本节点妙操作
开启穿透点击时,自动半透明窗口
给子窗口增加shadow
按住ctrl或者shift框选加选或者叉选时,增加视觉提示
给特效界面增加提示
## Bug修复
修复涂鸦后没有记录历史的问题
防止一开始启动软件视野缩放过大
暂时修复详细信息报错问题
\`\`\`
`;
// 发送请求到 API
try {
const response = await fetch(
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=" +
process.env.GEMINI_API_KEY,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
system_instruction: {
parts: [
{
text: prompt,
},
],
},
contents: [
{
parts: [
{
text: commits,
},
],
},
],
}),
},
);
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const data = await response.json();
const changelog = data.candidates[0].content.parts[0].text;
const finalChangelog = `以下内容为AI根据git历史自动生成总结,不保证完全准确
${changelog}
`;
console.log(finalChangelog);
} catch (err) {
console.error("AI生成changelog失败,使用降级方案:", err.message);
// 降级方案:直接输出commit列表
const fallbackChangelog = generateFallbackChangelog(commits);
console.log(fallbackChangelog);
}
================================================
FILE: .github/scripts/generate-pkgbuild.mjs
================================================
/* eslint-disable */
import { writeFileSync } from "fs";
// 命令行参数:
// node ./generate-pkgbuild.mjs <pkgname> <pkgver> <sha256sums>
const pkgname = process.argv[2];
const pkgver = process.argv[3];
const sha256sums = process.argv[4];
if (!pkgname || !pkgver || !sha256sums) {
console.error("Usage: node generate-pkgbuild.mjs <pkgname> <pkgver> <sha256sums>");
process.exit(1);
}
const conflicts =
pkgname === "project-graph-nightly-bin"
? ["project-graph-bin", "project-graph-git"]
: ["project-graph-nightly-bin", "project-graph-git"];
const source =
pkgname === "project-graph-nightly-bin"
? `https://github.com/LiRenTech/project-graph/releases/download/nightly/Project.Graph_0.0.0-nightly.${pkgver.slice(1)}_amd64.deb`
: `https://github.com/LiRenTech/project-graph/releases/download/v${pkgver}/Project.Graph_${pkgver}_amd64.deb`;
const PKGBUILD = `# Maintainer: zty012 <me@zty012.de>
pkgname=${pkgname}
pkgver=${pkgver.replaceAll("-", ".")}
pkgrel=1
pkgdesc="A simple tool to create topology diagrams."
arch=('x86_64')
url="https://github.com/LiRenTech/project-graph"
license=('mit')
depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk')
options=('!strip' '!emptydirs')
provides=('project-graph')
conflicts=(${conflicts.map((x) => `'${x}'`).join(" ")})
install=${pkgname}.install
source_x86_64=('${source}')
sha256sums_x86_64=('${sha256sums}')
package() {
# Extract package data
tar -xz -f data.tar.gz -C "\${pkgdir}"
}
`;
console.log("===== PKGBUILD =====");
console.log(PKGBUILD);
writeFileSync("./PKGBUILD", PKGBUILD);
const SRCINFO = `pkgbase = ${pkgname}
\tpkgdesc = A simple tool to create topology diagrams.
\tpkgver = ${pkgver.replaceAll("-", ".")}
\tpkgrel = 1
\turl = https://github.com/LiRenTech/project-graph
\tinstall = ${pkgname}.install
\tarch = x86_64
\tlicense = mit
\tdepends = cairo
\tdepends = desktop-file-utils
\tdepends = gdk-pixbuf2
\tdepends = glib2
\tdepends = gtk3
\tdepends = hicolor-icon-theme
\tdepends = libsoup
\tdepends = pango
\tdepends = webkit2gtk
\tprovides = project-graph
${conflicts.map((x) => `\tconflicts = ${x}`).join("\n")}
\toptions = !strip
\toptions = !emptydirs
\tsource_x86_64 = ${source}
\tsha256sums_x86_64 = ${sha256sums}
pkgname = ${pkgname}`;
console.log("===== .SRCINFO =====");
console.log(SRCINFO);
writeFileSync("./.SRCINFO", SRCINFO);
================================================
FILE: .github/scripts/set-tauri-features.mjs
================================================
/* eslint-disable */
import { readFileSync, writeFileSync } from "fs";
const features = process.argv[2].split(",");
const CARGO_TOML_PATH = "app/src-tauri/Cargo.toml";
const conf = readFileSync(CARGO_TOML_PATH);
const updated = conf
.toString()
.replace(
/tauri = { version = "(.*)", features = \["(.*)"\] }/,
`tauri = { version = "$1", features = ["macos-private-api", "${features.join('", "')}"] }`,
);
writeFileSync(CARGO_TOML_PATH, updated);
console.log(updated);
================================================
FILE: .github/scripts/set-version.mjs
================================================
/* eslint-disable */
import { readFileSync, writeFileSync } from "fs";
const version = process.argv[2];
const TAURI_CONF_PATH = "app/src-tauri/tauri.conf.json";
const conf = JSON.parse(readFileSync(TAURI_CONF_PATH));
conf.version = version;
writeFileSync(TAURI_CONF_PATH, JSON.stringify(conf, null, 2));
console.log(conf);
================================================
FILE: .github/workflows/nightly.yml
================================================
name: "Nightly"
run-name: "Nightly ${{ github.run_number }}"
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
build:
permissions:
contents: write
uses: ./.github/workflows/publish.yml
with:
android_key_alias: "upload"
android_key_path: "upload.jks"
app_version: 0.0.0-nightly.${{ github.run_number }}
app_version_android: 0.0.${{ github.run_number }}
aur_version: r${{ github.run_number }}
aur_key_algorithm: "ed25519"
aur_package_name: "project-graph-nightly-bin"
delete_release: true
prerelease: true
release_name: Nightly ${{ inputs.version }}
release_tag: nightly
task_build: build:ci
# task_build_android: build
include_devtools: true
secrets:
ANDROID_KEYSTORE: ${{ secrets.ANDROID_RELEASE_KEYSTORE }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_RELEASE_PASSWORD }}
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish
on:
workflow_call:
inputs:
app_version:
type: string
description: The version of the app.
required: false
default: "0.0.0"
app_version_android:
type: string
description: The version of the app for Android, CANNOT be `0.0.0`
required: true
release_name:
type: string
description: The name of the release.
required: false
default: Release
release_tag:
type: string
description: The tag to use for the release.
required: true
prerelease:
type: boolean
description: Whether to make the release a prerelease.
required: false
default: false
delete_release:
type: boolean
description: Whether to delete the release.
required: false
default: true
android_key_path:
type: string
description: The path to the Android key file, relative to app_root
required: false
default: "upload.jks"
aur_package_name:
type: string
description: The name of the AUR package.
required: false
default: ""
aur_key_algorithm:
type: string
description: The algorithm to use for the AUR key.
required: false
default: "ed25519"
aur_version:
type: string
description: The version of the AUR package.
required: true
task_build:
type: string
description: The task to run for building the app.
required: false
default: "tauri:build"
task_build_android:
type: string
description: The task to run for building the app for Android.
required: false
default: "tauri:build:android"
android_key_alias:
type: string
description: The alias of the Android key.
required: false
default: "upload"
include_devtools:
type: boolean
description: Whether to include devtools in the build.
required: false
default: false
secrets:
TAURI_SIGNING_PRIVATE_KEY:
description: Sign app binaries for updater support.
required: false
TAURI_SIGNING_PRIVATE_KEY_PASSWORD:
description: Password for the signing key.
required: false
ANDROID_KEYSTORE:
description: Base64 of `jks` file for APK signing.
required: false
ANDROID_KEYSTORE_PASSWORD:
description: Password for the keystore.
required: false
BUILD_ENV:
description: "Environment variables to pass to `tauri build`. Format: `key1=value1\\nkey2=value2\\n...`."
required: false
AUR_SSH_PRIVATE_KEY:
description: "SSH private key for AUR publishing."
required: false
GEMINI_API_KEY:
description: Authenticate Google Gemini to generate changelog.
required: false
jobs:
create-release:
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
- name: Install dependencies
run: npm i -g node-fetch
- name: Delete release
if: inputs.delete_release == true
run: |
gh release delete ${{ inputs.release_tag }} --yes --cleanup-tag || true
sleep 1
- name: Create release
env:
tag: ${{ inputs.release_tag }}
name: ${{ inputs.release_name }}
branch: ${{ github.ref_name }}
run: |
notes=$(GEMINI_API_KEY="${{ secrets.GEMINI_API_KEY }}" node ./.github/scripts/generate-changelog.mjs)
gh release create "$tag" --target "$branch" --title "$name" --notes "$notes" ${{ inputs.prerelease == true && '--prerelease' || '' }}
publish-tauri:
needs: [create-release]
outputs:
hash: ${{ steps.sha256sum.outputs.hash }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: "ubuntu-22.04"
dist: "src-tauri/target/release/bundle/**/*.{deb,AppImage,rpm,sig}"
- platform: "windows-latest"
dist: "src-tauri/target/release/bundle/nsis"
- platform: "macos-latest"
args: "--target universal-apple-darwin"
rust_targets: "aarch64-apple-darwin,x86_64-apple-darwin"
dist: "src-tauri/target/universal-apple-darwin/release/bundle/**/*.{dmg,tar.gz,sig}"
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
#region Prepare environment
- name: Linux - Install dependencies
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libudev-dev
- uses: pnpm/action-setup@v4
id: pnpm
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: "pnpm"
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_targets }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: "app/src-tauri -> target"
#endregion
#region Android - Prepare environment
- name: Android - Setup Java
if: matrix.android
uses: actions/setup-java@v4
with:
distribution: "zulu"
java-version: "17"
- name: Android - Setup Android SDK
if: matrix.android
uses: android-actions/setup-android@v3
- name: Android - Setup Android NDK
if: matrix.android
run: sdkmanager "ndk;27.0.11902837"
- name: Android - Setup Android APK Signing
if: matrix.android
run: |
cd app/src-tauri/gen/android
cat > keystore.properties <<EOF
password=${{ secrets.ANDROID_RELEASE_PASSWORD }}
keyAlias=${{ inputs.android_key_alias }}
storeFile=${{ inputs.android_key_path }}
EOF
echo "${{ secrets.ANDROID_RELEASE_KEYSTORE }}" | base64 --decode > app/${{ inputs.android_key_path }}
#endregion
#region Edit version
- name: Set app version
if: ${{ !matrix.android && !matrix.variant }}
run: |
node ./.github/scripts/set-version.mjs ${{ inputs.app_version }}
- name: Set app version when variant exists
if: ${{ !matrix.android && matrix.variant }}
run: |
node ./.github/scripts/set-version.mjs ${{ inputs.app_version }}-${{ matrix.variant }}
- name: Enable DevTools
if: ${{ inputs.include_devtools }}
run: |
node ./.github/scripts/set-tauri-features.mjs devtools
node ./.github/scripts/enable-sourcemap.mjs
- name: Android - Set app version
if: matrix.android
run: |
node ./.github/scripts/set-version.mjs ${{ inputs.app_version_android }}
- name: Variant - win7
if: matrix.variant == 'win7'
run: |
(Get-Content ./app/src-tauri/tauri.conf.json).Replace('downloadBootstrapper', 'embedBootstrapper') | Set-Content ./app/src-tauri/tauri.conf.json
cat ./app/src-tauri/tauri.conf.json
#endregion
#region Build
- name: Write BUILD_ENV to .env file
if: matrix.variant != 'foss'
run: |
echo "${{ secrets.BUILD_ENV }}" > app/.env
- name: Build
run: |
pnpm run ${{ matrix.android && inputs.task_build_android || inputs.task_build }}
env:
TAURI_BUILD_ARGS: ${{ matrix.args }}
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/27.0.11902837
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
- name: MacOS - Rename app.tar.gz
if: matrix.platform == 'macos-latest'
run: |
cd app/src-tauri/target/*/release/bundle/macos
mv *.app.tar.gz "Project Graph_${{ inputs.app_version }}_universal.app.tar.gz"
mv *.app.tar.gz.sig "Project Graph_${{ inputs.app_version }}_universal.app.tar.gz.sig"
- name: Linux - Rename rpm
if: matrix.platform == 'ubuntu-22.04'
run: |
cd app/src-tauri/target/release/bundle/rpm
mv *.rpm "Project Graph_${{ inputs.app_version }}_amd64.rpm"
- name: Linux / MacOS - Upload
if: matrix.platform != 'windows-latest'
run: |
gh release upload ${{ inputs.release_tag }} app/${{ matrix.dist }} --clobber
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Windows - Upload
if: matrix.platform == 'windows-latest'
run: |
gh release upload ${{ inputs.release_tag }} (Get-Item .\app\${{ matrix.dist }}\*.exe).FullName --clobber
gh release upload ${{ inputs.release_tag }} (Get-Item .\app\${{ matrix.dist }}\*.sig).FullName --clobber
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- id: sha256sum
name: Linux - Calculate SHA256 hash for AUR package
if: matrix.platform == 'ubuntu-22.04'
run: |
cd app/src-tauri/target/release/bundle/deb
sha256sum ./*.deb | awk '{print $1}' > sha256sum.txt
echo "hash=$(cat sha256sum.txt)" >> "$GITHUB_OUTPUT"
#endregion
# publish-tauri-linux-arm:
# runs-on: ubuntu-22.04
# needs: [create-release, build-frontend]
# permissions:
# contents: write
# strategy:
# matrix:
# arch: [aarch64]
# include:
# - arch: aarch64
# cpu: cortex-a72
# base_image: https://dietpi.com/downloads/images/DietPi_RPi5-ARMv8-Bookworm.img.xz
# deb: arm64
# rpm: aarch64
# appimage: aarch64
# # - arch: armv7l
# # cpu: cortex-a53
# # deb: armhfp
# # rpm: arm
# # appimage: armhf
# # base_image: https://dietpi.com/downloads/images/DietPi_RPi-ARMv7-Bookworm.img.xz
# steps:
# - uses: actions/checkout@v3
# - name: Cache rust build artifacts
# uses: Swatinem/rust-cache@v2
# with:
# workspaces: src-tauri
# cache-on-failure: true
# - name: Build app
# uses: pguyot/arm-runner-action@v2.6.5
# with:
# base_image: ${{ matrix.base_image }}
# cpu: ${{ matrix.cpu }}
# bind_mount_repository: true
# image_additional_mb: 10240
# optimize_image: no
# #exit_on_fail: no
# commands: |
# # Prevent Rust from complaining about $HOME not matching eid home
# export HOME=/root
# # Workaround to CI worker being stuck on Updating crates.io index
# export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
# # Install setup prerequisites
# apt-get update -y --allow-releaseinfo-change
# apt-get autoremove -y
# apt-get install -y --no-install-recommends --no-install-suggests curl libwebkit2gtk-4.1-dev build-essential libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev patchelf libfuse2 file
# curl https://sh.rustup.rs -sSf | sh -s -- -y
# . "$HOME/.cargo/env"
# # Install Node.js
# curl -fsSL https://deb.nodesource.com/setup_lts.x | bash
# apt-get install -y nodejs
# # Install frontend dependencies
# npm i -g pnpm
# pnpm i
# # Build the application
# pnpm tauri:build
# - name: Upload
# run: |
# gh release upload ${{ inputs.release_tag }} app/src-tauri/target/release/bundle/*.{deb,rpm,AppImage} --clobber
# env:
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
bump-aur-version:
needs: publish-tauri
runs-on: ubuntu-latest
if: inputs.aur_package_name != ''
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
- name: Setup AUR private key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.AUR_SSH_PRIVATE_KEY }}" > ~/.ssh/id_${{ inputs.aur_key_algorithm }}
chmod 600 ~/.ssh/id_${{ inputs.aur_key_algorithm }}
ssh-keyscan -t "${{ inputs.aur_key_algorithm }}" aur.archlinux.org >> ~/.ssh/known_hosts
- name: Clone AUR repository
run: git clone ssh://aur@aur.archlinux.org/${{ inputs.aur_package_name }}.git ./aurpackage
- name: Update version in PKGBUILD and .SRCINFO
env:
repo: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd aurpackage
node ../.github/scripts/generate-pkgbuild.mjs ${{ inputs.aur_package_name }} ${{ inputs.aur_version }} ${{ needs.publish-tauri.outputs.hash }}
- name: Commit and push changes
run: |
cd aurpackage
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add PKGBUILD .SRCINFO
git commit -m "Bump version to ${{ inputs.app_version }}"
git push origin master
================================================
FILE: .github/workflows/release.yml
================================================
name: "Release"
run-name: "v${{ inputs.version }}"
on:
workflow_dispatch:
inputs:
version:
description: "应用版本 (x.y.z)"
required: true
prerelease:
type: boolean
description: "Is pre-release"
required: false
default: false
delete_release:
type: boolean
description: "删除以前的release"
required: false
default: false
jobs:
build:
permissions:
contents: write
uses: ./.github/workflows/publish.yml
with:
android_key_alias: "upload"
android_key_path: "upload.jks"
app_version: ${{ inputs.version }}
app_version_android: ${{ inputs.version }}
aur_version: ${{ inputs.version }}
aur_key_algorithm: "ed25519"
aur_package_name: "project-graph-bin"
delete_release: ${{ inputs.delete_release }}
prerelease: ${{ inputs.prerelease }}
release_name: "v${{ inputs.version }}"
release_tag: "v${{ inputs.version }}"
task_build: build:ci
# task_build_android: "tauri:build:android"
secrets:
ANDROID_KEYSTORE: ${{ secrets.ANDROID_RELEASE_KEYSTORE }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_RELEASE_PASSWORD }}
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
BUILD_ENV: |
LR_API_BASE_URL=${{ secrets.ENV_API_BASE_URL }}
LR_GITHUB_CLIENT_SECRET=${{ secrets.ENV_GITHUB_CLIENT_SECRET }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
================================================
FILE: .github/workflows/render-docs-svg.yml
================================================
name: Render files in ./docs-pg to SVG
on:
push:
branches:
- master
paths:
- "docs-pg/**"
workflow_dispatch:
jobs:
render-svg:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v2
- name: Install Project Graph
run: |
gh release download -p "*.deb" -O project-graph.deb --clobber
sudo apt-get update
sudo apt-get install -y ./project-graph.deb
rm -rf ./project-graph.deb
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install xvfb
run: sudo apt-get install -y xvfb
- name: Render SVG files
run: |
cd docs-pg
for file in *.json; do
echo "Rendering $file"
xvfb-run -a project-graph "$file" -o "${file%.json}.svg"
done
- name: Commit files
run: |
git add .
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git commit -a -m "📝 Render SVG files"
git pull
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
================================================
FILE: .gitignore
================================================
node_modules
dist
.env
.idea
storybook-static
.swc
docs/src/.vitepress/dist
docs/src/.vitepress/cache
docs/src/.vitepress/.temp
# pg早期的备份文件
*.backup
# 自动保存导致产生的文件
app/src-tauri/Project Graph
backup_projectGraphTips
*.backup.json
# 省略文件夹
backup_*
.turbo
# mac下开发需要忽略
.DS_Store
.nx/cache
.nx/workspace-data
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md
================================================
FILE: .husky/pre-commit
================================================
pnpm lint-staged
================================================
FILE: .lintstagedrc
================================================
{
"*.{ts,tsx}": ["eslint --fix"],
"*.{json,md,yaml,yml,ts,tsx}": ["prettier --write"]
}
================================================
FILE: .prettierignore
================================================
#app/src-tauri
# 防止翻译总是被格式化
app/src/locales/*.yml
# 这个基本不会被手动修改
router.ts
vite-env.d.ts
# prettier不支持mdx3.0
# *.mdx
dist
.next
out
LICENSE
app/src-tauri/gen
app/src-tauri/target
app/src/css/theme.pcss
================================================
FILE: .prettierrc
================================================
{
"plugins": ["prettier-plugin-tailwindcss"],
"printWidth": 120
}
================================================
FILE: .trae/documents/plan_20251223_165257.md
================================================
1. **添加upgradeNAnyToNLatest函数**:
- 在ProjectUpgrader namespace中添加upgradeNAnyToNLatest函数
- 该函数用于升级N版本的prg文件到最新版本
- 内部调用convertN1toN2等转换函数
2. **添加convertN1toN2转换函数**:
- 该函数用于将N1版本升级到N2版本
- 为LineEdge添加lineType属性,默认值为'solid'
- 确保升级逻辑正确处理所有实体
3. **在prg文件中增加metadata.msgpack**:
- 修改保存prg文件的逻辑,添加metadata.msgpack
- metadata.msgpack中包含dataVersion和dataVersionType字段
- dataVersion初始值为2(N2版本),dataVersionType为'N'
- 在升级时更新dataVersion字段
4. **更新相关调用**:
- 确保在保存和加载prg文件时正确处理metadata
- 在升级过程中更新dataVersion字段
5. **测试和验证**:
- 确保升级逻辑正确
- 确保metadata.msgpack被正确添加到prg文件中
- 确保lineType属性被正确处理
================================================
FILE: .trae/documents/plan_20260101_170503.md
================================================
1. **修改现有的重置按钮**
* 添加确认弹窗,用户确认后才执行重置
* 更新按钮文本,添加提醒信息
* 确保重置时同时重置快捷键值和启用状态
2. **添加两个新的重置按钮**
* 只重置启用状态的按钮
* 只重置快捷键值的按钮
* 同样添加确认弹窗
* 更新按钮显示,添加明确的功能说明
3. **实现重置功能的细分**
* 修改`KeyBindsUI`命名空间,添加两个新的重置方法:
* `resetAllKeyBindsEnabledState()`:仅重置启用状态
* `resetAllKeyBindsValues()`:仅重置快捷键值
* 确保现有`resetAllKeyBinds()`方法同时重置两者
4. **更新UI界面**
* 重新布局重置按钮区域
* 使用清晰的文本和图标区分三个重置按钮
* 添加适当的样式和间距
5. **测试功能**
* 测试所有三个重置按钮的功能
* 验证确认弹窗的显示和交互
* 检查重置后的数据状态是否正确
**预期效果**:
* 快捷键设置页面左侧分类栏底部会显示三个重置按钮
* 每个按钮都有明确的功能说明和提醒
* 点击任何重置按钮都会先显示确认弹窗
* 重置后页面数据会立即更新
* 用户可以根据需要选择不同的重置选项
================================================
FILE: .trae/documents/为LineEdge添加虚线形态属性.md
================================================
1. 在LineEdge类中添加线条类型属性:
- 在LineEdge.tsx中添加`@serializable`装饰的`lineType`属性,使用字符串枚举类型
- 支持的值:'solid'(实线)和'dashed'(虚线),后续可扩展
- 在构造函数中初始化该属性为'solid'
- 更新相关类型定义
2. 更新渲染逻辑:
- 在StraightEdgeRenderer.tsx中修改renderNormalState和renderShiftingState方法,根据lineType属性选择调用renderSolidLine或renderDashedLine
- 确保其他渲染器(如SymmetryCurveEdgeRenderer和VerticalPolyEdgeRenderer)也支持虚线渲染
3. 更新序列化和反序列化:
- 确保lineType属性能够被正确序列化和反序列化
- 在convertVAnyToN1函数中,为LineEdge添加lineType属性,默认值为'solid'
4. 测试和验证:
- 确保新属性能够被正确保存和加载
- 测试实线和虚线的渲染效果
- 确保现有功能不受影响
================================================
FILE: .trae/documents/为RecentFilesWindow添加独立的隐私模式功能.md
================================================
## 计划概述
为 RecentFilesWindow 页面添加独立的隐私模式开关,当开启时对文件夹名和文件名进行凯撒移位加密显示。
## 实施步骤
1. **添加本地隐私模式状态**
- 在组件中添加 `isLocalPrivacyMode` 状态
- 添加切换按钮到工具栏
2. **创建凯撒移位加密函数**
- 复用现有的 `replaceTextWhenProtect` 函数,但强制使用凯撒模式
- 或者创建专用的文件名加密函数
3. **修改显示逻辑**
- 在平铺视图中对文件名应用加密
- 在嵌套视图的文件夹名和文件名上应用加密
- 只影响显示,不改变实际数据
4. **UI优化**
- 添加隐私模式切换按钮,图标使用遮罩或眼睛图标
- 按钮状态反映当前是否开启隐私模式
## 技术要点
- 使用凯撒移位加密(字符后移一位)
- 复用现有的加密逻辑
- 只在前端渲染层面做改变,不影响数据存储
- 支持中英文字符的合理加密处理
================================================
FILE: .trae/documents/优化Tab键和反斜杠键创建节点的字体大小.md
================================================
# 优化Tab键和反斜杠键创建节点的字体大小
## 一、问题分析
当前Tab键和反斜杠键创建节点时,新节点的字体大小总是使用默认值(fontScaleLevel = 0),而没有考虑兄弟节点的字体大小。根据需求,新创建的节点应该:
1. 查看同方向兄弟节点的字体大小
2. 如果兄弟节点大小一致,新节点使用相同大小
3. 如果兄弟节点大小不一致,使用父节点大小。
4. 只考虑同方向的兄弟节点(上、下、左、右四个方向)
## 二、实现思路
1. **获取同方向兄弟节点**:根据节点的出边方向,将子节点分为四个方向组
2. **检查兄弟节点字体大小一致性**:遍历同方向兄弟节点,检查它们的fontScaleLevel是否相同
3. **设置新节点字体大小**:如果兄弟节点大小一致,新节点使用相同大小;否则使用父节点大小或默认值
4. **修改两个创建节点的方法**:`onDeepGenerateNode`(Tab键)和`onBroadGenerateNode`(反斜杠键)
## 三、关键修改点
### 1. 修改 `onDeepGenerateNode` 方法(Tab键深度创建节点)
**文件路径**:`/Volumes/移动固态1/project-graph-1/app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyTreeEngine.tsx`
**修改内容**:
- 在创建新节点之前,获取父节点的出边
- 根据预方向过滤出同方向的兄弟节点
- 检查这些兄弟节点的字体大小是否一致
- 为新节点设置合适的fontScaleLevel
### 2. 修改 `onBroadGenerateNode` 方法(反斜杠键广度创建节点)
**文件路径**:`/Volumes/移动固态1/project-graph-1/app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyTreeEngine.tsx`
**修改内容**:
- 在创建新节点之前,获取父节点的出边
- 根据预方向过滤出同方向的兄弟节点
- 检查这些兄弟节点的字体大小是否一致
- 为新节点设置合适的fontScaleLevel
### 3. 辅助函数(可选)
可以考虑添加一个辅助函数,用于获取同方向兄弟节点并检查字体大小一致性,以避免代码重复。
## 四、实现步骤
1. **在** **`onDeepGenerateNode`** **方法中**:
- 获取父节点的出边
- 根据预方向过滤出同方向的兄弟节点
- 检查兄弟节点的字体大小一致性
- 为新节点设置合适的fontScaleLevel
2. **在** **`onBroadGenerateNode`** **方法中**:
- 获取父节点的出边
- 根据预方向过滤出同方向的兄弟节点
- 检查兄弟节点的字体大小一致性
- 为新节点设置合适的fontScaleLevel
3. **测试验证**:
- 创建树形结构,为不同方向的子节点设置不同的字体大小
- 使用Tab键和反斜杠键创建新节点
- 验证新节点的字体大小是否符合预期
## 五、预期效果
1. 当使用Tab键或反斜杠键创建新节点时,新节点的字体大小会与同方向兄弟节点保持一致
2. 如果没有同方向兄弟节点,新节点使用父节点的字体大小
3. 只考虑同方向的兄弟节点,不同方向的节点不影响
4. 保持原有功能不变,只优化字体大小设置
## 六、注意事项
1. 确保代码兼容性,不破坏现有功能
2. 处理边界情况,如没有兄弟节点、兄弟节点字体大小不一致等
3. 保持代码风格一致,遵循现有代码的设计模式
4. 考虑性能影响,避免不必要的计算
================================================
FILE: .trae/documents/优化嫁接操作与添加反向操作.md
================================================
# 优化嫁接操作与添加反向操作
## 1. 优化嫁接操作(insertNodeToTree)
**问题**:当前嫁接操作创建的新连线总是使用默认的中心点连接,没有保持原连线的方向。
**解决方案**:
- 修改 `TextNodeSmartTools.insertNodeToTree` 方法
- 保存原碰撞连线的 `sourceRectangleRate` 和 `targetRectangleRate` 属性
- 在创建新连线时使用这些属性,保持原连线的方向
- 对于向右的连线,确保新连线从源头右侧发出,目标左侧接收
## 2. 实现反向操作(removeNodeFromTree)
**功能**:将选中的节点从树中移除,并重新连接其前后节点。
**实现步骤**:
- 在 `TextNodeSmartTools` 命名空间中添加 `removeNodeFromTree` 方法
- 逻辑:
1. 检查选中节点数量(必须为1)
2. 找到选中节点的所有入边和出边
3. 删除这些边
4. 将入边的源节点直接连接到出边的目标节点
5. 删除选中的节点
6. 记录操作历史
## 3. 添加快捷键
**快捷键设置**:
- 嫁接操作:`1 e`
- 摘除操作:`1 r`
**实现**:在 `shortcutKeysRegister.tsx` 中添加两个新的快捷键注册:
- 嫁接:`id: "graftNodeToTree", defaultKey: "1 e"`
- 摘除:`id: "removeNodeFromTree", defaultKey: "1 r"`
## 4. 新增快捷键分类
**分类设置**:
- 名称:"node"(节点相关)
- 图标:`<Network />`
- 包含快捷键:`["graftNodeToTree", "removeNodeFromTree"]`
**实现**:在 `keybinds.tsx` 的 `shortcutKeysGroups` 数组中添加新分类。
## 5. 文件修改清单
1. `textNodeSmartTools.tsx`:
- 优化 `insertNodeToTree` 方法
- 添加 `removeNodeFromTree` 方法
2. `shortcutKeysRegister.tsx`:
- 注册两个新快捷键
3. `keybinds.tsx`:
- 添加新的快捷键分类
4. `locales/zh_CN.yml`(可选):
- 添加新快捷键的国际化标题和描述
## 6. 预期效果
- 嫁接操作:保持原连线方向,特别是向右的连线会从源头右侧发出,目标左侧接收
- 摘除操作:快速将节点从树中移除,自动重新连接前后节点
- 快捷键:方便的 "1 e" 和 "1 r" 组合键
- 快捷键分类:更清晰的快捷键管理,新分类 "节点相关" 包含这两个操作
================================================
FILE: .trae/documents/优化文本节点渲染判断逻辑.md
================================================
### 问题分析
当前文本节点的文字渲染判断是基于固定的摄像机缩放阈值 `Settings.ignoreTextNodeTextRenderLessThanCameraScale`,当摄像机缩放比例小于这个阈值时,所有文本节点的文字都不会被渲染。这导致大字体的文本节点在宏观视野下更容易被看不见,因为它们的文字可能在摄像机缩放比例还比较大的时候就已经被隐藏了。
### 解决方案
1. 将设置项 `ignoreTextNodeTextRenderLessThanCameraScale` 重命名为 `ignoreTextNodeTextRenderLessThanFontSize`,以更准确地反映其功能
2. 改为基于实际渲染字体大小的动态判断:根据文本节点的字体大小和当前摄像机缩放比例,计算出实际渲染的字体大小,然后判断这个实际字体大小是否大于设置的最小可见字体大小,只有当实际字体大小大于这个值时,才渲染文字
### 实现方案
#### 1. 重命名设置项
**1.1 Settings.tsx**
- 将 `ignoreTextNodeTextRenderLessThanCameraScale` 重命名为 `ignoreTextNodeTextRenderLessThanFontSize`
- 设置合理的默认值和范围:`z.number().min(1).max(15).default(10)`
**1.2 SettingsIcons.tsx**
- 更新相关图标配置,将 `ignoreTextNodeTextRenderLessThanCameraScale` 改为 `ignoreTextNodeTextRenderLessThanFontSize`
**1.3 语言文件**
- 在所有语言文件中,将 `ignoreTextNodeTextRenderLessThanCameraScale` 重命名为 `ignoreTextNodeTextRenderLessThanFontSize`
- 更新描述,说明它现在表示最小可见字体大小(像素)
**1.4 settings.tsx**
- 更新设置项,将 `ignoreTextNodeTextRenderLessThanCameraScale` 改为 `ignoreTextNodeTextRenderLessThanFontSize`
#### 2. 修改渲染逻辑
**2.1 TextNodeRenderer.tsx**
- **第25行**:将基于摄像机缩放比例的透明背景判断改为基于实际渲染字体大小
- **第52行**:将基于摄像机缩放比例的文字渲染判断改为基于实际渲染字体大小
- 计算实际渲染字体大小:`const renderedFontSize = node.getFontSize() * this.project.camera.currentScale`
- 使用新的设置项:`renderedFontSize < Settings.ignoreTextNodeTextRenderLessThanFontSize`
**2.2 EntityRenderer.tsx**
- 修改使用 `ignoreTextNodeTextRenderLessThanCameraScale` 的渲染逻辑,改为使用 `ignoreTextNodeTextRenderLessThanFontSize` 并基于实际渲染字体大小
**2.3 SectionRenderer.tsx**
- 修改使用 `ignoreTextNodeTextRenderLessThanCameraScale` 的渲染逻辑,改为使用 `ignoreTextNodeTextRenderLessThanFontSize` 并基于实际渲染字体大小
**2.4 MultiTargetUndirectedEdgeRenderer.tsx**
- 修改使用 `ignoreTextNodeTextRenderLessThanCameraScale` 的渲染逻辑,改为使用 `ignoreTextNodeTextRenderLessThanFontSize` 并基于实际渲染字体大小
### 预期效果
- 大字体的文本节点在宏观视野下会比小字体的文本节点更晚消失
- 所有文本节点的文字在视觉上达到相同的清晰度阈值时才会消失
- 提高了宏观视野下的可读性,用户可以在更远的距离看到重要的大字体文本
- 优化了渲染性能,只渲染在当前缩放级别下可见的文字
- 设置项范围合理,用户可以在1-15像素之间调整最小可见字体大小
### 实施步骤
1. 在 `Settings.tsx` 中重命名设置项并设置范围:`z.number().min(1).max(15).default(10)`
2. 更新 `SettingsIcons.tsx` 中的配置
3. 更新所有语言文件中的设置项名称和描述
4. 更新 `settings.tsx` 中的设置项
5. 修改 `TextNodeRenderer.tsx` 中的渲染逻辑
6. 修改其他相关文件中的渲染逻辑
7. 测试不同字体大小的文本节点在不同摄像机缩放级别下的渲染效果
8. 验证设置调整是否生效
================================================
FILE: .trae/documents/修复Ctrl+T快捷键只能触发一个功能的问题.md
================================================
## 问题分析
1. **现象**:用户按下Ctrl+T快捷键时,只有一个功能被触发,而不是三个绑定了该快捷键的功能都被触发
2. **原因**:在`KeyBindsUI.tsx`的`check`函数中,当第一个匹配的快捷键执行后,会立即调用`userEventQueue.clear()`清空事件队列,导致后续绑定了相同快捷键的功能无法匹配到事件
3. **涉及文件**:
- `app/src/core/service/controlService/shortcutKeysEngine/KeyBindsUI.tsx` - 快捷键处理核心逻辑
- `app/src/core/service/controlService/shortcutKeysEngine/shortcutKeysRegister.tsx` - 快捷键注册定义
## 解决方案
修改`KeyBindsUI.tsx`中的`check`函数,调整事件队列清空的时机,确保所有匹配的快捷键都能被执行:
1. 移除在单个快捷键执行后立即清空队列的逻辑
2. 收集所有匹配的快捷键,执行完所有匹配的快捷键后再清空队列
3. 或者保持队列清空逻辑,但确保每个快捷键都能检查到匹配的事件
## 具体修改步骤
1. 打开`KeyBindsUI.tsx`文件
2. 修改`check`函数,将`userEventQueue.clear()`移到所有快捷键检查完成之后
3. 确保所有匹配的快捷键都能被执行
4. 测试修改效果,确认按下Ctrl+T时三个功能都能被触发
## 预期效果
- 按下Ctrl+T时,会依次执行:
- `folderSection` - 切换/折叠章节
- `reverseEdges` - 反转选中的边
- `reverseSelectedNodeEdge` - 反转选中节点的边
- 所有绑定了相同快捷键的功能都能正常触发
- 不影响其他快捷键的正常工作
================================================
FILE: .trae/documents/修复引用块转换时连线悬空问题.md
================================================
## 问题分析
当文本节点转换为引用块时,如果该文本节点已经有连线连接,这些连线会变成"架空"状态,无法删除。
### 根本原因
1. `changeTextNodeToReferenceBlock` 函数直接调用 `StageManager.delete(selectedNode)` 删除原文本节点
2. `StageManager.delete()` 只是简单地从数组中移除对象,没有处理关联的连线
3. 虽然 `DeleteManager` 有 `deleteEntityAfterClearAssociation` 方法来清理节点删除后的连线,但该方法只在 `DeleteManager.deleteEntities()` 中被调用
4. 转换过程中创建了新的引用块节点,但没有处理原节点的连线关系
## 解决方案
修改 `changeTextNodeToReferenceBlock` 函数,在转换节点时正确处理连线关系:
1. 在删除原文本节点前,获取所有与该节点相关的连线
2. 创建新的引用块节点
3. 将原节点的连线更新为连接到新的引用块节点
4. 最后删除原文本节点
## 实施步骤
1. 查看 `changeTextNodeToReferenceBlock` 函数的完整实现
2. 修改该函数,添加连线处理逻辑
3. 测试修复效果
## 预期结果
- 文本节点转换为引用块时,原节点的连线会自动转移到新的引用块节点
- 不会出现"架空"的连线
- 转换后的引用块节点可以正常与其他节点连接
## 代码修改点
- `/Users/littlefean/Desktop/Projects/project-graph/app/src/core/service/dataManageService/textNodeSmartTools.tsx`:修改 `changeTextNodeToReferenceBlock` 函数
## 具体修改思路
1. 在删除原节点前,遍历所有关联,找出与原节点相关的连线
2. 创建新的引用块节点
3. 更新这些连线的源/目标为新的引用块节点
4. 删除原节点
这样可以确保连线关系被正确转移,不会出现悬空的连线。
================================================
FILE: .trae/documents/全局快捷键重构方案.md
================================================
## 计划概述
为 RecentFilesWindow 页面添加独立的隐私模式开关,当开启时对文件夹名和文件名进行凯撒移位加密显示。
## 实施步骤
1. **添加本地隐私模式状态**
- 在组件中添加 `isLocalPrivacyMode` 状态
- 添加切换按钮到工具栏
2. **创建凯撒移位加密函数**
- 复用现有的 `replaceTextWhenProtect` 函数,但强制使用凯撒模式
- 或者创建专用的文件名加密函数
3. **修改显示逻辑**
- 在平铺视图中对文件名应用加密
- 在嵌套视图的文件夹名和文件名上应用加密
- 只影响显示,不改变实际数据
4. **UI优化**
- 添加隐私模式切换按钮,图标使用遮罩或眼睛图标
- 按钮状态反映当前是否开启隐私模式
## 技术要点
- 使用凯撒移位加密(字符后移一位)
- 复用现有的加密逻辑
- 只在前端渲染层面做改变,不影响数据存储
- 支持中英文字符的合理加密处理
================================================
FILE: .trae/documents/在快捷键设置页面添加重置所有快捷键按钮.md
================================================
1. **修改`keybinds.tsx`文件**,在左侧快捷键分类栏底部添加分割线和重置所有快捷键按钮
- 在`SidebarMenu`组件中,所有分类项之后添加一个分割线
- 分割线使用合适的样式,与现有UI设计保持一致
- 在分割线下方添加重置按钮
- 按钮使用合适的图标和文字
- 绑定点击事件处理函数
2. **实现重置按钮点击事件**
- 调用`KeyBindsUI.resetAllKeyBinds()`方法重置所有快捷键
- 更新页面数据状态
- 显示重置成功提示
3. **更新UI界面**
- 确保按钮样式与现有分类项一致
- 按钮位置在分类栏最底部,分割线下方
- 添加适当的视觉区分
4. **测试功能**
- 点击重置按钮,验证所有快捷键是否恢复默认值
- 检查页面显示是否更新
- 验证提示信息是否正确显示
**预期效果**:
- 快捷键设置页面左侧分类栏底部会显示一个分割线
- 分割线下方显示"重置所有快捷键"按钮
- 点击按钮后,所有快捷键将恢复为默认值
- 页面会更新显示,同时显示重置成功的提示信息
- 重置功能与顶部导航栏的重置按钮功能一致
================================================
FILE: .trae/documents/实现 Section 的 isHidden 属性功能.md
================================================
# 实现 Section 的 isHidden 属性功能
## 功能需求
1. **isHidden 属性**:控制 section 内部细节的隐藏状态
2. **移动限制**:隐藏后内部物体不能移动(包括跳跃式移动、普通拖拽、ctrl 拖拽)
3. **删除限制**:隐藏后内部物体不能删除(包括劈砍删除和 del 删除)
4. **跳跃式移动限制**:内部物体不能跳出去,外部物体不能跳进来
5. **操作方式**:右键菜单添加"隐藏 Section 内部细节"项
6. **渲染形态**:隐藏的 section 框显示斜着的线性阴影状态
7. **详细注释**:为 isHidden 属性添加详细注释
## 实现步骤
### 1. 修改 Section.tsx
- 为 isHidden 属性添加详细注释,说明其功能是隐藏内部细节并实现内部锁定效果
- 确保 isHidden 属性在构造函数中正确初始化
### 2. 修改右键菜单
- 在 `context-menu-content.tsx` 中添加"隐藏 Section 内部细节"菜单项
- 实现菜单项的点击逻辑,切换 section 的 isHidden 状态
### 3. 修改移动控制
- **跳跃式移动**:在 `ControllerEntityLayerMoving.tsx` 和 `StageEntityMoveManager.tsx` 中添加 isHidden 检查
- **普通移动**:在 `ControllerEntityClickSelectAndMove.tsx` 中添加 isHidden 检查
- **移动限制逻辑**:检查实体是否在 isHidden 为 true 的 section 内
### 4. 修改删除控制
- **劈砍删除**:在 `ControllerCutting.tsx` 中添加 isHidden 检查
- **del 删除**:在 `StageManager.tsx` 的 deleteSelectedStageObjects 方法中添加 isHidden 检查
### 5. 修改渲染逻辑
- 在 `SectionRenderer.tsx` 中添加隐藏状态的特殊渲染逻辑
- 为隐藏的 section 框添加斜着的线性阴影效果
- 确保隐藏状态下的 section 框有清晰的视觉标识
### 6. 测试验证
- 测试右键菜单的隐藏功能
- 测试隐藏后内部物体的移动限制
- 测试隐藏后内部物体的删除限制
- 测试跳跃式移动的限制
- 测试隐藏 section 的斜线性阴影渲染效果
## 技术要点
- 使用现有的 isHidden 属性,无需添加新属性
- 确保所有移动和删除操作都检查实体是否在隐藏的 section 内
- 为隐藏的 section 添加斜着的线性阴影效果作为视觉标识
- 添加详细的代码注释,便于其他开发者理解
================================================
FILE: .trae/documents/实现Section框大标题相机缩放阈值控制.md
================================================
1. **添加设置项**:在`Settings.tsx`的`settingsSchema`中添加新的设置项`sectionBigTitleCameraScaleThreshold`,类型为number,范围0.01到1,步长0.01,默认值0.5
2. **添加图标**:在`SettingsIcons.tsx`中为新设置项添加合适的图标
3. **添加翻译**:在中文翻译文件`zh_CN.yml`中添加新设置项的标题和描述
4. **修改渲染逻辑**:
- 在`SectionRenderer.tsx`的`renderBigCoveredTitle`和`renderTopTitle`方法中,添加相机缩放阈值判断
- 在`EntityRenderer.tsx`的`renderAllSectionsBigTitle`方法中,添加相机缩放阈值判断
5. **确保设置项显示**:确认新设置项在设置界面中正确显示
================================================
FILE: .trae/documents/实现关闭软件前的未保存文件警告.md
================================================
## 问题分析
当用户点击关闭软件按钮时,系统会遍历所有项目并调用 `closeProject` 函数,对每个未保存的项目弹出保存询问。然而,这种方式存在风险:保存操作是异步的,可能在保存完成前软件就已关闭,导致文件损坏或丢失。
## 解决方案
在关闭窗口前,先检查是否有未保存的项目,如果有则弹出一个统一的警告对话框,告知用户有未保存文件,建议先手动保存,避免自动保存可能出现的问题。
## 实现步骤
1. **修改关闭窗口事件处理逻辑**:
- 在 `App.tsx` 的 `onCloseRequested` 事件处理中,添加未保存项目检查
- 如果存在未保存项目,弹出统一警告对话框
- 根据用户选择决定是否继续关闭流程
2. **检查未保存项目**:
- 遍历所有项目,检查其状态是否为 `ProjectState.Unsaved` 或 `ProjectState.Stashed`
- 统计未保存项目数量
3. **弹出警告对话框**:
- 使用现有的 `Dialog` 组件创建警告对话框
- 显示未保存项目数量和警告信息
- 提供 "继续关闭" 和 "取消" 两个选项
4. **处理用户选择**:
- 如果用户选择 "继续关闭",则执行原有的关闭流程
- 如果用户选择 "取消",则中止关闭流程
## 核心修改点
- 文件:`/Volumes/移动固态1/project-graph-1/app/src/App.tsx`
- 函数:`onCloseRequested` 事件处理函数(第262-280行)
- 新增逻辑:未保存项目检查和统一警告对话框
## 预期效果
- 当用户关闭软件时,如果有未保存文件,会先看到一个统一的警告
- 用户可以选择继续关闭(执行原有保存流程)或取消关闭(手动保存文件)
- 减少文件保存不完整的风险,提高用户数据安全性
- 增强用户体验,让用户更清楚当前的文件状态
================================================
FILE: .trae/documents/实现图片节点拖拽缩放功能.md
================================================
# 实现图片节点拖拽缩放功能
## 1. 实现目标
- 选中图片节点后,在右下角显示缩放控制点
- 拖拽控制点可等比例缩放图片
- 保持现有的等比例缩放特性
- 性能优化:只在选中时显示控制点
## 2. 实现步骤
### 步骤1:让ImageNode实现ResizeAble接口
- 修改`ImageNode.tsx`,让其实现`ResizeAble`接口
- 添加`getResizeHandleRect()`方法,返回右下角缩放控制点矩形
- 添加`resizeHandle()`方法,根据拖拽距离计算新缩放比例
### 步骤2:修改EntityRenderer渲染缩放控制点
- 修改`EntityRenderer.tsx`中的`renderImageNode`方法
- 选中状态下,调用`shapeRenderer.renderRect()`绘制缩放控制点
- 控制点位置:右下角,大小随相机缩放
### 步骤3:确保ControllerEntityResize支持ImageNode
- 检查`ControllerEntityResize.tsx`是否能处理ImageNode
- 确保`utilsControl.tsx`中`isClickedResizeRect`能正确检测ImageNode的缩放控制点
### 步骤4:移除旧的提示文字
- 在`EntityRenderer.tsx`的`renderImageNode`方法中,移除"ctrl+滚轮缩放大小"提示
- 保持Ctrl+滚轮缩放功能不变,增加拖拽缩放作为补充
### 步骤5:性能优化
- 复用现有的渲染逻辑,避免额外性能开销
- 只在节点选中且相机缩放足够大时绘制控制点
- 使用与TextNode相同的缩放控制点样式,保持一致性
## 3. 技术细节
### 缩放控制点设计
- 位置:图片右下角
- 大小:固定像素大小,随相机缩放
- 样式:与TextNode缩放控制点一致
- 颜色:使用`stageStyleManager.currentStyle.CollideBoxSelected`
### 缩放逻辑
- 保持等比例缩放,根据拖拽距离计算新的缩放比例
- 缩放范围:0.1 - 10(与现有逻辑一致)
- 拖拽时实时更新碰撞箱
### 交互流程
1. 选中图片节点
2. 右下角显示缩放控制点
3. 鼠标悬停控制点时,鼠标样式变为缩放样式
4. 拖拽控制点,图片等比例缩放
5. 释放鼠标,完成缩放
## 4. 代码修改点
1. **`ImageNode.tsx`**:实现ResizeAble接口,添加缩放相关方法
2. **`EntityRenderer.tsx`**:渲染缩放控制点,移除旧提示
3. **`ControllerEntityResize.tsx`**:确保支持ImageNode(如果需要)
4. **`utilsControl.tsx`**:确保能检测ImageNode的缩放控制点(如果需要)
## 5. 预期效果
- 选中图片节点后,右下角显示缩放控制点
- 拖拽控制点可流畅地等比例缩放图片
- 保持现有Ctrl+滚轮缩放功能不变
- 性能良好,不影响其他操作
- 与现有UI风格保持一致
================================================
FILE: .trae/documents/实现引用块节点的精准连线定位.md
================================================
### 实现引用块节点的精准连线定位
#### 问题分析
图片节点在连线时有一个特性:当鼠标拖拽连线时,会根据鼠标位置精准定位连线的箭头位置,无论是从图片节点发出还是连接到图片节点,都能精准定位到图片内部的具体位置。现在需要让引用块节点也具有相同的特性。
#### 实现方案
需要修改以下几个文件:
1. **ControllerNodeConnection.tsx**
- 在 `onMouseDown` 方法中添加对 `ReferenceBlockNode` 的支持,记录起始点在引用块上的精确位置
- 在 `mouseUp` 方法中添加对 `ReferenceBlockNode` 的支持,记录结束点在引用块上的精确位置
- 在 `dragMultiConnect` 方法中添加对 `ReferenceBlockNode` 的支持,使用精确位置计算连线起点和终点
2. **Edge.tsx**
- 在 `bodyLine` getter 方法中添加对 `ReferenceBlockNode` 的支持,当连线连接到引用块节点且使用精确位置时,直接使用内部位置
3. **SymmetryCurveEdgeRenderer.tsx**
- 在 `renderNormalState` 方法中添加对 `ReferenceBlockNode` 的支持,检查是否是引用块节点的精确位置,并使用相应的法线向量计算方式
#### 实现思路
1. 在处理图片节点的地方,同时添加对引用块节点的检查
2. 复用现有的精确位置计算逻辑
3. 确保引用块节点在连线时能像图片节点一样精准定位
#### 预期效果
引用块节点在进行连线操作时,无论是作为连线的起点还是终点,都能根据鼠标位置精准定位连线的箭头位置,就像图片节点一样。
================================================
FILE: .trae/documents/实现快捷键开关功能.md
================================================
# 实现快捷键开关功能
## 核心需求
- 为每个快捷键添加开关功能,支持自定义默认状态
- 在设置页面的快捷键页面中显示开关控件
- 支持开关状态的持久化存储
- 修改相关代码以支持开关状态的触发控制
## 实现步骤
### 1. 修改快捷键定义接口
- 修改 `shortcutKeysRegister.tsx` 中的 `KeyBindItem` 接口,添加 `defaultEnabled: boolean` 属性
- 为所有现有快捷键添加默认 `defaultEnabled: true`
- 支持后续修改特定快捷键的默认启用状态
### 2. 设计持久化存储方案
- **方案选择**:使用现有 `keybinds2.json` 文件,扩展数据结构
- **数据结构设计**:
```json
{
"shortcutId": {
"key": "C-z",
"isEnabled": true
}
}
```
- **向后兼容**:未设置的快捷键使用 `defaultEnabled` 值
### 3. 扩展快捷键管理系统
- 修改 `KeyBinds.tsx` 和 `KeyBindsUI.tsx`,添加开关状态管理
- 更新 `create` 方法,支持初始化开关状态
- 添加 `toggleEnabled` 方法,支持切换开关状态
- 修改 `get` 和 `set` 方法,支持获取和设置完整的快捷键配置
### 4. 修改快捷键触发逻辑
- 在 `KeyBinds.tsx` 的 `check` 方法中,添加开关状态检查
- 在 `KeyBindsUI.tsx` 的 `check` 方法中,添加开关状态检查
- 只有 `isEnabled` 为 `true` 的快捷键才会被触发
### 5. 更新设置页面组件
- 修改 `keybinds.tsx`,在每个快捷键项中添加开关控件
- 引入 `Switch` 组件(假设已有或从UI库中引入)
- 添加开关状态的保存和加载逻辑
- 支持实时更新开关状态
### 6. 修改快捷键组件
- 更新 `KeyBind` 组件,支持显示和操作开关状态
- 在组件中集成开关控件
- 支持开关状态的回调通知
## 文件修改清单
1. `shortcutKeysRegister.tsx` - 扩展快捷键定义,添加 `defaultEnabled` 属性
2. `KeyBinds.tsx` - 支持项目级快捷键开关管理
3. `KeyBindsUI.tsx` - 支持UI级快捷键开关管理
4. `keybinds.tsx` - 添加设置页面开关控件
5. `KeyBind.tsx` - 更新快捷键组件,集成开关功能
## 技术要点
- 使用现有的Tauri Store进行持久化存储
- 采用扩展数据结构而非新增文件,简化管理
- 保持向后兼容性,旧配置自动迁移
- 实时更新开关状态,无需重启应用
- 支持自定义默认启用状态
## 预期效果
- 每个快捷键都有独立的开关控制
- 设置页面直观显示所有快捷键的开关状态
- 关闭的快捷键不会响应键盘事件
- 开关状态持久化保存,重启应用后保持
- 支持通过修改 `defaultEnabled` 调整默认启用状态
## 风险评估
- 需确保所有现有快捷键都正确添加 `defaultEnabled` 属性
- 需测试快捷键触发逻辑,确保关闭状态的快捷键不会被触发
- 需确保设置页面的开关控件正常工作
- 需确保数据结构扩展后与现有代码兼容
## 测试计划
1. 验证所有快捷键默认开启
2. 测试单个快捷键开关功能
3. 测试多个快捷键批量开关
4. 测试开关状态持久化
5. 测试关闭状态的快捷键是否被正确忽略
6. 测试设置页面开关控件的交互体验
7. 测试修改 `defaultEnabled` 后新配置的效果
## 优化建议
- 考虑添加"全选"和"反选"功能,方便批量管理快捷键开关
- 考虑添加快捷键分组开关,方便按组管理
- 考虑添加重置开关状态到默认值的功能
## 实现细节
- 使用 `isEnabled` 表示当前启用状态,`defaultEnabled` 表示默认启用状态
- 存储时只保存与默认值不同的配置,节省存储空间
- 加载时优先使用存储的配置,否则使用默认值
- 开关状态与快捷键键位独立管理,允许单独修改
================================================
FILE: .trae/documents/实现搜索范围选项.md
================================================
# 实现搜索范围选项
## 需求分析
需要在搜索功能中添加两个搜索范围选项:
1. 只搜索所有选中的内容(选中的节点)
2. 只搜索所有选中内容的外接矩形范围内的所有实体
## 实现思路
1. **修改搜索引擎核心**
- 在`ContentSearch`类中添加搜索范围枚举和相关属性
- 修改`startSearch`方法,根据搜索范围过滤搜索对象
- 添加获取选中对象外接矩形的方法
2. **增强搜索面板UI**
- 在`FindWindow`中添加搜索范围选择控件
- 实现UI与搜索引擎的状态同步
- 添加相应的图标和提示
3. **实现搜索范围逻辑**
- 实现"只搜索选中内容"逻辑:过滤出选中的对象进行搜索
- 实现"搜索外接矩形范围"逻辑:计算选中对象的外接矩形,然后搜索该范围内的所有对象
## 实现步骤
1. **修改`contentSearchEngine.tsx`**
- 添加`SearchScope`枚举类型
- 在`ContentSearch`类中添加`searchScope`属性
- 修改`startSearch`方法,根据搜索范围过滤搜索对象
- 添加`getSelectedObjectsBounds`方法,计算选中对象的外接矩形
- 添加`isObjectInBounds`方法,判断对象是否在指定范围内
2. **修改`FindWindow.tsx`**
- 添加搜索范围状态管理
- 在UI中添加搜索范围选择按钮
- 实现搜索范围切换逻辑
- 同步UI状态到搜索引擎
3. **测试验证**
- 测试不同搜索范围下的搜索结果
- 验证UI控件的交互和状态显示
- 确保原有功能不受影响
## 文件修改
- `app/src/core/service/dataManageService/contentSearchEngine/contentSearchEngine.tsx`
- `app/src/sub/FindWindow.tsx`
================================================
FILE: .trae/documents/实现背景图片功能和背景管理器.md
================================================
# 实现背景图片功能和背景管理器
## 1. 为ImageNode添加背景图片属性
- 在ImageNode类中添加`isBackground`属性,用于标记图片是否为背景图片
- 确保该属性可序列化,以便保存到项目文件中
## 2. 修改选择和删除逻辑
- 修改StageManager中的选择相关方法(如`findEntityByLocation`、`findImageNodeByLocation`等),跳过背景图片
- 修改删除相关方法(如`deleteEntities`、`deleteSelectedStageObjects`等),跳过背景图片
- 修改框选逻辑,确保背景图片不被框选选中
## 3. 添加右键菜单项
- 在context-menu-content.tsx中为图片节点添加"转化为背景图片"菜单项
- 为背景图片添加"取消背景化"菜单项
- 实现对应的处理函数
## 4. 创建背景管理器窗口
- 创建BackgroundManagerWindow组件
- 实现显示所有背景化图片的功能
- 实现单独取消背景化的功能
## 5. 在右侧工具栏添加背景管理器入口
- 在右侧工具栏中添加背景管理器的按钮
- 实现点击按钮打开背景管理器窗口的功能
## 6. 测试和优化
- 测试背景图片的选择、删除和背景化功能
- 测试背景管理器的功能
- 优化用户体验
## 技术要点
- 确保背景图片在渲染时位于底层
- 确保背景图片不响应鼠标事件
- 确保背景图片的状态正确保存和加载
- 确保背景管理器能够正确显示和管理所有背景图片
================================================
FILE: .trae/documents/引用块节点精准连线定位功能问题记录.md
================================================
# 引用块节点精准连线定位功能问题记录
## 问题现象
在实现引用块节点(ReferenceBlockNode)的精准连线定位功能时,应用在启动时出现窗口无法弹出的问题。
## 问题原因
经过分析,问题是由于循环依赖导致的。当我们在以下文件中导入ReferenceBlockNode类时,形成了循环依赖:
1. `ControllerNodeConnection.tsx`
2. `Edge.tsx`
3. `SymmetryCurveEdgeRenderer.tsx`
循环依赖导致应用在启动时无法正确加载模块,从而导致窗口无法弹出。
## 解决方法
1. **移除ReferenceBlockNode的导入语句**:在所有相关文件中移除ReferenceBlockNode的导入语句,避免循环依赖。
2. **使用构造函数名称检查替代直接类型检查**:在需要检查对象是否为ReferenceBlockNode类型的地方,使用`constructor.name === 'ReferenceBlockNode'`来替代直接的`instanceof`检查。
3. **具体修改文件**:
- `ControllerNodeConnection.tsx`:移除导入,使用构造函数名称检查来记录起始点和结束点的精确位置
- `Edge.tsx`:移除导入,使用构造函数名称检查来处理引用块节点的精确位置
- `SymmetryCurveEdgeRenderer.tsx`:移除导入,使用构造函数名称检查来处理引用块节点的法线向量计算
4. **修复后的效果**:应用可以正常启动,窗口能够弹出,同时引用块节点可以实现精准连线定位功能。
## 代码修改示例
```typescript
// 修复前
if (clickedConnectableEntity instanceof ImageNode || clickedConnectableEntity instanceof ReferenceBlockNode) {
// 处理逻辑
}
// 修复后
if (
clickedConnectableEntity instanceof ImageNode ||
clickedConnectableEntity.constructor.name === "ReferenceBlockNode"
) {
// 处理逻辑
}
```
## 总结
通过移除循环依赖,使用构造函数名称检查替代直接类型检查,我们成功解决了窗口无法弹出的问题,同时实现了引用块节点的精准连线定位功能。这种方法可以避免循环依赖问题,同时保持代码的可读性和可维护性。
================================================
FILE: .trae/documents/文本节点自定义文字大小功能设计方案.md
================================================
# 文本节点自定义文字大小功能设计方案
## 一、需求分析
1. **功能需求**:
- 为文本节点添加自定义文字大小功能
- 支持通过快捷键(放大/缩小)调整字体大小
- 采用指数形式缩放(例如:2 → 4 → 8 → 16 → 32)
2. **技术约束**:
- 当前所有文本节点共享 `Renderer.FONT_SIZE = 32` 常量
- 渲染时字体大小会乘以相机缩放比例
- 已有完整的快捷键系统
## 二、方案对比
### 方案1:存储缩放级别(整数)
**设计**:
- 在 `TextNode` 类中添加 `fontScaleLevel` 字段,类型为整数
- 基准值为0,对应默认字体大小(32px)
- 计算公式:`finalFontSize = Renderer.FONT_SIZE * Math.pow(2, fontScaleLevel)`
- 快捷键操作:每次按放大键 `fontScaleLevel++`,按缩小键 `fontScaleLevel--`
**优点**:
- 存储值范围小,占用空间少
- 缩放逻辑清晰,符合用户期望的指数增长
- 便于实现快捷键操作(只需增减整数)
- 支持正负值,可放大可缩小
**缺点**:
- 需要额外计算才能得到实际像素值
- 无法直接表示非2的幂次的字体大小
### 方案2:直接存储像素值
**设计**:
- 在 `TextNode` 类中添加 `fontSize` 字段,类型为数值
- 默认值为 `Renderer.FONT_SIZE`(32px)
- 快捷键操作:根据当前值计算指数缩放后的新值
**优点**:
- 直接存储最终使用的像素值,无需计算
- 支持任意字体大小,灵活性更高
- 直观易懂,便于调试
**缺点**:
- 存储值范围大,占用空间多
- 快捷键操作需要复杂计算(需要记录缩放次数或反向计算当前缩放级别)
- 缩放逻辑不直观,用户难以预测下一次缩放后的大小
## 三、推荐方案
### 推荐方案:存储缩放级别(方案1的改进版)
**设计**:
1. **字段设计**:
- 在 `TextNode` 类中添加 `fontScale` 字段,类型为数值(支持小数)
- 默认值为1.0,对应默认字体大小
- 计算公式:`finalFontSize = Renderer.FONT_SIZE * fontScale`
2. **缩放逻辑**:
- 快捷键放大:`fontScale *= 2`
- 快捷键缩小:`fontScale /= 2`
- 支持直接设置特定缩放比例(如1.5、0.5等)
3. **实现细节**:
- 添加 `increaseFontSize()` 和 `decreaseFontSize()` 方法
- 在快捷键注册中添加对应绑定
- 更新渲染逻辑,使用节点自身的 `fontScale` 计算最终字体大小
- 确保新字段支持序列化和反序列化
**优势**:
- 结合了方案1和方案2的优点
- 缩放逻辑清晰,符合指数增长预期
- 支持精确调整字体大小
- 存储空间合理
- 便于实现快捷键操作
## 四、实现步骤
1. **修改 `TextNode` 类**:
- 添加 `@serializable` 装饰的 `fontScale` 字段
- 添加字体大小调整方法
2. **更新渲染逻辑**:
- 在 `TextNodeRenderer` 中使用节点的 `fontScale` 计算字体大小
- 更新 `getMultiLineTextSize` 等相关方法
3. **添加快捷键支持**:
- 在 `shortcutKeysRegister.tsx` 中注册放大/缩小快捷键
- 实现快捷键回调函数
4. **数据升级**:
- 在 `ProjectUpgrader.tsx` 中添加升级逻辑,为旧节点设置默认 `fontScale`
5. **测试验证**:
- 测试新建节点的默认字体大小
- 测试快捷键放大缩小功能
- 测试不同缩放级别的节点渲染效果
- 测试数据保存和加载功能
## 五、预期效果
- 新创建的文本节点使用默认字体大小(32px)
- 选中文本节点后,按放大键(如 `+`)字体大小翻倍
- 按缩小键(如 `-`)字体大小减半
- 不同节点可以有不同的字体大小
- 保存和加载后字体大小保持不变
## 六、扩展考虑
- 未来可添加字体大小输入框,支持直接输入像素值
- 可添加字体大小范围限制(最小/最大)
- 可支持批量调整多个节点的字体大小
该方案既满足了用户期望的指数缩放效果,又保持了良好的灵活性和可扩展性。
================================================
FILE: .trae/documents/添加大标题遮罩透明度设置.md
================================================
1. **添加设置项**:在 `Settings.tsx` 中添加一个新的设置项 `sectionBigTitleOpacity`,类型为 `z.number().min(0).max(1).default(0.5)`,用于控制大标题遮罩的透明度
2. **更新图标映射**:在 `SettingsIcons.tsx` 中为 `sectionBigTitleOpacity` 添加合适的图标,建议使用 `Blend` 图标,与其他透明度相关设置保持一致
3. **添加翻译**:在三个翻译文件中添加对应的标题和描述:
- `zh_CN.yml`:标题为"框的缩略大标题透明度",描述为"控制半透明覆盖大标题的透明度,取值范围0-1"
- `zh_TW.yml`:标题为"框的縮略大標題透明度",描述为"控制半透明覆蓋大標題的透明度,取值範圍0-1"
- `en.yml`:标题为"Section Big Title Opacity",描述为"Control the opacity of the semi-transparent cover big title, range 0-1"
4. **修改渲染逻辑**:在 `SectionRenderer.tsx` 中,将硬编码的 `0.5` 透明度替换为使用 `Settings.sectionBigTitleOpacity` 值,确保设置项生效
5. **测试验证**:确保新设置项能够正确保存和应用,并且在广视野下能够看到大标题遮罩透明度的变化
================================================
FILE: .trae/documents/添加快捷键冲突检测和提醒功能.md
================================================
# 快捷键冲突检测和提醒功能实现计划
## 1. 功能需求分析
- 在快捷键设置页面中,为每个快捷键添加冲突检测
- 当快捷键重复时,显示警告色提示并说明与多少个快捷键冲突
- 点击提示可以查看具体与哪一个快捷键冲突
- 没有冲突时不显示任何内容,不占用额外视觉空间
## 2. 实现方案
### 2.1 添加冲突检测函数
- 在 `KeyBindsPage` 组件中添加 `detectKeyConflicts` 函数
- 该函数接收一个快捷键值,返回与该快捷键冲突的所有快捷键信息
- 冲突检测逻辑:检查所有启用的快捷键,找出具有相同键值的项
### 2.2 修改快捷键设置项渲染
- 修改 `renderKeyFields` 函数,为每个快捷键设置项添加冲突检测
- 当检测到冲突时,在 `Field` 组件下方添加冲突提示元素
- 冲突提示元素使用警告色样式,显示冲突数量
### 2.3 添加冲突详情对话框
- 添加一个对话框组件,用于显示冲突的快捷键详情
- 当用户点击冲突提示时,打开对话框并列出所有冲突的快捷键
- 对话框中显示冲突快捷键的名称、当前键值和所属分组
### 2.4 优化用户体验
- 实时检测:当用户修改快捷键时,立即更新冲突状态
- 视觉反馈:使用明显的警告色和图标,让用户快速识别冲突
- 交互便捷:点击提示即可查看详情,无需额外操作
## 3. 技术实现要点
### 3.1 冲突检测逻辑
```typescript
const detectKeyConflicts = (targetKey: string, targetId: string) => {
return data.filter((item) => item.key === targetKey && item.id !== targetId && item.isEnabled);
};
```
### 3.2 冲突提示组件
- 使用 `Badge` 或自定义元素显示冲突数量
- 添加点击事件处理函数,打开详情对话框
- 应用适当的样式,确保警告效果明显
### 3.3 对话框实现
- 使用现有的 `Dialog` 组件
- 动态生成冲突列表,显示每个冲突快捷键的详细信息
- 添加关闭按钮,确保用户可以方便地关闭对话框
## 4. 具体修改文件
- `/Volumes/移动固态1/project-graph-1/app/src/sub/SettingsWindow/keybinds.tsx`:主修改文件,添加冲突检测和提醒功能
## 5. 预期效果
- 用户在设置快捷键时,能够实时看到冲突提示
- 点击提示可以查看具体冲突的快捷键,便于调整
- 界面简洁,没有冲突时不显示额外元素,保持原有布局美观
================================================
FILE: .trae/documents/粘贴bug崩溃报告.txt
================================================
-------------------------------------
Translated Report (Full Report Below)
-------------------------------------
Process: project-graph [68049]
Path: /Applications/Project Graph.app/Contents/MacOS/project-graph
Identifier: liren.project-graph
Version: 2.9.13 (2.9.13)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: liren.project-graph [1342]
User ID: 501
Date/Time: 2026-02-13 15:56:44.8734 +0800
Launch Time: 2026-02-13 09:40:05.9876 +0800
Hardware Model: Mac16,12
OS Version: macOS 26.1 (25B78)
Release Type: User
Crash Reporter Key: B6C57097-5B06-A3FA-7F07-E57289B4D2B6
Incident Identifier: 2CD58038-FC0A-4005-9C57-8CF12FA876D5
Sleep/Wake UUID: 5946CB7E-C783-40E2-ABF2-93A7C8E35F2C
Time Awake Since Boot: 240000 seconds
Time Since Wake: 23429 seconds
System Integrity Protection: enabled
Triggered by Thread: 0 main, Dispatch Queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x003aea405a1445a0
Exception Codes: 0x0000000000000001, 0x003aea405a1445a0
Termination Reason: Namespace SIGNAL, Code 11, Segmentation fault: 11
Terminating Process: exc handler [68049]
VM Region Info: 0x6a405a1445a0 is not in any region.
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
UNUSED SPACE AT END
Thread 0 Crashed:: main Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x18848d820 objc_msgSend + 32
1 AppKit 0x18cdd812c -[NSPasteboard _updateTypeCacheIfNeeded] + 1064
2 AppKit 0x18d776820 -[NSPasteboard _typesAtIndex:combinesItems:] + 36
3 WebCore 0x1af2ccaec WebCore::PlatformPasteboard::informationForItemAtIndex(unsigned long, long long) + 172
4 WebCore 0x1aefb36b4 WebCore::PlatformPasteboard::allPasteboardItemInfo(long long) + 204
5 WebKit 0x1b250b57c WebKit::WebPasteboardProxy::grantAccessToCurrentData(WebKit::WebProcessProxy&, WTF::String const&, WTF::CompletionHandler<void ()>&&) + 92
6 WebKit 0x1b24b97a4 WebKit::WebPageProxy::grantAccessToCurrentPasteboardData(WTF::String const&, WTF::CompletionHandler<void ()>&&, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::FrameIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>>) + 120
7 WebKit 0x1b267eeac WebKit::WebPageProxy::willPerformPasteCommand(WebCore::DOMPasteAccessCategory, WTF::CompletionHandler<void ()>&&, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::FrameIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>>) + 96
8 WebKit 0x1b27e0990 WebKit::WebPageProxy::executeEditCommand(WTF::String const&, WTF::String const&) + 352
9 WebKit 0x1b2693628 WebKit::WebViewImpl::executeEditCommandForSelector(objc_selector*, WTF::String const&) + 56
10 WebKit 0x1b23b7c28 -[WKWebView(WKImplementationMac) paste:] + 44
11 AppKit 0x18d852104 -[NSApplication(NSResponder) sendAction:to:from:] + 560
12 AppKit 0x18d6bc344 -[NSMenuItem _corePerformAction:] + 540
13 AppKit 0x18d880e7c _NSMenuPerformActionWithHighlighting + 160
14 AppKit 0x18d6a3424 -[NSMenu _performKeyEquivalentForItemAtIndex:] + 172
15 AppKit 0x18d6a3068 -[NSMenu performKeyEquivalent:] + 356
16 AppKit 0x18d850a9c routeKeyEquivalent + 444
17 AppKit 0x18d84ecd0 -[NSApplication(NSEventRouting) sendEvent:] + 1844
18 project-graph 0x104f4df94 0x104b58000 + 4153236
19 WebKit 0x1b269d1a8 WebKit::WebViewImpl::doneWithKeyEvent(NSEvent*, bool) + 168
20 WebKit 0x1b1dc409c WebKit::PageClientImpl::doneWithKeyEvent(WebKit::NativeWebKeyboardEvent const&, bool) + 56
21 WebKit 0x1b2808228 WebKit::WebPageProxy::didReceiveEvent(IPC::Connection*, WebKit::WebEventType, bool, std::__1::optional<WebCore::RemoteUserInputEventData>&&) + 1168
22 WebKit 0x1b2293088 WebKit::WebPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 7124
23 WebKit 0x1b2ea8dd8 IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 264
24 WebKit 0x1b28878b0 WebKit::WebProcessProxy::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 40
25 WebKit 0x1b22b2614 WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 1620
26 WebKit 0x1b2e824dc IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 300
27 WebKit 0x1b2e82a0c IPC::Connection::dispatchIncomingMessages() + 536
28 JavaScriptCore 0x1a9e971d8 WTF::RunLoop::performWork() + 552
29 JavaScriptCore 0x1a9e98bd0 WTF::RunLoop::performWork(void*) + 36
30 CoreFoundation 0x1889789e8 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
31 CoreFoundation 0x18897897c __CFRunLoopDoSource0 + 172
32 CoreFoundation 0x1889786e8 __CFRunLoopDoSources0 + 232
33 CoreFoundation 0x188977378 __CFRunLoopRun + 820
34 CoreFoundation 0x188a3135c _CFRunLoopRunSpecificWithOptions + 532
35 HIToolbox 0x195434768 RunCurrentEventLoopInMode + 316
36 HIToolbox 0x195437a90 ReceiveNextEventCommon + 488
37 HIToolbox 0x1955c1308 _BlockUntilNextEventMatchingListInMode + 48
38 AppKit 0x18d2883c0 _DPSBlockUntilNextEventMatchingListInMode + 236
39 AppKit 0x18cd81e34 _DPSNextEvent + 588
40 AppKit 0x18d84ff44 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 688
41 AppKit 0x18d84fc50 -[NSApplication(NSEventRouting) nextEventMatchingMask:untilDate:inMode:dequeue:] + 72
42 AppKit 0x18cd7a780 -[NSApplication run] + 368
43 project-graph 0x104cb392c 0x104b58000 + 1423660
44 project-graph 0x104cb37b4 0x104b58000 + 1423284
45 project-graph 0x104cb37a8 0x104b58000 + 1423272
46 project-graph 0x104cb364c 0x104b58000 + 1422924
47 project-graph 0x104cb072c 0x104b58000 + 1410860
48 project-graph 0x104b59010 0x104b58000 + 4112
49 project-graph 0x104b59350 0x104b58000 + 4944
50 dyld 0x188511d54 start + 7184
Thread 1:: com.apple.NSEventThread
0 libsystem_kernel.dylib 0x188896c34 mach_msg2_trap + 8
1 libsystem_kernel.dylib 0x1888a9028 mach_msg2_internal + 76
2 libsystem_kernel.dylib 0x18889f98c mach_msg_overwrite + 484
3 libsystem_kernel.dylib 0x188896fb4 mach_msg + 24
4 CoreFoundation 0x188978b90 __CFRunLoopServiceMachPort + 160
5 CoreFoundation 0x1889774e8 __CFRunLoopRun + 1188
6 CoreFoundation 0x188a3135c _CFRunLoopRunSpecificWithOptions + 532
7 AppKit 0x18ce11cb4 _NSEventThread + 184
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 2:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 3:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 4:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 5:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 6:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 7:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 8:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 9:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 10:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 11:
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x105023e50 0x104b58000 + 5029456
4 project-graph 0x105023b8c 0x104b58000 + 5028748
5 project-graph 0x104e22e8c 0x104b58000 + 2928268
6 project-graph 0x104e22bc0 0x104b58000 + 2927552
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 12:: WebCore: Scrolling
0 libsystem_kernel.dylib 0x188896c34 mach_msg2_trap + 8
1 libsystem_kernel.dylib 0x1888a9028 mach_msg2_internal + 76
2 libsystem_kernel.dylib 0x18889f98c mach_msg_overwrite + 484
3 libsystem_kernel.dylib 0x188896fb4 mach_msg + 24
4 CoreFoundation 0x188978b90 __CFRunLoopServiceMachPort + 160
5 CoreFoundation 0x1889774e8 __CFRunLoopRun + 1188
6 CoreFoundation 0x188a3135c _CFRunLoopRunSpecificWithOptions + 532
7 CoreFoundation 0x1889caa30 CFRunLoopRun + 64
8 JavaScriptCore 0x1a9e98198 WTF::Detail::CallableWrapper<WTF::RunLoop::create(WTF::ASCIILiteral, WTF::ThreadType, WTF::Thread::QOS)::$_0, void>::call() + 244
9 JavaScriptCore 0x1a9edae5c WTF::Thread::entryPoint(WTF::Thread::NewThreadContext*) + 260
10 JavaScriptCore 0x1a9ca5490 WTF::wtfThreadEntryPoint(void*) + 16
11 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
12 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 13:: Log work queue
0 libsystem_kernel.dylib 0x188896bb0 semaphore_wait_trap + 8
1 WebKit 0x1b2eae6b4 IPC::StreamConnectionWorkQueue::startProcessingThread()::$_0::operator()() + 44
2 JavaScriptCore 0x1a9edae5c WTF::Thread::entryPoint(WTF::Thread::NewThreadContext*) + 260
3 JavaScriptCore 0x1a9ca5490 WTF::wtfThreadEntryPoint(void*) + 16
4 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
5 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 14:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 15:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889cf30 kevent + 8
1 project-graph 0x104fca0a8 0x104b58000 + 4661416
2 project-graph 0x104fc95c4 0x104b58000 + 4658628
3 project-graph 0x104fc8780 0x104b58000 + 4654976
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 16:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 17:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 18:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 19:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 20:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 21:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 22:: tokio-runtime-worker Dispatch queue: Client CFPasteboard-Apple CFPasteboard general
0 libsystem_kernel.dylib 0x188896b2c _kernelrpc_mach_port_construct_trap + 8
1 libsystem_kernel.dylib 0x188897eb8 mach_port_construct + 40
2 libxpc.dylib 0x1885dd05c _xpc_try_mach_port_construct + 64
3 libxpc.dylib 0x1885dd0a8 _xpc_mach_port_construct + 28
4 libxpc.dylib 0x1885b5544 _xpc_mach_port_allocate + 36
5 libxpc.dylib 0x1885b9bf0 xpc_connection_send_message_with_reply + 160
6 CoreFoundation 0x188a25778 -[_CFPasteboardEntry requestDataForPasteboard:generation:immediatelyAvailableResult:] + 1520
7 CoreFoundation 0x18897587c __CFPasteboardCopyData_block_invoke + 152
8 CoreFoundation 0x188a26824 ____CFPasteboardPerformOnQueue_block_invoke + 292
9 libdispatch.dylib 0x188721e1c _dispatch_block_sync_invoke + 240
10 libdispatch.dylib 0x188736ac4 _dispatch_client_callout + 16
11 libdispatch.dylib 0x18872c940 _dispatch_lane_barrier_sync_invoke_and_complete + 56
12 libdispatch.dylib 0x188723138 _dispatch_sync_block_with_privdata + 452
13 CoreFoundation 0x188975074 CFPasteboardCopyData + 652
14 AppKit 0x18d776ad4 -[NSPasteboard _dataWithoutConversionForTypeIdentifier:index:securityScoped:] + 432
15 AppKit 0x18d77734c -[NSPasteboard _dataForType:index:usesPboardTypes:combinesItems:securityScoped:] + 272
16 AppKit 0x18dc4fea0 -[NSPasteboardItem __dataForType:async:completionHandler:] + 316
17 AppKit 0x18dc4ffac -[NSPasteboardItem stringForType:] + 28
18 project-graph 0x104ddc3f0 0x104b58000 + 2638832
19 project-graph 0x104ddca18 0x104b58000 + 2640408
20 project-graph 0x104fc8c0c 0x104b58000 + 4656140
21 project-graph 0x104fce078 0x104b58000 + 4677752
22 project-graph 0x104fcb0a4 0x104b58000 + 4665508
23 project-graph 0x104fcaef8 0x104b58000 + 4665080
24 project-graph 0x104f379b4 0x104b58000 + 4061620
25 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
26 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 23:: tokio-runtime-worker
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 project-graph 0x104fc9404 0x104b58000 + 4658180
3 project-graph 0x104fc8830 0x104b58000 + 4655152
4 project-graph 0x104fce4ec 0x104b58000 + 4678892
5 project-graph 0x104fcb0a4 0x104b58000 + 4665508
6 project-graph 0x104fcaef8 0x104b58000 + 4665080
7 project-graph 0x104f379b4 0x104b58000 + 4061620
8 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
9 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 24:: JavaScriptCore libpas scavenger
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da0dc _pthread_cond_wait + 984
2 JavaScriptCore 0x1ab59be78 scavenger_thread_main + 1440
3 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
4 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 25:: CVDisplayLink
0 libsystem_kernel.dylib 0x18889a4f8 __psynch_cvwait + 8
1 libsystem_pthread.dylib 0x1888da108 _pthread_cond_wait + 1028
2 CoreVideo 0x192ee9b3c CVDisplayLink::waitUntil(unsigned long long) + 336
3 CoreVideo 0x192ee8c24 CVDisplayLink::runIOThread() + 500
4 libsystem_pthread.dylib 0x1888d9c08 _pthread_start + 136
5 libsystem_pthread.dylib 0x1888d4ba8 thread_start + 8
Thread 26:
Thread 27:
Thread 28:
Thread 29:
Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x000000080c0228b0 x1: 0x00000002034a58e8 x2: 0x000000016b2a1320 x3: 0x000000016b2a13a0
x4: 0x0000000000000010 x5: 0x0000000000000000 x6: 0xffffffffbfc007ff x7: 0xfffff0003ffff800
x8: 0x3d2d25f44434003c x9: 0x0000000202feace8 x10: 0x6ae100080c0228b0 x11: 0x000000000000007f
x12: 0x0000000000000031 x13: 0x000000080dc25b00 x14: 0x4d3aea405a144595 x15: 0x003aea405a144590
x16: 0x003aea405a144590 x17: 0x00000001f6895ca0 x18: 0x0000000000000000 x19: 0x000000080d0d03c0
x20: 0x0000000000000001 x21: 0x0000000000000000 x22: 0x000000080c0228b0 x23: 0x000000080c0228b0
x24: 0x000000080c0223d0 x25: 0x0000000000000001 x26: 0x00000001f6900978 x27: 0x0000000000000001
x28: 0x0000000100000002 fp: 0x000000016b2a1480 lr: 0x000000018cdd812c
sp: 0x000000016b2a12f0 pc: 0x000000018848d820 cpsr: 0x20000000
far: 0x003aea405a1445a0 esr: 0x92000004 (Data Abort) byte read Translation fault
Binary Images:
0x104b58000 - 0x1053dffff liren.project-graph (2.9.13) <946c435c-f6bb-3969-9092-d73ba4a59315> /Applications/Project Graph.app/Contents/MacOS/project-graph
0x1171b4000 - 0x1171bffff libobjc-trampolines.dylib (*) <f8bd9069-8c4f-37ea-af9a-2b1060f54e4f> /usr/lib/libobjc-trampolines.dylib
0x1191b8000 - 0x1199dffff com.apple.AGXMetalG16G-B0 (341.11) <a22549f3-d4f5-3b88-af18-e06837f0d352> /System/Library/Extensions/AGXMetalG16G_B0.bundle/Contents/MacOS/AGXMetalG16G_B0
0x118760000 - 0x1187c3fff com.apple.AppleMetalOpenGLRenderer (1.0) <7fba6cd5-06ae-37aa-aa67-580c920ea69d> /System/Library/Extensions/AppleMetalOpenGLRenderer.bundle/Contents/MacOS/AppleMetalOpenGLRenderer
0x188484000 - 0x1884d748b libobjc.A.dylib (*) <5a0aab4e-0c1a-3680-82c9-43dc4007a6e7> /usr/lib/libobjc.A.dylib
0x18cd62000 - 0x18e48eb9f com.apple.AppKit (6.9) <3c0949bb-e361-369a-80b7-17440eb09e98> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
0x1adf91000 - 0x1b16a45df com.apple.WebCore (21622) <ccd2dfa6-ae82-311f-b824-a9aad0a6f12e> /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/WebCore
0x1b1d8c000 - 0x1b32a68bf com.apple.WebKit (21622) <3b55482a-efe2-35a7-b1c9-3f41a823a30b> /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit
0x1a9c9e000 - 0x1ab7bce7f com.apple.JavaScriptCore (21622) <c79071c9-db50-3264-a316-94abd0d3b9a9> /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore
0x188919000 - 0x188e5fabf com.apple.CoreFoundation (6.9) <3c4a3add-9e48-33da-82ee-80520e6cbe3b> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
0x195373000 - 0x1956757ff com.apple.HIToolbox (2.1.1) <9ab64c08-0685-3a0d-9a7e-83e7a1e9ebb4> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
0x188509000 - 0x1885a7f63 dyld (*) <b50f5a1a-be81-3068-92e1-3554f2be478a> /usr/lib/dyld
0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???
0x188896000 - 0x1888d249f libsystem_kernel.dylib (*) <9fe7c84d-0c2b-363f-bee5-6fd76d67a227> /usr/lib/system/libsystem_kernel.dylib
0x1888d3000 - 0x1888dfabb libsystem_pthread.dylib (*) <e95973b8-824c-361e-adf4-390747c40897> /usr/lib/system/libsystem_pthread.dylib
0x1885ac000 - 0x188600f7f libxpc.dylib (*) <8346be50-de08-3606-9fb6-9a352975661d> /usr/lib/system/libxpc.dylib
0x18871b000 - 0x188761e9f libdispatch.dylib (*) <8fb392ae-401f-399a-96ae-41531cf91162> /usr/lib/system/libdispatch.dylib
0x192ee6000 - 0x192f69fff com.apple.CoreVideo (1.8) <d8605842-8c6c-36d7-820d-2132d91e0c06> /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo
External Modification Summary:
Calls made by other processes targeting this process:
task_for_pid: 0
thread_create: 0
thread_set_state: 0
Calls made by this process:
task_for_pid: 0
thread_create: 0
thread_set_state: 0
Calls made by all processes on this machine:
task_for_pid: 0
thread_create: 0
thread_set_state: 0
VM Region Summary:
ReadOnly portion of Libraries: Total=1.8G resident=0K(0%) swapped_out_or_unallocated=1.8G(100%)
Writable regions: Total=4.7G written=1841K(0%) resident=945K(0%) swapped_out=896K(0%) unallocated=4.7G(100%)
VIRTUAL REGION
REGION TYPE SIZE COUNT (non-coalesced)
=========== ======= =======
Activity Tracing 256K 1
ColorSync 32K 2
CoreAnimation 912K 57
CoreGraphics 64K 4
CoreUI image data 240K 2
Foundation 48K 2
Kernel Alloc Once 32K 1
MALLOC 268.9M 32
MALLOC guard page 3120K 4
STACK GUARD 464K 29
Stack 53.4M 30
Stack Guard 56.0M 1
VM_ALLOCATE 4880K 41
VM_ALLOCATE (reserved) 4.0G 21 reserved VM address space (unallocated)
WebKit Malloc 400.2M 9
__AUTH 5853K 652
__AUTH_CONST 88.8M 1037
__CTF 824 1
__DATA 30.0M 988
__DATA_CONST 33.2M 1046
__DATA_DIRTY 8836K 898
__FONT_DATA 2352 1
__GLSLBUILTINS 5174K 1
__INFO_FILTER 8 1
__LINKEDIT 594.2M 5
__OBJC_RO 78.3M 1
__OBJC_RW 2567K 1
__TEXT 1.2G 1069
__TPRO_CONST 128K 2
mapped file 600.6M 75
page table in kernel 945K 1
shared memory 912K 15
=========== ======= =======
TOTAL 7.4G 6030
TOTAL, minus reserved VM space 3.4G 6030
-----------
Full Report
-----------
{"app_name":"project-graph","timestamp":"2026-02-13 15:56:49.00 +0800","app_version":"2.9.13","slice_uuid":"946c435c-f6bb-3969-9092-d73ba4a59315","build_version":"2.9.13","platform":1,"bundleID":"liren.project-graph","share_with_app_devs":0,"is_first_party":0,"bug_type":"309","os_version":"macOS 26.1 (25B78)","roots_installed":0,"name":"project-graph","incident_id":"2CD58038-FC0A-4005-9C57-8CF12FA876D5"}
{
"uptime" : 240000,
"procRole" : "Foreground",
"version" : 2,
"userID" : 501,
"deployVersion" : 210,
"modelCode" : "Mac16,12",
"coalitionID" : 1342,
"osVersion" : {
"train" : "macOS 26.1",
"build" : "25B78",
"releaseType" : "User"
},
"captureTime" : "2026-02-13 15:56:44.8734 +0800",
"codeSigningMonitor" : 2,
"incident" : "2CD58038-FC0A-4005-9C57-8CF12FA876D5",
"pid" : 68049,
"translated" : false,
"cpuType" : "ARM-64",
"roots_installed" : 0,
"bug_type" : "309",
"procLaunch" : "2026-02-13 09:40:05.9876 +0800",
"procStartAbsTime" : 5425199234391,
"procExitAbsTime" : 5967573695900,
"procName" : "project-graph",
"procPath" : "\/Applications\/Project Graph.app\/Contents\/MacOS\/project-graph",
"bundleInfo" : {"CFBundleShortVersionString":"2.9.13","CFBundleVersion":"2.9.13","CFBundleIdentifier":"liren.project-graph"},
"storeInfo" : {"deviceIdentifierForVendor":"78F3C8D6-5DAC-5F0A-85D3-F7225CCAD22B","thirdParty":true},
"parentProc" : "launchd",
"parentPid" : 1,
"coalitionName" : "liren.project-graph",
"crashReporterKey" : "B6C57097-5B06-A3FA-7F07-E57289B4D2B6",
"appleIntelligenceStatus" : {"reasons":["regionIneligible","countryBillingIneligible","countryLocationIneligible"],"state":"unavailable"},
"developerMode" : 1,
"codeSigningID" : "project_graph-908b4450466f1c40",
"codeSigningTeamID" : "",
"codeSigningFlags" : 570556929,
"codeSigningValidationCategory" : 10,
"codeSigningTrustLevel" : 4294967295,
"codeSigningAuxiliaryInfo" : 0,
"instructionByteStream" : {"beforePC":"HyAD1R8gA9UfAADx7QMAVA4AQPnQzX2S6gMAqipc7fJQGcHa7wMQqg==","atPC":"CgpA+Uv9cNNKvUCSLBxByowBCwpNEQyLsSX\/qD8BAeuBAABUSgEByg=="},
"bootSessionUUID" : "56C16D5F-59C7-4085-A8AE-12AE71F4376E",
"wakeTime" : 23429,
"sleepWakeUUID" : "5946CB7E-C783-40E2-ABF2-93A7C8E35F2C",
"sip" : "enabled",
"vmRegionInfo" : "0x6a405a1445a0 is not in any region. \n REGION TYPE START - END [ VSIZE] PRT\/MAX SHRMOD REGION DETAIL\n UNUSED SPACE AT START\n---> \n UNUSED SPACE AT END",
"exception" : {"codes":"0x0000000000000001, 0x003aea405a1445a0","rawCodes":[1,16583110759302560],"type":"EXC_BAD_ACCESS","signal":"SIGSEGV","subtype":"KERN_INVALID_ADDRESS at 0x003aea405a1445a0"},
"termination" : {"flags":0,"code":11,"namespace":"SIGNAL","indicator":"Segmentation fault: 11","byProc":"exc handler","byPid":68049},
"vmregioninfo" : "0x6a405a1445a0 is not in any region. \n REGION TYPE START - END [ VSIZE] PRT\/MAX SHRMOD REGION DETAIL\n UNUSED SPACE AT START\n---> \n UNUSED SPACE AT END",
"extMods" : {"caller":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"system":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"targeted":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"warnings":0},
"faultingThread" : 0,
"threads" : [{"threadState":{"x":[{"value":34561206448},{"value":8645138664,"objc-selector":"countByEnumeratingWithState:objects:count:"},{"value":6092886816},{"value":6092886944},{"value":16},{"value":0},{"value":18446744072631617535},{"value":18446726482597246976},{"value":4408221341312090172},{"value":8640179432,"objc-selector":"retain"},{"value":7701436872341465264},{"value":127},{"value":49},{"value":34590579456},{"value":5565017851679753621},{"value":16583110759302544},{"value":16583110759302544},{"value":8431164576},{"value":0},{"value":34578695104},{"value":1},{"value":0},{"value":34561206448},{"value":34561206448},{"value":34561205200},{"value":1},{"value":8431602040},{"value":1},{"value":4294967298}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6658294060},"cpsr":{"value":536870912},"fp":{"value":6092887168},"sp":{"value":6092886768},"esr":{"value":2449473540,"description":"(Data Abort) byte read Translation fault"},"pc":{"value":6581442592,"matchesCrashFrame":1},"far":{"value":16583110759302560}},"id":6246490,"triggered":true,"name":"main","queue":"com.apple.main-thread","frames":[{"imageOffset":38944,"symbol":"objc_msgSend","symbolLocation":32,"imageIndex":4},{"imageOffset":483628,"symbol":"-[NSPasteboard _updateTypeCacheIfNeeded]","symbolLocation":1064,"imageIndex":5},{"imageOffset":10569760,"symbol":"-[NSPasteboard _typesAtIndex:combinesItems:]","symbolLocation":36,"imageIndex":5},{"imageOffset":20167404,"symbol":"WebCore::PlatformPasteboard::informationForItemAtIndex(unsigned long, long long)","symbolLocation":172,"imageIndex":6},{"imageOffset":16918196,"symbol":"WebCore::PlatformPasteboard::allPasteboardItemInfo(long long)","symbolLocation":204,"imageIndex":6},{"imageOffset":7861628,"symbol":"WebKit::WebPasteboardProxy::grantAccessToCurrentData(WebKit::WebProcessProxy&, WTF::String const&, WTF::CompletionHandler<void ()>&&)","symbolLocation":92,"imageIndex":7},{"imageOffset":7526308,"symbol":"WebKit::WebPageProxy::grantAccessToCurrentPasteboardData(WTF::String const&, WTF::CompletionHandler<void ()>&&, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::FrameIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>>)","symbolLocation":120,"imageIndex":7},{"imageOffset":9383596,"symbol":"WebKit::WebPageProxy::willPerformPasteCommand(WebCore::DOMPasteAccessCategory, WTF::CompletionHandler<void ()>&&, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::FrameIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>>)","symbolLocation":96,"imageIndex":7},{"imageOffset":10832272,"symbol":"WebKit::WebPageProxy::executeEditCommand(WTF::String const&, WTF::String const&)","symbolLocation":352,"imageIndex":7},{"imageOffset":9467432,"symbol":"WebKit::WebViewImpl::executeEditCommandForSelector(objc_selector*, WTF::String const&)","symbolLocation":56,"imageIndex":7},{"imageOffset":6470696,"symbol":"-[WKWebView(WKImplementationMac) paste:]","symbolLocation":44,"imageIndex":7},{"imageOffset":11469060,"symbol":"-[NSApplication(NSResponder) sendAction:to:from:]","symbolLocation":560,"imageIndex":5},{"imageOffset":9806660,"symbol":"-[NSMenuItem _corePerformAction:]","symbolLocation":540,"imageIndex":5},{"imageOffset":11660924,"symbol":"_NSMenuPerformActionWithHighlighting","symbolLocation":160,"imageIndex":5},{"imageOffset":9704484,"symbol":"-[NSMenu _performKeyEquivalentForItemAtIndex:]","symbolLocation":172,"imageIndex":5},{"imageOffset":9703528,"symbol":"-[NSMenu performKeyEquivalent:]","symbolLocation":356,"imageIndex":5},{"imageOffset":11463324,"symbol":"routeKeyEquivalent","symbolLocation":444,"imageIndex":5},{"imageOffset":11455696,"symbol":"-[NSApplication(NSEventRouting) sendEvent:]","symbolLocation":1844,"imageIndex":5},{"imageOffset":4153236,"imageIndex":0},{"imageOffset":9507240,"symbol":"WebKit::WebViewImpl::doneWithKeyEvent(NSEvent*, bool)","symbolLocation":168,"imageIndex":7},{"imageOffset":229532,"symbol":"WebKit::PageClientImpl::doneWithKeyEvent(WebKit::NativeWebKeyboardEvent const&, bool)","symbolLocation":56,"imageIndex":7},{"imageOffset":10994216,"symbol":"WebKit::WebPageProxy::didReceiveEvent(IPC::Connection*, WebKit::WebEventType, bool, std::__1::optional<WebCore::RemoteUserInputEventData>&&)","symbolLocation":1168,"imageIndex":7},{"imageOffset":5271688,"symbol":"WebKit::WebPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&)","symbolLocation":7124,"imageIndex":7},{"imageOffset":17944024,"symbol":"IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&)","symbolLocation":264,"imageIndex":7},{"imageOffset":11516080,"symbol":"WebKit::WebProcessProxy::dispatchMessage(IPC::Connection&, IPC::Decoder&)","symbolLocation":40,"imageIndex":7},{"imageOffset":5400084,"symbol":"WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&)","symbolLocation":1620,"imageIndex":7},{"imageOffset":17786076,"symbol":"IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>)","symbolLocation":300,"imageIndex":7},{"imageOffset":17787404,"symbol":"IPC::Connection::dispatchIncomingMessages()","symbolLocation":536,"imageIndex":7},{"imageOffset":2068952,"symbol":"WTF::RunLoop::performWork()","symbolLocation":552,"imageIndex":8},{"imageOffset":2075600,"symbol":"WTF::RunLoop::performWork(void*)","symbolLocation":36,"imageIndex":8},{"imageOffset":391656,"symbol":"__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__","symbolLocation":28,"imageIndex":9},{"imageOffset":391548,"symbol":"__CFRunLoopDoSource0","symbolLocation":172,"imageIndex":9},{"imageOffset":390888,"symbol":"__CFRunLoopDoSources0","symbolLocation":232,"imageIndex":9},{"imageOffset":385912,"symbol":"__CFRunLoopRun","symbolLocation":820,"imageIndex":9},{"imageOffset":1147740,"symbol":"_CFRunLoopRunSpecificWithOptions","symbolLocation":532,"imageIndex":9},{"imageOffset":792424,"symbol":"RunCurrentEventLoopInMode","symbolLocation":316,"imageIndex":10},{"imageOffset":805520,"symbol":"ReceiveNextEventCommon","symbolLocation":488,"imageIndex":10},{"imageOffset":2417416,"symbol":"_BlockUntilNextEventMatchingListInMode","symbolLocation":48,"imageIndex":10},{"imageOffset":5399488,"symbol":"_DPSBlockUntilNextEventMatchingListInMode","symbolLocation":236,"imageIndex":5},{"imageOffset":130612,"symbol":"_DPSNextEvent","symbolLocation":588,"imageIndex":5},{"imageOffset":11460420,"symbol":"-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]","symbolLocation":688,"imageIndex":5},{"imageOffset":11459664,"symbol":"-[NSApplication(NSEventRouting) nextEventMatchingMask:untilDate:inMode:dequeue:]","symbolLocation":72,"imageIndex":5},{"imageOffset":100224,"symbol":"-[NSApplication run]","symbolLocation":368,"imageIndex":5},{"imageOffset":1423660,"imageIndex":0},{"imageOffset":1423284,"imageIndex":0},{"imageOffset":1423272,"imageIndex":0},{"imageOffset":1422924,"imageIndex":0},{"imageOffset":1410860,"imageIndex":0},{"imageOffset":4112,"imageIndex":0},{"imageOffset":4944,"imageIndex":0},{"imageOffset":36180,"symbol":"start","symbolLocation":7184,"imageIndex":11}]},{"id":6246504,"name":"com.apple.NSEventThread","threadState":{"x":[{"value":268451845},{"value":21592279046},{"value":8589934592},{"value":98968931401728},{"value":0},{"value":98968931401728},{"value":2},{"value":4294967295},{"value":0},{"value":17179869184},{"value":0},{"value":2},{"value":0},{"value":0},{"value":23043},{"value":0},{"value":18446744073709551569},{"value":8431213296},{"value":0},{"value":4294967295},{"value":2},{"value":98968931401728},{"value":0},{"value":98968931401728},{"value":6095184008},{"value":8589934592},{"value":21592279046},{"value":18446744073709550527},{"value":4412409862}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585749544},"cpsr":{"value":0},"fp":{"value":6095183856},"sp":{"value":6095183776},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585674804},"far":{"value":0}},"frames":[{"imageOffset":3124,"symbol":"mach_msg2_trap","symbolLocation":8,"imageIndex":13},{"imageOffset":77864,"symbol":"mach_msg2_internal","symbolLocation":76,"imageIndex":13},{"imageOffset":39308,"symbol":"mach_msg_overwrite","symbolLocation":484,"imageIndex":13},{"imageOffset":4020,"symbol":"mach_msg","symbolLocation":24,"imageIndex":13},{"imageOffset":392080,"symbol":"__CFRunLoopServiceMachPort","symbolLocation":160,"imageIndex":9},{"imageOffset":386280,"symbol":"__CFRunLoopRun","symbolLocation":1188,"imageIndex":9},{"imageOffset":1147740,"symbol":"_CFRunLoopRunSpecificWithOptions","symbolLocation":532,"imageIndex":9},{"imageOffset":720052,"symbol":"_NSEventThread","symbolLocation":184,"imageIndex":5},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246508,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":256},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6097332792},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570813760},{"value":34574244080},{"value":6097334496},{"value":0},{"value":0},{"value":256},{"value":257},{"value":512},{"value":0},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6097332912},"sp":{"value":6097332768},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246509,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":256},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6099479096},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570813952},{"value":34574244224},{"value":6099480800},{"value":0},{"value":0},{"value":256},{"value":257},{"value":512},{"value":3},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6099479216},"sp":{"value":6099479072},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246510,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":0},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6101625400},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570814016},{"value":34575026144},{"value":6101627104},{"value":0},{"value":0},{"value":0},{"value":1},{"value":256},{"value":2},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6101625520},"sp":{"value":6101625376},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246511,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":0},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6103771704},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570814080},{"value":34575025664},{"value":6103773408},{"value":0},{"value":0},{"value":0},{"value":1},{"value":256},{"value":5},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6103771824},"sp":{"value":6103771680},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246512,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":512},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6105918008},{"value":0},{"value":512},{"value":2199023256066},{"value":2199023256066},{"value":512},{"value":0},{"value":2199023256064},{"value":305},{"value":8431211416},{"value":0},{"value":34570949440},{"value":34574242928},{"value":6105919712},{"value":0},{"value":0},{"value":512},{"value":513},{"value":768},{"value":3},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6105918128},"sp":{"value":6105917984},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246513,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":256},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6108064312},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570814144},{"value":34575025808},{"value":6108066016},{"value":0},{"value":0},{"value":256},{"value":257},{"value":512},{"value":8},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6108064432},"sp":{"value":6108064288},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246514,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":256},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6110210616},{"value":0},{"value":256},{"value":1099511628034},{"value":1099511628034},{"value":256},{"value":0},{"value":1099511628032},{"value":305},{"value":8431211416},{"value":0},{"value":34570814208},{"value":34575026096},{"value":6110212320},{"value":0},{"value":0},{"value":256},{"value":257},{"value":512},{"value":1},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6110210736},"sp":{"value":6110210592},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246515,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":256},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6112356920},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570814272},{"value":34575025856},{"value":6112358624},{"value":0},{"value":0},{"value":256},{"value":257},{"value":512},{"value":2},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6112357040},"sp":{"value":6112356896},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246516,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":0},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6114503224},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570814336},{"value":34575026192},{"value":6114504928},{"value":0},{"value":0},{"value":0},{"value":1},{"value":256},{"value":5},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6114503344},"sp":{"value":6114503200},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246517,"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":5029456,"imageIndex":0},{"imageOffset":5028748,"imageIndex":0},{"imageOffset":2928268,"imageIndex":0},{"imageOffset":2927552,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}],"threadState":{"x":[{"value":260},{"value":0},{"value":256},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6116649528},{"value":0},{"value":1024},{"value":4398046512130},{"value":4398046512130},{"value":1024},{"value":0},{"value":4398046512128},{"value":305},{"value":8431211416},{"value":0},{"value":34570814400},{"value":34575025952},{"value":6116651232},{"value":0},{"value":0},{"value":256},{"value":257},{"value":512},{"value":8},{"value":4389625392}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6116649648},"sp":{"value":6116649504},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}}},{"id":6246544,"name":"WebCore: Scrolling","threadState":{"x":[{"value":268451845},{"value":21592279046},{"value":8589934592},{"value":329866373234688},{"value":0},{"value":329866373234688},{"value":2},{"value":4294967295},{"value":0},{"value":17179869184},{"value":0},{"value":2},{"value":0},{"value":0},{"value":76803},{"value":0},{"value":18446744073709551569},{"value":8431213296},{"value":0},{"value":4294967295},{"value":2},{"value":329866373234688},{"value":0},{"value":329866373234688},{"value":6118940616},{"value":8589934592},{"value":21592279046},{"value":18446744073709550527},{"value":4412409862}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585749544},"cpsr":{"value":0},"fp":{"value":6118940464},"sp":{"value":6118940384},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585674804},"far":{"value":0}},"frames":[{"imageOffset":3124,"symbol":"mach_msg2_trap","symbolLocation":8,"imageIndex":13},{"imageOffset":77864,"symbol":"mach_msg2_internal","symbolLocation":76,"imageIndex":13},{"imageOffset":39308,"symbol":"mach_msg_overwrite","symbolLocation":484,"imageIndex":13},{"imageOffset":4020,"symbol":"mach_msg","symbolLocation":24,"imageIndex":13},{"imageOffset":392080,"symbol":"__CFRunLoopServiceMachPort","symbolLocation":160,"imageIndex":9},{"imageOffset":386280,"symbol":"__CFRunLoopRun","symbolLocation":1188,"imageIndex":9},{"imageOffset":1147740,"symbol":"_CFRunLoopRunSpecificWithOptions","symbolLocation":532,"imageIndex":9},{"imageOffset":727600,"symbol":"CFRunLoopRun","symbolLocation":64,"imageIndex":9},{"imageOffset":2072984,"symbol":"WTF::Detail::CallableWrapper<WTF::RunLoop::create(WTF::ASCIILiteral, WTF::ThreadType, WTF::Thread::QOS)::$_0, void>::call()","symbolLocation":244,"imageIndex":8},{"imageOffset":2346588,"symbol":"WTF::Thread::entryPoint(WTF::Thread::NewThreadContext*)","symbolLocation":260,"imageIndex":8},{"imageOffset":29840,"symbol":"WTF::wtfThreadEntryPoint(void*)","symbolLocation":16,"imageIndex":8},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246578,"name":"Log work queue","threadState":{"x":[{"value":14},{"value":4917346528},{"value":0},{"value":6124099888},{"value":8373513120,"symbolLocation":0,"symbol":"_os_log_current_test_callback"},{"value":20},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":1498952},{"value":8408172592,"symbolLocation":0,"symbol":"OBJC_CLASS_$_OS_os_log"},{"value":8408172592,"symbolLocation":0,"symbol":"OBJC_CLASS_$_OS_os_log"},{"value":18446744073709551580},{"value":8431215768},{"value":0},{"value":4915725184},{"value":4915725224},{"value":6124105728},{"value":0},{"value":0},{"value":4915725312},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":7296706228},"cpsr":{"value":2147483648},"fp":{"value":6124105552},"sp":{"value":6124105536},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585674672},"far":{"value":0}},"frames":[{"imageOffset":2992,"symbol":"semaphore_wait_trap","symbolLocation":8,"imageIndex":13},{"imageOffset":17966772,"symbol":"IPC::StreamConnectionWorkQueue::startProcessingThread()::$_0::operator()()","symbolLocation":44,"imageIndex":7},{"imageOffset":2346588,"symbol":"WTF::Thread::entryPoint(WTF::Thread::NewThreadContext*)","symbolLocation":260,"imageIndex":8},{"imageOffset":29840,"symbol":"WTF::wtfThreadEntryPoint(void*)","symbolLocation":16,"imageIndex":8},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246619,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":768},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6126250792},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34563165440},{"value":34563271600},{"value":6126252256},{"value":0},{"value":0},{"value":768},{"value":769},{"value":1024},{"value":3},{"value":34562640160}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6126250912},"sp":{"value":6126250768},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246620,"name":"tokio-runtime-worker","threadState":{"x":[{"value":4},{"value":0},{"value":0},{"value":34590130176},{"value":1024},{"value":0},{"value":0},{"value":0},{"value":0},{"value":6128397048},{"value":0},{"value":2},{"value":0},{"value":0},{"value":0},{"value":4},{"value":363},{"value":8431213136},{"value":0},{"value":34589889304},{"value":34590130176},{"value":1000000000},{"value":34571335216},{"value":0},{"value":1000000000},{"value":34586341936},{"value":0},{"value":8},{"value":34562644000}],"flavor":"ARM_THREAD_STATE64","lr":{"value":4378632360},"cpsr":{"value":1610612736},"fp":{"value":6128397152},"sp":{"value":6128397008},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585700144},"far":{"value":0}},"frames":[{"imageOffset":28464,"symbol":"kevent","symbolLocation":8,"imageIndex":13},{"imageOffset":4661416,"imageIndex":0},{"imageOffset":4658628,"imageIndex":0},{"imageOffset":4654976,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246621,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":504320},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6130543400},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34563172928},{"value":34563270736},{"value":6130544864},{"value":0},{"value":0},{"value":504320},{"value":504321},{"value":504576},{"value":9},{"value":34562643616}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6130543520},"sp":{"value":6130543376},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246622,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":2816},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6132689704},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570828544},{"value":34575026240},{"value":6132691168},{"value":0},{"value":0},{"value":2816},{"value":2817},{"value":3072},{"value":9},{"value":34562642464}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6132689824},"sp":{"value":6132689680},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246623,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":113664},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6134836008},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570828480},{"value":34575027056},{"value":6134837472},{"value":0},{"value":0},{"value":113664},{"value":113665},{"value":113920},{"value":5},{"value":34562644768}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6134836128},"sp":{"value":6134835984},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246624,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":0},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6136982312},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570827520},{"value":34575027728},{"value":6136983776},{"value":0},{"value":0},{"value":0},{"value":1},{"value":256},{"value":1},{"value":34562645152}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6136982432},"sp":{"value":6136982288},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246625,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":625408},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6139128616},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34563165568},{"value":34563271696},{"value":6139130080},{"value":0},{"value":0},{"value":625408},{"value":625409},{"value":625664},{"value":6},{"value":34562645536}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6139128736},"sp":{"value":6139128592},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246626,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":0},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6141274920},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34570826496},{"value":34575025712},{"value":6141276384},{"value":0},{"value":0},{"value":0},{"value":1},{"value":256},{"value":0},{"value":34562645920}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6141275040},"sp":{"value":6141274896},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"threadState":{"x":[{"value":0},{"value":6143414984},{"value":0},{"value":6143414956},{"value":0},{"value":0},{"value":18446744072631617535},{"value":18446726482597246976},{"value":0},{"value":8408210216,"symbolLocation":0,"symbol":"_current_pid"},{"value":2},{"value":1099511627776},{"value":4294967293},{"value":0},{"value":0},{"value":0},{"value":18446744073709551592},{"value":8431213360},{"value":0},{"value":6143414956},{"value":0},{"value":6143414984},{"value":515},{"value":8408210344,"symbolLocation":0,"symbol":"mach_task_self_"},{"value":34561206448},{"value":687865929},{"value":34561200832},{"value":34561209952},{"value":34591780288}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585679544},"cpsr":{"value":536870912},"fp":{"value":6143414864},"sp":{"value":6143414832},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585674540},"far":{"value":0}},"id":6246627,"name":"tokio-runtime-worker","queue":"Client CFPasteboard-Apple CFPasteboard general","frames":[{"imageOffset":2860,"symbol":"_kernelrpc_mach_port_construct_trap","symbolLocation":8,"imageIndex":13},{"imageOffset":7864,"symbol":"mach_port_construct","symbolLocation":40,"imageIndex":13},{"imageOffset":200796,"symbol":"_xpc_try_mach_port_construct","symbolLocation":64,"imageIndex":15},{"imageOffset":200872,"symbol":"_xpc_mach_port_construct","symbolLocation":28,"imageIndex":15},{"imageOffset":38212,"symbol":"_xpc_mach_port_allocate","symbolLocation":36,"imageIndex":15},{"imageOffset":56304,"symbol":"xpc_connection_send_message_with_reply","symbolLocation":160,"imageIndex":15},{"imageOffset":1099640,"symbol":"-[_CFPasteboardEntry requestDataForPasteboard:generation:immediatelyAvailableResult:]","symbolLocation":1520,"imageIndex":9},{"imageOffset":379004,"symbol":"__CFPasteboardCopyData_block_invoke","symbolLocation":152,"imageIndex":9},{"imageOffset":1103908,"symbol":"____CFPasteboardPerformOnQueue_block_invoke","symbolLocation":292,"imageIndex":9},{"imageOffset":28188,"symbol":"_dispatch_block_sync_invoke","symbolLocation":240,"imageIndex":16},{"imageOffset":113348,"symbol":"_dispatch_client_callout","symbolLocation":16,"imageIndex":16},{"imageOffset":72000,"symbol":"_dispatch_lane_barrier_sync_invoke_and_complete","symbolLocation":56,"imageIndex":16},{"imageOffset":33080,"symbol":"_dispatch_sync_block_with_privdata","symbolLocation":452,"imageIndex":16},{"imageOffset":376948,"symbol":"CFPasteboardCopyData","symbolLocation":652,"imageIndex":9},{"imageOffset":10570452,"symbol":"-[NSPasteboard _dataWithoutConversionForTypeIdentifier:index:securityScoped:]","symbolLocation":432,"imageIndex":5},{"imageOffset":10572620,"symbol":"-[NSPasteboard _dataForType:index:usesPboardTypes:combinesItems:securityScoped:]","symbolLocation":272,"imageIndex":5},{"imageOffset":15654560,"symbol":"-[NSPasteboardItem __dataForType:async:completionHandler:]","symbolLocation":316,"imageIndex":5},{"imageOffset":15654828,"symbol":"-[NSPasteboardItem stringForType:]","symbolLocation":28,"imageIndex":5},{"imageOffset":2638832,"imageIndex":0},{"imageOffset":2640408,"imageIndex":0},{"imageOffset":4656140,"imageIndex":0},{"imageOffset":4677752,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6246628,"name":"tokio-runtime-worker","threadState":{"x":[{"value":260},{"value":0},{"value":723456},{"value":0},{"value":0},{"value":160},{"value":0},{"value":0},{"value":6145567528},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34563165504},{"value":34563271744},{"value":6145568992},{"value":0},{"value":0},{"value":723456},{"value":723457},{"value":723712},{"value":7},{"value":34562646688}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6145567648},"sp":{"value":6145567504},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":4658180,"imageIndex":0},{"imageOffset":4655152,"imageIndex":0},{"imageOffset":4678892,"imageIndex":0},{"imageOffset":4665508,"imageIndex":0},{"imageOffset":4665080,"imageIndex":0},{"imageOffset":4061620,"imageIndex":0},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6548446,"name":"JavaScriptCore libpas scavenger","threadState":{"x":[{"value":260},{"value":0},{"value":21455104},{"value":0},{"value":0},{"value":160},{"value":0},{"value":100000000},{"value":6093467304},{"value":0},{"value":256},{"value":1099511628034},{"value":1099511628034},{"value":256},{"value":0},{"value":1099511628032},{"value":305},{"value":8431211416},{"value":0},{"value":4764985408},{"value":4764985472},{"value":6093467872},{"value":100000000},{"value":0},{"value":21455104},{"value":44261633},{"value":44261888},{"value":8381325312,"symbolLocation":2744,"symbol":"WTF::RefLogSingleton::s_buffer"},{"value":8410828800,"symbolLocation":1816,"symbol":"bmalloc_common_primitive_heap_support"}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950428},"cpsr":{"value":1610612736},"fp":{"value":6093467424},"sp":{"value":6093467280},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28892,"symbol":"_pthread_cond_wait","symbolLocation":984,"imageIndex":14},{"imageOffset":26205816,"symbol":"scavenger_thread_main","symbolLocation":1440,"imageIndex":8},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6770305,"name":"CVDisplayLink","threadState":{"x":[{"value":260},{"value":0},{"value":0},{"value":0},{"value":0},{"value":65704},{"value":0},{"value":15638083},{"value":270710273},{"value":0},{"value":0},{"value":2},{"value":2},{"value":0},{"value":0},{"value":0},{"value":305},{"value":8431211416},{"value":0},{"value":34574594104},{"value":34574594168},{"value":1},{"value":15638083},{"value":0},{"value":0},{"value":270710273},{"value":270710528},{"value":5967573841783},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6585950472},"cpsr":{"value":2684354560},"fp":{"value":6094040496},"sp":{"value":6094040352},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585689336},"far":{"value":0}},"frames":[{"imageOffset":17656,"symbol":"__psynch_cvwait","symbolLocation":8,"imageIndex":13},{"imageOffset":28936,"symbol":"_pthread_cond_wait","symbolLocation":1028,"imageIndex":14},{"imageOffset":15164,"symbol":"CVDisplayLink::waitUntil(unsigned long long)","symbolLocation":336,"imageIndex":17},{"imageOffset":11300,"symbol":"CVDisplayLink::runIOThread()","symbolLocation":500,"imageIndex":17},{"imageOffset":27656,"symbol":"_pthread_start","symbolLocation":136,"imageIndex":14},{"imageOffset":7080,"symbol":"thread_start","symbolLocation":8,"imageIndex":14}]},{"id":6835598,"frames":[],"threadState":{"x":[{"value":6118371328},{"value":124343},{"value":6117834752},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":0},"fp":{"value":0},"sp":{"value":6118371328},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585928596},"far":{"value":0}}},{"id":6837987,"frames":[],"threadState":{"x":[{"value":6094614528},{"value":37483},{"value":6094077952},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":0},"fp":{"value":0},"sp":{"value":6094614528},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585928596},"far":{"value":0}}},{"id":6837989,"frames":[],"threadState":{"x":[{"value":6117797888},{"value":103203},{"value":6117261312},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":0},"fp":{"value":0},"sp":{"value":6117797888},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585928596},"far":{"value":0}}},{"id":6838119,"frames":[],"threadState":{"x":[{"value":6119518208},{"value":106279},{"value":6118981632},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":0},"fp":{"value":0},"sp":{"value":6119518208},"esr":{"value":1442840704,"description":"(Syscall)"},"pc":{"value":6585928596},"far":{"value":0}}}],
"usedImages" : [
{
"source" : "P",
"arch" : "arm64",
"base" : 4373970944,
"CFBundleShortVersionString" : "2.9.13",
"CFBundleIdentifier" : "liren.project-graph",
"size" : 8945664,
"uuid" : "946c435c-f6bb-3969-9092-d73ba4a59315",
"path" : "\/Applications\/Project Graph.app\/Contents\/MacOS\/project-graph",
"name" : "project-graph",
"CFBundleVersion" : "2.9.13"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 4682629120,
"size" : 49152,
"uuid" : "f8bd9069-8c4f-37ea-af9a-2b1060f54e4f",
"path" : "\/usr\/lib\/libobjc-trampolines.dylib",
"name" : "libobjc-trampolines.dylib"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 4716199936,
"CFBundleShortVersionString" : "341.11",
"CFBundleIdentifier" : "com.apple.AGXMetalG16G-B0",
"size" : 8552448,
"uuid" : "a22549f3-d4f5-3b88-af18-e06837f0d352",
"path" : "\/System\/Library\/Extensions\/AGXMetalG16G_B0.bundle\/Contents\/MacOS\/AGXMetalG16G_B0",
"name" : "AGXMetalG16G_B0",
"CFBundleVersion" : "341.11"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 4705353728,
"CFBundleShortVersionString" : "1.0",
"CFBundleIdentifier" : "com.apple.AppleMetalOpenGLRenderer",
"size" : 409600,
"uuid" : "7fba6cd5-06ae-37aa-aa67-580c920ea69d",
"path" : "\/System\/Library\/Extensions\/AppleMetalOpenGLRenderer.bundle\/Contents\/MacOS\/AppleMetalOpenGLRenderer",
"name" : "AppleMetalOpenGLRenderer",
"CFBundleVersion" : "1"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6581403648,
"size" : 341132,
"uuid" : "5a0aab4e-0c1a-3680-82c9-43dc4007a6e7",
"path" : "\/usr\/lib\/libobjc.A.dylib",
"name" : "libobjc.A.dylib"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6657810432,
"CFBundleShortVersionString" : "6.9",
"CFBundleIdentifier" : "com.apple.AppKit",
"size" : 24300448,
"uuid" : "3c0949bb-e361-369a-80b7-17440eb09e98",
"path" : "\/System\/Library\/Frameworks\/AppKit.framework\/Versions\/C\/AppKit",
"name" : "AppKit",
"CFBundleVersion" : "2685.20.119"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 7213748224,
"CFBundleShortVersionString" : "21622",
"CFBundleIdentifier" : "com.apple.WebCore",
"size" : 57751008,
"uuid" : "ccd2dfa6-ae82-311f-b824-a9aad0a6f12e",
"path" : "\/System\/Library\/Frameworks\/WebKit.framework\/Versions\/A\/Frameworks\/WebCore.framework\/Versions\/A\/WebCore",
"name" : "WebCore",
"CFBundleVersion" : "21622.2.11.11.9"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 7278739456,
"CFBundleShortVersionString" : "21622",
"CFBundleIdentifier" : "com.apple.WebKit",
"size" : 22128832,
"uuid" : "3b55482a-efe2-35a7-b1c9-3f41a823a30b",
"path" : "\/System\/Library\/Frameworks\/WebKit.framework\/Versions\/A\/WebKit",
"name" : "WebKit",
"CFBundleVersion" : "21622.2.11.11.9"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 7143546880,
"CFBundleShortVersionString" : "21622",
"CFBundleIdentifier" : "com.apple.JavaScriptCore",
"size" : 28438144,
"uuid" : "c79071c9-db50-3264-a316-94abd0d3b9a9",
"path" : "\/System\/Library\/Frameworks\/JavaScriptCore.framework\/Versions\/A\/JavaScriptCore",
"name" : "JavaScriptCore",
"CFBundleVersion" : "21622.2.11.11.9"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6586208256,
"CFBundleShortVersionString" : "6.9",
"CFBundleIdentifier" : "com.apple.CoreFoundation",
"size" : 5532352,
"uuid" : "3c4a3add-9e48-33da-82ee-80520e6cbe3b",
"path" : "\/System\/Library\/Frameworks\/CoreFoundation.framework\/Versions\/A\/CoreFoundation",
"name" : "CoreFoundation",
"CFBundleVersion" : "4109.1.401"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6798389248,
"CFBundleShortVersionString" : "2.1.1",
"CFBundleIdentifier" : "com.apple.HIToolbox",
"size" : 3155968,
"uuid" : "9ab64c08-0685-3a0d-9a7e-83e7a1e9ebb4",
"path" : "\/System\/Library\/Frameworks\/Carbon.framework\/Versions\/A\/Frameworks\/HIToolbox.framework\/Versions\/A\/HIToolbox",
"name" : "HIToolbox"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6581948416,
"size" : 651108,
"uuid" : "b50f5a1a-be81-3068-92e1-3554f2be478a",
"path" : "\/usr\/lib\/dyld",
"name" : "dyld"
},
{
"size" : 0,
"source" : "A",
"base" : 0,
"uuid" : "00000000-0000-0000-0000-000000000000"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6585671680,
"size" : 246944,
"uuid" : "9fe7c84d-0c2b-363f-bee5-6fd76d67a227",
"path" : "\/usr\/lib\/system\/libsystem_kernel.dylib",
"name" : "libsystem_kernel.dylib"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6585921536,
"size" : 51900,
"uuid" : "e95973b8-824c-361e-adf4-390747c40897",
"path" : "\/usr\/lib\/system\/libsystem_pthread.dylib",
"name" : "libsystem_pthread.dylib"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6582616064,
"size" : 348032,
"uuid" : "8346be50-de08-3606-9fb6-9a352975661d",
"path" : "\/usr\/lib\/system\/libxpc.dylib",
"name" : "libxpc.dylib"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6584119296,
"size" : 290464,
"uuid" : "8fb392ae-401f-399a-96ae-41531cf91162",
"path" : "\/usr\/lib\/system\/libdispatch.dylib",
"name" : "libdispatch.dylib"
},
{
"source" : "P",
"arch" : "arm64e",
"base" : 6760062976,
"CFBundleShortVersionString" : "1.8",
"CFBundleIdentifier" : "com.apple.CoreVideo",
"size" : 540672,
"uuid" : "d8605842-8c6c-36d7-820d-2132d91e0c06",
"path" : "\/System\/Library\/Frameworks\/CoreVideo.framework\/Versions\/A\/CoreVideo",
"name" : "CoreVideo",
"CFBundleVersion" : "726.2"
}
],
"sharedCache" : {
"base" : 6580862976,
"size" : 5609635840,
"uuid" : "b69ff43c-dbfd-3fb1-b4fe-a8fe32ea1062"
},
"vmSummary" : "ReadOnly portion of Libraries: Total=1.8G resident=0K(0%) swapped_out_or_unallocated=1.8G(100%)\nWritable regions: Total=4.7G written=1841K(0%) resident=945K(0%) swapped_out=896K(0%) unallocated=4.7G(100%)\n\n VIRTUAL REGION \nREGION TYPE SIZE COUNT (non-coalesced) \n=========== ======= ======= \nActivity Tracing 256K 1 \nColorSync 32K 2 \nCoreAnimation 912K 57 \nCoreGraphics 64K 4 \nCoreUI image data 240K 2 \nFoundation 48K 2 \nKernel Alloc Once 32K 1 \nMALLOC 268.9M 32 \nMALLOC guard page 3120K 4 \nSTACK GUARD 464K 29 \nStack 53.4M 30 \nStack Guard 56.0M 1 \nVM_ALLOCATE 4880K 41 \nVM_ALLOCATE (reserved) 4.0G 21 reserved VM address space (unallocated)\nWebKit Malloc 400.2M 9 \n__AUTH 5853K 652 \n__AUTH_CONST 88.8M 1037 \n__CTF 824 1 \n__DATA 30.0M 988 \n__DATA_CONST 33.2M 1046 \n__DATA_DIRTY 8836K 898 \n__FONT_DATA 2352 1 \n__GLSLBUILTINS 5174K 1 \n__INFO_FILTER 8 1 \n__LINKEDIT 594.2M 5 \n__OBJC_RO 78.3M 1 \n__OBJC_RW 2567K 1 \n__TEXT 1.2G 1069 \n__TPRO_CONST 128K 2 \nmapped file 600.6M 75 \npage table in kernel 945K 1 \nshared memory 912K 15 \n=========== ======= ======= \nTOTAL 7.4G 6030 \nTOTAL, minus reserved VM space 3.4G 6030 \n",
"legacyInfo" : {
"threadTriggered" : {
"name" : "main",
"queue" : "com.apple.main-thread"
}
},
"logWritingSignature" : "be58563517ee84a143ff0fa4d7387166d5414db0",
"trialInfo" : {
"rollouts" : [
{
"rolloutId" : "64628732bf2f5257dedc8988",
"factorPackIds" : [
],
"deploymentId" : 240000001
},
{
"rolloutId" : "6246d6a916a70b047e454124",
"factorPackIds" : [
],
"deploymentId" : 240000010
}
],
"experiments" : [
]
}
}
Model: Mac16,12, BootROM 13822.41.1, proc 10:4:6 processors, 24 GB, SMC
Graphics: Apple M4, Apple M4, Built-In
Display: Mi Monitor, 3840 x 2160 (2160p/4K UHD 1 - Ultra High Definition), Main, MirrorOff, Online
Display: Color LCD, 2560 x 1664 Retina, MirrorOff, Online
Memory Module: LPDDR5, Hynix
AirPort: spairport_wireless_card_type_wifi (0x14E4, 0x4388), wl0: Oct 3 2025 00:48:50 version 23.41.7.0.41.51.200 FWID 01-8b09c4e0
IO80211_driverkit-1530.16 "IO80211_driverkit-1530.16" Oct 10 2025 22:56:35
AirPort:
Bluetooth: Version (null), 0 services, 0 devices, 0 incoming serial ports
Network Service: Wi-Fi, AirPort, en0
Thunderbolt Bus: MacBook Air, Apple Inc.
Thunderbolt Bus: MacBook Air, Apple Inc.
================================================
FILE: .trae/skills/create-keybind/SKILL.md
================================================
---
name: create-keybind
description: 指导如何在 Project Graph 项目中创建新的快捷键。当用户需要添加新的快捷键、修改快捷键绑定或需要了解快捷键系统的实现方式时使用此技能。
---
# 创建新的快捷键功能
本技能指导如何在 Project Graph 项目中创建新的快捷键。
## 创建快捷键的步骤
创建新快捷键需要完成以下 4 个步骤:
### 1. 在 shortcutKeysRegister.tsx 中注册快捷键
在 `app/src/core/service/controlService/shortcutKeysEngine/shortcutKeysRegister.tsx` 文件的 `allKeyBinds` 数组中添加新的快捷键定义。
**快捷键定义结构:**
```typescript
{
id: "uniqueKeybindId", // 唯一标识符,使用驼峰命名
defaultKey: "A-S-m", // 默认快捷键组合
onPress: (project?: Project) => void, // 按下时的回调函数
onRelease?: (project?: Project) => void, // 松开时的回调函数(可选)
isGlobal?: boolean, // 是否为全局快捷键(可选,默认 false)
isUI?: boolean, // 是否为 UI 级别快捷键(可选,默认 false)
defaultEnabled?: boolean, // 默认是否启用(可选,默认 true)
}
```
**快捷键键位格式:**
- `C-` = Ctrl (Windows/Linux) 或 Command (macOS)
- `A-` = Alt (Windows/Linux) 或 Option (macOS)
- `S-` = Shift
- `M-` = Meta (macOS 上等同于 Command)
- `F11`, `F12` 等 = 功能键
- `arrowup`, `arrowdown`, `arrowleft`, `arrowright` = 方向键
- `home`, `end`, `pageup`, `pagedown` = 导航键
- `space`, `enter`, `escape` = 特殊键
- 普通字母直接写,如 `m`, `t`, `k` 等
- 多个按键用空格分隔,如 `"t t t"` 表示连续按三次 t
**注意:** Mac 系统会自动将 `C-` 和 `M-` 互换,所以不需要手动处理平台差异。
**示例:**
```typescript
{
id: "setWindowToMiniSize",
defaultKey: "A-S-m", // Alt+Shift+M
onPress: async () => {
const window = getCurrentWindow();
// 执行操作
await window.setSize(new LogicalSize(width, height));
},
isUI: true, // UI 级别快捷键,不需要项目上下文
},
```
**快捷键类型说明:**
- **项目级快捷键(默认)**:需要项目上下文,`onPress` 会接收 `project` 参数
- **UI 级别快捷键(`isUI: true`)**:不需要项目上下文,可以在没有打开项目时使用
- **全局快捷键(`isGlobal: true`)**:使用 Tauri 全局快捷键系统,即使应用不在焦点也能触发
**使用 Tauri API 时的类型处理:**
如果快捷键需要使用 Tauri 窗口 API(如 `setSize`),需要导入正确的类型:
```typescript
import { getCurrentWindow } from "@tauri-apps/api/window";
import { LogicalSize } from "@tauri-apps/api/dpi"; // 或 PhysicalSize
// 使用 LogicalSize(推荐,会自动处理 DPI 缩放)
await window.setSize(new LogicalSize(width, height));
// 或使用 PhysicalSize(物理像素)
await window.setSize(new PhysicalSize(width, height));
```
### 2. 将快捷键添加到分组中
在 `app/src/sub/SettingsWindow/keybinds.tsx` 文件的 `shortcutKeysGroups` 数组中,将新快捷键的 `id` 添加到相应的分组数组中。
**分组结构:**
```typescript
export const shortcutKeysGroups: ShortcutKeysGroup[] = [
{
title: "basic", // 分组标识符(对应翻译文件中的 key)
icon: <Keyboard />, // 分组图标
keys: [ // 该分组包含的快捷键 ID 列表
"saveFile",
"openFile",
"undo",
"redo",
// ...
],
},
{
title: "ui", // UI 控制分组
icon: <AppWindow />,
keys: [
"closeAllSubWindows",
"toggleFullscreen",
"setWindowToMiniSize", // 添加新快捷键
// ...
],
},
// ... 其他分组
];
```
**可用分组:**
- `basic` - 基础快捷键(撤销、重做、保存、打开等)
- `camera` - 摄像机控制(移动、缩放、重置视野等)
- `app` - 应用控制(切换项目、切换模式等)
- `ui` - UI 控制(关闭窗口、全屏、窗口大小等)
- `draw` - 涂鸦相关
- `select` - 切换选择
- `moveEntity` - 移动实体
- `generateTextNodeInTree` - 生长节点
- `generateTextNodeRoundedSelectedNode` - 在选中节点周围生成节点
- `aboutTextNode` - 关于文本节点(分割、合并、创建等)
- `section` - Section 框相关
- `edge` - 连线相关
- `color` - 颜色相关
- `node` - 节点相关
**分组选择指南:**
- **UI 控制(`ui`)**:窗口管理、界面切换、全屏、窗口大小等
- **基础快捷键(`basic`)**:文件操作、编辑操作(撤销、重做、复制、粘贴等)
- **摄像机控制(`camera`)**:视野移动、缩放、重置等
- **应用控制(`app`)**:项目切换、模式切换等
- **文本节点相关(`aboutTextNode`)**:节点创建、分割、合并、编辑等
- **其他**:根据功能特性选择最合适的分组
**注意:** 如果快捷键不属于任何现有分组,可以:
1. 添加到最接近的现有分组
2. 创建新的分组(需要同时更新翻译文件)
### 3. 添加翻译文本
在所有语言文件中添加翻译:
- `app/src/locales/zh_CN.yml` - 简体中文
- `app/src/locales/zh_TW.yml` - 繁体中文
- `app/src/locales/en.yml` - 英文
- `app/src/locales/zh_TWC.yml` - 繁体中文(台湾)
**翻译结构:**
在 `keyBinds` 部分添加:
```yaml
keyBinds:
keybindId:
title: "快捷键标题"
description: |
快捷键的详细描述
可以多行
说明快捷键的功能和使用场景
```
**示例:**
```yaml
keyBinds:
setWindowToMiniSize:
title: 设置窗口为迷你大小
description: |
将窗口大小设置为设置中配置的迷你窗口宽度和高度。
```
**翻译文件位置:**
- 简体中文:`app/src/locales/zh_CN.yml`
- 繁体中文:`app/src/locales/zh_TW.yml`
- 繁体中文(台湾):`app/src/locales/zh_TWC.yml`
- 英文:`app/src/locales/en.yml`
**注意:**
- 翻译键名(`keybindId`)必须与快捷键定义中的 `id` 完全一致
- 所有语言文件都需要添加翻译,否则会显示默认值或键名
### 4. 更新分组翻译(如果需要创建新分组)
如果创建了新的快捷键分组,需要在所有语言文件的 `keyBindsGroup` 部分添加分组翻译:
```yaml
keyBindsGroup:
newGroupName:
title: "新分组标题"
description: |
分组的详细描述
说明该分组包含哪些类型的快捷键
```
**示例:**
```yaml
keyBindsGroup:
ui:
title: UI控制
description: |
用于控制UI的一些功能
```
## 快捷键类型详解
### 项目级快捷键(默认)
项目级快捷键需要项目上下文,`onPress` 函数会接收 `project` 参数:
```typescript
{
id: "myKeybind",
defaultKey: "C-k",
onPress: (project) => {
if (!project) {
toast.warning("请先打开工程文件");
return;
}
// 使用 project 进行操作
project.stageManager.doSomething();
},
}
```
### UI 级别快捷键
UI 级别快捷键不需要项目上下文,可以在没有打开项目时使用:
```typescript
{
id: "myUIKeybind",
defaultKey: "A-S-m",
onPress: async () => {
// 不需要 project 参数
const window = getCurrentWindow();
await window.setSize(new LogicalSize(300, 300));
},
isUI: true, // 标记为 UI 级别
}
```
### 全局快捷键
全局快捷键使用 Tauri 全局快捷键系统,即使应用不在焦点也能触发:
```typescript
{
id: "myGlobalKeybind",
defaultKey: "CommandOrControl+Shift+G",
onPress: () => {
// 全局快捷键逻辑
},
isGlobal: true, // 标记为全局快捷键
}
```
**注意:** 全局快捷键的键位格式与普通快捷键不同,使用 `CommandOrControl+Shift+G` 格式。
## 访问快捷键配置
在代码中访问快捷键配置:
```typescript
import { KeyBindsUI } from "@/core/service/controlService/shortcutKeysEngine/KeyBindsUI";
// 获取快捷键配置
const config = await KeyBindsUI.get("keybindId");
// 修改快捷键
await KeyBindsUI.changeOneUIKeyBind("keybindId", "new-key-combination");
// 重置所有快捷键
await KeyBindsUI.resetAllKeyBinds();
```
## 注意事项
1. **快捷键 ID 命名规范:** 使用驼峰命名法(camelCase),如 `setWindowToMiniSize`
2. **唯一性:** 快捷键 ID 必须唯一,不能与现有快捷键重复
3. **默认键位:** 选择不冲突的默认键位组合
4. **类型安全:** TypeScript 会自动推断类型,确保类型一致性
5. **翻译键名:** 翻译文件中的键名必须与快捷键的 `id` 完全一致
6. **分组必须:** 所有快捷键都必须添加到 `shortcutKeysGroups` 中的相应分组,否则不会在设置页面中显示
7. **分组选择:** 根据快捷键的功能特性选择合适的分组,保持设置页面的逻辑清晰
8. **Tauri API 类型:** 使用窗口 API 时,需要使用 `LogicalSize` 或 `PhysicalSize` 类型,不能直接使用普通对象
9. **Mac 兼容性:** Mac 系统会自动将 `C-` 和 `M-` 互换,无需手动处理
10. **UI vs 项目级:** 根据快捷键是否需要项目上下文选择合适的类型
## 完整示例
假设要添加一个"设置窗口为迷你大小"的快捷键:
**1. shortcutKeysRegister.tsx - 注册快捷键:**
```typescript
import { getCurrentWindow } from "@tauri-apps/api/window";
import { LogicalSize } from "@tauri-apps/api/dpi";
import { Settings } from "@/core/service/Settings";
export const allKeyBinds: KeyBindItem[] = [
// ... 其他快捷键
{
id: "setWindowToMiniSize",
defaultKey: "A-S-m",
onPress: async () => {
const window = getCurrentWindow();
// 如果当前是最大化状态,先取消最大化
if (await window.isMaximized()) {
await window.unmaximize();
store.set(isWindowMaxsizedAtom, false);
}
// 如果当前是全屏状态,先退出全屏
if (await window.isFullscreen()) {
await window.setFullscreen(false);
}
// 设置窗口大小为设置中的迷你窗口大小
const width = Settings.windowCollapsingWidth;
const height = Settings.windowCollapsingHeight;
await window.setSize(new LogicalSize(width, height));
},
isUI: true,
},
// ... 其他快捷键
];
```
**2. keybinds.tsx - 添加到分组:**
```typescript
export const shortcutKeysGroups: ShortcutKeysGroup[] = [
// ... 其他分组
{
title: "ui",
icon: <AppWindow />,
keys: [
"closeAllSubWindows",
"toggleFullscreen",
"setWindowToMiniSize", // 添加到 UI 控制分组
// ...
],
},
// ... 其他分组
];
```
**3. zh_CN.yml - 添加翻译:**
```yaml
keyBinds:
setWindowToMiniSize:
title: 设置窗口为迷你大小
description: |
将窗口大小设置为设置中配置的迷你窗口宽度和高度。
```
**4. 其他语言文件也需要添加相应翻译**
## 快捷键键位格式参考
**修饰键:**
- `C-` = Ctrl/Command
- `A-` = Alt/Option
- `S-` = Shift
- `M-` = Meta (macOS)
**特殊键:**
- `F1` - `F12` = 功能键
- `arrowup`, `arrowdown`, `arrowleft`, `arrowright` = 方向键
- `home`, `end`, `pageup`, `pagedown` = 导航键
- `space`, `enter`, `escape`, `tab`, `backspace`, `delete` = 特殊键
**组合示例:**
- `"C-s"` = Ctrl+S
- `"A-S-m"` = Alt+Shift+M
- `"C-A-S-t"` = Ctrl+Alt+Shift+T
- `"F11"` = F11
- `"C-F11"` = Ctrl+F11
- `"t t t"` = 连续按三次 T
- `"arrowup"` = 上方向键
- `"S-arrowup"` = Shift+上方向键
## 快捷键设置页面
快捷键添加到分组后,会在设置页面的"快捷键绑定"标签页中自动显示:
1. 用户可以在设置页面查看所有快捷键
2. 用户可以自定义快捷键键位
3. 用户可以启用/禁用快捷键
4. 用户可以重置快捷键为默认值
快捷键会自动保存到 `keybinds2.json` 文件中,并在应用重启后恢复。
================================================
FILE: .trae/skills/create-setting-item/SKILL.md
================================================
---
name: create-setting-item
description: 指导如何在 Project Graph 项目中创建新的设置项。当用户需要添加新的设置项、配置选项或需要了解设置系统的实现方式时使用此技能。
---
# 创建新的设置项功能
本技能指导如何在 Project Graph 项目中创建新的设置项。
## 创建设置项的步骤
创建新设置项需要完成以下 5 个步骤:
### 1. 在 Settings.tsx 中添加 Schema 定义
在 `app/src/core/service/Settings.tsx` 文件的 `settingsSchema` 对象中添加新的设置项定义。
**支持的 Zod 类型:**
- `z.boolean().default(false)` - 布尔值开关
- `z.number().min(x).max(y).default(z)` - 数字(可添加 `.int()` 限制为整数)
- `z.string().default("")` - 字符串
- `z.union([z.literal("option1"), z.literal("option2")]).default("option1")` - 枚举选择
- `z.tuple([z.number(), z.number(), z.number(), z.number()]).default([0,0,0,0])` - 元组(如颜色 RGBA)
**示例:**
```typescript
// 布尔值设置
enableNewFeature: z.boolean().default(false),
// 数字范围设置(带滑块)
newSliderValue: z.number().min(0).max(100).int().default(50),
// 枚举选择设置
newMode: z.union([z.literal("mode1"), z.literal("mode2")]).default("mode1"),
```
### 2. 在 SettingsIcons.tsx 中添加图标
在 `app/src/core/service/SettingsIcons.tsx` 文件的 `settingsIcons` 对象中添加对应的图标。
**步骤:**
1. 从 `lucide-react` 导入合适的图标组件
2. 在 `settingsIcons` 对象中添加映射:`settingKey: IconComponent`
**示例:**
```typescript
import { NewIcon } from "lucide-react";
export const settingsIcons = {
// ... 其他设置项
enableNewFeature: NewIcon,
};
```
### 3. 添加翻译文本
在所有语言文件中添加翻译:
- `app/src/locales/zh_CN.yml` - 简体中文
- `app/src/locales/zh_TW.yml` - 繁体中文
- `app/src/locales/en.yml` - 英文
- `app/src/locales/zh_TWC.yml` - 接地气繁体中文
**翻译结构:**
```yaml
settings:
settingKey:
title: "设置项标题"
description: |
设置项的详细描述
可以多行
options: # 仅枚举类型需要
option1: "选项1显示文本"
option2: "选项2显示文本"
```
**示例:**
```yaml
settings:
enableNewFeature:
title: "启用新功能"
description: |
开启后将启用新功能特性。
此功能可能会影响性能。
newMode:
title: "新模式"
description: "选择新的模式选项"
options:
mode1: "模式一"
mode2: "模式二"
```
### 4. 将设置项添加到分组中
在 `app/src/sub/SettingsWindow/settings.tsx` 文件的 `categories` 对象中,将新设置项的键名添加到相应的分组数组中。
**分组结构:**
```typescript
const categories = {
visual: { // 一级分类:视觉
basic: [...], // 二级分组:基础
background: [...], // 二级分组:背景
node: [...], // 二级分组:节点样式
// ...
},
automation: { // 一级分类:自动化
autoNamer: [...],
autoSave: [...],
// ...
},
control: { // 一级分类:控制
mouse: [...],
cameraMove: [...],
// ...
},
performance: { // 一级分类:性能
memory: [...],
cpu: [...],
// ...
},
ai: { // 一级分类:AI
api: [...],
},
};
```
**添加设置项到分组:**
```typescript
const categories = {
visual: {
basic: [
"language",
"isClassroomMode",
"enableNewFeature", // 添加新设置项
// ...
],
},
// ...
};
```
**分组选择指南:**
- **visual(视觉)**:界面显示、主题、背景、节点样式、连线样式等
- `basic`: 基础视觉设置
- `background`: 背景相关设置
- `node`: 节点样式设置
- `edge`: 连线样式设置
- `section`: Section 框的样式设置
- `entityDetails`: 实体详情面板设置
- `debug`: 调试相关设置
- `miniWindow`: 迷你窗口设置
- `experimental`: 实验性视觉功能
- **automation(自动化)**:自动保存、自动备份、自动命名等
- `autoNamer`: 自动命名相关
- `autoSave`: 自动保存相关
- `autoBackup`: 自动备份相关
- `autoImport`: 自动导入相关
- **control(控制)**:鼠标、键盘、触摸板、相机控制等
- `mouse`: 鼠标相关设置
- `touchpad`: 触摸板设置
- `cameraMove`: 相机移动设置
- `cameraZoom`: 相机缩放设置
- `objectSelect`: 对象选择设置
- `textNode`: 文本节点编辑设置
- `edge`: 连线操作设置
- `generateNode`: 节点生成设置
- `gamepad`: 游戏手柄设置
- **performance(性能)**:内存、CPU、渲染性能相关
- `memory`: 内存相关设置
- `cpu`: CPU 相关设置
- `render`: 渲染相关设置
- `experimental`: 实验性性能功能
- **ai(AI)**:AI 相关设置
- `api`: AI API 配置
**注意:** 如果设置项不属于任何现有分组,可以:
1. 添加到最接近的现有分组
2. 在相应分类下创建新的分组(需要同时更新翻译文件中的分类结构)
### 5. 在设置页面中使用 SettingField 组件
设置项添加到分组后,会在设置页面的相应分组中自动显示。如果需要手动渲染或添加额外内容,可以使用 `SettingField` 组件:
**基本用法:**
```tsx
import { SettingField } from "@/components/ui/field";
<SettingField settingKey="enableNewFeature" />;
```
**带额外内容的用法:**
```tsx
<SettingField settingKey="enableNewFeature" extra={<Button>额外按钮</Button>} />
```
**注意:** 大多数情况下,只需要将设置项添加到 `categories` 中即可,设置页面会自动渲染。只有在需要特殊布局或额外功能时才需要手动使用 `SettingField` 组件。
## SettingField 组件的自动类型推断
`SettingField` 组件会根据 schema 定义自动渲染对应的 UI 控件:
- **字符串类型** → `Input` 输入框
- **数字类型(有 min/max)** → `Slider` 滑块 + `Input` 数字输入框
- **数字类型(无范围)** → `Input` 数字输入框
- **布尔类型** → `Switch` 开关
- **枚举类型(Union)** → `Select` 下拉选择框
## 访问设置值
在代码中访问设置值:
```typescript
import { Settings } from "@/core/service/Settings";
// 读取设置值
const value = Settings.enableNewFeature;
// 修改设置值
Settings.enableNewFeature = true;
// 监听设置变化(返回取消监听的函数)
const unsubscribe = Settings.watch("enableNewFeature", (newValue) => {
console.log("设置已更改:", newValue);
});
// React Hook 方式(在组件中使用)
const [value, setValue] = Settings.use("enableNewFeature");
```
## 注意事项
1. **设置项键名命名规范:** 使用驼峰命名法(camelCase),如 `enableNewFeature`
2. **默认值:** 所有设置项都必须提供默认值(`.default()`)
3. **类型安全:** TypeScript 会自动推断类型,确保类型一致性
4. **持久化:** 设置值会自动保存到 `settings.json` 文件中
5. **翻译键名:** 翻译文件中的键名必须与设置项的键名完全一致
6. **图标可选:** 如果不需要图标,可以不在 `settingsIcons` 中添加,组件会使用 Fragment
7. **分组必须:** 所有设置项都必须添加到 `categories` 对象中的相应分组,否则不会在设置页面中显示
8. **分组选择:** 根据设置项的功能特性选择合适的分类和分组,保持设置页面的逻辑清晰
## 完整示例
假设要添加一个"启用暗色模式"的设置项:
**1. Settings.tsx:**
```typescript
export const settingsSchema = z.object({
// ... 其他设置项
enableDarkMode: z.boolean().default(false),
});
```
**2. SettingsIcons.tsx:**
```typescript
import { Moon } from "lucide-react";
export const settingsIcons = {
// ... 其他设置项
enableDarkMode: Moon,
};
```
**3. zh_CN.yml:**
```yaml
settings:
enableDarkMode:
title: "启用暗色模式"
description: "开启后将使用暗色主题界面"
```
**4. settings.tsx - 添加到分组:**
```typescript
const categories = {
visual: {
basic: [
"language",
"isClassroomMode",
"enableDarkMode", // 添加到基础视觉设置分组
// ...
],
// ...
},
// ...
};
```
**5. 设置项会自动显示:**
设置项添加到 `categories` 后,会在设置页面的"视觉 > 基础"分组中自动显示,无需手动使用 `SettingField` 组件。
## 快捷设置栏支持
如果希望设置项出现在快捷设置栏(Quick Settings Toolbar)中,需要:
1. 确保设置项已正确创建(完成上述 4 步)
2. 快捷设置栏会自动显示所有布尔类型的设置项
3. 可以通过 `QuickSettingsManager.addQuickSetting()` 手动添加非布尔类型的设置项
================================================
FILE: .vscode/extensions.json
================================================
{
"recommendations": ["tauri-apps.tauri-vscode", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Tauri Development Debug",
"cargo": {
"args": ["build", "--manifest-path=./src-tauri/Cargo.toml", "--no-default-features"],
"cwd": "${workspaceFolder}/app"
},
"cwd": "${workspaceFolder}/app",
// task for the `beforeDevCommand` if used, must be configured in `.vscode/tasks.json`
"preLaunchTask": "ui:dev"
},
{
"type": "lldb",
"request": "launch",
"name": "Tauri Production Debug",
"cargo": {
"args": ["build", "--release", "--manifest-path=./src-tauri/Cargo.toml"],
"cwd": "${workspaceFolder}/app"
},
"cwd": "${workspaceFolder}/app",
// task for the `beforeBuildCommand` if used, must be configured in `.vscode/tasks.json`
"preLaunchTask": "ui:build"
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"i18n-ally.localesPaths": ["src/locales"],
"i18n-ally.keystyle": "nested",
"eslint.options": {
"overrideConfigFile": "./eslint.config.js"
},
"vue.server.includeLanguages": ["vue"],
"rust-analyzer.linkedProjects": ["app/src-tauri/Cargo.toml"],
"files.associations": {
"*.pg-theme": "yaml"
},
"todo-tree.tree.disableCompactFolders": false,
"todo-tree.tree.scanMode": "workspace only",
"typescript.tsdk": "app/node_modules/typescript/lib"
}
================================================
FILE: .vscode/tasks.json
================================================
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "ui:dev",
"type": "shell",
// `dev` keeps running in the background
// ideally you should also configure a `problemMatcher`
// see https://code.visualstudio.com/docs/editor/tasks#_can-a-background-task-be-used-as-a-prelaunchtask-in-launchjson
"isBackground": true,
// change this to your `beforeDevCommand`:
"command": "pnpm",
"args": ["dev"]
},
{
"label": "ui:build",
"type": "shell",
// change this to your `beforeBuildCommand`:
"command": "pnpm",
"args": ["build"]
}
]
}
================================================
FILE: .zed/settings.json
================================================
// Folder-specific settings
//
// For a full list of overridable settings, and general information on folder-specific settings,
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
{
"file_types": {
"YAML": ["*.pg-theme"]
},
"lsp": {
"vtsls": {
"settings": {
"typescript": {
"tsdk": "app/node_modules/typescript/lib"
}
}
}
}
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
support@project-graph.top.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: CONTRIBUTING.md
================================================
Please refer to [Contributing](https://project-graph.top/docs/contribute)
================================================
FILE: TODO.md
================================================
================================================
FILE: app/.browserslistrc
================================================
Chrome>=111, Edge>=111, Android>=111, Safari>=16.4
================================================
FILE: app/LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exe
gitextract_v1_e28b6/ ├── .cursor/ │ └── skills/ │ ├── create-keybind/ │ │ └── SKILL.md │ └── create-setting-item/ │ └── SKILL.md ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── config.yml │ │ └── no-issues.yml │ ├── copilot-instructions.md │ ├── scripts/ │ │ ├── enable-sourcemap.mjs │ │ ├── generate-changelog.mjs │ │ ├── generate-pkgbuild.mjs │ │ ├── set-tauri-features.mjs │ │ └── set-version.mjs │ └── workflows/ │ ├── nightly.yml │ ├── publish.yml │ ├── release.yml │ └── render-docs-svg.yml ├── .gitignore ├── .husky/ │ └── pre-commit ├── .lintstagedrc ├── .prettierignore ├── .prettierrc ├── .trae/ │ ├── documents/ │ │ ├── plan_20251223_165257.md │ │ ├── plan_20260101_170503.md │ │ ├── 为LineEdge添加虚线形态属性.md │ │ ├── 为RecentFilesWindow添加独立的隐私模式功能.md │ │ ├── 优化Tab键和反斜杠键创建节点的字体大小.md │ │ ├── 优化嫁接操作与添加反向操作.md │ │ ├── 优化文本节点渲染判断逻辑.md │ │ ├── 修复Ctrl+T快捷键只能触发一个功能的问题.md │ │ ├── 修复引用块转换时连线悬空问题.md │ │ ├── 全局快捷键重构方案.md │ │ ├── 在快捷键设置页面添加重置所有快捷键按钮.md │ │ ├── 实现 Section 的 isHidden 属性功能.md │ │ ├── 实现Section框大标题相机缩放阈值控制.md │ │ ├── 实现关闭软件前的未保存文件警告.md │ │ ├── 实现图片节点拖拽缩放功能.md │ │ ├── 实现引用块节点的精准连线定位.md │ │ ├── 实现快捷键开关功能.md │ │ ├── 实现搜索范围选项.md │ │ ├── 实现背景图片功能和背景管理器.md │ │ ├── 引用块节点精准连线定位功能问题记录.md │ │ ├── 文本节点自定义文字大小功能设计方案.md │ │ ├── 添加大标题遮罩透明度设置.md │ │ ├── 添加快捷键冲突检测和提醒功能.md │ │ └── 粘贴bug崩溃报告.txt │ └── skills/ │ ├── create-keybind/ │ │ └── SKILL.md │ └── create-setting-item/ │ └── SKILL.md ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── .zed/ │ └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── TODO.md ├── app/ │ ├── .browserslistrc │ ├── LICENSE │ ├── README.md │ ├── components.json │ ├── index.html │ ├── package.json │ ├── scripts/ │ │ ├── sync-locales.ts │ │ └── tauri_build.js │ ├── splash.html │ ├── src/ │ │ ├── App.tsx │ │ ├── DropWindowCover.tsx │ │ ├── ProjectTabs.tsx │ │ ├── assets/ │ │ │ └── versions.json │ │ ├── cli.tsx │ │ ├── components/ │ │ │ ├── context-menu-content.tsx │ │ │ ├── editor/ │ │ │ │ ├── editor-base-kit.tsx │ │ │ │ ├── plugins/ │ │ │ │ │ ├── align-base-kit.tsx │ │ │ │ │ ├── basic-blocks-base-kit.tsx │ │ │ │ │ ├── basic-blocks-kit.tsx │ │ │ │ │ ├── basic-marks-base-kit.tsx │ │ │ │ │ ├── basic-marks-kit.tsx │ │ │ │ │ ├── callout-base-kit.tsx │ │ │ │ │ ├── code-block-base-kit.tsx │ │ │ │ │ ├── code-block-kit.tsx │ │ │ │ │ ├── column-base-kit.tsx │ │ │ │ │ ├── comment-base-kit.tsx │ │ │ │ │ ├── comment-kit.tsx │ │ │ │ │ ├── date-base-kit.tsx │ │ │ │ │ ├── discussion-kit.tsx │ │ │ │ │ ├── fixed-toolbar-kit.tsx │ │ │ │ │ ├── floating-toolbar-kit.tsx │ │ │ │ │ ├── font-base-kit.tsx │ │ │ │ │ ├── font-kit.tsx │ │ │ │ │ ├── indent-base-kit.tsx │ │ │ │ │ ├── indent-kit.tsx │ │ │ │ │ ├── line-height-base-kit.tsx │ │ │ │ │ ├── link-base-kit.tsx │ │ │ │ │ ├── link-kit.tsx │ │ │ │ │ ├── list-base-kit.tsx │ │ │ │ │ ├── list-kit.tsx │ │ │ │ │ ├── markdown-kit.tsx │ │ │ │ │ ├── math-base-kit.tsx │ │ │ │ │ ├── math-kit.tsx │ │ │ │ │ ├── media-base-kit.tsx │ │ │ │ │ ├── mention-base-kit.tsx │ │ │ │ │ ├── suggestion-base-kit.tsx │ │ │ │ │ ├── suggestion-kit.tsx │ │ │ │ │ ├── table-base-kit.tsx │ │ │ │ │ ├── table-kit.tsx │ │ │ │ │ ├── toc-base-kit.tsx │ │ │ │ │ └── toggle-base-kit.tsx │ │ │ │ └── transforms.ts │ │ │ ├── key-tooltip.tsx │ │ │ ├── render-sub-windows.tsx │ │ │ ├── right-toolbar.tsx │ │ │ ├── theme-mode-switch.tsx │ │ │ ├── toolbar-content.tsx │ │ │ ├── ui/ │ │ │ │ ├── ai-node.tsx │ │ │ │ ├── ai-toolbar-button.tsx │ │ │ │ ├── alert-dialog.tsx │ │ │ │ ├── alert.tsx │ │ │ │ ├── align-toolbar-button.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── block-discussion.tsx │ │ │ │ ├── block-list-static.tsx │ │ │ │ ├── block-list.tsx │ │ │ │ ├── block-selection.tsx │ │ │ │ ├── block-suggestion.tsx │ │ │ │ ├── blockquote-node-static.tsx │ │ │ │ ├── blockquote-node.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── calendar.tsx │ │ │ │ ├── callout-node-static.tsx │ │ │ │ ├── callout-node.tsx │ │ │ │ ├── caption.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── checkbox.tsx │ │ │ │ ├── code-block-node-static.tsx │ │ │ │ ├── code-block-node.tsx │ │ │ │ ├── code-node-static.tsx │ │ │ │ ├── code-node.tsx │ │ │ │ ├── collapsible.tsx │ │ │ │ ├── column-node-static.tsx │ │ │ │ ├── column-node.tsx │ │ │ │ ├── command.tsx │ │ │ │ ├── comment-node-static.tsx │ │ │ │ ├── comment-node.tsx │ │ │ │ ├── comment-toolbar-button.tsx │ │ │ │ ├── comment.tsx │ │ │ │ ├── context-menu.tsx │ │ │ │ ├── date-node-static.tsx │ │ │ │ ├── date-node.tsx │ │ │ │ ├── dialog.tsx │ │ │ │ ├── dropdown-menu.tsx │ │ │ │ ├── editor-static.tsx │ │ │ │ ├── editor.tsx │ │ │ │ ├── emoji-node.tsx │ │ │ │ ├── emoji-toolbar-button.tsx │ │ │ │ ├── equation-node-static.tsx │ │ │ │ ├── equation-node.tsx │ │ │ │ ├── equation-toolbar-button.tsx │ │ │ │ ├── export-toolbar-button.tsx │ │ │ │ ├── field.tsx │ │ │ │ ├── file-chooser.tsx │ │ │ │ ├── fixed-toolbar-buttons.tsx │ │ │ │ ├── fixed-toolbar.tsx │ │ │ │ ├── floating-toolbar-buttons.tsx │ │ │ │ ├── floating-toolbar.tsx │ │ │ │ ├── font-color-toolbar-button.tsx │ │ │ │ ├── font-size-toolbar-button.tsx │ │ │ │ ├── heading-node-static.tsx │ │ │ │ ├── heading-node.tsx │ │ │ │ ├── highlight-node-static.tsx │ │ │ │ ├── highlight-node.tsx │ │ │ │ ├── history-toolbar-button.tsx │ │ │ │ ├── hr-node-static.tsx │ │ │ │ ├── hr-node.tsx │ │ │ │ ├── import-toolbar-button.tsx │ │ │ │ ├── indent-toolbar-button.tsx │ │ │ │ ├── inline-combobox.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── insert-toolbar-button.tsx │ │ │ │ ├── kbd-node-static.tsx │ │ │ │ ├── kbd-node.tsx │ │ │ │ ├── key-bind.tsx │ │ │ │ ├── line-height-toolbar-button.tsx │ │ │ │ ├── link-node-static.tsx │ │ │ │ ├── link-node.tsx │ │ │ │ ├── link-toolbar-button.tsx │ │ │ │ ├── link-toolbar.tsx │ │ │ │ ├── list-toolbar-button.tsx │ │ │ │ ├── mark-toolbar-button.tsx │ │ │ │ ├── markdown.tsx │ │ │ │ ├── media-audio-node-static.tsx │ │ │ │ ├── media-audio-node.tsx │ │ │ │ ├── media-file-node-static.tsx │ │ │ │ ├── media-file-node.tsx │ │ │ │ ├── media-image-node-static.tsx │ │ │ │ ├── media-image-node.tsx │ │ │ │ ├── media-toolbar-button.tsx │ │ │ │ ├── media-toolbar.tsx │ │ │ │ ├── media-video-node-static.tsx │ │ │ │ ├── media-video-node.tsx │ │ │ │ ├── mention-node-static.tsx │ │ │ │ ├── mention-node.tsx │ │ │ │ ├── menubar.tsx │ │ │ │ ├── mode-toolbar-button.tsx │ │ │ │ ├── more-toolbar-button.tsx │ │ │ │ ├── paragraph-node-static.tsx │ │ │ │ ├── paragraph-node.tsx │ │ │ │ ├── popover.tsx │ │ │ │ ├── progress.tsx │ │ │ │ ├── resize-handle.tsx │ │ │ │ ├── select.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── sheet.tsx │ │ │ │ ├── sidebar.tsx │ │ │ │ ├── skeleton.tsx │ │ │ │ ├── slider.tsx │ │ │ │ ├── sonner.tsx │ │ │ │ ├── suggestion-node-static.tsx │ │ │ │ ├── suggestion-node.tsx │ │ │ │ ├── suggestion-toolbar-button.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── table-icons.tsx │ │ │ │ ├── table-node-static.tsx │ │ │ │ ├── table-node.tsx │ │ │ │ ├── table-toolbar-button.tsx │ │ │ │ ├── tabs.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ ├── toc-node-static.tsx │ │ │ │ ├── toc-node.tsx │ │ │ │ ├── toggle-node-static.tsx │ │ │ │ ├── toggle-node.tsx │ │ │ │ ├── toggle-toolbar-button.tsx │ │ │ │ ├── toolbar.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ ├── tree.tsx │ │ │ │ └── turn-into-toolbar-button.tsx │ │ │ ├── vditor-panel.tsx │ │ │ └── welcome-page.tsx │ │ ├── core/ │ │ │ ├── Project.tsx │ │ │ ├── algorithm/ │ │ │ │ ├── arrayFunctions.tsx │ │ │ │ ├── geometry/ │ │ │ │ │ ├── README.md │ │ │ │ │ └── convexHull.tsx │ │ │ │ ├── numberFunctions.tsx │ │ │ │ ├── random.tsx │ │ │ │ └── setFunctions.tsx │ │ │ ├── fileSystemProvider/ │ │ │ │ ├── FileSystemProviderDraft.tsx │ │ │ │ └── FileSystemProviderFile.tsx │ │ │ ├── interfaces/ │ │ │ │ └── Service.tsx │ │ │ ├── loadAllServices.tsx │ │ │ ├── plugin/ │ │ │ │ ├── PluginCodeParseData.tsx │ │ │ │ ├── PluginWorker.tsx │ │ │ │ ├── README.md │ │ │ │ ├── UserScriptsManager.tsx │ │ │ │ ├── apis.tsx │ │ │ │ └── types.tsx │ │ │ ├── render/ │ │ │ │ ├── 3d/ │ │ │ │ │ └── README.md │ │ │ │ ├── canvas2d/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── basicRenderer/ │ │ │ │ │ │ ├── ImageRenderer.tsx │ │ │ │ │ │ ├── curveRenderer.tsx │ │ │ │ │ │ ├── shapeRenderer.tsx │ │ │ │ │ │ ├── svgRenderer.tsx │ │ │ │ │ │ └── textRenderer.tsx │ │ │ │ │ ├── controllerRenderer/ │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ └── drawingRenderer.tsx │ │ │ │ │ ├── debugRender.tsx │ │ │ │ │ ├── entityRenderer/ │ │ │ │ │ │ ├── CollisionBoxRenderer.tsx │ │ │ │ │ │ ├── EntityDetailsButtonRenderer.tsx │ │ │ │ │ │ ├── EntityRenderer.tsx │ │ │ │ │ │ ├── ReferenceBlockRenderer.tsx │ │ │ │ │ │ ├── edge/ │ │ │ │ │ │ │ ├── EdgeRenderer.tsx │ │ │ │ │ │ │ ├── EdgeRendererClass.tsx │ │ │ │ │ │ │ └── concrete/ │ │ │ │ │ │ │ ├── StraightEdgeRenderer.tsx │ │ │ │ │ │ │ ├── SymmetryCurveEdgeRenderer.tsx │ │ │ │ │ │ │ └── VerticalPolyEdgeRenderer.tsx │ │ │ │ │ │ ├── multiTargetUndirectedEdge/ │ │ │ │ │ │ │ └── MultiTargetUndirectedEdgeRenderer.tsx │ │ │ │ │ │ ├── section/ │ │ │ │ │ │ │ └── SectionRenderer.tsx │ │ │ │ │ │ ├── svgNode/ │ │ │ │ │ │ │ └── SvgNodeRenderer.tsx │ │ │ │ │ │ ├── textNode/ │ │ │ │ │ │ │ └── TextNodeRenderer.tsx │ │ │ │ │ │ └── urlNode/ │ │ │ │ │ │ └── urlNodeRenderer.tsx │ │ │ │ │ ├── renderer.tsx │ │ │ │ │ └── utilsRenderer/ │ │ │ │ │ ├── RenderUtils.tsx │ │ │ │ │ ├── WorldRenderUtils.tsx │ │ │ │ │ ├── backgroundRenderer.tsx │ │ │ │ │ ├── globalMaskRenderer.tsx │ │ │ │ │ └── searchContentHighlightRenderer.tsx │ │ │ │ ├── domElement/ │ │ │ │ │ ├── RectangleElement.tsx │ │ │ │ │ └── inputElement.tsx │ │ │ │ └── svg/ │ │ │ │ ├── README.md │ │ │ │ └── SvgUtils.tsx │ │ │ ├── service/ │ │ │ │ ├── AssetsRepository.tsx │ │ │ │ ├── FeatureFlags.tsx │ │ │ │ ├── GlobalMenu.tsx │ │ │ │ ├── QuickSettingsManager.tsx │ │ │ │ ├── Settings.tsx │ │ │ │ ├── SettingsIcons.tsx │ │ │ │ ├── SubWindow.tsx │ │ │ │ ├── Telemetry.tsx │ │ │ │ ├── Themes.tsx │ │ │ │ ├── Tourials.tsx │ │ │ │ ├── UserState.tsx │ │ │ │ ├── controlService/ │ │ │ │ │ ├── DirectionKeyUtilsEngine/ │ │ │ │ │ │ └── directionKeyUtilsEngine.tsx │ │ │ │ │ ├── MouseLocation.tsx │ │ │ │ │ ├── autoLayoutEngine/ │ │ │ │ │ │ ├── autoLayoutFastTreeMode.tsx │ │ │ │ │ │ └── mainTick.tsx │ │ │ │ │ ├── controller/ │ │ │ │ │ │ ├── Controller.tsx │ │ │ │ │ │ ├── ControllerClass.tsx │ │ │ │ │ │ └── concrete/ │ │ │ │ │ │ ├── ControllerAssociationReshape.tsx │ │ │ │ │ │ ├── ControllerCamera/ │ │ │ │ │ │ │ └── mac.tsx │ │ │ │ │ │ ├── ControllerCamera.tsx │ │ │ │ │ │ ├── ControllerContextMenu.tsx │ │ │ │ │ │ ├── ControllerCutting.tsx │ │ │ │ │ │ ├── ControllerEdgeEdit.tsx │ │ │ │ │ │ ├── ControllerEntityClickSelectAndMove.tsx │ │ │ │ │ │ ├── ControllerEntityCreate.tsx │ │ │ │ │ │ ├── ControllerEntityLayerMoving.tsx │ │ │ │ │ │ ├── ControllerEntityResize.tsx │ │ │ │ │ │ ├── ControllerImageScale.tsx │ │ │ │ │ │ ├── ControllerNodeConnection.tsx │ │ │ │ │ │ ├── ControllerNodeEdit.tsx │ │ │ │ │ │ ├── ControllerPenStrokeControl.tsx │ │ │ │ │ │ ├── ControllerPenStrokeDrawing.tsx │ │ │ │ │ │ ├── ControllerRectangleSelect.tsx │ │ │ │ │ │ ├── ControllerSectionEdit.tsx │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ └── utilsControl.tsx │ │ │ │ │ ├── keyboardOnlyEngine/ │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── keyboardOnlyDirectionController.tsx │ │ │ │ │ │ ├── keyboardOnlyEngine.tsx │ │ │ │ │ │ ├── keyboardOnlyGraphEngine.tsx │ │ │ │ │ │ ├── keyboardOnlyTreeEngine.tsx │ │ │ │ │ │ ├── newTargetLocationSelector.tsx │ │ │ │ │ │ └── selectChangeEngine.tsx │ │ │ │ │ ├── rectangleSelectEngine/ │ │ │ │ │ │ └── rectangleSelectEngine.tsx │ │ │ │ │ ├── shortcutKeysEngine/ │ │ │ │ │ │ ├── GlobalShortcutManager.tsx │ │ │ │ │ │ ├── KeyBinds.tsx │ │ │ │ │ │ ├── KeyBindsUI.tsx │ │ │ │ │ │ ├── ShortcutKeyFixer.tsx │ │ │ │ │ │ └── shortcutKeysRegister.tsx │ │ │ │ │ └── stageMouseInteractionCore/ │ │ │ │ │ └── stageMouseInteractionCore.tsx │ │ │ │ ├── dataFileService/ │ │ │ │ │ ├── AutoSaveBackupService.tsx │ │ │ │ │ ├── RecentFileManager.tsx │ │ │ │ │ └── StartFilesManager.tsx │ │ │ │ ├── dataGenerateService/ │ │ │ │ │ ├── autoComputeEngine/ │ │ │ │ │ │ ├── AutoComputeUtils.tsx │ │ │ │ │ │ ├── functions/ │ │ │ │ │ │ │ ├── compareLogic.tsx │ │ │ │ │ │ │ ├── mathLogic.tsx │ │ │ │ │ │ │ ├── nodeLogic.tsx │ │ │ │ │ │ │ ├── programLogic.tsx │ │ │ │ │ │ │ └── stringLogic.tsx │ │ │ │ │ │ ├── logicNodeNameEnum.tsx │ │ │ │ │ │ └── mainTick.tsx │ │ │ │ │ ├── crossFileContentQuery.tsx │ │ │ │ │ ├── dataTransferEngine/ │ │ │ │ │ │ └── dataTransferEngine.tsx │ │ │ │ │ ├── generateFromFolderEngine/ │ │ │ │ │ │ └── GenerateFromFolderEngine.tsx │ │ │ │ │ ├── generateScreenshot.tsx │ │ │ │ │ ├── stageExportEngine/ │ │ │ │ │ │ ├── BaseExporter.tsx │ │ │ │ │ │ ├── MarkdownExporter.tsx │ │ │ │ │ │ ├── MermaidExporter.tsx │ │ │ │ │ │ ├── PlainTextExporter.tsx │ │ │ │ │ │ ├── StageExportPng.tsx │ │ │ │ │ │ ├── StageExportSvg.tsx │ │ │ │ │ │ ├── TabExporter.tsx │ │ │ │ │ │ └── stageExportEngine.tsx │ │ │ │ │ └── stageImportEngine/ │ │ │ │ │ ├── BaseImporter.tsx │ │ │ │ │ ├── GraphImporter.tsx │ │ │ │ │ ├── MarkdownImporter.tsx │ │ │ │ │ ├── MermaidImporter.tsx │ │ │ │ │ ├── TreeImporter.tsx │ │ │ │ │ └── stageImportEngine.tsx │ │ │ │ ├── dataManageService/ │ │ │ │ │ ├── ComplexityDetector.tsx │ │ │ │ │ ├── aiEngine/ │ │ │ │ │ │ ├── AIEngine.tsx │ │ │ │ │ │ └── AITools.tsx │ │ │ │ │ ├── colorSmartTools.tsx │ │ │ │ │ ├── connectNodeSmartTools.tsx │ │ │ │ │ ├── contentSearchEngine/ │ │ │ │ │ │ └── contentSearchEngine.tsx │ │ │ │ │ ├── copyEngine/ │ │ │ │ │ │ ├── VirtualClipboard.tsx │ │ │ │ │ │ ├── copyEngine.tsx │ │ │ │ │ │ ├── copyEngineImage.tsx │ │ │ │ │ │ ├── copyEngineText.tsx │ │ │ │ │ │ ├── copyEngineUtils.tsx │ │ │ │ │ │ └── stringValidTools.tsx │ │ │ │ │ ├── dragFileIntoStageEngine/ │ │ │ │ │ │ └── dragFileIntoStageEngine.tsx │ │ │ │ │ └── textNodeSmartTools.tsx │ │ │ │ └── feedbackService/ │ │ │ │ ├── ColorManager.tsx │ │ │ │ ├── SoundService.tsx │ │ │ │ ├── effectEngine/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── concrete/ │ │ │ │ │ │ ├── CircleChangeRadiusEffect.tsx │ │ │ │ │ │ ├── CircleFlameEffect.tsx │ │ │ │ │ │ ├── EdgeCutEffect.tsx │ │ │ │ │ │ ├── EntityAlignEffect.tsx │ │ │ │ │ │ ├── EntityCreateFlashEffect.tsx │ │ │ │ │ │ ├── EntityDashTipEffect.tsx │ │ │ │ │ │ ├── EntityJumpMoveEffect.tsx │ │ │ │ │ │ ├── EntityShakeEffect.tsx │ │ │ │ │ │ ├── EntityShrinkEffect.tsx │ │ │ │ │ │ ├── ExplodeDashEffect.tsx │ │ │ │ │ │ ├── LineCuttingEffect.tsx │ │ │ │ │ │ ├── LineEffect.tsx │ │ │ │ │ │ ├── MouseTipFeedbackEffect.tsx │ │ │ │ │ │ ├── NodeMoveShadowEffect.tsx │ │ │ │ │ │ ├── PenStrokeDeletedEffect.tsx │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── RectangleLittleNoteEffect.tsx │ │ │ │ │ │ ├── RectangleNoteEffect.tsx │ │ │ │ │ │ ├── RectangleNoteReversedEffect.tsx │ │ │ │ │ │ ├── RectanglePushInEffect.tsx │ │ │ │ │ │ ├── RectangleRenderEffect.tsx │ │ │ │ │ │ ├── RectangleSlideEffect.tsx │ │ │ │ │ │ ├── RectangleSplitTwoPartEffect.tsx │ │ │ │ │ │ ├── TextRaiseEffectLocated.tsx │ │ │ │ │ │ ├── ViewFlashEffect.tsx │ │ │ │ │ │ └── ViewOutlineFlashEffect.tsx │ │ │ │ │ ├── effectElements/ │ │ │ │ │ │ └── effectParticle.tsx │ │ │ │ │ ├── effectMachine.tsx │ │ │ │ │ ├── effectObject.tsx │ │ │ │ │ └── mathTools/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── animateFunctions.tsx │ │ │ │ │ ├── easings.tsx │ │ │ │ │ └── rateFunctions.tsx │ │ │ │ └── stageStyle/ │ │ │ │ ├── README.md │ │ │ │ ├── StageStyleManager.tsx │ │ │ │ └── stageStyle.tsx │ │ │ └── stage/ │ │ │ ├── Camera.tsx │ │ │ ├── Canvas.tsx │ │ │ ├── ProjectUpgrader.tsx │ │ │ ├── stageManager/ │ │ │ │ ├── StageHistoryManager.tsx │ │ │ │ ├── StageManager.tsx │ │ │ │ ├── basicMethods/ │ │ │ │ │ ├── GraphMethods.tsx │ │ │ │ │ ├── PenStrokeMethods.tsx │ │ │ │ │ └── SectionMethods.tsx │ │ │ │ └── concreteMethods/ │ │ │ │ ├── LayoutManager.tsx │ │ │ │ ├── README.md │ │ │ │ ├── SectionCollisionSolver.tsx │ │ │ │ ├── StageAutoAlignManager.tsx │ │ │ │ ├── StageDeleteManager.tsx │ │ │ │ ├── StageEntityMoveManager.tsx │ │ │ │ ├── StageManagerUtils.tsx │ │ │ │ ├── StageMultiTargetEdgeMove.tsx │ │ │ │ ├── StageNodeAdder.tsx │ │ │ │ ├── StageNodeConnector.tsx │ │ │ │ ├── StageObjectColorManager.tsx │ │ │ │ ├── StageObjectSelectCounter.tsx │ │ │ │ ├── StageReferenceManager.tsx │ │ │ │ ├── StageSectionInOutManager.tsx │ │ │ │ ├── StageSectionPackManager.tsx │ │ │ │ ├── StageTagManager.tsx │ │ │ │ └── stageNodeRotate.tsx │ │ │ └── stageObject/ │ │ │ ├── README.md │ │ │ ├── abstract/ │ │ │ │ ├── Association.tsx │ │ │ │ ├── ConnectableEntity.tsx │ │ │ │ ├── StageEntity.tsx │ │ │ │ ├── StageObject.tsx │ │ │ │ └── StageObjectInterface.tsx │ │ │ ├── association/ │ │ │ │ ├── CubicCatmullRomSplineEdge.tsx │ │ │ │ ├── Edge.tsx │ │ │ │ ├── EdgeCollisionBoxGetter.tsx │ │ │ │ ├── LineEdge.tsx │ │ │ │ └── MutiTargetUndirectedEdge.tsx │ │ │ ├── collisionBox/ │ │ │ │ └── collisionBox.tsx │ │ │ ├── entity/ │ │ │ │ ├── ConnectPoint.tsx │ │ │ │ ├── ImageNode.tsx │ │ │ │ ├── PenStroke.tsx │ │ │ │ ├── ReferenceBlockNode.tsx │ │ │ │ ├── Section.tsx │ │ │ │ ├── SvgNode.tsx │ │ │ │ ├── TextNode.tsx │ │ │ │ └── UrlNode.tsx │ │ │ └── tools/ │ │ │ └── entityDetailsManager.tsx │ │ ├── css/ │ │ │ ├── index.css │ │ │ └── markdown.css │ │ ├── examples/ │ │ │ └── tauri-global-shortcut-guide.md │ │ ├── hooks/ │ │ │ ├── use-debounce.ts │ │ │ ├── use-mobile.ts │ │ │ └── use-mounted.ts │ │ ├── locales/ │ │ │ ├── README.md │ │ │ ├── en.yml │ │ │ ├── id.yml │ │ │ ├── zh_CN.yml │ │ │ ├── zh_TW.yml │ │ │ └── zh_TWC.yml │ │ ├── main.tsx │ │ ├── state.tsx │ │ ├── sub/ │ │ │ ├── AIToolsWindow.tsx │ │ │ ├── AIWindow.tsx │ │ │ ├── AttachmentsWindow.tsx │ │ │ ├── AutoCompleteWindow.tsx │ │ │ ├── AutoComputeWindow.tsx │ │ │ ├── BackgroundManagerWindow.tsx │ │ │ ├── ColorPaletteWindow.tsx │ │ │ ├── ColorWindow.tsx │ │ │ ├── ExportPngWindow.tsx │ │ │ ├── FindWindow.tsx │ │ │ ├── GenerateNodeWindow.tsx │ │ │ ├── KeyboardRecentFilesWindow.tsx │ │ │ ├── LoginWindow.tsx │ │ │ ├── NewExportPngWindow.tsx │ │ │ ├── NodeDetailsWindow.tsx │ │ │ ├── OnboardingWindow.tsx │ │ │ ├── RecentFilesWindow.tsx │ │ │ ├── ReferencesWindow.tsx │ │ │ ├── SettingsWindow/ │ │ │ │ ├── about.tsx │ │ │ │ ├── appearance/ │ │ │ │ │ ├── effects.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── sounds.tsx │ │ │ │ ├── assets/ │ │ │ │ │ └── font.css │ │ │ │ ├── credits.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── keybinds.tsx │ │ │ │ ├── keybindsGlobal.tsx │ │ │ │ ├── quick-settings.tsx │ │ │ │ ├── settings.tsx │ │ │ │ └── themes/ │ │ │ │ ├── editor.tsx │ │ │ │ └── index.tsx │ │ │ ├── TagWindow.tsx │ │ │ ├── TestWindow.tsx │ │ │ └── UserWindow.tsx │ │ ├── themes/ │ │ │ ├── dark-blue.pg-theme │ │ │ ├── dark.pg-theme │ │ │ ├── light.pg-theme │ │ │ ├── macaron.pg-theme │ │ │ ├── morandi.pg-theme │ │ │ └── park.pg-theme │ │ ├── types/ │ │ │ ├── cursors.tsx │ │ │ ├── directions.tsx │ │ │ ├── metadata.tsx │ │ │ └── node.tsx │ │ ├── utils/ │ │ │ ├── base64.tsx │ │ │ ├── cn.tsx │ │ │ ├── dateChecker.tsx │ │ │ ├── emacs.tsx │ │ │ ├── externalOpen.tsx │ │ │ ├── font.tsx │ │ │ ├── imageExport.tsx │ │ │ ├── keyboardFunctions.tsx │ │ │ ├── markdownParse.tsx │ │ │ ├── otherApi.tsx │ │ │ ├── path.tsx │ │ │ ├── pathString.tsx │ │ │ ├── platform.tsx │ │ │ ├── sleep.tsx │ │ │ ├── store.tsx │ │ │ ├── updater.tsx │ │ │ ├── xml.tsx │ │ │ └── yaml.tsx │ │ └── vite-env.d.ts │ ├── src-tauri/ │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── build.rs │ │ ├── capabilities/ │ │ │ ├── default.json │ │ │ └── desktop.json │ │ ├── gen/ │ │ │ └── android/ │ │ │ ├── .editorconfig │ │ │ ├── .gitignore │ │ │ ├── app/ │ │ │ │ ├── .gitignore │ │ │ │ ├── build.gradle.kts │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src/ │ │ │ │ └── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── liren/ │ │ │ │ │ └── project_graph/ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ └── ic_launcher_background.xml │ │ │ │ ├── drawable-v24/ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── layout/ │ │ │ │ │ └── activity_main.xml │ │ │ │ ├── value-night/ │ │ │ │ │ └── styles.xml │ │ │ │ ├── values/ │ │ │ │ │ ├── colors.xml │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ │ └── xml/ │ │ │ │ └── file_paths.xml │ │ │ ├── build.gradle.kts │ │ │ ├── buildSrc/ │ │ │ │ ├── build.gradle.kts │ │ │ │ └── src/ │ │ │ │ └── main/ │ │ │ │ └── java/ │ │ │ │ └── liren/ │ │ │ │ └── project_graph/ │ │ │ │ └── kotlin/ │ │ │ │ ├── BuildTask.kt │ │ │ │ └── RustPlugin.kt │ │ │ ├── gradle/ │ │ │ │ └── wrapper/ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradle.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ ├── keystore.properties │ │ │ └── settings.gradle │ │ ├── icons/ │ │ │ └── icon.icns │ │ ├── nsis/ │ │ │ └── installer.nsh │ │ ├── src/ │ │ │ ├── cmd/ │ │ │ │ ├── device.rs │ │ │ │ ├── fs.rs │ │ │ │ └── mod.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── tauri.conf.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── vite-plugins/ │ │ └── i18n-auto-tw.ts │ └── vite.config.ts ├── config.xlings ├── docs-pg/ │ ├── Project Graph v2.json │ ├── ProjectGraph决策日志.json │ ├── ProjectGraph开发进程图.json │ ├── ProjectGraph开发进程图.prg │ ├── ProjectGraph继承体系.json │ ├── ProjectGraph项目架构.json │ ├── README_FOR_AI.md │ ├── issue分类.json │ └── 服务器.prg ├── eslint.config.js ├── nx.json ├── package.json ├── packages/ │ ├── api/ │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── package.json │ │ ├── src/ │ │ │ ├── apis/ │ │ │ │ ├── camera.ts │ │ │ │ ├── controller.ts │ │ │ │ └── dialog.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ └── tsconfig.json │ ├── data-structures/ │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── package.json │ │ ├── src/ │ │ │ ├── Cache.ts │ │ │ ├── Color.ts │ │ │ ├── LimitLengthQueue.ts │ │ │ ├── MonoStack.ts │ │ │ ├── ProgressNumber.ts │ │ │ ├── Queue.ts │ │ │ ├── Stack.ts │ │ │ ├── Vector.ts │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── Cache.test.ts │ │ │ ├── Color.test.ts │ │ │ ├── LimitLengthQueue.test.ts │ │ │ ├── MonoStack.test.ts │ │ │ ├── ProgressNumber.test.ts │ │ │ ├── Queue.test.ts │ │ │ ├── Stack.test.ts │ │ │ └── Vector.test.ts │ │ ├── tsconfig.json │ │ └── tsdown.config.ts │ ├── serializer/ │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ └── shapes/ │ ├── .gitignore │ ├── .npmignore │ ├── LICENSE │ ├── package.json │ ├── src/ │ │ ├── Circle.ts │ │ ├── CubicCatmullRomSpline.ts │ │ ├── Curve.ts │ │ ├── Line.ts │ │ ├── Rectangle.ts │ │ ├── Shape.ts │ │ └── index.ts │ ├── tests/ │ │ ├── Circle.test.ts │ │ ├── CubicCatmullRomSpline.test.ts │ │ ├── Curve.test.ts │ │ ├── Line.test.ts │ │ └── Rectangle.test.ts │ ├── tsconfig.json │ └── tsdown.config.ts ├── patches/ │ └── typescript.patch ├── pnpm-workspace.yaml ├── utils/ │ ├── add-ts-nocheck.ts │ ├── class2namespace.ts │ ├── generate-service-docs.sh │ ├── lines.sh │ └── relative2alias.ts ├── vitest.config.ts └── 文本节点功能分析.md
Showing preview only (243K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2583 symbols across 429 files)
FILE: .github/scripts/enable-sourcemap.mjs
constant VITE_CONFIG_PATH (line 3) | const VITE_CONFIG_PATH = "app/vite.config.ts";
FILE: .github/scripts/generate-changelog.mjs
function generateFallbackChangelog (line 19) | function generateFallbackChangelog(commits) {
FILE: .github/scripts/generate-pkgbuild.mjs
constant PKGBUILD (line 25) | const PKGBUILD = `# Maintainer: zty012 <me@zty012.de>
constant SRCINFO (line 50) | const SRCINFO = `pkgbase = ${pkgname}
FILE: .github/scripts/set-tauri-features.mjs
constant CARGO_TOML_PATH (line 7) | const CARGO_TOML_PATH = "app/src-tauri/Cargo.toml";
FILE: .github/scripts/set-version.mjs
constant TAURI_CONF_PATH (line 7) | const TAURI_CONF_PATH = "app/src-tauri/tauri.conf.json";
FILE: app/scripts/sync-locales.ts
function convert (line 14) | function convert() {
FILE: app/src-tauri/build.rs
function main (line 1) | fn main() {
FILE: app/src-tauri/src/cmd/device.rs
function get_device_id (line 8) | pub fn get_device_id() -> Result<String, String> {
function get_device_id (line 23) | pub fn get_device_id() -> Result<String, String> {
function get_device_id (line 46) | pub fn get_device_id() -> Result<String, String> {
function get_device_id (line 57) | pub fn get_device_id() -> Result<String, String> {
FILE: app/src-tauri/src/cmd/fs.rs
type FolderEntry (line 8) | pub struct FolderEntry {
function read_folder_structure (line 18) | pub fn read_folder_structure(path: String) -> FolderEntry {
function exists (line 58) | pub fn exists(path: String) -> bool {
function read_folder (line 65) | pub fn read_folder(path: String) -> Vec<String> {
function read_folder_recursive (line 85) | pub fn read_folder_recursive(path: String, file_exts: Vec<String>) -> Ve...
function delete_file (line 112) | pub fn delete_file(path: String) -> Result<(), String> {
function read_text_file (line 119) | pub fn read_text_file(path: String) -> String {
function read_file_base64 (line 128) | pub fn read_file_base64(path: String) -> Result<String, String> {
function write_text_file (line 135) | pub fn write_text_file(path: String, content: String) -> Result<(), Stri...
function write_file_base64 (line 142) | pub fn write_file_base64(content: String, path: String) -> Result<(), St...
function create_folder (line 160) | pub fn create_folder(path: String) -> bool {
FILE: app/src-tauri/src/lib.rs
function write_stdout (line 8) | fn write_stdout(content: String) {
function write_stderr (line 13) | fn write_stderr(content: String) {
function exit (line 18) | fn exit(code: i32) {
function run (line 23) | pub fn run() {
FILE: app/src-tauri/src/main.rs
function main (line 4) | fn main() {
FILE: app/src/App.tsx
function App (line 41) | function App() {
function WindowButtons (line 456) | function WindowButtons() {
function Catch (line 566) | function Catch() {
FILE: app/src/cli.tsx
function runCli (line 4) | async function runCli(matches: CliMatches) {
FILE: app/src/components/context-menu-content.tsx
function MyContextMenuContent (line 120) | function MyContextMenuContent() {
function ContextMenuTooltip (line 1248) | function ContextMenuTooltip({ keyId, children = <></> }: { keyId: string...
FILE: app/src/components/editor/plugins/comment-kit.tsx
type CommentConfig (line 11) | type CommentConfig = ExtendConfig<
FILE: app/src/components/editor/plugins/discussion-kit.tsx
type TDiscussion (line 9) | interface TDiscussion {
FILE: app/src/components/editor/plugins/suggestion-kit.tsx
type SuggestionConfig (line 12) | type SuggestionConfig = ExtendConfig<
FILE: app/src/components/editor/transforms.ts
constant ACTION_THREE_COLUMNS (line 17) | const ACTION_THREE_COLUMNS = "action_three_columns";
FILE: app/src/components/key-tooltip.tsx
function KeyTooltip (line 9) | function KeyTooltip({ keyId, children = <></> }: { keyId: string; childr...
FILE: app/src/components/render-sub-windows.tsx
function RenderSubWindows (line 13) | function RenderSubWindows() {
FILE: app/src/components/right-toolbar.tsx
function QuickSettingButton (line 19) | function QuickSettingButton({
function RightToolbar (line 102) | function RightToolbar() {
FILE: app/src/components/theme-mode-switch.tsx
function ThemeModeSwitch (line 8) | function ThemeModeSwitch() {
FILE: app/src/components/toolbar-content.tsx
function ToolbarContent (line 19) | function ToolbarContent() {
FILE: app/src/components/ui/ai-node.tsx
function AILeaf (line 8) | function AILeaf(props: PlateTextProps) {
function AIAnchorElement (line 28) | function AIAnchorElement(props: PlateElementProps) {
FILE: app/src/components/ui/ai-toolbar-button.tsx
function AIToolbarButton (line 11) | function AIToolbarButton(props: React.ComponentProps<typeof ToolbarButto...
FILE: app/src/components/ui/alert-dialog.tsx
function AlertDialog (line 7) | function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDial...
function AlertDialogTrigger (line 11) | function AlertDialogTrigger({ ...props }: React.ComponentProps<typeof Al...
function AlertDialogPortal (line 15) | function AlertDialogPortal({ ...props }: React.ComponentProps<typeof Ale...
function AlertDialogOverlay (line 19) | function AlertDialogOverlay({ className, ...props }: React.ComponentProp...
function AlertDialogContent (line 32) | function AlertDialogContent({ className, ...props }: React.ComponentProp...
function AlertDialogHeader (line 48) | function AlertDialogHeader({ className, ...props }: React.ComponentProps...
function AlertDialogFooter (line 58) | function AlertDialogFooter({ className, ...props }: React.ComponentProps...
function AlertDialogTitle (line 68) | function AlertDialogTitle({ className, ...props }: React.ComponentProps<...
function AlertDialogDescription (line 78) | function AlertDialogDescription({
function AlertDialogAction (line 91) | function AlertDialogAction({ className, ...props }: React.ComponentProps...
function AlertDialogCancel (line 95) | function AlertDialogCancel({ className, ...props }: React.ComponentProps...
FILE: app/src/components/ui/alert.tsx
function Alert (line 22) | function Alert({ className, variant, ...props }: React.ComponentProps<"d...
function AlertTitle (line 26) | function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
function AlertDescription (line 36) | function AlertDescription({ className, ...props }: React.ComponentProps<...
FILE: app/src/components/ui/align-toolbar-button.tsx
function AlignToolbarButton (line 41) | function AlignToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/ui/avatar.tsx
function Avatar (line 6) | function Avatar({ className, ...props }: React.ComponentProps<typeof Ava...
function AvatarImage (line 16) | function AvatarImage({ className, ...props }: React.ComponentProps<typeo...
function AvatarFallback (line 22) | function AvatarFallback({ className, ...props }: React.ComponentProps<ty...
FILE: app/src/components/ui/block-discussion.tsx
function BlockComment (line 225) | function BlockComment({ discussion, isLast }: { discussion: TDiscussion;...
FILE: app/src/components/ui/block-list-static.tsx
function List (line 29) | function List(props: SlateRenderElementProps) {
function TodoMarkerStatic (line 42) | function TodoMarkerStatic(props: SlateRenderElementProps) {
function TodoLiStatic (line 63) | function TodoLiStatic(props: SlateRenderElementProps) {
FILE: app/src/components/ui/block-list.tsx
function List (line 33) | function List(props: PlateElementProps) {
function TodoMarker (line 46) | function TodoMarker(props: PlateElementProps) {
function TodoLi (line 58) | function TodoLi(props: PlateElementProps) {
FILE: app/src/components/ui/block-selection.tsx
function BlockSelection (line 24) | function BlockSelection(props: PlateElementProps) {
FILE: app/src/components/ui/block-suggestion.tsx
type ResolvedSuggestion (line 31) | interface ResolvedSuggestion extends TResolvedSuggestion {
constant BLOCK_SUGGESTION (line 35) | const BLOCK_SUGGESTION = "__block__";
constant TYPE_TEXT_MAP (line 37) | const TYPE_TEXT_MAP: Record<string, (node?: TElement) => string> = {
function BlockSuggestion (line 67) | function BlockSuggestion({ element }: { element: TSuggestionElement }) {
function BlockSuggestionCard (line 85) | function BlockSuggestionCard({
FILE: app/src/components/ui/blockquote-node-static.tsx
function BlockquoteElementStatic (line 4) | function BlockquoteElementStatic(props: SlateElementProps) {
FILE: app/src/components/ui/blockquote-node.tsx
function BlockquoteElement (line 5) | function BlockquoteElement(props: PlateElementProps) {
FILE: app/src/components/ui/button.tsx
function Button (line 35) | function Button({
FILE: app/src/components/ui/calendar.tsx
function Calendar (line 10) | function Calendar({
function CalendarDayButton (line 128) | function CalendarDayButton({ className, day, modifiers, ...props }: Reac...
FILE: app/src/components/ui/callout-node-static.tsx
function CalloutElementStatic (line 8) | function CalloutElementStatic({ children, className, ...props }: SlateEl...
FILE: app/src/components/ui/callout-node.tsx
function CalloutElement (line 14) | function CalloutElement({
FILE: app/src/components/ui/caption.tsx
function Caption (line 32) | function Caption({
function CaptionTextarea (line 40) | function CaptionTextarea(props: React.ComponentProps<typeof CaptionTexta...
FILE: app/src/components/ui/card.tsx
function SimpleCard (line 5) | function SimpleCard({ className, ...props }: React.ComponentProps<"div">) {
function Card (line 15) | function Card({ className, ...props }: React.ComponentProps<"div">) {
function CardHeader (line 25) | function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
function CardTitle (line 38) | function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
function CardDescription (line 42) | function CardDescription({ className, ...props }: React.ComponentProps<"...
function CardAction (line 46) | function CardAction({ className, ...props }: React.ComponentProps<"div">) {
function CardContent (line 56) | function CardContent({ className, ...props }: React.ComponentProps<"div"...
function CardFooter (line 60) | function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
FILE: app/src/components/ui/checkbox.tsx
function Checkbox (line 7) | function Checkbox({ className, ...props }: React.ComponentProps<typeof C...
FILE: app/src/components/ui/code-block-node-static.tsx
function CodeBlockElementStatic (line 4) | function CodeBlockElementStatic(props: SlateElementProps<TCodeBlockEleme...
function CodeLineElementStatic (line 19) | function CodeLineElementStatic(props: SlateElementProps) {
function CodeSyntaxLeafStatic (line 23) | function CodeSyntaxLeafStatic(props: SlateLeafProps) {
FILE: app/src/components/ui/code-block-node.tsx
function CodeBlockElement (line 16) | function CodeBlockElement(props: PlateElementProps<TCodeBlockElement>) {
function CodeBlockCombobox (line 56) | function CodeBlockCombobox() {
function CopyButton (line 120) | function CopyButton({
function CodeLineElement (line 146) | function CodeLineElement(props: PlateElementProps) {
function CodeSyntaxLeaf (line 150) | function CodeSyntaxLeaf(props: PlateLeafProps<TCodeSyntaxLeaf>) {
FILE: app/src/components/ui/code-node-static.tsx
function CodeLeafStatic (line 6) | function CodeLeafStatic(props: SlateLeafProps) {
FILE: app/src/components/ui/code-node.tsx
function CodeLeaf (line 8) | function CodeLeaf(props: PlateLeafProps) {
FILE: app/src/components/ui/collapsible.tsx
function Collapsible (line 4) | function Collapsible({ ...props }: React.ComponentProps<typeof Collapsib...
function CollapsibleTrigger (line 8) | function CollapsibleTrigger({ ...props }: React.ComponentProps<typeof Co...
type CollapsibleContentProps (line 12) | type CollapsibleContentProps = React.ComponentProps<typeof CollapsiblePr...
function CollapsibleContent (line 16) | function CollapsibleContent({ className, animate = true, ...props }: Col...
FILE: app/src/components/ui/column-node-static.tsx
function ColumnElementStatic (line 6) | function ColumnElementStatic(props: SlateElementProps<TColumnElement>) {
function ColumnGroupElementStatic (line 18) | function ColumnGroupElementStatic(props: SlateElementProps) {
FILE: app/src/components/ui/column-node.tsx
function DropLine (line 109) | function DropLine() {
function ColumnGroupElement (line 126) | function ColumnGroupElement(props: PlateElementProps) {
function ColumnFloatingToolbar (line 136) | function ColumnFloatingToolbar({ children }: React.PropsWithChildren) {
FILE: app/src/components/ui/command.tsx
function Command (line 10) | function Command({ className, ...props }: React.ComponentProps<typeof Co...
function CommandDialog (line 23) | function CommandDialog({
function CommandInput (line 51) | function CommandInput({ className, ...props }: React.ComponentProps<type...
function CommandList (line 67) | function CommandList({ className, ...props }: React.ComponentProps<typeo...
function CommandEmpty (line 77) | function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandP...
function CommandGroup (line 81) | function CommandGroup({ className, ...props }: React.ComponentProps<type...
function CommandSeparator (line 94) | function CommandSeparator({ className, ...props }: React.ComponentProps<...
function CommandItem (line 104) | function CommandItem({ className, ...props }: React.ComponentProps<typeo...
function CommandShortcut (line 117) | function CommandShortcut({ className, ...props }: React.ComponentProps<"...
FILE: app/src/components/ui/comment-node-static.tsx
function CommentLeafStatic (line 8) | function CommentLeafStatic(props: SlateLeafProps<TCommentText>) {
FILE: app/src/components/ui/comment-node.tsx
function CommentLeaf (line 15) | function CommentLeaf(props: PlateLeafProps<TCommentText>) {
FILE: app/src/components/ui/comment-toolbar-button.tsx
function CommentToolbarButton (line 13) | function CommentToolbarButton() {
FILE: app/src/components/ui/comment.tsx
type TComment (line 30) | interface TComment {
function Comment (line 39) | function Comment(props: {
function CommentMoreDropdown (line 249) | function CommentMoreDropdown(props: {
function CommentCreateForm (line 343) | function CommentCreateForm({
FILE: app/src/components/ui/context-menu.tsx
function ContextMenu (line 7) | function ContextMenu({ ...props }: React.ComponentProps<typeof ContextMe...
function ContextMenuTrigger (line 11) | function ContextMenuTrigger({ ...props }: React.ComponentProps<typeof Co...
function ContextMenuGroup (line 15) | function ContextMenuGroup({ ...props }: React.ComponentProps<typeof Cont...
function ContextMenuPortal (line 19) | function ContextMenuPortal({ ...props }: React.ComponentProps<typeof Con...
function ContextMenuSub (line 23) | function ContextMenuSub({ ...props }: React.ComponentProps<typeof Contex...
function ContextMenuRadioGroup (line 27) | function ContextMenuRadioGroup({ ...props }: React.ComponentProps<typeof...
function ContextMenuSubTrigger (line 31) | function ContextMenuSubTrigger({
function ContextMenuSubContent (line 55) | function ContextMenuSubContent({ className, ...props }: React.ComponentP...
function ContextMenuContent (line 68) | function ContextMenuContent({ className, ...props }: React.ComponentProp...
function ContextMenuItem (line 83) | function ContextMenuItem({
function ContextMenuCheckboxItem (line 106) | function ContextMenuCheckboxItem({
function ContextMenuRadioItem (line 132) | function ContextMenuRadioItem({
function ContextMenuLabel (line 156) | function ContextMenuLabel({
function ContextMenuSeparator (line 173) | function ContextMenuSeparator({ className, ...props }: React.ComponentPr...
function ContextMenuShortcut (line 183) | function ContextMenuShortcut({ className, ...props }: React.ComponentPro...
FILE: app/src/components/ui/date-node-static.tsx
function DateElementStatic (line 8) | function DateElementStatic(props: SlateElementProps<TDateElement>) {
FILE: app/src/components/ui/date-node.tsx
function DateElement (line 12) | function DateElement(props: PlateElementProps<TDateElement>) {
FILE: app/src/components/ui/dialog.tsx
function Dialog (line 15) | function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitiv...
function DialogTrigger (line 19) | function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogP...
function DialogPortal (line 23) | function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPr...
function DialogClose (line 27) | function DialogClose({ ...props }: React.ComponentProps<typeof DialogPri...
function DialogOverlay (line 31) | function DialogOverlay({ className, ...props }: React.ComponentProps<typ...
function DialogContent (line 44) | function DialogContent({
function DialogHeader (line 78) | function DialogHeader({ className, ...props }: React.ComponentProps<"div...
function DialogFooter (line 88) | function DialogFooter({ className, ...props }: React.ComponentProps<"div...
function DialogTitle (line 98) | function DialogTitle({ className, ...props }: React.ComponentProps<typeo...
function DialogDescription (line 108) | function DialogDescription({ className, ...props }: React.ComponentProps...
function Component (line 120) | function Component({ winId }: { winId?: string }) {
function Component (line 176) | function Component({ winId }: { winId?: string }) {
function Component (line 264) | function Component({ winId }: { winId?: string }) {
function Component (line 307) | function Component({ winId }: { winId?: string }) {
FILE: app/src/components/ui/dropdown-menu.tsx
function DropdownMenu (line 7) | function DropdownMenu({ ...props }: React.ComponentProps<typeof Dropdown...
function DropdownMenuPortal (line 11) | function DropdownMenuPortal({ ...props }: React.ComponentProps<typeof Dr...
function DropdownMenuTrigger (line 15) | function DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof D...
function DropdownMenuContent (line 19) | function DropdownMenuContent({
function DropdownMenuGroup (line 39) | function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof Dro...
function DropdownMenuItem (line 43) | function DropdownMenuItem({
function DropdownMenuCheckboxItem (line 66) | function DropdownMenuCheckboxItem({
function DropdownMenuRadioGroup (line 92) | function DropdownMenuRadioGroup({ ...props }: React.ComponentProps<typeo...
function DropdownMenuRadioItem (line 96) | function DropdownMenuRadioItem({
function DropdownMenuLabel (line 120) | function DropdownMenuLabel({
function DropdownMenuSeparator (line 137) | function DropdownMenuSeparator({ className, ...props }: React.ComponentP...
function DropdownMenuShortcut (line 147) | function DropdownMenuShortcut({ className, ...props }: React.ComponentPr...
function DropdownMenuSub (line 157) | function DropdownMenuSub({ ...props }: React.ComponentProps<typeof Dropd...
function DropdownMenuSubTrigger (line 161) | function DropdownMenuSubTrigger({
function DropdownMenuSubContent (line 185) | function DropdownMenuSubContent({
FILE: app/src/components/ui/editor-static.tsx
function EditorStatic (line 43) | function EditorStatic({ className, variant, ...props }: PlateStaticProps...
FILE: app/src/components/ui/editor.tsx
function EditorContainer (line 38) | function EditorContainer({
type EditorProps (line 87) | type EditorProps = PlateContentProps & VariantProps<typeof editorVariants>;
function EditorView (line 112) | function EditorView({ className, variant, ...props }: PlateViewProps & V...
FILE: app/src/components/ui/emoji-node.tsx
function EmojiInputElement (line 22) | function EmojiInputElement(props: PlateElementProps) {
FILE: app/src/components/ui/emoji-toolbar-button.tsx
function EmojiToolbarButton (line 33) | function EmojiToolbarButton({
function EmojiPopover (line 56) | function EmojiPopover({
function EmojiPicker (line 78) | function EmojiPicker({
function EmojiPickerContent (line 192) | function EmojiPickerContent({
function EmojiPickerSearchBar (line 295) | function EmojiPickerSearchBar({
function EmojiPickerSearchAndClear (line 322) | function EmojiPickerSearchAndClear({
function EmojiPreview (line 355) | function EmojiPreview({ emoji }: Pick<UseEmojiPickerType, "emoji">) {
function NoEmoji (line 367) | function NoEmoji({ i18n }: Pick<UseEmojiPickerType, "i18n">) {
function PickAnEmoji (line 379) | function PickAnEmoji({ i18n }: Pick<UseEmojiPickerType, "i18n">) {
function EmojiPickerPreview (line 390) | function EmojiPickerPreview({
function EmojiPickerNavigation (line 410) | function EmojiPickerNavigation({
FILE: app/src/components/ui/equation-node-static.tsx
function EquationElementStatic (line 12) | function EquationElementStatic(props: SlateElementProps<TEquationElement...
function InlineEquationElementStatic (line 56) | function InlineEquationElementStatic(props: SlateElementProps<TEquationE...
FILE: app/src/components/ui/equation-node.tsx
function EquationElement (line 27) | function EquationElement(props: PlateElementProps<TEquationElement>) {
function InlineEquationElement (line 85) | function InlineEquationElement(props: PlateElementProps<TEquationElement...
FILE: app/src/components/ui/equation-toolbar-button.tsx
function InlineEquationToolbarButton (line 11) | function InlineEquationToolbarButton(props: React.ComponentProps<typeof ...
FILE: app/src/components/ui/export-toolbar-button.tsx
function ExportToolbarButton (line 26) | function ExportToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/ui/field.tsx
function SettingField (line 15) | function SettingField({ settingKey, extra = <></> }: { settingKey: keyof...
function ButtonField (line 110) | function ButtonField({
function Field (line 148) | function Field({
function FieldGroup (line 202) | function FieldGroup({
FILE: app/src/components/ui/file-chooser.tsx
function FileChooser (line 7) | function FileChooser({
FILE: app/src/components/ui/fixed-toolbar-buttons.tsx
function FixedToolbarButtons (line 33) | function FixedToolbarButtons() {
FILE: app/src/components/ui/fixed-toolbar.tsx
function FixedToolbar (line 7) | function FixedToolbar(props: React.ComponentProps<typeof Toolbar>) {
FILE: app/src/components/ui/floating-toolbar-buttons.tsx
function FloatingToolbarButtons (line 14) | function FloatingToolbarButtons() {
FILE: app/src/components/ui/floating-toolbar.tsx
function FloatingToolbar (line 21) | function FloatingToolbar({
FILE: app/src/components/ui/font-color-toolbar-button.tsx
function FontColorToolbarButton (line 24) | function FontColorToolbarButton({
function PureColorPicker (line 117) | function PureColorPicker({
function ColorCustom (line 166) | function ColorCustom({
function ColorInput (line 241) | function ColorInput({ children, className, value = "#000000", ...props }...
type TColor (line 269) | type TColor = {
function ColorDropdownMenuItem (line 275) | function ColorDropdownMenuItem({
function ColorDropdownMenuItems (line 321) | function ColorDropdownMenuItems({
constant DEFAULT_COLORS (line 351) | const DEFAULT_COLORS = [
constant DEFAULT_CUSTOM_COLORS (line 760) | const DEFAULT_CUSTOM_COLORS = [
FILE: app/src/components/ui/font-size-toolbar-button.tsx
constant DEFAULT_FONT_SIZE (line 19) | const DEFAULT_FONT_SIZE = "16";
constant FONT_SIZE_MAP (line 21) | const FONT_SIZE_MAP = {
constant FONT_SIZES (line 27) | const FONT_SIZES = ["8", "9", "10", "12", "14", "16", "18", "24", "30", ...
function FontSizeToolbarButton (line 29) | function FontSizeToolbarButton() {
FILE: app/src/components/ui/heading-node-static.tsx
function HeadingElementStatic (line 21) | function HeadingElementStatic({
function H1ElementStatic (line 32) | function H1ElementStatic(props: SlateElementProps) {
function H2ElementStatic (line 36) | function H2ElementStatic(props: React.ComponentProps<typeof HeadingEleme...
function H3ElementStatic (line 40) | function H3ElementStatic(props: React.ComponentProps<typeof HeadingEleme...
function H4ElementStatic (line 44) | function H4ElementStatic(props: React.ComponentProps<typeof HeadingEleme...
function H5ElementStatic (line 48) | function H5ElementStatic(props: React.ComponentProps<typeof HeadingEleme...
function H6ElementStatic (line 52) | function H6ElementStatic(props: React.ComponentProps<typeof HeadingEleme...
FILE: app/src/components/ui/heading-node.tsx
function HeadingElement (line 24) | function HeadingElement({ variant = "h1", ...props }: PlateElementProps ...
function H1Element (line 32) | function H1Element(props: PlateElementProps) {
function H2Element (line 36) | function H2Element(props: PlateElementProps) {
function H3Element (line 40) | function H3Element(props: PlateElementProps) {
function H4Element (line 44) | function H4Element(props: PlateElementProps) {
function H5Element (line 48) | function H5Element(props: PlateElementProps) {
function H6Element (line 52) | function H6Element(props: PlateElementProps) {
FILE: app/src/components/ui/highlight-node-static.tsx
function HighlightLeafStatic (line 8) | function HighlightLeafStatic(props: SlateLeafProps) {
FILE: app/src/components/ui/highlight-node.tsx
function HighlightLeaf (line 10) | function HighlightLeaf(props: PlateLeafProps) {
FILE: app/src/components/ui/history-toolbar-button.tsx
function RedoToolbarButton (line 11) | function RedoToolbarButton(props: React.ComponentProps<typeof ToolbarBut...
function UndoToolbarButton (line 28) | function UndoToolbarButton(props: React.ComponentProps<typeof ToolbarBut...
FILE: app/src/components/ui/hr-node-static.tsx
function HrElementStatic (line 10) | function HrElementStatic(props: SlateElementProps) {
FILE: app/src/components/ui/hr-node.tsx
function HrElement (line 12) | function HrElement(props: PlateElementProps) {
FILE: app/src/components/ui/import-toolbar-button.tsx
type ImportType (line 23) | type ImportType = "html" | "markdown";
function ImportToolbarButton (line 25) | function ImportToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/ui/indent-toolbar-button.tsx
function IndentToolbarButton (line 10) | function IndentToolbarButton(props: React.ComponentProps<typeof ToolbarB...
function OutdentToolbarButton (line 20) | function OutdentToolbarButton(props: React.ComponentProps<typeof Toolbar...
FILE: app/src/components/ui/inline-combobox.tsx
type FilterFn (line 28) | type FilterFn = (
type InlineComboboxContextValue (line 33) | interface InlineComboboxContextValue {
type InlineComboboxProps (line 53) | interface InlineComboboxProps {
function InlineComboboxGroup (line 307) | function InlineComboboxGroup({ className, ...props }: React.ComponentPro...
function InlineComboboxGroupLabel (line 316) | function InlineComboboxGroupLabel({ className, ...props }: React.Compone...
FILE: app/src/components/ui/input.tsx
function Input (line 5) | function Input({ className, type, ...props }: React.ComponentProps<"inpu...
FILE: app/src/components/ui/insert-toolbar-button.tsx
type Group (line 42) | type Group = {
type Item (line 47) | interface Item {
function InsertToolbarButton (line 211) | function InsertToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/ui/kbd-node-static.tsx
function KbdLeafStatic (line 8) | function KbdLeafStatic(props: SlateLeafProps) {
FILE: app/src/components/ui/kbd-node.tsx
function KbdLeaf (line 10) | function KbdLeaf(props: PlateLeafProps) {
FILE: app/src/components/ui/key-bind.tsx
function KeyBind (line 12) | function KeyBind({
function RenderKey (line 90) | function RenderKey({ data }: { data: ReturnType<typeof parseEmacsKey>[nu...
function Modifiers (line 109) | function Modifiers({
function MouseButton (line 172) | function MouseButton({ key_ }: { key_: string }) {
FILE: app/src/components/ui/line-height-toolbar-button.tsx
function LineHeightToolbarButton (line 22) | function LineHeightToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/ui/link-node-static.tsx
function LinkElementStatic (line 9) | function LinkElementStatic(props: SlateElementProps<TLinkElement>) {
FILE: app/src/components/ui/link-node.tsx
function LinkElement (line 12) | function LinkElement(props: PlateElementProps<TLinkElement>) {
FILE: app/src/components/ui/link-toolbar-button.tsx
function LinkToolbarButton (line 10) | function LinkToolbarButton(props: React.ComponentProps<typeof ToolbarBut...
FILE: app/src/components/ui/link-toolbar.tsx
function LinkFloatingToolbar (line 34) | function LinkFloatingToolbar({ state }: { state?: LinkFloatingToolbarSta...
function LinkOpenButton (line 133) | function LinkOpenButton() {
FILE: app/src/components/ui/list-toolbar-button.tsx
function BulletedListToolbarButton (line 20) | function BulletedListToolbarButton() {
function NumberedListToolbarButton (line 93) | function NumberedListToolbarButton() {
function TodoListToolbarButton (line 182) | function TodoListToolbarButton(props: React.ComponentProps<typeof Toolba...
FILE: app/src/components/ui/mark-toolbar-button.tsx
function MarkToolbarButton (line 9) | function MarkToolbarButton({
FILE: app/src/components/ui/markdown.tsx
function Markdown (line 12) | function Markdown({ source, className = "" }: { source: string; classNam...
FILE: app/src/components/ui/media-audio-node-static.tsx
function AudioElementStatic (line 8) | function AudioElementStatic(props: SlateElementProps<TAudioElement>) {
FILE: app/src/components/ui/media-file-node-static.tsx
function FileElementStatic (line 9) | function FileElementStatic(props: SlateElementProps<TFileElement>) {
FILE: app/src/components/ui/media-image-node-static.tsx
function ImageElementStatic (line 10) | function ImageElementStatic(props: SlateElementProps<TImageElement & TCa...
FILE: app/src/components/ui/media-toolbar-button.tsx
constant MEDIA_CONFIG (line 36) | const MEDIA_CONFIG: Record<
function MediaToolbarButton (line 71) | function MediaToolbarButton({ nodeType, ...props }: DropdownMenuProps & ...
function MediaUrlDialogContent (line 136) | function MediaUrlDialogContent({
FILE: app/src/components/ui/media-toolbar.tsx
function MediaToolbar (line 36) | function MediaToolbar({ children, plugin }: { children: React.ReactNode;...
FILE: app/src/components/ui/media-video-node-static.tsx
function VideoElementStatic (line 8) | function VideoElementStatic(props: SlateElementProps<TVideoElement & TCa...
FILE: app/src/components/ui/mention-node-static.tsx
function MentionElementStatic (line 9) | function MentionElementStatic(
FILE: app/src/components/ui/mention-node.tsx
function MentionElement (line 24) | function MentionElement(
function MentionInputElement (line 75) | function MentionInputElement(props: PlateElementProps<TComboboxInputElem...
constant MENTIONABLES (line 104) | const MENTIONABLES = [
FILE: app/src/components/ui/menubar.tsx
function Menubar (line 8) | function Menubar({ className, ...props }: React.ComponentProps<typeof Me...
function MenubarMenu (line 21) | function MenubarMenu({ ...props }: React.ComponentProps<typeof MenubarPr...
function MenubarGroup (line 25) | function MenubarGroup({ ...props }: React.ComponentProps<typeof MenubarP...
function MenubarPortal (line 29) | function MenubarPortal({ ...props }: React.ComponentProps<typeof Menubar...
function MenubarRadioGroup (line 33) | function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof Men...
function MenubarTrigger (line 37) | function MenubarTrigger({ className, ...props }: React.ComponentProps<ty...
function MenubarContent (line 56) | function MenubarContent({
function MenubarItem (line 80) | function MenubarItem({
function MenubarCheckboxItem (line 109) | function MenubarCheckboxItem({
function MenubarRadioItem (line 135) | function MenubarRadioItem({ className, children, ...props }: React.Compo...
function MenubarLabel (line 155) | function MenubarLabel({
function MenubarSeparator (line 172) | function MenubarSeparator({ className, ...props }: React.ComponentProps<...
function MenubarShortcut (line 182) | function MenubarShortcut({ className, ...props }: React.ComponentProps<"...
function MenubarSub (line 192) | function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPri...
function MenubarSubTrigger (line 196) | function MenubarSubTrigger({
function MenubarSubContent (line 226) | function MenubarSubContent({ className, ...props }: React.ComponentProps...
FILE: app/src/components/ui/mode-toolbar-button.tsx
function ModeToolbarButton (line 20) | function ModeToolbarButton(props: DropdownMenuProps) {
function Indicator (line 110) | function Indicator() {
FILE: app/src/components/ui/more-toolbar-button.tsx
function MoreToolbarButton (line 21) | function MoreToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/ui/paragraph-node-static.tsx
function ParagraphElementStatic (line 10) | function ParagraphElementStatic(props: SlateElementProps) {
FILE: app/src/components/ui/paragraph-node.tsx
function ParagraphElement (line 12) | function ParagraphElement(props: PlateElementProps) {
FILE: app/src/components/ui/popover.tsx
function Popover (line 9) | function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimit...
function PopoverTrigger (line 13) | function PopoverTrigger({ ...props }: React.ComponentProps<typeof Popove...
function PopoverContent (line 17) | function PopoverContent({
function PopoverAnchor (line 39) | function PopoverAnchor({ ...props }: React.ComponentProps<typeof Popover...
FILE: app/src/components/ui/progress.tsx
function Progress (line 6) | function Progress({ className, value, ...props }: React.ComponentProps<t...
FILE: app/src/components/ui/resize-handle.tsx
function ResizeHandle (line 43) | function ResizeHandle({
function Resizable (line 73) | function Resizable({
FILE: app/src/components/ui/select.tsx
function Select (line 7) | function Select({ ...props }: React.ComponentProps<typeof SelectPrimitiv...
function SelectGroup (line 11) | function SelectGroup({ ...props }: React.ComponentProps<typeof SelectPri...
function SelectValue (line 15) | function SelectValue({ ...props }: React.ComponentProps<typeof SelectPri...
function SelectTrigger (line 19) | function SelectTrigger({
function SelectContent (line 45) | function SelectContent({
function SelectLabel (line 80) | function SelectLabel({ className, ...props }: React.ComponentProps<typeo...
function SelectItem (line 90) | function SelectItem({ className, children, ...props }: React.ComponentPr...
function SelectSeparator (line 110) | function SelectSeparator({ className, ...props }: React.ComponentProps<t...
function SelectScrollUpButton (line 120) | function SelectScrollUpButton({ className, ...props }: React.ComponentPr...
function SelectScrollDownButton (line 132) | function SelectScrollDownButton({
FILE: app/src/components/ui/separator.tsx
function Separator (line 8) | function Separator({
FILE: app/src/components/ui/sheet.tsx
function Sheet (line 7) | function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive....
function SheetTrigger (line 11) | function SheetTrigger({ ...props }: React.ComponentProps<typeof SheetPri...
function SheetClose (line 15) | function SheetClose({ ...props }: React.ComponentProps<typeof SheetPrimi...
function SheetPortal (line 19) | function SheetPortal({ ...props }: React.ComponentProps<typeof SheetPrim...
function SheetOverlay (line 23) | function SheetOverlay({ className, ...props }: React.ComponentProps<type...
function SheetContent (line 36) | function SheetContent({
function SheetHeader (line 73) | function SheetHeader({ className, ...props }: React.ComponentProps<"div"...
function SheetFooter (line 77) | function SheetFooter({ className, ...props }: React.ComponentProps<"div"...
function SheetTitle (line 81) | function SheetTitle({ className, ...props }: React.ComponentProps<typeof...
function SheetDescription (line 91) | function SheetDescription({ className, ...props }: React.ComponentProps<...
FILE: app/src/components/ui/sidebar.tsx
function Sidebar (line 11) | function Sidebar({
function SidebarInset (line 64) | function SidebarInset({ className, ...props }: React.ComponentProps<"mai...
function SidebarInput (line 78) | function SidebarInput({ className, ...props }: React.ComponentProps<type...
function SidebarHeader (line 89) | function SidebarHeader({ className, ...props }: React.ComponentProps<"di...
function SidebarFooter (line 100) | function SidebarFooter({ className, ...props }: React.ComponentProps<"di...
function SidebarSeparator (line 111) | function SidebarSeparator({ className, ...props }: React.ComponentProps<...
function SidebarContent (line 122) | function SidebarContent({ className, ...props }: React.ComponentProps<"d...
function SidebarGroup (line 136) | function SidebarGroup({ className, ...props }: React.ComponentProps<"div...
function SidebarGroupLabel (line 147) | function SidebarGroupLabel({
function SidebarGroupAction (line 168) | function SidebarGroupAction({
function SidebarGroupContent (line 191) | function SidebarGroupContent({ className, ...props }: React.ComponentPro...
function SidebarMenu (line 202) | function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
function SidebarMenuItem (line 213) | function SidebarMenuItem({ className, ...props }: React.ComponentProps<"...
function SidebarMenuButton (line 246) | function SidebarMenuButton({
function SidebarMenuAction (line 290) | function SidebarMenuAction({
function SidebarMenuBadge (line 322) | function SidebarMenuBadge({ className, ...props }: React.ComponentProps<...
function SidebarMenuSkeleton (line 341) | function SidebarMenuSkeleton({
function SidebarMenuSub (line 374) | function SidebarMenuSub({ className, ...props }: React.ComponentProps<"u...
function SidebarMenuSubItem (line 389) | function SidebarMenuSubItem({ className, ...props }: React.ComponentProp...
function SidebarMenuSubButton (line 400) | function SidebarMenuSubButton({
FILE: app/src/components/ui/skeleton.tsx
function Skeleton (line 3) | function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
FILE: app/src/components/ui/slider.tsx
function Slider (line 6) | function Slider({
FILE: app/src/components/ui/suggestion-node-static.tsx
function SuggestionLeafStatic (line 11) | function SuggestionLeafStatic(props: SlateLeafProps<TSuggestionText>) {
FILE: app/src/components/ui/suggestion-node.tsx
function SuggestionLeaf (line 14) | function SuggestionLeaf(props: PlateLeafProps<TSuggestionText>) {
function SuggestionLineBreakContent (line 69) | function SuggestionLineBreakContent({ suggestionData }: { suggestionData...
FILE: app/src/components/ui/suggestion-toolbar-button.tsx
function SuggestionToolbarButton (line 14) | function SuggestionToolbarButton() {
FILE: app/src/components/ui/switch.tsx
function Switch (line 6) | function Switch({ className, ...props }: React.ComponentProps<typeof Swi...
FILE: app/src/components/ui/table-icons.tsx
function BorderAllIcon (line 5) | function BorderAllIcon(props: LucideProps) {
function BorderBottomIcon (line 27) | function BorderBottomIcon(props: LucideProps) {
function BorderLeftIcon (line 61) | function BorderLeftIcon(props: LucideProps) {
function BorderNoneIcon (line 100) | function BorderNoneIcon(props: LucideProps) {
function BorderRightIcon (line 140) | function BorderRightIcon(props: LucideProps) {
function BorderTopIcon (line 179) | function BorderTopIcon(props: LucideProps) {
FILE: app/src/components/ui/table-node-static.tsx
function TableElementStatic (line 10) | function TableElementStatic({ children, ...props }: SlateElementProps<TT...
function TableRowElementStatic (line 25) | function TableRowElementStatic(props: SlateElementProps) {
function TableCellElementStatic (line 33) | function TableCellElementStatic({
function TableCellHeaderElementStatic (line 83) | function TableCellHeaderElementStatic(props: SlateElementProps<TTableCel...
FILE: app/src/components/ui/table-node.tsx
function TableFloatingToolbar (line 126) | function TableFloatingToolbar({ children, ...props }: React.ComponentPro...
function TableBordersDropdownMenuContent (line 257) | function TableBordersDropdownMenuContent(props: React.ComponentProps<typ...
function ColorDropdownMenu (line 314) | function ColorDropdownMenu({ children, tooltip }: { children: React.Reac...
function TableRowElement (line 357) | function TableRowElement(props: PlateElementProps<TTableRowElement>) {
function RowDragHandle (line 402) | function RowDragHandle({ dragRef }: { dragRef: React.Ref<any> }) {
function RowDropLine (line 424) | function RowDropLine() {
function TableCellElement (line 436) | function TableCellElement({
function TableCellHeaderElement (line 541) | function TableCellHeaderElement(props: React.ComponentProps<typeof Table...
FILE: app/src/components/ui/table-toolbar-button.tsx
function TableToolbarButton (line 37) | function TableToolbarButton(props: DropdownMenuProps) {
function TablePicker (line 205) | function TablePicker() {
FILE: app/src/components/ui/tabs.tsx
function Tabs (line 7) | function Tabs({ className, ...props }: React.ComponentProps<typeof TabsP...
function TabsList (line 11) | function TabsList({ className, ...props }: React.ComponentProps<typeof T...
function TabsTrigger (line 24) | function TabsTrigger({ className, ...props }: React.ComponentProps<typeo...
function TabsContent (line 43) | function TabsContent({ className, ...props }: React.ComponentProps<typeo...
FILE: app/src/components/ui/textarea.tsx
function Textarea (line 5) | function Textarea({ className, ...props }: React.ComponentProps<"textare...
FILE: app/src/components/ui/toc-node-static.tsx
function TocElementStatic (line 25) | function TocElementStatic(props: SlateElementProps) {
FILE: app/src/components/ui/toc-node.tsx
function TocElement (line 27) | function TocElement(props: PlateElementProps) {
FILE: app/src/components/ui/toggle-node-static.tsx
function ToggleElementStatic (line 9) | function ToggleElementStatic(props: SlateElementProps) {
FILE: app/src/components/ui/toggle-node.tsx
function ToggleElement (line 14) | function ToggleElement(props: PlateElementProps) {
FILE: app/src/components/ui/toggle-toolbar-button.tsx
function ToggleToolbarButton (line 10) | function ToggleToolbarButton(props: React.ComponentProps<typeof ToolbarB...
FILE: app/src/components/ui/toolbar.tsx
function Toolbar (line 15) | function Toolbar({ className, ...props }: React.ComponentProps<typeof To...
function ToolbarToggleGroup (line 19) | function ToolbarToggleGroup({
function ToolbarLink (line 26) | function ToolbarLink({ className, ...props }: React.ComponentProps<typeo...
function ToolbarSeparator (line 30) | function ToolbarSeparator({ className, ...props }: React.ComponentProps<...
type ToolbarButtonProps (line 80) | type ToolbarButtonProps = {
function ToolbarSplitButton (line 138) | function ToolbarSplitButton({ className, ...props }: React.ComponentProp...
type ToolbarSplitButtonPrimaryProps (line 142) | type ToolbarSplitButtonPrimaryProps = Omit<React.ComponentPropsWithoutRe...
function ToolbarSplitButtonPrimary (line 145) | function ToolbarSplitButtonPrimary({
function ToolbarSplitButtonSecondary (line 170) | function ToolbarSplitButtonSecondary({
function ToolbarToggleItem (line 195) | function ToolbarToggleItem({
function ToolbarGroup (line 204) | function ToolbarGroup({ children, className }: React.ComponentProps<"div...
type TooltipProps (line 216) | type TooltipProps<T extends React.ElementType> = {
function withTooltip (line 223) | function withTooltip<T extends React.ElementType>(Component: T) {
function TooltipContent (line 255) | function TooltipContent({
function ToolbarMenuGroup (line 281) | function ToolbarMenuGroup({
FILE: app/src/components/ui/tooltip.tsx
function TooltipProvider (line 8) | function TooltipProvider({ delayDuration = 0, ...props }: React.Componen...
function Tooltip (line 12) | function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimit...
function TooltipTrigger (line 20) | function TooltipTrigger({ ...props }: React.ComponentProps<typeof Toolti...
function TooltipContent (line 24) | function TooltipContent({
FILE: app/src/components/ui/tree.tsx
function Tree (line 5) | function Tree({ obj, deep = 0, className = "" }: { obj: any; deep?: numb...
FILE: app/src/components/ui/turn-into-toolbar-button.tsx
function TurnIntoToolbarButton (line 126) | function TurnIntoToolbarButton(props: DropdownMenuProps) {
FILE: app/src/components/vditor-panel.tsx
function MarkdownEditor (line 5) | function MarkdownEditor({
FILE: app/src/components/welcome-page.tsx
function WelcomePage (line 31) | function WelcomePage() {
FILE: app/src/core/Project.tsx
type ProjectState (line 96) | enum ProjectState {
class Project (line 122) | class Project extends EventEmitter<{
method constructor (line 162) | constructor(uri: URI) {
method newDraft (line 170) | static newDraft(): Project {
method loadService (line 182) | loadService(service: { id?: string; new (...args: any[]): any }) {
method disposeService (line 197) | disposeService(serviceId: string) {
method compareVersion (line 212) | private compareVersion(version1: string, version2: string): number {
method checkAndConfirmUpgrade (line 231) | private async checkAndConfirmUpgrade(currentVersion: string, latestVer...
method parseProjectFile (line 262) | private async parseProjectFile(): Promise<{
method init (line 317) | async init() {
method loop (line 354) | loop() {
method pause (line 362) | pause() {
method tick (line 367) | private tick() {
method dispose (line 399) | async dispose() {
method getService (line 416) | getService<T extends keyof this & string>(serviceId: T): this[T] {
method isDraft (line 420) | get isDraft() {
method uri (line 423) | get uri() {
method uri (line 426) | set uri(uri: URI) {
method stash (line 442) | async stash() {
method save (line 448) | async save() {
method getFileContent (line 465) | async getFileContent() {
method stageHash (line 488) | get stageHash() {
method registerFileSystemProvider (line 500) | registerFileSystemProvider(scheme: string, provider: { new (...args: a...
method fs (line 504) | get fs(): FileSystemProvider {
method addAttachment (line 508) | addAttachment(data: Blob) {
method state (line 514) | set state(state: ProjectState) {
method state (line 520) | get state(): ProjectState {
method isSaving (line 524) | set isSaving(isSaving: boolean) {
method isSaving (line 530) | get isSaving(): boolean {
method isRunning (line 534) | get isRunning(): boolean {
type Project (line 546) | interface Project {
method constructor (line 162) | constructor(uri: URI) {
method newDraft (line 170) | static newDraft(): Project {
method loadService (line 182) | loadService(service: { id?: string; new (...args: any[]): any }) {
method disposeService (line 197) | disposeService(serviceId: string) {
method compareVersion (line 212) | private compareVersion(version1: string, version2: string): number {
method checkAndConfirmUpgrade (line 231) | private async checkAndConfirmUpgrade(currentVersion: string, latestVer...
method parseProjectFile (line 262) | private async parseProjectFile(): Promise<{
method init (line 317) | async init() {
method loop (line 354) | loop() {
method pause (line 362) | pause() {
method tick (line 367) | private tick() {
method dispose (line 399) | async dispose() {
method getService (line 416) | getService<T extends keyof this & string>(serviceId: T): this[T] {
method isDraft (line 420) | get isDraft() {
method uri (line 423) | get uri() {
method uri (line 426) | set uri(uri: URI) {
method stash (line 442) | async stash() {
method save (line 448) | async save() {
method getFileContent (line 465) | async getFileContent() {
method stageHash (line 488) | get stageHash() {
method registerFileSystemProvider (line 500) | registerFileSystemProvider(scheme: string, provider: { new (...args: a...
method fs (line 504) | get fs(): FileSystemProvider {
method addAttachment (line 508) | addAttachment(data: Blob) {
method state (line 514) | set state(state: ProjectState) {
method state (line 520) | get state(): ProjectState {
method isSaving (line 524) | set isSaving(isSaving: boolean) {
method isSaving (line 530) | get isSaving(): boolean {
method isRunning (line 534) | get isRunning(): boolean {
FILE: app/src/core/algorithm/arrayFunctions.tsx
function sum (line 5) | function sum(arr: number[]): number {
function average (line 12) | function average(arr: number[]): number {
function isSame (line 19) | function isSame(arr: number[]): boolean {
function variance (line 38) | function variance(arr: number[]): number {
function standardDeviation (line 46) | function standardDeviation(arr: number[]): number {
function getMinAbsValue (line 54) | function getMinAbsValue(arr: number[]): number {
FILE: app/src/core/algorithm/geometry/convexHull.tsx
function computeConvexHull (line 13) | function computeConvexHull(points: Vector[]): Vector[] {
function cross (line 42) | function cross(a: Vector, b: Vector, c: Vector): number {
function buildHull (line 47) | function buildHull(hull: Vector[], point: Vector, shouldRemove: (a: Vect...
function isCollinear (line 60) | function isCollinear(points: Vector[]): boolean {
FILE: app/src/core/algorithm/numberFunctions.tsx
function isNumberNear (line 12) | function isNumberNear(number1: number, number2: number, tolerance: numbe...
function sinNumberByTime (line 22) | function sinNumberByTime(maxValue: number, minValue: number, cycleTime: ...
function mod (line 32) | function mod(x: number, y: number): number {
function logBase (line 42) | function logBase(x: number, b: number) {
FILE: app/src/core/algorithm/random.tsx
function randomInt (line 4) | function randomInt(min: number, max: number): number {
function randomFloat (line 7) | function randomFloat(min: number, max: number): number {
function randomBoolean (line 10) | function randomBoolean(): boolean {
function randomItem (line 13) | function randomItem<T>(items: T[]): T {
function randomItems (line 16) | function randomItems<T>(items: T[], count: number): T[] {
function randomVector (line 23) | function randomVector(min: Vector, max: Vector): Vector {
function randomVectorOnNormalCircle (line 30) | function randomVectorOnNormalCircle(): Vector {
function poissonRandom (line 39) | function poissonRandom(lambda: number): number {
FILE: app/src/core/algorithm/setFunctions.tsx
function isSubset (line 8) | function isSubset<T>(setA: Set<T>, setB: Set<T>): boolean {
FILE: app/src/core/fileSystemProvider/FileSystemProviderDraft.tsx
class FileSystemProviderDraft (line 9) | class FileSystemProviderDraft implements FileSystemProvider {
method constructor (line 10) | constructor(private readonly project: Project) {}
method read (line 12) | async read() {
method readDir (line 23) | async readDir() {
method write (line 26) | async write(_uri: URI, content: Uint8Array) {
method remove (line 39) | async remove() {}
method exists (line 40) | async exists() {
method mkdir (line 43) | async mkdir() {}
method rename (line 44) | async rename() {}
FILE: app/src/core/fileSystemProvider/FileSystemProviderFile.tsx
class FileSystemProviderFile (line 5) | class FileSystemProviderFile implements FileSystemProvider {
method read (line 6) | async read(uri: URI) {
method readDir (line 9) | async readDir(uri: URI) {
method write (line 12) | async write(uri: URI, content: Uint8Array) {
method remove (line 15) | async remove(uri: URI) {
method exists (line 18) | async exists(uri: URI) {
method mkdir (line 21) | async mkdir(uri: URI) {
method rename (line 24) | async rename(oldUri: URI, newUri: URI) {
FILE: app/src/core/interfaces/Service.tsx
type Service (line 4) | interface Service {
type FileSystemProvider (line 9) | interface FileSystemProvider {
FILE: app/src/core/loadAllServices.tsx
function loadAllServicesBeforeInit (line 82) | function loadAllServicesBeforeInit(project: Project): void {
function loadAllServicesAfterInit (line 176) | function loadAllServicesAfterInit(project: Project): void {
FILE: app/src/core/plugin/PluginCodeParseData.tsx
type PluginCodeParseData (line 4) | interface PluginCodeParseData {
function parsePluginCode (line 34) | function parsePluginCode(code: string): { data: PluginCodeParseData; err...
FILE: app/src/core/plugin/PluginWorker.tsx
class PluginWorker (line 7) | class PluginWorker {
method constructor (line 12) | constructor(code: string, manifest: PluginManifest) {
method destroy (line 117) | destroy() {
FILE: app/src/core/plugin/UserScriptsManager.tsx
type UserScriptFile (line 16) | type UserScriptFile = {
function init (line 31) | async function init() {
function startRunUserScripts (line 44) | async function startRunUserScripts() {
function enableUserScript (line 59) | async function enableUserScript(filePath: string) {
function disableUserScript (line 71) | async function disableUserScript(filePath: string) {
function validAndRefresh (line 81) | async function validAndRefresh() {
function getAllUserScripts (line 113) | async function getAllUserScripts(): Promise<UserScriptFile[]> {
function addUserScript (line 123) | async function addUserScript(filePath: string) {
function checkoutUserScriptEnabled (line 148) | async function checkoutUserScriptEnabled(filePath: string, enabled: bool...
function removeUserScript (line 173) | async function removeUserScript(filePath: string) {
FILE: app/src/core/plugin/apis.tsx
method hello (line 5) | hello(userString: string) {
FILE: app/src/core/plugin/types.tsx
type PluginPackage (line 4) | interface PluginPackage {
function getAllAPIMethods (line 25) | function getAllAPIMethods(): (keyof typeof apiTypes)[] {
type Zod2Interface (line 29) | type Zod2Interface<T> = {
type Asyncize (line 45) | type Asyncize<T extends (...args: any[]) => any> = (...args: Parameters<...
type AsyncizeInterface (line 46) | type AsyncizeInterface<T> = {
type SyncOrAsyncizeInterface (line 49) | type SyncOrAsyncizeInterface<T> = {
type PluginAPI (line 53) | type PluginAPI = Zod2Interface<typeof apiTypes>;
type PluginAPIMayAsync (line 54) | type PluginAPIMayAsync = SyncOrAsyncizeInterface<PluginAPI>;
type CallAPIMessage (line 61) | type CallAPIMessage = {
type APIResponseMessage (line 73) | type APIResponseMessage = {
type WorkerMessage (line 82) | type WorkerMessage = CallAPIMessage | APIResponseMessage;
type PluginManifest (line 87) | interface PluginManifest {
FILE: app/src/core/render/canvas2d/basicRenderer/ImageRenderer.tsx
class ImageRenderer (line 9) | class ImageRenderer {
method constructor (line 10) | constructor(private readonly project: Project) {}
method renderImageElement (line 18) | renderImageElement(
method renderImageBitmap (line 38) | renderImageBitmap(
FILE: app/src/core/render/canvas2d/basicRenderer/curveRenderer.tsx
class CurveRenderer (line 11) | class CurveRenderer {
method constructor (line 12) | constructor(private readonly project: Project) {}
method renderSolidLine (line 21) | renderSolidLine(start: Vector, end: Vector, color: Color, width: numbe...
method renderSolidLineMultiple (line 36) | renderSolidLineMultiple(locations: Vector[], color: Color, width: numb...
method renderPenStroke (line 46) | renderPenStroke(stroke: PenStrokeSegment[], color: Color): void {
method renderSolidLineMultipleSmoothly (line 83) | renderSolidLineMultipleSmoothly(locations: Vector[], color: Color, wid...
method smoothPoints (line 97) | private smoothPoints(points: Vector[], tension = 0.5) {
method renderSolidLineMultipleWithWidth (line 129) | renderSolidLineMultipleWithWidth(locations: Vector[], color: Color, wi...
method renderSolidLineMultipleWithShadow (line 160) | renderSolidLineMultipleWithShadow(
method renderDashedLine (line 191) | renderDashedLine(start: Vector, end: Vector, color: Color, width: numb...
method renderDoubleLine (line 212) | renderDoubleLine(start: Vector, end: Vector, color: Color, width: numb...
method renderBezierCurve (line 226) | renderBezierCurve(curve: CubicBezierCurve, color: Color, width: number...
method renderDashedBezierCurve (line 249) | renderDashedBezierCurve(curve: CubicBezierCurve, color: Color, width: ...
method renderDoubleBezierCurve (line 276) | renderDoubleBezierCurve(curve: CubicBezierCurve, color: Color, width: ...
method renderSymmetryCurve (line 312) | renderSymmetryCurve(curve: SymmetryCurve, color: Color, width: number)...
method renderGradientLine (line 319) | renderGradientLine(start: Vector, end: Vector, startColor: Color, endC...
method renderGradientBezierCurve (line 335) | renderGradientBezierCurve(curve: CubicBezierCurve, startColor: Color, ...
FILE: app/src/core/render/canvas2d/basicRenderer/shapeRenderer.tsx
class ShapeRenderer (line 10) | class ShapeRenderer {
method constructor (line 11) | constructor(private readonly project: Project) {}
method renderCircle (line 22) | renderCircle(centerLocation: Vector, radius: number, color: Color, str...
method renderArc (line 42) | renderArc(
method renderRectFromCenter (line 67) | renderRectFromCenter(
method renderRect (line 99) | renderRect(rect: Rectangle, color: Color, strokeColor: Color, strokeWi...
method renderDashedRect (line 109) | renderDashedRect(
method renderRectWithShadow (line 133) | renderRectWithShadow(
method renderPolygonAndFill (line 169) | renderPolygonAndFill(
method renderCircleTransition (line 195) | renderCircleTransition(viewLocation: Vector, radius: number, centerCol...
method renderCameraShapeBorder (line 224) | renderCameraShapeBorder(rect: Rectangle, borderColor: Color, borderWid...
method renderResizeArrow (line 274) | renderResizeArrow(rect: Rectangle, color: Color, strokeWidth: number) {
FILE: app/src/core/render/canvas2d/basicRenderer/svgRenderer.tsx
class SvgRenderer (line 5) | class SvgRenderer {
method constructor (line 8) | constructor(private readonly project: Project) {}
method renderSvgFromLeftTop (line 10) | renderSvgFromLeftTop(svg: string, location: Vector, width: number, hei...
method renderSvgFromCenter (line 22) | renderSvgFromCenter(svg: string, centerLocation: Vector, width: number...
method renderSvgFromLeftTopWithoutSize (line 40) | renderSvgFromLeftTopWithoutSize(svg: string, location: Vector, scaleNu...
method renderSvgFromCenterWithoutSize (line 59) | renderSvgFromCenterWithoutSize(svg: string, centerLocation: Vector): v...
FILE: app/src/core/render/canvas2d/basicRenderer/textRenderer.tsx
class TextRenderer (line 14) | class TextRenderer {
method constructor (line 17) | constructor(private readonly project: Project) {}
method hash (line 19) | private hash(text: string, size: number): string {
method getCache (line 24) | private getCache(text: string, size: number) {
method getCacheNearestSize (line 32) | private getCacheNearestSize(text: string, size: number): ImageBitmap |...
method buildCache (line 56) | private buildCache(text: string, size: number, color: Color): CanvasIm...
method renderText (line 85) | renderText(text: string, location: Vector, size: number, color: Color ...
method renderTempText (line 130) | renderTempText(text: string, location: Vector, size: number, color: Co...
method renderTextFromCenter (line 147) | renderTextFromCenter(text: string, centerLocation: Vector, size: numbe...
method renderTempTextFromCenter (line 156) | renderTempTextFromCenter(text: string, centerLocation: Vector, size: n...
method renderTextInRectangle (line 166) | renderTextInRectangle(text: string, rectangle: Rectangle, color: Color...
method getFontSizeByRectangleSize (line 171) | private getFontSizeByRectangleSize(text: string, rectangle: Rectangle)...
method renderMultiLineText (line 205) | renderMultiLineText(
method renderTempMultiLineText (line 238) | renderTempMultiLineText(
method renderMultiLineTextFromCenter (line 267) | renderMultiLineTextFromCenter(
method renderTempMultiLineTextFromCenter (line 300) | renderTempMultiLineTextFromCenter(
method textToTextArrayWrapCache (line 342) | private textToTextArrayWrapCache(text: string, fontSize: number, limit...
method textToTextArray (line 358) | private textToTextArray(text: string, fontSize: number, limitWidth: nu...
method measureMultiLineTextSize (line 404) | measureMultiLineTextSize(text: string, fontSize: number, limitWidth: n...
FILE: app/src/core/render/canvas2d/controllerRenderer/drawingRenderer.tsx
class DrawingControllerRenderer (line 11) | class DrawingControllerRenderer {
method constructor (line 12) | constructor(private readonly project: Project) {}
method renderTempDrawing (line 17) | renderTempDrawing() {
method renderTrace (line 37) | private renderTrace(currentStrokeColor: Color) {
method renderMouse (line 84) | private renderMouse(currentStrokeColor: Color) {
method renderAdjusting (line 100) | private renderAdjusting(currentStrokeColor: Color) {
method renderAxisMouse (line 125) | private renderAxisMouse() {
method rotateUpAngle (line 141) | rotateUpAngle() {
method rotateDownAngle (line 145) | rotateDownAngle() {
method renderAngleMouse (line 152) | private renderAngleMouse(mouseLocation: Vector) {
method renderLine (line 184) | private renderLine(lineStart: Vector, lineEnd: Vector) {
FILE: app/src/core/render/canvas2d/debugRender.tsx
function debugRender (line 4) | function debugRender() {}
FILE: app/src/core/render/canvas2d/entityRenderer/CollisionBoxRenderer.tsx
class CollisionBoxRenderer (line 10) | class CollisionBoxRenderer {
method constructor (line 11) | constructor(private readonly project: Project) {}
method render (line 13) | render(collideBox: CollisionBox, color: Color) {
FILE: app/src/core/render/canvas2d/entityRenderer/EntityDetailsButtonRenderer.tsx
class EntityDetailsButtonRenderer (line 11) | class EntityDetailsButtonRenderer {
method constructor (line 12) | constructor(private readonly project: Project) {}
method render (line 14) | render(entity: Entity) {
FILE: app/src/core/render/canvas2d/entityRenderer/EntityRenderer.tsx
class EntityRenderer (line 20) | class EntityRenderer {
method constructor (line 23) | constructor(private readonly project: Project) {}
method sortSectionsByZIndex (line 30) | sortSectionsByZIndex() {
method renderAllSectionsBackground (line 38) | renderAllSectionsBackground(viewRectangle: Rectangle) {
method renderAllSectionsBigTitle (line 61) | renderAllSectionsBigTitle(viewRectangle: Rectangle) {
method shouldSkipEntity (line 87) | private shouldSkipEntity(entity: Entity, viewRectangle: Rectangle): bo...
method isBackgroundImageNode (line 95) | private isBackgroundImageNode(entity: Entity): boolean {
method renderAllEntities (line 102) | renderAllEntities(viewRectangle: Rectangle) {
method renderEntity (line 145) | renderEntity(entity: Entity) {
method renderEntityDebug (line 175) | private renderEntityDebug(entity: Entity) {
method renderConnectPoint (line 186) | private renderConnectPoint(connectPoint: ConnectPoint) {
method renderImageNode (line 222) | private renderImageNode(imageNode: ImageNode) {
method renderPenStroke (line 300) | private renderPenStroke(penStroke: PenStroke) {
method renderEntityDetails (line 340) | renderEntityDetails(entity: Entity) {
method _renderEntityDetails (line 351) | _renderEntityDetails(entity: Entity, limitLiens: number) {
method renderEntityTagShap (line 368) | renderEntityTagShap(entity: Entity) {
FILE: app/src/core/render/canvas2d/entityRenderer/ReferenceBlockRenderer.tsx
class ReferenceBlockRenderer (line 12) | class ReferenceBlockRenderer {
method constructor (line 13) | constructor(private readonly project: Project) {}
method render (line 15) | render(referenceBlockNode: ReferenceBlockNode) {
method renderBrackets (line 151) | private renderBrackets(rect: Rectangle, color: Color) {
method renderSourceSectionBorder (line 205) | public renderSourceSectionBorder(section: Section, countNumber: number...
FILE: app/src/core/render/canvas2d/entityRenderer/edge/EdgeRenderer.tsx
class EdgeRenderer (line 22) | class EdgeRenderer {
method constructor (line 29) | constructor(private readonly project: Project) {
method checkRendererBySettings (line 34) | checkRendererBySettings(lineStyle: Settings["lineStyle"]) {
method updateRenderer (line 45) | async updateRenderer(style: Settings["lineStyle"]) {
method renderLineEdge (line 55) | renderLineEdge(edge: LineEdge) {
method renderCrEdge (line 107) | renderCrEdge(edge: CubicCatmullRomSplineEdge) {
method getMinNonCollapseParentSection (line 159) | getMinNonCollapseParentSection(innerEntity: ConnectableEntity): Section {
method getEdgeView (line 173) | getEdgeView(edge: LineEdge): LineEdge {
method getEdgeSvg (line 197) | getEdgeSvg(edge: LineEdge): React.ReactNode {
method renderVirtualEdge (line 213) | renderVirtualEdge(startNode: ConnectableEntity, mouseLocation: Vector) {
method renderVirtualConfirmedEdge (line 216) | renderVirtualConfirmedEdge(startNode: ConnectableEntity, endNode: Conn...
method getCuttingEffects (line 220) | getCuttingEffects(edge: Edge) {
method getConnectedEffects (line 223) | getConnectedEffects(startNode: ConnectableEntity, toNode: ConnectableE...
method renderArrowHead (line 233) | renderArrowHead(endPoint: Vector, direction: Vector, size: number, col...
method generateArrowHeadSvg (line 258) | generateArrowHeadSvg(endPoint: Vector, direction: Vector, size: number...
FILE: app/src/core/render/canvas2d/entityRenderer/edge/EdgeRendererClass.tsx
method constructor (line 29) | constructor() {}
method isCycleState (line 31) | isCycleState(edge: LineEdge): boolean {
method isNormalState (line 34) | isNormalState(edge: LineEdge): boolean {
FILE: app/src/core/render/canvas2d/entityRenderer/edge/concrete/StraightEdgeRenderer.tsx
class StraightEdgeRenderer (line 20) | class StraightEdgeRenderer extends EdgeRendererClass {
method constructor (line 21) | constructor(private readonly project: Project) {
method getCuttingEffects (line 25) | getCuttingEffects(edge: LineEdge): Effect[] {
method getConnectedEffects (line 36) | getConnectedEffects(startNode: ConnectableEntity, toNode: ConnectableE...
method renderLine (line 55) | private renderLine(start: Vector, end: Vector, edge: LineEdge, width: ...
method renderNormalState (line 70) | public renderNormalState(edge: LineEdge): void {
method getNormalStageSvg (line 134) | public getNormalStageSvg(edge: LineEdge): React.ReactNode {
method getCycleStageSvg (line 177) | public getCycleStageSvg(): React.ReactNode {
method getShiftingStageSvg (line 180) | public getShiftingStageSvg(): React.ReactNode {
method renderArrowHead (line 184) | private renderArrowHead(edge: LineEdge, direction: Vector, endPoint = ...
method renderShiftingState (line 191) | public renderShiftingState(edge: LineEdge): void {
method renderCycleState (line 253) | public renderCycleState(edge: LineEdge): void {
method renderVirtualEdge (line 283) | public renderVirtualEdge(startNode: ConnectableEntity, mouseLocation: ...
method renderVirtualConfirmedEdge (line 293) | public renderVirtualConfirmedEdge(startNode: ConnectableEntity, endNod...
FILE: app/src/core/render/canvas2d/entityRenderer/edge/concrete/SymmetryCurveEdgeRenderer.tsx
class SymmetryCurveEdgeRenderer (line 22) | class SymmetryCurveEdgeRenderer extends EdgeRendererClass {
method constructor (line 23) | constructor(private readonly project: Project) {
method getCuttingEffects (line 27) | getCuttingEffects(edge: LineEdge): Effect[] {
method getConnectedEffects (line 49) | getConnectedEffects(startNode: ConnectableEntity, toNode: ConnectableE...
method renderNormalState (line 68) | public renderNormalState(edge: LineEdge): void {
method renderShiftingState (line 148) | public renderShiftingState(edge: LineEdge): void {
method renderCycleState (line 180) | public renderCycleState(edge: LineEdge): void {
method getNormalStageSvg (line 205) | public getNormalStageSvg(edge: LineEdge): React.ReactNode {
method getCycleStageSvg (line 248) | public getCycleStageSvg(): React.ReactNode {
method getShiftingStageSvg (line 251) | public getShiftingStageSvg(): React.ReactNode {
method renderVirtualEdge (line 254) | public renderVirtualEdge(startNode: ConnectableEntity, mouseLocation: ...
method renderVirtualConfirmedEdge (line 277) | public renderVirtualConfirmedEdge(startNode: ConnectableEntity, endNod...
method renderArrowCurve (line 299) | private renderArrowCurve(curve: SymmetryCurve, color: Color, width = 2...
method renderText (line 387) | private renderText(curve: SymmetryCurve, edge: LineEdge): void {
FILE: app/src/core/render/canvas2d/entityRenderer/edge/concrete/VerticalPolyEdgeRenderer.tsx
class VerticalPolyEdgeRenderer (line 18) | class VerticalPolyEdgeRenderer extends EdgeRendererClass {
method constructor (line 19) | constructor(private readonly project: Project) {
method getCuttingEffects (line 23) | getCuttingEffects(edge: LineEdge): Effect[] {
method getConnectedEffects (line 46) | getConnectedEffects(startNode: ConnectableEntity, toNode: ConnectableE...
method getVerticalDirection (line 74) | getVerticalDirection(edge: LineEdge): Vector {
method renderTest (line 129) | renderTest(edge: LineEdge) {
method gaussianFunction (line 141) | gaussianFunction(x: number) {
method renderNormalState (line 146) | public renderNormalState(edge: LineEdge): void {
method renderShiftingState (line 296) | public renderShiftingState(edge: LineEdge): void {
method renderArrowHead (line 347) | private renderArrowHead(edge: LineEdge, direction: Vector, endPoint = ...
method renderCycleState (line 352) | public renderCycleState(edge: LineEdge): void {
method getNormalStageSvg (line 370) | public getNormalStageSvg(edge: LineEdge): React.ReactNode {
method getCycleStageSvg (line 413) | public getCycleStageSvg(): React.ReactNode {
method getShiftingStageSvg (line 416) | public getShiftingStageSvg(): React.ReactNode {
method renderVirtualEdge (line 420) | public renderVirtualEdge(startNode: ConnectableEntity, mouseLocation: ...
method renderVirtualConfirmedEdge (line 430) | public renderVirtualConfirmedEdge(startNode: ConnectableEntity, endNod...
FILE: app/src/core/render/canvas2d/entityRenderer/multiTargetUndirectedEdge/MultiTargetUndirectedEdgeRenderer.tsx
class MultiTargetUndirectedEdgeRenderer (line 9) | class MultiTargetUndirectedEdgeRenderer {
method constructor (line 10) | constructor(private readonly project: Project) {}
method render (line 12) | render(edge: MultiTargetUndirectedEdge) {
method renderLineShape (line 80) | private renderLineShape(edge: MultiTargetUndirectedEdge, edgeColor: Co...
method renderConvexShape (line 123) | private renderConvexShape(edge: MultiTargetUndirectedEdge, edgeColor: ...
method renderCircle (line 151) | private renderCircle(edge: MultiTargetUndirectedEdge, edgeColor: Color...
FILE: app/src/core/render/canvas2d/entityRenderer/section/SectionRenderer.tsx
class SectionRenderer (line 10) | class SectionRenderer {
method constructor (line 11) | constructor(private readonly project: Project) {}
method renderCollapsed (line 14) | private renderCollapsed(section: Section) {
method renderNoCollapse (line 51) | private renderNoCollapse(section: Section) {
method renderBackgroundColor (line 81) | renderBackgroundColor(section: Section) {
method renderBigCoveredTitle (line 119) | renderBigCoveredTitle(section: Section) {
method renderTopTitle (line 163) | renderTopTitle(section: Section) {
method render (line 229) | render(section: Section): void {
FILE: app/src/core/render/canvas2d/entityRenderer/svgNode/SvgNodeRenderer.tsx
class SvgNodeRenderer (line 9) | class SvgNodeRenderer {
method constructor (line 10) | constructor(private readonly project: Project) {}
method render (line 13) | render(svgNode: SvgNode) {
FILE: app/src/core/render/canvas2d/entityRenderer/textNode/TextNodeRenderer.tsx
class TextNodeRenderer (line 15) | class TextNodeRenderer {
method constructor (line 17) | constructor(private readonly project: Project) {}
method renderTextNode (line 19) | renderTextNode(node: TextNode) {
method renderKeyboardTreeHint (line 137) | private renderKeyboardTreeHint(node: TextNode): void {
method renderLogicNodeWarningTrap (line 203) | private renderLogicNodeWarningTrap(node: TextNode) {
method renderTextNodeTextLayer (line 259) | private renderTextNodeTextLayer(node: TextNode) {
FILE: app/src/core/render/canvas2d/entityRenderer/urlNode/urlNodeRenderer.tsx
class UrlNodeRenderer (line 9) | class UrlNodeRenderer {
method constructor (line 10) | constructor(private readonly project: Project) {}
method render (line 12) | render(urlNode: UrlNode): void {
method renderHoverState (line 69) | private renderHoverState(urlNode: UrlNode): void {
FILE: app/src/core/render/canvas2d/renderer.tsx
class Renderer (line 18) | class Renderer {
method resizeWindow (line 54) | resizeWindow(newW: number, newH: number) {
method constructor (line 66) | constructor(private readonly project: Project) {}
method tick (line 73) | tick() {
method tick_ (line 83) | private tick_() {
method renderViewElements (line 95) | private renderViewElements(_viewRectangle: Rectangle) {
method renderMainStageElements (line 101) | private renderMainStageElements(viewRectangle: Rectangle) {
method renderStageElementsWithoutReactions (line 118) | private renderStageElementsWithoutReactions(viewRectangle: Rectangle) {
method isOverView (line 130) | isOverView(viewRectangle: Rectangle, entity: StageObject): boolean {
method renderCenterPointer (line 140) | private renderCenterPointer() {
method renderHoverCollisionBox (line 166) | private renderHoverCollisionBox() {
method renderSelectingRectangle (line 194) | private renderSelectingRectangle() {
method renderCuttingLine (line 276) | private renderCuttingLine() {
method renderConnectingLine (line 288) | private renderConnectingLine() {
method renderKeyboardOnly (line 330) | private renderKeyboardOnly() {
method rendererLayerMovingLine (line 379) | private rendererLayerMovingLine() {
method renderJumpLine (line 454) | private renderJumpLine(startLocation: Vector, endLocation: Vector) {
method renderWarningStageObjects (line 505) | private renderWarningStageObjects() {
method renderTags (line 529) | private renderTags() {
method renderEntities (line 548) | private renderEntities(viewRectangle: Rectangle) {
method renderEdges (line 552) | private renderEdges(viewRectangle: Rectangle) {
method renderBackground (line 574) | private renderBackground() {
method updateFPS (line 602) | private updateFPS() {
method renderDebugDetails (line 619) | private renderDebugDetails() {
method renderSpecialKeys (line 668) | private renderSpecialKeys() {
method transformWorld2View (line 745) | transformWorld2View(arg1: Vector | Rectangle): Vector | Rectangle {
method transformView2World (line 771) | transformView2World(arg1: Vector | Rectangle): Vector | Rectangle {
method getCoverWorldRectangle (line 789) | getCoverWorldRectangle(): Rectangle {
FILE: app/src/core/render/canvas2d/utilsRenderer/RenderUtils.tsx
class RenderUtils (line 9) | class RenderUtils {
method constructor (line 10) | constructor(private readonly project: Project) {}
method renderPixel (line 17) | renderPixel(location: Vector, color: Color) {
method renderArrow (line 30) | renderArrow(direction: Vector, location: Vector, color: Color, size: n...
FILE: app/src/core/render/canvas2d/utilsRenderer/WorldRenderUtils.tsx
class WorldRenderUtils (line 10) | class WorldRenderUtils {
method constructor (line 11) | constructor(private readonly project: Project) {}
method renderCubicCatmullRomSpline (line 17) | renderCubicCatmullRomSpline(spline: CubicCatmullRomSpline, color: Colo...
method renderBezierCurve (line 69) | renderBezierCurve(curve: CubicBezierCurve, color: Color, width: number...
method renderSymmetryCurve (line 86) | renderSymmetryCurve(curve: SymmetryCurve, color: Color, width: number)...
method renderDashedSymmetryCurve (line 94) | renderDashedSymmetryCurve(curve: SymmetryCurve, color: Color, width: n...
method renderDoubleSymmetryCurve (line 116) | renderDoubleSymmetryCurve(curve: SymmetryCurve, color: Color, width: n...
method renderLaser (line 134) | renderLaser(start: Vector, end: Vector, width: number, color: Color): ...
method renderPrismaticBlock (line 174) | renderPrismaticBlock(
method renderRectangleFlash (line 200) | renderRectangleFlash(rectangle: Rectangle, shadowColor: Color, shadowB...
method renderCuttingFlash (line 221) | renderCuttingFlash(start: Vector, end: Vector, width: number, shadowCo...
FILE: app/src/core/render/canvas2d/utilsRenderer/backgroundRenderer.tsx
class BackgroundRenderer (line 6) | class BackgroundRenderer {
method constructor (line 7) | constructor(private readonly project: Project) {}
method renderDotBackground (line 15) | renderDotBackground(viewRect: Rectangle) {
method renderHorizonBackground (line 36) | renderHorizonBackground(viewRect: Rectangle) {
method renderVerticalBackground (line 58) | renderVerticalBackground(viewRect: Rectangle) {
method renderCartesianBackground (line 80) | renderCartesianBackground(viewRect: Rectangle) {
method getCurrentGap (line 122) | getCurrentGap(): number {
method getLocationXIterator (line 133) | *getLocationXIterator(viewRect: Rectangle, currentGap: number): Iterab...
method getLocationYIterator (line 141) | *getLocationYIterator(viewRect: Rectangle, currentGap: number): Iterab...
FILE: app/src/core/render/canvas2d/utilsRenderer/globalMaskRenderer.tsx
function renderMask (line 9) | function renderMask(project: Project, mouseLocation: { x: number; y: num...
function renderCircleMask (line 27) | function renderCircleMask(project: Project, mouseLocation: { x: number; ...
function renderSquareMask (line 57) | function renderSquareMask(project: Project, mouseLocation: { x: number; ...
function renderTopLeftQuadrantMask (line 91) | function renderTopLeftQuadrantMask(project: Project, mouseLocation: { x:...
function renderSmartContextMask (line 129) | function renderSmartContextMask(project: Project, mouseLocation: { x: nu...
FILE: app/src/core/render/canvas2d/utilsRenderer/searchContentHighlightRenderer.tsx
class SearchContentHighlightRenderer (line 8) | class SearchContentHighlightRenderer {
method constructor (line 9) | constructor(private readonly project: Project) {}
method render (line 11) | render(frameTickIndex: number) {
FILE: app/src/core/render/domElement/RectangleElement.tsx
function div (line 8) | function div(rectangle: Rectangle, color: Color) {
FILE: app/src/core/render/domElement/inputElement.tsx
class InputElement (line 14) | class InputElement {
method input (line 23) | input(
method textarea (line 129) | textarea(
method addSuccessEffect (line 342) | private addSuccessEffect() {
method addFailEffect (line 349) | private addFailEffect(withToast = true) {
method constructor (line 359) | constructor(private readonly project: Project) {}
function moveToLineStart (line 363) | function moveToLineStart(textarea: HTMLTextAreaElement, isSelecting = fa...
function moveToLineEnd (line 397) | function moveToLineEnd(textarea: HTMLTextAreaElement, isSelecting = fals...
FILE: app/src/core/render/svg/SvgUtils.tsx
function line (line 11) | function line(start: Vector, end: Vector, strokeColor: Color, strokeWidt...
function textFromCenter (line 25) | function textFromCenter(text: string, location: Vector, fontSize: number...
function textFromLeftTop (line 42) | function textFromLeftTop(text: string, location: Vector, fontSize: numbe...
function multiLineTextFromLeftTop (line 59) | function multiLineTextFromLeftTop(
function rectangle (line 76) | function rectangle(rectangle: Rectangle, fillColor: Color, strokeColor: ...
FILE: app/src/core/service/AssetsRepository.tsx
function fetchFile (line 7) | async function fetchFile<T extends string>(path: T extends `/${string}` ...
function getGuideFileUrl (line 13) | function getGuideFileUrl<T extends string>(path: T extends `/${string}` ...
FILE: app/src/core/service/GlobalMenu.tsx
function GlobalMenu (line 155) | function GlobalMenu() {
function onNewDraft (line 1554) | async function onNewDraft() {
function onOpenFile (line 1563) | async function onOpenFile(uri?: URI, source: string = "unknown"): Promis...
function createFileAtCurrentProjectDir (line 1772) | async function createFileAtCurrentProjectDir(activeProject: Project | un...
function getOneSelectedTextNodeWhenExportingPlainText (line 1850) | function getOneSelectedTextNodeWhenExportingPlainText(activeProject: Pro...
FILE: app/src/core/service/QuickSettingsManager.tsx
type QuickSettingItem (line 15) | type QuickSettingItem = {
function init (line 37) | async function init() {
function getQuickSettings (line 50) | async function getQuickSettings(): Promise<QuickSettingItem[]> {
function setQuickSettings (line 58) | async function setQuickSettings(items: QuickSettingItem[]): Promise<void> {
function addQuickSetting (line 66) | async function addQuickSetting(item: QuickSettingItem): Promise<void> {
function removeQuickSetting (line 78) | async function removeQuickSetting(
function reorderQuickSettings (line 89) | async function reorderQuickSettings(newOrder: QuickSettingItem[]): Promi...
function isValidBooleanSetting (line 96) | function isValidBooleanSetting(settingKey: string): boolean {
function getAllAvailableBooleanSettings (line 115) | function getAllAvailableBooleanSettings(): Array<keyof ReturnType<typeof...
FILE: app/src/core/service/Settings.tsx
type Settings (line 208) | type Settings = z.infer<typeof settingsSchema>;
FILE: app/src/core/service/SubWindow.tsx
type Window (line 9) | interface Window {
function getMaxZIndex (line 40) | function getMaxZIndex() {
function create (line 43) | function create(options: Partial<Window>): Window {
function update (line 83) | function update(id: string, options: Partial<Omit<Window, "id">>) {
function close (line 89) | function close(id: string) {
function focus (line 117) | function focus(id: string) {
function get (line 126) | function get(id: string) {
function closeAll (line 134) | function closeAll() {
function hasOpenWindows (line 146) | function hasOpenWindows(): boolean {
FILE: app/src/core/service/Telemetry.tsx
function event (line 15) | async function event(event: string, data: any = {}) {
FILE: app/src/core/service/Themes.tsx
type Metadata (line 8) | type Metadata = {
type Theme (line 15) | type Theme = {
function getThemeById (line 33) | async function getThemeById(id: string) {
function convertThemeToCSS (line 50) | function convertThemeToCSS(theme: any) {
function applyThemeById (line 66) | async function applyThemeById(themeId: string) {
function applyTheme (line 69) | async function applyTheme(themeContent: any) {
function writeCustomTheme (line 83) | async function writeCustomTheme(theme: Theme) {
function deleteCustomTheme (line 91) | async function deleteCustomTheme(themeId: string) {
function ids (line 96) | async function ids() {
function list (line 105) | async function list() {
FILE: app/src/core/service/Tourials.tsx
function init (line 11) | async function init() {
function finish (line 15) | async function finish(tourial: string) {
function reset (line 20) | async function reset() {
function tour (line 25) | async function tour(tourial: string, fn: () => void | Promise<void>) {
FILE: app/src/core/service/UserState.tsx
function init (line 8) | async function init() {
function getToken (line 15) | async function getToken() {
function setToken (line 21) | async function setToken(token: string) {
FILE: app/src/core/service/controlService/DirectionKeyUtilsEngine/directionKeyUtilsEngine.tsx
class DirectionKeyUtilsEngine (line 10) | class DirectionKeyUtilsEngine {
method constructor (line 40) | constructor() {}
method reset (line 52) | protected reset() {}
method resetLocation (line 58) | public resetLocation(location: Vector) {
method init (line 68) | public init() {}
method keyPress (line 72) | public keyPress(direction: Direction) {
method keyRelease (line 84) | public keyRelease(direction: Direction) {
method logicTick (line 94) | public logicTick() {
FILE: app/src/core/service/controlService/MouseLocation.tsx
method init (line 6) | init() {
method vector (line 32) | vector(): Vector {
FILE: app/src/core/service/controlService/autoLayoutEngine/autoLayoutFastTreeMode.tsx
class AutoLayoutFastTree (line 12) | class AutoLayoutFastTree {
method constructor (line 13) | constructor(private readonly project: Project) {}
method getTreeBoundingRectangle (line 20) | private getTreeBoundingRectangle(node: ConnectableEntity): Rectangle {
method moveTreeRectTo (line 30) | private moveTreeRectTo(treeRoot: ConnectableEntity, targetLocation: Ve...
method getSortedChildNodes (line 42) | private getSortedChildNodes(
method alignTrees (line 67) | private alignTrees(trees: ConnectableEntity[], direction: "top" | "bot...
method adjustChildrenTreesByRootNodeLocation (line 121) | private adjustChildrenTreesByRootNodeLocation(
method resolveSubtreeOverlaps (line 179) | private resolveSubtreeOverlaps(
method hasOverlapOrLineIntersection (line 281) | private hasOverlapOrLineIntersection(
method autoLayoutFastTreeMode (line 510) | public autoLayoutFastTreeMode(rootNode: ConnectableEntity) {
method treeReverseX (line 589) | treeReverseX(selectedRootEntity: ConnectableEntity) {
method treeReverseY (line 592) | treeReverseY(selectedRootEntity: ConnectableEntity) {
method treeReverse (line 599) | private treeReverse(selectedRootEntity: ConnectableEntity, direction: ...
FILE: app/src/core/service/controlService/autoLayoutEngine/mainTick.tsx
function getEntityRadius (line 11) | function getEntityRadius(entity: ConnectableEntity): number {
function distanceToForce (line 22) | function distanceToForce(distance: number): number {
class AutoLayout (line 27) | class AutoLayout {
method constructor (line 28) | constructor(private readonly project: Project) {}
method tick (line 32) | tick() {
method setGravityLayoutStart (line 43) | public setGravityLayoutStart() {
method setGravityLayoutEnd (line 47) | public setGravityLayoutEnd() {
method getDAGLayoutInput (line 54) | private getDAGLayoutInput(entities: ConnectableEntity[]): {
method computeDAGLayout (line 91) | private computeDAGLayout(input: {
method topologicalSort (line 199) | private topologicalSort(
method autoLayoutDAG (line 274) | public autoLayoutDAG(entities: ConnectableEntity[]) {
method gravityLayoutTick (line 309) | gravityLayoutTick() {
FILE: app/src/core/service/controlService/controller/Controller.tsx
class Controller (line 29) | class Controller {
method pressingKeysString (line 38) | pressingKeysString(): string {
method resetCountdownTimer (line 90) | public resetCountdownTimer() {
method isManipulateOverTime (line 98) | isManipulateOverTime() {
method constructor (line 111) | constructor(private readonly project: Project) {
method dispose (line 133) | dispose() {
method mousedown (line 151) | private mousedown(event: MouseEvent) {
method mouseup (line 157) | private mouseup(event: MouseEvent) {
method mousewheel (line 163) | private mousewheel(event: WheelEvent) {
method handleMousedown (line 170) | private handleMousedown(button: number, _x: number, _y: number) {
method handleMouseup (line 182) | private handleMouseup(button: number, x: number, y: number) {
method keydown (line 191) | private keydown(event: KeyboardEvent) {
method keyup (line 225) | private keyup(event: KeyboardEvent) {
method touchstart (line 239) | private touchstart(e: TouchEvent) {
method touchmove (line 257) | private touchmove(e: TouchEvent) {
method touchend (line 288) | private touchend(e: TouchEvent) {
type Controller (line 309) | interface Controller {
method pressingKeysString (line 38) | pressingKeysString(): string {
method resetCountdownTimer (line 90) | public resetCountdownTimer() {
method isManipulateOverTime (line 98) | isManipulateOverTime() {
method constructor (line 111) | constructor(private readonly project: Project) {
method dispose (line 133) | dispose() {
method mousedown (line 151) | private mousedown(event: MouseEvent) {
method mouseup (line 157) | private mouseup(event: MouseEvent) {
method mousewheel (line 163) | private mousewheel(event: WheelEvent) {
method handleMousedown (line 170) | private handleMousedown(button: number, _x: number, _y: number) {
method handleMouseup (line 182) | private handleMouseup(button: number, x: number, y: number) {
method keydown (line 191) | private keydown(event: KeyboardEvent) {
method keyup (line 225) | private keyup(event: KeyboardEvent) {
method touchstart (line 239) | private touchstart(e: TouchEvent) {
method touchmove (line 257) | private touchmove(e: TouchEvent) {
method touchend (line 288) | private touchend(e: TouchEvent) {
FILE: app/src/core/service/controlService/controller/ControllerClass.tsx
class ControllerClass (line 9) | class ControllerClass {
method constructor (line 10) | constructor(protected readonly project: Project) {
method dispose (line 40) | public dispose() {
method mouseMoveOutWindowForcedShutdown (line 152) | public mouseMoveOutWindowForcedShutdown(_outsideLocation: Vector) {
FILE: app/src/core/service/controlService/controller/concrete/ControllerAssociationReshape.tsx
class ControllerAssociationReshapeClass (line 17) | class ControllerAssociationReshapeClass extends ControllerClass {
FILE: app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx
class ControllerCameraClass (line 20) | class ControllerCameraClass extends ControllerClass {
method mouseMoveOutWindowForcedShutdown (line 248) | public mouseMoveOutWindowForcedShutdown(vectorObject: Vector) {
method dealStealthMode (line 333) | private dealStealthMode(event: WheelEvent) {
method mousewheelFunction (line 356) | private mousewheelFunction(event: WheelEvent) {
method moveCameraByMouseMove (line 444) | private moveCameraByMouseMove(x: number, y: number, mouseIndex: number) {
method moveCameraByTouchPadTwoFingerMove (line 451) | private moveCameraByTouchPadTwoFingerMove(event: WheelEvent) {
method zoomCameraByMouseWheel (line 467) | private zoomCameraByMouseWheel(event: WheelEvent) {
method moveYCameraByMouseWheel (line 496) | private moveYCameraByMouseWheel(event: WheelEvent) {
method moveCameraByMouseSideWheel (line 509) | private moveCameraByMouseSideWheel(event: WheelEvent) {
method zoomCameraByMouseSideWheel (line 559) | private zoomCameraByMouseSideWheel(event: WheelEvent) {
method moveYCameraByMouseSideWheel (line 569) | private moveYCameraByMouseSideWheel(event: WheelEvent) {
method moveXCameraByMouseWheel (line 580) | private moveXCameraByMouseWheel(event: WheelEvent) {
method moveXCameraByMouseSideWheel (line 593) | private moveXCameraByMouseSideWheel(event: WheelEvent) {
method isMouseWheel (line 614) | private isMouseWheel(event: WheelEvent): boolean {
method addDistanceNumberAndDetect (line 656) | private addDistanceNumberAndDetect(distance: number): boolean {
FILE: app/src/core/service/controlService/controller/concrete/ControllerCamera/mac.tsx
class ControllerCameraMac (line 7) | class ControllerCameraMac {
method constructor (line 8) | constructor(protected readonly project: Project) {}
method isMouseWheel (line 14) | isMouseWheel(event: WheelEvent) {
method isTouchPadTwoFingerScale (line 63) | isTouchPadTwoFingerScale(event: WheelEvent): boolean {
method handleTwoFingerScale (line 103) | handleTwoFingerScale(event: WheelEvent) {
method moveCameraByTouchPadTwoFingerMove (line 127) | moveCameraByTouchPadTwoFingerMove(event: WheelEvent) {
method handleRectangleSelectByTwoFingerMove (line 146) | private handleRectangleSelectByTwoFingerMove(event: WheelEvent) {
method handleDrageMoveEntityByTwoFingerMove (line 165) | private handleDrageMoveEntityByTwoFingerMove(event: WheelEvent) {
FILE: app/src/core/service/controlService/controller/concrete/ControllerContextMenu.tsx
class ControllerContextMenuClass (line 5) | class ControllerContextMenuClass extends ControllerClass {
FILE: app/src/core/service/controlService/controller/concrete/ControllerCutting.tsx
class ControllerCuttingClass (line 24) | class ControllerCuttingClass extends ControllerClass {
method registerControlKeyEvents (line 57) | private registerControlKeyEvents() {
method unregisterControlKeyEvents (line 65) | private unregisterControlKeyEvents() {
method constructor (line 72) | constructor(protected readonly project: Project) {
method dispose (line 77) | dispose() {
method mouseDownEvent (line 122) | private mouseDownEvent(event: MouseEvent) {
method clearIsolationPoint (line 163) | private clearIsolationPoint() {
method mouseUpFunction (line 189) | public mouseUpFunction(mouseUpWindowLocation: Vector) {
method mouseMoveOutWindowForcedShutdown (line 253) | public mouseMoveOutWindowForcedShutdown(outsideLocation: Vector) {
method updateWarningObjectByCuttingLine (line 270) | private updateWarningObjectByCuttingLine() {
method addEffectByWarningEntity (line 339) | private addEffectByWarningEntity() {
FILE: app/src/core/service/controlService/controller/concrete/ControllerEdgeEdit.tsx
class ControllerEdgeEditClass (line 9) | class ControllerEdgeEditClass extends ControllerClass {
FILE: app/src/core/service/controlService/controller/concrete/ControllerEntityClickSelectAndMove.tsx
class ControllerEntityClickSelectAndMoveClass (line 15) | class ControllerEntityClickSelectAndMoveClass extends ControllerClass {
method mouseMoveOutWindowForcedShutdown (line 223) | public mouseMoveOutWindowForcedShutdown(_outsideLocation: Vector): void {
FILE: app/src/core/service/controlService/controller/concrete/ControllerEntityCreate.tsx
class ControllerEntityCreateClass (line 10) | class ControllerEntityCreateClass extends ControllerClass {
method constructor (line 11) | constructor(protected readonly project: Project) {
method createConnectPoint (line 51) | createConnectPoint(pressLocation: Vector, addToSections: Section[]) {
FILE: app/src/core/service/controlService/controller/concrete/ControllerEntityLayerMoving.tsx
class ControllerLayerMovingClass (line 17) | class ControllerLayerMovingClass extends ControllerClass {
method isEnabled (line 18) | public get isEnabled(): boolean {
FILE: app/src/core/service/controlService/controller/concrete/ControllerEntityResize.tsx
class ControllerEntityResizeClass (line 9) | class ControllerEntityResizeClass extends ControllerClass {
FILE: app/src/core/service/controlService/controller/concrete/ControllerImageScale.tsx
class ControllerImageScaleClass (line 8) | class ControllerImageScaleClass extends ControllerClass {
FILE: app/src/core/service/controlService/controller/concrete/ControllerNodeConnection.tsx
class ControllerNodeConnectionClass (line 25) | class ControllerNodeConnectionClass extends ControllerClass {
method registerControlKeyEvents (line 57) | private registerControlKeyEvents() {
method unregisterControlKeyEvents (line 65) | private unregisterControlKeyEvents() {
method isUsing (line 79) | public get isUsing(): boolean {
method constructor (line 83) | constructor(protected readonly project: Project) {
method dispose (line 88) | dispose() {
method getMouseLocationsPoints (line 99) | public getMouseLocationsPoints(): Vector[] {
method createConnectPointWhenConnect (line 107) | public createConnectPointWhenConnect() {
method onMouseDown (line 158) | private onMouseDown(event: MouseEvent) {
method mouseMove (line 265) | private mouseMove(event: MouseEvent) {
method mouseUp (line 314) | private mouseUp(event: MouseEvent) {
method getConnectDirectionByMouseTrack (line 403) | private getConnectDirectionByMouseTrack(): [Direction | null, Directio...
method clickMultiConnect (line 470) | private clickMultiConnect(releaseWorldLocation: Vector) {
method clear (line 496) | private clear() {
method dragMultiConnect (line 505) | private dragMultiConnect(
method isConnecting (line 644) | private isConnecting() {
method addConnectEffect (line 648) | private addConnectEffect(from: ConnectableEntity, to: ConnectableEntit...
FILE: app/src/core/service/controlService/controller/concrete/ControllerNodeEdit.tsx
class ControllerNodeEditClass (line 16) | class ControllerNodeEditClass extends ControllerClass {
method constructor (line 17) | constructor(protected readonly project: Project) {
FILE: app/src/core/service/controlService/controller/concrete/ControllerPenStrokeControl.tsx
class ControllerPenStrokeControlClass (line 8) | class ControllerPenStrokeControlClass extends ControllerClass {
FILE: app/src/core/service/controlService/controller/concrete/ControllerPenStrokeDrawing.tsx
class ControllerPenStrokeDrawingClass (line 13) | class ControllerPenStrokeDrawingClass extends ControllerClass {
method constructor (line 24) | constructor(protected readonly project: Project) {
method releaseMouseAndClear (line 127) | private releaseMouseAndClear() {
method getCurrentStrokeColor (line 149) | public getCurrentStrokeColor() {
method changeCurrentStrokeColorAlpha (line 157) | public changeCurrentStrokeColorAlpha(dAlpha: number) {
FILE: app/src/core/service/controlService/controller/concrete/ControllerRectangleSelect.tsx
class ControllerRectangleSelectClass (line 6) | class ControllerRectangleSelectClass extends ControllerClass {
method isUsing (line 16) | public get isUsing() {
method shutDown (line 20) | public shutDown() {
method mouseMoveOutWindowForcedShutdown (line 25) | public mouseMoveOutWindowForcedShutdown(mouseLocation: Vector) {
method getSelectMode (line 90) | public getSelectMode(): "contain" | "intersect" {
FILE: app/src/core/service/controlService/controller/concrete/ControllerSectionEdit.tsx
class ControllerSectionEditClass (line 12) | class ControllerSectionEditClass extends ControllerClass {
method constructor (line 13) | constructor(protected readonly project: Project) {
FILE: app/src/core/service/controlService/controller/concrete/utilsControl.tsx
class ControllerUtils (line 38) | class ControllerUtils {
method constructor (line 40) | constructor(private readonly project: Project) {}
method editTextNode (line 46) | editTextNode(clickedNode: TextNode, selectAll = true) {
method editEdgeText (line 136) | editEdgeText(clickedLineEdge: Edge, selectAll = true) {
method editMultiTargetEdgeText (line 175) | editMultiTargetEdgeText(clickedEdge: MultiTargetUndirectedEdge, select...
method editUrlNodeTitle (line 215) | editUrlNodeTitle(clickedUrlNode: UrlNode) {
method editSectionTitle (line 246) | editSectionTitle(section: Section) {
method editNodeDetailsByKeyboard (line 287) | editNodeDetailsByKeyboard() {
method editNodeDetails (line 296) | editNodeDetails(clickedNode: Entity) {
method addTextNodeByLocation (line 305) | async addTextNodeByLocation(location: Vector, selectCurrent: boolean =...
method createConnectPoint (line 315) | createConnectPoint(location: Vector) {
method addTextNodeFromCurrentSelectedNode (line 320) | addTextNodeFromCurrentSelectedNode(direction: Direction, selectCurrent...
method textNodeInEditModeByUUID (line 328) | textNodeInEditModeByUUID(uuid: string) {
method getClickedStageObject (line 345) | getClickedStageObject(clickedLocation: Vector) {
method isClickedResizeRect (line 374) | isClickedResizeRect(clickedLocation: Vector): boolean {
method selectedEntityNormalizing (line 403) | public selectedEntityNormalizing() {
method handleAutoComplete (line 429) | private async handleAutoComplete(
method handleAutoCompleteLogic (line 451) | private handleAutoCompleteLogic(
method handleAutoCompleteReference (line 504) | private async handleAutoCompleteReference(
method finishChangeTextNode (line 620) | public finishChangeTextNode(textNode: TextNode) {
method autoChangeTextNodeToReferenceBlock (line 624) | private async autoChangeTextNodeToReferenceBlock(project: Project, tex...
method syncChangeTextNode (line 652) | private syncChangeTextNode(textNode: TextNode) {
FILE: app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyDirectionController.tsx
class KeyboardOnlyDirectionController (line 8) | class KeyboardOnlyDirectionController extends DirectionKeyUtilsEngine {
method reset (line 9) | protected reset(): void {
method clearSpeedAndAcc (line 13) | public clearSpeedAndAcc(): void {
method init (line 19) | override init(): void {
FILE: app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyEngine.tsx
class KeyboardOnlyEngine (line 13) | class KeyboardOnlyEngine {
method constructor (line 14) | constructor(private readonly project: Project) {
method setOpenning (line 23) | setOpenning(value: boolean) {
method isOpenning (line 26) | isOpenning() {
method dispose (line 30) | public dispose() {
method addSuccessEffect (line 89) | private addSuccessEffect() {
method addFailEffect (line 96) | private addFailEffect() {
FILE: app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyGraphEngine.tsx
class KeyboardOnlyGraphEngine (line 12) | class KeyboardOnlyGraphEngine {
method virtualTargetLocation (line 18) | virtualTargetLocation(): Vector {
method tick (line 22) | tick() {
method constructor (line 26) | constructor(private readonly project: Project) {
method isEnableVirtualCreate (line 32) | isEnableVirtualCreate(): boolean {
method isCreating (line 48) | isCreating(): boolean {
method createStart (line 56) | createStart(): void {
method getPressTabTimeInterval (line 90) | getPressTabTimeInterval(): number {
method createFinished (line 97) | async createFinished() {
method moveVirtualTarget (line 151) | moveVirtualTarget(delta: Vector): void {
method createCancel (line 158) | createCancel(): void {
method isTargetLocationHaveEntity (line 167) | isTargetLocationHaveEntity(): boolean {
FILE: app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyTreeEngine.tsx
class KeyboardOnlyTreeEngine (line 20) | class KeyboardOnlyTreeEngine {
method constructor (line 21) | constructor(private readonly project: Project) {}
method getNodePreDirection (line 29) | public getNodePreDirection(node: ConnectableEntity): "right" | "left" ...
method changePreDirection (line 68) | public changePreDirection(nodes: ConnectableEntity[], direction: "righ...
method addNodeEffectByPreDirection (line 80) | public addNodeEffectByPreDirection(node: ConnectableEntity): void {
method onDeepGenerateNode (line 98) | onDeepGenerateNode(defaultText = "新节点", selectAll = true) {
method onBroadGenerateNode (line 280) | onBroadGenerateNode() {
method adjustTreeNode (line 416) | adjustTreeNode(entity: ConnectableEntity, withEffect = true) {
method onDeleteCurrentNode (line 459) | onDeleteCurrentNode() {
method calculateNewNodeFontScaleLevel (line 469) | private calculateNewNodeFontScaleLevel(
function extractNumberAndReturnNext (line 555) | function extractNumberAndReturnNext(str: string): string {
FILE: app/src/core/service/controlService/keyboardOnlyEngine/newTargetLocationSelector.tsx
method onTabDown (line 19) | onTabDown(selectedNode: ConnectableEntity): Vector {
method onTabUp (line 28) | onTabUp(selectedNode: ConnectableEntity, finalChoiceLocation: Vector): v...
FILE: app/src/core/service/controlService/keyboardOnlyEngine/selectChangeEngine.tsx
class SelectChangeEngine (line 12) | class SelectChangeEngine {
method constructor (line 15) | constructor(private readonly project: Project) {}
method selectUp (line 22) | selectUp(addSelect = false) {
method selectDown (line 42) | selectDown(addSelect = false) {
method selectLeft (line 62) | selectLeft(addSelect = false) {
method selectRight (line 82) | selectRight(addSelect = false) {
method expandSelect (line 103) | expandSelect(isKeepExpand = false, reversed: boolean = false) {
method afterSelect (line 166) | private afterSelect(
method getCurrentSelectedNode (line 190) | private getCurrentSelectedNode(): ConnectableEntity | null {
method addEffect (line 218) | private addEffect(selectedNodeRect: Rectangle, newSelectNodeRect: Rect...
method getMostNearConnectableEntity (line 259) | private getMostNearConnectableEntity(nodes: ConnectableEntity[], locat...
method selectMostNearLocationNode (line 283) | private selectMostNearLocationNode(location: Vector): ConnectableEntit...
method collectTopNodes (line 305) | collectTopNodes(node: ConnectableEntity): ConnectableEntity[] {
method collectBottomNodes (line 332) | collectBottomNodes(node: ConnectableEntity): ConnectableEntity[] {
method collectLeftNodes (line 359) | collectLeftNodes(node: ConnectableEntity): ConnectableEntity[] {
method collectRightNodes (line 386) | collectRightNodes(node: ConnectableEntity): ConnectableEntity[] {
FILE: app/src/core/service/controlService/rectangleSelectEngine/rectangleSelectEngine.tsx
class RectangleSelect (line 17) | class RectangleSelect {
method constructor (line 18) | constructor(private readonly project: Project) {}
method getSelectStartLocation (line 23) | public getSelectStartLocation(): Vector {
method getSelectEndLocation (line 26) | public getSelectEndLocation(): Vector {
method getRectangle (line 35) | getRectangle(): Rectangle | null {
method shutDown (line 38) | public shutDown() {
method startSelecting (line 42) | startSelecting(worldLocation: Vector) {
method moveSelecting (line 78) | moveSelecting(newEndLocation: Vector) {
method endSelecting (line 104) | endSelecting() {
method updateStageObjectByMove (line 122) | private updateStageObjectByMove() {
method isSelectWithEntity (line 213) | private isSelectWithEntity(entity: StageObject) {
method getSelectMode (line 226) | public getSelectMode(): "contain" | "intersect" {
FILE: app/src/core/service/controlService/shortcutKeysEngine/GlobalShortcutManager.tsx
type GlobalShortcut (line 7) | interface GlobalShortcut {
class GlobalShortcutManager (line 14) | class GlobalShortcutManager {
method constructor (line 20) | constructor() {
method initializeShortcuts (line 25) | private initializeShortcuts() {
method init (line 43) | public async init() {
method updateShortcuts (line 60) | public async updateShortcuts() {
method registerShortcut (line 69) | private async registerShortcut(shortcut: GlobalShortcut) {
method handleToggleClickThrough (line 89) | private async handleToggleClickThrough() {
method handleShowWindow (line 107) | private async handleShowWindow() {
method dispose (line 116) | public async dispose() {
method getShortcuts (line 131) | public getShortcuts() {
FILE: app/src/core/service/controlService/shortcutKeysEngine/KeyBinds.tsx
type KeyBindConfig (line 12) | interface KeyBindConfig {
class KeyBinds (line 21) | class KeyBinds {
method constructor (line 24) | constructor(private readonly project: Project) {
method set (line 32) | async set(id: string, config: KeyBindConfig) {
method get (line 47) | async get(id: string): Promise<KeyBindConfig | null> {
method toggleEnabled (line 70) | async toggleEnabled(id: string): Promise<boolean> {
method watch (line 89) | watch(key: string, callback: (value: KeyBindConfig) => void) {
method entries (line 113) | async entries() {
method create (line 135) | async create(
method dispose (line 178) | dispose() {
method resetAllKeyBinds (line 188) | async resetAllKeyBinds() {
class _Bind (line 204) | class _Bind {
method enqueue (line 212) | private enqueue(event: MouseEvent | KeyboardEvent | WheelEvent) {
method check (line 223) | private check() {
method constructor (line 258) | constructor(
method dispose (line 294) | dispose() {
FILE: app/src/core/service/controlService/shortcutKeysEngine/KeyBindsUI.tsx
function enqueue (line 15) | function enqueue(event: MouseEvent | KeyboardEvent | WheelEvent) {
type UIKeyBind (line 23) | interface UIKeyBind {
function registerAllUIKeyBinds (line 40) | async function registerAllUIKeyBinds() {
function registerOneUIKeyBind (line 75) | async function registerOneUIKeyBind(
function changeOneUIKeyBind (line 96) | async function changeOneUIKeyBind(id: string, key: string) {
function toggleEnabled (line 118) | async function toggleEnabled(id: string): Promise<boolean> {
function resetAllKeyBinds (line 144) | async function resetAllKeyBinds() {
function resetAllKeyBindsEnabledState (line 158) | async function resetAllKeyBindsEnabledState() {
function resetAllKeyBindsValues (line 198) | async function resetAllKeyBindsValues() {
function uiStartListen (line 244) | function uiStartListen() {
function uiStopListen (line 251) | function uiStopListen() {
function shouldProcessKeyboardEvent (line 263) | function shouldProcessKeyboardEvent() {
function check (line 271) | function check() {
function onMouseDown (line 300) | function onMouseDown(event: MouseEvent) {
function onKeyDown (line 304) | function onKeyDown(event: KeyboardEvent) {
function onKeyUp (line 315) | function onKeyUp(event: KeyboardEvent) {
function onWheel (line 335) | function onWheel(event: WheelEvent) {
FILE: app/src/core/service/controlService/shortcutKeysEngine/ShortcutKeyFixer.tsx
function fixF11ShortcutInStorage (line 11) | async function fixF11ShortcutInStorage(): Promise<void> {
function checkAndFixShortcutStorage (line 66) | async function checkAndFixShortcutStorage(): Promise<void> {
FILE: app/src/core/service/controlService/shortcutKeysEngine/shortcutKeysRegister.tsx
type KeyBindItem (line 37) | interface KeyBindItem {
class KeyBindsRegistrar (line 1492) | class KeyBindsRegistrar {
method constructor (line 1493) | constructor(private readonly project: Project) {}
method registerAllKeyBinds (line 1499) | async registerAllKeyBinds() {
function getKeyBindTypeById (line 1505) | function getKeyBindTypeById(id: string): "global" | "ui" | "project" {
function isKeyBindHasRelease (line 1514) | function isKeyBindHasRelease(id: string) {
FILE: app/src/core/service/controlService/stageMouseInteractionCore/stageMouseInteractionCore.tsx
class MouseInteraction (line 9) | class MouseInteraction {
method constructor (line 10) | constructor(private readonly project: Project) {}
method hoverEdges (line 29) | get hoverEdges(): Edge[] {
method firstHoverEdge (line 33) | get firstHoverEdge(): Edge | undefined {
method hoverSections (line 37) | get hoverSections(): Section[] {
method hoverConnectPoints (line 41) | get hoverConnectPoints(): ConnectPoint[] {
method firstHoverSection (line 45) | get firstHoverSection(): Section | undefined {
method hoverMultiTargetEdges (line 48) | get hoverMultiTargetEdges(): MultiTargetUndirectedEdge[] {
method firstHoverMultiTargetEdge (line 52) | get firstHoverMultiTargetEdge(): MultiTargetUndirectedEdge | undefined {
method updateByMouseMove (line 61) | public updateByMouseMove(mouseWorldLocation: Vector): void {
FILE: app/src/core/service/dataFileService/AutoSaveBackupService.tsx
class AutoSaveBackupService (line 17) | class AutoSaveBackupService {
method constructor (line 25) | constructor(private readonly project: Project) {
method tick (line 32) | tick() {
method autoSave (line 50) | private async autoSave() {
method autoBackup (line 63) | private async autoBackup() {
method manualBackup (line 123) | public async manualBackup() {
method backupCurrentProject (line 132) | private async backupCurrentProject(backupDir: string) {
method generateBackupFileName (line 155) | private generateBackupFileName(): string {
method getOriginalFileName (line 168) | private getOriginalFileName(): string {
method createBackupFile (line 184) | private async createBackupFile(backupFilePath: string): Promise<void> {
method manageBackupFiles (line 201) | private async manageBackupFiles(backupDir: string): Promise<void> {
FILE: app/src/core/service/dataFileService/RecentFileManager.tsx
type RecentFile (line 13) | type RecentFile = {
function init (line 21) | async function init() {
function addRecentFile (line 30) | async function addRecentFile(file: RecentFile) {
function addRecentFileByUri (line 47) | async function addRecentFileByUri(uri: URI) {
function addRecentFilesByUris (line 54) | async function addRecentFilesByUris(uris: URI[]) {
function removeRecentFileByUri (line 78) | async function removeRecentFileByUri(uri: URI) {
function clearAllRecentFiles (line 96) | async function clearAllRecentFiles() {
function getRecentFiles (line 104) | async function getRecentFiles(): Promise<RecentFile[]> {
function validAndRefreshRecentFiles (line 118) | async function validAndRefreshRecentFiles() {
function sortTimeRecentFiles (line 149) | async function sortTimeRecentFiles() {
function clearRecentFiles (line 163) | async function clearRecentFiles() {
FILE: app/src/core/service/dataFileService/StartFilesManager.tsx
type StartFile (line 8) | type StartFile = {
function init (line 19) | async function init() {
function clearStartFiles (line 24) | async function clearStartFiles() {
function getStartFiles (line 31) | async function getStartFiles(): Promise<StartFile[]> {
function getCurrentStartFile (line 35) | async function getCurrentStartFile(): Promise<string> {
function setCurrentStartFile (line 39) | async function setCurrentStartFile(filePath: string) {
function addStartFile (line 58) | async function addStartFile(filePath: string) {
function removeStartFile (line 74) | async function removeStartFile(filePath: string) {
function validateAndRefreshStartFiles (line 99) | async function validateAndRefreshStartFiles() {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/AutoComputeUtils.tsx
class AutoComputeUtils (line 16) | class AutoComputeUtils {
method constructor (line 17) | constructor(private readonly project: Project) {}
method getParentTextNodes (line 24) | getParentTextNodes(node: TextNode): TextNode[] {
method getParentEntities (line 33) | getParentEntities(node: TextNode): ConnectableEntity[] {
method getChildTextNodes (line 47) | getChildTextNodes(node: TextNode): TextNode[] {
method getNodeOneResult (line 59) | getNodeOneResult(node: TextNode, resultText: string) {
method getSectionOneResult (line 91) | getSectionOneResult(section: Section, resultText: string) {
method getSectionMultiResult (line 115) | getSectionMultiResult(section: Section, resultTextList: string[]) {
method generateMultiResult (line 157) | generateMultiResult(node: TextNode, resultTextList: string[]) {
method stringToNumber (line 201) | stringToNumber(str: string) {
method isNodeConnectedWithLogicNode (line 213) | isNodeConnectedWithLogicNode(node: ConnectableEntity): boolean {
method isNameIsLogicNode (line 233) | isNameIsLogicNode(name: string): boolean {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/functions/compareLogic.tsx
function lessThan (line 13) | function lessThan(numbers: number[]): number[] {
function greaterThan (line 28) | function greaterThan(numbers: number[]): number[] {
function isIncreasing (line 43) | function isIncreasing(numbers: number[]): number[] {
function isDecreasing (line 58) | function isDecreasing(numbers: number[]): number[] {
function isSame (line 72) | function isSame(numbers: number[]): number[] {
function isDistinct (line 86) | function isDistinct(numbers: number[]): number[] {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/functions/mathLogic.tsx
function add (line 9) | function add(numbers: number[]): number[] {
function subtract (line 13) | function subtract(numbers: number[]): number[] {
function multiply (line 28) | function multiply(numbers: number[]): number[] {
function divide (line 32) | function divide(numbers: number[]): number[] {
function modulo (line 46) | function modulo(numbers: number[]): number[] {
function power (line 60) | function power(numbers: number[]): number[] {
function factorial (line 74) | function factorial(numbers: number[]): number[] {
function sqrt (line 78) | function sqrt(numbers: number[]): number[] {
function abs (line 82) | function abs(numbers: number[]): number[] {
function log (line 86) | function log(numbers: number[]): number[] {
function ln (line 97) | function ln(numbers: number[]): number[] {
function exp (line 101) | function exp(numbers: number[]): number[] {
function sin (line 105) | function sin(numbers: number[]): number[] {
function cos (line 109) | function cos(numbers: number[]): number[] {
function tan (line 113) | function tan(numbers: number[]): number[] {
function asin (line 117) | function asin(numbers: number[]): number[] {
function acos (line 121) | function acos(numbers: number[]): number[] {
function atan (line 125) | function atan(numbers: number[]): number[] {
function sinh (line 129) | function sinh(numbers: number[]): number[] {
function cosh (line 133) | function cosh(numbers: number[]): number[] {
function tanh (line 137) | function tanh(numbers: number[]): number[] {
function max (line 140) | function max(numbers: number[]): number[] {
function min (line 143) | function min(numbers: number[]): number[] {
function random (line 148) | function random(_: number[]): number[] {
function randomInt (line 151) | function randomInt(numbers: number[]): number[] {
function randomFloat (line 154) | function randomFloat(numbers: number[]): number[] {
function randomBoolean (line 158) | function randomBoolean(_: number[]): number[] {
function randomPoisson (line 161) | function randomPoisson(numbers: number[]): number[] {
function round (line 164) | function round(numbers: number[]): number[] {
function floor (line 167) | function floor(numbers: number[]): number[] {
function ceil (line 170) | function ceil(numbers: number[]): number[] {
function and (line 174) | function and(numbers: number[]): number[] {
function or (line 177) | function or(numbers: number[]): number[] {
function not (line 180) | function not(numbers: number[]): number[] {
function xor (line 183) | function xor(numbers: number[]): number[] {
function count (line 189) | function count(numbers: number[]): number[] {
function average (line 197) | function average(numbers: number[]): number[] {
function median (line 205) | function median(numbers: number[]): number[] {
function mode (line 217) | function mode(numbers: number[]): number[] {
function variance (line 242) | function variance(numbers: number[]): number[] {
function standardDeviation (line 258) | function standardDeviation(numbers: number[]): number[] {
function _factorial (line 265) | function _factorial(n: number): number {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/functions/nodeLogic.tsx
function setColorByRGB (line 33) | function setColorByRGB(
function setColorByRGBA (line 57) | function setColorByRGBA(
function getLocation (line 88) | function getLocation(
function setLocation (line 102) | function setLocation(
function setLocationByUUID (line 126) | function setLocationByUUID(
function getLocationByUUID (line 157) | function getLocationByUUID(
function getSize (line 175) | function getSize(
function getMouseLocation (line 189) | function getMouseLocation(
function getMouseWorldLocation (line 198) | function getMouseWorldLocation(
function getCameraLocation (line 208) | function getCameraLocation(
function setCameraLocation (line 217) | function setCameraLocation(
function getCameraScale (line 235) | function getCameraScale(
function setCameraScale (line 244) | function setCameraScale(
function isCollision (line 260) | function isCollision(
function getTime (line 275) | function getTime(
function getDateTime (line 284) | function getDateTime(
function addDateTime (line 304) | function addDateTime(
function playSound (line 363) | function playSound(
function getFps (line 382) | function getFps(
function collectNodeNameByRGBA (line 390) | function collectNodeNameByRGBA(
function collectNodeDetailsByRGBA (line 436) | function collectNodeDetailsByRGBA(
function getNodeRGBA (line 477) | function getNodeRGBA(
function getNodeUUID (line 493) | function getNodeUUID(
function createTextNodeOnLocation (line 512) | function createTextNodeOnLocation(
function isHaveEntityOnLocation (line 553) | function isHaveEntityOnLocation(
function replaceGlobalContent (line 581) | function replaceGlobalContent(
function searchContent (line 612) | function searchContent(
function deletePenStrokeByColor (line 643) | function deletePenStrokeByColor(
function delayCopy (line 684) | function delayCopy(
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/functions/programLogic.tsx
function getVarInCore (line 9) | function getVarInCore(project: Project, varName: string): string {
function isHaveVar (line 13) | function isHaveVar(project: Project, varName: string): boolean {
function setVar (line 22) | function setVar(project: Project, args: string[]): string[] {
function getVar (line 42) | function getVar(project: Project, args: string[]): string[] {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/functions/stringLogic.tsx
function upper (line 7) | function upper(strings: string[]): string[] {
function lower (line 11) | function lower(strings: string[]): string[] {
function capitalize (line 15) | function capitalize(strings: string[]): string[] {
function len (line 19) | function len(strings: string[]): string[] {
function copy (line 23) | function copy(strings: string[]): string[] {
function connect (line 27) | function connect(strings: string[]): string[] {
function join (line 38) | function join(strings: string[]): string[] {
function replace (line 44) | function replace(strings: string[]): string[] {
function trim (line 52) | function trim(strings: string[]): string[] {
function slice (line 62) | function slice(strings: string[]): string[] {
function split (line 80) | function split(strings: string[]): string[] {
function length (line 98) | function length(strings: string[]): string[] {
function contains (line 108) | function contains(strings: string[]): string[] {
function startsWith (line 120) | function startsWith(strings: string[]): string[] {
function endsWith (line 133) | function endsWith(strings: string[]): string[] {
function checkRegexMatch (line 152) | function checkRegexMatch(strings: string[]): string[] {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/logicNodeNameEnum.tsx
type LogicNodeNameEnum (line 4) | enum LogicNodeNameEnum {
function getLogicNodeRenderName (line 293) | function getLogicNodeRenderName(name: LogicNodeNameEnum): string {
type LogicNodeSimpleOperatorEnum (line 303) | enum LogicNodeSimpleOperatorEnum {
FILE: app/src/core/service/dataGenerateService/autoComputeEngine/mainTick.tsx
type MathFunctionType (line 18) | type MathFunctionType = (args: number[]) => number[];
type StringFunctionType (line 19) | type StringFunctionType = (args: string[]) => string[];
type OtherFunctionType (line 20) | type OtherFunctionType = (
type VariableFunctionType (line 25) | type VariableFunctionType = (project: Project, args: string[]) => string[];
type StringFunctionMap (line 26) | type StringFunctionMap = Record<string, StringFunctionType>;
type OtherFunctionMap (line 27) | type OtherFunctionMap = Record<string, OtherFunctionType>;
type VariableFunctionMap (line 28) | type VariableFunctionMap = Record<string, VariableFunctionType>;
class AutoCompute (line 31) | class AutoCompute {
method constructor (line 163) | constructor(private readonly project: Project) {}
method tick (line 172) | tick() {
method funcTypeTrans (line 222) | funcTypeTrans(mF: MathFunctionType): StringFunctionType {
method isTextNodeLogic (line 230) | isTextNodeLogic(node: TextNode): boolean {
method isSectionLogic (line 239) | private isSectionLogic(section: Section): boolean {
method sortEntityByLocation (line 253) | private sortEntityByLocation(entities: ConnectableEntity[]): Connectab...
method computeTextNode (line 270) | private computeTextNode(node: TextNode) {
method computeSection (line 317) | private computeSection(section: Section) {
method computeEdge (line 335) | private computeEdge(edge: LineEdge) {
FILE: app/src/core/service/dataGenerateService/crossFileContentQuery.tsx
function getSectionsByFileName (line 22) | async function getSectionsByFileName(fileName: string): Promise<string[]> {
function clearCache (line 72) | function clearCache(fileName?: string): void {
FILE: app/src/core/service/dataGenerateService/dataTransferEngine/dataTransferEngine.tsx
function xmindToString (line 10) | function xmindToString(xmindContentJson: any): string {
type XmindNode (line 39) | interface XmindNode {
FILE: app/src/core/service/dataGenerateService/generateFromFolderEngine/GenerateFromFolderEngine.tsx
class GenerateFromFolder (line 20) | class GenerateFromFolder {
method constructor (line 21) | constructor(private readonly project: Project) {}
method generateFromFolder (line 23) | async generateFromFolder(folderPath: string): Promise<void> {
method generateTreeFromFolder (line 66) | async generateTreeFromFolder(folderPath: string): Promise<void> {
method getColorByPath (line 113) | private getColorByPath(path: string): Color {
type FolderEntry (line 145) | type FolderEntry = {
function readFolderStructure (line 152) | function readFolderStructure(path: string): Promise<FolderEntry> {
function generateKeyboardLayout (line 161) | async function generateKeyboardLayout(project: Project): Promise<void> {
function formatKeyDisplay (line 526) | function formatKeyDisplay(key: string): string {
FILE: app/src/core/service/dataGenerateService/generateScreenshot.tsx
function renderProjectToBlob (line 22) | async function renderProjectToBlob(
function generateSection (line 102) | async function generateSection(
function generateFullView (line 147) | async function generateFullView(fileName: string, maxDimension: number =...
function generateFromActiveProject (line 186) | async function generateFromActiveProject(
FILE: app/src/core/service/dataGenerateService/stageExportEngine/BaseExporter.tsx
method constructor (line 9) | constructor(protected readonly project: Project) {}
method getTreeTypeString (line 17) | protected getTreeTypeString(textNode: TextNode, nodeToStringFunc: (node:...
method getNodeChildrenArray (line 41) | protected getNodeChildrenArray(node: TextNode): ConnectableEntity[] {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/MarkdownExporter.tsx
class MarkdownExporter (line 9) | class MarkdownExporter extends BaseExporter {
method export (line 15) | public export(textNode: TextNode): string {
method getNodeMarkdown (line 25) | private getNodeMarkdown(node: TextNode, level: number): string {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/MermaidExporter.tsx
class MermaidExporter (line 22) | class MermaidExporter {
method constructor (line 23) | constructor(private readonly project: Project) {}
method export (line 30) | public export(entities: Entity[]): string {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/PlainTextExporter.tsx
class PlainTextExporter (line 18) | class PlainTextExporter {
method constructor (line 19) | constructor(private readonly project: Project) {}
method export (line 26) | public export(nodes: Entity[]): string {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/StageExportPng.tsx
type EventMap (line 6) | interface EventMap {
class StageExportPng (line 13) | class StageExportPng {
method constructor (line 14) | constructor(private readonly project: Project) {}
method exportStage_ (line 19) | private async exportStage_(emitter: EventEmitter<EventMap>, signal: Ab...
method exportStage (line 78) | exportStage(signal: AbortSignal, sleepTime: number = 2) {
method generateCanvasNode (line 84) | generateCanvasNode(): HTMLCanvasElement {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/StageExportSvg.tsx
type SvgExportConfig (line 17) | interface SvgExportConfig {
class StageExportSvg (line 27) | class StageExportSvg {
method constructor (line 28) | constructor(private readonly project: Project) {}
method setConfig (line 39) | setConfig(config: SvgExportConfig) {
method dumpNode (line 43) | dumpNode(node: TextNode) {
method dumpSection (line 77) | dumpSection(section: Section) {
method dumpSectionBase (line 104) | dumpSectionBase(section: Section) {
method dumpEdge (line 111) | dumpEdge(edge: LineEdge): React.ReactNode {
method dumpImageNode (line 120) | dumpImageNode(node: ImageNode, svgConfigObject: SvgExportConfig) {
method getEntitiesOuterRectangle (line 188) | private getEntitiesOuterRectangle(entities: Entity[], padding: number)...
method dumpSelected (line 210) | private dumpSelected(): React.ReactNode {
method dumpStage (line 277) | private dumpStage(): React.ReactNode {
method dumpStageToSVGString (line 315) | dumpStageToSVGString(): string {
method dumpSelectedToSVGString (line 323) | dumpSelectedToSVGString(): string {
method exportStageToSVGFile (line 331) | async exportStageToSVGFile(filePath: string): Promise<void> {
method exportSelectedToSVGFile (line 377) | async exportSelectedToSVGFile(filePath: string): Promise<void> {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/TabExporter.tsx
class TabExporter (line 9) | class TabExporter extends BaseExporter {
method export (line 15) | public export(textNode: TextNode): string {
method getTabText (line 25) | private getTabText(node: TextNode, level: number): string {
FILE: app/src/core/service/dataGenerateService/stageExportEngine/stageExportEngine.tsx
class StageExport (line 14) | class StageExport {
method constructor (line 20) | constructor(private readonly project: Project) {
method getPlainTextByEntities (line 40) | public getPlainTextByEntities(nodes: Entity[]) {
method getMarkdownStringByTextNode (line 44) | public getMarkdownStringByTextNode(textNode: TextNode) {
method getTabStringByTextNode (line 48) | public getTabStringByTextNode(textNode: TextNode) {
method getMermaidTextByEntites (line 64) | public getMermaidTextByEntites(entities: Entity[]): string {
FILE: app/src/core/service/dataGenerateService/stageImportEngine/BaseImporter.tsx
method constructor (line 7) | constructor(protected readonly project: Project) {}
FILE: app/src/core/service/dataGenerateService/stageImportEngine/GraphImporter.tsx
class GraphImporter (line 16) | class GraphImporter extends BaseImporter {
method constructor (line 17) | constructor(project: Project) {
method import (line 27) | public import(text: string, diffLocation: Vector = Vector.getZero()): ...
FILE: app/src/core/service/dataGenerateService/stageImportEngine/MarkdownImporter.tsx
class MarkdownImporter (line 17) | class MarkdownImporter extends BaseImporter {
method constructor (line 18) | constructor(project: Project) {
method import (line 28) | public import(markdownText: string, diffLocation: Vector = Vector.getZ...
FILE: app/src/core/service/dataGenerateService/stageImportEngine/MermaidImporter.tsx
type MermaidNodeToken (line 13) | type MermaidNodeToken = {
class MermaidImporter (line 27) | class MermaidImporter extends BaseImporter {
method constructor (line 28) | constructor(project: Project) {
method import (line 42) | public import(text: string, diffLocation: Vector = Vector.getZero()): ...
method normalizeLine (line 280) | private normalizeLine(line: string): string {
method decodeMermaidText (line 287) | private decodeMermaidText(value: string): string {
method sanitizeLabel (line 294) | private sanitizeLabel(raw: string | undefined): string | undefined {
method parseNodeToken (line 310) | private parseNodeToken(token: string): MermaidNodeToken {
FILE: app/src/core/service/dataGenerateService/stageImportEngine/TreeImporter.tsx
class TreeImporter (line 16) | class TreeImporter extends BaseImporter {
method constructor (line 17) | constructor(project: Project) {
method import (line 27) | public import(text: string, indention: number, diffLocation: Vector = ...
method importFromNode (line 84) | public importFromNode(
method getIndentLevel (line 165) | private getIndentLevel(line: string, indention: number): number {
FILE: app/src/core/service/dataGenerateService/stageImportEngine/stageImportEngine.tsx
class StageImport (line 12) | class StageImport {
method constructor (line 18) | constructor(readonly project: Project) {
method addNodeGraphByText (line 34) | public addNodeGraphByText(text: string, diffLocation: Vector = Vector....
method addNodeTreeByText (line 45) | public addNodeTreeByText(text: string, indention: number, diffLocation...
method addNodeTreeByTextFromNode (line 56) | public addNodeTreeByTextFromNode(
method addNodeMermaidByText (line 75) | public addNodeMermaidByText(text: string, diffLocation: Vector = Vecto...
method addNodeByMarkdown (line 91) | public addNodeByMarkdown(markdownText: string, diffLocation: Vector = ...
FILE: app/src/core/service/dataManageService/ComplexityDetector.tsx
type CountResultObject (line 10) | interface CountResultObject {
class ComplexityDetector (line 55) | class ComplexityDetector {
method constructor (line 56) | constructor(private readonly project: Project) {}
method detectorCurrentStage (line 61) | detectorCurrentStage(): CountResultObject {
FILE: app/src/core/service/dataManageService/aiEngine/AIEngine.tsx
class AIEngine (line 8) | class AIEngine {
method updateConfig (line 17) | async updateConfig() {
method chat (line 22) | async chat(messages: OpenAI.ChatCompletionMessageParam[]) {
method getModels (line 36) | async getModels() {
FILE: app/src/core/service/dataManageService/aiEngine/AITools.tsx
function addTool (line 15) | function addTool<A extends z.ZodObject>(
FILE: app/src/core/service/dataManageService/colorSmartTools.tsx
function increaseBrightness (line 6) | function increaseBrightness(project: Project) {
function decreaseBrightness (line 21) | function decreaseBrightness(project: Project) {
function gradientColor (line 36) | function gradientColor(project: Project) {
function changeColorHueUp (line 47) | function changeColorHueUp(project: Project) {
function changeColorHueDown (line 58) | function changeColorHueDown(project: Project) {
function changeColorHueMajorUp (line 71) | function changeColorHueMajorUp(project: Project) {
function changeColorHueMajorDown (line 82) | function changeColorHueMajorDown(project: Project) {
FILE: app/src/core/service/dataManageService/connectNodeSmartTools.tsx
function connectDown (line 16) | function connectDown(project: Project) {
function connectRight (line 31) | function connectRight(project: Project) {
function connectAll (line 46) | function connectAll(project: Project) {
function insertNodeToTree (line 64) | function insertNodeToTree(project: Project) {
function removeNodeFromTree (line 159) | function removeNodeFromTree(project: Project) {
FILE: app/src/core/service/dataManageService/contentSearchEngine/contentSearchEngine.tsx
type SearchScope (line 16) | enum SearchScope {
class ContentSearch (line 32) | class ContentSearch {
method constructor (line 33) | constructor(private readonly project: Project) {}
method getStageObjectText (line 60) | public getStageObjectText(stageObject: StageObject): string {
method getSelectedObjectsBounds (line 84) | private getSelectedObjectsBounds(): Rectangle | null {
method isObjectInBounds (line 112) | private isObjectInBounds(obj: StageObject, bounds: Rectangle): boolean {
method startSearch (line 122) | public startSearch(searchString: string, autoFocus = true): boolean {
method nextSearchResult (line 194) | public nextSearchResult() {
method previousSearchResult (line 219) | public previousSearchResult() {
FILE: app/src/core/service/dataManageService/copyEngine/VirtualClipboard.tsx
function copy (line 10) | function copy(newData: any) {
function paste (line 13) | function paste() {
function clear (line 16) | function clear() {
function hasData (line 19) | function hasData() {
FILE: app/src/core/service/dataManageService/copyEngine/copyEngine.tsx
class CopyEngine (line 31) | class CopyEngine {
method constructor (line 35) | constructor(private readonly project: Project) {
method copy (line 45) | async copy() {
method paste (line 97) | paste() {
method virtualClipboardPaste (line 106) | virtualClipboardPaste() {
method cut (line 245) | async cut() {
method readSystemClipboardAndPaste (line 250) | async readSystemClipboardAndPaste() {
function getRectangleFromSerializedEntities (line 300) | function getRectangleFromSerializedEntities(serializedEntities: Serializ...
FILE: app/src/core/service/dataManageService/copyEngine/copyEngineImage.tsx
class CopyEngineImage (line 15) | class CopyEngineImage {
method constructor (line 16) | constructor(private project: Project) {}
method processClipboardImage (line 18) | public async processClipboardImage() {
method processImageStandard (line 38) | private async processImageStandard() {
method copyEnginePasteImage (line 89) | async copyEnginePasteImage(item: Blob) {
method debugImageData (line 105) | private debugImageData(imageData: any): void {
method fixImageData (line 183) | private fixImageData(data: Uint8ClampedArray): Uint8ClampedArray {
method processImageWindowsCompat (line 258) | private async processImageWindowsCompat() {
method ensureImageDataFormat (line 321) | private ensureImageDataFormat(data: any, width: number, height: number...
method validateCanvasContent (line 347) | private validateCanvasContent(ctx: CanvasRenderingContext2D, width: nu...
method createBlobFromCanvas (line 391) | private async createBlobFromCanvas(canvas: HTMLCanvasElement): Promise...
FILE: app/src/core/service/dataManageService/copyEngine/copyEngineText.tsx
class CopyEngineText (line 20) | class CopyEngineText {
method constructor (line 21) | constructor(private project: Project) {}
method copyEnginePastePlainText (line 23) | async copyEnginePastePlainText(item: string) {
FILE: app/src/core/service/dataManageService/copyEngine/copyEngineUtils.tsx
function getAllStageObjectFromEntities (line 21) | function getAllStageObjectFromEntities(project: Project, entities: Entit...
function collectAttachmentFromStageObjects (line 66) | async function collectAttachmentFromStageObjects(
FILE: app/src/core/service/dataManageService/copyEngine/stringValidTools.tsx
function isSvgString (line 3) | function isSvgString(str: string): boolean {
function isMermaidGraphString (line 39) | function isMermaidGraphString(str: string): boolean {
FILE: app/src/core/service/dataManageService/dragFileIntoStageEngine/dragFileIntoStageEngine.tsx
function handleDrop (line 25) | async function handleDrop(project: Project, pathList: string[]) {
function handleDropFileAbsolutePath (line 56) | async function handleDropFileAbsolutePath(project: Project, pathList: st...
function handleDropFileRelativePath (line 72) | async function handleDropFileRelativePath(project: Project, pathList: st...
function convertToPngBlob (line 95) | async function convertToPngBlob(fileData: Uint8Array, sourceMime: string...
function handleDropImage (line 128) | async function handleDropImage(project: Project, filePath: string, sourc...
function handleDropPng (line 153) | async function handleDropPng(project: Project, filePath: string) {
function handleDropTxt (line 157) | async function handleDropTxt(project: Project, filePath: string) {
function handleDropSvg (line 169) | async function handleDropSvg(project: Project, filePath: string) {
FILE: app/src/core/service/dataManageService/textNodeSmartTools.tsx
function getAnchorRateForTextNode (line 20) | function getAnchorRateForTextNode(project: Project, node: TextNode): Vec...
function ttt (line 27) | function ttt(project: Project) {
function rua (line 44) | function rua(project: Project) {
function collectUpstreamEdges (line 84) | function collectUpstreamEdges(project: Project, nodes: TextNode[]): Map<...
function collectDownstreamEdges (line 107) | function collectDownstreamEdges(project: Project, nodes: TextNode[]): Ma...
function createMergedNode (line 130) | function createMergedNode(project: Project, nodes: TextNode[], userInput...
function processUpstreamEdges (line 154) | function processUpstreamEdges(project: Project, upstreamEdges: Map<strin...
function processDownstreamEdges (line 177) | function processDownstreamEdges(project: Project, downstreamEdges: Map<s...
function mergeEdgeProperties (line 200) | function mergeEdgeProperties(edges: Edge[]): {
function kei (line 230) | function kei(project: Project) {
function keiOneTextNode (line 250) | function keiOneTextNode(project: Project, node: TextNode, userInput: str...
function exchangeTextAndDetails (line 312) | function exchangeTextAndDetails(project: Project) {
function removeFirstCharFromSelectedTextNodes (line 324) | function removeFirstCharFromSelectedTextNodes(project: Project) {
function removeLastCharFromSelectedTextNodes (line 383) | function removeLastCharFromSelectedTextNodes(project: Project) {
function okk (line 446) | function okk(project: Project) {
function err (line 464) | function err(project: Project) {
function changeTextNodeToReferenceBlock (line 487) | async function changeTextNodeToReferenceBlock(project: Project) {
FILE: app/src/core/service/feedbackService/ColorManager.tsx
type ColorData (line 8) | type ColorData = {
function init (line 15) | async function init() {
function getUserEntityFillColors (line 20) | async function getUserEntityFillColors(): Promise<Color[]> {
function colorToColorData (line 30) | function colorToColorData(colors: Color[]): ColorData[] {
function addUserEntityFillColor (line 48) | async function addUserEntityFillColor(color: Color) {
function removeUserEntityFillColor (line 66) | async function removeUserEntityFillColor(color: Color) {
function organizeUserEntityFillColors (line 90) | async function organizeUserEntityFillColors() {
function sortColorsByHue (line 101) | function sortColorsByHue(colors: Color[]): Color[] {
function isGrayscale (line 125) | function isGrayscale(color: Color): boolean {
function getGrayscaleBrightness (line 133) | function getGrayscaleBrightness(color: Color): number {
function getColorHue (line 142) | function getColorHue(color: Color): number {
FILE: app/src/core/service/feedbackService/SoundService.tsx
function getPitchVariationRange (line 14) | function getPitchVariationRange() {
function cuttingLineStart (line 19) | function cuttingLineStart() {
function connectLineStart (line 24) | function connectLineStart() {
function connectFindTarget (line 29) | function connectFindTarget() {
function cuttingLineRelease (line 39) | function cuttingLineRelease() {
function alignAndAttach (line 45) | function alignAndAttach() {
function mouseEnterButton (line 49) | function mouseEnterButton() {
function mouseClickButton (line 52) | function mouseClickButton() {
function mouseClickSwitchButtonOn (line 55) | function mouseClickSwitchButtonOn() {
function mouseClickSwitchButtonOff (line 58) | function mouseClickSwitchButtonOff() {
function packEntityToSectionSoundFile (line 63) | function packEntityToSectionSoundFile() {
function treeGenerateDeepSoundFile (line 70) | function treeGenerateDeepSoundFile() {
function treeGenerateBroadSoundFile (line 77) | function treeGenerateBroadSoundFile() {
function treeAdjustSoundFile (line 84) | function treeAdjustSoundFile() {
function viewAdjustSoundFile (line 91) | function viewAdjustSoundFile() {
function entityJumpSoundFile (line 98) | function entityJumpSoundFile() {
function associationAdjustSoundFile (line 105) | function associationAdjustSoundFile() {
function playSoundByFilePath (line 112) | function playSoundByFilePath(filePath: string) {
function loadAndPlaySound (line 116) | async function loadAndPlaySound(filePath: string) {
function getAudioBufferByFilePath (line 140) | async function getAudioBufferByFilePath(filePath: string) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/CircleChangeRadiusEffect.tsx
class CircleChangeRadiusEffect (line 8) | class CircleChangeRadiusEffect extends Effect {
method constructor (line 9) | constructor(
method radius (line 22) | get radius() {
method fromConnectPointExpand (line 26) | static fromConnectPointExpand(location: Vector, expandRadius: number) {
method fromConnectPointShrink (line 35) | static fromConnectPointShrink(location: Vector, currentRadius: number) {
method render (line 45) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/CircleFlameEffect.tsx
class CircleFlameEffect (line 9) | class CircleFlameEffect extends Effect {
method constructor (line 10) | constructor(
method render (line 22) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EdgeCutEffect.tsx
class EdgeCutEffect (line 9) | class EdgeCutEffect extends Effect {
method constructor (line 10) | constructor(
method default (line 21) | static default(start: Vector, end: Vector, color: Color, width: number) {
method render (line 25) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EntityAlignEffect.tsx
class EntityAlignEffect (line 9) | class EntityAlignEffect extends Effect {
method fromEntity (line 11) | static fromEntity(moveRectangle: Rectangle, targetRectangle: Rectangle...
method constructor (line 14) | constructor(
method render (line 89) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EntityCreateFlashEffect.tsx
class EntityCreateFlashEffect (line 12) | class EntityCreateFlashEffect extends Effect {
method constructor (line 13) | constructor(
method fromRectangle (line 31) | static fromRectangle(rectangle: Rectangle) {
method fromCreateEntity (line 35) | static fromCreateEntity(entity: Entity) {
method render (line 62) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EntityDashTipEffect.tsx
class EntityDashTipEffect (line 8) | class EntityDashTipEffect extends Effect {
method constructor (line 9) | constructor(
method tick (line 74) | override tick(project: Project) {
method render (line 85) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EntityJumpMoveEffect.tsx
class EntityJumpMoveEffect (line 8) | class EntityJumpMoveEffect extends Effect {
method constructor (line 9) | constructor(
method render (line 17) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EntityShakeEffect.tsx
class EntityShakeEffect (line 14) | class EntityShakeEffect extends Effect {
method constructor (line 15) | constructor(
method tick (line 25) | override tick(project: Project) {
method fromEntity (line 33) | static fromEntity(entity: Entity): EntityShakeEffect {
method render (line 37) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/EntityShrinkEffect.tsx
class EntityShrinkEffect (line 11) | class EntityShrinkEffect extends Effect {
method constructor (line 12) | constructor(
method tick (line 22) | override tick(project: Project) {
method fromEntity (line 30) | static fromEntity(entity: Entity): EntityShrinkEffect {
method render (line 38) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/ExplodeDashEffect.tsx
class ExplodeDashEffect (line 10) | class ExplodeDashEffect extends Effect {
method getDashCountPreEntity (line 14) | private getDashCountPreEntity(): number {
method constructor (line 26) | constructor(
method tick (line 48) | override tick(project: Project) {
method render (line 55) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/LineCuttingEffect.tsx
class LineCuttingEffect (line 16) | class LineCuttingEffect extends Effect {
method constructor (line 17) | constructor(
method render (line 28) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/LineEffect.tsx
class LineEffect (line 9) | class LineEffect extends Effect {
method constructor (line 10) | constructor(
method default (line 20) | static default(fromLocation: Vector, toLocation: Vector, width = 1) {
method rectangleEdgeTip (line 31) | static rectangleEdgeTip(fromLocation: Vector, toLocation: Vector) {
method render (line 42) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/MouseTipFeedbackEffect.tsx
type MouseTipType (line 6) | type MouseTipType =
class MouseTipFeedbackEffect (line 21) | class MouseTipFeedbackEffect extends Effect {
method constructor (line 22) | constructor(
method default (line 30) | static default(type: MouseTipType) {
method directionObject (line 39) | static directionObject(direction: Vector) {
method render (line 43) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/NodeMoveShadowEffect.tsx
class NodeMoveShadowEffect (line 10) | class NodeMoveShadowEffect extends Effect {
method constructor (line 14) | constructor(
method tick (line 51) | override tick(project: Project) {
method getSpeedMainDirection (line 62) | getSpeedMainDirection(speed: Vector): "top" | "bottom" | "left" | "rig...
method render (line 82) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/PenStrokeDeletedEffect.tsx
class PenStrokeDeletedEffect (line 6) | class PenStrokeDeletedEffect extends Effect {
method constructor (line 11) | constructor(
method fromPenStroke (line 22) | static fromPenStroke(penStroke: PenStroke): PenStrokeDeletedEffect {
method tick (line 28) | override tick(project: Project) {
method render (line 34) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectangleLittleNoteEffect.tsx
class RectangleLittleNoteEffect (line 12) | class RectangleLittleNoteEffect extends Effect {
method constructor (line 15) | constructor(
method fromUtilsLittleNote (line 25) | static fromUtilsLittleNote(stageObject: StageObject): RectangleLittleN...
method fromUtilsSlowNote (line 33) | static fromUtilsSlowNote(stageObject: StageObject): RectangleLittleNot...
method fromSearchNode (line 41) | static fromSearchNode(stageObject: StageObject): RectangleLittleNoteEf...
method tick (line 50) | override tick(project: Project) {
method render (line 55) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectangleNoteEffect.tsx
class RectangleNoteEffect (line 17) | class RectangleNoteEffect extends Effect {
method constructor (line 18) | constructor(
method fromShiftClickSelect (line 26) | static fromShiftClickSelect(project: Project, rectangle: Rectangle) {
method render (line 34) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectangleNoteReversedEffect.tsx
class RectangleNoteReversedEffect (line 17) | class RectangleNoteReversedEffect extends Effect {
method constructor (line 18) | constructor(
method render (line 26) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectanglePushInEffect.tsx
class RectanglePushInEffect (line 10) | class RectanglePushInEffect extends Effect {
method constructor (line 11) | constructor(
method sectionGoInGoOut (line 47) | static sectionGoInGoOut(entityRectangle: Rectangle, sectionRectangle: ...
method render (line 54) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectangleRenderEffect.tsx
class RectangleRenderEffect (line 10) | class RectangleRenderEffect extends Effect {
method constructor (line 11) | constructor(
method render (line 21) | render(project: Project) {
method fromPreAlign (line 31) | static fromPreAlign(rectangle: Rectangle): RectangleRenderEffect {
method fromShiftClickSelect (line 43) | static fromShiftClickSelect(rectangle: Rectangle): RectangleRenderEffe...
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectangleSlideEffect.tsx
class RectangleSlideEffect (line 12) | class RectangleSlideEffect extends Effect {
method constructor (line 13) | constructor(
method render (line 65) | render(project: Project) {
method horizontalSlide (line 74) | static horizontalSlide(startRect: Rectangle, endRect: Rectangle, color...
method verticalSlide (line 82) | static verticalSlide(startRect: Rectangle, endRect: Rectangle, color?:...
FILE: app/src/core/service/feedbackService/effectEngine/concrete/RectangleSplitTwoPartEffect.tsx
class RectangleSplitTwoPartEffect (line 10) | class RectangleSplitTwoPartEffect extends Effect {
method constructor (line 18) | constructor(
method render (line 131) | render(project: Project) {
method tick (line 136) | override tick(project: Project) {
class SplitedRectangle (line 150) | class SplitedRectangle {
method constructor (line 159) | constructor(
method center (line 170) | get center(): Vector {
method tick (line 179) | public tick() {
method move (line 185) | public move(offset: Vector) {
method moveTo (line 191) | public moveTo(position: Vector) {
method render (line 197) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/TextRaiseEffectLocated.tsx
class TextRaiseEffectLocated (line 9) | class TextRaiseEffectLocated extends Effect {
method constructor (line 10) | constructor(
method render (line 20) | render(project: Project) {
method fromDebugLogicNode (line 34) | static fromDebugLogicNode(n: number, location: Vector): TextRaiseEffec...
FILE: app/src/core/service/feedbackService/effectEngine/concrete/ViewFlashEffect.tsx
class ViewFlashEffect (line 9) | class ViewFlashEffect extends Effect {
method constructor (line 10) | constructor(
method SaveFile (line 17) | static SaveFile() {
method Portal (line 23) | static Portal() {
method render (line 27) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/concrete/ViewOutlineFlashEffect.tsx
class ViewOutlineFlashEffect (line 9) | class ViewOutlineFlashEffect extends Effect {
method constructor (line 10) | constructor(
method normal (line 17) | static normal(color: Color): ViewOutlineFlashEffect {
method short (line 21) | static short(color: Color): ViewOutlineFlashEffect {
method render (line 25) | render(project: Project) {
FILE: app/src/core/service/feedbackService/effectEngine/effectElements/effectParticle.tsx
class EffectParticle (line 7) | class EffectParticle {
method constructor (line 8) | constructor(
method tick (line 16) | tick() {
FILE: app/src/core/service/feedbackService/effectEngine/effectMachine.tsx
class Effects (line 13) | class Effects {
method constructor (line 14) | constructor(private readonly project: Project) {}
method addEffect (line 18) | public addEffect(effect: Effect) {
method effectsCount (line 25) | public get effectsCount() {
method addEffects (line 29) | public addEffects(effects: Effect[]) {
method tick (line 35) | tick() {
FILE: app/src/core/service/feedbackService/effectEngine/effectObject.tsx
method constructor (line 9) | constructor(
method tick (line 20) | tick(project: Project): void {
FILE: app/src/core/service/feedbackService/effectEngine/mathTools/rateFunctions.tsx
function doorFunction (line 7) | function doorFunction(xRate: number): number {
function quadraticDownward (line 16) | function quadraticDownward(xRate: number): number {
FILE: app/src/core/service/feedbackService/stageStyle/StageStyleManager.tsx
class StageStyleManager (line 9) | class StageStyleManager {
method constructor (line 13) | constructor() {
FILE: app/src/core/service/feedbackService/stageStyle/stageStyle.tsx
type EffectColors (line 5) | interface EffectColors {
class StageStyle (line 17) | class StageStyle {
method styleFromTheme (line 53) | static async styleFromTheme(theme: Settings["theme"]) {
FILE: app/src/core/stage/Camera.tsx
class Camera (line 24) | class Camera {
method pageMove (line 82) | pageMove(direction: Direction) {
method bombMove (line 102) | bombMove(targetLocation: Vector, frameCount = 40) {
method tick (line 123) | tick() {
method setAllowScaleFollowMouseLocationTicks (line 234) | setAllowScaleFollowMouseLocationTicks(ticks: number) {
method zoomInByKeyboardPress (line 238) | zoomInByKeyboardPress() {
method zoomOutByKeyboardPress (line 243) | zoomOutByKeyboardPress() {
method addScaleFollowMouseLocationTime (line 248) | public addScaleFollowMouseLocationTime(sec: number) {
method dealCycleSpace (line 258) | private dealCycleSpace() {
method setLocationByOtherLocation (line 270) | private setLocationByOtherLocation(otherWorldLocation: Vector, viewLoc...
method clearMoveCommander (line 281) | clearMoveCommander() {
method stopImmediately (line 289) | stopImmediately() {
method dealCameraScaleInTick (line 302) | private dealCameraScaleInTick() {
method constructor (line 327) | constructor(private readonly project: Project) {}
method reset (line 333) | reset() {
method resetBySelected (line 348) | resetBySelected() {
method resetByRectangle (line 359) | resetByRectangle(viewRectangle: Rectangle) {
method resetScale (line 374) | resetScale() {
method resetLocationToZero (line 379) | resetLocationToZero() {
method saveCameraState (line 387) | saveCameraState() {
method restoreCameraState (line 401) | restoreCameraState() {
FILE: app/src/core/stage/Canvas.tsx
class Canvas (line 8) | class Canvas {
method constructor (line 11) | constructor(
method mount (line 85) | mount(wrapper: HTMLDivElement) {
method dispose (line 95) | dispose() {
FILE: app/src/core/stage/ProjectUpgrader.tsx
function compareVersion (line 22) | function compareVersion(version1: string, version2: string): number {
function upgradeVAnyToVLatest (line 43) | function upgradeVAnyToVLatest(data: Record<string, any>): Record<string,...
function convertV1toV2 (line 63) | function convertV1toV2(data: Record<string, any>): Record<string, any> {
function convertV2toV3 (line 98) | function convertV2toV3(data: Record<string, any>): Record<string, any> {
function convertV3toV4 (line 127) | function convertV3toV4(data: Record<string, any>): Record<string, any> {
function convertV4toV5 (line 141) | function convertV4toV5(data: Record<string, any>): Record<string, any> {
function convertV5toV6 (line 155) | function convertV5toV6(data: Record<string, any>): Record<string, any> {
function convertV6toV7 (line 169) | function convertV6toV7(data: Record<string, any>): Record<string, any> {
function convertV7toV8 (line 183) | function convertV7toV8(data: Record<string, any>): Record<string, any> {
function convertV8toV9 (line 198) | function convertV8toV9(data: Record<string, any>): Record<string, any> {
function convertV9toV10 (line 207) | function convertV9toV10(data: Record<string, any>): Record<string, any> {
function convertV10toV11 (line 217) | function convertV10toV11(data: Record<string, any>): Record<string, any> {
function convertV11toV12 (line 243) | function convertV11toV12(data: Record<string, any>): Record<string, any> {
function convertV12toV13 (line 264) | function convertV12toV13(data: Record<string, any>): Record<string, any> {
function convertV13toV14 (line 288) | function convertV13toV14(data: Record<string, any>): Record<string, any> {
function convertV14toV15 (line 306) | function convertV14toV15(data: Record<string, any>): Record<string, any> {
function convertV15toV16 (line 325) | function convertV15toV16(data: Record<string, any>): Record<string, any> {
function convertV16toV17 (line 344) | function convertV16toV17(data: Record<string, any>): Record<string, any> {
function upgradeNAnyToNLatest (line 364) | function upgradeNAnyToNLatest(data: any[], metadata: any): [any[], Proje...
function convertN1toN2 (line 386) | function convertN1toN2(data: any[], metadata: any): [any[], ProjectMetad...
function convertN2toN3 (line 405) | function convertN2toN3(data: any[], metadata: any): [any[], ProjectMetad...
function convertVAnyToN1 (line 418) | async function convertVAnyToN1(json: Record<string, any>, uri: URI) {
FILE: app/src/core/stage/stageManager/StageHistoryManager.tsx
class HistoryManagerTimeEfficient (line 17) | class HistoryManagerTimeEfficient extends HistoryManagerAbs {
method constructor (line 35) | constructor(private readonly project: Project) {
method recordStep (line 44) | recordStep() {
method estimateMemoryUsage (line 66) | private estimateMemoryUsage(): string {
method undo (line 89) | undo() {
method redo (line 125) | redo() {
method get (line 165) | get(index: number) {
method clearHistory (line 180) | clearHistory() {
class HistorymanagerMemoryEfficient (line 191) | class HistorymanagerMemoryEfficient extends HistoryManagerAbs {
method constructor (line 217) | constructor(private readonly project: Project) {
method recordStep (line 226) | recordStep() {
method undo (line 283) | undo() {
method redo (line 314) | redo() {
method get (line 343) | get(index: number) {
method clearHistory (line 368) | clearHistory() {
class HistoryManager (line 385) | class HistoryManager extends HistoryManagerAbs {
method constructor (line 392) | constructor(project: Project) {
method recordStep (line 410) | public recordStep(): void {
method undo (line 417) | public undo(): void {
method redo (line 424) | public redo(): void {
method get (line 433) | public get(index: number): Record<string, any>[] {
method clearHistory (line 440) | public clearHistory(): void {
method switchMode (line 448) | public switchMode(useTimeEfficient: boolean): void {
FILE: app/src/core/stage/stageManager/StageManager.tsx
type ChildCameraData (line 35) | type ChildCameraData = {
class StageManager (line 56) | class StageManager {
method constructor (line 57) | constructor(private readonly project: Project) {}
method get (line 64) | get(uuid: string) {
method isEmpty (line 68) | isEmpty(): boolean {
method getTextNodes (line 71) | getTextNodes(): TextNode[] {
method getConnectableEntity (line 74) | getConnectableEntity(): ConnectableEntity[] {
method isEntityExists (line 86) | isEntityExists(uuid: string): boolean {
method getSections (line 89) | getSections(): Section[] {
method getImageNodes (line 92) | getImageNodes(): ImageNode[] {
method getConnectPoints (line 95) | getConnectPoints(): ConnectPoint[] {
method getUrlNodes (line 98) | getUrlNodes(): UrlNode[] {
method getPenStrokes (line 104) | getPenStrokes(): PenStroke[] {
method getSvgNodes (line 107) | getSvgNodes(): SvgNode[] {
method getStageObjects (line 111) | getStageObjects(): StageObject[] {
method getEntities (line 119) | getEntities(): Entity[] {
method getEntitiesByUUIDs (line 122) | getEntitiesByUUIDs(uuids: string[]): Entity[] {
method isNoEntity (line 125) | isNoEntity(): boolean {
method delete (line 128) | delete(stageObject: StageObject) {
method getAssociations (line 132) | getAssociations(): Association[] {
method getEdges (line 135) | getEdges(): Edge[] {
method getLineEdges (line 138) | getLineEdges(): LineEdge[] {
method getCrEdges (line 141) | getCrEdges(): CubicCatmullRomSplineEdge[] {
method add (line 145) | add(stageObject: StageObject) {
method updateReferences (line 156) | updateReferences() {
method getTextNodeByUUID (line 207) | getTextNodeByUUID(uuid: string): TextNode | null {
method getConnectableEntityByUUID (line 215) | getConnectableEntityByUUID(uuid: string): ConnectableEntity | null {
method isSectionByUUID (line 223) | isSectionByUUID(uuid: string): boolean {
method getSectionByUUID (line 226) | getSectionByUUID(uuid: string): Section | null {
method getCenter (line 237) | getCenter(): Vector {
method getSize (line 250) | getSize(): Vector {
method getBoundingRectangle (line 262) | getBoundingRectangle(): Rectangle {
method findTextNodeByLocation (line 275) | findTextNodeByLocation(location: Vector): TextNode | null {
method findLineEdgeByLocation (line 289) | findLineEdgeByLocation(location: Vector): LineEdge | null {
method findAssociationByLocation (line 298) | findAssociationByLocation(location: Vector): Association | null {
method findSectionByLocation (line 307) | findSectionByLocation(location: Vector): Section | null {
method findImageNodeByLocation (line 316) | findImageNodeByLocation(location: Vector): ImageNode | null {
method findConnectableEntityByLocation (line 325) | findConnectableEntityByLocation(location: Vector): ConnectableEntity |...
method findEntityByLocation (line 343) | findEntityByLocation(location: Vector): Entity | null {
method findConnectPointByLocation (line 364) | findConnectPointByLocation(location: Vector): ConnectPoint | null {
method isHaveEntitySelected (line 375) | isHaveEntitySelected(): boolean {
method getSelectedEntities (line 388) | getSelectedEntities(): Entity[] {
method getSelectedAssociations (line 393) | getSelectedAssociations(): Association[] {
method getSelectedStageObjects (line 396) | getSelectedStageObjects(): StageObject[] {
method getBoundingBoxOfSelected (line 407) | getBoundingBoxOfSelected(): Rectangle {
method isEntityOnLocation (line 423) | isEntityOnLocation(location: Vector): boolean {
method isAssociationOnLocation (line 437) | isAssociationOnLocation(location: Vector): boolean {
method deleteEntities (line 455) | deleteEntities(deleteNodes: Entity[]) {
method deleteSelectedStageObjects (line 467) | deleteSelectedStageObjects() {
method deleteAssociation (line 502) | deleteAssociation(deleteAssociation: Association): boolean {
method deleteEdge (line 514) | deleteEdge(deleteEdge: Edge): boolean {
method connectEntity (line 528) | connectEntity(fromNode: ConnectableEntity, toNode: ConnectableEntity, ...
method connectMultipleEntities (line 554) | connectMultipleEntities(
method reverseNodeEdges (line 588) | private reverseNodeEdges(connectEntity: ConnectableEntity) {
method reverseSelectedNodeEdge (line 601) | reverseSelectedNodeEdge() {
method reverseSelectedEdges (line 608) | reverseSelectedEdges() {
method generateNodeTreeByText (line 621) | generateNodeTreeByText(text: string, indention: number = 4, location =...
method generateNodeGraphByText (line 626) | generateNodeGraphByText(text: string, location = this.project.camera.l...
method generateNodeMermaidByText (line 635) | generateNodeMermaidByText(text: string, location = this.project.camera...
method generateNodeByMarkdown (line 644) | generateNodeByMarkdown(text: string, location = this.project.camera.lo...
method packEntityToSection (line 650) | async packEntityToSection(addEntities: Entity[]) {
method packEntityToSectionBySelected (line 656) | async packEntityToSectionBySelected() {
method goInSection (line 664) | goInSection(entities: Entity[], section: Section) {
method goOutSection (line 669) | goOutSection(entities: Entity[], section: Section) {
method packSelectedSection (line 674) | packSelectedSection() {
method unpackSelectedSection (line 680) | unpackSelectedSection() {
method sectionSwitchCollapse (line 688) | sectionSwitchCollapse() {
method connectEntityByCrEdge (line 693) | connectEntityByCrEdge(fromNode: ConnectableEntity, toNode: Connectable...
method refreshAllStageObjects (line 700) | refreshAllStageObjects() {
method refreshSelected (line 716) | refreshSelected() {
method changeSelectedEdgeConnectLocation (line 729) | changeSelectedEdgeConnectLocation(direction: Direction | null, isSourc...
method changeEdgesConnectLocation (line 740) | changeEdgesConnectLocation(edges: Edge[], direction: Direction | null,...
method switchLineEdgeToCrEdge (line 763) | switchLineEdgeToCrEdge() {
method switchEdgeToUndirectedEdge (line 780) | switchEdgeToUndirectedEdge() {
method switchUndirectedEdgeToEdge (line 804) | switchUndirectedEdgeToEdge() {
method addSelectedCREdgeControlPoint (line 829) | addSelectedCREdgeControlPoint() {
method addSelectedCREdgeTension (line 836) | addSelectedCREdgeTension() {
method reduceSelectedCREdgeTension (line 844) | reduceSelectedCREdgeTension() {
method setSelectedEdgeLineType (line 855) | setSelectedEdgeLineType(lineType: string) {
method selectAll (line 865) | selectAll() {
method clearSelectAll (line 871) | clearSelectAll() {
FILE: app/src/core/stage/stageManager/basicMethods/GraphMethods.tsx
class GraphMethods (line 7) | class GraphMethods {
method constructor (line 8) | constructor(protected readonly project: Project) {}
method isTree (line 10) | isTree(node: ConnectableEntity): boolean {
method nodeChildrenArray (line 28) | nodeChildrenArray(node: ConnectableEntity): ConnectableEntity[] {
method nodeParentArray (line 42) | nodeParentArray(node: ConnectableEntity): ConnectableEntity[] {
method edgeChildrenArray (line 52) | edgeChildrenArray(node: ConnectableEntity): Edge[] {
method edgeParentArray (line 56) | edgeParentArray(node: ConnectableEntity): Edge[] {
method getReversedEdgeDict (line 64) | private getReversedEdgeDict(): Record<string, string> {
method isCurrentNodeInTreeStructAndNotRoot (line 77) | isCurrentNodeInTreeStructAndNotRoot(node: ConnectableEntity): boolean {
method getRoots (line 93) | getRoots(node: ConnectableEntity): ConnectableEntity[] {
method isConnected (line 115) | isConnected(node: ConnectableEntity, target: ConnectableEntity): boole...
method getSuccessorSet (line 129) | getSuccessorSet(node: ConnectableEntity, isHaveSelf: boolean = true): ...
method getOneStepSuccessorSet (line 162) | getOneStepSuccessorSet(node: ConnectableEntity): ConnectableEntity[] {
method getEdgesBetween (line 172) | getEdgesBetween(node1: ConnectableEntity, node2: ConnectableEntity): E...
method getEdgeFromTwoEntity (line 182) | getEdgeFromTwoEntity(fromNode: ConnectableEntity, toNode: ConnectableE...
method getHyperEdgesByNode (line 196) | getHyperEdgesByNode(node: ConnectableEntity): MultiTargetUndirectedEdg...
method getOutgoingEdges (line 214) | public getOutgoingEdges(node: ConnectableEntity): Edge[] {
method getIncomingEdges (line 229) | public getIncomingEdges(node: ConnectableEntity): Edge[] {
method getNodesConnectedByHyperEdges (line 245) | public getNodesConnectedByHyperEdges(node: ConnectableEntity): Connect...
method nodeChildrenArrayWithinSet (line 266) | private nodeChildrenArrayWithinSet(node: ConnectableEntity, nodeSet: S...
method nodeParentArrayWithinSet (line 270) | private nodeParentArrayWithinSet(node: ConnectableEntity, nodeSet: Set...
method getTreeRootByNodes (line 281) | public getTreeRootByNodes(nodes: ConnectableEntity[]): ConnectableEnti...
method isTreeByNodes (line 290) | public isTreeByNodes(nodes: ConnectableEntity[]): boolean {
method isDAGByNodes (line 323) | public isDAGByNodes(nodes: ConnectableEntity[]): boolean {
FILE: app/src/core/stage/stageManager/basicMethods/PenStrokeMethods.tsx
function selectEntityByPenStroke (line 54) | function selectEntityByPenStroke(project: Project) {
function getTouchingPenStrokes (line 77) | function getTouchingPenStrokes(project: Project, entity: ConnectableEnti...
function getConnectableEntitiesByPenStroke (line 92) | function getConnectableEntitiesByPenStroke(project: Project, penStroke: ...
function isConnectableEntityCollideWithPenStroke (line 102) | function isConnectableEntityCollideWithPenStroke(entity: ConnectableEnti...
FILE: app/src/core/stage/stageManager/basicMethods/SectionMethods.tsx
class SectionMethods (line 10) | class SectionMethods {
method constructor (line 11) | constructor(protected readonly project: Project) {}
method getFatherSections (line 18) | getFatherSections(entity: Entity): Section[] {
method isObjectBeLockedBySection (line 35) | isObjectBeLockedBySection(object: StageObject): boolean {
method getFatherSectionsList (line 72) | getFatherSectionsList(entity: Entity): Section[] {
method getSectionsByInnerLocation (line 98) | getSectionsByInnerLocation(location: Vector): Section[] {
method deeperSections (line 115) | private deeperSections(sections: Section[]): Section[] {
method shallowerSection (line 143) | shallowerSection(sections: Section[]): Section[] {
method shallowerNotSectionEntities (line 166) | shallowerNotSectionEntities(entities: Entity[]): Entity[] {
method isEntityInSection (line 192) | isEntityInSection(entity: Entity, section: Section): boolean {
method isEntityInSection_fake (line 202) | private isEntityInSection_fake(entity: Entity, section: Section): bool...
method _isEntityInSection (line 208) | private _isEntityInSection(entity: Entity, section: Section, deep = 0)...
method isTreePack (line 232) | isTreePack(rootNode: Section) {
method getSectionMaxDeep (line 254) | getSectionMaxDeep(section: Section): number {
method getAllEntitiesInSelectedSectionsOrEntities (line 277) | getAllEntitiesInSelectedSectionsOrEntities(selectedEntities: Entity[])...
method getSortedSectionsByZ (line 296) | getSortedSectionsByZ(sections: Section[]): Section[] {
FILE: app/src/core/stage/stageManager/concreteMethods/LayoutManager.tsx
class LayoutManager (line 10) | class LayoutManager {
method constructor (line 11) | constructor(private readonly project: Project) {}
method alignLeft (line 14) | alignLeft() {
method alignRight (line 24) | alignRight() {
method alignTop (line 37) | alignTop() {
method alignBottom (line 47) | alignBottom() {
method alignCenterHorizontal (line 59) | alignCenterHorizontal() {
method alignCenterVertical (line 77) | alignCenterVertical() {
method alignHorizontalSpaceBetween (line 96) | alignHorizontalSpaceBetween() {
method alignVerticalSpaceBetween (line 116) | alignVerticalSpaceBetween() {
method alignLeftToRightNoSpace (line 138) | alignLeftToRightNoSpace() {
method alignTopToBottomNoSpace (line 156) | alignTopToBottomNoSpace() {
method layoutBySelected (line 171) | layoutBySelected(layoutFunction: (entities: Entity[]) => void, isDeep:...
method adjustSelectedTextNodeWidth (line 200) | adjustSelectedTextNodeWidth(mode: "maxWidth" | "minWidth" | "average") {
method layoutToSquare (line 227) | layoutToSquare(entities: Entity[]) {
method layoutToTightSquare (line 281) | layoutToTightSquare(entities: Entity[]) {
function getOptimalRowsCols (line 309) | function getOptimalRowsCols(n: number): { rows: number; cols: number } {
function sortRectangleGreedy (line 348) | function sortRectangleGreedy(rectangles: Rectangle[], margin = 20): Rect...
function arrangeRectangleInCompactByBranch (line 552) | function arrangeRectangleInCompactByBranch(rectangles: Rectangle[], marg...
FILE: app/src/core/stage/stageManager/concreteMethods/SectionCollisionSolver.tsx
class SectionCollisionSolver (line 16) | class SectionCollisionSolver {
method constructor (line 17) | constructor(private readonly project: Project) {}
method solveOverlaps (line 27) | solveOverlaps(grownSection: Section, visited: Set<string> = new Set())...
method updateAncestorsAfterShift (line 62) | private updateAncestorsAfterShift(entity: Entity, visited: Set<string>...
method getSiblingsSections (line 76) | private getSiblingsSections(section: Section): Section[] {
method computePushDelta (line 105) | private computePushDelta(grownRect: Rectangle, siblingRect: Rectangle)...
method rawShiftEntityTree (line 132) | private rawShiftEntityTree(entity: Entity, delta: Vector): void {
FILE: app/src/core/stage/stageManager/concreteMethods/StageAutoAlignManager.tsx
class AutoAlign (line 16) | class AutoAlign {
method constructor (line 17) | constructor(private readonly project: Project) {}
method alignAllSelectedToGrid (line 22) | alignAllSelectedToGrid() {
method alignAllSelected (line 37) | alignAllSelected() {
method preAlignAllSelected (line 57) | preAlignAllSelected() {
method onEntityMoveAlignToGrid (line 76) | private onEntityMoveAlignToGrid(selectedEntity: Entity) {
method onEntityMoveAlignToGridX (line 81) | private onEntityMoveAlignToGridX(selectedEntity: Entity) {
method onEntityMoveAlignToGridY (line 107) | private onEntityMoveAlignToGridY(selectedEntity: Entity) {
method onEntityMoveAlignToOtherEntity (line 138) | private onEntityMoveAlignToOtherEntity(selectedEntity: Entity, otherEn...
method _addAlignEffect (line 199) | private _addAlignEffect(selectedEntity: Entity, otherEntity: Entity) {
method onEntityMoveAlignToTargetEntityX (line 211) | private onEntityMoveAlignToTargetEntityX(selectedEntity: Entity, other...
method onEntityMoveAlignToTargetEntityY (line 232) | private onEntityMoveAlignToTargetEntityY(selectedEntity: Entity, other...
method calculateDistance (line 254) | private calculateDistance(entityA: Entity, entityB: Entity) {
method autoLayoutSelectedFastTreeMode (line 269) | autoLayoutSelectedFastTreeMode(selectedRootEntity: ConnectableEntity) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageDeleteManager.tsx
type DeleteHandler (line 19) | type DeleteHandler<T extends StageObject> = (object: T) => void;
type Constructor (line 20) | type Constructor<T> = { new (...args: any[]): T };
class DeleteManager (line 26) | class DeleteManager {
method registerHandler (line 29) | private registerHandler<T extends StageObject>(constructor: Constructo...
method constructor (line 33) | constructor(private readonly project: Project) {
method deleteEntities (line 45) | deleteEntities(deleteNodes: Entity[]) {
method findDeleteHandler (line 53) | private findDeleteHandler(object: StageObject) {
method deleteSvgNode (line 60) | private deleteSvgNode(entity: SvgNode) {
method deleteReferenceBlockNode (line 68) | private deleteReferenceBlockNode(entity: ReferenceBlockNode) {
method deletePenStroke (line 76) | private deletePenStroke(penStroke: PenStroke) {
method deleteSection (line 82) | private deleteSection(entity: Section) {
method deleteImageNode (line 100) | private deleteImageNode(entity: ImageNode) {
method deleteUrlNode (line 110) | private deleteUrlNode(entity: UrlNode) {
method deleteConnectPoint (line 118) | private deleteConnectPoint(entity: ConnectPoint) {
method deleteTextNode (line 133) | private deleteTextNode(entity: TextNode) {
method deleteEntityAfterClearAssociation (line 159) | private deleteEntityAfterClearAssociation(entity: ConnectableEntity) {
method deleteEdge (line 186) | deleteEdge(deleteEdge: Edge): boolean {
method deleteMultiTargetUndirectedEdge (line 207) | deleteMultiTargetUndirectedEdge(edge: MultiTargetUndirectedEdge) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageEntityMoveManager.tsx
class EntityMoveManager (line 16) | class EntityMoveManager {
method constructor (line 17) | constructor(private readonly project: Project) {}
method canMoveEntity (line 24) | private canMoveEntity(entity: Entity): boolean {
method moveEntityUtils (line 39) | moveEntityUtils(entity: Entity, delta: Vector, isAutoAdjustSection: bo...
method jumpMoveEntityUtils (line 73) | jumpMoveEntityUtils(entity: Entity, delta: Vector) {
method moveEntityToUtils (line 119) | moveEntityToUtils(entity: Entity, location: Vector) {
method moveSelectedEntities (line 138) | moveSelectedEntities(delta: Vector, isAutoAdjustSection: boolean = tru...
method jumpMoveSelectedConnectableEntities (line 151) | jumpMoveSelectedConnectableEntities(delta: Vector) {
method moveEntitiesWithChildren (line 163) | moveEntitiesWithChildren(delta: Vector) {
method moveWithChildren (line 179) | moveWithChildren(node: ConnectableEntity, delta: Vector) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageManagerUtils.tsx
class StageUtils (line 11) | class StageUtils {
method constructor (line 12) | constructor(private readonly project: Project) {}
method replaceAutoNameWithoutStage (line 19) | replaceAutoNameWithoutStage(template: string): string {
method replaceAutoNameTemplate (line 42) | replaceAutoNameTemplate(currentName: string, targetStageObject: StageO...
method isNameConflictWithTextNodes (line 69) | isNameConflictWithTextNodes(name: string): boolean {
method isNameConflictWithSections (line 83) | isNameConflictWithSections(name: string): boolean {
FILE: app/src/core/stage/stageManager/concreteMethods/StageMultiTargetEdgeMove.tsx
class MultiTargetEdgeMove (line 10) | class MultiTargetEdgeMove {
method constructor (line 11) | constructor(private readonly project: Project) {}
method moveMultiTargetEdge (line 18) | moveMultiTargetEdge(diffLocation: Vector) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageNodeAdder.tsx
class NodeAdder (line 19) | class NodeAdder {
method constructor (line 20) | constructor(private readonly project: Project) {}
method addTextNodeByClick (line 29) | async addTextNodeByClick(
method addTextNodeFromCurrentSelectedNode (line 74) | async addTextNodeFromCurrentSelectedNode(
method getAutoName (line 139) | private async getAutoName(): Promise<string> {
method getAutoColor (line 145) | private getAutoColor(): Color {
method addConnectPoint (line 155) | public addConnectPoint(clickWorldLocation: Vector, addToSections: Sect...
method addNodeGraphByText (line 190) | public addNodeGraphByText(text: string, diffLocation: Vector = Vector....
method addNodeTreeByText (line 197) | public addNodeTreeByText(text: string, indention: number, diffLocation...
method addNodeMermaidByText (line 207) | public addNodeMermaidByText(text: string, diffLocation: Vector = Vecto...
method addNodeByMarkdown (line 217) | public addNodeByMarkdown(markdownText: string, diffLocation: Vector = ...
method getIndentLevel (line 226) | private getIndentLevel(line: string, indention: number): number {
FILE: app/src/core/stage/stageManager/concreteMethods/StageNodeConnector.tsx
class NodeConnector (line 12) | class NodeConnector {
method constructor (line 13) | constructor(private readonly project: Project) {}
method isConnectable (line 20) | private isConnectable(fromNode: ConnectableEntity, toNode: Connectable...
method connectConnectableEntity (line 46) | connectConnectableEntity(
method connectEntityFast (line 68) | connectEntityFast(fromNode: ConnectableEntity, toNode: ConnectableEnti...
method addCrEdge (line 79) | addCrEdge(fromNode: ConnectableEntity, toNode: ConnectableEntity): void {
method reverseEdges (line 91) | reverseEdges(edges: LineEdge[]) {
method changeEdgeTarget (line 109) | private changeEdgeTarget(edge: LineEdge, newTarget: ConnectableEntity) {
method changeEdgeSource (line 123) | private changeEdgeSource(edge: LineEdge, newSource: ConnectableEntity) {
method changeSelectedEdgeTarget (line 135) | changeSelectedEdgeTarget(newTarget: ConnectableEntity) {
method changeSelectedEdgeSource (line 150) | changeSelectedEdgeSource(newSource: ConnectableEntity) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageObjectColorManager.tsx
class StageObjectColorManager (line 9) | class StageObjectColorManager {
method constructor (line 10) | constructor(private readonly project: Project) {}
method setSelectedStageObjectColor (line 12) | setSelectedStageObjectColor(color: Color) {
method darkenNodeColor (line 49) | darkenNodeColor() {
method lightenNodeColor (line 62) | lightenNodeColor() {
FILE: app/src/core/stage/stageManager/concreteMethods/StageObjectSelectCounter.tsx
class StageObjectSelectCounter (line 18) | class StageObjectSelectCounter {
method constructor (line 19) | constructor(private readonly project: Project) {}
method update (line 38) | update() {
FILE: app/src/core/stage/stageManager/concreteMethods/StageReferenceManager.tsx
type parserResult (line 14) | interface parserResult {
class ReferenceManager (line 34) | class ReferenceManager {
method constructor (line 35) | constructor(private readonly project: Project) {}
method referenceBlockTextParser (line 43) | public static referenceBlockTextParser(text: string): parserResult {
method onClickReferenceNumber (line 100) | public onClickReferenceNumber(clickLocation: Vector) {
method buildSectionName2SectionMap (line 115) | private buildSectionName2SectionMap(sectionNames: string[]): Record<st...
method updateOneSectionReferenceInfo (line 131) | public async updateOneSectionReferenceInfo(recentFiles: RecentFileMana...
method updateCurrentProjectReference (line 171) | public async updateCurrentProjectReference() {
method checkReferenceBlockInProject (line 201) | public checkReferenceBlockInProject(project: Project, fileName: string...
method insertRefDataToSourcePrgFile (line 214) | public async insertRefDataToSourcePrgFile(fileName: string, sectionNam...
method jumpToReferenceLocation (line 288) | public async jumpToReferenceLocation(fileName: string, referenceBlockN...
method openSectionReferencePanel (line 318) | private openSectionReferencePanel(section: Section) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageSectionInOutManager.tsx
class SectionInOutManager (line 13) | class SectionInOutManager {
method constructor (line 14) | constructor(private readonly project: Project) {}
method goInSection (line 16) | goInSection(entities: Entity[], section: Section) {
method goInSections (line 37) | goInSections(entities: Entity[], sections: Section[]) {
method goOutSection (line 48) | goOutSection(entities: Entity[], section: Section) {
method entityDropParent (line 55) | private entityDropParent(entity: Entity) {
method sectionDropChild (line 68) | private sectionDropChild(section: Section, entity: Entity) {
method convertSectionToTextNode (line 89) | private convertSectionToTextNode(section: Section) {
FILE: app/src/core/stage/stageManager/concreteMethods/StageSectionPackManager.tsx
class SectionPackManager (line 22) | class SectionPackManager {
method constructor (line 23) | constructor(private readonly project: Project) {}
method packSection (line 26) | packSection(): void {
method modifyHiddenDfs (line 42) | private modifyHiddenDfs(section: Section, isCollapsed: boolean) {
method unpackSection (line 53) | unpackSection(): void {
method switchCollapse (line 64) | switchCollapse(): void {
method textNodeToSection (line 80) | textNodeToSection(): void {
method textNodeTreeToSection (line 93) | textNodeTreeToSection(rootNode: TextNode): void {
method textNodeTreeToSectionNoDeep (line 126) | textNodeTreeToSectionNoDeep(rootNode: TextNode): void {
method targetTextNodeToSection (line 158) | targetTextNodeToSection(
method unpackSelectedSections (line 230) | unpackSelectedSections() {
method unpackSections (line 242) | private unpackSections(entities: Entity[]) {
method packEntityToSection (line 273) | async packEntityToSection(addEntities: Entity[]) {
method createSectionFromSelectionRectangle (line 331) | createSectionFromSelectionRectangle(): void {
method packSelectedEntitiesToSection (line 393) | packSelectedEntitiesToSection(): void {
method getSmartSectionTitle (line 406) | private getSmartSectionTitle(addEntities: Entity[]): string {
FILE: app/src/core/stage/stageManager/concreteMethods/StageTagManager.tsx
class TagManager (line 21) | class TagManager {
method constructor (line 22) | constructor(private readonly project: Project) {}
method reset (line 31) | reset(uuids: string[]) {
method addTag (line 39) | addTag(uuid: string) {
method removeTag (line 44) | removeTag(uuid: string) {
method hasTag (line 57) | hasTag(uuid: string): boolean {
method updateTags (line 64) | updateTags() {
method moveUpTag (line 74) | moveUpTag(uuid: string) {
method moveDownTag (line 83) | moveDownTag(uuid: string) {
method changeTagBySelected (line 97) | changeTagBySelected() {
method refreshTagNamesUI (line 112) | refreshTagNamesUI() {
method moveCameraToTag (line 154) | moveCameraToTag(tagUUID: string) {
FILE: app/src/core/stage/stageManager/concreteMethods/stageNodeRotate.tsx
class StageNodeRotate (line 11) | class StageNodeRotate {
method constructor (line 12) | constructor(private readonly project: Project) {}
method moveEdges (line 20) | moveEdges(lastMoveLocation: Vector, diffLocation: Vector) {
method rotateNodeDfs (line 60) | rotateNodeDfs(
FILE: app/src/core/stage/stageObject/abstract/Association.tsx
method reverse (line 26) | public reverse() {
method target (line 30) | get target(): ConnectableEntity {
method target (line 34) | set target(value: ConnectableEntity) {
method source (line 38) | get source(): ConnectableEntity {
method source (line 41) | set source(value: ConnectableEntity) {
FILE: app/src/core/stage/stageObject/abstract/StageEntity.tsx
method detailsButtonRectangle (line 43) | public detailsButtonRectangle(): Rectangle {
method isMouseInDetailsButton (line 47) | public isMouseInDetailsButton(mouseWorldLocation: Vector): boolean {
method referenceButtonCircle (line 51) | public referenceButtonCircle(): Circle {
method isMouseInReferenceButton (line 55) | public isMouseInReferenceButton(mouseWorldLocation: Vector): boolean {
method updateFatherSectionByMove (line 63) | protected updateFatherSectionByMove() {
method updateOtherEntityLocationByMove (line 76) | protected updateOtherEntityLocationByMove() {
method collideWithOtherEntity (line 92) | protected collideWithOtherEntity(other: Entity) {
FILE: app/src/core/stage/stageObject/abstract/StageObject.tsx
method isSelected (line 26) | public get isSelected(): boolean {
method isSelected (line 30) | public set isSelected(value: boolean) {
FILE: app/src/core/stage/stageObject/abstract/StageObjectInterface.tsx
type ResizeAble (line 8) | interface ResizeAble {
FILE: app/src/core/stage/stageObject/association/CubicCatmullRomSplineEdge.tsx
class CubicCatmullRomSplineEdge (line 19) | class CubicCatmullRomSplineEdge extends Edge {
method getControlPoints (line 28) | public getControlPoints(): Vector[] {
method addControlPoint (line 33) | public addControlPoint() {
method collisionBox (line 47) | get collisionBox(): CollisionBox {
method fromTwoEntity (line 51) | static fromTwoEntity(
method constructor (line 82) | constructor(
method getShape (line 114) | public getShape(): CubicCatmullRomSpline {
method textRectangle (line 124) | get textRectangle(): Rectangle {
method autoUpdateControlPoints (line 129) | autoUpdateControlPoints() {
method getArrowHead (line 148) | getArrowHead(): { location: Vector; direction: Vector } {
method adjustSizeByText (line 159) | adjustSizeByText(): void {}
FILE: app/src/core/stage/stageObject/association/Edge.tsx
method isHiddenBySectionCollapse (line 21) | get isHiddenBySectionCollapse(): boolean {
method isSelected (line 30) | public get isSelected(): boolean {
method isSelected (line 33) | public set isSelected(value: boolean) {
method bodyLine (line 48) | get bodyLine(): Line {
method sourceLocation (line 101) | get sourceLocation(): Vector {
method targetLocation (line 107) | get targetLocation(): Vector {
method getCenterLine (line 123) | static getCenterLine(source: ConnectableEntity, target: ConnectableEntit...
method rename (line 139) | public rename(text: string) {
method isIntersectsWithRectangle (line 149) | public isIntersectsWithRectangle(rectangle: Rectangle): boolean {
method isIntersectsWithLocation (line 158) | public isIntersectsWithLocation(location: Vector): boolean {
method isIntersectsWithLine (line 167) | public isIntersectsWithLine(line: Line): boolean {
method isLeftToRight (line 171) | public isLeftToRight(): boolean {
method isRightToLeft (line 174) | public isRightToLeft(): boolean {
method isTopToBottom (line 178) | public isTopToBottom(): boolean {
method isBottomToTop (line 181) | public isBottomToTop(): boolean {
method isUnknownDirection (line 185) | public isUnknownDirection(): boolean {
FILE: app/src/core/stage/stageObject/association/EdgeCollisionBoxGetter.tsx
function init (line 12) | function init() {
function updateState (line 18) | function updateState(style: Settings["lineStyle"]) {
function getCollisionBox (line 26) | function getCollisionBox(edge: LineEdge): CollisionBox {
function getBezierCollisionBox (line 44) | function getBezierCollisionBox(edge: LineEdge): CollisionBox {
function getStraightCollisionBox (line 96) | function getStraightCollisionBox(edge: LineEdge): CollisionBox {
FILE: app/src/core/stage/stageObject/association/LineEdge.tsx
class LineEdge (line 14) | class LineEdge extends Edge {
method collisionBox (line 25) | get collisionBox(): CollisionBox {
method isShifting (line 33) | get isShifting(): boolean {
method isShifting (line 36) | set isShifting(value: boolean) {
method constructor (line 41) | constructor(
method fromTwoEntity (line 68) | static fromTwoEntity(project: Project, source: ConnectableEntity, targ...
method rename (line 75) | public rename(text: string) {
method textRectangle (line 80) | get textRectangle(): Rectangle {
method shiftingMidPoint (line 90) | get shiftingMidPoint(): Vector {
method adjustSizeByText (line 106) | adjustSizeByText(): void {}
FILE: app/src/core/stage/stageObject/association/MutiTargetUndirectedEdge.tsx
type UndirectedEdgeArrowType (line 18) | type UndirectedEdgeArrowType = "inner" | "outer" | "none";
type MultiTargetUndirectedEdgeRenderType (line 25) | type MultiTargetUndirectedEdgeRenderType = "line" | "convex" | "circle";
class MultiTargetUndirectedEdge (line 35) | class MultiTargetUndirectedEdge extends ConnectableAssociation {
method collisionBox (line 40) | get collisionBox(): CollisionBox {
method rename (line 145) | public rename(text: string) {
method constructor (line 149) | constructor(
method centerLocation (line 191) | public get centerLocation(): Vector {
method textRectangle (line 198) | get textRectangle(): Rectangle {
method createFromSomeEntity (line 204) | static createFromSomeEntity(project: Project, entities: ConnectableEnt...
method isSelected (line 225) | public get isSelected(): boolean {
method isSelected (line 228) | public set isSelected(value: boolean) {
FILE: app/src/core/stage/stageObject/collisionBox/collisionBox.tsx
class CollisionBox (line 8) | class CollisionBox {
method constructor (line 12) | constructor(shapes: Shape[]) {
method updateShapeList (line 20) | updateShapeList(shapes: Shape[]): void {
method isContainsPoint (line 24) | public isContainsPoint(location: Vector): boolean {
method isIntersectsWithRectangle (line 38) | public isIntersectsWithRectangle(rectangle: Rectangle): boolean {
method isContainedByRectangle (line 52) | public isContainedByRectangle(rectangle: Rectangle): boolean {
method isIntersectsWithLine (line 77) | public isIntersectsWithLine(line: Line): boolean {
method getRectangle (line 90) | getRectangle(): Rectangle {
FILE: app/src/core/stage/stageObject/entity/ConnectPoint.tsx
class ConnectPoint (line 14) | class ConnectPoint extends ConnectableEntity {
method geometryCenter (line 20) | get geometryCenter(): Vector {
method radius (line 32) | get radius(): number {
method isSelected (line 44) | public get isSelected() {
method isSelected (line 48) | public set isSelected(value: boolean) {
method constructor (line 72) | constructor(
method move (line 89) | move(delta: Vector): void {
method moveTo (line 96) | moveTo(location: Vector): void {
FILE: app/src/core/stage/stageObject/entity/ImageNode.tsx
class ImageNode (line 25) | class ImageNode extends ConnectableEntity implements ResizeAble {
method isS
Condensed preview — 664 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,334K chars).
[
{
"path": ".cursor/skills/create-keybind/SKILL.md",
"chars": 8261,
"preview": "---\nname: create-keybind\ndescription: 指导如何在 Project Graph 项目中创建新的快捷键。当用户需要添加新的快捷键、修改快捷键绑定或需要了解快捷键系统的实现方式时使用此技能。\n---\n\n# 创"
},
{
"path": ".cursor/skills/create-setting-item/SKILL.md",
"chars": 6004,
"preview": "---\nname: create-setting-item\ndescription: 指导如何在 Project Graph 项目中创建新的设置项。当用户需要添加新的设置项、配置选项或需要了解设置系统的实现方式时使用此技能。\n---\n\n# "
},
{
"path": ".github/FUNDING.yml",
"chars": 940,
"preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 29,
"preview": "#blank_issues_enabled: false\n"
},
{
"path": ".github/ISSUE_TEMPLATE/no-issues.yml",
"chars": 404,
"preview": "name: 不要创建 Issue,请前往 Disscussions!\ndescription: 不要创建issue\nbody:\n - type: checkboxes\n attributes:\n label: 不要创建 I"
},
{
"path": ".github/copilot-instructions.md",
"chars": 2646,
"preview": "## Project Background\n\nGithub Repository: `graphif/project-graph`\n\nProject Graph is a desktop application designed to vi"
},
{
"path": ".github/scripts/enable-sourcemap.mjs",
"chars": 290,
"preview": "import { readFileSync, writeFileSync } from \"fs\";\n\nconst VITE_CONFIG_PATH = \"app/vite.config.ts\";\n\nconst conf = readFile"
},
{
"path": ".github/scripts/generate-changelog.mjs",
"chars": 3164,
"preview": "/* eslint-disable */\nimport { execSync } from \"child_process\";\n\n// 获取最近一次发布的标签\nconst lastRelease = execSync(\n \"git for-"
},
{
"path": ".github/scripts/generate-pkgbuild.mjs",
"chars": 2397,
"preview": "/* eslint-disable */\n\nimport { writeFileSync } from \"fs\";\n\n// 命令行参数:\n// node ./generate-pkgbuild.mjs <pkgname> <pkgver> "
},
{
"path": ".github/scripts/set-tauri-features.mjs",
"chars": 488,
"preview": "/* eslint-disable */\n\nimport { readFileSync, writeFileSync } from \"fs\";\n\nconst features = process.argv[2].split(\",\");\n\nc"
},
{
"path": ".github/scripts/set-version.mjs",
"chars": 329,
"preview": "/* eslint-disable */\n\nimport { readFileSync, writeFileSync } from \"fs\";\n\nconst version = process.argv[2];\n\nconst TAURI_C"
},
{
"path": ".github/workflows/nightly.yml",
"chars": 1194,
"preview": "name: \"Nightly\"\nrun-name: \"Nightly ${{ github.run_number }}\"\n\non:\n schedule:\n - cron: \"0 0 * * *\"\n workflow_dispatc"
},
{
"path": ".github/workflows/publish.yml",
"chars": 13730,
"preview": "name: Publish\n\non:\n workflow_call:\n inputs:\n app_version:\n type: string\n description: The version"
},
{
"path": ".github/workflows/release.yml",
"chars": 1640,
"preview": "name: \"Release\"\nrun-name: \"v${{ inputs.version }}\"\n\non:\n workflow_dispatch:\n inputs:\n version:\n descript"
},
{
"path": ".github/workflows/render-docs-svg.yml",
"chars": 1319,
"preview": "name: Render files in ./docs-pg to SVG\n\non:\n push:\n branches:\n - master\n paths:\n - \"docs-pg/**\"\n workf"
},
{
"path": ".gitignore",
"chars": 377,
"preview": "node_modules\ndist\n.env\n.idea\nstorybook-static\n.swc\n\ndocs/src/.vitepress/dist\ndocs/src/.vitepress/cache\ndocs/src/.vitepre"
},
{
"path": ".husky/pre-commit",
"chars": 17,
"preview": "pnpm lint-staged\n"
},
{
"path": ".lintstagedrc",
"chars": 92,
"preview": "{\n \"*.{ts,tsx}\": [\"eslint --fix\"],\n \"*.{json,md,yaml,yml,ts,tsx}\": [\"prettier --write\"]\n}\n"
},
{
"path": ".prettierignore",
"chars": 206,
"preview": "#app/src-tauri\n\n# 防止翻译总是被格式化\napp/src/locales/*.yml\n\n# 这个基本不会被手动修改\nrouter.ts\nvite-env.d.ts\n\n# prettier不支持mdx3.0\n# *.mdx\n\n"
},
{
"path": ".prettierrc",
"chars": 70,
"preview": "{\n \"plugins\": [\"prettier-plugin-tailwindcss\"],\n \"printWidth\": 120\n}\n"
},
{
"path": ".trae/documents/plan_20251223_165257.md",
"chars": 628,
"preview": "1. **添加upgradeNAnyToNLatest函数**:\n - 在ProjectUpgrader namespace中添加upgradeNAnyToNLatest函数\n\n - 该函数用于升级N版本的prg文件到最新版本\n\n "
},
{
"path": ".trae/documents/plan_20260101_170503.md",
"chars": 627,
"preview": "1. **修改现有的重置按钮**\n\n * 添加确认弹窗,用户确认后才执行重置\n\n * 更新按钮文本,添加提醒信息\n\n * 确保重置时同时重置快捷键值和启用状态\n\n2. **添加两个新的重置按钮**\n\n * 只重置启用状态的按"
},
{
"path": ".trae/documents/为LineEdge添加虚线形态属性.md",
"chars": 553,
"preview": "1. 在LineEdge类中添加线条类型属性:\n - 在LineEdge.tsx中添加`@serializable`装饰的`lineType`属性,使用字符串枚举类型\n\n - 支持的值:'solid'(实线)和'dashed'(虚线"
},
{
"path": ".trae/documents/为RecentFilesWindow添加独立的隐私模式功能.md",
"chars": 458,
"preview": "## 计划概述\n\n为 RecentFilesWindow 页面添加独立的隐私模式开关,当开启时对文件夹名和文件名进行凯撒移位加密显示。\n\n## 实施步骤\n\n1. **添加本地隐私模式状态**\n - 在组件中添加 `isLocalPriv"
},
{
"path": ".trae/documents/优化Tab键和反斜杠键创建节点的字体大小.md",
"chars": 1669,
"preview": "# 优化Tab键和反斜杠键创建节点的字体大小\n\n## 一、问题分析\n\n当前Tab键和反斜杠键创建节点时,新节点的字体大小总是使用默认值(fontScaleLevel = 0),而没有考虑兄弟节点的字体大小。根据需求,新创建的节点应该:\n\n1"
},
{
"path": ".trae/documents/优化嫁接操作与添加反向操作.md",
"chars": 1268,
"preview": "# 优化嫁接操作与添加反向操作\n\n## 1. 优化嫁接操作(insertNodeToTree)\n\n**问题**:当前嫁接操作创建的新连线总是使用默认的中心点连接,没有保持原连线的方向。\n\n**解决方案**:\n\n- 修改 `TextNodeS"
},
{
"path": ".trae/documents/优化文本节点渲染判断逻辑.md",
"chars": 2223,
"preview": "### 问题分析\n\n当前文本节点的文字渲染判断是基于固定的摄像机缩放阈值 `Settings.ignoreTextNodeTextRenderLessThanCameraScale`,当摄像机缩放比例小于这个阈值时,所有文本节点的文字都不会"
},
{
"path": ".trae/documents/修复Ctrl+T快捷键只能触发一个功能的问题.md",
"chars": 840,
"preview": "## 问题分析\n\n1. **现象**:用户按下Ctrl+T快捷键时,只有一个功能被触发,而不是三个绑定了该快捷键的功能都被触发\n2. **原因**:在`KeyBindsUI.tsx`的`check`函数中,当第一个匹配的快捷键执行后,会立即"
},
{
"path": ".trae/documents/修复引用块转换时连线悬空问题.md",
"chars": 947,
"preview": "## 问题分析\n\n当文本节点转换为引用块时,如果该文本节点已经有连线连接,这些连线会变成\"架空\"状态,无法删除。\n\n### 根本原因\n\n1. `changeTextNodeToReferenceBlock` 函数直接调用 `StageMan"
},
{
"path": ".trae/documents/全局快捷键重构方案.md",
"chars": 466,
"preview": "## 计划概述\n\n为 RecentFilesWindow 页面添加独立的隐私模式开关,当开启时对文件夹名和文件名进行凯撒移位加密显示。\n\n## 实施步骤\n\n1. **添加本地隐私模式状态**\n - 在组件中添加 `isLocalPriv"
},
{
"path": ".trae/documents/在快捷键设置页面添加重置所有快捷键按钮.md",
"chars": 552,
"preview": "1. **修改`keybinds.tsx`文件**,在左侧快捷键分类栏底部添加分割线和重置所有快捷键按钮\n - 在`SidebarMenu`组件中,所有分类项之后添加一个分割线\n\n - 分割线使用合适的样式,与现有UI设计保持一致\n"
},
{
"path": ".trae/documents/实现 Section 的 isHidden 属性功能.md",
"chars": 1243,
"preview": "# 实现 Section 的 isHidden 属性功能\n\n## 功能需求\n\n1. **isHidden 属性**:控制 section 内部细节的隐藏状态\n2. **移动限制**:隐藏后内部物体不能移动(包括跳跃式移动、普通拖拽、ctrl"
},
{
"path": ".trae/documents/实现Section框大标题相机缩放阈值控制.md",
"chars": 413,
"preview": "1. **添加设置项**:在`Settings.tsx`的`settingsSchema`中添加新的设置项`sectionBigTitleCameraScaleThreshold`,类型为number,范围0.01到1,步长0.01,默认值"
},
{
"path": ".trae/documents/实现关闭软件前的未保存文件警告.md",
"chars": 851,
"preview": "## 问题分析\n\n当用户点击关闭软件按钮时,系统会遍历所有项目并调用 `closeProject` 函数,对每个未保存的项目弹出保存询问。然而,这种方式存在风险:保存操作是异步的,可能在保存完成前软件就已关闭,导致文件损坏或丢失。\n\n## "
},
{
"path": ".trae/documents/实现图片节点拖拽缩放功能.md",
"chars": 1381,
"preview": "# 实现图片节点拖拽缩放功能\n\n## 1. 实现目标\n\n- 选中图片节点后,在右下角显示缩放控制点\n- 拖拽控制点可等比例缩放图片\n- 保持现有的等比例缩放特性\n- 性能优化:只在选中时显示控制点\n\n## 2. 实现步骤\n\n### 步骤1:"
},
{
"path": ".trae/documents/实现引用块节点的精准连线定位.md",
"chars": 785,
"preview": "### 实现引用块节点的精准连线定位\n\n#### 问题分析\n\n图片节点在连线时有一个特性:当鼠标拖拽连线时,会根据鼠标位置精准定位连线的箭头位置,无论是从图片节点发出还是连接到图片节点,都能精准定位到图片内部的具体位置。现在需要让引用块节点"
},
{
"path": ".trae/documents/实现快捷键开关功能.md",
"chars": 1887,
"preview": "# 实现快捷键开关功能\n\n## 核心需求\n\n- 为每个快捷键添加开关功能,支持自定义默认状态\n- 在设置页面的快捷键页面中显示开关控件\n- 支持开关状态的持久化存储\n- 修改相关代码以支持开关状态的触发控制\n\n## 实现步骤\n\n### 1."
},
{
"path": ".trae/documents/实现搜索范围选项.md",
"chars": 916,
"preview": "# 实现搜索范围选项\n\n## 需求分析\n\n需要在搜索功能中添加两个搜索范围选项:\n\n1. 只搜索所有选中的内容(选中的节点)\n2. 只搜索所有选中内容的外接矩形范围内的所有实体\n\n## 实现思路\n\n1. **修改搜索引擎核心**\n - "
},
{
"path": ".trae/documents/实现背景图片功能和背景管理器.md",
"chars": 690,
"preview": "# 实现背景图片功能和背景管理器\n\n## 1. 为ImageNode添加背景图片属性\n\n- 在ImageNode类中添加`isBackground`属性,用于标记图片是否为背景图片\n- 确保该属性可序列化,以便保存到项目文件中\n\n## 2."
},
{
"path": ".trae/documents/引用块节点精准连线定位功能问题记录.md",
"chars": 1150,
"preview": "# 引用块节点精准连线定位功能问题记录\n\n## 问题现象\n\n在实现引用块节点(ReferenceBlockNode)的精准连线定位功能时,应用在启动时出现窗口无法弹出的问题。\n\n## 问题原因\n\n经过分析,问题是由于循环依赖导致的。当我们在"
},
{
"path": ".trae/documents/文本节点自定义文字大小功能设计方案.md",
"chars": 2057,
"preview": "# 文本节点自定义文字大小功能设计方案\n\n## 一、需求分析\n\n1. **功能需求**:\n - 为文本节点添加自定义文字大小功能\n - 支持通过快捷键(放大/缩小)调整字体大小\n - 采用指数形式缩放(例如:2 → 4 → 8 "
},
{
"path": ".trae/documents/添加大标题遮罩透明度设置.md",
"chars": 664,
"preview": "1. **添加设置项**:在 `Settings.tsx` 中添加一个新的设置项 `sectionBigTitleOpacity`,类型为 `z.number().min(0).max(1).default(0.5)`,用于控制大标题遮罩的"
},
{
"path": ".trae/documents/添加快捷键冲突检测和提醒功能.md",
"chars": 1183,
"preview": "# 快捷键冲突检测和提醒功能实现计划\n\n## 1. 功能需求分析\n\n- 在快捷键设置页面中,为每个快捷键添加冲突检测\n- 当快捷键重复时,显示警告色提示并说明与多少个快捷键冲突\n- 点击提示可以查看具体与哪一个快捷键冲突\n- 没有冲突时不显"
},
{
"path": ".trae/documents/粘贴bug崩溃报告.txt",
"chars": 93443,
"preview": "-------------------------------------\nTranslated Report (Full Report Below)\n-------------------------------------\nProces"
},
{
"path": ".trae/skills/create-keybind/SKILL.md",
"chars": 8191,
"preview": "---\nname: create-keybind\ndescription: 指导如何在 Project Graph 项目中创建新的快捷键。当用户需要添加新的快捷键、修改快捷键绑定或需要了解快捷键系统的实现方式时使用此技能。\n---\n\n# 创"
},
{
"path": ".trae/skills/create-setting-item/SKILL.md",
"chars": 5968,
"preview": "---\nname: create-setting-item\ndescription: 指导如何在 Project Graph 项目中创建新的设置项。当用户需要添加新的设置项、配置选项或需要了解设置系统的实现方式时使用此技能。\n---\n\n# "
},
{
"path": ".vscode/extensions.json",
"chars": 105,
"preview": "{\n \"recommendations\": [\"tauri-apps.tauri-vscode\", \"dbaeumer.vscode-eslint\", \"esbenp.prettier-vscode\"]\n}\n"
},
{
"path": ".vscode/launch.json",
"chars": 1091,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n //"
},
{
"path": ".vscode/settings.json",
"chars": 470,
"preview": "{\n \"i18n-ally.localesPaths\": [\"src/locales\"],\n \"i18n-ally.keystyle\": \"nested\",\n \"eslint.options\": {\n \"overrideConf"
},
{
"path": ".vscode/tasks.json",
"chars": 735,
"preview": "{\n // See https://go.microsoft.com/fwlink/?LinkId=733558\n // for the documentation about the tasks.json format\n \"vers"
},
{
"path": ".zed/settings.json",
"chars": 410,
"preview": "// Folder-specific settings\n//\n// For a full list of overridable settings, and general information on folder-specific se"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 5226,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
},
{
"path": "CONTRIBUTING.md",
"chars": 74,
"preview": "Please refer to [Contributing](https://project-graph.top/docs/contribute)\n"
},
{
"path": "TODO.md",
"chars": 0,
"preview": ""
},
{
"path": "app/.browserslistrc",
"chars": 50,
"preview": "Chrome>=111, Edge>=111, Android>=111, Safari>=16.4"
},
{
"path": "app/LICENSE",
"chars": 35149,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "app/README.md",
"chars": 1326,
"preview": "<div align=\"center\">\n\n<img src=\"app/src/assets/logo-animated.svg\" height=\"150\" alt=\"banner\">\n<h1>Project Graph</h1>\n\n</d"
},
{
"path": "app/components.json",
"chars": 431,
"preview": "{\n \"$schema\": \"https://ui.shadcn.com/schema.json\",\n \"style\": \"new-york\",\n \"rsc\": false,\n \"tsx\": true,\n \"tailwind\": "
},
{
"path": "app/index.html",
"chars": 669,
"preview": "<!doctype html>\n<html>\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, init"
},
{
"path": "app/package.json",
"chars": 5776,
"preview": "{\n \"name\": \"@graphif/project-graph\",\n \"private\": true,\n \"version\": \"0.0.0\",\n \"type\": \"module\",\n \"license\": \"GPL-3.0"
},
{
"path": "app/scripts/sync-locales.ts",
"chars": 890,
"preview": "import * as OpenCC from \"opencc-js\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } fr"
},
{
"path": "app/scripts/tauri_build.js",
"chars": 563,
"preview": "/* eslint-disable */\nimport { spawn } from \"child_process\";\n\n// 从环境变量获取参数并分割成数组\nconst tauriBuildArgs = process.env.TAURI"
},
{
"path": "app/splash.html",
"chars": 542,
"preview": "<!doctype html>\n<html>\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, init"
},
{
"path": "app/src/App.tsx",
"chars": 19355,
"preview": "import MyContextMenuContent from \"@/components/context-menu-content\";\nimport RenderSubWindows from \"@/components/render-"
},
{
"path": "app/src/DropWindowCover.tsx",
"chars": 1613,
"preview": "import { cn } from \"./utils/cn\";\n\n/**\n * 拖拽鼠标进入舞台时,覆盖一个提示区域\n * 用于提示用户在不同位置释放有不同的效果\n */\nexport const DropWindowCover = ({"
},
{
"path": "app/src/ProjectTabs.tsx",
"chars": 6241,
"preview": "import { memo, useCallback, useEffect, useRef, useState } from \"react\";\nimport { Project, ProjectState } from \"./core/Pr"
},
{
"path": "app/src/assets/versions.json",
"chars": 1046,
"preview": "[\n {\n \"version\": \"0.0.0-dev\",\n \"name\": \"筑梦空间\",\n \"name_en\": \"Development Build\"\n },\n {\n \"version\": \"0.0.0-"
},
{
"path": "app/src/cli.tsx",
"chars": 1258,
"preview": "import { writeStdout } from \"@/utils/otherApi\";\nimport { CliMatches } from \"@tauri-apps/plugin-cli\";\n\nexport async funct"
},
{
"path": "app/src/components/context-menu-content.tsx",
"chars": 46403,
"preview": "import { Button } from \"@/components/ui/button\";\nimport {\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuSub,\n C"
},
{
"path": "app/src/components/editor/editor-base-kit.tsx",
"chars": 1633,
"preview": "import { BaseAlignKit } from \"./plugins/align-base-kit\";\nimport { BaseBasicBlocksKit } from \"./plugins/basic-blocks-base"
},
{
"path": "app/src/components/editor/plugins/align-base-kit.tsx",
"chars": 464,
"preview": "import { BaseTextAlignPlugin } from \"@platejs/basic-styles\";\nimport { KEYS } from \"platejs\";\n\nexport const BaseAlignKit "
},
{
"path": "app/src/components/editor/plugins/basic-blocks-base-kit.tsx",
"chars": 1138,
"preview": "import {\n BaseBlockquotePlugin,\n BaseH1Plugin,\n BaseH2Plugin,\n BaseH3Plugin,\n BaseH4Plugin,\n BaseH5Plugin,\n BaseH"
},
{
"path": "app/src/components/editor/plugins/basic-blocks-kit.tsx",
"chars": 1877,
"preview": "\"use client\";\n\nimport {\n BlockquotePlugin,\n H1Plugin,\n H2Plugin,\n H3Plugin,\n H4Plugin,\n H5Plugin,\n H6Plugin,\n Ho"
},
{
"path": "app/src/components/editor/plugins/basic-marks-base-kit.tsx",
"chars": 771,
"preview": "import {\n BaseBoldPlugin,\n BaseCodePlugin,\n BaseHighlightPlugin,\n BaseItalicPlugin,\n BaseKbdPlugin,\n BaseStrikethr"
},
{
"path": "app/src/components/editor/plugins/basic-marks-kit.tsx",
"chars": 1017,
"preview": "\"use client\";\n\nimport {\n BoldPlugin,\n CodePlugin,\n HighlightPlugin,\n ItalicPlugin,\n KbdPlugin,\n StrikethroughPlugi"
},
{
"path": "app/src/components/editor/plugins/callout-base-kit.tsx",
"chars": 219,
"preview": "import { BaseCalloutPlugin } from \"@platejs/callout\";\n\nimport { CalloutElementStatic } from \"@/components/ui/callout-nod"
},
{
"path": "app/src/components/editor/plugins/code-block-base-kit.tsx",
"chars": 595,
"preview": "import { BaseCodeBlockPlugin, BaseCodeLinePlugin, BaseCodeSyntaxPlugin } from \"@platejs/code-block\";\nimport { all, creat"
},
{
"path": "app/src/components/editor/plugins/code-block-kit.tsx",
"chars": 588,
"preview": "\"use client\";\n\nimport { CodeBlockPlugin, CodeLinePlugin, CodeSyntaxPlugin } from \"@platejs/code-block/react\";\nimport { a"
},
{
"path": "app/src/components/editor/plugins/column-base-kit.tsx",
"chars": 329,
"preview": "import { BaseColumnItemPlugin, BaseColumnPlugin } from \"@platejs/layout\";\n\nimport { ColumnElementStatic, ColumnGroupElem"
},
{
"path": "app/src/components/editor/plugins/comment-base-kit.tsx",
"chars": 213,
"preview": "import { BaseCommentPlugin } from \"@platejs/comment\";\n\nimport { CommentLeafStatic } from \"@/components/ui/comment-node-s"
},
{
"path": "app/src/components/editor/plugins/comment-kit.tsx",
"chars": 2148,
"preview": "\"use client\";\n\nimport type { ExtendConfig, Path } from \"platejs\";\n\nimport { type BaseCommentConfig, BaseCommentPlugin, g"
},
{
"path": "app/src/components/editor/plugins/date-base-kit.tsx",
"chars": 198,
"preview": "import { BaseDatePlugin } from \"@platejs/date\";\n\nimport { DateElementStatic } from \"@/components/ui/date-node-static\";\n\n"
},
{
"path": "app/src/components/editor/plugins/discussion-kit.tsx",
"chars": 3423,
"preview": "\"use client\";\n\nimport type { TComment } from \"@/components/ui/comment\";\n\nimport { createPlatePlugin } from \"platejs/reac"
},
{
"path": "app/src/components/editor/plugins/fixed-toolbar-kit.tsx",
"chars": 492,
"preview": "\"use client\";\n\nimport { createPlatePlugin } from \"platejs/react\";\n\nimport { FixedToolbar } from \"@/components/ui/fixed-t"
},
{
"path": "app/src/components/editor/plugins/floating-toolbar-kit.tsx",
"chars": 464,
"preview": "\"use client\";\n\nimport { createPlatePlugin } from \"platejs/react\";\n\nimport { FloatingToolbar } from \"@/components/ui/floa"
},
{
"path": "app/src/components/editor/plugins/font-base-kit.tsx",
"chars": 526,
"preview": "import type { SlatePluginConfig } from \"platejs\";\n\nimport {\n BaseFontBackgroundColorPlugin,\n BaseFontColorPlugin,\n Ba"
},
{
"path": "app/src/components/editor/plugins/font-kit.tsx",
"chars": 624,
"preview": "\"use client\";\n\nimport type { PlatePluginConfig } from \"platejs/react\";\n\nimport {\n FontBackgroundColorPlugin,\n FontColo"
},
{
"path": "app/src/components/editor/plugins/indent-base-kit.tsx",
"chars": 311,
"preview": "import { BaseIndentPlugin } from \"@platejs/indent\";\nimport { KEYS } from \"platejs\";\n\nexport const BaseIndentKit = [\n Ba"
},
{
"path": "app/src/components/editor/plugins/indent-kit.tsx",
"chars": 330,
"preview": "\"use client\";\n\nimport { IndentPlugin } from \"@platejs/indent/react\";\nimport { KEYS } from \"platejs\";\n\nexport const Inden"
},
{
"path": "app/src/components/editor/plugins/line-height-base-kit.tsx",
"chars": 348,
"preview": "import { BaseLineHeightPlugin } from \"@platejs/basic-styles\";\nimport { KEYS } from \"platejs\";\n\nexport const BaseLineHeig"
},
{
"path": "app/src/components/editor/plugins/link-base-kit.tsx",
"chars": 198,
"preview": "import { BaseLinkPlugin } from \"@platejs/link\";\n\nimport { LinkElementStatic } from \"@/components/ui/link-node-static\";\n\n"
},
{
"path": "app/src/components/editor/plugins/link-kit.tsx",
"chars": 349,
"preview": "\"use client\";\n\nimport { LinkPlugin } from \"@platejs/link/react\";\n\nimport { LinkElement } from \"@/components/ui/link-node"
},
{
"path": "app/src/components/editor/plugins/list-base-kit.tsx",
"chars": 486,
"preview": "import { BaseListPlugin } from \"@platejs/list\";\nimport { KEYS } from \"platejs\";\n\nimport { BaseIndentKit } from \"@/compon"
},
{
"path": "app/src/components/editor/plugins/list-kit.tsx",
"chars": 473,
"preview": "\"use client\";\n\nimport { ListPlugin } from \"@platejs/list/react\";\nimport { KEYS } from \"platejs\";\n\nimport { IndentKit } f"
},
{
"path": "app/src/components/editor/plugins/markdown-kit.tsx",
"chars": 388,
"preview": "import { MarkdownPlugin, remarkMdx, remarkMention } from \"@platejs/markdown\";\nimport { KEYS } from \"platejs\";\nimport rem"
},
{
"path": "app/src/components/editor/plugins/math-base-kit.tsx",
"chars": 349,
"preview": "import { BaseEquationPlugin, BaseInlineEquationPlugin } from \"@platejs/math\";\n\nimport { EquationElementStatic, InlineEqu"
},
{
"path": "app/src/components/editor/plugins/math-kit.tsx",
"chars": 319,
"preview": "\"use client\";\n\nimport { EquationPlugin, InlineEquationPlugin } from \"@platejs/math/react\";\n\nimport { EquationElement, In"
},
{
"path": "app/src/components/editor/plugins/media-base-kit.tsx",
"chars": 1011,
"preview": "import { BaseCaptionPlugin } from \"@platejs/caption\";\nimport {\n BaseAudioPlugin,\n BaseFilePlugin,\n BaseImagePlugin,\n "
},
{
"path": "app/src/components/editor/plugins/mention-base-kit.tsx",
"chars": 219,
"preview": "import { BaseMentionPlugin } from \"@platejs/mention\";\n\nimport { MentionElementStatic } from \"@/components/ui/mention-nod"
},
{
"path": "app/src/components/editor/plugins/suggestion-base-kit.tsx",
"chars": 234,
"preview": "import { BaseSuggestionPlugin } from \"@platejs/suggestion\";\n\nimport { SuggestionLeafStatic } from \"@/components/ui/sugge"
},
{
"path": "app/src/components/editor/plugins/suggestion-kit.tsx",
"chars": 2237,
"preview": "\"use client\";\n\nimport { type BaseSuggestionConfig, BaseSuggestionPlugin } from \"@platejs/suggestion\";\nimport { type Exte"
},
{
"path": "app/src/components/editor/plugins/table-base-kit.tsx",
"chars": 557,
"preview": "import { BaseTableCellHeaderPlugin, BaseTableCellPlugin, BaseTablePlugin, BaseTableRowPlugin } from \"@platejs/table\";\n\ni"
},
{
"path": "app/src/components/editor/plugins/table-kit.tsx",
"chars": 478,
"preview": "\"use client\";\n\nimport { TableCellHeaderPlugin, TableCellPlugin, TablePlugin, TableRowPlugin } from \"@platejs/table/react"
},
{
"path": "app/src/components/editor/plugins/toc-base-kit.tsx",
"chars": 191,
"preview": "import { BaseTocPlugin } from \"@platejs/toc\";\n\nimport { TocElementStatic } from \"@/components/ui/toc-node-static\";\n\nexpo"
},
{
"path": "app/src/components/editor/plugins/toggle-base-kit.tsx",
"chars": 212,
"preview": "import { BaseTogglePlugin } from \"@platejs/toggle\";\n\nimport { ToggleElementStatic } from \"@/components/ui/toggle-node-st"
},
{
"path": "app/src/components/editor/transforms.ts",
"chars": 4871,
"preview": "\"use client\";\n\nimport type { PlateEditor } from \"platejs/react\";\n\nimport { insertCallout } from \"@platejs/callout\";\nimpo"
},
{
"path": "app/src/components/key-tooltip.tsx",
"chars": 1516,
"preview": "import { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { activeProjectAtom } from \"@/"
},
{
"path": "app/src/components/render-sub-windows.tsx",
"chars": 8835,
"preview": "import { SimpleCard } from \"@/components/ui/card\";\nimport { SubWindow } from \"@/core/service/SubWindow\";\nimport { cn } f"
},
{
"path": "app/src/components/right-toolbar.tsx",
"chars": 4646,
"preview": "import { Settings, settingsSchema } from \"@/core/service/Settings\";\nimport { QuickSettingsManager } from \"@/core/service"
},
{
"path": "app/src/components/theme-mode-switch.tsx",
"chars": 1698,
"preview": "import { Settings } from \"@/core/service/Settings\";\nimport { Switch } from \"./ui/switch\";\nimport { Sun, Moon } from \"luc"
},
{
"path": "app/src/components/toolbar-content.tsx",
"chars": 4425,
"preview": "import { Settings } from \"@/core/service/Settings\";\nimport { Button } from \"./ui/button\";\nimport { Toolbar } from \"./ui/"
},
{
"path": "app/src/components/ui/ai-node.tsx",
"chars": 1031,
"preview": "\"use client\";\n\nimport { AIChatPlugin } from \"@platejs/ai/react\";\nimport { type PlateElementProps, type PlateTextProps, P"
},
{
"path": "app/src/components/ui/ai-toolbar-button.tsx",
"chars": 527,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport { AIChatPlugin } from \"@platejs/ai/react\";\nimport "
},
{
"path": "app/src/components/ui/alert-dialog.tsx",
"chars": 3737,
"preview": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } fro"
},
{
"path": "app/src/components/ui/alert.tsx",
"chars": 1551,
"preview": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \""
},
{
"path": "app/src/components/ui/align-toolbar-button.tsx",
"chars": 2211,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { Alignment } from \"@platejs/basic-styles\";\nimport type { Dr"
},
{
"path": "app/src/components/ui/avatar.tsx",
"chars": 1007,
"preview": "import * as React from \"react\";\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\";\n\nimport { cn } from \"@/utils/"
},
{
"path": "app/src/components/ui/block-discussion.tsx",
"chars": 10641,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { PlateElementProps, RenderNodeWrapper } from"
},
{
"path": "app/src/components/ui/block-list-static.tsx",
"chars": 2111,
"preview": "import * as React from \"react\";\n\nimport type { RenderStaticNodeWrapper, SlateRenderElementProps, TListElement } from \"pl"
},
{
"path": "app/src/components/ui/block-list.tsx",
"chars": 1763,
"preview": "\"use client\";\n\nimport React from \"react\";\n\nimport type { TListElement } from \"platejs\";\n\nimport { isOrderedList } from \""
},
{
"path": "app/src/components/ui/block-selection.tsx",
"chars": 982,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport { DndPlugin } from \"@platejs/dnd\";\nimport { useBlockSelected } from \"@platejs/selec"
},
{
"path": "app/src/components/ui/block-suggestion.tsx",
"chars": 14233,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TResolvedSuggestion } from \"@platejs/suggestion\";\n\nimport "
},
{
"path": "app/src/components/ui/blockquote-node-static.tsx",
"chars": 244,
"preview": "// @ts-nocheck\nimport { type SlateElementProps, SlateElement } from \"platejs\";\n\nexport function BlockquoteElementStatic("
},
{
"path": "app/src/components/ui/blockquote-node.tsx",
"chars": 244,
"preview": "\"use client\";\n\nimport { type PlateElementProps, PlateElement } from \"platejs/react\";\n\nexport function BlockquoteElement("
},
{
"path": "app/src/components/ui/button.tsx",
"chars": 2070,
"preview": "import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"cla"
},
{
"path": "app/src/components/ui/calendar.tsx",
"chars": 7143,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from \"lucid"
},
{
"path": "app/src/components/ui/callout-node-static.tsx",
"chars": 972,
"preview": "// @ts-nocheck\nimport type { SlateElementProps } from \"platejs\";\n\nimport { SlateElement } from \"platejs\";\n\nimport { cn }"
},
{
"path": "app/src/components/ui/callout-node.tsx",
"chars": 1863,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useCalloutEmojiPicker } from \"@platejs/callout/react\";\nimport {"
},
{
"path": "app/src/components/ui/caption.tsx",
"chars": 1490,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { VariantProps } from \"class-variance-authority\";\n\nimport {\n"
},
{
"path": "app/src/components/ui/card.tsx",
"chars": 2073,
"preview": "import * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nfunction SimpleCard({ className, ...props }: React.Co"
},
{
"path": "app/src/components/ui/checkbox.tsx",
"chars": 1214,
"preview": "import * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { CheckIcon } from"
},
{
"path": "app/src/components/ui/code-block-node-static.tsx",
"chars": 2767,
"preview": "// @ts-nocheck\nimport { type SlateElementProps, type SlateLeafProps, type TCodeBlockElement, SlateElement, SlateLeaf } f"
},
{
"path": "app/src/components/ui/code-block-node.tsx",
"chars": 10559,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { formatCodeBlock, isLangSupported } from \"@platejs/code-block\";\n"
},
{
"path": "app/src/components/ui/code-node-static.tsx",
"chars": 367,
"preview": "// @ts-nocheck\nimport type { SlateLeafProps } from \"platejs\";\n\nimport { SlateLeaf } from \"platejs\";\n\nexport function Cod"
},
{
"path": "app/src/components/ui/code-node.tsx",
"chars": 388,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport type { PlateLeafProps } from \"platejs/react\";\n\nimport { PlateLeaf } from \"platejs/r"
},
{
"path": "app/src/components/ui/collapsible.tsx",
"chars": 1101,
"preview": "import { cn } from \"@/utils/cn\";\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\nfunction Collapsi"
},
{
"path": "app/src/components/ui/column-node-static.tsx",
"chars": 797,
"preview": "// @ts-nocheck\nimport type { SlateElementProps, TColumnElement } from \"platejs\";\n\nimport { SlateElement } from \"platejs\""
},
{
"path": "app/src/components/ui/column-node.tsx",
"chars": 8556,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TColumnElement } from \"platejs\";\nimport typ"
},
{
"path": "app/src/components/ui/command.tsx",
"chars": 4680,
"preview": "\"use client\";\n\nimport * as React from \"react\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { SearchIcon }"
},
{
"path": "app/src/components/ui/comment-node-static.tsx",
"chars": 367,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateLeafProps, TCommentText } from \"platejs\";\n\nimport { S"
},
{
"path": "app/src/components/ui/comment-node.tsx",
"chars": 1574,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TCommentText } from \"platejs\";\nimport type "
},
{
"path": "app/src/components/ui/comment-toolbar-button.tsx",
"chars": 606,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport { MessageSquareTextIcon } from \"lucide-react\";\nimp"
},
{
"path": "app/src/components/ui/comment.tsx",
"chars": 17328,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { CreatePlateEditorOptions } from \"platejs/re"
},
{
"path": "app/src/components/ui/context-menu.tsx",
"chars": 8442,
"preview": "import * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon }"
},
{
"path": "app/src/components/ui/date-node-static.tsx",
"chars": 1479,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TDateElement } from \"platejs\";\n\nimport "
},
{
"path": "app/src/components/ui/date-node.tsx",
"chars": 2370,
"preview": "\"use client\";\n\nimport type { TDateElement } from \"platejs\";\nimport type { PlateElementProps } from \"platejs/react\";\n\nimp"
},
{
"path": "app/src/components/ui/dialog.tsx",
"chars": 11639,
"preview": "import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport * as React from "
},
{
"path": "app/src/components/ui/dropdown-menu.tsx",
"chars": 8159,
"preview": "import * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { CheckIc"
},
{
"path": "app/src/components/ui/editor-static.tsx",
"chars": 1655,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { VariantProps } from \"class-variance-authority\";\n\nimport { "
},
{
"path": "app/src/components/ui/editor.tsx",
"chars": 4046,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { VariantProps } from \"class-variance-authority\";\nimport typ"
},
{
"path": "app/src/components/ui/emoji-node.tsx",
"chars": 1802,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { PlateElementProps } from \"platejs/react\";\n\nimport { EmojiI"
},
{
"path": "app/src/components/ui/emoji-toolbar-button.tsx",
"chars": 16195,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { Emoji } from \"@emoji-mart/data\";\n\nimport { type EmojiCateg"
},
{
"path": "app/src/components/ui/equation-node-static.tsx",
"chars": 2624,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TEquationElement } from \"platejs\";\n\nimp"
},
{
"path": "app/src/components/ui/equation-node.tsx",
"chars": 6159,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\nimport TextareaAutosize, { type TextareaAutosizeProps } fr"
},
{
"path": "app/src/components/ui/equation-toolbar-button.tsx",
"chars": 574,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { insertInlineEquation } from \"@platejs/math\";\nimport { RadicalIc"
},
{
"path": "app/src/components/ui/export-toolbar-button.tsx",
"chars": 5551,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { DropdownMenuProps } from \"@radix-ui/react-dropdown-menu\";\n"
},
{
"path": "app/src/components/ui/field.tsx",
"chars": 9052,
"preview": "import { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Select, SelectC"
},
{
"path": "app/src/components/ui/file-chooser.tsx",
"chars": 886,
"preview": "import { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { isWeb } from \"@"
},
{
"path": "app/src/components/ui/fixed-toolbar-buttons.tsx",
"chars": 4205,
"preview": "\"use client\";\n\nimport {\n ArrowUpToLineIcon,\n BaselineIcon,\n BoldIcon,\n Code2Icon,\n ItalicIcon,\n PaintBucketIcon,\n "
},
{
"path": "app/src/components/ui/fixed-toolbar.tsx",
"chars": 484,
"preview": "\"use client\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { Toolbar } from \"./toolbar\";\n\nexport function FixedToolbar(prop"
},
{
"path": "app/src/components/ui/floating-toolbar-buttons.tsx",
"chars": 2033,
"preview": "\"use client\";\n\nimport { BoldIcon, Code2Icon, ItalicIcon, StrikethroughIcon, UnderlineIcon } from \"lucide-react\";\nimport "
},
{
"path": "app/src/components/ui/floating-toolbar.tsx",
"chars": 1886,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n type FloatingToolbarState,\n flip,\n offset,\n "
},
{
"path": "app/src/components/ui/font-color-toolbar-button.tsx",
"chars": 16134,
"preview": "\"use client\";\n\nimport React from \"react\";\n\nimport type { DropdownMenuItemProps, DropdownMenuProps } from \"@radix-ui/reac"
},
{
"path": "app/src/components/ui/font-size-toolbar-button.tsx",
"chars": 3778,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TElement } from \"platejs\";\n\nimport { toUnit"
},
{
"path": "app/src/components/ui/heading-node-static.tsx",
"chars": 1875,
"preview": "import * as React from \"react\";\n\nimport type { SlateElementProps } from \"platejs\";\n\nimport { type VariantProps, cva } fr"
},
{
"path": "app/src/components/ui/heading-node.tsx",
"chars": 1675,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { PlateElementProps } from \"platejs/react\";\n\n"
},
{
"path": "app/src/components/ui/highlight-node-static.tsx",
"chars": 331,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateLeafProps } from \"platejs\";\n\nimport { SlateLeaf } fro"
},
{
"path": "app/src/components/ui/highlight-node.tsx",
"chars": 352,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { PlateLeafProps } from \"platejs/react\";\n\nimp"
},
{
"path": "app/src/components/ui/history-toolbar-button.tsx",
"chars": 1107,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport { Redo2Icon, Undo2Icon } from \"lucide-react\";\nimpo"
},
{
"path": "app/src/components/ui/hr-node-static.tsx",
"chars": 490,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps } from \"platejs\";\n\nimport { SlateElement"
},
{
"path": "app/src/components/ui/hr-node.tsx",
"chars": 793,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { PlateElementProps } from \"platejs/react\";\n\n"
},
{
"path": "app/src/components/ui/import-toolbar-button.tsx",
"chars": 2590,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { DropdownMenuProps } from \"@radix-ui/react-dropdown-menu\";\n"
},
{
"path": "app/src/components/ui/indent-toolbar-button.tsx",
"chars": 763,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useIndentButton, useOutdentButton } from \"@platejs/indent/react"
},
{
"path": "app/src/components/ui/inline-combobox.tsx",
"chars": 8958,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { Point, TElement } from \"platejs\";\n\nimport {"
},
{
"path": "app/src/components/ui/input.tsx",
"chars": 971,
"preview": "import * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nfunction Input({ className, type, ...props }: React.C"
},
{
"path": "app/src/components/ui/insert-toolbar-button.tsx",
"chars": 5253,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { DropdownMenuProps } from \"@radix-ui/react-dropdown-menu\";\n"
},
{
"path": "app/src/components/ui/kbd-node-static.tsx",
"chars": 803,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateLeafProps } from \"platejs\";\n\nimport { SlateLeaf } fro"
},
{
"path": "app/src/components/ui/kbd-node.tsx",
"chars": 824,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { PlateLeafProps } from \"platejs/react\";\n\nimp"
},
{
"path": "app/src/components/ui/key-bind.tsx",
"chars": 4818,
"preview": "import { Button } from \"@/components/ui/button\";\nimport { formatEmacsKey, parseEmacsKey } from \"@/utils/emacs\";\nimport {"
},
{
"path": "app/src/components/ui/line-height-toolbar-button.tsx",
"chars": 2119,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { DropdownMenuProps } from \"@radix-ui/react-dropdown-menu\";\n"
},
{
"path": "app/src/components/ui/link-node-static.tsx",
"chars": 604,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TLinkElement } from \"platejs\";\n\nimport "
},
{
"path": "app/src/components/ui/link-node.tsx",
"chars": 728,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TLinkElement } from \"platejs\";\nimport type "
},
{
"path": "app/src/components/ui/link-toolbar-button.tsx",
"chars": 546,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useLinkToolbarButton, useLinkToolbarButtonState } from \"@platej"
},
{
"path": "app/src/components/ui/link-toolbar.tsx",
"chars": 5005,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TLinkElement } from \"platejs\";\n\nimport { ty"
},
{
"path": "app/src/components/ui/list-toolbar-button.tsx",
"chars": 5887,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { ListStyleType, someList, toggleList } from \"@platejs/list\";\nimp"
},
{
"path": "app/src/components/ui/mark-toolbar-button.tsx",
"chars": 531,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useMarkToolbarButton, useMarkToolbarButtonState } from \"platejs"
},
{
"path": "app/src/components/ui/markdown.tsx",
"chars": 916,
"preview": "import \"@/css/markdown.css\";\nimport { cn } from \"@/utils/cn\";\nimport { useEffect, useState } from \"react\";\nimport produc"
},
{
"path": "app/src/components/ui/media-audio-node-static.tsx",
"chars": 535,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TAudioElement } from \"platejs\";\n\nimport"
},
{
"path": "app/src/components/ui/media-audio-node.tsx",
"chars": 1075,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TAudioElement } from \"platejs\";\nimport type"
},
{
"path": "app/src/components/ui/media-file-node-static.tsx",
"chars": 860,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TFileElement } from \"platejs\";\n\nimport "
},
{
"path": "app/src/components/ui/media-file-node.tsx",
"chars": 1352,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TFileElement } from \"platejs\";\nimport type "
},
{
"path": "app/src/components/ui/media-image-node-static.tsx",
"chars": 1057,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TCaptionProps, TImageElement, TResizabl"
},
{
"path": "app/src/components/ui/media-image-node.tsx",
"chars": 2438,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TImageElement } from \"platejs\";\nimport type"
},
{
"path": "app/src/components/ui/media-toolbar-button.tsx",
"chars": 5936,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { DropdownMenuProps } from \"@radix-ui/react-d"
},
{
"path": "app/src/components/ui/media-toolbar.tsx",
"chars": 3161,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\n\nimport type { WithRequiredKey } from \"platejs\";\n\nimport {"
},
{
"path": "app/src/components/ui/media-video-node-static.tsx",
"chars": 831,
"preview": "// @ts-nocheck\nimport * as React from \"react\";\n\nimport type { SlateElementProps, TCaptionElement, TResizableProps, TVide"
},
{
"path": "app/src/components/ui/media-video-node.tsx",
"chars": 5215,
"preview": "// @ts-nocheck\n\"use client\";\n\nimport * as React from \"react\";\nimport LiteYouTubeEmbed from \"react-lite-youtube-embed\";\ni"
},
{
"path": "app/src/components/ui/mention-node-static.tsx",
"chars": 972,
"preview": "import * as React from \"react\";\n\nimport type { SlateElementProps, TMentionElement } from \"platejs\";\n\nimport { KEYS, Slat"
},
{
"path": "app/src/components/ui/mention-node.tsx",
"chars": 5136,
"preview": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { TComboboxInputElement, TMentionElement } from \"platejs\";\ni"
},
{
"path": "app/src/components/ui/menubar.tsx",
"chars": 9409,
"preview": "import * as MenubarPrimitive from \"@radix-ui/react-menubar\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lu"
}
]
// ... and 464 more files (download for full content)
About this extraction
This page contains the full source code of the graphif/project-graph GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 664 files (3.0 MB), approximately 819.7k tokens, and a symbol index with 2583 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.