refactor(navigation): 移除全局两侧悬浮元素
This commit is contained in:
1 parent
5cead7ce00
commit
9cf832b318
8 files changed
+103
-217
No files matched your search
@@ -97,9 +97,4 @@ abstract final class AppDimens {
|
||||
static const double mineUserName = 20;
|
||||
static const double mineUid = 13;
|
||||
static const double mineMenuIcon = 22;
|
||||
static const double mineMiniWidth = 96;
|
||||
static const double mineMiniHeight = 132;
|
||||
static const double mineMiniRadius = 8;
|
||||
static const double mineMiniTitle = 10;
|
||||
static const double mineMiniClose = 22;
|
||||
}
|
||||
@@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user