深色模式、首页设置页面和功能优化

This commit is contained in:
Developer
2026-04-02 07:06:55 +08:00
parent f0a62ed68b
commit 954d173329
88 changed files with 12157 additions and 7578 deletions

View File

@@ -0,0 +1,394 @@
/// 时间: 2026-03-29
/// 功能: 首页自动刷新管理
/// 介绍: 管理首页诗句自动刷新功能,包括定时器、状态管理等
/// 最新变化: 新建文件
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../utils/http/poetry_api.dart';
import '../../../../constants/app_constants.dart';
class SecondaryButtonsManager {
static const String _hideSecondaryButtonsKey = 'hide_secondary_buttons';
static SecondaryButtonsManager? _instance;
bool _isHidden = false;
final ValueNotifier<bool> _hiddenNotifier = ValueNotifier<bool>(false);
SecondaryButtonsManager._internal();
factory SecondaryButtonsManager() {
_instance ??= SecondaryButtonsManager._internal();
return _instance!;
}
Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
_isHidden = prefs.getBool(_hideSecondaryButtonsKey) ?? false;
_hiddenNotifier.value = _isHidden;
}
bool get isHidden => _isHidden;
ValueNotifier<bool> get hiddenNotifier => _hiddenNotifier;
Future<void> setHidden(bool hidden) async {
_isHidden = hidden;
_hiddenNotifier.value = hidden;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_hideSecondaryButtonsKey, hidden);
}
void dispose() {
_hiddenNotifier.value = false;
}
}
class AutoRefreshManager {
static const String _autoRefreshKey = 'auto_refresh_enabled';
static const Duration _refreshInterval = Duration(seconds: 5);
static AutoRefreshManager? _instance;
Timer? _refreshTimer;
bool _isEnabled = false;
VoidCallback? _onRefresh;
final ValueNotifier<bool> _enabledNotifier = ValueNotifier<bool>(false);
AutoRefreshManager._internal();
factory AutoRefreshManager() {
_instance ??= AutoRefreshManager._internal();
return _instance!;
}
Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
_isEnabled = prefs.getBool(_autoRefreshKey) ?? false;
_enabledNotifier.value = _isEnabled;
if (_isEnabled) {
_startTimer();
}
}
bool get isEnabled => _isEnabled;
ValueNotifier<bool> get enabledNotifier => _enabledNotifier;
Future<void> setEnabled(bool enabled) async {
_isEnabled = enabled;
_enabledNotifier.value = enabled;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_autoRefreshKey, enabled);
if (enabled) {
_startTimer();
} else {
_stopTimer();
}
}
void setOnRefresh(VoidCallback? callback) {
_onRefresh = callback;
}
void _startTimer() {
_stopTimer();
_refreshTimer = Timer.periodic(_refreshInterval, (timer) {
if (_onRefresh != null) {
_onRefresh!();
}
});
}
void _stopTimer() {
if (_refreshTimer != null) {
_refreshTimer!.cancel();
_refreshTimer = null;
}
}
void stopTimer() {
_stopTimer();
}
void dispose() {
_stopTimer();
_onRefresh = null;
}
}
class DebugInfoManager {
static const String _debugInfoKey = 'debug_info_enabled';
static DebugInfoManager? _instance;
bool _isEnabled = false;
final ValueNotifier<bool> _enabledNotifier = ValueNotifier<bool>(false);
DebugInfoManager._internal();
factory DebugInfoManager() {
_instance ??= DebugInfoManager._internal();
return _instance!;
}
Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
_isEnabled = prefs.getBool(_debugInfoKey) ?? false;
_enabledNotifier.value = _isEnabled;
}
bool get isEnabled => _isEnabled;
ValueNotifier<bool> get enabledNotifier => _enabledNotifier;
Future<void> setEnabled(bool enabled) async {
_isEnabled = enabled;
_enabledNotifier.value = enabled;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_debugInfoKey, enabled);
}
void showMessage(String message) {
if (!_isEnabled) return;
Get.snackbar(
'调试信息',
message,
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.transparent,
colorText: Colors.white,
duration: const Duration(seconds: 2),
margin: const EdgeInsets.all(16),
borderRadius: 20,
animationDuration: const Duration(milliseconds: 300),
snackbarStatus: (status) {},
maxWidth: Get.width - 32,
overlayBlur: 0.1,
overlayColor: Colors.transparent,
isDismissible: true,
padding: EdgeInsets.zero,
shouldIconPulse: false,
barBlur: 20,
// backgroundColor: Colors.black.withValues(alpha: 0.15),
);
}
void showRefreshSuccess() {
showMessage('刷新成功');
}
void showRefreshFailed() {
showMessage('刷新失败');
}
void showNextSuccess() {
showMessage('下一条成功');
}
void showNextFailed() {
showMessage('下一条失败');
}
void showPreviousSuccess() {
showMessage('上一条成功');
}
void showPreviousFailed() {
showMessage('上一条失败');
}
void showLiked() {
showMessage('已点赞');
}
void showUnliked() {
showMessage('已取消点赞');
}
void showCopySuccess() {
showMessage('复制成功');
}
void showCopyFailed() {
showMessage('复制失败');
}
void dispose() {}
}
class OfflineDataManager {
static const String _offlineDataKey = 'offline_poetry_data';
static const String _onlineStatusKey = 'personal_card_online';
static OfflineDataManager? _instance;
List<Map<String, dynamic>> _cachedPoetryList = [];
int _currentIndex = 0;
OfflineDataManager._internal();
factory OfflineDataManager() {
_instance ??= OfflineDataManager._internal();
return _instance!;
}
Future<void> init() async {
await _loadCachedData();
}
Future<bool> isOnline() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(_onlineStatusKey) ?? true;
}
Future<bool> hasCachedData() async {
await _loadCachedData();
return _cachedPoetryList.isNotEmpty;
}
Future<PoetryData?> getNextPoetry() async {
await _loadCachedData();
if (_cachedPoetryList.isEmpty) {
return null;
}
final poetryData = _cachedPoetryList[_currentIndex];
_currentIndex = (_currentIndex + 1) % _cachedPoetryList.length;
return _convertToPoetryData(poetryData);
}
Future<PoetryData?> getPreviousPoetry() async {
await _loadCachedData();
if (_cachedPoetryList.isEmpty) {
return null;
}
_currentIndex =
(_currentIndex - 1 + _cachedPoetryList.length) %
_cachedPoetryList.length;
final poetryData = _cachedPoetryList[_currentIndex];
return _convertToPoetryData(poetryData);
}
Future<void> _loadCachedData() async {
final prefs = await SharedPreferences.getInstance();
final cachedData = prefs.getStringList(_offlineDataKey) ?? [];
_cachedPoetryList = [];
for (final item in cachedData) {
try {
// 移除 Map 两边的大括号,然后分割键值对
final cleanItem = item.substring(1, item.length - 1);
final keyValuePairs = cleanItem.split(', ');
final map = <String, dynamic>{};
for (final pair in keyValuePairs) {
final parts = pair.split(': ');
if (parts.length == 2) {
final key = parts[0].replaceAll('"', '');
var value = parts[1].replaceAll('"', '');
// 尝试转换数字
if (int.tryParse(value) != null) {
map[key] = int.parse(value);
} else if (double.tryParse(value) != null) {
map[key] = double.parse(value);
} else {
map[key] = value;
}
}
}
_cachedPoetryList.add(map);
} catch (e) {
// 解析失败
}
}
}
PoetryData? _convertToPoetryData(Map<String, dynamic> data) {
try {
final id = data['id'] ?? 0;
final name = data['name'] ?? '';
final alias = data['alias'] ?? '';
final keywords = data['keywords'] ?? '';
final introduce = data['introduce'] ?? '';
final drtime = data['drtime'] ?? '';
final like = data['like'] ?? 0;
final url = data['url'] ?? '';
final tui = data['tui'] ?? 0;
final star = data['star'] ?? 5;
final hitsTotal = data['hitsTotal'] ?? 0;
final hitsMonth = data['hitsMonth'] ?? 0;
final hitsDay = data['hitsDay'] ?? 0;
final date = data['date'] ?? '';
final datem = data['datem'] ?? '';
final time = data['time'] ?? '';
final createTime = data['createTime'] ?? '';
final updateTime = data['updateTime'] ?? '';
return PoetryData(
id: id,
name: name,
alias: alias,
keywords: keywords,
introduce: introduce,
drtime: drtime,
like: like,
url: url,
tui: tui,
star: star,
hitsTotal: hitsTotal,
hitsMonth: hitsMonth,
hitsDay: hitsDay,
date: date,
datem: datem,
time: time,
createTime: createTime,
updateTime: updateTime,
);
} catch (e) {
return null;
}
}
}
class GlobalTipsManager {
static const String _globalTipsKey = 'global_tips_enabled';
static GlobalTipsManager? _instance;
bool _isEnabled = true;
final ValueNotifier<bool> _enabledNotifier = ValueNotifier<bool>(true);
GlobalTipsManager._internal();
factory GlobalTipsManager() {
_instance ??= GlobalTipsManager._internal();
return _instance!;
}
Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
_isEnabled = prefs.getBool(_globalTipsKey) ?? true;
_enabledNotifier.value = _isEnabled;
}
bool get isEnabled => _isEnabled;
ValueNotifier<bool> get enabledNotifier => _enabledNotifier;
Future<void> setEnabled(bool enabled) async {
_isEnabled = enabled;
_enabledNotifier.value = enabled;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_globalTipsKey, enabled);
}
void dispose() {
_enabledNotifier.value = true;
}
}