readful/lib/main.dart
ddshi bef0de5909 feat: 完成文件导入功能和Book模型扩展
## 新增功能
- EPUB文件导入功能:支持文件选择、解析和存储
- 文件重复检测:避免重复导入同一文件
- 导入状态反馈:成功/失败消息提示

## 模型扩展
- Book模型新增多作者支持(authors字段)
- 新增章节数统计(chapterCount字段)
- 新增语言标识(language字段)
- 新增EPUB标识符(identifier字段)
- 优化TypeAdapter序列化支持

## 服务优化
- 新增EpubParserService:EPUB文件解析服务
- 改进DatabaseService:错误处理和数据迁移
- 优化BookRepository:调试日志和错误追踪

## 依赖更新
- 新增epubx ^4.0.0:EPUB电子书解析库
- 更新pubspec.lock:同步依赖版本

## UI改进
- AppHeader组件集成完整导入功能
- SafeArea适配:避免系统状态栏重叠
- 优化测试数据结构

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 20:34:16 +08:00

378 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('✅ 数据库初始化完成,启动应用');
} catch (e) {
print('❌ 数据库初始化失败: $e');
print('🚨 应用将退出,因为数据库初始化是必须的');
return;
}
// 启动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.create(
title: 'Flutter开发实战',
filePath: '/path/to/flutter.epub',
format: BookFormat.epub,
fileSize: 2048000,
author: '张三',
totalPages: 100,
).copyWith(
addedDate: DateTime.now().subtract(const Duration(days: 30)),
status: ReadingStatus.reading,
),
Book.create(
title: 'Dart编程语言',
filePath: '/path/to/dart.epub',
format: BookFormat.epub,
fileSize: 1536000,
author: '李四',
totalPages: 333,
).copyWith(
addedDate: DateTime.now().subtract(const Duration(days: 60)),
status: ReadingStatus.completed,
),
Book.create(
title: '移动应用设计指南',
filePath: '/path/to/design.pdf',
format: BookFormat.pdf,
fileSize: 5120000,
author: '王五',
totalPages: 1000,
tags: ['设计', '移动应用', 'UI'],
).copyWith(
addedDate: DateTime.now().subtract(const Duration(days: 10)),
status: ReadingStatus.pending,
),
Book.create(
title: '人工智能简史',
filePath: '/path/to/ai_history.epub',
format: BookFormat.epub,
fileSize: 3072000,
// author: null, // 测试作者为null的情况
totalPages: 192,
).copyWith(
addedDate: DateTime.now().subtract(const Duration(days: 5)),
status: ReadingStatus.reading,
),
Book.create(
title: '算法与数据结构',
filePath: '/path/to/algorithm.epub',
format: BookFormat.epub,
fileSize: 3072000,
author: '赵六',
totalPages: 250,
).copyWith(
addedDate: DateTime.now().subtract(const Duration(days: 20)),
status: ReadingStatus.completed,
),
];
}
@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(),
),
);
}
}