merge: 共享清屏状态并左贴集数
This commit is contained in:
commit
5ca5846a26
4 files changed
+78
-50
No files matched your search
@@ -71,7 +71,7 @@ class PlayerPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
||||||
late final PlayerLogic logic;
|
late final PlayerLogic logic;
|
||||||
bool _feedChromeVisible = true;
|
bool _chromeVisible = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -190,7 +190,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
children: [
|
children: [
|
||||||
const ColoredBox(color: AppColors.ink),
|
const ColoredBox(color: AppColors.ink),
|
||||||
?video,
|
?video,
|
||||||
if (!logic.chromeHidden && (!widget.homeMode || _feedChromeVisible))
|
if (!logic.chromeHidden && (!widget.homeMode || _chromeVisible))
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
key: widget.homeMode ? const Key('home-feed-scrim') : null,
|
key: widget.homeMode ? const Key('home-feed-scrim') : null,
|
||||||
child: const DecoratedBox(
|
child: const DecoratedBox(
|
||||||
@@ -209,7 +209,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.homeMode && _feedChromeVisible && !logic.chromeHidden)
|
if (widget.homeMode && _chromeVisible && !logic.chromeHidden)
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
key: const Key('home-feed-video-toggle'),
|
key: const Key('home-feed-video-toggle'),
|
||||||
@@ -317,7 +317,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
if (logic.pip || logic.pipPreparing)
|
if (logic.pip || logic.pipPreparing)
|
||||||
const SizedBox.expand()
|
const SizedBox.expand()
|
||||||
else if (widget.homeMode)
|
else if (widget.homeMode)
|
||||||
_feedChromeVisible
|
_chromeVisible
|
||||||
? HomeFeedOverlay(
|
? HomeFeedOverlay(
|
||||||
l10n: l10n,
|
l10n: l10n,
|
||||||
drama: drama,
|
drama: drama,
|
||||||
@@ -359,7 +359,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
onShare: () => logic.shareDrama(context, drama),
|
onShare: () => logic.shareDrama(context, drama),
|
||||||
onEpisodes: () => logic.showEpisodes(context),
|
onEpisodes: () => logic.showEpisodes(context),
|
||||||
onDownload: () => requestEpisodeDownload(context, episode.id),
|
onDownload: () => requestEpisodeDownload(context, episode.id),
|
||||||
onClear: () => setState(() => _feedChromeVisible = false),
|
onClear: () => setState(() => _chromeVisible = false),
|
||||||
onSearch:
|
onSearch:
|
||||||
widget.onSearch ?? () => logic.showDiscover(context),
|
widget.onSearch ?? () => logic.showDiscover(context),
|
||||||
onPip: logic.pictureInPicture.isPlatformSupported
|
onPip: logic.pictureInPicture.isPlatformSupported
|
||||||
@@ -384,6 +384,9 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
? () => unawaited(logic.playNextEpisode())
|
? () => unawaited(logic.playNextEpisode())
|
||||||
: null,
|
: null,
|
||||||
playing: logic.session.userWantsPlay,
|
playing: logic.session.userWantsPlay,
|
||||||
|
controlsVisible: _chromeVisible,
|
||||||
|
onClear: () => setState(() => _chromeVisible = false),
|
||||||
|
onExitClear: () => setState(() => _chromeVisible = true),
|
||||||
onTogglePlay: () =>
|
onTogglePlay: () =>
|
||||||
logic.session.setUserWantsPlay(!logic.session.userWantsPlay),
|
logic.session.setUserWantsPlay(!logic.session.userWantsPlay),
|
||||||
// 收藏/点赞要对到具体账号:未登录先引导登录(首页/详情仍可匿名浏览)
|
// 收藏/点赞要对到具体账号:未登录先引导登录(首页/详情仍可匿名浏览)
|
||||||
@@ -427,7 +430,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
? (position) => logic.seekTo(context, videoPort!, position)
|
? (position) => logic.seekTo(context, videoPort!, position)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
if (widget.homeMode && !_feedChromeVisible)
|
if (widget.homeMode && !_chromeVisible)
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
key: const Key('home-feed-video-tap'),
|
key: const Key('home-feed-video-tap'),
|
||||||
@@ -436,7 +439,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
logic.session.setUserWantsPlay(!logic.session.userWantsPlay),
|
logic.session.setUserWantsPlay(!logic.session.userWantsPlay),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.homeMode && !_feedChromeVisible)
|
if (widget.homeMode && !_chromeVisible)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
@@ -447,7 +450,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
|||||||
child: ExitClearScreenButton(
|
child: ExitClearScreenButton(
|
||||||
key: const Key('home-feed-exit-clear-screen'),
|
key: const Key('home-feed-exit-clear-screen'),
|
||||||
tooltip: l10n.exitClearScreen,
|
tooltip: l10n.exitClearScreen,
|
||||||
onPressed: () => setState(() => _feedChromeVisible = true),
|
onPressed: () => setState(() => _chromeVisible = true),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -599,7 +602,10 @@ class _PlaybackOverlay extends StatefulWidget {
|
|||||||
required this.liked,
|
required this.liked,
|
||||||
required this.saved,
|
required this.saved,
|
||||||
required this.playing,
|
required this.playing,
|
||||||
|
required this.controlsVisible,
|
||||||
required this.onTogglePlay,
|
required this.onTogglePlay,
|
||||||
|
required this.onClear,
|
||||||
|
required this.onExitClear,
|
||||||
required this.onBack,
|
required this.onBack,
|
||||||
required this.onEpisodes,
|
required this.onEpisodes,
|
||||||
required this.onComments,
|
required this.onComments,
|
||||||
@@ -620,7 +626,10 @@ class _PlaybackOverlay extends StatefulWidget {
|
|||||||
final bool liked;
|
final bool liked;
|
||||||
final bool saved;
|
final bool saved;
|
||||||
final bool playing;
|
final bool playing;
|
||||||
|
final bool controlsVisible;
|
||||||
final VoidCallback onTogglePlay;
|
final VoidCallback onTogglePlay;
|
||||||
|
final VoidCallback onClear;
|
||||||
|
final VoidCallback onExitClear;
|
||||||
final VoidCallback? onBack;
|
final VoidCallback? onBack;
|
||||||
final VoidCallback onEpisodes;
|
final VoidCallback onEpisodes;
|
||||||
final VoidCallback onComments;
|
final VoidCallback onComments;
|
||||||
@@ -638,14 +647,6 @@ class _PlaybackOverlay extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlaybackOverlayState extends State<_PlaybackOverlay> {
|
class _PlaybackOverlayState extends State<_PlaybackOverlay> {
|
||||||
bool _controlsVisible = true;
|
|
||||||
|
|
||||||
void _onVideoTap() {
|
|
||||||
widget.onTogglePlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _clearScreen() => setState(() => _controlsVisible = false);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
@@ -655,10 +656,10 @@ class _PlaybackOverlayState extends State<_PlaybackOverlay> {
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
key: const Key('player-video-tap'),
|
key: const Key('player-video-tap'),
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: _onVideoTap,
|
onTap: widget.onTogglePlay,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_controlsVisible)
|
if (widget.controlsVisible)
|
||||||
Column(
|
Column(
|
||||||
key: const Key('player-controls-visible'),
|
key: const Key('player-controls-visible'),
|
||||||
children: [
|
children: [
|
||||||
@@ -766,14 +767,14 @@ class _PlaybackOverlayState extends State<_PlaybackOverlay> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (!_controlsVisible)
|
if (!widget.controlsVisible)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 8,
|
top: 8,
|
||||||
right: 12,
|
right: 12,
|
||||||
child: ExitClearScreenButton(
|
child: ExitClearScreenButton(
|
||||||
key: const Key('player-exit-clear-screen'),
|
key: const Key('player-exit-clear-screen'),
|
||||||
tooltip: widget.l10n.exitClearScreen,
|
tooltip: widget.l10n.exitClearScreen,
|
||||||
onPressed: () => setState(() => _controlsVisible = true),
|
onPressed: widget.onExitClear,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!widget.playing)
|
if (!widget.playing)
|
||||||
@@ -828,7 +829,7 @@ class _PlaybackOverlayState extends State<_PlaybackOverlay> {
|
|||||||
key: const Key('player-clear-screen'),
|
key: const Key('player-clear-screen'),
|
||||||
tooltip: widget.l10n.clearScreen,
|
tooltip: widget.l10n.clearScreen,
|
||||||
icon: Icons.fullscreen_rounded,
|
icon: Icons.fullscreen_rounded,
|
||||||
onPressed: _clearScreen,
|
onPressed: widget.onClear,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
_TopAction(
|
_TopAction(
|
||||||
|
|||||||
@@ -167,38 +167,27 @@ class HomeFeedOverlay extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Wrap(
|
||||||
|
spacing: 6,
|
||||||
|
runSpacing: 4,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
if (genre.isNotEmpty)
|
||||||
child: Wrap(
|
_tag(
|
||||||
spacing: 6,
|
genre,
|
||||||
runSpacing: 4,
|
background: AppColors.blue,
|
||||||
children: [
|
foreground: AppColors.onPrimary,
|
||||||
if (genre.isNotEmpty)
|
|
||||||
_tag(
|
|
||||||
genre,
|
|
||||||
background: AppColors.blue,
|
|
||||||
foreground: AppColors.onPrimary,
|
|
||||||
),
|
|
||||||
if (drama.category.isNotEmpty && drama.category != genre)
|
|
||||||
_tag(
|
|
||||||
drama.category,
|
|
||||||
background: const Color(0xFF333333),
|
|
||||||
foreground: const Color(0xFFDDDDDD),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
if (drama.category.isNotEmpty && drama.category != genre)
|
||||||
const SizedBox(width: 8),
|
_tag(
|
||||||
Flexible(
|
drama.category,
|
||||||
child: Text(
|
background: const Color(0xFF333333),
|
||||||
l10n.episodeOfTotal(episode.number, drama.episodeCount),
|
foreground: const Color(0xFFDDDDDD),
|
||||||
key: const Key('home-feed-episode'),
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
style: const TextStyle(color: Color(0xFFBBBBBB), fontSize: 9),
|
|
||||||
),
|
),
|
||||||
|
Text(
|
||||||
|
l10n.episodeOfTotal(episode.number, drama.episodeCount),
|
||||||
|
key: const Key('home-feed-episode'),
|
||||||
|
style: const TextStyle(color: Color(0xFFBBBBBB), fontSize: 9),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ void main() {
|
|||||||
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
|
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
|
||||||
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget);
|
||||||
expect(find.byKey(const Key('home-feed-episode')), findsOneWidget);
|
expect(find.byKey(const Key('home-feed-episode')), findsOneWidget);
|
||||||
|
final cardRect = tester.getRect(
|
||||||
|
find.byKey(const Key('home-feed-info-card')),
|
||||||
|
);
|
||||||
|
final episodeRect = tester.getRect(
|
||||||
|
find.byKey(const Key('home-feed-episode')),
|
||||||
|
);
|
||||||
|
expect(episodeRect.left, lessThan(cardRect.center.dx));
|
||||||
expect(find.byKey(const Key('home-feed-follow-series')), findsOneWidget);
|
expect(find.byKey(const Key('home-feed-follow-series')), findsOneWidget);
|
||||||
expect(find.byKey(const Key('home-feed-episodes')), findsOneWidget);
|
expect(find.byKey(const Key('home-feed-episodes')), findsOneWidget);
|
||||||
for (final key in const [Key('home-feed-search'), Key('home-feed-more')]) {
|
for (final key in const [Key('home-feed-search'), Key('home-feed-more')]) {
|
||||||
|
|||||||
@@ -216,6 +216,37 @@ void main() {
|
|||||||
expect(tester.takeException(), isNull);
|
expect(tester.takeException(), isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('should_keep_series_clear_state_when_swiping_next_episode', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
await _pumpApp(tester);
|
||||||
|
await tester.binding.handlePopRoute();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.binding.handlePopRoute();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.byKey(const Key('drawer-open-series')));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.byKey(const Key('detail-cta')));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(find.byKey(const Key('player-clear-screen')));
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||||
|
|
||||||
|
await tester.drag(find.byType(PageView), const Offset(0, -550));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.byKey(const Key('player-controls-top')), findsNothing);
|
||||||
|
expect(find.byKey(const Key('player-controls-bottom')), findsNothing);
|
||||||
|
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.byKey(const Key('player-exit-clear-screen')));
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.byKey(const Key('player-controls-top')), findsOneWidget);
|
||||||
|
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
|
||||||
|
expect(find.byKey(const Key('player-exit-clear-screen')), findsNothing);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('should_clear_and_restore_home_feed_chrome', (tester) async {
|
testWidgets('should_clear_and_restore_home_feed_chrome', (tester) async {
|
||||||
await _pumpApp(tester);
|
await _pumpApp(tester);
|
||||||
await tester.tap(find.byKey(const Key('tab-home')));
|
await tester.tap(find.byKey(const Key('tab-home')));
|
||||||
|
|||||||
Reference in new issue
Block a user