feat: select school terms and smooth refractive Dock motion

This commit is contained in:
Codex
2026-10-13 19:08:36 +08:00
parent 3e2d8864af
commit 50fcc70e8e
33 changed files with 1245 additions and 94 deletions
+26 -1
View File
@@ -2,6 +2,7 @@ import 'app_settings.dart';
import 'course.dart';
import 'semester.dart';
import 'exam_schedule.dart';
import 'school_term.dart';
class ImportMetadata {
const ImportMetadata({
@@ -20,16 +21,32 @@ class AppSnapshot {
List<Course> courses = const [],
this.importMetadata,
this.examSchedule,
SchoolTerm? schoolTerm,
this.calendarCleanupPending = false,
Map<String, String> calendarEventIds = const {},
}) : courses = List.unmodifiable(courses),
}) : schoolTerm = schoolTerm ?? _legacyTerm(courses, examSchedule),
courses = List.unmodifiable(courses),
calendarEventIds = Map.unmodifiable(calendarEventIds);
final AppSettings settings;
final List<Course> courses;
final ImportMetadata? importMetadata;
final ExamSchedule? examSchedule;
final SchoolTerm? schoolTerm;
final Map<String, String> calendarEventIds;
final bool calendarCleanupPending;
static SchoolTerm? _legacyTerm(List<Course> courses, ExamSchedule? exams) {
final ids = courses
.map(
(course) => RegExp(r'^uestc-(\d+)-').firstMatch(course.id)?.group(1),
)
.whereType<String>()
.toSet();
if (exams != null) ids.add(exams.termId);
if (ids.length != 1) return null;
final id = int.tryParse(ids.single);
return id != null && id >= 1 && id <= 9999 ? SchoolTerm(id) : null;
}
AppSnapshot copyWith({
AppSettings? settings,
List<Course>? courses,
@@ -38,6 +55,7 @@ class AppSnapshot {
bool clearMetadata = false,
ExamSchedule? examSchedule,
bool clearExams = false,
SchoolTerm? schoolTerm,
bool? calendarCleanupPending,
}) => AppSnapshot(
settings: settings ?? this.settings,
@@ -46,6 +64,7 @@ class AppSnapshot {
? null
: importMetadata ?? this.importMetadata,
examSchedule: clearExams ? null : examSchedule ?? this.examSchedule,
schoolTerm: schoolTerm ?? this.schoolTerm,
calendarEventIds: calendarEventIds ?? this.calendarEventIds,
calendarCleanupPending:
calendarCleanupPending ?? this.calendarCleanupPending,
@@ -53,6 +72,7 @@ class AppSnapshot {
Map<String, dynamic> toJson() => {
'schemaVersion': 1,
'examSchedule': examSchedule?.toJson(),
'schoolTerm': schoolTerm?.toJson(),
'courses': courses.map((c) => c.toJson()).toList(),
'settings': {
'semester': settings.semester == null
@@ -116,6 +136,11 @@ class AppSnapshot {
);
final metadata = json['importMetadata'];
return AppSnapshot(
schoolTerm: json['schoolTerm'] == null
? null
: SchoolTerm.fromJson(
Map<String, dynamic>.from(json['schoolTerm'] as Map),
),
examSchedule: json['examSchedule'] == null
? null
: ExamSchedule.fromJson(