301 lines
9.2 KiB
Markdown
301 lines
9.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
This is a Flutter mobile application for managing a personal book library. The app features book cataloging, categorization, reading status tracking, and cover scanning capabilities (via camera + Gemini AI).
|
|
|
|
**Tech Stack:**
|
|
- Flutter SDK ^3.10.8
|
|
- State Management: flutter_bloc ^9.1.0
|
|
- UI: Material 3 with Google Fonts (Inter)
|
|
- AI: google_generative_ai ^0.4.6 (for book cover analysis)
|
|
- Camera: camera ^0.11.1
|
|
|
|
## Development Commands
|
|
|
|
### Running the App
|
|
```bash
|
|
# Run on connected device/simulator
|
|
flutter run
|
|
|
|
# Run on specific device
|
|
flutter run -d <device-id>
|
|
|
|
# Run in release mode
|
|
flutter run --release
|
|
|
|
# List available devices
|
|
flutter devices
|
|
```
|
|
|
|
### Building
|
|
```bash
|
|
# Build APK for Android
|
|
flutter build apk
|
|
|
|
# Build iOS
|
|
flutter build ios
|
|
|
|
# Build for web (not currently configured)
|
|
flutter build web
|
|
```
|
|
|
|
### Code Quality
|
|
```bash
|
|
# Install/update dependencies
|
|
flutter pub get
|
|
|
|
# Check for outdated packages
|
|
flutter pub outdated
|
|
|
|
# Run static analysis
|
|
flutter analyze
|
|
|
|
# Format all Dart files
|
|
flutter format lib/
|
|
|
|
# Run tests
|
|
flutter test
|
|
```
|
|
|
|
### Using Dart MCP Tools
|
|
When the Dart MCP server is available, prefer using these tools instead of bash commands:
|
|
- `mcp__dart__analyze_files` instead of `flutter analyze`
|
|
- `mcp__dart__dart_format` instead of `flutter format`
|
|
- `mcp__dart__run_tests` instead of `flutter test`
|
|
- `mcp__dart__list_devices` to see available devices
|
|
- `mcp__dart__launch_app` to run the app with DTD integration
|
|
|
|
## Architecture
|
|
|
|
### State Management (BLoC Pattern)
|
|
|
|
The app uses **flutter_bloc** for state management with two main BLoCs:
|
|
|
|
#### 1. BookBloc (`lib/bloc/book_bloc.dart`)
|
|
Manages the book collection state and operations:
|
|
- **State**: `BookState` containing `List<Book>`
|
|
- **Events**:
|
|
- `AddBook(book)` - Add new book to library
|
|
- `UpdateBook(book)` - Update existing book
|
|
- `DeleteBook(id)` - Remove book from library
|
|
- `ToggleFavorite(id)` - Toggle favorite status
|
|
- **Initial State**: Loads from `initialBooks` in `constants.dart`
|
|
- **Note**: Currently uses in-memory storage; no persistence layer
|
|
|
|
#### 2. NavigationBloc (`lib/bloc/navigation_bloc.dart`)
|
|
Manages app navigation and screen state:
|
|
- **State**: `NavigationState` with:
|
|
- `screen` (AppScreen enum) - Current screen
|
|
- `selectedBook` - Book being viewed/edited
|
|
- `prefilledData` - Data for pre-populating forms
|
|
- **Event**: `NavigateTo(screen, {selectedBook, prefilledData})`
|
|
- **Pattern**: Declarative navigation where UI rebuilds based on state
|
|
- **Important**: `prefilledData` is used when scanning covers to prefill book form, while `selectedBook` is used for editing existing books
|
|
|
|
### Data Models (`lib/models/models.dart`)
|
|
|
|
Uses Dart 3 **record types** for immutability:
|
|
|
|
```dart
|
|
typedef Book = ({
|
|
String id,
|
|
String title,
|
|
String author,
|
|
String genre,
|
|
String annotation,
|
|
String? coverUrl,
|
|
int? pages,
|
|
String? language,
|
|
int? publishedYear,
|
|
double? rating,
|
|
String status, // 'reading', 'done', 'want_to_read'
|
|
double? progress, // 0-100 for reading progress
|
|
bool isFavorite,
|
|
});
|
|
```
|
|
|
|
**Important**: Records are immutable. To update a book, create a new record with updated fields using record syntax:
|
|
```dart
|
|
final updatedBook = (
|
|
id: book.id,
|
|
title: newTitle,
|
|
// ... copy all other fields
|
|
);
|
|
```
|
|
|
|
### Navigation Flow
|
|
|
|
The app uses a custom navigation system via `NavigationBloc`:
|
|
|
|
1. **Library Screen** (default) → Shows all books in grid/category view
|
|
2. **Categories Screen** → Browse books by predefined categories
|
|
3. **Book Details** → View/edit single book (triggered by tapping book card)
|
|
4. **Add/Edit Book** → Form for adding new books or editing existing
|
|
5. **Scanner Screen** → Camera interface for scanning book covers
|
|
6. **Wishlist/Settings** → Placeholder screens
|
|
|
|
**Navigation Pattern:**
|
|
```dart
|
|
context.read<NavigationBloc>().add(
|
|
NavigateTo(AppScreen.details, selectedBook: book)
|
|
);
|
|
```
|
|
|
|
The main shell (`_AppShell` in `main.dart`) rebuilds based on `NavigationState.screen`.
|
|
|
|
### Theme System (Material 3)
|
|
|
|
**Critical**: This app uses a **centralized theme system**. Never hardcode colors, text styles, or spacing.
|
|
|
|
**Theme Files:**
|
|
- `lib/theme/app_colors.dart` - Semantic color constants (cyan-based palette)
|
|
- `lib/theme/app_spacing.dart` - Spacing scale (8px base) and border radius
|
|
- `lib/theme/app_theme.dart` - Material 3 ThemeData with component themes
|
|
|
|
**Usage Pattern:**
|
|
```dart
|
|
final colorScheme = Theme.of(context).colorScheme;
|
|
final textTheme = Theme.of(context).textTheme;
|
|
|
|
// Use semantic colors
|
|
Container(color: colorScheme.primary)
|
|
|
|
// Use text styles
|
|
Text('Title', style: textTheme.displayMedium)
|
|
|
|
// Use spacing constants
|
|
Padding(padding: EdgeInsets.all(AppSpacing.md))
|
|
|
|
// Use shadows
|
|
BoxDecoration(boxShadow: AppTheme.shadowMd)
|
|
```
|
|
|
|
**Color Scheme:**
|
|
- Primary: #0891B2 (Cyan-600)
|
|
- Success/CTA: #22C55E (Green-500)
|
|
- Background: #ECFEFF (Cyan-50)
|
|
- Surface: #FFFFFF
|
|
|
|
**Typography:** Inter font family loaded via Google Fonts with weights 300-700.
|
|
|
|
### Screen Structure
|
|
|
|
All main screens follow this pattern:
|
|
1. Wrap in `SafeArea` for notch/status bar handling
|
|
2. Use `BlocBuilder` to listen to relevant BLoC state
|
|
3. Access theme via `Theme.of(context)`
|
|
4. Use `AppSpacing.*` constants for all padding/margins
|
|
5. Use theme colors and text styles exclusively
|
|
|
|
**Example:**
|
|
```dart
|
|
class MyScreen extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final colorScheme = Theme.of(context).colorScheme;
|
|
final textTheme = Theme.of(context).textTheme;
|
|
|
|
return SafeArea(
|
|
child: BlocBuilder<BookBloc, BookState>(
|
|
builder: (context, state) {
|
|
return Padding(
|
|
padding: EdgeInsets.all(AppSpacing.lg),
|
|
child: Text(
|
|
'Hello',
|
|
style: textTheme.headlineMedium,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Widget Conventions
|
|
|
|
**BookCard** (`lib/widgets/book_card.dart`):
|
|
- Displays book cover with metadata overlay
|
|
- Includes Hero animation with tag `'book-cover-${book.id}'`
|
|
- Shows shimmer loading while image loads
|
|
- Has hover effect on desktop/web (1.02 scale)
|
|
- Displays favorite badge, status badge, or progress bar based on book state
|
|
|
|
**Hero Animations:**
|
|
When navigating from library to book details, book covers animate smoothly:
|
|
```dart
|
|
Hero(
|
|
tag: 'book-cover-${book.id}',
|
|
child: Image.network(book.coverUrl),
|
|
)
|
|
```
|
|
Both `BookCard` and `BookDetailsScreen` must use matching tags.
|
|
|
|
### Gemini AI Integration
|
|
|
|
The `GeminiService` (`lib/services/gemini_service.dart`) is a placeholder for future AI-powered book cover scanning:
|
|
- Takes base64-encoded image from camera
|
|
- Will analyze cover and extract metadata (title, author, etc.)
|
|
- Returns `Book?` record with prefilled data
|
|
- Currently returns `null` - implementation pending
|
|
|
|
**Intended Flow:**
|
|
1. User opens Scanner Screen
|
|
2. Takes photo of book cover
|
|
3. Image sent to `GeminiService.analyzeBookCover()`
|
|
4. Extracted data passed to Add Book screen via `NavigationBloc` with `prefilledData`
|
|
|
|
## Important Patterns
|
|
|
|
### When Adding New Features
|
|
|
|
1. **New Book Fields**: Update the `Book` typedef in `models.dart` and all places that construct book records
|
|
2. **New Screens**: Add to `AppScreen` enum, handle in `_AppShell` switch statement
|
|
3. **Theme Changes**: Only modify theme files, never inline styles
|
|
4. **Navigation**: Always use `NavigationBloc`, never `Navigator.push()`
|
|
|
|
### Code Style Requirements
|
|
|
|
- **Immutability**: Use records for data models, never mutable classes
|
|
- **Theme Compliance**: Zero hardcoded colors/styles/spacing
|
|
- **BLoC Pattern**: UI is always a pure function of state
|
|
- **Const Constructors**: Use `const` for all stateless widgets and values
|
|
- **Reduced Motion**: Check `MediaQuery.of(context).disableAnimations` for animations
|
|
|
|
### Testing Gotchas
|
|
|
|
- Books are stored in-memory only; restarting app resets to `initialBooks`
|
|
- Camera requires physical device or simulator with camera support
|
|
- Gemini API requires valid API key (not implemented yet)
|
|
- Hero animations require matching tags between screens
|
|
|
|
## Project-Specific Notes
|
|
|
|
### Why Records Instead of Classes?
|
|
|
|
This codebase uses Dart 3 record types for immutability and simplicity. When updating books, create new records rather than mutating fields. This makes BLoC state updates predictable and prevents accidental mutations.
|
|
|
|
### Navigation Without Navigator
|
|
|
|
The app doesn't use Flutter's built-in Navigator. Instead, `NavigationBloc` tracks the current screen, and `_AppShell` rebuilds the entire UI tree based on state. This gives centralized control over navigation state but means:
|
|
- No native back button handling (would need to emit `NavigateTo` events)
|
|
- No deep linking support (yet)
|
|
- All screens must be handled in the main switch statement
|
|
|
|
### Initial Data
|
|
|
|
Books are initialized from `initialBooks` constant in `lib/constants/constants.dart`. Categories are defined in the same file. To add sample data, modify these constants.
|
|
|
|
### Future Enhancements
|
|
|
|
Based on the codebase structure, likely next steps:
|
|
- Implement persistence (SharedPreferences, SQLite, or Firebase)
|
|
- Complete Gemini AI integration for cover scanning
|
|
- Add native back button handling
|
|
- Implement book search/filtering
|
|
- Add reading statistics/charts
|
|
- Support for book series and collections
|