Files
xianyan/lib/core/services/notification/notification_scheduler.dart
Developer c44457f94c style: 修复文件头部注释的多余BOM头字符
移除所有文件头部的不可见BOM前缀字符,统一文件头部注释格式,确保跨平台编译一致性
2026-05-27 08:05:47 +08:00

421 lines
12 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// ============================================================
/// 闲言APP — 通知调度器
/// 创建时间: 2026-05-02
/// 更新时间: 2026-05-22
/// 作用: 统一管理本地通知调度 (每日推荐/签到/节气/番茄钟/运势/学习进度)
/// 上次更新: @Deprecated 已合并至NotificationCenter请使用NotificationCenter替代
/// ============================================================
import 'local_notification_service.dart';
import '../../storage/kv_storage.dart';
import '../../utils/logger.dart';
@Deprecated('已合并至NotificationCenter请使用NotificationCenter替代')
class NotificationScheduler {
NotificationScheduler._();
static const _keyNotificationsEnabled = 'notifications_enabled';
static const _keyDailySentenceEnabled = 'daily_sentence_enabled';
static const _keySigninReminderEnabled = 'signin_reminder_enabled';
static const _keySolarTermEnabled = 'solar_term_enabled';
static const _keyDailySentenceHour = 'daily_sentence_hour';
static const _keyDailySentenceMinute = 'daily_sentence_minute';
static const _keySigninReminderHour = 'signin_reminder_hour';
static const _keySigninReminderMinute = 'signin_reminder_minute';
static const _keyFortuneEnabled = 'fortune_enabled';
static const _keyFortuneHour = 'fortune_hour';
static const _keyFortuneMinute = 'fortune_minute';
static const _keyStudyProgressEnabled = 'study_progress_enabled';
static Future<void> _cancelAllManaged() async {
await LocalNotificationService.cancel(1001);
await LocalNotificationService.cancel(1002);
await LocalNotificationService.cancel(1003);
await LocalNotificationService.cancel(1004);
await LocalNotificationService.cancel(2001);
}
static Future<void> configureAll() async {
final enabled = KvStorage.getBool(_keyNotificationsEnabled) ?? false;
if (!enabled) {
await _cancelAllManaged();
Log.i('通知调度: 通知已关闭,取消所有调度');
return;
}
await _cancelAllManaged();
final dailySentence = KvStorage.getBool(_keyDailySentenceEnabled) ?? true;
if (dailySentence) {
final hour = KvStorage.getInt(_keyDailySentenceHour) ?? 8;
final minute = KvStorage.getInt(_keyDailySentenceMinute) ?? 0;
await LocalNotificationService.scheduleDaily(
id: 1001,
title: '闲言每日一句',
body: '今天的句子已准备好,来看看吧 ✨',
hour: hour,
minute: minute,
payload: 'daily_sentence',
);
}
final signinReminder =
KvStorage.getBool(_keySigninReminderEnabled) ?? true;
if (signinReminder) {
final hour = KvStorage.getInt(_keySigninReminderHour) ?? 20;
final minute = KvStorage.getInt(_keySigninReminderMinute) ?? 0;
await LocalNotificationService.scheduleDaily(
id: 1002,
title: '闲言 · 签到提醒',
body: '别忘了今日签到哦 📝',
hour: hour,
minute: minute,
payload: 'signin_reminder',
);
}
final solarTerm = KvStorage.getBool(_keySolarTermEnabled) ?? true;
if (solarTerm) {
await _scheduleNextSolarTerm();
}
final fortune = KvStorage.getBool(_keyFortuneEnabled) ?? false;
if (fortune) {
final hour = KvStorage.getInt(_keyFortuneHour) ?? 8;
final minute = KvStorage.getInt(_keyFortuneMinute) ?? 0;
await LocalNotificationService.scheduleDaily(
id: 1003,
title: '闲言 · 🔮 每日运势',
body: '今日运势已生成,快来看看你的运势吧 ✨',
hour: hour,
minute: minute,
payload: 'daily_fortune',
);
}
final studyProgress = KvStorage.getBool(_keyStudyProgressEnabled) ?? false;
if (studyProgress) {
await LocalNotificationService.scheduleDaily(
id: 1004,
title: '闲言 · 学习进度',
body: '该复习今天的学习内容了 📊',
hour: 20,
payload: 'study_progress',
);
}
Log.i('通知调度: 所有通知已配置');
}
static Future<void> _scheduleNextSolarTerm() async {
final nextTerm = _getNextSolarTerm();
if (nextTerm == null) return;
final scheduledTime = DateTime(
nextTerm['year'] as int,
nextTerm['month'] as int,
nextTerm['day'] as int,
8,
);
await LocalNotificationService.scheduleOnce(
id: 2001,
title: '闲言 · ${nextTerm['emoji']} ${nextTerm['name']}',
body: '今日${nextTerm['name']}${nextTerm['poem']}',
scheduledTime: scheduledTime,
payload: 'solar_term',
);
}
static Map<String, dynamic>? _getNextSolarTerm() {
final now = DateTime.now();
final terms = _solarTerms2026;
for (final term in terms) {
final date = DateTime(
term['year'] as int,
term['month'] as int,
term['day'] as int,
);
if (date.isAfter(now)) return term;
}
return terms.isNotEmpty ? terms.first : null;
}
static bool get isNotificationsEnabled =>
KvStorage.getBool(_keyNotificationsEnabled) ?? false;
static bool get isDailySentenceEnabled =>
KvStorage.getBool(_keyDailySentenceEnabled) ?? true;
static bool get isSigninReminderEnabled =>
KvStorage.getBool(_keySigninReminderEnabled) ?? true;
static bool get isSolarTermEnabled =>
KvStorage.getBool(_keySolarTermEnabled) ?? true;
static int get dailySentenceHour =>
KvStorage.getInt(_keyDailySentenceHour) ?? 8;
static int get dailySentenceMinute =>
KvStorage.getInt(_keyDailySentenceMinute) ?? 0;
static int get signinReminderHour =>
KvStorage.getInt(_keySigninReminderHour) ?? 20;
static int get signinReminderMinute =>
KvStorage.getInt(_keySigninReminderMinute) ?? 0;
static bool get isFortuneEnabled =>
KvStorage.getBool(_keyFortuneEnabled) ?? false;
static int get fortuneHour => KvStorage.getInt(_keyFortuneHour) ?? 8;
static int get fortuneMinute => KvStorage.getInt(_keyFortuneMinute) ?? 0;
static bool get isStudyProgressEnabled =>
KvStorage.getBool(_keyStudyProgressEnabled) ?? false;
static Future<void> setNotificationsEnabled(bool v) async {
await KvStorage.setBool(_keyNotificationsEnabled, v);
await configureAll();
}
static Future<void> setDailySentenceEnabled(bool v) async {
await KvStorage.setBool(_keyDailySentenceEnabled, v);
await configureAll();
}
static Future<void> setSigninReminderEnabled(bool v) async {
await KvStorage.setBool(_keySigninReminderEnabled, v);
await configureAll();
}
static Future<void> setSolarTermEnabled(bool v) async {
await KvStorage.setBool(_keySolarTermEnabled, v);
await configureAll();
}
static Future<void> setDailySentenceTime(int hour, int minute) async {
await KvStorage.setInt(_keyDailySentenceHour, hour);
await KvStorage.setInt(_keyDailySentenceMinute, minute);
await configureAll();
}
static Future<void> setSigninReminderTime(int hour, int minute) async {
await KvStorage.setInt(_keySigninReminderHour, hour);
await KvStorage.setInt(_keySigninReminderMinute, minute);
await configureAll();
}
static Future<void> setFortuneEnabled(bool v) async {
await KvStorage.setBool(_keyFortuneEnabled, v);
await configureAll();
}
static Future<void> setFortuneTime(int hour, int minute) async {
await KvStorage.setInt(_keyFortuneHour, hour);
await KvStorage.setInt(_keyFortuneMinute, minute);
await configureAll();
}
static Future<void> setStudyProgressEnabled(bool v) async {
await KvStorage.setBool(_keyStudyProgressEnabled, v);
await configureAll();
}
static final List<Map<String, dynamic>> _solarTerms2026 = [
{
'year': 2026,
'month': 1,
'day': 5,
'name': '小寒',
'emoji': '❄️',
'poem': '小寒连大吕,欢鹊垒新巢',
},
{
'year': 2026,
'month': 1,
'day': 20,
'name': '大寒',
'emoji': '🧊',
'poem': '大寒须守火,无事不出门',
},
{
'year': 2026,
'month': 2,
'day': 4,
'name': '立春',
'emoji': '🌱',
'poem': '春风如贵客,一到便繁华',
},
{
'year': 2026,
'month': 2,
'day': 18,
'name': '雨水',
'emoji': '🌧️',
'poem': '好雨知时节,当春乃发生',
},
{
'year': 2026,
'month': 3,
'day': 5,
'name': '惊蛰',
'emoji': '',
'poem': '微雨众卉新,一雷惊蛰始',
},
{
'year': 2026,
'month': 3,
'day': 20,
'name': '春分',
'emoji': '🌸',
'poem': '雪入春分省见稀,半开桃李不胜威',
},
{
'year': 2026,
'month': 4,
'day': 5,
'name': '清明',
'emoji': '🍃',
'poem': '清明时节雨纷纷,路上行人欲断魂',
},
{
'year': 2026,
'month': 4,
'day': 20,
'name': '谷雨',
'emoji': '🌾',
'poem': '谷雨如丝复似尘,煮瓶浮蜡正尝新',
},
{
'year': 2026,
'month': 5,
'day': 5,
'name': '立夏',
'emoji': '☀️',
'poem': '绿树阴浓夏日长,楼台倒影入池塘',
},
{
'year': 2026,
'month': 5,
'day': 21,
'name': '小满',
'emoji': '🌿',
'poem': '夜莺啼绿柳,皓月醒长空',
},
{
'year': 2026,
'month': 6,
'day': 5,
'name': '芒种',
'emoji': '🌻',
'poem': '时雨及芒种,四野皆插秧',
},
{
'year': 2026,
'month': 6,
'day': 21,
'name': '夏至',
'emoji': '🌞',
'poem': '昼晷已云极,宵漏自此长',
},
{
'year': 2026,
'month': 7,
'day': 7,
'name': '小暑',
'emoji': '🌡️',
'poem': '倏忽温风至,因循小暑来',
},
{
'year': 2026,
'month': 7,
'day': 22,
'name': '大暑',
'emoji': '🔥',
'poem': '大暑三秋近,林钟九夏移',
},
{
'year': 2026,
'month': 8,
'day': 7,
'name': '立秋',
'emoji': '🍂',
'poem': '乳鸦啼散玉屏空,一枕新凉一扇风',
},
{
'year': 2026,
'month': 8,
'day': 23,
'name': '处暑',
'emoji': '🎐',
'poem': '处暑无三日,新凉直万金',
},
{
'year': 2026,
'month': 9,
'day': 7,
'name': '白露',
'emoji': '💎',
'poem': '露从今夜白,月是故乡明',
},
{
'year': 2026,
'month': 9,
'day': 23,
'name': '秋分',
'emoji': '🍁',
'poem': '金气秋分,风清露冷秋期半',
},
{
'year': 2026,
'month': 10,
'day': 8,
'name': '寒露',
'emoji': '💧',
'poem': '袅袅凉风动,凄凄寒露零',
},
{
'year': 2026,
'month': 10,
'day': 23,
'name': '霜降',
'emoji': '🧊',
'poem': '霜降碧天静,秋事促西风',
},
{
'year': 2026,
'month': 11,
'day': 7,
'name': '立冬',
'emoji': '🧣',
'poem': '冻笔新诗懒写,寒炉美酒时温',
},
{
'year': 2026,
'month': 11,
'day': 22,
'name': '小雪',
'emoji': '🌨️',
'poem': '片片互玲珑,飞扬玉漏终',
},
{
'year': 2026,
'month': 12,
'day': 7,
'name': '大雪',
'emoji': '❄️',
'poem': '大雪江南见未曾,今年方始是严凝',
},
{
'year': 2026,
'month': 12,
'day': 21,
'name': '冬至',
'emoji': '🥟',
'poem': '天时人事日相催,冬至阳生春又来',
},
];
}