merged develop
This commit is contained in:
commit
f98a6979fb
188 files changed
+7474
-2558
No files matched your search
@@ -14,9 +14,6 @@ enum WidgetLessonStatus {
|
||||
irregular,
|
||||
teacherChanged,
|
||||
event,
|
||||
// Sonder-Lesson-Types (Aufsicht, Sprechstunde, …) — Native-Widget-Renderer,
|
||||
// die den Status noch nicht kennen, fallen still auf den regulären Stil
|
||||
// zurück, sobald der String dort unbekannt ist.
|
||||
duty,
|
||||
}
|
||||
|
||||
@@ -35,6 +32,9 @@ abstract class WidgetLesson with _$WidgetLesson {
|
||||
String? originalTeacher,
|
||||
required WidgetLessonStatus status,
|
||||
String? customColor,
|
||||
/// Fertig aufgelöste Kachelfarbe als `#RRGGBB`. Native Renderer kennen die
|
||||
/// Paletten nicht — Änderungen daran brauchen so keinen nativen Eingriff.
|
||||
String? color,
|
||||
@Default(0) int siblingCount,
|
||||
}) = _WidgetLesson;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: type=lint, type=warning, deprecated_member_use, deprecated_member_use_from_same_package
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'widget_data.dart';
|
||||
@@ -9,6 +9,7 @@ part of 'widget_data.dart';
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
@@ -18,7 +19,9 @@ mixin _$WidgetLesson {
|
||||
DateTime get start; DateTime get end; String get subjectShort; String? get subjectLong; String? get room;/// On teacher accounts this carries the class label ("7a") instead of the
|
||||
/// teacher short name — see `WidgetDataMapper` `showClassInsteadOfTeacher`;
|
||||
/// [originalTeacher] is null in that case.
|
||||
String? get teacher; String? get originalTeacher; WidgetLessonStatus get status; String? get customColor; int get siblingCount;
|
||||
String? get teacher; String? get originalTeacher; WidgetLessonStatus get status; String? get customColor;/// Fertig aufgelöste Kachelfarbe als `#RRGGBB`. Native Renderer kennen die
|
||||
/// Paletten nicht — Änderungen daran brauchen so keinen nativen Eingriff.
|
||||
String? get color; int get siblingCount;
|
||||
/// Create a copy of WidgetLesson
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -31,16 +34,21 @@ $WidgetLessonCopyWith<WidgetLesson> get copyWith => _$WidgetLessonCopyWithImpl<W
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetLesson&&(identical(other.start, start) || other.start == start)&&(identical(other.end, end) || other.end == end)&&(identical(other.subjectShort, subjectShort) || other.subjectShort == subjectShort)&&(identical(other.subjectLong, subjectLong) || other.subjectLong == subjectLong)&&(identical(other.room, room) || other.room == room)&&(identical(other.teacher, teacher) || other.teacher == teacher)&&(identical(other.originalTeacher, originalTeacher) || other.originalTeacher == originalTeacher)&&(identical(other.status, status) || other.status == status)&&(identical(other.customColor, customColor) || other.customColor == customColor)&&(identical(other.siblingCount, siblingCount) || other.siblingCount == siblingCount));
|
||||
final _this = this as WidgetLesson;
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetLesson&&(identical(other.start, _this.start) || other.start == _this.start)&&(identical(other.end, _this.end) || other.end == _this.end)&&(identical(other.subjectShort, _this.subjectShort) || other.subjectShort == _this.subjectShort)&&(identical(other.subjectLong, _this.subjectLong) || other.subjectLong == _this.subjectLong)&&(identical(other.room, _this.room) || other.room == _this.room)&&(identical(other.teacher, _this.teacher) || other.teacher == _this.teacher)&&(identical(other.originalTeacher, _this.originalTeacher) || other.originalTeacher == _this.originalTeacher)&&(identical(other.status, _this.status) || other.status == _this.status)&&(identical(other.customColor, _this.customColor) || other.customColor == _this.customColor)&&(identical(other.color, _this.color) || other.color == _this.color)&&(identical(other.siblingCount, _this.siblingCount) || other.siblingCount == _this.siblingCount));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,start,end,subjectShort,subjectLong,room,teacher,originalTeacher,status,customColor,siblingCount);
|
||||
int get hashCode {
|
||||
final _this = this as WidgetLesson;
|
||||
return Object.hash(runtimeType,_this.start,_this.end,_this.subjectShort,_this.subjectLong,_this.room,_this.teacher,_this.originalTeacher,_this.status,_this.customColor,_this.color,_this.siblingCount);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetLesson(start: $start, end: $end, subjectShort: $subjectShort, subjectLong: $subjectLong, room: $room, teacher: $teacher, originalTeacher: $originalTeacher, status: $status, customColor: $customColor, siblingCount: $siblingCount)';
|
||||
final _this = this as WidgetLesson;
|
||||
return 'WidgetLesson(start: ${_this.start}, end: ${_this.end}, subjectShort: ${_this.subjectShort}, subjectLong: ${_this.subjectLong}, room: ${_this.room}, teacher: ${_this.teacher}, originalTeacher: ${_this.originalTeacher}, status: ${_this.status}, customColor: ${_this.customColor}, color: ${_this.color}, siblingCount: ${_this.siblingCount})';
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +59,7 @@ abstract mixin class $WidgetLessonCopyWith<$Res> {
|
||||
factory $WidgetLessonCopyWith(WidgetLesson value, $Res Function(WidgetLesson) _then) = _$WidgetLessonCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, int siblingCount
|
||||
DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, String? color, int siblingCount
|
||||
});
|
||||
|
||||
|
||||
@@ -68,8 +76,8 @@ class _$WidgetLessonCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of WidgetLesson
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? start = null,Object? end = null,Object? subjectShort = null,Object? subjectLong = freezed,Object? room = freezed,Object? teacher = freezed,Object? originalTeacher = freezed,Object? status = null,Object? customColor = freezed,Object? siblingCount = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? start = null,Object? end = null,Object? subjectShort = null,Object? subjectLong = freezed,Object? room = freezed,Object? teacher = freezed,Object? originalTeacher = freezed,Object? status = null,Object? customColor = freezed,Object? color = freezed,Object? siblingCount = null,}) {
|
||||
return _then(WidgetLesson(
|
||||
start: null == start ? _self.start : start // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,end: null == end ? _self.end : end // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,subjectShort: null == subjectShort ? _self.subjectShort : subjectShort // ignore: cast_nullable_to_non_nullable
|
||||
@@ -79,6 +87,7 @@ as String?,teacher: freezed == teacher ? _self.teacher : teacher // ignore: cast
|
||||
as String?,originalTeacher: freezed == originalTeacher ? _self.originalTeacher : originalTeacher // ignore: cast_nullable_to_non_nullable
|
||||
as String?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as WidgetLessonStatus,customColor: freezed == customColor ? _self.customColor : customColor // ignore: cast_nullable_to_non_nullable
|
||||
as String?,color: freezed == color ? _self.color : color // ignore: cast_nullable_to_non_nullable
|
||||
as String?,siblingCount: null == siblingCount ? _self.siblingCount : siblingCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
@@ -165,10 +174,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, int siblingCount)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, String? color, int siblingCount)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _WidgetLesson() when $default != null:
|
||||
return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that.room,_that.teacher,_that.originalTeacher,_that.status,_that.customColor,_that.siblingCount);case _:
|
||||
return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that.room,_that.teacher,_that.originalTeacher,_that.status,_that.customColor,_that.color,_that.siblingCount);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -186,10 +195,10 @@ return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, int siblingCount) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, String? color, int siblingCount) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _WidgetLesson():
|
||||
return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that.room,_that.teacher,_that.originalTeacher,_that.status,_that.customColor,_that.siblingCount);case _:
|
||||
return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that.room,_that.teacher,_that.originalTeacher,_that.status,_that.customColor,_that.color,_that.siblingCount);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -206,10 +215,10 @@ return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, int siblingCount)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, String? color, int siblingCount)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _WidgetLesson() when $default != null:
|
||||
return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that.room,_that.teacher,_that.originalTeacher,_that.status,_that.customColor,_that.siblingCount);case _:
|
||||
return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that.room,_that.teacher,_that.originalTeacher,_that.status,_that.customColor,_that.color,_that.siblingCount);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -221,7 +230,7 @@ return $default(_that.start,_that.end,_that.subjectShort,_that.subjectLong,_that
|
||||
@JsonSerializable()
|
||||
|
||||
class _WidgetLesson implements WidgetLesson {
|
||||
const _WidgetLesson({required this.start, required this.end, required this.subjectShort, this.subjectLong, this.room, this.teacher, this.originalTeacher, required this.status, this.customColor, this.siblingCount = 0});
|
||||
const _WidgetLesson({required this.start, required this.end, required this.subjectShort, this.subjectLong, this.room, this.teacher, this.originalTeacher, required this.status, this.customColor, this.color, this.siblingCount = 0});
|
||||
factory _WidgetLesson.fromJson(Map<String, dynamic> json) => _$WidgetLessonFromJson(json);
|
||||
|
||||
@override final DateTime start;
|
||||
@@ -236,6 +245,9 @@ class _WidgetLesson implements WidgetLesson {
|
||||
@override final String? originalTeacher;
|
||||
@override final WidgetLessonStatus status;
|
||||
@override final String? customColor;
|
||||
/// Fertig aufgelöste Kachelfarbe als `#RRGGBB`. Native Renderer kennen die
|
||||
/// Paletten nicht — Änderungen daran brauchen so keinen nativen Eingriff.
|
||||
@override final String? color;
|
||||
@override@JsonKey() final int siblingCount;
|
||||
|
||||
/// Create a copy of WidgetLesson
|
||||
@@ -251,16 +263,18 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetLesson&&(identical(other.start, start) || other.start == start)&&(identical(other.end, end) || other.end == end)&&(identical(other.subjectShort, subjectShort) || other.subjectShort == subjectShort)&&(identical(other.subjectLong, subjectLong) || other.subjectLong == subjectLong)&&(identical(other.room, room) || other.room == room)&&(identical(other.teacher, teacher) || other.teacher == teacher)&&(identical(other.originalTeacher, originalTeacher) || other.originalTeacher == originalTeacher)&&(identical(other.status, status) || other.status == status)&&(identical(other.customColor, customColor) || other.customColor == customColor)&&(identical(other.siblingCount, siblingCount) || other.siblingCount == siblingCount));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetLesson&&(identical(other.start, start) || other.start == start)&&(identical(other.end, end) || other.end == end)&&(identical(other.subjectShort, subjectShort) || other.subjectShort == subjectShort)&&(identical(other.subjectLong, subjectLong) || other.subjectLong == subjectLong)&&(identical(other.room, room) || other.room == room)&&(identical(other.teacher, teacher) || other.teacher == teacher)&&(identical(other.originalTeacher, originalTeacher) || other.originalTeacher == originalTeacher)&&(identical(other.status, status) || other.status == status)&&(identical(other.customColor, customColor) || other.customColor == customColor)&&(identical(other.color, color) || other.color == color)&&(identical(other.siblingCount, siblingCount) || other.siblingCount == siblingCount));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,start,end,subjectShort,subjectLong,room,teacher,originalTeacher,status,customColor,siblingCount);
|
||||
int get hashCode {
|
||||
return Object.hash(runtimeType,start,end,subjectShort,subjectLong,room,teacher,originalTeacher,status,customColor,color,siblingCount);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetLesson(start: $start, end: $end, subjectShort: $subjectShort, subjectLong: $subjectLong, room: $room, teacher: $teacher, originalTeacher: $originalTeacher, status: $status, customColor: $customColor, siblingCount: $siblingCount)';
|
||||
return 'WidgetLesson(start: $start, end: $end, subjectShort: $subjectShort, subjectLong: $subjectLong, room: $room, teacher: $teacher, originalTeacher: $originalTeacher, status: $status, customColor: $customColor, color: $color, siblingCount: $siblingCount)';
|
||||
}
|
||||
|
||||
|
||||
@@ -271,7 +285,7 @@ abstract mixin class _$WidgetLessonCopyWith<$Res> implements $WidgetLessonCopyWi
|
||||
factory _$WidgetLessonCopyWith(_WidgetLesson value, $Res Function(_WidgetLesson) _then) = __$WidgetLessonCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, int siblingCount
|
||||
DateTime start, DateTime end, String subjectShort, String? subjectLong, String? room, String? teacher, String? originalTeacher, WidgetLessonStatus status, String? customColor, String? color, int siblingCount
|
||||
});
|
||||
|
||||
|
||||
@@ -288,7 +302,7 @@ class __$WidgetLessonCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of WidgetLesson
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? start = null,Object? end = null,Object? subjectShort = null,Object? subjectLong = freezed,Object? room = freezed,Object? teacher = freezed,Object? originalTeacher = freezed,Object? status = null,Object? customColor = freezed,Object? siblingCount = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? start = null,Object? end = null,Object? subjectShort = null,Object? subjectLong = freezed,Object? room = freezed,Object? teacher = freezed,Object? originalTeacher = freezed,Object? status = null,Object? customColor = freezed,Object? color = freezed,Object? siblingCount = null,}) {
|
||||
return _then(_WidgetLesson(
|
||||
start: null == start ? _self.start : start // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,end: null == end ? _self.end : end // ignore: cast_nullable_to_non_nullable
|
||||
@@ -299,6 +313,7 @@ as String?,teacher: freezed == teacher ? _self.teacher : teacher // ignore: cast
|
||||
as String?,originalTeacher: freezed == originalTeacher ? _self.originalTeacher : originalTeacher // ignore: cast_nullable_to_non_nullable
|
||||
as String?,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as WidgetLessonStatus,customColor: freezed == customColor ? _self.customColor : customColor // ignore: cast_nullable_to_non_nullable
|
||||
as String?,color: freezed == color ? _self.color : color // ignore: cast_nullable_to_non_nullable
|
||||
as String?,siblingCount: null == siblingCount ? _self.siblingCount : siblingCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
@@ -332,16 +347,21 @@ $WidgetPeriodCopyWith<WidgetPeriod> get copyWith => _$WidgetPeriodCopyWithImpl<W
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetPeriod&&(identical(other.name, name) || other.name == name)&&(identical(other.startMinutes, startMinutes) || other.startMinutes == startMinutes)&&(identical(other.endMinutes, endMinutes) || other.endMinutes == endMinutes)&&(identical(other.virtualStartMinutes, virtualStartMinutes) || other.virtualStartMinutes == virtualStartMinutes)&&(identical(other.virtualEndMinutes, virtualEndMinutes) || other.virtualEndMinutes == virtualEndMinutes));
|
||||
final _this = this as WidgetPeriod;
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetPeriod&&(identical(other.name, _this.name) || other.name == _this.name)&&(identical(other.startMinutes, _this.startMinutes) || other.startMinutes == _this.startMinutes)&&(identical(other.endMinutes, _this.endMinutes) || other.endMinutes == _this.endMinutes)&&(identical(other.virtualStartMinutes, _this.virtualStartMinutes) || other.virtualStartMinutes == _this.virtualStartMinutes)&&(identical(other.virtualEndMinutes, _this.virtualEndMinutes) || other.virtualEndMinutes == _this.virtualEndMinutes));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,name,startMinutes,endMinutes,virtualStartMinutes,virtualEndMinutes);
|
||||
int get hashCode {
|
||||
final _this = this as WidgetPeriod;
|
||||
return Object.hash(runtimeType,_this.name,_this.startMinutes,_this.endMinutes,_this.virtualStartMinutes,_this.virtualEndMinutes);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetPeriod(name: $name, startMinutes: $startMinutes, endMinutes: $endMinutes, virtualStartMinutes: $virtualStartMinutes, virtualEndMinutes: $virtualEndMinutes)';
|
||||
final _this = this as WidgetPeriod;
|
||||
return 'WidgetPeriod(name: ${_this.name}, startMinutes: ${_this.startMinutes}, endMinutes: ${_this.endMinutes}, virtualStartMinutes: ${_this.virtualStartMinutes}, virtualEndMinutes: ${_this.virtualEndMinutes})';
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +390,7 @@ class _$WidgetPeriodCopyWithImpl<$Res>
|
||||
/// Create a copy of WidgetPeriod
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? name = null,Object? startMinutes = null,Object? endMinutes = null,Object? virtualStartMinutes = null,Object? virtualEndMinutes = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
return _then(WidgetPeriod(
|
||||
name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String,startMinutes: null == startMinutes ? _self.startMinutes : startMinutes // ignore: cast_nullable_to_non_nullable
|
||||
as int,endMinutes: null == endMinutes ? _self.endMinutes : endMinutes // ignore: cast_nullable_to_non_nullable
|
||||
@@ -547,16 +567,18 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetPeriod&&(identical(other.name, name) || other.name == name)&&(identical(other.startMinutes, startMinutes) || other.startMinutes == startMinutes)&&(identical(other.endMinutes, endMinutes) || other.endMinutes == endMinutes)&&(identical(other.virtualStartMinutes, virtualStartMinutes) || other.virtualStartMinutes == virtualStartMinutes)&&(identical(other.virtualEndMinutes, virtualEndMinutes) || other.virtualEndMinutes == virtualEndMinutes));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetPeriod&&(identical(other.name, name) || other.name == name)&&(identical(other.startMinutes, startMinutes) || other.startMinutes == startMinutes)&&(identical(other.endMinutes, endMinutes) || other.endMinutes == endMinutes)&&(identical(other.virtualStartMinutes, virtualStartMinutes) || other.virtualStartMinutes == virtualStartMinutes)&&(identical(other.virtualEndMinutes, virtualEndMinutes) || other.virtualEndMinutes == virtualEndMinutes));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,name,startMinutes,endMinutes,virtualStartMinutes,virtualEndMinutes);
|
||||
int get hashCode {
|
||||
return Object.hash(runtimeType,name,startMinutes,endMinutes,virtualStartMinutes,virtualEndMinutes);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetPeriod(name: $name, startMinutes: $startMinutes, endMinutes: $endMinutes, virtualStartMinutes: $virtualStartMinutes, virtualEndMinutes: $virtualEndMinutes)';
|
||||
return 'WidgetPeriod(name: $name, startMinutes: $startMinutes, endMinutes: $endMinutes, virtualStartMinutes: $virtualStartMinutes, virtualEndMinutes: $virtualEndMinutes)';
|
||||
}
|
||||
|
||||
|
||||
@@ -615,16 +637,21 @@ $WidgetDayInfoCopyWith<WidgetDayInfo> get copyWith => _$WidgetDayInfoCopyWithImp
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetDayInfo&&(identical(other.date, date) || other.date == date)&&(identical(other.isHoliday, isHoliday) || other.isHoliday == isHoliday)&&(identical(other.holidayName, holidayName) || other.holidayName == holidayName));
|
||||
final _this = this as WidgetDayInfo;
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetDayInfo&&(identical(other.date, _this.date) || other.date == _this.date)&&(identical(other.isHoliday, _this.isHoliday) || other.isHoliday == _this.isHoliday)&&(identical(other.holidayName, _this.holidayName) || other.holidayName == _this.holidayName));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,date,isHoliday,holidayName);
|
||||
int get hashCode {
|
||||
final _this = this as WidgetDayInfo;
|
||||
return Object.hash(runtimeType,_this.date,_this.isHoliday,_this.holidayName);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetDayInfo(date: $date, isHoliday: $isHoliday, holidayName: $holidayName)';
|
||||
final _this = this as WidgetDayInfo;
|
||||
return 'WidgetDayInfo(date: ${_this.date}, isHoliday: ${_this.isHoliday}, holidayName: ${_this.holidayName})';
|
||||
}
|
||||
|
||||
|
||||
@@ -653,7 +680,7 @@ class _$WidgetDayInfoCopyWithImpl<$Res>
|
||||
/// Create a copy of WidgetDayInfo
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? isHoliday = null,Object? holidayName = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
return _then(WidgetDayInfo(
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,isHoliday: null == isHoliday ? _self.isHoliday : isHoliday // ignore: cast_nullable_to_non_nullable
|
||||
as bool,holidayName: freezed == holidayName ? _self.holidayName : holidayName // ignore: cast_nullable_to_non_nullable
|
||||
@@ -818,16 +845,18 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetDayInfo&&(identical(other.date, date) || other.date == date)&&(identical(other.isHoliday, isHoliday) || other.isHoliday == isHoliday)&&(identical(other.holidayName, holidayName) || other.holidayName == holidayName));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetDayInfo&&(identical(other.date, date) || other.date == date)&&(identical(other.isHoliday, isHoliday) || other.isHoliday == isHoliday)&&(identical(other.holidayName, holidayName) || other.holidayName == holidayName));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,date,isHoliday,holidayName);
|
||||
int get hashCode {
|
||||
return Object.hash(runtimeType,date,isHoliday,holidayName);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetDayInfo(date: $date, isHoliday: $isHoliday, holidayName: $holidayName)';
|
||||
return 'WidgetDayInfo(date: $date, isHoliday: $isHoliday, holidayName: $holidayName)';
|
||||
}
|
||||
|
||||
|
||||
@@ -888,16 +917,21 @@ $WidgetTimetableDataCopyWith<WidgetTimetableData> get copyWith => _$WidgetTimeta
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetTimetableData&&(identical(other.fetchedAt, fetchedAt) || other.fetchedAt == fetchedAt)&&(identical(other.anchorDate, anchorDate) || other.anchorDate == anchorDate)&&const DeepCollectionEquality().equals(other.lessons, lessons)&&const DeepCollectionEquality().equals(other.periods, periods)&&(identical(other.isHoliday, isHoliday) || other.isHoliday == isHoliday)&&(identical(other.holidayName, holidayName) || other.holidayName == holidayName)&&const DeepCollectionEquality().equals(other.days, days));
|
||||
final _this = this as WidgetTimetableData;
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is WidgetTimetableData&&(identical(other.fetchedAt, _this.fetchedAt) || other.fetchedAt == _this.fetchedAt)&&(identical(other.anchorDate, _this.anchorDate) || other.anchorDate == _this.anchorDate)&&const DeepCollectionEquality().equals(other.lessons, _this.lessons)&&const DeepCollectionEquality().equals(other.periods, _this.periods)&&(identical(other.isHoliday, _this.isHoliday) || other.isHoliday == _this.isHoliday)&&(identical(other.holidayName, _this.holidayName) || other.holidayName == _this.holidayName)&&const DeepCollectionEquality().equals(other.days, _this.days));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,fetchedAt,anchorDate,const DeepCollectionEquality().hash(lessons),const DeepCollectionEquality().hash(periods),isHoliday,holidayName,const DeepCollectionEquality().hash(days));
|
||||
int get hashCode {
|
||||
final _this = this as WidgetTimetableData;
|
||||
return Object.hash(runtimeType,_this.fetchedAt,_this.anchorDate,const DeepCollectionEquality().hash(_this.lessons),const DeepCollectionEquality().hash(_this.periods),_this.isHoliday,_this.holidayName,const DeepCollectionEquality().hash(_this.days));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetTimetableData(fetchedAt: $fetchedAt, anchorDate: $anchorDate, lessons: $lessons, periods: $periods, isHoliday: $isHoliday, holidayName: $holidayName, days: $days)';
|
||||
final _this = this as WidgetTimetableData;
|
||||
return 'WidgetTimetableData(fetchedAt: ${_this.fetchedAt}, anchorDate: ${_this.anchorDate}, lessons: ${_this.lessons}, periods: ${_this.periods}, isHoliday: ${_this.isHoliday}, holidayName: ${_this.holidayName}, days: ${_this.days})';
|
||||
}
|
||||
|
||||
|
||||
@@ -926,7 +960,7 @@ class _$WidgetTimetableDataCopyWithImpl<$Res>
|
||||
/// Create a copy of WidgetTimetableData
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? fetchedAt = null,Object? anchorDate = null,Object? lessons = null,Object? periods = null,Object? isHoliday = null,Object? holidayName = freezed,Object? days = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
return _then(WidgetTimetableData(
|
||||
fetchedAt: null == fetchedAt ? _self.fetchedAt : fetchedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,anchorDate: null == anchorDate ? _self.anchorDate : anchorDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,lessons: null == lessons ? _self.lessons : lessons // ignore: cast_nullable_to_non_nullable
|
||||
@@ -1075,7 +1109,7 @@ return $default(_that.fetchedAt,_that.anchorDate,_that.lessons,_that.periods,_th
|
||||
@JsonSerializable()
|
||||
|
||||
class _WidgetTimetableData implements WidgetTimetableData {
|
||||
const _WidgetTimetableData({required this.fetchedAt, required this.anchorDate, required final List<WidgetLesson> lessons, final List<WidgetPeriod> periods = const <WidgetPeriod>[], this.isHoliday = false, this.holidayName, final List<WidgetDayInfo> days = const <WidgetDayInfo>[]}): _lessons = lessons,_periods = periods,_days = days;
|
||||
const _WidgetTimetableData({required this.fetchedAt, required this.anchorDate, required List<WidgetLesson> lessons, List<WidgetPeriod> periods = const <WidgetPeriod>[], this.isHoliday = false, this.holidayName, List<WidgetDayInfo> days = const <WidgetDayInfo>[]}): _lessons = lessons,_periods = periods,_days = days;
|
||||
factory _WidgetTimetableData.fromJson(Map<String, dynamic> json) => _$WidgetTimetableDataFromJson(json);
|
||||
|
||||
@override final DateTime fetchedAt;
|
||||
@@ -1122,16 +1156,18 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetTimetableData&&(identical(other.fetchedAt, fetchedAt) || other.fetchedAt == fetchedAt)&&(identical(other.anchorDate, anchorDate) || other.anchorDate == anchorDate)&&const DeepCollectionEquality().equals(other._lessons, _lessons)&&const DeepCollectionEquality().equals(other._periods, _periods)&&(identical(other.isHoliday, isHoliday) || other.isHoliday == isHoliday)&&(identical(other.holidayName, holidayName) || other.holidayName == holidayName)&&const DeepCollectionEquality().equals(other._days, _days));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _WidgetTimetableData&&(identical(other.fetchedAt, fetchedAt) || other.fetchedAt == fetchedAt)&&(identical(other.anchorDate, anchorDate) || other.anchorDate == anchorDate)&&const DeepCollectionEquality().equals(other.lessons, _lessons)&&const DeepCollectionEquality().equals(other.periods, _periods)&&(identical(other.isHoliday, isHoliday) || other.isHoliday == isHoliday)&&(identical(other.holidayName, holidayName) || other.holidayName == holidayName)&&const DeepCollectionEquality().equals(other.days, _days));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,fetchedAt,anchorDate,const DeepCollectionEquality().hash(_lessons),const DeepCollectionEquality().hash(_periods),isHoliday,holidayName,const DeepCollectionEquality().hash(_days));
|
||||
int get hashCode {
|
||||
return Object.hash(runtimeType,fetchedAt,anchorDate,const DeepCollectionEquality().hash(_lessons),const DeepCollectionEquality().hash(_periods),isHoliday,holidayName,const DeepCollectionEquality().hash(_days));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WidgetTimetableData(fetchedAt: $fetchedAt, anchorDate: $anchorDate, lessons: $lessons, periods: $periods, isHoliday: $isHoliday, holidayName: $holidayName, days: $days)';
|
||||
return 'WidgetTimetableData(fetchedAt: $fetchedAt, anchorDate: $anchorDate, lessons: $lessons, periods: $periods, isHoliday: $isHoliday, holidayName: $holidayName, days: $days)';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ _WidgetLesson _$WidgetLessonFromJson(Map<String, dynamic> json) =>
|
||||
originalTeacher: json['originalTeacher'] as String?,
|
||||
status: $enumDecode(_$WidgetLessonStatusEnumMap, json['status']),
|
||||
customColor: json['customColor'] as String?,
|
||||
color: json['color'] as String?,
|
||||
siblingCount: (json['siblingCount'] as num?)?.toInt() ?? 0,
|
||||
);
|
||||
|
||||
@@ -31,6 +32,7 @@ Map<String, dynamic> _$WidgetLessonToJson(_WidgetLesson instance) =>
|
||||
'originalTeacher': instance.originalTeacher,
|
||||
'status': _$WidgetLessonStatusEnumMap[instance.status]!,
|
||||
'customColor': instance.customColor,
|
||||
'color': instance.color,
|
||||
'siblingCount': instance.siblingCount,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:rrule/rrule.dart';
|
||||
import 'dart:ui';
|
||||
|
||||
import '../api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays_response.dart';
|
||||
import '../api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms_response.dart';
|
||||
@@ -10,10 +9,14 @@ import '../api/marianumconnect/queries/timetable_get_week/timetable_get_week_res
|
||||
import '../api/mhsl/custom_timetable_event/custom_timetable_event.dart';
|
||||
import '../api/mhsl/custom_timetable_event/get/get_custom_timetable_event_response.dart';
|
||||
import '../extensions/date_time.dart';
|
||||
import '../utils/recurrence_occurrences.dart';
|
||||
import '../view/pages/timetable/data/lesson_color.dart';
|
||||
import '../view/pages/timetable/data/lesson_labels.dart';
|
||||
import '../view/pages/timetable/data/lesson_merger.dart';
|
||||
import '../view/pages/timetable/data/lesson_period_schedule.dart';
|
||||
import '../view/pages/timetable/data/lesson_status.dart';
|
||||
import '../view/pages/timetable/data/lesson_type_label.dart';
|
||||
import '../view/pages/timetable/data/subject_color_palette.dart';
|
||||
import 'widget_data.dart';
|
||||
|
||||
class WidgetDataMapper {
|
||||
@@ -322,20 +325,26 @@ class WidgetDataMapper {
|
||||
}) {
|
||||
final start = lesson.startDateTime;
|
||||
final end = lesson.endDateTime;
|
||||
final status = _mapStatus(
|
||||
LessonStatusClassifier.classify(lesson, start, end, now),
|
||||
);
|
||||
final subjectShortRaw = lesson.subjects.firstOrNull?.trim() ?? '';
|
||||
// Webuntis sometimes ships subject-less entries (Wandertag etc.). Fall
|
||||
// back to "Event" so the tile isn't just a dash.
|
||||
final subjectShort = subjectShortRaw.isEmpty ? 'Event' : subjectShortRaw;
|
||||
String? subjectLong;
|
||||
if (subjects != null && subjectShortRaw.isNotEmpty) {
|
||||
subjectLong = subjects.result
|
||||
.where((s) => s.shortName == subjectShortRaw)
|
||||
.firstOrNull
|
||||
?.longName;
|
||||
}
|
||||
// Gleiche Einstufung wie TimetableAppointmentFactory, damit Aufsicht,
|
||||
// Prüfung & Co. im Widget dieselbe Farbe tragen wie in der App.
|
||||
final lessonStatus = LessonStatusClassifier.classify(
|
||||
lesson,
|
||||
start,
|
||||
end,
|
||||
now,
|
||||
isEvent: subjectShortRaw.isEmpty && lesson.lessonType == 'LESSON',
|
||||
isDuty: lesson.lessonType != 'LESSON',
|
||||
);
|
||||
final subjectShort = subjectShortRaw.isEmpty
|
||||
? LessonTypeLabel.forEntry(lesson)
|
||||
: subjectShortRaw;
|
||||
final subject = subjects == null || subjectShortRaw.isEmpty
|
||||
? null
|
||||
: subjects.result
|
||||
.where((s) => s.shortName == subjectShortRaw)
|
||||
.firstOrNull;
|
||||
final subjectLong = subject?.longName;
|
||||
final roomShort = lesson.rooms.firstOrNull;
|
||||
var roomName = roomShort;
|
||||
if (rooms != null && roomShort != null) {
|
||||
@@ -347,11 +356,12 @@ class WidgetDataMapper {
|
||||
}
|
||||
final teacher = lesson.teachers.firstOrNull;
|
||||
// Lehrerpläne: Klasse in den Teacher-Slot mappen, damit die nativen
|
||||
// Renderer unverändert bleiben. Klassenlose Einträge (Aufsichten) behalten
|
||||
// den Lehrer als Fallback.
|
||||
final classLabel = showClassInsteadOfTeacher ? lesson.classLabel : null;
|
||||
final teacherName = classLabel ?? teacher?.shortName;
|
||||
final originalTeacher = classLabel != null
|
||||
// Renderer unverändert bleiben. Klassenlose Einträge (Aufsichten) lassen
|
||||
// den Slot leer — die Lehrkraft wäre die Plan-Inhaberin selbst.
|
||||
final teacherName = showClassInsteadOfTeacher
|
||||
? lesson.classLabel
|
||||
: teacher?.shortName;
|
||||
final originalTeacher = showClassInsteadOfTeacher
|
||||
? null
|
||||
: teacher?.originalShortName;
|
||||
return WidgetLesson(
|
||||
@@ -362,10 +372,29 @@ class WidgetDataMapper {
|
||||
room: roomName,
|
||||
teacher: teacherName,
|
||||
originalTeacher: originalTeacher,
|
||||
status: status,
|
||||
status: _mapStatus(lessonStatus),
|
||||
color: _hex(_lessonColor(lessonStatus, subject?.color)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Das Widget kennt keine Zeitzustände: laufende Stunden bekommen dieselbe
|
||||
/// Farbe wie reguläre, sonst würde die Hervorhebung zwischen zwei
|
||||
/// Aktualisierungen veralten.
|
||||
static Color _lessonColor(LessonStatus status, String? subjectColor) {
|
||||
final isRegular =
|
||||
status == LessonStatus.regular ||
|
||||
status == LessonStatus.ongoing ||
|
||||
status == LessonStatus.past;
|
||||
if (!isRegular) return LessonColor.forStatus(status);
|
||||
return SubjectColorPalette.colorFromName(subjectColor) ??
|
||||
LessonColor.regular;
|
||||
}
|
||||
|
||||
static String _hex(Color color) {
|
||||
final rgb = color.toARGB32() & 0xFFFFFF;
|
||||
return '#${rgb.toRadixString(16).padLeft(6, '0').toUpperCase()}';
|
||||
}
|
||||
|
||||
static WidgetLessonStatus _mapStatus(LessonStatus status) {
|
||||
switch (status) {
|
||||
case LessonStatus.cancelled:
|
||||
@@ -439,11 +468,13 @@ class WidgetDataMapper {
|
||||
}
|
||||
|
||||
try {
|
||||
final parsed = RecurrenceRule.fromString(rule);
|
||||
final anchorUtc = event.startDate.toUtc();
|
||||
for (final occUtc in parsed.getInstances(start: anchorUtc)) {
|
||||
if (!occUtc.isBefore(rangeEndUtc)) break;
|
||||
if (occUtc.isBefore(rangeStartUtc)) continue;
|
||||
for (final occUtc in RecurrenceOccurrences.between(
|
||||
rule,
|
||||
anchorUtc,
|
||||
rangeStartUtc,
|
||||
rangeEndUtc,
|
||||
)) {
|
||||
final occLocal = occUtc.toLocal();
|
||||
final occStart = DateTime(
|
||||
occLocal.year,
|
||||
@@ -475,6 +506,12 @@ class WidgetDataMapper {
|
||||
subjectLong: title.isEmpty ? null : title,
|
||||
status: WidgetLessonStatus.event,
|
||||
customColor: event.color,
|
||||
color: _hex(
|
||||
SubjectColorPalette.colorFromName(event.color) ??
|
||||
SubjectColorPalette.displayOf(
|
||||
SubjectColorPalette.defaultColor,
|
||||
).color,
|
||||
),
|
||||
);
|
||||
|
||||
final isAllDay = duration == Duration.zero && _isMidnight(event.startDate);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../session/session_manager.dart';
|
||||
import '../state/app/modules/timetable/bloc/timetable_state.dart';
|
||||
import '../state/app/modules/timetable/subject/timetable_subject.dart';
|
||||
import '../storage/settings.dart';
|
||||
@@ -20,23 +22,75 @@ class WidgetPublisher {
|
||||
static DateTime widgetNow() =>
|
||||
kDebugMode ? DateTime.now().add(debugTimeShift) : DateTime.now();
|
||||
|
||||
/// Identical snapshots are still re-written after this long, so the stored
|
||||
/// `fetchedAt` (freshness for the background refresh) doesn't go stale.
|
||||
static const Duration _republishAfter = Duration(minutes: 10);
|
||||
|
||||
static Future<void> _queue = Future.value();
|
||||
static (bool, String, bool, String?)? _lastFlags;
|
||||
static String? _lastSignature;
|
||||
static DateTime? _lastPublishedAt;
|
||||
|
||||
/// Forgets what was written last, so the next publish writes again. Called
|
||||
/// whenever the stored widget data is cleared (sign-out).
|
||||
static void resetDedupe() {
|
||||
_lastFlags = null;
|
||||
_lastSignature = null;
|
||||
_lastPublishedAt = null;
|
||||
}
|
||||
|
||||
/// Publishes run one at a time: they are fire-and-forget from the bloc
|
||||
/// stream, and interleaved writes could leave day and week data from
|
||||
/// different states behind.
|
||||
/// [epoch] is the session the [state] belongs to; defaults to the current
|
||||
/// one. Callers that delay the publish must capture it up front.
|
||||
static Future<void> publishFromBlocState(
|
||||
TimetableState state, {
|
||||
required TimetableSubject subject,
|
||||
Settings? settings,
|
||||
bool showClassInsteadOfTeacher = false,
|
||||
int? epoch,
|
||||
}) {
|
||||
final sessionEpoch = epoch ?? SessionManager().sessionEpoch;
|
||||
return _queue = _queue.then(
|
||||
(_) => _publish(
|
||||
state,
|
||||
subject: subject,
|
||||
settings: settings,
|
||||
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
|
||||
epoch: sessionEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> _publish(
|
||||
TimetableState state, {
|
||||
required TimetableSubject subject,
|
||||
required Settings? settings,
|
||||
required bool showClassInsteadOfTeacher,
|
||||
required int epoch,
|
||||
}) async {
|
||||
if (!SessionManager().isCurrentSession(epoch)) return;
|
||||
try {
|
||||
final connectDouble =
|
||||
settings?.timetableSettings.connectDoubleLessons ?? true;
|
||||
// Mirror into widget storage so the background isolate sees the same
|
||||
// values the user just toggled — concurrently, they are independent.
|
||||
await Future.wait([
|
||||
WidgetSync.setConnectDoubleLessons(connectDouble),
|
||||
WidgetSync.setThemeMode(_themeName(settings?.appTheme)),
|
||||
WidgetSync.setShowClassInsteadOfTeacher(showClassInsteadOfTeacher),
|
||||
WidgetSync.setSubject(subject),
|
||||
]);
|
||||
final flags = (
|
||||
connectDouble,
|
||||
_themeName(settings?.appTheme),
|
||||
showClassInsteadOfTeacher,
|
||||
WidgetSync.encodeSubject(subject),
|
||||
);
|
||||
if (flags != _lastFlags) {
|
||||
await Future.wait([
|
||||
WidgetSync.setConnectDoubleLessons(flags.$1),
|
||||
WidgetSync.setThemeMode(flags.$2),
|
||||
WidgetSync.setShowClassInsteadOfTeacher(flags.$3),
|
||||
WidgetSync.setSubject(subject),
|
||||
]);
|
||||
_lastFlags = flags;
|
||||
}
|
||||
final lessons = state.getAllKnownLessons();
|
||||
final now = widgetNow();
|
||||
final dayData = WidgetDataMapper.buildDayData(
|
||||
@@ -61,6 +115,23 @@ class WidgetPublisher {
|
||||
connectDoubleLessons: connectDouble,
|
||||
showClassInsteadOfTeacher: showClassInsteadOfTeacher,
|
||||
);
|
||||
// A publish still running at sign-out would put the previous account's
|
||||
// plan back onto the just cleared widget.
|
||||
if (!SessionManager().isCurrentSession(epoch)) return;
|
||||
// Most bloc emits (week swipes, prefetches) don't touch the widget's
|
||||
// window; skip the SharedPreferences commits and widget re-render then.
|
||||
final signature = jsonEncode([
|
||||
_withoutFetchedAt(dayData.toJson()),
|
||||
_withoutFetchedAt(weekData.toJson()),
|
||||
]);
|
||||
final lastAt = _lastPublishedAt;
|
||||
if (signature == _lastSignature &&
|
||||
lastAt != null &&
|
||||
now.difference(lastAt) < _republishAfter) {
|
||||
return;
|
||||
}
|
||||
_lastSignature = signature;
|
||||
_lastPublishedAt = now;
|
||||
await WidgetSync.writeDayData(dayData);
|
||||
await WidgetSync.writeWeekData(weekData);
|
||||
await WidgetSync.setLoggedIn(true);
|
||||
@@ -72,6 +143,9 @@ class WidgetPublisher {
|
||||
}
|
||||
}
|
||||
|
||||
static Map<String, Object?> _withoutFetchedAt(Map<String, Object?> json) =>
|
||||
Map.of(json)..remove('fetchedAt');
|
||||
|
||||
static String _themeName(ThemeMode? mode) {
|
||||
switch (mode) {
|
||||
case ThemeMode.light:
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:home_widget/home_widget.dart';
|
||||
|
||||
import '../state/app/modules/timetable/subject/timetable_subject.dart';
|
||||
import 'widget_data.dart';
|
||||
import 'widget_publisher.dart';
|
||||
|
||||
/// Bridge to the native widget host. All keys/names live here so the Kotlin
|
||||
/// and Swift sides stay in sync.
|
||||
@@ -146,6 +147,7 @@ class WidgetSync {
|
||||
}
|
||||
|
||||
static Future<void> clear() async {
|
||||
WidgetPublisher.resetDedupe();
|
||||
await ensureInitialized();
|
||||
await HomeWidget.saveWidgetData<String>(dayDataKey, null);
|
||||
await HomeWidget.saveWidgetData<String>(weekDataKey, null);
|
||||
|
||||
Reference in new issue
Block a user