Fix release notification resource and add multiple advance reminders

This commit is contained in:
Codex
2026-10-14 11:30:37 +08:00
parent caf7abe0c0
commit 4d86db3dd5
16 changed files with 350 additions and 58 deletions
+16 -5
View File
@@ -3,23 +3,31 @@ import 'semester.dart';
enum ColorMode { single, multicolor }
class AppSettings {
const AppSettings({
AppSettings({
this.semester,
this.remindersEnabled = true,
this.reminderMinutes = 15,
int reminderMinutes = 15,
List<int>? reminderOffsets,
this.colorMode = ColorMode.multicolor,
this.singleColorArgb = 0xFF348F91,
this.calendarEnabled = false,
this.calendarId,
this.courseHeightScale = defaultCourseHeightScale,
});
}) : reminderOffsets = List.unmodifiable(
(reminderOffsets ?? [reminderMinutes]).toSet().toList()..sort(),
);
static const allowedReminderMinutes = [5, 10, 15, 30, 60];
static const defaultCourseHeightScale = 1.25;
static const minCourseHeightScale = 0.8;
static const maxCourseHeightScale = 2.0;
final double courseHeightScale;
final Semester? semester;
final bool remindersEnabled, calendarEnabled;
final int reminderMinutes, singleColorArgb;
final int singleColorArgb;
final List<int> reminderOffsets;
// Retain the single-value API and JSON field for existing saved data.
int get reminderMinutes =>
reminderOffsets.isEmpty ? 15 : reminderOffsets.first;
final ColorMode colorMode;
final String? calendarId;
AppSettings copyWith({
@@ -27,6 +35,7 @@ class AppSettings {
bool clearSemester = false,
bool? remindersEnabled,
int? reminderMinutes,
List<int>? reminderOffsets,
ColorMode? colorMode,
int? singleColorArgb,
bool? calendarEnabled,
@@ -35,7 +44,9 @@ class AppSettings {
}) => AppSettings(
semester: clearSemester ? null : semester ?? this.semester,
remindersEnabled: remindersEnabled ?? this.remindersEnabled,
reminderMinutes: reminderMinutes ?? this.reminderMinutes,
reminderOffsets:
reminderOffsets ??
(reminderMinutes == null ? this.reminderOffsets : [reminderMinutes]),
colorMode: colorMode ?? this.colorMode,
singleColorArgb: singleColorArgb ?? this.singleColorArgb,
calendarEnabled: calendarEnabled ?? this.calendarEnabled,
+14 -5
View File
@@ -17,14 +17,15 @@ class ImportMetadata {
class AppSnapshot {
AppSnapshot({
this.settings = const AppSettings(),
AppSettings? settings,
List<Course> courses = const [],
this.importMetadata,
this.examSchedule,
SchoolTerm? schoolTerm,
this.calendarCleanupPending = false,
Map<String, String> calendarEventIds = const {},
}) : schoolTerm = schoolTerm ?? _legacyTerm(courses, examSchedule),
}) : settings = settings ?? AppSettings(),
schoolTerm = schoolTerm ?? _legacyTerm(courses, examSchedule),
courses = List.unmodifiable(courses),
calendarEventIds = Map.unmodifiable(calendarEventIds);
final AppSettings settings;
@@ -85,6 +86,7 @@ class AppSnapshot {
},
'remindersEnabled': settings.remindersEnabled,
'reminderMinutes': settings.reminderMinutes,
'reminderOffsets': settings.reminderOffsets,
'colorMode': settings.colorMode.name,
'singleColorArgb': settings.singleColorArgb,
'calendarEnabled': settings.calendarEnabled,
@@ -112,10 +114,17 @@ class AppSnapshot {
throw const FormatException('保存课表无效');
}
final s = Map<String, dynamic>.from(json['settings'] as Map);
final minutes = s['reminderMinutes'] as int;
if (![5, 10, 15, 30, 60].contains(minutes)) {
final rawOffsets = s.containsKey('reminderOffsets')
? s['reminderOffsets']
: [s['reminderMinutes']];
if (rawOffsets is! List ||
rawOffsets.isEmpty ||
rawOffsets.any(
(v) => v is! int || !AppSettings.allowedReminderMinutes.contains(v),
)) {
throw const FormatException('提醒时间无效');
}
final offsets = rawOffsets.cast<int>();
final color = s['singleColorArgb'] as int;
if (color < 0 || color > 0xFFFFFFFF) throw const FormatException('颜色无效');
final rawHeight = s.containsKey('courseHeightScale')
@@ -152,7 +161,7 @@ class AppSnapshot {
settings: AppSettings(
semester: term,
remindersEnabled: s['remindersEnabled'] as bool,
reminderMinutes: minutes,
reminderOffsets: offsets,
colorMode: ColorMode.values.byName(s['colorMode'] as String),
singleColorArgb: color,
calendarEnabled: s['calendarEnabled'] as bool,