适配深色模式

This commit is contained in:
DelLevin-Home
2026-05-26 05:10:21 +08:00
parent b36f50827f
commit 73f3795e65
53 changed files with 3846 additions and 3211 deletions

View File

@@ -17,7 +17,7 @@ class BookTabPage extends StatefulWidget {
}
class _BookTabPageState extends State<BookTabPage> {
int _layoutStyle = 0; // 0: 封面网格, 1: 列表
int _layoutStyle = 0;
bool _firstLoad = true;
@override
@@ -42,6 +42,7 @@ class _BookTabPageState extends State<BookTabPage> {
}
Widget _buildBookList(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return Consumer<AppProvider>(
builder: (context, provider, child) {
final statusMap = {0: 'read', 1: 'reading', 2: 'want_to_read'};
@@ -55,8 +56,8 @@ class _BookTabPageState extends State<BookTabPage> {
if (books.isEmpty) {
return RefreshIndicator(
onRefresh: () async => await provider.loadBooks(),
color: const Color(0xFF1A1A1A),
backgroundColor: Colors.white,
color: colors.primary,
backgroundColor: colors.surface,
child: ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: [_buildEmptyState(context, provider.bookStatusIndex)],
@@ -73,10 +74,11 @@ class _BookTabPageState extends State<BookTabPage> {
}
Widget _buildGridView(List books, AppProvider provider) {
final colors = Theme.of(context).colorScheme;
return RefreshIndicator(
onRefresh: () async => await provider.loadBooks(),
color: const Color(0xFF1A1A1A),
backgroundColor: Colors.white,
color: colors.primary,
backgroundColor: colors.surface,
child: GridView.builder(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 100),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
@@ -92,10 +94,11 @@ class _BookTabPageState extends State<BookTabPage> {
}
Widget _buildListView(List books, AppProvider provider) {
final colors = Theme.of(context).colorScheme;
return RefreshIndicator(
onRefresh: () async => await provider.loadBooks(),
color: const Color(0xFF1A1A1A),
backgroundColor: Colors.white,
color: colors.primary,
backgroundColor: colors.surface,
child: ListView.builder(
padding: const EdgeInsets.fromLTRB(12, 8, 12, 100),
itemCount: books.length,
@@ -105,6 +108,7 @@ class _BookTabPageState extends State<BookTabPage> {
}
Widget _buildListCard(book) {
final colors = Theme.of(context).colorScheme;
return GestureDetector(
onTap: () => Navigator.pushNamed(context, '/book-detail', arguments: book),
onLongPress: () => _showDeleteDialog(context, book),
@@ -112,23 +116,22 @@ class _BookTabPageState extends State<BookTabPage> {
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFFAFAFA),
color: colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
// 封面缩略图
Container(
width: 48, height: 64,
decoration: BoxDecoration(
color: const Color(0xFFF0F0F0),
color: colors.outlineVariant,
borderRadius: BorderRadius.circular(6),
),
clipBehavior: Clip.antiAlias,
child: book.coverPath != null && book.coverPath!.isNotEmpty
? Image.file(File(book.coverPath!), fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const Icon(Icons.menu_book_outlined, size: 22, color: Color(0xFFCCCCCC)))
: const Icon(Icons.menu_book_outlined, size: 22, color: Color(0xFFCCCCCC)),
errorBuilder: (_, __, ___) => Icon(Icons.menu_book_outlined, size: 22, color: colors.onSurface.withValues(alpha: 0.25)))
: Icon(Icons.menu_book_outlined, size: 22, color: colors.onSurface.withValues(alpha: 0.25)),
),
const SizedBox(width: 12),
Expanded(
@@ -136,11 +139,11 @@ class _BookTabPageState extends State<BookTabPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(book.title, maxLines: 1, overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: colors.onSurface)),
if (book.authors.isNotEmpty) ...[
const SizedBox(height: 3),
Text(book.authors.take(2).join(''), maxLines: 1, overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 12, color: Color(0xFFAAAAAA))),
style: TextStyle(fontSize: 12, color: colors.onSurface.withValues(alpha: 0.35))),
],
const SizedBox(height: 6),
if (book.rating != null)
@@ -151,7 +154,7 @@ class _BookTabPageState extends State<BookTabPage> {
),
),
const SizedBox(width: 8),
const Icon(Icons.chevron_right, color: Color(0xFFD0D0D0), size: 20),
Icon(Icons.chevron_right, color: colors.onSurface.withValues(alpha: 0.2), size: 20),
],
),
),
@@ -159,19 +162,20 @@ class _BookTabPageState extends State<BookTabPage> {
}
void _showDeleteDialog(BuildContext context, book) {
final colors = Theme.of(context).colorScheme;
showDialog(
context: context,
builder: (ctx) => AlertDialog(
backgroundColor: Colors.white,
backgroundColor: colors.surface,
elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
title: const Text('确认删除', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600)),
title: Text('确认删除', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: colors.onSurface)),
content: Text('确定要删除《${book.title}》吗?删除后可在回收站恢复。',
style: const TextStyle(fontSize: 14, color: Color(0xFF666666), height: 1.5)),
style: TextStyle(fontSize: 14, color: colors.onSurface.withValues(alpha: 0.6), height: 1.5)),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: const Text('取消', style: TextStyle(color: Color(0xFF666666))),
child: Text('取消', style: TextStyle(color: colors.onSurface.withValues(alpha: 0.6))),
),
ElevatedButton(
onPressed: () async {
@@ -179,7 +183,7 @@ class _BookTabPageState extends State<BookTabPage> {
Navigator.pop(ctx);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red, foregroundColor: Colors.white, elevation: 0,
backgroundColor: colors.error, foregroundColor: colors.onError, elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
),
@@ -193,11 +197,12 @@ class _BookTabPageState extends State<BookTabPage> {
Widget _buildSkeleton() {
return _layoutStyle == 1
? MovieSkeletonGrid() // reuse same grid skeleton pattern
? MovieSkeletonGrid()
: const BookSkeletonGrid();
}
Widget _buildEmptyState(BuildContext context, int statusIndex) {
final colors = Theme.of(context).colorScheme;
final statusText = ['已读', '在读', '想读'][statusIndex];
return Center(
child: Column(
@@ -205,11 +210,11 @@ class _BookTabPageState extends State<BookTabPage> {
children: [
Container(
width: 80, height: 80,
decoration: BoxDecoration(color: const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(20)),
child: const Icon(Icons.menu_book_outlined, size: 40, color: Color(0xFFCCCCCC)),
decoration: BoxDecoration(color: colors.surfaceContainerHighest, borderRadius: BorderRadius.circular(20)),
child: Icon(Icons.menu_book_outlined, size: 40, color: colors.onSurface.withValues(alpha: 0.25)),
),
const SizedBox(height: 20),
Text('暂无$statusText的书籍', style: const TextStyle(fontSize: 16, color: Color(0xFF999999))),
Text('暂无$statusText的书籍', style: TextStyle(fontSize: 16, color: colors.onSurface.withValues(alpha: 0.4))),
const SizedBox(height: 24),
InkWell(
onTap: () {
@@ -218,8 +223,8 @@ class _BookTabPageState extends State<BookTabPage> {
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
decoration: BoxDecoration(color: const Color(0xFF1A1A1A), borderRadius: BorderRadius.circular(8)),
child: const Text('添加记录', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
decoration: BoxDecoration(color: colors.primary, borderRadius: BorderRadius.circular(8)),
child: Text('添加记录', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: colors.onPrimary)),
),
),
],