From f8c4a189207333e020bbf49d0bcb6075f505e335 Mon Sep 17 00:00:00 2001 From: ytc1012 <18001193130@163.com> Date: Tue, 25 Nov 2025 11:15:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=A0=8F=E5=9B=BE=E6=A0=87?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +- CLAUDE.md | 284 ++++++++++++++++++ ...kotlin-compiler-6168023911861129695.salive | 0 .../src/main/res/drawable/ic_notification.xml | 15 + lib/services/notification_service.dart | 5 +- 5 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 CLAUDE.md create mode 100644 android/.kotlin/sessions/kotlin-compiler-6168023911861129695.salive create mode 100644 android/app/src/main/res/drawable/ic_notification.xml diff --git a/.claude/settings.local.json b/.claude/settings.local.json index c344a19..d3f9009 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -43,7 +43,8 @@ "Bash(flutter clean:*)", "Bash(start ms-settings:developers)", "Bash(gradlew.bat --stop:*)", - "Bash(call gradlew.bat:*)" + "Bash(call gradlew.bat:*)", + "Bash(where:*)" ], "deny": [], "ask": [] diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9551b1a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,284 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +FocusBuddy is a Flutter-based focus timer app designed for neurodivergent minds, implementing a "no-punishment" philosophy. The core concept is that distractions during focus sessions are tracked but don't interrupt the timer, providing a gentler approach to productivity tracking. + +## Commands + +### Development Setup +```bash +# Check Flutter version and environment +flutter doctor + +# Get dependencies +flutter pub get + +# Generate localization files (required after editing .arb files) +flutter gen-l10n + +# Generate Hive adapters (required after modifying model classes) +flutter pub run build_runner build + +# Clean build artifacts +flutter clean +``` + +### Running the App +```bash +# List available devices/emulators +flutter devices + +# Run on default device +flutter run + +# Run on specific device +flutter run -d + +# Run on Chrome (web) +flutter run -d chrome + +# Run with hot reload (default in debug mode) +flutter run --hot +``` + +### Building +```bash +# Build APK for Android +flutter build apk + +# Build App Bundle for Google Play +flutter build appbundle + +# Build for iOS (requires macOS) +flutter build ios + +# Build for Windows +flutter build windows +``` + +### Testing & Analysis +```bash +# Run static analysis +flutter analyze + +# Run tests +flutter test + +# Check for outdated packages +flutter pub outdated +``` + +## Architecture + +### Core Philosophy +The app follows a **no-punishment approach** to focus tracking: +- Timer continues running even when user reports a distraction +- Distractions are tracked via "I got distracted" button +- Encouragement messages replace negative feedback +- All distraction counts are for awareness, not judgment + +### Key Technical Decisions + +**State Management**: Simple `StatefulWidget` approach (no external state management) +- Focus session state managed locally in `FocusScreen` +- Settings and preferences stored in `shared_preferences` +- Historical data stored in Hive local database + +**Data Persistence**: +- **Hive** for focus session history (typeId 0 for `FocusSession`) +- **SharedPreferences** for app settings (onboarding status, default duration, locale) +- Sessions stored with full distraction tracking but continue regardless of interruptions + +**Notifications**: +- Background notifications when app is inactive during focus session +- Uses `flutter_local_notifications` with `WidgetsBindingObserver` lifecycle tracking +- Notification updates every 30 seconds when app is backgrounded + +**Internationalization (i18n)**: +- Uses Flutter's official `intl` package with ARB files +- 13 supported languages (en, zh, ja, ko, es, de, fr, pt, ru, hi, id, it, ar) +- Locale can be changed at runtime without app restart via `MyApp.updateLocale()` +- Localization files generated in `lib/l10n/` via `flutter gen-l10n` + +### Project Structure + +``` +lib/ +├── main.dart # Entry point, app initialization +├── models/ # Data models +│ ├── focus_session.dart # Hive model for session data +│ ├── focus_session.g.dart # Generated Hive adapter +│ └── distraction_type.dart # Enum for distraction categories +├── screens/ # UI screens +│ ├── onboarding_screen.dart # First-time user guide +│ ├── home_screen.dart # Main screen with "Start Focus" button +│ ├── focus_screen.dart # Active timer + distraction button +│ ├── complete_screen.dart # Post-session summary +│ ├── history_screen.dart # Past sessions list +│ └── settings_screen.dart # Duration & locale settings +├── services/ # Business logic +│ ├── storage_service.dart # Hive database operations +│ ├── encouragement_service.dart # Random message picker +│ └── notification_service.dart # Background notifications +├── theme/ # Design system +│ ├── app_theme.dart # Material theme config +│ ├── app_colors.dart # Color palette constants +│ └── app_text_styles.dart # Typography definitions +└── l10n/ # Generated localization files + ├── app_localizations.dart + └── app_localizations_*.dart +``` + +### Data Flow + +**Focus Session Lifecycle**: +1. User selects duration in `HomeScreen` (loads from SharedPreferences) +2. `FocusScreen` starts countdown timer with `Timer.periodic` +3. User can tap "I got distracted" → adds to `_distractions` list, timer continues +4. Timer completion or manual stop → `FocusSession` saved to Hive via `StorageService` +5. `CompleteScreen` shows stats fetched from `StorageService.getTodaySessions()` +6. `HistoryScreen` displays all sessions from `StorageService.getAllSessions()` + +**Critical Implementation**: The distraction button **never** pauses the timer - this is the app's core differentiator. + +### FocusSession Model + +```dart +@HiveType(typeId: 0) +class FocusSession { + DateTime startTime; + int durationMinutes; // Planned (e.g., 25) + int actualMinutes; // May be less if stopped early + int distractionCount; // Total distractions logged + bool completed; // True if timer reached zero + List distractionTypes; // Categories selected +} +``` + +### Theme System + +Uses Google Fonts (Nunito) with centralized design tokens: +- **Primary Color**: `#6C63FF` (Purple) +- **Background**: `#F5F7FA` (Light Gray) +- **Text Primary**: `#2D3748` (Dark Gray) +- **Success**: `#48BB78` (Green - used sparingly) + +All UI components reference `AppTextStyles` and `AppColors` constants - never use hardcoded values. + +## MVP Feature Set + +**Current Implementation** (as of git commit `005ad8d`): +- ✅ Onboarding flow with "no-punishment" philosophy explanation +- ✅ Configurable session duration (15/25/45 minutes) +- ✅ Background notifications during active sessions +- ✅ Distraction tracking with 4 categories +- ✅ Today's stats on completion screen +- ✅ History view (today's sessions only in MVP) +- ✅ Multi-language support (13 languages) +- ✅ Settings for duration and locale + +**Intentionally Deferred** (see [README.md](README.md)): +- ⏸️ Variable duration slider (fixed presets preferred for MVP) +- ⏸️ White noise audio playback +- ⏸️ Weekly trend charts +- ⏸️ PDF report export +- ⏸️ AdMob integration (monetization post-validation) + +## Working with Localization + +### Adding/Editing Translations +1. Translations are defined in `l10n/app_en.arb` (source locale) and other `app_*.arb` files +2. After editing ARB files, regenerate code: + ```bash + flutter gen-l10n + ``` +3. Use in code: + ```dart + final l10n = AppLocalizations.of(context)!; + Text(l10n.appTitle); + ``` + +### Adding a New Language +1. Create `l10n/app_.arb` (copy from `app_en.arb`) +2. Add locale to `supportedLocales` in [main.dart](lib/main.dart:97-111) +3. Add to language picker in [settings_screen.dart](lib/screens/settings_screen.dart) +4. Run `flutter gen-l10n` + +## Modifying Data Models + +When changing Hive models (e.g., `FocusSession`): +1. Update model class with `@HiveField` annotations +2. Regenerate adapters: + ```bash + flutter pub run build_runner build --delete-conflicting-outputs + ``` +3. Consider migration strategy if changing existing fields (current MVP has no migration logic) + +## Code Generation + +This project uses code generation for: +- **Hive adapters**: `*.g.dart` files for model serialization +- **Localization**: `lib/l10n/app_localizations*.dart` from ARB files + +Never edit generated files manually - always modify source files and regenerate. + +## Platform-Specific Notes + +### Android +- Minimum SDK: 21 (Android 5.0) +- Target SDK: 34 (Android 14) +- Notification permission auto-requested on Android 13+ via `permission_handler` + +### iOS +- Requires Xcode for building +- Notification permissions requested via `DarwinInitializationSettings` +- See [MACOS_BUILD_GUIDE.md](MACOS_BUILD_GUIDE.md) for macOS-specific instructions + +### Web +- Notifications explicitly disabled on web platform (see `NotificationService._initialized`) +- Uses responsive layout but primarily designed for mobile + +## Design System Guidelines + +When adding new UI components: +1. Use `AppColors` constants - never hardcode colors +2. Use `AppTextStyles` for typography - never inline text styles +3. Border radius should be 16px for cards/buttons (consistency) +4. Button minimum height: 56px (touch-friendly) +5. Padding: Use multiples of 8 (8, 16, 24, 32, 48, 60) +6. Never use red/destructive colors for distractions (core philosophy) + +## Testing Strategy + +Current implementation focuses on manual testing: +- Test timer countdown accuracy across different durations +- Verify background notifications appear when app is minimized +- Test distraction button during active session (ensure timer continues) +- Verify data persists after app restart (Hive) +- Test locale switching without app restart + +## Known Constraints + +1. **No backend server** - All data stored locally (intentional for privacy) +2. **No analytics** - No Firebase/Amplitude in MVP (intentional) +3. **Single-device only** - No cross-device sync +4. **Today-focused** - History screen shows minimal data in MVP + +## Important Implementation Rules + +1. **Never pause timer on distraction** - This would violate the core philosophy +2. **Never show negative/punitive messaging** - Use encouragement instead +3. **Always use localized strings** - No hardcoded English text +4. **Always save sessions to Hive** - Even if stopped early (actualMinutes < durationMinutes) +5. **Background notifications required** - Users need countdown visibility when multitasking + +## Related Documentation + +- [README.md](README.md) - Product optimization strategy and MVP scope +- [ui-design-spec.md](ui-design-spec.md) - Complete UI/UX specifications +- [mvp-launch-checklist.md](mvp-launch-checklist.md) - 4-week development roadmap +- [product-design.md](product-design.md) - Original product vision +- [MACOS_BUILD_GUIDE.md](MACOS_BUILD_GUIDE.md) - macOS/iOS build instructions diff --git a/android/.kotlin/sessions/kotlin-compiler-6168023911861129695.salive b/android/.kotlin/sessions/kotlin-compiler-6168023911861129695.salive new file mode 100644 index 0000000..e69de29 diff --git a/android/app/src/main/res/drawable/ic_notification.xml b/android/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 0000000..699b730 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart index d2eb056..340cc1b 100644 --- a/lib/services/notification_service.dart +++ b/lib/services/notification_service.dart @@ -28,7 +28,7 @@ class NotificationService { try { // Android initialization settings - const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); + const androidSettings = AndroidInitializationSettings('@drawable/ic_notification'); // iOS initialization settings const iosSettings = DarwinInitializationSettings( @@ -147,6 +147,7 @@ class NotificationService { priority: Priority.high, enableVibration: true, playSound: true, + icon: '@drawable/ic_notification', ); const iosDetails = DarwinNotificationDetails( @@ -198,6 +199,7 @@ class NotificationService { channelDescription: 'Gentle reminders to focus', importance: Importance.defaultImportance, priority: Priority.defaultPriority, + icon: '@drawable/ic_notification', ); const iosDetails = DarwinNotificationDetails(); @@ -274,6 +276,7 @@ class NotificationService { playSound: false, // Show in status bar showProgress: false, + icon: '@drawable/ic_notification', ); const iosDetails = DarwinNotificationDetails(