memos/web/src/components/MemoEditor
boojack 9ca71229a6 fix: preserve draft content when tab is suspended or editor remounts
Gate auto-save on initialization to prevent empty content from overwriting
cached drafts on remount. Flush drafts synchronously on visibilitychange/
pagehide so Chromium tab suspension cannot drop pending debounced saves.
Restore cached draft over saved memo content when they differ (inline editing).
2026-04-10 08:48:50 +08:00
..
components feat(memo-editor): add compact live waveform recorder panel (#5817) 2026-04-07 20:40:34 +08:00
Editor feat(mentions): add memo mention parsing, notifications, and rendering (#5811) 2026-04-06 22:16:53 +08:00
hooks fix: preserve draft content when tab is suspended or editor remounts 2026-04-10 08:48:50 +08:00
services fix: preserve draft content when tab is suspended or editor remounts 2026-04-10 08:48:50 +08:00
state chore: refactor memo editor audio recording flow 2026-04-06 15:46:38 +08:00
Toolbar chore: refactor attachment media layout and insert menu organization 2026-04-08 23:28:49 +08:00
types feat(memo-editor): add compact live waveform recorder panel (#5817) 2026-04-07 20:40:34 +08:00
constants.ts refactor(web): improve MemoView and MemoEditor maintainability (#5754) 2026-03-21 07:20:18 +08:00
index.tsx fix: preserve draft content when tab is suspended or editor remounts 2026-04-10 08:48:50 +08:00
README.md refactor(editor): complete state machine and services migration 2025-12-23 08:38:02 +08:00

MemoEditor Architecture

Overview

MemoEditor uses a three-layer architecture for better separation of concerns and testability.

Architecture

┌─────────────────────────────────────────┐
│   Presentation Layer (Components)       │
│   - EditorToolbar, EditorContent, etc.  │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│   State Layer (Reducer + Context)       │
│   - state/, useEditorContext()          │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│   Service Layer (Business Logic)        │
│   - services/ (pure functions)          │
└─────────────────────────────────────────┘

Directory Structure

MemoEditor/
├── state/                  # State management (reducer, actions, context)
├── services/              # Business logic (pure functions)
├── components/            # UI components
├── hooks/                 # React hooks (utilities)
├── Editor/               # Core editor component
├── Toolbar/              # Toolbar components
├── constants.ts
└── types/

Key Concepts

State Management

Uses useReducer + Context for predictable state transitions. All state changes go through action creators.

Services

Pure TypeScript functions containing business logic. No React hooks, easy to test.

Components

Thin presentation components that dispatch actions and render UI.

Usage

import MemoEditor from "@/components/MemoEditor";

<MemoEditor
  memoName="memos/123"
  onConfirm={(name) => console.log('Saved:', name)}
  onCancel={() => console.log('Cancelled')}
/>

Testing

Services are pure functions - easy to unit test without React.

const state = mockEditorState();
const result = await memoService.save(state, { memoName: 'memos/123' });