readful/lib/main.dart
ddshi feb01c81ca feat: 完成搜索功能开发和Provider状态管理集成
## 新增功能
- 实时搜索:支持书名和作者的模糊搜索,300ms防抖优化
- Provider状态管理:使用ChangeNotifier模式管理搜索状态
- 搜索页面:完整的搜索UI,包括空状态、搜索中、无结果和结果列表
- 智能交互:一键清空搜索、焦点管理、状态同步

## 技术实现
- SearchProvider:防抖搜索、状态管理、多字段匹配
- SearchPage:StatefulWidget管理、控制器协调、生命周期优化
- 状态同步:TextEditingController与Provider协调,避免循环更新
- 用户体验:即时反馈、智能清空、页面状态重置

## 代码质量
- Flutter分析零警告
- 完整的代码注释和文档
- 内存安全:正确的资源清理
- 性能优化:防抖机制和精确UI重建

## 文档完善
- Provider状态管理学习指南
- 搜索功能开发实战总结
- 顶部导航组件开发总结

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 13:49:56 +08:00

381 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// import 'package:hive_flutter/hive_flutter.dart';
// 数据层服务
import 'services/database_service.dart';
import 'services/book_repository.dart';
import 'services/bookshelf_repository.dart';
import 'services/highlight_repository.dart';
// 数据模型(仅导入测试中使用的)
import 'models/book.dart';
import 'models/bookshelf.dart';
import 'models/bookmark.dart';
import 'models/highlight.dart';
// providers
import 'providers/search_provider.dart';
// UI层
import 'pages/main_navigation.dart';
import 'theme/app_theme.dart';
/// Readful 电子书阅读器应用入口
///
/// 这是一个跨平台的Flutter电子书阅读器应用支持
/// - 多格式电子书导入EPUB、MOBI、TXT、PDF
/// - 智能文本高亮和批注系统
/// - 个性化书签和阅读进度管理
/// - Material Design 3 界面设计
/// - 暗夜模式自动跟随系统
void main() async {
// 确保Flutter绑定初始化完成这是使用异步操作的前提
WidgetsFlutterBinding.ensureInitialized();
// 初始化Hive数据库系统
// 数据库包含:书籍、书架、书签、高亮批注等数据
try {
await DatabaseService.instance.init();
print('✅ Hive数据库初始化成功');
} catch (e) {
print('❌ 数据库初始化失败: $e');
}
// 启动Readful应用
runApp(const ReadfulApp());
}
/// 测试BookRepository的数据持久化功能
Future<void> runBookRepositoryTest() async {
final bookRepository = BookRepository();
print('\n🧪 开始测试BookRepository数据持久化功能...\n');
try {
// 1. 获取当前所有书籍
List<Book> currentBooks = await bookRepository.getAllBooks();
print('📚 当前书籍数量: ${currentBooks.length}');
// 2. 创建测试书籍
final testBook = Book(
id: 'test_book_001',
title: 'Flutter开发入门',
author: '张三',
publisher: '技术出版社',
description: '这是一本关于Flutter开发的入门书籍',
filePath: '/path/to/flutter_book.epub',
format: BookFormat.epub,
fileSize: 1024 * 1024, // 1MB
addedDate: DateTime.now(),
status: ReadingStatus.pending,
totalPages: 300,
);
// 3. 添加测试书籍
await bookRepository.addBook(testBook);
// 4. 再次获取所有书籍
List<Book> updatedBooks = await bookRepository.getAllBooks();
print('📚 添加后书籍数量: ${updatedBooks.length}');
// 5. 根据ID查找书籍
Book? foundBook = await bookRepository.getBookById(testBook.id);
if (foundBook != null) {
print('🔍 成功找到书籍: ${foundBook.title}');
print(' - 作者: ${foundBook.author}');
print(' - 格式: ${foundBook.format.name}');
print(' - 状态: ${foundBook.status.name}');
} else {
print('❌ 未找到指定书籍');
}
// 6. 测试更新书籍
final updatedBook = testBook.copyWith(status: ReadingStatus.completed);
await bookRepository.updateBook(updatedBook);
print('✅ 书籍状态更新为: ${updatedBook.status.name}');
// 7. 验证更新后的状态
Book? updatedFoundBook = await bookRepository.getBookById(testBook.id);
if (updatedFoundBook != null &&
updatedFoundBook.status == ReadingStatus.completed) {
print('✅ 状态更新验证成功!');
} else {
print('❌ 状态更新验证失败!');
}
print('\n✅ BookRepository测试完成所有功能正常工作\n');
} catch (e) {
print('❌ BookRepository测试失败: $e\n');
}
}
///测试书架持久化
Future<void> runBookshelfRepositoryTest() async {
final bookshelfRepository = BookshelfRepository();
print('\n🧪 开始测试BookshelfRepository数据持久化功能...\n');
try {
// 1. 获取当前所有书架
List<Bookshelf> currentBookshelves =
await bookshelfRepository.getAllBookshelves();
print('📚 当前书架数量: ${currentBookshelves.length}');
// 2. 创建测试书架
final testBookshelf = Bookshelf(
id: 'test_shelf_001',
name: '我的测试书架',
createdTime: DateTime.now(),
lastModifiedTime: DateTime.now(),
bookCount: 0,
type: BookshelfType.custom,
isDefault: false,
sortOrder: 1,
);
// 3. 添加测试书架
await bookshelfRepository.addBookshelf(testBookshelf);
// 4. 再次获取所有书架
List<Bookshelf> updatedBookshelves =
await bookshelfRepository.getAllBookshelves();
print('📚 添加后书架数量: ${updatedBookshelves.length}');
print('\n✅ BookshelfRepository测试完成所有功能正常工作\n');
} catch (e) {
print('❌ BookshelfRepository测试失败: $e\n');
}
}
///测试bookmark持久化
Future<void> runBookmarkRepositoryTest() async {
final databaseService = DatabaseService.instance;
print('\n🧪 开始测试Bookmark数据持久化功能...\n');
try {
// 1. 获取Bookmark Box
final bookmarksBox = databaseService.getBookmarksBox();
print('📚 当前书签数量: ${bookmarksBox.length}');
// 2. 创建测试书签
final testBookmark = Bookmark(
id: 'test_bookmark_001',
bookId: 'test_book_001',
chapterId: null,
title: '第一章开始',
description: '这是第一章的书签',
pageIndex: 1,
position: 0.0,
previewText: '这是书签的预览文本',
createdTime: DateTime.now(),
sortOrder: 1,
);
// 3. 添加测试书签
await bookmarksBox.put(testBookmark.id, testBookmark);
// 4. 再次获取所有书签
print('📚 添加后书签数量: ${bookmarksBox.length}');
// 5. 根据ID查找书签
Bookmark? foundBookmark = bookmarksBox.get(testBookmark.id);
if (foundBookmark != null) {
print('🔍 成功找到书签: ${foundBookmark.title}');
print(' - 所属书籍ID: ${foundBookmark.bookId}');
print(' - 页码索引: ${foundBookmark.pageIndex}');
} else {
print('❌ 未找到指定书签');
}
print('\n✅ Bookmark测试完成所有功能正常工作\n');
} catch (e) {
print('❌ Bookmark测试失败: $e\n');
}
}
///測試Highlight持久化
Future<void> runHighlightRepositoryTest() async {
final highlightRepository = HighlightRepository();
print('\n🧪 开始测试HighlightRepository数据持久化功能...\n');
try {
// 1. 获取当前所有高亮
List<Highlight> currentHighlights =
await highlightRepository.getAllHighlights();
print('📚 当前高亮数量: ${currentHighlights.length}');
// 2. 创建测试高亮
final testHighlight = Highlight(
id: 'test_highlight_001',
bookId: 'test_book_001',
chapterId: null,
color: HighlightColor.yellow,
annotationType: AnnotationType.note,
createdTime: DateTime.now(),
selectedText: '这是一个测试高亮文本',
startIndex: 100,
endIndex: 130,
);
// 3. 添加测试高亮
await highlightRepository.addHighlight(testHighlight);
// 4. 根据ID查找高亮
Highlight? foundHighlight =
await highlightRepository.getHighlightById(testHighlight.id);
if (foundHighlight != null) {
print('🔍 成功找到高亮: ${foundHighlight.selectedText}');
print(' - 所属书籍ID: ${foundHighlight.bookId}');
print(' - 颜色: ${foundHighlight.color.name}');
} else {
print('❌ 未找到指定高亮');
}
// 5. 再次获取所有高亮
List<Highlight> updatedHighlights =
await highlightRepository.getAllHighlights();
print('📚 添加后高亮数量: ${updatedHighlights.length}');
print('\n✅ HighlightRepository测试完成所有功能正常工作\n');
} catch (e) {
print('❌ HighlightRepository测试失败: $e\n');
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Readful',
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(title: const Text('readful 电子书阅读器')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('欢迎使用 readful', style: TextStyle(fontSize: 20)),
SizedBox(height: 20),
Text('✅ 数据库已初始化', style: TextStyle(color: Colors.green)),
Text('✅ BookRepository测试完成',
style: TextStyle(color: Colors.green)),
SizedBox(height: 10),
Text('请查看控制台输出查看详细测试结果'),
],
),
),
),
);
}
}
/// Readful应用根Widget
///
/// 配置Material Design应用包括
/// - 主题系统(亮色/暗色模式自动跟随)
/// - 应用标题和图标
/// - 主导航页面
class ReadfulApp extends StatelessWidget {
const ReadfulApp({super.key});
// 创建测试数据
List<Book> _createTestData() {
return [
Book(
id: '1',
title: 'Flutter开发实战',
author: '张三',
description: '一本关于Flutter移动开发的实战指南',
format: BookFormat.epub,
filePath: '/path/to/flutter.epub',
fileSize: 2048000,
addedDate: DateTime.now().subtract(const Duration(days: 30)),
status:ReadingStatus.reading,
totalPages: 100
),
Book(
id: '2',
title: 'Dart编程语言',
author: '李四',
description: '深入理解Dart编程语言的核心概念',
format: BookFormat.epub,
filePath: '/path/to/dart.epub',
fileSize: 1536000,
addedDate: DateTime.now().subtract(const Duration(days: 60)),
status: ReadingStatus.completed,
totalPages: 333
),
Book(
id: '3',
title: '移动应用设计指南',
author: '王五',
description: '移动应用UI/UX设计的最佳实践',
format: BookFormat.pdf,
filePath: '/path/to/design.pdf',
fileSize: 5120000,
addedDate: DateTime.now().subtract(const Duration(days: 10)),
tags: ['设计', '移动应用', 'UI'],
status: ReadingStatus.pending,
totalPages: 1000
),
Book(
id: '4',
title: '人工智能简史',
author: null, // 测试作者为null的情况
description: '人工智能发展历程的详细介绍',
format: BookFormat.mobi,
filePath: '/path/to/ai.mobi',
fileSize: 1024000,
addedDate: DateTime.now().subtract(const Duration(days: 5)),
status: ReadingStatus.reading,
totalPages: 192
),
Book(
id: '5',
title: '算法与数据结构',
author: '赵六',
description: '程序员必备的算法和数据结构知识',
format: BookFormat.epub,
filePath: '/path/to/algorithm.epub',
fileSize: 3072000,
addedDate: DateTime.now().subtract(const Duration(days: 20)),
status: ReadingStatus.completed,
totalPages: 250
),
];
}
@override
Widget build(BuildContext context) {
// 在MaterialApp外面包裹ChangeNotifierProvider
return ChangeNotifierProvider(
create: (context) {
final searchProvider = SearchProvider();
// 加载测试数据
final testData = _createTestData();
searchProvider.loadBooks(testData);
return searchProvider;
},
child: MaterialApp(
title: 'Readful',
debugShowCheckedModeBanner: false, // 隐藏调试横幅
// 主题配置
theme: AppTheme.lightTheme, // 亮色主题
darkTheme: AppTheme.darkTheme, // 暗色主题
themeMode: ThemeMode.system, // 跟随系统主题设置
// 主页面底部Tab导航
home: const MainNavigation(),
),
);
}
}