refactor(ui): 清理 K26 旧 UI 与死代码
This commit is contained in:
1 parent
a5398daab3
commit
5422581f8b
23 files changed
+291
-1225
No files matched your search
@@ -3,7 +3,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../core/data/models/drama.dart';
|
||||
@@ -71,10 +70,8 @@ class PlayerLogic extends ChangeNotifier {
|
||||
bool muted = false;
|
||||
bool stoppedAtFeedEnd = false;
|
||||
VideoPlayerPort? scrubbingPlayer;
|
||||
bool fullscreen = false;
|
||||
bool pip = false;
|
||||
bool pipPreparing = false;
|
||||
bool screenCleared = false;
|
||||
final Map<String, int> pickedEpisode = {};
|
||||
|
||||
bool Function() isMounted = () => false;
|
||||
@@ -98,9 +95,9 @@ class PlayerLogic extends ChangeNotifier {
|
||||
/// dispose 不能直接碰它们(例如页面构建失败或纯逻辑测试)。
|
||||
bool _started = false;
|
||||
|
||||
bool get immersive => fullscreen || pip || pipPreparing;
|
||||
bool get immersive => pip || pipPreparing;
|
||||
|
||||
bool get chromeHidden => immersive || screenCleared;
|
||||
bool get chromeHidden => immersive;
|
||||
|
||||
Episode displayEpisode(Drama drama, Episode fallback) {
|
||||
final number = pickedEpisode[drama.id];
|
||||
@@ -111,13 +108,6 @@ class PlayerLogic extends ChangeNotifier {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
void setScreenCleared(bool value) {
|
||||
if (screenCleared == value) return;
|
||||
screenCleared = value;
|
||||
notify();
|
||||
notifyImmersive();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
if (!_disposed) notifyListeners();
|
||||
}
|
||||
@@ -262,13 +252,7 @@ class PlayerLogic extends ChangeNotifier {
|
||||
final request = backRequest;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (isMounted() && backRequest == request) {
|
||||
if (fullscreen) {
|
||||
unawaited(setFullscreen(false));
|
||||
} else if (screenCleared) {
|
||||
setScreenCleared(false);
|
||||
} else {
|
||||
onMenu?.call();
|
||||
}
|
||||
onMenu?.call();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -295,12 +279,6 @@ class PlayerLogic extends ChangeNotifier {
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
pictureInPicture.setStateListener(null);
|
||||
if (fullscreen) {
|
||||
unawaited(
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]),
|
||||
);
|
||||
unawaited(SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge));
|
||||
}
|
||||
unawaited(saveCurrentProgress());
|
||||
if (_started) {
|
||||
session.setRouteVisible(false);
|
||||
@@ -313,32 +291,6 @@ class PlayerLogic extends ChangeNotifier {
|
||||
|
||||
void notifyImmersive() => onImmersiveChanged?.call(chromeHidden);
|
||||
|
||||
Future<void> setFullscreen(bool value) async {
|
||||
if (fullscreen == value || !isMounted()) return;
|
||||
fullscreen = value;
|
||||
notify();
|
||||
notifyImmersive();
|
||||
try {
|
||||
await SystemChrome.setPreferredOrientations(
|
||||
value
|
||||
? [
|
||||
DeviceOrientation.landscapeLeft,
|
||||
DeviceOrientation.landscapeRight,
|
||||
]
|
||||
: [DeviceOrientation.portraitUp],
|
||||
);
|
||||
await SystemChrome.setEnabledSystemUIMode(
|
||||
value ? SystemUiMode.immersiveSticky : SystemUiMode.edgeToEdge,
|
||||
);
|
||||
} catch (_) {
|
||||
if (value && isMounted()) {
|
||||
fullscreen = false;
|
||||
notify();
|
||||
notifyImmersive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> enterPip(BuildContext context) async {
|
||||
if (pip || pipPreparing) return;
|
||||
if (session.active is! VideoPlayerPort) {
|
||||
@@ -347,7 +299,6 @@ class PlayerLogic extends ChangeNotifier {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (fullscreen) await setFullscreen(false);
|
||||
pipPreparing = true;
|
||||
notify();
|
||||
notifyImmersive();
|
||||
|
||||
@@ -162,7 +162,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
||||
logic.session.preparedPlayerAt(index);
|
||||
final videoPort = port is VideoPlayerPort ? port : null;
|
||||
final ready = videoPort?.controller.value.isInitialized ?? false;
|
||||
final theater = logic.fullscreen || logic.pip || logic.pipPreparing;
|
||||
final theater = logic.pip || logic.pipPreparing;
|
||||
Widget? video;
|
||||
if (ready) {
|
||||
video = GestureDetector(
|
||||
@@ -322,20 +322,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
||||
),
|
||||
if (logic.pip || logic.pipPreparing)
|
||||
const SizedBox.expand()
|
||||
else if (logic.fullscreen)
|
||||
_FullscreenControls(
|
||||
l10n: l10n,
|
||||
controller: ready ? videoPort!.controller : null,
|
||||
onClose: () => unawaited(logic.setFullscreen(false)),
|
||||
onPip: logic.pictureInPicture.isPlatformSupported
|
||||
? () => unawaited(logic.enterPip(context))
|
||||
: null,
|
||||
onScrubStart: ready ? () => logic.beginScrub(videoPort!) : null,
|
||||
onSeek: ready
|
||||
? (position) => logic.seekTo(context, videoPort!, position)
|
||||
: null,
|
||||
)
|
||||
else if (!logic.screenCleared && widget.homeMode)
|
||||
else if (widget.homeMode)
|
||||
HomeFeedOverlay(
|
||||
l10n: l10n,
|
||||
drama: drama,
|
||||
@@ -375,13 +362,12 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
||||
onShare: () => logic.shareDrama(context, drama),
|
||||
onEpisodes: () => logic.showEpisodes(context),
|
||||
onDownload: () => requestEpisodeDownload(context, episode.id),
|
||||
onClear: () => logic.setScreenCleared(true),
|
||||
onSearch: widget.onSearch ?? () => logic.showDiscover(context),
|
||||
onPip: logic.pictureInPicture.isPlatformSupported
|
||||
? () => unawaited(logic.enterPip(context))
|
||||
: null,
|
||||
)
|
||||
else if (!logic.screenCleared)
|
||||
else
|
||||
_PlaybackOverlay(
|
||||
l10n: l10n,
|
||||
drama: drama,
|
||||
@@ -441,81 +427,11 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
|
||||
? (position) => logic.seekTo(context, videoPort!, position)
|
||||
: null,
|
||||
),
|
||||
if (logic.screenCleared)
|
||||
SafeArea(
|
||||
child: Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 4, right: 8),
|
||||
child: IconButton(
|
||||
tooltip: l10n.exitClearScreen,
|
||||
onPressed: () => logic.setScreenCleared(false),
|
||||
style: IconButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0x59000000),
|
||||
),
|
||||
icon: const Icon(Icons.close_fullscreen_rounded),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _FullscreenControls extends StatelessWidget {
|
||||
const _FullscreenControls({
|
||||
required this.l10n,
|
||||
required this.controller,
|
||||
required this.onClose,
|
||||
required this.onPip,
|
||||
required this.onScrubStart,
|
||||
required this.onSeek,
|
||||
});
|
||||
|
||||
final AppLocalizations l10n;
|
||||
final VideoPlayerController? controller;
|
||||
final VoidCallback onClose;
|
||||
final VoidCallback? onPip;
|
||||
final VoidCallback? onScrubStart;
|
||||
final Future<void> Function(Duration)? onSeek;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: l10n.exitFullscreen,
|
||||
onPressed: onClose,
|
||||
icon: const Icon(Icons.close_fullscreen_rounded),
|
||||
),
|
||||
const Spacer(),
|
||||
if (onPip != null)
|
||||
IconButton(
|
||||
tooltip: l10n.pictureInPicture,
|
||||
onPressed: onPip,
|
||||
icon: const Icon(Icons.picture_in_picture_alt_outlined),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 16),
|
||||
child: SeekProgressBar(
|
||||
valueListenable: controller,
|
||||
semanticsLabel: l10n.seekVideo,
|
||||
onScrubStart: onScrubStart,
|
||||
onSeek: onSeek,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 不可播放提示:文案由后端返回的 `accessType` 驱动(契约 §1.4),前端不自行推断。
|
||||
class _BlockedNotice extends StatelessWidget {
|
||||
const _BlockedNotice({
|
||||
|
||||
@@ -26,7 +26,6 @@ class HomeFeedOverlay extends StatelessWidget {
|
||||
required this.onShare,
|
||||
required this.onEpisodes,
|
||||
required this.onDownload,
|
||||
required this.onClear,
|
||||
required this.onSearch,
|
||||
this.onPip,
|
||||
});
|
||||
@@ -42,7 +41,6 @@ class HomeFeedOverlay extends StatelessWidget {
|
||||
final VoidCallback onShare;
|
||||
final VoidCallback onEpisodes;
|
||||
final VoidCallback onDownload;
|
||||
final VoidCallback onClear;
|
||||
final VoidCallback onSearch;
|
||||
final VoidCallback? onPip;
|
||||
|
||||
@@ -332,18 +330,6 @@ class HomeFeedOverlay extends StatelessWidget {
|
||||
onPip!();
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
key: const Key('home-feed-clear'),
|
||||
leading: const Icon(
|
||||
Icons.fit_screen_outlined,
|
||||
color: AppColors.secondary,
|
||||
),
|
||||
title: Text(l10n.clearScreen),
|
||||
onTap: () {
|
||||
Navigator.pop(sheetContext);
|
||||
onClear();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user