菜单

编辑器系统

相关源文件

编辑器系统是 AFFiNE 中负责文档编辑的核心组件。通过集成 AFFiNE 底层的文档编辑框架 BlockSuite,它提供了文本编辑(页面模式)和画布编辑(无边模式)两种体验。本页将详细介绍编辑器系统的架构、组件和关键功能。

有关编辑器系统与其他 AFFiNE 系统之间关系的更多信息,请参阅 前端架构

架构概述

编辑器系统由多个关键组件组成,它们协同工作以提供文档编辑功能。

来源

核心组件

编辑器实体 (Editor Entity)

编辑器实体是管理编辑器实例状态和行为的主要类。它定义在 modules/editor/entities/editor.ts 中,并包含:

主要属性

  • mode$:一个 LiveData 流,表示当前的编辑模式(页面模式或无边模式)。
  • selector$:一个 LiveData 流,表示编辑器中的当前选区。
  • doc:正在编辑的文档。
  • editorContainer$:一个 LiveData 流,持有 AffineEditorContainer 实例。
  • isPresenting$:一个 LiveData 流,指示编辑器是否处于演示模式。

关键方法

  • setMode(mode):设置当前的编辑模式。
  • toggleMode():在页面模式和无边模式之间切换。
  • setSelector(selector):设置当前的选区。
  • bindEditorContainer(container, docTitle, scrollViewport):将 BlockSuite 编辑器容器绑定到编辑器实体。
  • bindWorkbenchView(view):将编辑器绑定到工作台视图,启用视图相关功能。

来源

编辑器服务 (EditorService)

编辑器服务负责创建和管理编辑器实例。它定义在 modules/editor/services/editors.ts 中,并提供一个简单的 API 来创建新编辑器。

当创建编辑器时,该服务会通过编辑器的作用域发出 EditorInitialized 事件。

来源

UI 组件

页面详情编辑器 (PageDetailEditor)

PageDetailEditor 是渲染编辑器 UI 的主要 React 组件。它定义在 components/page-detail-editor.tsx 中,它:

  1. 使用编辑器服务获取当前编辑器实例。
  2. 从编辑器实体检索编辑器状态(模式、默认打开的属性等)。
  3. 使用适当的 props 渲染 BlockSuiteEditor 组件。

Props

  • onLoad?: (editor: AffineEditorContainer) => void:编辑器加载时调用的回调。
  • readonly?: boolean:编辑器是否应为只读。

来源

BlockSuiteEditor

BlockSuiteEditor 是一个 React 组件,它包装了 BlockSuite 编辑器并提供了 React 友好的接口。它渲染来自 BlockSuite 的 AffineEditorContainer。

文档预览 (DocPeekPreview)

DocPeekPreview 组件在预览视图中显示文档的预览。当鼠标悬停在文档引用上时使用。

来源

编辑器初始化与绑定

编辑器的初始化和绑定是一个多步骤过程:

关键步骤

  1. 工作台服务 (WorkbenchService) 为文档创建一个视图。
  2. 编辑器服务 (EditorService) 创建一个编辑器实体。
  3. 通过 bindWorkbenchView 将编辑器绑定到视图。
  4. PageDetailEditor 组件渲染 BlockSuiteEditor。
  5. 当 BlockSuiteEditor 准备就绪时,onLoad 回调调用 bindEditorContainer
  6. 编辑器设置事件处理程序并初始化编辑器状态。

来源

编辑器状态管理

编辑器实体使用 @toeverything/infra 框架中的 LiveData 流来管理状态。

状态管理的关键方面:

  1. 编辑器使用 LiveData 流来表示其状态。
  2. 当编辑器绑定到工作台视图时,它会将其状态与视图的查询参数同步。
  3. UI 组件会消费这些流来渲染相应的 UI。
  4. 状态的变化会触发 UI 组件的重新渲染。

来源

编辑器功能

页面模式和无边模式

编辑器支持两种主要的编辑模式:

  1. 页面模式:一种传统的文档编辑体验,具有垂直布局,侧重于文本内容。
  2. 无边模式:一种基于画布的编辑体验,提供无限空间和自由布局。

模式由编辑器实体中的 mode$ LiveData 流管理,可以通过 toggleMode()setMode() 方法进行切换。

文档引用和预览

编辑器支持文档引用,允许链接到其他文档。当鼠标悬停在引用上时,可以显示预览视图,以便在不离开当前文档的情况下预览引用的文档。

涉及的组件:

  • AffinePageReference:渲染文档链接。
  • DocPeekPreview:在预览视图中渲染被引用文档的预览。

来源

演示模式

编辑器在无边模式下支持演示模式,允许用户以幻灯片类似的方式在帧之间导航。它由 isPresenting$ LiveData 流控制,并通过 togglePresentation() 方法进行切换。

AI 集成

编辑器通过以下方式集成 AI 功能:

  1. AI 斜杠命令:用户可以通过输入“/”并选择与 AI 相关的命令来调用 AI 功能。
  2. AI 工具栏条目:AI 功能可从编辑器工具栏访问。
  3. AI 面板:用于 AI 交互的专用 UI 面板。

来源

与 BlockSuite 的集成

AFFiNE 的编辑器系统构建在可定制的块式编辑框架 BlockSuite 之上。集成通过几个组件实现:

关键集成点

  1. BlockSuiteEditor 组件:包装来自 BlockSuite 的 AffineEditorContainer。
  2. 编辑器绑定:编辑器实体绑定到 AffineEditorContainer 以控制和与之交互。
  3. BlockSuite 扩展:AFFiNE 使用以下内容扩展 BlockSuite:
    • AI 功能
    • 快速搜索功能。
    • 自定义斜杠菜单命令。
    • 自定义块类型。

来源

文档元数据展示

编辑器系统与 DocDisplayMetaService 配合使用,以显示文档信息,如标题和图标。

DocDisplayMetaService 提供:

  • title$(docId):提供文档标题的 LiveData 流。
  • icon$(docId):提供文档图标的 LiveData 流。

来源

移动支持

编辑器系统支持桌面和移动端接口,并为每个平台有不同的实现。

  • 桌面端DetailPageImpldesktop/pages/workspace/detail-page/detail-page.tsx 中。
  • 移动端DetailPageImplmobile/pages/workspace/detail/mobile-detail-page.tsx 中。

这两种实现都使用相同的核心编辑器实体,但具有不同的 UI 包装器和适合各平台的交互模式。

来源

总结

编辑器系统是 AFFiNE 的核心组件,它与 BlockSuite 集成以提供文档编辑功能。它使用 LiveData 流进行响应式状态管理,并为页面模式和无边模式下的文档编辑提供了一个灵活、可扩展的基础。

该系统设计为模块化和可适应的,允许轻松扩展新功能,如 AI 集成、快速搜索和自定义 UI 组件。