feat(theme): 校正 K26 预览色板与导航

This commit is contained in:
Zhou Weidong committed 2026-10-19 15:50:07 +08:00
1 parent eefabb6898
commit 87db548591
14 files changed
+293 -58

No files matched your search

+16 -7
View File
@@ -38,25 +38,34 @@ abstract final class AppColors {
static const ink = Color(0xFF0B0C10);
/// Bottom navigation background (rendered at 95% with blur).
static const bar = Color(0xFF0B0C10);
static const bar = Color(0xFF0D0D11);
/// Cards lifted off [ink].
static const card = Color(0xFF16181F);
static const card = Color(0xFF1B1C21);
/// Alternate card surface from the mobile preview.
static const cardAlt = Color(0xFF1C1D21);
/// Floating surfaces, inputs, and nested rows.
static const raised = Color(0xFF1D1E28);
static const raised = Color(0xFF1C1D21);
static const quick = Color(0xFF202126);
static const input = Color(0xFF25252A);
static const goldCard = Color(0xFF201B1E);
/// Body text on dark surfaces.
static const cream = Color(0xFFE3E2E8);
static const cream = Color(0xFFE6E1E3);
/// Titles and high-emphasis text.
static const onSurface = Color(0xFFFFFFFF);
/// Secondary text.
static const muted = Color(0xFFA1A1AA);
static const muted = Color(0xFFD2CDD0);
/// Weak hints and timestamps.
static const subtle = Color(0xFF71717A);
static const subtle = Color(0xFF9A96A3);
/// Soft orange used for continue labels and secondary times.
static const accent = Color(0xFFFFA490);
/// 8% white border used by cards and inputs.
static const border = Color(0x14FFFFFF);
@@ -65,7 +74,7 @@ abstract final class AppColors {
static const glassBorder = Color(0x24FFFFFF);
static const outlineDark = Color(0xFF2A2C36);
static const outlineVariantDark = Color(0xFF242630);
static const outlineVariantDark = Color(0xFF242329);
static const outlineLight = Color(0xFF8E8E93);
static const outlineVariantLight = Color(0xFFE4E4E7);
}
+21 -11
View File
@@ -9,15 +9,17 @@ abstract final class AppDimens {
static const double spaceXl = 24;
static const double pageHorizontal = 16;
static const double cardRadius = 16;
static const double cardRadius = 12;
static const double authCardRadius = 20;
static const double cardPadding = 16;
static const double innerRadius = 12;
static const double innerRadius = 10;
static const double innerPadding = 12;
static const double pillRadius = 20;
static const double glassSmallRadius = 16;
static const double glassRadius = 24;
static const double glassCardRadius = 26;
static const double glassSmallRadius = 12;
static const double glassRadius = 14;
static const double glassCardRadius = 14;
static const double buttonRadius = 9;
static const double coverRadius = 10;
static const double caption = 12;
static const double emptyStateSubtitle = 12.5;
@@ -27,17 +29,25 @@ abstract final class AppDimens {
static const double sectionTitle = 16;
static const double pageTitle = 20;
static const double detailHeadline = 24;
static const double navLabel = 11;
static const double detailHeadlineSmall = 18;
static const double previewCardTitle = 13;
static const double previewSectionTitle = 14;
static const double chipFont = 10;
static const double navLabel = 9;
static const double buttonHeight = 48;
static const double primaryButtonHeight = 52;
static const double buttonCompact = 32;
static const double buttonSmall = 34;
static const double buttonMedium = 40;
static const double buttonLarge = 44;
static const double tapTarget = 44;
static const double navHeight = 64;
static const double navIcon = 22;
static const double progressHeight = 4;
static const double progressRadius = 4;
static const double progressLineHeight = 1.5;
static const double navHeight = 54;
static const double navIcon = 17;
static const double progressHeight = 3;
static const double progressRadius = 2;
static const double progressLineHeight = 3;
static const double searchHeight = 44;
static const double navDot = 3;
+4 -16
View File
@@ -16,7 +16,6 @@ class AppBottomNavItem {
required this.label,
required this.onTap,
this.selected = false,
this.indicatorKey,
});
final Key tabKey;
@@ -25,7 +24,6 @@ class AppBottomNavItem {
final String label;
final VoidCallback onTap;
final bool selected;
final Key? indicatorKey;
}
/// Shared 3-tab navigation used by all root tabs and the player fallback.
@@ -52,7 +50,9 @@ class AppBottomNav extends StatelessWidget {
height: AppDimens.navHeight,
decoration: BoxDecoration(
color: backgroundColor.withValues(alpha: 0.95),
border: const Border(top: BorderSide(color: AppColors.border)),
border: const Border(
top: BorderSide(color: AppColors.outlineVariantDark),
),
),
child: Row(
children: [for (final item in items) _NavDestination(item: item)],
@@ -94,7 +94,7 @@ class _NavDestination extends StatelessWidget {
: Colors.white.withValues(alpha: 0.45),
),
),
const SizedBox(height: 3),
const SizedBox(height: 2),
Text(
item.label,
maxLines: 1,
@@ -108,18 +108,6 @@ class _NavDestination extends StatelessWidget {
letterSpacing: 0,
),
),
const SizedBox(height: 3),
AnimatedContainer(
key: item.indicatorKey,
duration: const Duration(milliseconds: 160),
curve: Curves.easeOut,
width: AppDimens.navDot,
height: AppDimens.navDot,
decoration: BoxDecoration(
color: item.selected ? AppColors.blue : Colors.transparent,
shape: BoxShape.circle,
),
),
],
),
),
+1 -1
View File
@@ -13,7 +13,7 @@ class GlassPanel extends StatelessWidget {
super.key,
required this.child,
this.radius = AppDimens.glassRadius,
this.blur = AppDimens.glassBlur,
this.blur = 10,
this.padding,
this.borderColor = AppColors.glassBorder,
this.gradient,
+22 -1
View File
@@ -15,6 +15,14 @@
"discoverTab": "Discover",
"searchDiscover": "Search dramas, actors, genres...",
"featured": "Featured",
"recommended": "Recommended",
"fruitShortsBrand": "FruitShorts",
"authLandingSubtitle": "Sign in to sync progress, favorites and coins",
"comingSoon": "Coming soon",
"authLegal": "By continuing, you agree to the Terms of Service and Privacy Policy.",
"authContinueGoogle": "Continue with Google",
"authPhoneSignIn": "Phone sign in",
"authEmailSignIn": "Email sign in",
"suspense": "Suspense",
"romance": "Romance",
"actionGenre": "Action",
@@ -31,6 +39,19 @@
"startWatching": "Start Watching",
"showLess": "Less",
"views": "views",
"episodeOfTotal": "Episode {current} / {total}",
"@episodeOfTotal": {
"placeholders": {
"current": {"type": "int"},
"total": {"type": "int"}
}
},
"minutesAgo": "{count} min ago",
"@minutesAgo": {
"placeholders": {
"count": {"type": "int"}
}
},
"artworkOnly": "Artwork",
"artworkOnlyNotice": "This is a visual catalog item. No video is available yet.",
"videoPending": "Video pending",
@@ -52,7 +73,7 @@
},
"resume": "Resume",
"history": "History",
"watchlist": "Watchlist",
"watchlist": "Favorites",
"likedTab": "Liked",
"all": "All",
"inProgress": "In Progress",
+22 -1
View File
@@ -12,9 +12,17 @@
"openQuickMenu": "Buka menu cepat",
"quickAccess": "Akses cepat",
"currentSeries": "Serial saat ini",
"discoverTab": "Jelajahi",
"discoverTab": "Temukan",
"searchDiscover": "Cari drama, aktor, genre...",
"featured": "Unggulan",
"recommended": "Rekomendasi",
"fruitShortsBrand": "FruitShorts",
"authLandingSubtitle": "Masuk untuk menyinkronkan progres, favorit, dan koin",
"comingSoon": "Segera hadir",
"authLegal": "Dengan melanjutkan, Anda menyetujui Ketentuan Layanan dan Kebijakan Privasi.",
"authContinueGoogle": "Lanjutkan dengan Google",
"authPhoneSignIn": "Masuk dengan ponsel",
"authEmailSignIn": "Masuk dengan email",
"suspense": "Thriller",
"romance": "Romantis",
"actionGenre": "Aksi",
@@ -31,6 +39,19 @@
"startWatching": "Mulai Menonton",
"showLess": "Lebih sedikit",
"views": "tayangan",
"episodeOfTotal": "Episode {current} / {total}",
"@episodeOfTotal": {
"placeholders": {
"current": {"type": "int"},
"total": {"type": "int"}
}
},
"minutesAgo": "{count} mnt lalu",
"@minutesAgo": {
"placeholders": {
"count": {"type": "int"}
}
},
"artworkOnly": "Gambar",
"artworkOnlyNotice": "Ini hanya gambar katalog. Videonya belum tersedia.",
"videoPending": "Video belum siap",
+61 -1
View File
@@ -190,6 +190,54 @@ abstract class AppLocalizations {
/// **'Featured'**
String get featured;
/// No description provided for @recommended.
///
/// In en, this message translates to:
/// **'Recommended'**
String get recommended;
/// No description provided for @fruitShortsBrand.
///
/// In en, this message translates to:
/// **'FruitShorts'**
String get fruitShortsBrand;
/// No description provided for @authLandingSubtitle.
///
/// In en, this message translates to:
/// **'Sign in to sync progress, favorites and coins'**
String get authLandingSubtitle;
/// No description provided for @comingSoon.
///
/// In en, this message translates to:
/// **'Coming soon'**
String get comingSoon;
/// No description provided for @authLegal.
///
/// In en, this message translates to:
/// **'By continuing, you agree to the Terms of Service and Privacy Policy.'**
String get authLegal;
/// No description provided for @authContinueGoogle.
///
/// In en, this message translates to:
/// **'Continue with Google'**
String get authContinueGoogle;
/// No description provided for @authPhoneSignIn.
///
/// In en, this message translates to:
/// **'Phone sign in'**
String get authPhoneSignIn;
/// No description provided for @authEmailSignIn.
///
/// In en, this message translates to:
/// **'Email sign in'**
String get authEmailSignIn;
/// No description provided for @suspense.
///
/// In en, this message translates to:
@@ -286,6 +334,18 @@ abstract class AppLocalizations {
/// **'views'**
String get views;
/// No description provided for @episodeOfTotal.
///
/// In en, this message translates to:
/// **'Episode {current} / {total}'**
String episodeOfTotal(int current, int total);
/// No description provided for @minutesAgo.
///
/// In en, this message translates to:
/// **'{count} min ago'**
String minutesAgo(int count);
/// No description provided for @artworkOnly.
///
/// In en, this message translates to:
@@ -373,7 +433,7 @@ abstract class AppLocalizations {
/// No description provided for @watchlist.
///
/// In en, this message translates to:
/// **'Watchlist'**
/// **'Favorites'**
String get watchlist;
/// No description provided for @likedTab.
+37 -1
View File
@@ -54,6 +54,32 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get featured => 'Featured';
@override
String get recommended => 'Recommended';
@override
String get fruitShortsBrand => 'FruitShorts';
@override
String get authLandingSubtitle =>
'Sign in to sync progress, favorites and coins';
@override
String get comingSoon => 'Coming soon';
@override
String get authLegal =>
'By continuing, you agree to the Terms of Service and Privacy Policy.';
@override
String get authContinueGoogle => 'Continue with Google';
@override
String get authPhoneSignIn => 'Phone sign in';
@override
String get authEmailSignIn => 'Email sign in';
@override
String get suspense => 'Suspense';
@@ -102,6 +128,16 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get views => 'views';
@override
String episodeOfTotal(int current, int total) {
return 'Episode $current / $total';
}
@override
String minutesAgo(int count) {
return '$count min ago';
}
@override
String get artworkOnly => 'Artwork';
@@ -149,7 +185,7 @@ class AppLocalizationsEn extends AppLocalizations {
String get history => 'History';
@override
String get watchlist => 'Watchlist';
String get watchlist => 'Favorites';
@override
String get likedTab => 'Liked';
+37 -1
View File
@@ -46,7 +46,7 @@ class AppLocalizationsId extends AppLocalizations {
String get currentSeries => 'Serial saat ini';
@override
String get discoverTab => 'Jelajahi';
String get discoverTab => 'Temukan';
@override
String get searchDiscover => 'Cari drama, aktor, genre...';
@@ -54,6 +54,32 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get featured => 'Unggulan';
@override
String get recommended => 'Rekomendasi';
@override
String get fruitShortsBrand => 'FruitShorts';
@override
String get authLandingSubtitle =>
'Masuk untuk menyinkronkan progres, favorit, dan koin';
@override
String get comingSoon => 'Segera hadir';
@override
String get authLegal =>
'Dengan melanjutkan, Anda menyetujui Ketentuan Layanan dan Kebijakan Privasi.';
@override
String get authContinueGoogle => 'Lanjutkan dengan Google';
@override
String get authPhoneSignIn => 'Masuk dengan ponsel';
@override
String get authEmailSignIn => 'Masuk dengan email';
@override
String get suspense => 'Thriller';
@@ -102,6 +128,16 @@ class AppLocalizationsId extends AppLocalizations {
@override
String get views => 'tayangan';
@override
String episodeOfTotal(int current, int total) {
return 'Episode $current / $total';
}
@override
String minutesAgo(int count) {
return '$count mnt lalu';
}
@override
String get artworkOnly => 'Gambar';
+36 -2
View File
@@ -45,7 +45,7 @@ class AppLocalizationsZh extends AppLocalizations {
String get currentSeries => '当前短剧';
@override
String get discoverTab => '找剧';
String get discoverTab => '发现';
@override
String get searchDiscover => '搜索短剧、演员、类型…';
@@ -53,6 +53,30 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get featured => '精选';
@override
String get recommended => '推荐';
@override
String get fruitShortsBrand => '水果短剧';
@override
String get authLandingSubtitle => '登录后同步进度、收藏与金币权益';
@override
String get comingSoon => '即将开放';
@override
String get authLegal => '继续即代表同意《用户协议》与《隐私政策》';
@override
String get authContinueGoogle => '使用 Google 继续';
@override
String get authPhoneSignIn => '手机号登录';
@override
String get authEmailSignIn => '邮箱登录';
@override
String get suspense => '悬疑';
@@ -101,6 +125,16 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get views => '次播放';
@override
String episodeOfTotal(int current, int total) {
return '第 $current 集 / 共 $total 集';
}
@override
String minutesAgo(int count) {
return '$count 分钟前';
}
@override
String get artworkOnly => '海报展示';
@@ -146,7 +180,7 @@ class AppLocalizationsZh extends AppLocalizations {
String get history => '历史';
@override
String get watchlist => '追剧';
String get watchlist => '收藏';
@override
String get likedTab => '喜欢';
+23 -2
View File
@@ -12,9 +12,17 @@
"openQuickMenu": "打开快捷菜单",
"quickAccess": "快捷入口",
"currentSeries": "当前短剧",
"discoverTab": "找剧",
"discoverTab": "发现",
"searchDiscover": "搜索短剧、演员、类型…",
"featured": "精选",
"recommended": "推荐",
"fruitShortsBrand": "水果短剧",
"authLandingSubtitle": "登录后同步进度、收藏与金币权益",
"comingSoon": "即将开放",
"authLegal": "继续即代表同意《用户协议》与《隐私政策》",
"authContinueGoogle": "使用 Google 继续",
"authPhoneSignIn": "手机号登录",
"authEmailSignIn": "邮箱登录",
"suspense": "悬疑",
"romance": "都市爱情",
"actionGenre": "动作",
@@ -31,6 +39,19 @@
"startWatching": "开始观看",
"showLess": "收起",
"views": "次播放",
"episodeOfTotal": "第 {current} 集 / 共 {total} 集",
"@episodeOfTotal": {
"placeholders": {
"current": {"type": "int"},
"total": {"type": "int"}
}
},
"minutesAgo": "{count} 分钟前",
"@minutesAgo": {
"placeholders": {
"count": {"type": "int"}
}
},
"artworkOnly": "海报展示",
"artworkOnlyNotice": "这张海报仅用于目录展示,暂时没有可播放视频。",
"videoPending": "视频待提供",
@@ -52,7 +73,7 @@
},
"resume": "继续播放",
"history": "历史",
"watchlist": "追剧",
"watchlist": "收藏",
"likedTab": "喜欢",
"all": "全部",
"inProgress": "未看完",
+4 -7
View File
@@ -245,11 +245,10 @@ class _HomeTabsState extends State<_HomeTabs> {
items: [
AppBottomNavItem(
tabKey: const Key('tab-home'),
icon: Icons.home_outlined,
selectedIcon: Icons.home_rounded,
icon: Icons.play_circle_outline_rounded,
selectedIcon: Icons.play_circle_fill_rounded,
label: l10n.homeTab,
selected: logic.tab == 0,
indicatorKey: const Key('tab-home-indicator'),
onTap: () => _selectTab(context, 0),
),
AppBottomNavItem(
@@ -258,16 +257,14 @@ class _HomeTabsState extends State<_HomeTabs> {
selectedIcon: Icons.explore_rounded,
label: l10n.discoverTab,
selected: logic.tab == 1,
indicatorKey: const Key('tab-discover-indicator'),
onTap: () => _selectTab(context, 1),
),
AppBottomNavItem(
tabKey: const Key('tab-my'),
icon: Icons.person_outline_rounded,
selectedIcon: Icons.person_rounded,
icon: Icons.video_library_outlined,
selectedIcon: Icons.video_library_rounded,
label: l10n.myTab,
selected: logic.tab == 2,
indicatorKey: const Key('tab-my-indicator'),
onTap: () => _selectTab(context, 2, myProfile: true),
),
],