Files
huangguo_android/lib/hj_utils/history_util.dart
T
2026-09-15 15:44:13 +07:00

126 lines
5.2 KiB
Dart
Raw 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.
import 'dart:convert';
import 'package:hgdj/hj_model/home/collection_model.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/hj_utils/const.dart';
import 'package:hgdj/tools_base/cache/history/base_history_record_store.dart';
import 'package:hgdj/tools_base/cache/history/cartoon_history_store.dart';
import 'package:hgdj/tools_base/cache/history/comics_history_store.dart';
import 'package:hgdj/tools_base/cache/history/community_history_store.dart';
import 'package:hgdj/tools_base/cache/history/game_history_store.dart';
import 'package:hgdj/tools_base/cache/history/novel_history_store.dart';
import 'package:hgdj/tools_base/cache/history/pic_history_store.dart';
import 'package:hgdj/tools_base/cache/history/search_history_store.dart';
import 'package:hgdj/tools_base/cache/history/short_video_history_store.dart';
import 'package:hgdj/tools_base/cache/history/video_history_store.dart';
import 'package:hgdj/tools_base/debug_log.dart';
import '../hj_model/cartoon_media_info.dart';
/// 浏览历史 + 搜索历史的统一入口。按 [MediaStyle] 派发到各自的 store,业务层不直接碰 store
class HistoryUtil {
/// 每种类型独占一个 db 文件,store 自身是单例。返回 null = 该类型不记历史
static BaseHistoryRecordStore? _storeOf(MediaStyle type) => switch (type) {
MediaStyle.Video => VideoHistoryStore(),
MediaStyle.ShortVideo => ShortVideoHistoryStore(),
MediaStyle.Comics => ComicsHistoryStore(),
MediaStyle.Cartoon => CartoonHistoryStore(),
MediaStyle.Novel => NovelHistoryStore(),
MediaStyle.Community => CommunityHistoryStore(),
MediaStyle.Pic => PicHistoryStore(),
MediaStyle.Game => GameHistoryStore(),
// 短剧的观看历史和续播位置是同一张表,走 DramaResumeStore;其余是当前业务无浏览历史需求的类型
MediaStyle.Drama ||
MediaStyle.Area ||
MediaStyle.Seed ||
MediaStyle.Actress ||
MediaStyle.NakedChat ||
MediaStyle.GroupChat =>
null,
};
/// 插入浏览历史(已存在则刷新到最前;超上限自动删最旧,上限见 BaseHistoryRecordStore.maxRows
static Future<void> insert(Object? model, MediaStyle type) async {
try {
final json = _toJson(model);
if (json == null) {
//类型没在 _toJson/_idOf 里登记 → 静默不记历史。入参是 Object? 编译期拦不住,只能靠日志暴露
debugLog('HistoryUtil.insert 未登记的类型', model?.runtimeType);
return;
}
final id = _idOf(model);
final store = _storeOf(type);
if (id == null || id.isEmpty || store == null) return;
await store.save(modelId: id, modelDataJson: jsonEncode(json));
} catch (e) {
debugLog('HistoryUtil.insert', e);
}
}
/// 删除单条浏览历史
static Future<void> delete(Object? model, MediaStyle type) async {
try {
final id = _idOf(model);
if (id == null) {
debugLog('HistoryUtil.delete 未登记的类型', model?.runtimeType);
return;
}
final store = _storeOf(type);
if (id.isEmpty || store == null) return;
await store.remove(id);
} catch (e) {
debugLog('HistoryUtil.delete', e);
}
}
/// 指定类型的浏览历史(按时间倒序,分页)。解析不出的条目直接丢弃,不让一条脏数据废掉整页
static Future<List<T>> fetch<T>(MediaStyle type,
{int page = 1, int pageSize = 20}) async {
try {
final store = _storeOf(type);
if (store == null) return <T>[];
final jsonList = await store.fetch(page: page, pageSize: pageSize);
return jsonList.map((e) => _fromJson<T>(e)).whereType<T>().toList();
} catch (e) {
debugLog('HistoryUtil.fetch', e);
return <T>[];
}
}
/// 三个 _xxx 按实例匹配,新增可记历史的 model 时这里和 [_fromJson] 一起加一行
static String? _idOf(Object? model) => switch (model) {
VideoModel m => m.id,
CartoonMediaInfo m => m.id,
CollectionModel m => m.id,
_ => null,
};
static Map<String, dynamic>? _toJson(Object? model) => switch (model) {
VideoModel m => m.toJson(),
CartoonMediaInfo m => m.toJson(),
CollectionModel m => m.toJson(),
_ => null,
};
/// 反序列化只能按 [T] 分派(拿不到实例)。**必须用 T == 类型比较**:
/// 靠 T.toString() 对类名在 release 混淆后必然失配,表现是列表静默空白
static T? _fromJson<T>(String raw) {
final json = Map<String, dynamic>.from(jsonDecode(raw));
if (T == VideoModel) return VideoModel.fromJson(json) as T;
if (T == CartoonMediaInfo) return CartoonMediaInfo.fromJson(json) as T;
if (T == CollectionModel) return CollectionModel.fromJson(json) as T;
return null;
}
//搜索历史(按时间倒序)
static Future<List<String>> searchHistories() =>
SearchHistoryStore().fetchAll();
//新增一条搜索历史(已存在则去重提到最前,超上限自动删最旧)
static Future<void> addSearch(String keyword) =>
SearchHistoryStore().save(keyword);
//清空搜索历史
static Future<void> clearSearch() => SearchHistoryStore().clean();
}