Files
Qlyra/lib/core/config/app_theme_schedule.dart

96 lines
3.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../utils/format.dart';
class ThemeSchedule {
final TimeOfDay darkStart;
final TimeOfDay darkEnd;
const ThemeSchedule({required this.darkStart, required this.darkEnd});
bool isDarkAt(DateTime now) {
final nowMin = now.hour * 60 + now.minute;
final startMin = darkStart.hour * 60 + darkStart.minute;
final endMin = darkEnd.hour * 60 + darkEnd.minute;
if (startMin == endMin) return false;
if (startMin < endMin) {
return nowMin >= startMin && nowMin < endMin;
}
return nowMin >= startMin || nowMin < endMin;
}
Duration durationUntilNextSwitch(DateTime now) {
final nowMin = now.hour * 60 + now.minute;
final startMin = darkStart.hour * 60 + darkStart.minute;
final endMin = darkEnd.hour * 60 + darkEnd.minute;
int? nextMin;
for (final m in [startMin, endMin]) {
final delta = (m - nowMin + 1440) % 1440;
final candidate = delta == 0 ? 1440 : delta;
if (nextMin == null || candidate < nextMin) nextMin = candidate;
}
final secondsLeft = (nextMin ?? 1) * 60 - now.second;
return Duration(seconds: secondsLeft.clamp(1, 24 * 60 * 60));
}
}
class AppThemeSchedule {
static const prefKey = 'app_theme_schedule';
static const _defaultStart = TimeOfDay(hour: 22, minute: 0);
static const _defaultEnd = TimeOfDay(hour: 7, minute: 0);
static final ValueNotifier<ThemeSchedule> current = ValueNotifier(
const ThemeSchedule(darkStart: _defaultStart, darkEnd: _defaultEnd),
);
static Future<ThemeSchedule> load() async {
final prefs = await SharedPreferences.getInstance();
final value = _parse(prefs.getString(prefKey));
current.value = value;
return value;
}
static Future<void> save(ThemeSchedule schedule) async {
current.value = schedule;
final prefs = await SharedPreferences.getInstance();
await prefs.setString(
prefKey,
'${_fmt(schedule.darkStart)}-${_fmt(schedule.darkEnd)}',
);
}
static String _fmt(TimeOfDay t) => '${pad2(t.hour)}:${pad2(t.minute)}';
static ThemeSchedule _parse(String? val) {
if (val == null) {
return const ThemeSchedule(
darkStart: _defaultStart,
darkEnd: _defaultEnd,
);
}
final parts = val.split('-');
if (parts.length != 2) {
return const ThemeSchedule(
darkStart: _defaultStart,
darkEnd: _defaultEnd,
);
}
final start = _parseTime(parts[0]) ?? _defaultStart;
final end = _parseTime(parts[1]) ?? _defaultEnd;
return ThemeSchedule(darkStart: start, darkEnd: end);
}
static TimeOfDay? _parseTime(String val) {
final parts = val.split(':');
if (parts.length != 2) return null;
final h = int.tryParse(parts[0]);
final m = int.tryParse(parts[1]);
if (h == null || m == null) return null;
if (h < 0 || h > 23 || m < 0 || m > 59) return null;
return TimeOfDay(hour: h, minute: m);
}
static String format(TimeOfDay t) => _fmt(t);
}