78 lines
2.6 KiB
Dart
78 lines
2.6 KiB
Dart
import 'dart:developer';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../state/app/modules/timetable/bloc/timetable_state.dart';
|
|
import '../storage/settings.dart';
|
|
import 'widget_data_mapper.dart';
|
|
import 'widget_sync.dart';
|
|
|
|
/// Pushes timetable state to the native widget whenever the foreground bloc
|
|
/// has fresh data, so the widget doesn't have to wait for the next periodic
|
|
/// background fetch.
|
|
class WidgetPublisher {
|
|
/// Debug-only "now" offset. Gated by [kDebugMode] so a stray non-zero
|
|
/// value cannot ship in release.
|
|
static const Duration debugTimeShift = Duration.zero;
|
|
|
|
static DateTime widgetNow() =>
|
|
kDebugMode ? DateTime.now().add(debugTimeShift) : DateTime.now();
|
|
|
|
static Future<void> publishFromBlocState(
|
|
TimetableState state, {
|
|
Settings? settings,
|
|
}) async {
|
|
try {
|
|
final connectDouble =
|
|
settings?.timetableSettings.connectDoubleLessons ?? true;
|
|
// Mirror into widget storage so the background isolate sees the same
|
|
// value the user just toggled.
|
|
await WidgetSync.setConnectDoubleLessons(connectDouble);
|
|
await WidgetSync.setThemeMode(_themeName(settings?.appTheme));
|
|
final lessons = state.getAllKnownLessons();
|
|
final now = widgetNow();
|
|
final dayData = WidgetDataMapper.buildDayData(
|
|
now: now,
|
|
lessons: lessons,
|
|
subjects: state.subjects,
|
|
rooms: state.rooms,
|
|
holidays: state.schoolHolidays,
|
|
timegrid: state.timegrid,
|
|
customEvents: state.customEvents,
|
|
connectDoubleLessons: connectDouble,
|
|
);
|
|
final weekData = WidgetDataMapper.buildWeekData(
|
|
now: now,
|
|
lessons: lessons,
|
|
subjects: state.subjects,
|
|
rooms: state.rooms,
|
|
holidays: state.schoolHolidays,
|
|
timegrid: state.timegrid,
|
|
customEvents: state.customEvents,
|
|
connectDoubleLessons: connectDouble,
|
|
);
|
|
await WidgetSync.writeDayData(dayData);
|
|
await WidgetSync.writeWeekData(weekData);
|
|
await WidgetSync.setLoggedIn(true);
|
|
await WidgetSync.triggerUpdate();
|
|
} on Object catch (e, s) {
|
|
// Catch Object: non-Exception Errors (RangeError, StateError) from the
|
|
// bloc layer must not escape into the stream listener.
|
|
log('WidgetPublisher.publishFromBlocState failed: $e', stackTrace: s);
|
|
}
|
|
}
|
|
|
|
static String _themeName(ThemeMode? mode) {
|
|
switch (mode) {
|
|
case ThemeMode.light:
|
|
return 'light';
|
|
case ThemeMode.dark:
|
|
return 'dark';
|
|
case ThemeMode.system:
|
|
case null:
|
|
return 'system';
|
|
}
|
|
}
|
|
}
|