feat: select school terms and smooth refractive Dock motion
This commit is contained in:
@@ -24,6 +24,7 @@ class AppSettings {
|
||||
final String? calendarId;
|
||||
AppSettings copyWith({
|
||||
Semester? semester,
|
||||
bool clearSemester = false,
|
||||
bool? remindersEnabled,
|
||||
int? reminderMinutes,
|
||||
ColorMode? colorMode,
|
||||
@@ -32,7 +33,7 @@ class AppSettings {
|
||||
String? calendarId,
|
||||
double? courseHeightScale,
|
||||
}) => AppSettings(
|
||||
semester: semester ?? this.semester,
|
||||
semester: clearSemester ? null : semester ?? this.semester,
|
||||
remindersEnabled: remindersEnabled ?? this.remindersEnabled,
|
||||
reminderMinutes: reminderMinutes ?? this.reminderMinutes,
|
||||
colorMode: colorMode ?? this.colorMode,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/// The graduate system's term number, independent of teaching-week dates.
|
||||
class SchoolTerm {
|
||||
SchoolTerm(this.id) {
|
||||
if (id < 1 || id > 9999) throw ArgumentError('学校学期编号无效');
|
||||
}
|
||||
final int id;
|
||||
String get label {
|
||||
final year = 1990 + ((id - 1) ~/ 2);
|
||||
return '$year-${year + 1}年${id.isOdd ? '秋' : '春'}';
|
||||
}
|
||||
|
||||
static List<SchoolTerm> get choices =>
|
||||
List.generate(73, (index) => SchoolTerm(73 - index));
|
||||
Uri get timetableUri =>
|
||||
Uri.https('yjsjy.uestc.edu.cn', '/pyxx/pygl/xskbcx/index/$id');
|
||||
Uri get examUri =>
|
||||
Uri.https('yjsjy.uestc.edu.cn', '/pyxx/pygl/kskcxx/index', {'xq': '$id'});
|
||||
Map<String, dynamic> toJson() => {'id': id};
|
||||
factory SchoolTerm.fromJson(Map<String, dynamic> json) {
|
||||
if (json['id'] is! int) throw const FormatException('学校学期无效');
|
||||
return SchoolTerm(json['id'] as int);
|
||||
}
|
||||
@override
|
||||
bool operator ==(Object other) => other is SchoolTerm && other.id == id;
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
}
|
||||
Reference in New Issue
Block a user