1
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../core/log/action_logger.dart';
|
||||
import '../core/network/api_client.dart';
|
||||
import '../core/network/api_exception.dart';
|
||||
import '../core/storage/token_store.dart';
|
||||
@@ -46,6 +47,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
try {
|
||||
final user = await UserService.fetchMe();
|
||||
state = AuthState(user: user, restored: true);
|
||||
ActionLogger.I.bindUser(user.email);
|
||||
} on ApiException catch (e) {
|
||||
// 仅 Token 确认失效(1002)才清理回游客态;
|
||||
// 网络异常等情况保留 Token,下次启动/请求重试恢复
|
||||
@@ -62,9 +64,12 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
/// 需补拉全量资料,否则积分显示为 0、编辑资料保存会把服务端字段清空。
|
||||
Future<void> onLoginSuccess(UserModel user) async {
|
||||
state = AuthState(user: user, restored: true);
|
||||
ActionLogger.I.bindUser(user.email);
|
||||
try {
|
||||
final full = await UserService.fetchMe();
|
||||
state = state.copyWith(user: full);
|
||||
// 全量资料里的 email 字段更权威(用户可能登录后改过邮箱)
|
||||
ActionLogger.I.bindUser(full.email);
|
||||
} catch (_) {
|
||||
// 补拉失败不影响登录态,保留简要信息
|
||||
}
|
||||
@@ -75,11 +80,13 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
|
||||
/// 退出登录:先通知服务端注销(失败忽略,本地照常清理),再清空登录态
|
||||
Future<void> logout() async {
|
||||
ActionLogger.I.log('logout', page: 'mine');
|
||||
try {
|
||||
await AuthService.logout();
|
||||
} catch (_) {
|
||||
// 服务端已不可达或 Token 已失效:本地清理即可
|
||||
}
|
||||
ActionLogger.I.unbind();
|
||||
await _clearLocal();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@ enum FeedStrategy {
|
||||
latest('latest', '最新'),
|
||||
hot('hot', '热度'),
|
||||
liked('liked', '口碑'),
|
||||
viewed('viewed', '热播');
|
||||
viewed('viewed', '热播'),
|
||||
// 搜索播放专用策略:数据由搜索页注入,不走网络 refresh;
|
||||
// 顶部 Tab 不显示该项,仅作为独立播放器池存在
|
||||
search('search', '搜索');
|
||||
|
||||
const FeedStrategy(this.apiValue, this.label);
|
||||
|
||||
@@ -106,7 +109,10 @@ class FeedState {
|
||||
class FeedNotifier extends StateNotifier<FeedState> {
|
||||
FeedNotifier(this._ref, this.strategy) : super(const FeedState()) {
|
||||
pool = FeedPlayerPool(onWatchComplete: _onWatchComplete)..init();
|
||||
refresh();
|
||||
// search 策略由外部 injectItems 灌入数据,不走网络 refresh
|
||||
if (strategy != FeedStrategy.search) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
final Ref _ref;
|
||||
@@ -123,6 +129,8 @@ class FeedNotifier extends StateNotifier<FeedState> {
|
||||
|
||||
/// 刷新(首屏 / 下拉 / 切策略)
|
||||
Future<void> refresh() async {
|
||||
// search 策略不支持下拉刷新(数据由搜索页注入)
|
||||
if (strategy == FeedStrategy.search) return;
|
||||
state = state.copyWith(isRefreshing: true, loadFailed: false);
|
||||
try {
|
||||
final page = await VideoService.fetchFeed(type: strategy.apiValue);
|
||||
@@ -142,6 +150,8 @@ class FeedNotifier extends StateNotifier<FeedState> {
|
||||
|
||||
/// 加载更多(游标分页)
|
||||
Future<void> loadMore() async {
|
||||
// search 策略暂不支持自动加载更多(如需要可由搜索页同步注入新数据)
|
||||
if (strategy == FeedStrategy.search) return;
|
||||
if (!state.hasMore || state.isLoadingMore) return;
|
||||
state = state.copyWith(isLoadingMore: true);
|
||||
try {
|
||||
@@ -159,6 +169,16 @@ class FeedNotifier extends StateNotifier<FeedState> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 外部数据注入(仅 search 策略用):把搜索结果整列表灌入并定位到点击的那一条。
|
||||
/// 池子由 SearchFeedScreen 独占,注入后立即绑定播放。
|
||||
Future<void> injectItems(List<VideoItem> items, int initialIndex) async {
|
||||
if (strategy != FeedStrategy.search) return;
|
||||
if (items.isEmpty) return;
|
||||
final index = initialIndex.clamp(0, items.length - 1);
|
||||
state = FeedState(items: items, currentIndex: index);
|
||||
await _bindAndReport(index);
|
||||
}
|
||||
|
||||
/// 从全屏播放器返回后恢复:stopAll 清空了槽位,重新绑定当前页并播放。
|
||||
/// 不上报观看(本次进入 Feed 时已上报过,且 _bindAndReport 有按日去重)。
|
||||
Future<void> rebindCurrent() async {
|
||||
|
||||
Reference in New Issue
Block a user