此提交包含多项变更: 1. 新增鸿蒙平台支持,完善设备检测与数据库适配 2. 替换旧版分享插件API为SharePlus 3. 批量迁移StateNotifier到Notifier以适配新版Riverpod 4. 修复zip编码判断、图表API参数等bug 5. 更新应用图标、启动页资源与多尺寸适配图标 6. 调整Android最小SDK版本与应用名称 7. 优化日志打印与正则表达式使用 8. 修正编辑器画布样式初始化与配置逻辑 9. 更新依赖与CI插件配置
105 lines
3.0 KiB
Dart
105 lines
3.0 KiB
Dart
// ============================================================
|
|
// 闲言APP — 学习打卡状态管理
|
|
// 创建时间: 2026-04-29
|
|
// 更新时间: 2026-04-29
|
|
// 作用: 打卡/打卡记录状态管理
|
|
// 上次更新: 初始创建
|
|
// ============================================================
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../../core/utils/logger.dart';
|
|
import '../models/achievement_models.dart';
|
|
import '../services/achievement_service.dart';
|
|
|
|
class CheckinState {
|
|
const CheckinState({
|
|
this.isLoading = false,
|
|
this.isChecking = false,
|
|
this.error,
|
|
this.records = const [],
|
|
this.checkinResult,
|
|
this.page = 1,
|
|
this.hasMore = true,
|
|
});
|
|
|
|
final bool isLoading;
|
|
final bool isChecking;
|
|
final String? error;
|
|
final List<CheckinRecord> records;
|
|
final Map<String, dynamic>? checkinResult;
|
|
final int page;
|
|
final bool hasMore;
|
|
|
|
CheckinState copyWith({
|
|
bool? isLoading,
|
|
bool? isChecking,
|
|
String? error,
|
|
bool clearError = false,
|
|
List<CheckinRecord>? records,
|
|
Map<String, dynamic>? checkinResult,
|
|
bool clearCheckinResult = false,
|
|
int? page,
|
|
bool? hasMore,
|
|
}) {
|
|
return CheckinState(
|
|
isLoading: isLoading ?? this.isLoading,
|
|
isChecking: isChecking ?? this.isChecking,
|
|
error: clearError ? null : (error ?? this.error),
|
|
records: records ?? this.records,
|
|
checkinResult:
|
|
clearCheckinResult ? null : (checkinResult ?? this.checkinResult),
|
|
page: page ?? this.page,
|
|
hasMore: hasMore ?? this.hasMore,
|
|
);
|
|
}
|
|
}
|
|
|
|
class CheckinNotifier extends Notifier<CheckinState> {
|
|
@override
|
|
CheckinState build() => const CheckinState();
|
|
CheckinNotifier();
|
|
|
|
/// 加载打卡记录
|
|
Future<void> loadRecords({bool refresh = false}) async {
|
|
if (isLoading && !refresh) return;
|
|
final page = refresh ? 1 : state.page;
|
|
state = state.copyWith(isLoading: true, clearError: true, page: page);
|
|
|
|
try {
|
|
final records =
|
|
await AchievementService.getCheckinRecords(page: page);
|
|
state = state.copyWith(
|
|
records: refresh ? records : [...state.records, ...records],
|
|
isLoading: false,
|
|
page: page + 1,
|
|
hasMore: records.length >= 20,
|
|
);
|
|
} catch (e) {
|
|
Log.e('加载打卡记录失败', e);
|
|
state = state.copyWith(isLoading: false, error: '加载失败');
|
|
}
|
|
}
|
|
|
|
/// 执行打卡
|
|
Future<bool> checkin({required String type, String? content, int duration = 300}) async {
|
|
state = state.copyWith(isChecking: true, clearCheckinResult: true);
|
|
try {
|
|
final result =
|
|
await AchievementService.checkin(type: type, content: content, duration: duration);
|
|
state = state.copyWith(isChecking: false, checkinResult: result);
|
|
await loadRecords(refresh: true);
|
|
return true;
|
|
} catch (e) {
|
|
Log.e('打卡失败', e);
|
|
state = state.copyWith(isChecking: false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool get isLoading => state.isLoading;
|
|
}
|
|
|
|
final checkinProvider =
|
|
NotifierProvider<CheckinNotifier, CheckinState>(CheckinNotifier.new);
|