The RecentBooksService maintains a list of recently accessed books with persistent storage. It uses MobX for reactive state management, making it easy to observe changes to the recent books list.
Initialization
init
Initializes the recent books service with persistent storage.
static Future<RecentBooksService> init(String databaseDirectory)
The directory path where the recent books database files will be stored.
return
Future<RecentBooksService>
A fully initialized service instance with loaded recent books.
Example:
final recentBooksService = await RecentBooksService.init('/path/to/database');
Properties
recentBooks
ObservableList<RecentBook>
An observable list of recently accessed books, sorted by the time they were added. This list is reactive and will trigger UI updates when modified.
Methods
addRecentBook
Adds a book to the recent books list. If the book already exists in the list, it removes the old entry and adds a new one with the current timestamp.
Future<void> addRecentBook(Book book)
The book to add to the recent books list. The book’s metadata will be extracted and stored as a RecentBook entry.
The method creates a RecentBook entry containing:
- Book ID and title
- Comma-separated author names
- Cover URL
- Series name and number (if applicable)
- Portal reference
- Current timestamp
Example:
final book = await portal.getBook('12345');
await recentBooksService.addRecentBook(book);
removeRecentBook
Removes a book from the recent books list and deletes it from storage.
Future<void> removeRecentBook(RecentBook book)
The recent book entry to remove.
Books are matched by a combination of portal code and book ID to ensure uniqueness across different portals.
Example:
final bookToRemove = recentBooksService.recentBooks.first;
await recentBooksService.removeRecentBook(bookToRemove);
restoreRecentBook
Restores a previously removed book back to the recent books list. This is useful for implementing undo functionality.
Future<void> restoreRecentBook(RecentBook book)
The recent book entry to restore.
The book is added back to the list and the list is re-sorted by the added timestamp to maintain chronological order.
Example:
// Remove a book but keep the reference
final removedBook = recentBooksService.recentBooks[0];
await recentBooksService.removeRecentBook(removedBook);
// Later, restore it
await recentBooksService.restoreRecentBook(removedBook);
MobX integration
The RecentBooksService extends a MobX store, making the recentBooks list observable. This enables automatic UI updates when books are added, removed, or restored.
Example with Flutter and MobX:
import 'package:flutter_mobx/flutter_mobx.dart';
class RecentBooksWidget extends StatelessWidget {
final RecentBooksService service;
const RecentBooksWidget({required this.service});
@override
Widget build(BuildContext context) {
return Observer(
builder: (_) {
if (service.recentBooks.isEmpty) {
return Text('No recent books');
}
return ListView.builder(
itemCount: service.recentBooks.length,
itemBuilder: (context, index) {
final book = service.recentBooks[index];
return ListTile(
title: Text(book.title),
subtitle: Text(book.authors),
leading: Image.network(book.coverUrl),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => service.removeRecentBook(book),
),
);
},
);
},
);
}
}
Usage
Basic usage:
import 'package:re_ucm_lib/recent_books/recent_books_service.cg.dart';
Future<void> main() async {
// Initialize the service
final recentBooks = await RecentBooksService.init('/path/to/database');
// Add a book when user views it
final portal = PortalFactory.fromCode('flibust');
final book = await portal.service.getBook('12345');
await recentBooks.addRecentBook(book);
// Display recent books
for (final recent in recentBooks.recentBooks) {
print('${recent.title} by ${recent.authors}');
if (recent.seriesName != null) {
print(' Series: ${recent.seriesName} #${recent.seriesNumber}');
}
}
// Remove a book
await recentBooks.removeRecentBook(recentBooks.recentBooks.first);
}
Undo/redo pattern:
class RecentBooksManager {
final RecentBooksService service;
final List<RecentBook> _deletedBooks = [];
RecentBooksManager(this.service);
Future<void> deleteWithUndo(RecentBook book) async {
await service.removeRecentBook(book);
_deletedBooks.add(book);
// Show snackbar with undo option
showSnackBar(
'Book removed',
action: SnackBarAction(
label: 'Undo',
onPressed: () => undoDelete(),
),
);
}
Future<void> undoDelete() async {
if (_deletedBooks.isNotEmpty) {
final book = _deletedBooks.removeLast();
await service.restoreRecentBook(book);
}
}
}
Data persistence
The service automatically persists all changes to the database:
addRecentBook: Saves the new entry to storage
removeRecentBook: Deletes the entry from storage
restoreRecentBook: Re-saves the entry to storage
All recent books are loaded from storage during initialization, ensuring data persists across app restarts.