fix(player): 解锁状态登录期内共享,重进播放页不再丢解锁

解锁记录原本是播放页实例的私有集合,退出再进入会先闪一次锁定态,还会
被 selectLocked 提前释放播放器。改为进程内共享的 UnlockedEpisodeRegistry,
由全局注入并在登录态变化时清空;播放器三处渲染分支统一走同一判定,
会话锁态只约束当前页,避免相邻预加载页被误判为锁定。
This commit is contained in:
Zhou Weidong authored and trae-solo-agent committed 2026-10-29 10:44:44 +08:00
1 parent a4d08e7c1e
commit 57f84c45bd
6 files changed
+103 -18

No files matched your search

@@ -8,6 +8,7 @@ import 'package:fruitshorts/core/data/repositories/commerce_repository.dart';
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
import 'package:fruitshorts/core/data/services/android_picture_in_picture.dart';
import 'package:fruitshorts/core/data/services/playback_session.dart';
import 'package:fruitshorts/core/data/services/unlocked_episode_registry.dart';
import 'package:fruitshorts/core/data/services/wallet_controller.dart';
import 'package:fruitshorts/pages/player/player_logic.dart';
import 'package:fruitshorts/pages/player/player_view.dart';
@@ -120,6 +121,36 @@ void main() {
logic.dispose();
await _drain(logic);
});
test('should_keep_episode_unlocked_when_reentering_player_page', () async {
final registry = UnlockedEpisodeRegistry();
registry.markUnlocked('locked-1');
final playback = FakePlaybackRepository(
ticket: const PlayTicket(
episodeId: 'locked-1',
accessible: true,
accessType: 'ENTITLED',
playUrl: '/files/locked-1.mp4',
),
);
// 重进播放页 = 新建 PlayerLogic,但沿用同一张解锁登记表。
final logic = _logic(playback, unlockedEpisodes: registry);
logic.attach(
const PlayerPage(drama: _lockedDrama, initialIndex: 0),
isMounted: () => true,
);
logic.start(
factory: (_) => _NoopPlayer(),
coordinator: PlaybackCoordinator(),
);
await _drain(logic);
expect(logic.isEpisodeLocked(logic.sessionEpisodes.single), isFalse);
expect(logic.session.active, isNotNull);
logic.dispose();
await _drain(logic);
});
}
PlayerLogic _logic(
@@ -127,11 +158,13 @@ PlayerLogic _logic(
bool signedIn = true,
bool Function()? isSignedIn,
WalletController? wallet,
UnlockedEpisodeRegistry? unlockedEpisodes,
}) {
return PlayerLogic(
history: FakeWatchHistory(),
playback: playback,
wallet: wallet,
unlockedEpisodes: unlockedEpisodes,
pictureInPicture: AndroidPictureInPicture(
channel: const MethodChannel('test/player_locked_auth_flow/pip'),
),