Todo stores editor documents too, so the document, the editor, its view, the format bar, links, the clipboard, scripts and EditorBlocks move, with their strings and tests, to a shared package on the same appflowy_editor fork. What is Learn's alone stays in Learn on top of it, and what the editor took from it directly is inverted: EditorBlocks gains textMarks, formatActions and onEditorClosed, RichContentEditor a wrapEditor, and an InsertableBlock's name takes the BuildContext. Learn's screens use LearnContentEditor and LearnContentView, which add Learn's blocks and the grammar check. Learn behaves as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
65 lines
2.9 KiB
Markdown
65 lines
2.9 KiB
Markdown
# halkyon_editor
|
|
|
|
Halkyon's rich text, shared by its apps: the document as an app keeps it, the
|
|
one editor and the one read-only view of it, built on
|
|
[`appflowy_editor`](https://github.com/AppFlowy-IO/appflowy-editor) (our fork,
|
|
pinned, as every app's), with their texts in British English, American English
|
|
and German. Moved out of Halkyon Learn on 6 Nov 2026, when Halkyon Todo took
|
|
editor documents too (ADR 0033, D37).
|
|
|
|
## Using it
|
|
|
|
An app installs `HalkyonEditorLocalizations.delegate` beside its other
|
|
delegates, and halkyon_ui's, whose sheets the Insert menu opens in.
|
|
|
|
```dart
|
|
// Stored: RichContent is the editor's document JSON and its format's version.
|
|
final content = RichContent.plain('Buy milk'); // or RichContent.empty()
|
|
content.plainText; // 'Buy milk'
|
|
content.isBlank; // false
|
|
final stored = content.toJson();
|
|
RichContent.fromJson(stored);
|
|
|
|
RichContentEditor(
|
|
initialContent: content,
|
|
onChanged: (content) => save(content),
|
|
formatBar: true,
|
|
);
|
|
RichContentView(content: content);
|
|
```
|
|
|
|
## What it holds
|
|
|
|
- **`RichContent`** (`lib/src/content/`): pure Dart, the document in JSON.
|
|
`content_blocks.dart` names every block's type and attributes across the
|
|
apps, for `plainText` and for what a block's type is called for good.
|
|
- **`RichContentEditor`, `RichContentView`** (`lib/src/editor/`): the editor,
|
|
with the `FormatBar` docked below it while it has the focus, copying and
|
|
pasting that keep the formats (`EditorClipboard`), links (`editLink`, Ctrl+K)
|
|
and superscript and subscript; the view, display only, taking the height of
|
|
its content.
|
|
- **`EditorBlocks`**: what an editor knows. `basicBlocks` is what it knows
|
|
without an app (the editor's own builders; headings, lists, a checklist, a
|
|
quote, a divider and a table to insert). An app adds its own blocks, and
|
|
passes them as `blocks:` or through `EditorBlocksScope`, with:
|
|
- `builders`, `insertable` (the Insert sheet and the desktop's `/` menu show
|
|
the same list) and `shortcuts`;
|
|
- `textMarks`, how marks of its own are drawn, each wrapping the one before
|
|
it, and `formatActions`, their buttons, after subscript;
|
|
- `onEditorClosed`, for what its text left outside the editor.
|
|
`plus` joins two sets, `offering` narrows what is offered and nothing else.
|
|
- **`AtomicBlock`, `BlockNotice`**: for an app's block taken whole, selected
|
|
and removed as one. A type nothing knows shows as needing a newer app, and
|
|
stays as it is.
|
|
|
|
`RichContentEditor`'s `wrapEditor` puts what an app adds around the editor
|
|
itself, knowing its state and focus (Learn's check of the spelling).
|
|
|
|
Editors are tested as in Learn: host one in a scrollable body with a slot of
|
|
fixed height, `pump(const Duration(seconds: 1))` after changes, and find its
|
|
text with `findRichText: true`.
|
|
|
|
## Licence
|
|
|
|
GNU Affero General Public License, version 3 or any later version
|
|
(`AGPL-3.0-or-later`), as the other packages of the apps; see [LICENSE](LICENSE).
|