feat(flutter): 重设计创作与我的页面
This commit is contained in:
1 parent
d50c6e6d9f
commit
03c3964353
17 files changed
+807
-234
No files matched your search
@@ -5,33 +5,30 @@ 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/download_controller.dart';
|
||||
import '../../core/data/services/wallet_controller.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/app_bottom_nav.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../downloads/downloads_page.dart';
|
||||
import '../favorites/favorites_page.dart';
|
||||
import '../player/player_view.dart';
|
||||
import '../notices/notices_page.dart';
|
||||
import '../settings/settings_page.dart';
|
||||
import '../store/recharge_page.dart';
|
||||
import '../store/vip_page.dart';
|
||||
import '../wallet/wallet_page.dart';
|
||||
import '../watch_records/watch_records_page.dart';
|
||||
import 'mine_binding.dart';
|
||||
import 'mine_logic.dart';
|
||||
import 'mine_types.dart';
|
||||
import 'widgets/continue_watching_card.dart';
|
||||
import 'widgets/mine_header.dart';
|
||||
import 'widgets/mine_menu.dart';
|
||||
|
||||
/// 极简「我的」页:续看 + 追剧 / 历史 / 下载 / 钱包 / 会员 / 设置。
|
||||
/// K28-B 我的页。
|
||||
class MyPage extends StatefulWidget {
|
||||
const MyPage({
|
||||
super.key,
|
||||
@@ -101,36 +98,22 @@ class _MyPageState extends State<MyPage> {
|
||||
|
||||
Widget _topBar(AppLocalizations l10n) {
|
||||
return SizedBox(
|
||||
height: 46,
|
||||
height: AppDimens.contentHeaderHeight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.blue,
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.play_arrow_rounded,
|
||||
color: AppColors.onPrimary,
|
||||
size: 16,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppDimens.pageHorizontal,
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
l10n.myTab,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Outfit',
|
||||
color: AppColors.onSurface,
|
||||
fontSize: AppDimens.pageTitle,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
l10n.myTab,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Outfit',
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -139,26 +122,27 @@ class _MyPageState extends State<MyPage> {
|
||||
Widget _body(BuildContext context, AppLocalizations l10n) {
|
||||
final auth = context.watch<AuthController>();
|
||||
final wallet = context.watch<WalletController>();
|
||||
final record = _continueRecord;
|
||||
final drama = _dramaFor(record);
|
||||
return ListView(
|
||||
padding: const EdgeInsets.only(bottom: 18),
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
AppDimens.pageHorizontal,
|
||||
0,
|
||||
AppDimens.pageHorizontal,
|
||||
AppDimens.spaceXl,
|
||||
),
|
||||
children: [
|
||||
const MineHeader(),
|
||||
if (drama != null && record != null)
|
||||
ContinueWatchingCard(
|
||||
drama: drama,
|
||||
record: record,
|
||||
onResume: () => _resume(drama),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
child: MineMenu(
|
||||
walletValue: _walletValue(l10n, auth, wallet),
|
||||
onOpen: _openDestination,
|
||||
),
|
||||
MineHeader(onTap: () => _openDestination(MineDestination.settings)),
|
||||
const SizedBox(height: AppDimens.spaceMd),
|
||||
MineShortcutGrid(onOpen: _openDestination),
|
||||
const SizedBox(height: AppDimens.spaceMd),
|
||||
MineWalletCard(
|
||||
balance: _walletValue(l10n, auth, wallet),
|
||||
onOpen: () => _openDestination(MineDestination.wallet),
|
||||
onRecharge: _openRecharge,
|
||||
),
|
||||
const SizedBox(height: AppDimens.spaceMd),
|
||||
MineVipCard(onOpen: () => _openDestination(MineDestination.vip)),
|
||||
const SizedBox(height: AppDimens.spaceMd),
|
||||
MineMenuList(onOpen: _openDestination),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -173,39 +157,6 @@ class _MyPageState extends State<MyPage> {
|
||||
return l10n.walletBalanceShort(wallet.balance);
|
||||
}
|
||||
|
||||
WatchProgress? get _continueRecord {
|
||||
for (final record in logic.recent) {
|
||||
if (!record.finished && record.hasPosition) return record;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Drama? _dramaFor(WatchProgress? record) {
|
||||
if (record == null) return null;
|
||||
for (final drama in context.read<CatalogController>().dramas) {
|
||||
if (drama.id == record.dramaId) return drama;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _resume(Drama drama) {
|
||||
final callback = widget.callbacks.onDramaSelected;
|
||||
if (callback != null) {
|
||||
callback(drama);
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).push<void>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => PlayerPage(
|
||||
drama: drama,
|
||||
initialIndex: 0,
|
||||
wallet: context.read<WalletController>(),
|
||||
downloads: context.read<DownloadController>(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _openDestination(MineDestination destination) {
|
||||
switch (destination) {
|
||||
case MineDestination.watchlist:
|
||||
@@ -218,8 +169,16 @@ class _MyPageState extends State<MyPage> {
|
||||
_openProtected(const WalletPage());
|
||||
case MineDestination.vip:
|
||||
_openVip();
|
||||
case MineDestination.works:
|
||||
_pushPlaceholder(MinePlaceholderKind.works);
|
||||
case MineDestination.creatorCenter:
|
||||
_pushPlaceholder(MinePlaceholderKind.creator);
|
||||
case MineDestination.notices:
|
||||
_push(const NoticesPage());
|
||||
case MineDestination.settings:
|
||||
_push(const SettingsPage());
|
||||
case MineDestination.help:
|
||||
_pushPlaceholder(MinePlaceholderKind.help);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +186,10 @@ class _MyPageState extends State<MyPage> {
|
||||
Navigator.of(context).push<void>(MaterialPageRoute(builder: (_) => page));
|
||||
}
|
||||
|
||||
void _pushPlaceholder(MinePlaceholderKind kind) {
|
||||
_push(_MinePlaceholderPage(kind: kind));
|
||||
}
|
||||
|
||||
Future<void> _openProtected(Widget page) async {
|
||||
if (!context.read<AuthController>().isSignedIn) {
|
||||
await ensureSignedIn(context);
|
||||
@@ -240,6 +203,11 @@ class _MyPageState extends State<MyPage> {
|
||||
_openProtected(VipPage(onPurchased: () => unawaited(wallet.load())));
|
||||
}
|
||||
|
||||
void _openRecharge() {
|
||||
final wallet = context.read<WalletController>();
|
||||
_openProtected(RechargePage(onPurchased: () => unawaited(wallet.load())));
|
||||
}
|
||||
|
||||
Widget _bottomNav(AppLocalizations l10n) {
|
||||
return AppBottomNav(
|
||||
items: [
|
||||
@@ -266,8 +234,8 @@ class _MyPageState extends State<MyPage> {
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('mine-nav-current'),
|
||||
icon: Icons.video_library_outlined,
|
||||
selectedIcon: Icons.video_library_rounded,
|
||||
icon: Icons.person_outline_rounded,
|
||||
selectedIcon: Icons.person_rounded,
|
||||
label: l10n.myTab,
|
||||
selected: true,
|
||||
onTap: () {},
|
||||
@@ -285,3 +253,35 @@ class _MyPageState extends State<MyPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum MinePlaceholderKind { works, creator, help }
|
||||
|
||||
class _MinePlaceholderPage extends StatelessWidget {
|
||||
const _MinePlaceholderPage({required this.kind});
|
||||
|
||||
final MinePlaceholderKind kind;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final title = switch (kind) {
|
||||
MinePlaceholderKind.works => l10n.myWorks,
|
||||
MinePlaceholderKind.creator => l10n.creatorCenter,
|
||||
MinePlaceholderKind.help => l10n.helpFeedback,
|
||||
};
|
||||
return Scaffold(
|
||||
key: const Key('mine-placeholder-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(title: Text(title)),
|
||||
body: Center(
|
||||
child: Text(
|
||||
l10n.comingSoon,
|
||||
style: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: AppDimens.body,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user