整个课程和数据UI重新设计版本

This commit is contained in:
shenlei
2026-09-18 17:55:44 +09:00
parent febfd30f49
commit 0a4f97d105
154 changed files with 12366 additions and 4784 deletions
+9 -7
View File
@@ -6,12 +6,11 @@ import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'models.dart';
import 'a0_core.dart';
import 'courses/courses.dart';
import 'app_theme.dart';
import 'generated_content.dart';
import 'local_store.dart';
import 'review_feedback.dart';
import 'seed_courses.dart';
import 'courses/course_repository.dart';
import 'ai_config.dart';
import 'ai_service.dart';
import 'sherpa_stt_service.dart';
@@ -93,7 +92,7 @@ abstract class _AppStateData extends ChangeNotifier {
}
class AppState extends _AppStateData
with _ReviewAndMastery, _LessonProgress, _AssessmentProgress, _AiContent {
with _ReviewAndMastery, _AssessmentProgress, _LessonProgress, _AiContent {
static const _storageKey = 'learning_state_v1';
bool isLoaded = false;
bool _writing = false;
@@ -112,6 +111,9 @@ class AppState extends _AppStateData
Future<void> load() async {
try {
unawaited(SherpaSttService.instance.initialize());
// Adapt the A1–B1 JSON packs into the runtime registries before the saved
// snapshot is restored, so progress that points at those lessons resolves.
await CourseRepository.instance.load();
final config = await AiConfigFile.loadFromAsset();
if (config != null) {
if (config.apiKey != null && config.apiKey!.trim().isNotEmpty) {
@@ -219,10 +221,10 @@ class AppState extends _AppStateData
notifyListeners();
}
/// Applies the placement result. Only A0 starting points exist until A1
/// content is frozen, and placement never counts as passing a lesson.
/// Applies the placement result. The start may land on any loaded lesson
/// across A0–B1, and placement never counts as passing a lesson.
void setPlacementStartLesson(String lessonId) {
if (!a0SeedLessons.any((lesson) => lesson.id == lessonId)) return;
if (!allLessons.any((lesson) => lesson.id == lessonId)) return;
placementStartLessonId = lessonId;
activeLessonId = lessonId;
_resetLessonFlow();