diff --git a/app/lib/features/editor/bloc/editor_bloc.dart b/app/lib/features/editor/bloc/editor_bloc.dart index 80877c1..0b8dfac 100644 --- a/app/lib/features/editor/bloc/editor_bloc.dart +++ b/app/lib/features/editor/bloc/editor_bloc.dart @@ -163,6 +163,28 @@ class TextFormatChanged extends EditorEvent { }); } +/// 加载已有日记数据(从 JournalRepository 读取后原子注入) +/// +/// 与 StrokesLoaded/ElementsLoaded/TagsLoaded 等细粒度事件不同, +/// LoadJournal 一次性还原所有日记状态,不触发 auto-save (isDirty=false)。 +class LoadJournal extends EditorEvent { + final String title; + final Mood mood; + final List tags; + final List strokes; + final List elements; + final DateTime? lastSavedAt; + + LoadJournal({ + required this.title, + required this.mood, + required this.tags, + required this.strokes, + required this.elements, + this.lastSavedAt, + }); +} + // ============================================================ // 状态 // ============================================================ @@ -303,6 +325,9 @@ class EditorBloc extends Bloc { on(_onElementSelected); on(_onElementsLoaded); + // 日记加载事件 + on(_onLoadJournal); + // 工具栏事件 on(_onToolChanged); @@ -458,6 +483,25 @@ class EditorBloc extends Bloc { emit(state.copyWith(elements: event.elements)); } + // ============================================================ + // 日记加载事件处理 + // ============================================================ + + /// 加载已有日记 — 原子操作,一次性还原所有状态 + /// + /// 不触发 auto-save(isDirty=false),因为这是加载而非用户编辑。 + void _onLoadJournal(LoadJournal event, Emitter emit) { + emit(state.copyWith( + title: event.title, + selectedMood: event.mood, + tags: event.tags, + strokes: event.strokes, + elements: event.elements, + lastSavedAt: event.lastSavedAt, + isDirty: false, + )); + } + // ============================================================ // 工具栏事件处理 // ============================================================ diff --git a/app/lib/features/mood/bloc/mood_bloc.dart b/app/lib/features/mood/bloc/mood_bloc.dart index e92bef9..03ff35c 100644 --- a/app/lib/features/mood/bloc/mood_bloc.dart +++ b/app/lib/features/mood/bloc/mood_bloc.dart @@ -1,5 +1,6 @@ // 心情 BLoC — 通过 API 加载心情统计数据 +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:nuanji_app/data/models/journal_entry.dart'; import 'package:nuanji_app/data/remote/api_client.dart'; diff --git a/app/test/features/editor/bloc/editor_bloc_test.dart b/app/test/features/editor/bloc/editor_bloc_test.dart index a36be24..9ee3d34 100644 --- a/app/test/features/editor/bloc/editor_bloc_test.dart +++ b/app/test/features/editor/bloc/editor_bloc_test.dart @@ -6,6 +6,7 @@ import 'dart:math'; import 'package:flutter_test/flutter_test.dart'; +import 'package:nuanji_app/data/models/journal_entry.dart'; import 'package:nuanji_app/data/models/journal_element.dart'; import 'package:nuanji_app/features/editor/bloc/editor_bloc.dart'; import 'package:nuanji_app/features/editor/widgets/stroke_model.dart'; @@ -262,5 +263,35 @@ void main() { bloc.close(); }); + + // ===== LoadJournal 原子加载 ===== + + test('LoadJournal 还原已有日记数据', () async { + final strokes = [_testStroke(id: 's1')]; + final elements = [ + JournalElement.createSticker( + journalId: 'j1', + emoji: '😊', + position: Offset.zero, + ), + ]; + + final state = await dispatch(LoadJournal( + title: '测试日记', + mood: Mood.happy, + tags: const ['开心', '学校'], + strokes: strokes, + elements: elements, + lastSavedAt: DateTime(2026, 6, 1), + )); + + expect(state.title, '测试日记'); + expect(state.selectedMood, Mood.happy); + expect(state.tags, ['开心', '学校']); + expect(state.strokes.length, 1); + expect(state.elements.length, 1); + expect(state.lastSavedAt, DateTime(2026, 6, 1)); + expect(state.isDirty, isFalse, reason: 'LoadJournal 不应标记为 dirty'); + }); }); }