feat(app): 添加 EditorBloc.LoadJournal event — 加载已有日记数据
- LoadJournal event: 原子加载 title/mood/tags/strokes/elements/lastSavedAt - _onLoadJournal handler: 不触发 auto-save (isDirty=false) - 单元测试: 验证 LoadJournal 正确还原所有状态字段 - mood_bloc: linter 补充 foundation.dart import
This commit is contained in:
@@ -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<String> tags;
|
||||||
|
final List<Stroke> strokes;
|
||||||
|
final List<JournalElement> 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<EditorEvent, EditorState> {
|
|||||||
on<ElementSelected>(_onElementSelected);
|
on<ElementSelected>(_onElementSelected);
|
||||||
on<ElementsLoaded>(_onElementsLoaded);
|
on<ElementsLoaded>(_onElementsLoaded);
|
||||||
|
|
||||||
|
// 日记加载事件
|
||||||
|
on<LoadJournal>(_onLoadJournal);
|
||||||
|
|
||||||
// 工具栏事件
|
// 工具栏事件
|
||||||
on<ToolChanged>(_onToolChanged);
|
on<ToolChanged>(_onToolChanged);
|
||||||
|
|
||||||
@@ -458,6 +483,25 @@ class EditorBloc extends Bloc<EditorEvent, EditorState> {
|
|||||||
emit(state.copyWith(elements: event.elements));
|
emit(state.copyWith(elements: event.elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 日记加载事件处理
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// 加载已有日记 — 原子操作,一次性还原所有状态
|
||||||
|
///
|
||||||
|
/// 不触发 auto-save(isDirty=false),因为这是加载而非用户编辑。
|
||||||
|
void _onLoadJournal(LoadJournal event, Emitter<EditorState> emit) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
title: event.title,
|
||||||
|
selectedMood: event.mood,
|
||||||
|
tags: event.tags,
|
||||||
|
strokes: event.strokes,
|
||||||
|
elements: event.elements,
|
||||||
|
lastSavedAt: event.lastSavedAt,
|
||||||
|
isDirty: false,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 工具栏事件处理
|
// 工具栏事件处理
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// 心情 BLoC — 通过 API 加载心情统计数据
|
// 心情 BLoC — 通过 API 加载心情统计数据
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:nuanji_app/data/models/journal_entry.dart';
|
import 'package:nuanji_app/data/models/journal_entry.dart';
|
||||||
import 'package:nuanji_app/data/remote/api_client.dart';
|
import 'package:nuanji_app/data/remote/api_client.dart';
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
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/data/models/journal_element.dart';
|
||||||
import 'package:nuanji_app/features/editor/bloc/editor_bloc.dart';
|
import 'package:nuanji_app/features/editor/bloc/editor_bloc.dart';
|
||||||
import 'package:nuanji_app/features/editor/widgets/stroke_model.dart';
|
import 'package:nuanji_app/features/editor/widgets/stroke_model.dart';
|
||||||
@@ -262,5 +263,35 @@ void main() {
|
|||||||
|
|
||||||
bloc.close();
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user