refactor(navigation): 移除全局两侧悬浮元素

This commit is contained in:
Zhou Weidong committed 2026-10-22 17:58:43 +08:00
1 parent 5cead7ce00
commit 9cf832b318
8 files changed
+103 -217

No files matched your search

+15 -70
View File
@@ -5,11 +5,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../core/data/models/drama.dart';
import '../../core/data/models/watch_progress.dart';
import '../../core/data/repositories/watch_history_repository.dart';
import '../../core/data/services/auth_controller.dart';
import '../../core/data/services/catalog_controller.dart';
import '../../core/data/services/locale_controller.dart';
import '../../core/data/services/wallet_controller.dart';
import '../../core/theme/app_colors.dart';
@@ -23,7 +20,6 @@ import '../downloads/downloads_page.dart';
import '../account/account_profile_page.dart';
import '../filter/filter_page.dart';
import '../notices/notices_page.dart';
import '../player/open_player.dart';
import '../settings/settings_page.dart';
import '../store/vip_page.dart';
import '../wallet/wallet_page.dart';
@@ -33,7 +29,6 @@ import 'mine_logic.dart';
import 'mine_types.dart';
import 'widgets/mine_header.dart';
import 'widgets/mine_menu.dart';
import 'widgets/mine_mini_player.dart';
/// K28-B 我的页。
class MyPage extends StatefulWidget {
@@ -52,7 +47,6 @@ class MyPage extends StatefulWidget {
class _MyPageState extends State<MyPage> {
late final MineLogic logic;
bool _miniDismissed = false;
bool get embedded => widget.callbacks.embedded;
@@ -133,44 +127,23 @@ class _MyPageState extends State<MyPage> {
Widget _body(BuildContext context, AppLocalizations l10n) {
final locale = context.watch<LocaleController>();
final recent = _miniRecord;
return Stack(
return ListView(
key: const Key('mine-page-scroll'),
padding: const EdgeInsets.fromLTRB(
AppDimens.pageHorizontal,
0,
AppDimens.pageHorizontal,
AppDimens.spaceXl,
),
children: [
Positioned.fill(
child: ListView(
key: const Key('mine-page-scroll'),
padding: EdgeInsets.fromLTRB(
AppDimens.pageHorizontal,
0,
AppDimens.pageHorizontal,
recent == null ? AppDimens.spaceXl : 156,
),
children: [
MineHeader(onLogin: _openLogin, onEdit: _openEditActions),
MineVipBanner(
onOpen: () => _openDestination(MineDestination.vip),
),
const SizedBox(height: AppDimens.spaceMd),
MineMenuList(
onOpen: _openDestination,
onLanguage: _openLanguage,
languageLabel: _languageLabel(l10n, locale.locale),
),
],
),
MineHeader(onLogin: _openLogin, onEdit: _openEditActions),
MineVipBanner(onOpen: () => _openDestination(MineDestination.vip)),
const SizedBox(height: AppDimens.spaceMd),
MineMenuList(
onOpen: _openDestination,
onLanguage: _openLanguage,
languageLabel: _languageLabel(l10n, locale.locale),
),
if (recent != null)
Positioned(
left: AppDimens.pageHorizontal,
bottom: AppDimens.spaceMd,
child: MineMiniPlayer(
title: _miniTitle(l10n, recent),
coverUrl: recent.dramaCover?.trim() ?? '',
episodeLabel: l10n.episodeLabel(recent.episodeNumber ?? 0),
onTap: () => unawaited(_openRecent(recent)),
onClose: () => setState(() => _miniDismissed = true),
),
),
],
);
}
@@ -300,34 +273,6 @@ class _MyPageState extends State<MyPage> {
await context.read<LocaleController>().select(selected);
}
WatchProgress? get _miniRecord {
if (_miniDismissed || logic.recent.isEmpty) return null;
final recent = logic.recent.first;
return recent.episodeId.isEmpty ? null : recent;
}
String _miniTitle(AppLocalizations l10n, WatchProgress recent) {
final title = recent.dramaTitle?.trim() ?? '';
return title.isEmpty ? l10n.episodeLabel(recent.episodeNumber ?? 0) : title;
}
Future<void> _openRecent(WatchProgress recent) async {
final catalog = context.read<CatalogController>();
final seed = Drama(
id: recent.dramaId,
title: recent.dramaTitle?.trim() ?? '',
synopsis: '',
posterUrl: recent.dramaCover?.trim() ?? '',
);
try {
final detail = await catalog.requireDetail(seed);
if (!mounted) return;
await playDramaFromCatalog(context, detail, episodeId: recent.episodeId);
} catch (_) {
// 最近记录失效时不投射错误页,等待下一次记录刷新。
}
}
Widget _bottomNav() {
return AppRootBottomNav(
selected: AppRootTab.mine,
@@ -1,124 +0,0 @@
// Author: fruit.com.cn
import 'package:flutter/material.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_dimens.dart';
import '../../../core/widgets/remote_image.dart';
const double _infoHeight = 42;
/// 「我的」页左下角最近观看迷你播放器。
class MineMiniPlayer extends StatelessWidget {
const MineMiniPlayer({
super.key,
required this.title,
required this.coverUrl,
required this.episodeLabel,
required this.onTap,
required this.onClose,
});
final String title;
final String coverUrl;
final String episodeLabel;
final VoidCallback onTap;
final VoidCallback onClose;
@override
Widget build(BuildContext context) {
return SizedBox(
key: const Key('mine-mini-player'),
width: AppDimens.mineMiniWidth,
height: AppDimens.mineMiniHeight,
child: DecoratedBox(
decoration: BoxDecoration(
color: AppColors.mineCard,
borderRadius: BorderRadius.circular(AppDimens.mineMiniRadius),
border: Border.all(color: AppColors.contentBorder),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(AppDimens.mineMiniRadius),
child: Material(
color: AppColors.transparent,
child: InkWell(
onTap: onTap,
child: Stack(
children: [
Column(
children: [
Expanded(
child: RemoteImage(
coverUrl,
fit: BoxFit.cover,
showFallbackIcon: true,
fallbackColor: AppColors.contentSurface,
),
),
SizedBox(
height: _infoHeight,
child: ColoredBox(
color: AppColors.mineCard,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 4,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.textPrimary,
fontSize: AppDimens.mineMiniTitle,
fontWeight: FontWeight.w600,
),
),
Text(
episodeLabel,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.textSecondary,
fontSize: AppDimens.mineMiniTitle,
),
),
],
),
),
),
),
],
),
Positioned(
right: 3,
top: 3,
child: IconButton(
key: const Key('mine-mini-close'),
tooltip: MaterialLocalizations.of(
context,
).closeButtonTooltip,
onPressed: onClose,
style: IconButton.styleFrom(
minimumSize: const Size.square(AppDimens.mineMiniClose),
maximumSize: const Size.square(AppDimens.mineMiniClose),
padding: EdgeInsets.zero,
backgroundColor: AppColors.controlScrim,
foregroundColor: AppColors.textPrimary,
),
iconSize: 14,
icon: const Icon(Icons.close_rounded),
),
),
],
),
),
),
),
),
);
}
}