feat(flutter): 统一二级页头并恢复新剧暖色
This commit is contained in:
1 parent
7b2970d5c5
commit
1c6c92170d
26 files changed
+492
-427
No files matched your search
@@ -3,6 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/app_colors.dart';
|
||||
import 'subpage_header.dart';
|
||||
|
||||
/// 二级页面通用骨架:返回栏 + 标题/副标题 + 可滚动内容,无底部导航。
|
||||
class PlainPageScaffold extends StatelessWidget {
|
||||
@@ -30,47 +31,11 @@ class PlainPageScaffold extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(6, 4, 14, 0),
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
key: backKey,
|
||||
tooltip: MaterialLocalizations.of(
|
||||
context,
|
||||
).backButtonTooltip,
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
icon: const Icon(
|
||||
Icons.chevron_left_rounded,
|
||||
color: AppColors.onSurface,
|
||||
size: 26,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
AppSubpageHeader(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
backKey: backKey,
|
||||
),
|
||||
if (subtitle != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
|
||||
child: Text(
|
||||
subtitle!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(color: AppColors.muted, fontSize: 12),
|
||||
),
|
||||
),
|
||||
Expanded(child: child),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/app_colors.dart';
|
||||
|
||||
const double _height = 52;
|
||||
const double _heightWithSubtitle = 64;
|
||||
const double _horizontal = 14;
|
||||
const double _backSize = 36;
|
||||
const double _backGap = 12;
|
||||
const double _titleFontSize = 18;
|
||||
const double _subtitleFontSize = 12;
|
||||
const double _actionGap = 8;
|
||||
const double _iconSize = 20;
|
||||
|
||||
/// 二级页面统一返回按钮,浅色页使用 card 圆底,深色页使用透明底。
|
||||
class AppSubpageBackButton extends StatelessWidget {
|
||||
const AppSubpageBackButton({
|
||||
super.key,
|
||||
required this.backKey,
|
||||
this.dark = false,
|
||||
this.onBack,
|
||||
});
|
||||
|
||||
final Key backKey;
|
||||
final bool dark;
|
||||
final VoidCallback? onBack;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
key: backKey,
|
||||
width: _backSize,
|
||||
height: _backSize,
|
||||
child: Tooltip(
|
||||
message: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
child: Material(
|
||||
color: dark ? Colors.transparent : AppColors.card,
|
||||
shape: const CircleBorder(),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
onTap: onBack ?? () => Navigator.of(context).maybePop(),
|
||||
child: Icon(
|
||||
Icons.chevron_left_rounded,
|
||||
color: dark ? Colors.white : AppColors.onSurface,
|
||||
size: _iconSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 二级页面统一页头:返回按钮、左对齐标题、可选副标题与右侧操作。
|
||||
class AppSubpageHeader extends StatelessWidget {
|
||||
const AppSubpageHeader({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.backKey,
|
||||
this.subtitle,
|
||||
this.actions,
|
||||
this.onBack,
|
||||
this.dark = false,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final Key backKey;
|
||||
final String? subtitle;
|
||||
final Widget? actions;
|
||||
final VoidCallback? onBack;
|
||||
final bool dark;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final foreground = dark ? Colors.white : AppColors.onSurface;
|
||||
final secondary = dark ? Colors.white70 : AppColors.muted;
|
||||
return SizedBox(
|
||||
key: const Key('subpage-header'),
|
||||
height: subtitle == null ? _height : _heightWithSubtitle,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: _horizontal),
|
||||
child: Row(
|
||||
children: [
|
||||
AppSubpageBackButton(backKey: backKey, dark: dark, onBack: onBack),
|
||||
const SizedBox(width: _backGap),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
key: const Key('subpage-title'),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: foreground,
|
||||
fontSize: _titleFontSize,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
if (subtitle != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
subtitle!,
|
||||
key: const Key('subpage-subtitle'),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: secondary,
|
||||
fontSize: _subtitleFontSize,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
if (actions != null) ...[
|
||||
const SizedBox(width: _actionGap),
|
||||
actions!,
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'account_bindings.dart';
|
||||
import 'account_deactivate_logic.dart';
|
||||
@@ -51,23 +52,16 @@ class _AccountDeactivatePageState extends State<AccountDeactivatePage> {
|
||||
final canShow = signedIn || _logic.scheduledAt != null;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('account-deactivate-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
title: Text(l10n.accountDeactivate),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: canShow
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('account-deactivate-page'),
|
||||
backKey: const Key('account-deactivate-back'),
|
||||
title: l10n.accountDeactivate,
|
||||
child: canShow
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'account_bindings.dart';
|
||||
import 'account_devices_logic.dart';
|
||||
@@ -51,23 +52,16 @@ class _AccountDevicesPageState extends State<AccountDevicesPage> {
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('account-devices-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
title: Text(l10n.accountDevices),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: signedIn
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('account-devices-page'),
|
||||
backKey: const Key('account-devices-back'),
|
||||
title: l10n.accountDevices,
|
||||
child: signedIn
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'account_bindings.dart';
|
||||
import 'account_export_logic.dart';
|
||||
@@ -52,23 +53,16 @@ class _AccountExportPageState extends State<AccountExportPage> {
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('account-export-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
title: Text(l10n.accountDataExport),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: signedIn
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('account-export-page'),
|
||||
backKey: const Key('account-export-back'),
|
||||
title: l10n.accountDataExport,
|
||||
child: signedIn
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../core/widgets/remote_image.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'account_bindings.dart';
|
||||
@@ -72,23 +73,16 @@ class _AccountProfilePageState extends State<AccountProfilePage> {
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('account-profile-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
title: Text(l10n.accountProfile),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: signedIn
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('account-profile-page'),
|
||||
backKey: const Key('account-profile-back'),
|
||||
title: l10n.accountProfile,
|
||||
child: signedIn
|
||||
? ListenableBuilder(
|
||||
listenable: _logic,
|
||||
builder: (context, _) => _body(l10n),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
const double _cardHeight = 196;
|
||||
@@ -343,11 +344,11 @@ class _CreatePlaceholderPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
return Scaffold(
|
||||
key: const Key('create-placeholder-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(title: Text(title)),
|
||||
body: Center(
|
||||
return PlainPageScaffold(
|
||||
pageKey: const Key('create-placeholder-page'),
|
||||
backKey: const Key('create-placeholder-back'),
|
||||
title: title,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/data/models/drama.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../drama_detail/drama_detail_view.dart';
|
||||
import 'widgets/drama_grid.dart';
|
||||
@@ -28,32 +28,25 @@ class CategoryDramasPage extends StatelessWidget {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('category-dramas-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(title),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: dramas.isEmpty
|
||||
? EmptyState(
|
||||
key: const Key('category-dramas-empty'),
|
||||
icon: Icons.movie_filter_outlined,
|
||||
title: l10n.noCategoryDramas,
|
||||
subtitle: l10n.emptyHint,
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(top: 12, bottom: 28),
|
||||
child: DramaGrid(
|
||||
l10n: l10n,
|
||||
dramas: dramas,
|
||||
onOpen: (drama) => _open(context, drama),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('category-dramas-page'),
|
||||
backKey: const Key('category-dramas-back'),
|
||||
title: title,
|
||||
child: dramas.isEmpty
|
||||
? EmptyState(
|
||||
key: const Key('category-dramas-empty'),
|
||||
icon: Icons.movie_filter_outlined,
|
||||
title: l10n.noCategoryDramas,
|
||||
subtitle: l10n.emptyHint,
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(top: 8, bottom: 28),
|
||||
child: DramaGrid(
|
||||
l10n: l10n,
|
||||
dramas: dramas,
|
||||
onOpen: (drama) => _open(context, drama),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../player/player_view.dart';
|
||||
import 'downloads_binding.dart';
|
||||
@@ -55,20 +56,13 @@ class _DownloadsPageState extends State<DownloadsPage> {
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('downloads-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: Colors.white,
|
||||
title: Text(l10n.downloads),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: signedIn
|
||||
? _DownloadsBody(downloads: context.watch<DownloadController>())
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('downloads-page'),
|
||||
backKey: const Key('downloads-back'),
|
||||
title: l10n.downloads,
|
||||
child: signedIn
|
||||
? _DownloadsBody(downloads: context.watch<DownloadController>())
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/download_action.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/subpage_header.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../interaction/widgets/report_dialog.dart';
|
||||
import 'drama_detail_binding.dart';
|
||||
@@ -145,24 +146,14 @@ class _DramaDetailPageState extends State<DramaDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _loading(AppLocalizations l10n) => Scaffold(
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.surfaceTop,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(localizedDramaTitle(l10n, widget.drama)),
|
||||
),
|
||||
body: const Center(child: CircularProgressIndicator()),
|
||||
Widget _loading(AppLocalizations l10n) => _statePage(
|
||||
localizedDramaTitle(l10n, widget.drama),
|
||||
const Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
|
||||
Widget _failed(AppLocalizations l10n) => Scaffold(
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.surfaceTop,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(localizedDramaTitle(l10n, widget.drama)),
|
||||
),
|
||||
body: Center(
|
||||
Widget _failed(AppLocalizations l10n) => _statePage(
|
||||
localizedDramaTitle(l10n, widget.drama),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Column(
|
||||
@@ -181,14 +172,9 @@ class _DramaDetailPageState extends State<DramaDetailPage> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget _empty(AppLocalizations l10n, Drama drama) => Scaffold(
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.surfaceTop,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(localizedDramaTitle(l10n, drama)),
|
||||
),
|
||||
body: EmptyState(
|
||||
Widget _empty(AppLocalizations l10n, Drama drama) => _statePage(
|
||||
localizedDramaTitle(l10n, drama),
|
||||
EmptyState(
|
||||
key: const Key('drama-detail-empty'),
|
||||
icon: Icons.video_library_outlined,
|
||||
title: l10n.noEpisodesYet,
|
||||
@@ -198,6 +184,18 @@ class _DramaDetailPageState extends State<DramaDetailPage> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget _statePage(String title, Widget child) => Scaffold(
|
||||
backgroundColor: AppColors.ink,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
AppSubpageHeader(title: title, backKey: const Key('detail-back')),
|
||||
Expanded(child: child),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget? _resume(AppLocalizations l10n) {
|
||||
final fraction = _continueFraction;
|
||||
final progressError = logic.progressError;
|
||||
|
||||
@@ -6,6 +6,7 @@ import '../../../core/data/models/drama.dart';
|
||||
import '../../../core/formatting/localized_content.dart';
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
import '../../../core/widgets/remote_image.dart';
|
||||
import '../../../core/widgets/subpage_header.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
|
||||
const double _horizontal = 14;
|
||||
@@ -80,11 +81,10 @@ class DramaDetailHeader extends StatelessWidget {
|
||||
Widget _actions(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
_CircleAction(
|
||||
actionKey: const Key('detail-back'),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
icon: Icons.chevron_left_rounded,
|
||||
onPressed: actions.onBack,
|
||||
AppSubpageBackButton(
|
||||
backKey: const Key('detail-back'),
|
||||
dark: true,
|
||||
onBack: actions.onBack,
|
||||
),
|
||||
const Spacer(),
|
||||
_CircleAction(
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/library_drama_tile.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../drama_detail/drama_detail_view.dart';
|
||||
import 'favorites_binding.dart';
|
||||
@@ -52,19 +53,13 @@ class _FavoritesPageState extends State<FavoritesPage> {
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: Colors.white,
|
||||
title: Text(l10n.myFavorites),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: signedIn
|
||||
? _FavoritesBody(favorites: context.watch<FavoriteController>())
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('favorites-page'),
|
||||
backKey: const Key('favorites-back'),
|
||||
title: l10n.myFavorites,
|
||||
child: signedIn
|
||||
? _FavoritesBody(favorites: context.watch<FavoriteController>())
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import '../../core/data/services/catalog_controller.dart';
|
||||
import '../../core/data/services/category_controller.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/subpage_header.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'widgets/filter_result_card.dart';
|
||||
|
||||
@@ -64,7 +65,10 @@ class _FilterPageState extends State<FilterPage> {
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
_topBar(l10n),
|
||||
AppSubpageHeader(
|
||||
title: l10n.filter,
|
||||
backKey: const Key('filter-back'),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
@@ -123,44 +127,6 @@ class _FilterPageState extends State<FilterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _topBar(AppLocalizations l10n) {
|
||||
return SizedBox(
|
||||
height: 52,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
key: const Key('filter-back'),
|
||||
width: 48,
|
||||
height: 48,
|
||||
child: IconButton(
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(
|
||||
Icons.chevron_left_rounded,
|
||||
color: AppColors.onSurface,
|
||||
size: 26,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
l10n.filter,
|
||||
style: const TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 48),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _groups(
|
||||
AppLocalizations l10n,
|
||||
List<String> categories,
|
||||
|
||||
@@ -14,6 +14,7 @@ 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 '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../downloads/downloads_page.dart';
|
||||
import '../favorites/favorites_page.dart';
|
||||
@@ -364,11 +365,11 @@ class _MinePlaceholderPage extends StatelessWidget {
|
||||
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(
|
||||
return PlainPageScaffold(
|
||||
pageKey: const Key('mine-placeholder-page'),
|
||||
backKey: const Key('mine-placeholder-back'),
|
||||
title: title,
|
||||
child: Center(
|
||||
child: Text(
|
||||
l10n.comingSoon,
|
||||
style: const TextStyle(
|
||||
|
||||
@@ -11,16 +11,18 @@ import '../../core/data/services/catalog_controller.dart';
|
||||
import '../../core/formatting/count_format.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/widgets/remote_image.dart';
|
||||
import '../../core/widgets/subpage_header.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../player/open_player.dart';
|
||||
|
||||
const int _moreLimit = 12;
|
||||
const int _filmHoles = 8;
|
||||
const Color _premiereTop = Color(0xFF1F1B16);
|
||||
const Color _premiereBottom = Color(0xFF2E2119);
|
||||
const Color _filmHole = Color(0x33FFFFFF);
|
||||
const double _cardPadding = 8;
|
||||
const double _cardWidth = 124;
|
||||
const double _rowHeight = 204;
|
||||
const double _cardRadius = 12;
|
||||
|
||||
/// 新剧页:暗色首映厅,今日首映大卡 + 横向更多新剧。
|
||||
/// 新剧页:暖色首映厅,今日首映大卡 + 横向更多新剧。
|
||||
class NewReleasesPage extends StatelessWidget {
|
||||
const NewReleasesPage({super.key});
|
||||
|
||||
@@ -32,29 +34,35 @@ class NewReleasesPage extends StatelessWidget {
|
||||
final hero = dramas.isEmpty ? null : dramas.first;
|
||||
final more = dramas.skip(1).take(_moreLimit).toList();
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle.light,
|
||||
value: SystemUiOverlayStyle.dark,
|
||||
child: Scaffold(
|
||||
key: const Key('new-releases-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
body: DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [_premiereTop, _premiereBottom],
|
||||
colors: [AppColors.surfaceTop, AppColors.ink],
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_header(context, l10n, dramas.length),
|
||||
AppSubpageHeader(
|
||||
title: l10n.newReleasesTitle,
|
||||
subtitle: l10n.newReleasesSubtitle,
|
||||
backKey: const Key('new-releases-back'),
|
||||
actions: _countChip(l10n, dramas.length),
|
||||
),
|
||||
Expanded(
|
||||
child: hero == null
|
||||
? Center(
|
||||
child: Text(
|
||||
l10n.noStories,
|
||||
key: const Key('new-releases-empty'),
|
||||
style: const TextStyle(color: Colors.white70),
|
||||
style: const TextStyle(color: AppColors.muted),
|
||||
),
|
||||
)
|
||||
: ListView(
|
||||
@@ -73,7 +81,7 @@ class NewReleasesPage extends StatelessWidget {
|
||||
_moreHeader(l10n),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
height: 196,
|
||||
height: _rowHeight,
|
||||
child: ListView.separated(
|
||||
key: const Key('new-releases-row'),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@@ -103,63 +111,21 @@ class NewReleasesPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _header(BuildContext context, AppLocalizations l10n, int count) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(6, 4, 16, 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
key: const Key('new-releases-back'),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
icon: const Icon(
|
||||
Icons.chevron_left_rounded,
|
||||
color: Colors.white,
|
||||
size: 26,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
l10n.newReleasesTitle,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
key: const Key('new-releases-count'),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 5,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.blue,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Text(
|
||||
l10n.newReleasesCount(count),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
l10n.newReleasesSubtitle,
|
||||
style: const TextStyle(color: Colors.white70, fontSize: 12),
|
||||
),
|
||||
),
|
||||
],
|
||||
Widget _countChip(AppLocalizations l10n, int count) {
|
||||
return Container(
|
||||
key: const Key('new-releases-count'),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.badgeBeige,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Text(
|
||||
l10n.newReleasesCount(count),
|
||||
style: const TextStyle(
|
||||
color: AppColors.blue,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -286,7 +252,7 @@ class NewReleasesPage extends StatelessWidget {
|
||||
child: Text(
|
||||
l10n.rankingNew,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
@@ -294,7 +260,7 @@ class NewReleasesPage extends StatelessWidget {
|
||||
),
|
||||
Text(
|
||||
l10n.seeAll,
|
||||
style: const TextStyle(color: Colors.white54, fontSize: 12),
|
||||
style: const TextStyle(color: AppColors.subtle, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -310,13 +276,25 @@ class NewReleasesPage extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
key: Key('new-release-card-${drama.id}'),
|
||||
onTap: () => unawaited(playDramaFromCatalog(context, drama)),
|
||||
child: SizedBox(
|
||||
width: 108,
|
||||
child: Container(
|
||||
width: _cardWidth,
|
||||
padding: const EdgeInsets.all(_cardPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.card,
|
||||
borderRadius: BorderRadius.circular(_cardRadius),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: AppColors.cardShadow,
|
||||
blurRadius: 12,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: SizedBox(
|
||||
width: 108,
|
||||
height: 144,
|
||||
@@ -348,7 +326,7 @@ class NewReleasesPage extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -356,7 +334,7 @@ class NewReleasesPage extends StatelessWidget {
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
_releaseDate(index),
|
||||
style: const TextStyle(color: Colors.white54, fontSize: 12),
|
||||
style: const TextStyle(color: AppColors.subtle, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -407,7 +385,13 @@ class _FilmStrip extends StatelessWidget {
|
||||
return Container(
|
||||
key: const Key('new-releases-film'),
|
||||
height: 22,
|
||||
color: const Color(0x1A000000),
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColors.raised,
|
||||
border: Border(
|
||||
top: BorderSide(color: AppColors.border),
|
||||
bottom: BorderSide(color: AppColors.border),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [_holes(), _holes()],
|
||||
@@ -424,7 +408,7 @@ class _FilmStrip extends StatelessWidget {
|
||||
width: 6,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: _filmHole,
|
||||
color: AppColors.border,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -14,6 +14,7 @@ import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// Anonymous system notice list with pagination and detail dialog.
|
||||
@@ -45,20 +46,13 @@ class _NoticesPageState extends State<NoticesPage> {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('notices-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onPrimary,
|
||||
title: Text(l10n.notices),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: ListenableBuilder(
|
||||
listenable: _controller,
|
||||
builder: (context, _) => _body(l10n),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('notices-page'),
|
||||
backKey: const Key('notices-back'),
|
||||
title: l10n.notices,
|
||||
child: ListenableBuilder(
|
||||
listenable: _controller,
|
||||
builder: (context, _) => _body(l10n),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/widgets/subpage_header.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../new_releases/new_releases_page.dart';
|
||||
|
||||
@@ -43,7 +44,11 @@ class _ReservePageState extends State<ReservePage> {
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.fromLTRB(0, 4, 0, 24),
|
||||
children: [
|
||||
_header(context, l10n),
|
||||
AppSubpageHeader(
|
||||
title: l10n.reserveTitle,
|
||||
subtitle: l10n.reserveSubtitle,
|
||||
backKey: const Key('reserve-back'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
|
||||
child: _weekStrip(l10n),
|
||||
@@ -62,48 +67,6 @@ class _ReservePageState extends State<ReservePage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _header(BuildContext context, AppLocalizations l10n) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(6, 0, 16, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
key: const Key('reserve-back'),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
icon: const Icon(
|
||||
Icons.chevron_left_rounded,
|
||||
color: AppColors.onSurface,
|
||||
size: 26,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
l10n.reserveTitle,
|
||||
style: const TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
l10n.reserveSubtitle,
|
||||
style: const TextStyle(color: AppColors.muted, fontSize: 12),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _weekStrip(AppLocalizations l10n) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
@@ -9,6 +9,7 @@ import '../../core/data/services/auth_controller.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../account/account_entry_card.dart';
|
||||
import '../notices/notices_page.dart';
|
||||
@@ -23,28 +24,21 @@ class SettingsPage extends StatelessWidget {
|
||||
final auth = context.watch<AuthController>();
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('settings-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(l10n.settings),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.fromLTRB(14, 12, 14, 28),
|
||||
children: [
|
||||
if (auth.isSignedIn) ...[
|
||||
const AccountEntryCard(),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
_noticesTile(context, l10n),
|
||||
const SizedBox(height: 24),
|
||||
_authAction(context, l10n, auth),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('settings-page'),
|
||||
backKey: const Key('settings-back'),
|
||||
title: l10n.settings,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.fromLTRB(14, 8, 14, 28),
|
||||
children: [
|
||||
if (auth.isSignedIn) ...[
|
||||
const AccountEntryCard(),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
_noticesTile(context, l10n),
|
||||
const SizedBox(height: 24),
|
||||
_authAction(context, l10n, auth),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@ import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// 商品货架:金币包与会员档位共用一套真实接口渲染。
|
||||
@@ -57,20 +58,13 @@ class _StorePageState extends State<StorePage> {
|
||||
final isVip = widget.type == StoreController.vipType;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('store-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(isVip ? l10n.vipTitle : l10n.rechargeTitle),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: ListenableBuilder(
|
||||
listenable: controller,
|
||||
builder: (context, _) => _body(l10n, isVip),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('store-page'),
|
||||
backKey: const Key('store-back'),
|
||||
title: isVip ? l10n.vipTitle : l10n.rechargeTitle,
|
||||
child: ListenableBuilder(
|
||||
listenable: controller,
|
||||
builder: (context, _) => _body(l10n, isVip),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@ import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../store/recharge_page.dart';
|
||||
import '../store/vip_page.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
@@ -45,15 +46,11 @@ class _WalletPageState extends State<WalletPage> {
|
||||
final wallet = context.watch<WalletController>();
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('wallet-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
title: Text(l10n.wallet),
|
||||
),
|
||||
body: SafeArea(top: false, child: _body(l10n, wallet)),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('wallet-page'),
|
||||
backKey: const Key('wallet-back'),
|
||||
title: l10n.wallet,
|
||||
child: _body(l10n, wallet),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../core/widgets/remote_image.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../drama_detail/drama_detail_view.dart';
|
||||
@@ -34,18 +35,11 @@ class WatchRecordsPage extends StatelessWidget {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
return Theme(
|
||||
data: AppTheme.light(),
|
||||
child: Scaffold(
|
||||
key: const Key('watch-records-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.ink,
|
||||
foregroundColor: Colors.white,
|
||||
title: Text(l10n.watchHistory),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: signedIn ? const _WatchRecordsBody() : const AuthGatePanel(),
|
||||
),
|
||||
child: PlainPageScaffold(
|
||||
pageKey: const Key('watch-records-page'),
|
||||
backKey: const Key('watch-records-back'),
|
||||
title: l10n.watchHistory,
|
||||
child: signedIn ? const _WatchRecordsBody() : const AuthGatePanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user