diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..a4d5bac --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,47 @@ +# Code of Conduct + +## Our Commitment + +We are committed to providing a welcoming and inspiring community for all. We expect our community members to behave with respect, professionalism, and kindness towards each other. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members +- Being patient and understanding with others + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission +- Violence, threats of violence, or violent language directed against another person +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement + +Violations of this Code of Conduct may be reported by sending an email to our maintainers at conduct@docpilot.app. All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. + +## Consequences + +Community members who violate this Code of Conduct will be subject to appropriate consequences, which may include: + +- A warning or temporary ban from participating in the community +- Removal of contributions or access to community spaces +- Permanent ban from the community (in severe cases) + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.0. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9b7fccf --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,691 @@ +# Contributing to DocPilot + +We're thrilled that you're interested in contributing to DocPilot! This guide will help you get started with contributing to our AI-powered medical documentation assistant. + +## ๐Ÿ“‹ Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Development Setup](#development-setup) +- [Contributing Process](#contributing-process) +- [Code Standards](#code-standards) +- [Testing Guidelines](#testing-guidelines) +- [Pull Request Process](#pull-request-process) +- [Issue Guidelines](#issue-guidelines) +- [Documentation](#documentation) +- [Community](#community) + +## ๐Ÿ“œ Code of Conduct + +This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to the project maintainers. + +## ๐Ÿš€ Getting Started + +### Prerequisites + +Before you begin, ensure you have the following installed: + +- **Flutter SDK**: Version 3.22.0 or later +- **Dart**: Version 3.6.0 or later +- **Android Studio** or **VS Code** with Flutter extensions +- **Git**: For version control +- **Java JDK**: Version 17 or later (for Android builds) +- **Xcode**: Latest version (for iOS builds, macOS only) + +### Quick Start + +1. **Fork the Repository** + ```bash + # Fork on GitHub, then clone your fork + git clone https://github.com/YOUR_USERNAME/DocPilot.git + cd DocPilot + ``` + +2. **Set Up Upstream Remote** + ```bash + git remote add upstream https://github.com/AOSSIE-Org/DocPilot.git + ``` + +3. **Install Dependencies** + ```bash + flutter pub get + cd ios && pod install && cd .. # macOS only + ``` + +4. **Run the App** + ```bash + flutter run + ``` + +## ๐Ÿ› ๏ธ Development Setup + +### Environment Configuration + +1. **Create Environment File** + ```bash + cp .env.example .env + ``` + +2. **Configure API Keys** (Optional for basic development) + ```env + GEMINI_API_KEY=your_gemini_api_key_here + DEEPGRAM_API_KEY=your_deepgram_api_key_here + ``` + +3. **Verify Setup** + ```bash + flutter doctor + flutter analyze + flutter test + ``` + +### IDE Setup + +#### VS Code +Install these extensions: +- Flutter +- Dart +- GitLens +- Error Lens +- Bracket Pair Colorizer + +#### Android Studio +- Install Flutter and Dart plugins +- Configure Flutter SDK path +- Enable Dart Analysis Server + +### Build Verification + +Ensure you can build for your target platforms: + +```bash +# Android +flutter build apk --debug + +# iOS (macOS only) +flutter build ios --debug --no-codesign + +# Web +flutter build web + +# Desktop (Ubuntu/macOS/Windows) +flutter build linux # or macos/windows +``` + +## ๐Ÿ”„ Contributing Process + +### 1. Find an Issue + +- Browse [open issues](https://github.com/AOSSIE-Org/DocPilot/issues) +- Look for issues labeled `good first issue` for newcomers +- Check `help wanted` for areas needing assistance +- Propose new features by creating an issue first + +### 2. Create a Branch + +```bash +# Sync with upstream +git checkout main +git pull upstream main + +# Create feature branch +git checkout -b feature/your-feature-name +``` + +### 3. Make Changes + +- Follow our [code standards](#code-standards) +- Write tests for new functionality +- Update documentation as needed +- Keep commits focused and atomic + +### 4. Test Your Changes + +```bash +# Run tests +flutter test + +# Run analysis +flutter analyze + +# Format code +dart format lib test + +# Generate mocks if needed +dart run build_runner build +``` + +### 5. Commit Changes + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +```bash +# Examples of good commit messages +git commit -m "feat: add audio transcription retry logic" +git commit -m "fix: resolve PDF generation memory leak" +git commit -m "docs: update API integration guide" +git commit -m "test: add unit tests for ChatbotService" +git commit -m "refactor: simplify network utility logic" +``` + +### 6. Push and Create PR + +```bash +git push origin feature/your-feature-name +# Create PR via GitHub UI or gh CLI +gh pr create --title "feat: your feature title" --body "Description of changes" +``` + +## ๐Ÿ“ Code Standards + +### Code Style + +We follow [Dart's official style guide](https://dart.dev/guides/language/effective-dart). + +#### Formatting +- Use `dart format` to format your code +- Line length: 80 characters (flexible for readability) +- Use trailing commas for better diffs + +#### Naming Conventions +```dart +// Classes: PascalCase +class ChatbotService {} + +// Variables and functions: camelCase +String userInput; +void processResponse() {} + +// Constants: camelCase with const +const int maxRetries = 3; + +// Files: snake_case +chat_service.dart +network_utility.dart +``` + +#### Code Organization +```dart +// Import order: dart, flutter, packages, local +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +import '../utils/network_utility.dart'; +import 'base_service.dart'; +``` + +### Architecture Patterns + +#### Service Layer +```dart +class ApiService { + // Private fields with underscore + final String _apiKey; + final http.Client _httpClient; + + // Constructor with named parameters + ApiService({ + required String apiKey, + http.Client? httpClient, + }) : _apiKey = apiKey, + _httpClient = httpClient ?? http.Client(); + + // Public methods with clear documentation + /// Processes user input and returns AI response + /// + /// [input] The user's text input + /// Returns processed response or error message + Future processInput(String input) async { + // Implementation + } + + // Dispose resources + void dispose() { + _httpClient.close(); + } +} +``` + +#### Error Handling +```dart +// Use specific exception types +class ValidationException implements Exception { + final String message; + const ValidationException(this.message); + + @override + String toString() => 'ValidationException: $message'; +} + +// Handle errors gracefully +try { + final result = await service.operation(); + return result; +} on ValidationException catch (e) { + return 'Invalid input: ${e.message}'; +} on NetworkException catch (e) { + return 'Connection error: ${e.message}'; +} catch (e) { + return 'Unexpected error: $e'; +} +``` + +#### State Management +- Use `provider` for dependency injection +- Keep state classes simple and focused +- Use `changeNotifier` for reactive state updates + +### Documentation + +#### Code Comments +```dart +/// Service for handling AI chat interactions +/// +/// This service manages communication with the Gemini API, +/// including retry logic and error handling. +class ChatService { + /// Creates a new chat service with the given [apiKey] + /// + /// Optionally accepts a custom [httpClient] for testing + ChatService({required String apiKey, http.Client? httpClient}); + + /// Sends a message to the AI and returns the response + /// + /// [message] The user's message to process + /// + /// Throws [ValidationException] if message is empty + /// Throws [NetworkException] if connection fails + /// + /// Returns AI response or user-friendly error message + Future sendMessage(String message) async { + // Implementation + } +} +``` + +#### README Updates +When adding features, update relevant sections: +- Features list +- Installation instructions +- Usage examples +- API documentation + +## ๐Ÿงช Testing Guidelines + +### Test Structure + +```dart +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; + +void main() { + group('ChatService', () { + late ChatService chatService; + + setUp(() { + chatService = ChatService(apiKey: 'test-key'); + }); + + tearDown(() { + chatService.dispose(); + }); + + group('sendMessage', () { + test('should return response for valid input', () async { + // Arrange + const input = 'Hello, AI!'; + + // Act + final result = await chatService.sendMessage(input); + + // Assert + expect(result, isNotEmpty); + expect(result, isNot(startsWith('Error:'))); + }); + + test('should handle empty input gracefully', () async { + // Arrange + const input = ''; + + // Act + final result = await chatService.sendMessage(input); + + // Assert + expect(result, startsWith('Error:')); + }); + }); + }); +} +``` + +### Test Categories + +#### Unit Tests +- Test individual functions and methods +- Mock external dependencies +- Cover edge cases and error conditions +- Aim for >90% code coverage + +#### Widget Tests +- Test UI components in isolation +- Verify user interactions +- Test state changes and rebuilds + +#### Integration Tests +- Test complete user workflows +- Verify service integrations +- Test with real network calls (sparingly) + +### Running Tests + +```bash +# All tests +flutter test + +# Specific test file +flutter test test/services/chat_service_test.dart + +# With coverage +flutter test --coverage + +# Generate coverage report +genhtml coverage/lcov.info -o coverage/html +``` + +## ๐Ÿ” Pull Request Process + +### Before Creating a PR + +โœ… **Pre-flight Checklist:** +- [ ] Code follows style guidelines +- [ ] All tests pass locally +- [ ] New tests cover your changes +- [ ] Documentation is updated +- [ ] No new warnings from `flutter analyze` +- [ ] Commits follow conventional format + +### PR Requirements + +#### Title Format +Use [Conventional Commits](https://www.conventionalcommits.org/): +- `feat: add voice transcription feature` +- `fix: resolve API timeout issue` +- `docs: update installation guide` +- `test: add integration tests for auth` + +#### Description Template +```markdown +## Description +Brief description of changes and motivation. + +## Type of Change +- [ ] ๐Ÿ› Bug fix (non-breaking change which fixes an issue) +- [ ] โœจ New feature (non-breaking change which adds functionality) +- [ ] ๐Ÿ’ฅ Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] ๐Ÿ“š Documentation (changes to documentation) +- [ ] ๐Ÿงช Tests (add missing tests or update existing ones) +- [ ] ๐Ÿ”ง Refactor (code change that doesn't add features or fix bugs) + +## Testing +- [ ] Unit tests pass +- [ ] Widget tests pass +- [ ] Integration tests pass +- [ ] Manual testing completed + +## Screenshots/Videos +If applicable, add screenshots or videos to help explain your changes. + +## Checklist +- [ ] My code follows the style guidelines +- [ ] I have performed a self-review +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +``` + +### Review Process + +1. **Automated Checks** + - CI/CD pipeline runs automatically + - Code quality gate must pass + - All tests must pass + +2. **Code Review** + - At least one maintainer review required + - Address feedback promptly + - Keep discussions constructive + +3. **Testing** + - Manual testing by reviewers + - Regression testing for critical changes + - Performance impact assessment + +## ๐Ÿ› Issue Guidelines + +### Creating Issues + +#### Bug Reports +```markdown +**Bug Description** +A clear description of what the bug is. + +**Steps to Reproduce** +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected Behavior** +What you expected to happen. + +**Actual Behavior** +What actually happened. + +**Screenshots** +If applicable, add screenshots. + +**Environment** +- Device: [e.g. iPhone 12, Pixel 6] +- OS: [e.g. iOS 15.0, Android 12] +- App Version: [e.g. 1.2.0] +- Flutter Version: [e.g. 3.22.0] + +**Additional Context** +Any other context about the problem. +``` + +#### Feature Requests +```markdown +**Feature Description** +A clear description of what you want to happen. + +**Problem Statement** +Explain the problem this feature would solve. + +**Proposed Solution** +Describe the solution you'd like. + +**Alternatives Considered** +Describe alternatives you've considered. + +**Additional Context** +Any other context or screenshots. +``` + +### Issue Labels + +- `bug` - Something isn't working +- `enhancement` - New feature or request +- `documentation` - Improvements or additions to documentation +- `good first issue` - Good for newcomers +- `help wanted` - Extra attention is needed +- `priority: high` - High priority issue +- `priority: low` - Low priority issue +- `wontfix` - This will not be worked on + +## ๐Ÿ“š Documentation + +### Types of Documentation + +#### Code Documentation +- Inline comments for complex logic +- Class and method documentation +- API documentation +- Architecture decisions (ADRs) + +#### User Documentation +- Installation guides +- Feature usage guides +- Troubleshooting guides +- FAQ + +#### Developer Documentation +- Contributing guidelines (this file) +- Development setup +- Testing procedures +- Deployment process + +### Documentation Standards + +#### Markdown Style +- Use clear, descriptive headings +- Include table of contents for long documents +- Use code blocks with language specification +- Include screenshots for UI-related docs + +#### Code Examples +```dart +// โœ… Good: Clear, commented example +/// Example of using the ChatService +Future exampleUsage() async { + // Initialize service with API key + final chatService = ChatService(apiKey: 'your-api-key'); + + try { + // Send message and handle response + final response = await chatService.sendMessage('Hello AI'); + print('Response: $response'); + } catch (e) { + print('Error: $e'); + } finally { + // Always dispose of resources + chatService.dispose(); + } +} +``` + +#### API Documentation +Use comprehensive dartdoc comments: + +```dart +/// Manages AI chat interactions with retry logic and error handling +/// +/// This service provides a high-level interface for communicating with +/// AI services while handling network issues, rate limiting, and errors. +/// +/// Example usage: +/// ```dart +/// final service = ChatService(apiKey: 'your-key'); +/// final response = await service.sendMessage('Hello'); +/// ``` +class ChatService { + /// Creates a chat service with the specified [apiKey] + /// + /// The [httpClient] parameter is optional and mainly used for testing. + /// If not provided, a default HTTP client will be used. + /// + /// Throws [ArgumentError] if [apiKey] is empty. + ChatService({ + required String apiKey, + http.Client? httpClient, + }); +} +``` + +## ๐ŸŒŸ Community + +### Communication Channels + +- **GitHub Issues**: Bug reports and feature requests +- **GitHub Discussions**: General questions and ideas +- **Discord**: Real-time chat and collaboration +- **Email**: maintainers@docpilot.app + +### Getting Help + +1. **Search Existing Issues**: Others might have had the same question +2. **Check Documentation**: README, wiki, and docs/ folder +3. **Ask in Discussions**: For general questions +4. **Create an Issue**: For bugs or feature requests + +### Recognition + +We believe in recognizing our contributors: + +- **Contributors**: Listed in our README +- **Special Recognition**: For significant contributions +- **Maintainer Status**: For consistent, quality contributions + +## ๐ŸŽฏ Areas for Contribution + +### High-Priority Areas +- ๐Ÿงช **Testing**: Increase test coverage +- ๐Ÿ”ง **Performance**: Optimize app performance +- ๐ŸŒ **Accessibility**: Improve accessibility features +- ๐Ÿ“ฑ **Platform Support**: iOS/Android improvements +- ๐ŸŽจ **UI/UX**: Enhance user interface + +### Beginner-Friendly Areas +- ๐Ÿ“š **Documentation**: Improve guides and examples +- ๐Ÿ› **Bug Fixes**: Fix small, well-defined bugs +- ๐ŸŽจ **Styling**: Improve UI consistency +- ๐Ÿงน **Code Cleanup**: Refactor and improve code quality + +### Advanced Areas +- ๐Ÿ—๏ธ **Architecture**: Improve app architecture +- ๐Ÿ”’ **Security**: Enhance security measures +- โšก **Performance**: Advanced optimizations +- ๐Ÿš€ **DevOps**: Improve CI/CD pipeline + +## โ“ Frequently Asked Questions + +### General + +**Q: How long does review take?** +A: Typically 1-3 days for small changes, up to a week for larger features. + +**Q: Can I work on multiple issues?** +A: Yes, but please update the issues to avoid duplication of effort. + +**Q: How do I become a maintainer?** +A: Consistent, quality contributions over time. Reach out to current maintainers. + +### Technical + +**Q: Which Flutter version should I use?** +A: Use Flutter 3.22.0 or later. Check `.fvmrc` for the exact version. + +**Q: How do I run tests locally?** +A: Use `flutter test` for unit/widget tests, see testing section above. + +**Q: Where should I put new features?** +A: Follow the existing folder structure in `lib/`. Ask if unsure. + +### Process + +**Q: Should I create an issue before starting work?** +A: Yes, especially for new features. This helps avoid duplicate work. + +**Q: Can I change the commit history?** +A: Yes, please clean up your commits before submitting PR. + +**Q: What if tests fail in CI but pass locally?** +A: Check for environment differences, missing dependencies, or race conditions. + +--- + +Thank you for contributing to DocPilot! Your efforts help make medical documentation more accessible and efficient for healthcare professionals worldwide. ๐Ÿฅโœจ \ No newline at end of file diff --git a/docs/API_INTEGRATION.md b/docs/API_INTEGRATION.md new file mode 100644 index 0000000..e2172c6 --- /dev/null +++ b/docs/API_INTEGRATION.md @@ -0,0 +1,479 @@ +# API Integration Guide + +This guide explains how to integrate various APIs with DocPilot and how to use the built-in services. + +## Overview of Integrated APIs + +| API | Service | Purpose | Status | +|-----|---------|---------|--------| +| **Gemini** | ChatbotService | AI text generation and analysis | โœ… Active | +| **Deepgram** | DeepgramService | Audio transcription | โœ… Active | +| **Google Docs API** | Planned | Document synchronization | ๐Ÿ”„ Planned | +| **EHR Systems** | Planned | Clinical data integration | ๐Ÿ”„ Planned | + +## Gemini API Integration + +### Setup + +1. **Obtain API Key** + - Visit [Google AI Studio](https://makersuite.google.com/app/apikey) + - Create new API key + - Copy the key + +2. **Configure in App** + ```bash + # Add to .env file + GEMINI_API_KEY=your_api_key_here + ``` + +3. **Verify Setup** + ```bash + flutter run + # App should initialize without API key errors + ``` + +### Usage + +#### Basic Usage +```dart +import 'package:doc_pilot/services/enhanced_chatbot_service.dart'; + +final chatbotService = EnhancedChatbotService( + apiKey: 'your-api-key', +); + +try { + final response = await chatbotService.getGeminiResponse( + 'Generate a medical summary for patient with fever and cough.', + ); + print('Response: $response'); +} catch (e) { + print('Error: $e'); +} finally { + chatbotService.dispose(); +} +``` + +#### With Retry Configuration +```dart +final response = await chatbotService.getGeminiResponse( + prompt, + retryConfig: RetryConfig.critical, // 5 attempts + timeoutDuration: const Duration(seconds: 45), +); +``` + +#### Enhanced Error Handling +```dart +try { + final response = await chatbotService.getEnhancedGeminiResponse( + prompt, + retryConfig: RetryConfig.critical, + ); + return response; +} on MaxRetriesExceededException catch (e) { + // Show user: "Service temporarily unavailable, please try again" + return buildUserFriendlyError(e.lastException); +} on NetworkException catch (e) { + // Show user: "Please check your internet connection" + return 'Network Error: ${e.message}'; +} +``` + +### Rate Limiting + +Gemini API has rate limits: +- **Free tier**: 60 requests per minute +- **Paid tier**: Higher limits based on plan + +The retry logic automatically handles rate limiting with exponential backoff. + +### API Response Format + +```json +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "Generated response text" + } + ] + } + } + ] +} +``` + +### Common Errors + +``` +โŒ 401 Unauthorized: Invalid API key + โ†’ Check GEMINI_API_KEY in .env + +โŒ 429 Too Many Requests: Rate limited + โ†’ Retry logic automatically handles this + โ†’ Wait before retrying manually + +โŒ 500 Internal Server Error: Server issue + โ†’ Retry with exponential backoff + โ†’ Usually resolves quickly + +โŒ Timeout: Request took too long + โ†’ Check internet connection + โ†’ Try shorter prompts + โ†’ Increase timeout duration if persistent +``` + +## Deepgram API Integration + +### Setup + +1. **Obtain API Key** + - Visit [Deepgram Console](https://console.deepgram.com) + - Create project + - Generate API key + - Copy the key + +2. **Configure in App** + ```bash + # Add to .env file + DEEPGRAM_API_KEY=your_api_key_here + ``` + +### Supported Audio Formats + +| Format | MIME Type | Sample Rate | Bit Depth | +|--------|-----------|-------------|-----------| +| MP3 | audio/mp3 | 8-48 kHz | 16-bit | +| WAV | audio/wav | 8-48 kHz | 16-bit | +| M4A | audio/m4a | 8-48 kHz | 16-bit | +| FLAC | audio/flac | 8-48 kHz | 16-bit | +| OGG | audio/ogg | 8-48 kHz | 16-bit | + +### Usage + +#### Basic Transcription +```dart +import 'package:doc_pilot/features/transcription/data/enhanced_deepgram_service.dart'; + +final deepgramService = EnhancedDeepgramService( + apiKey: 'your-api-key', +); + +try { + final result = await deepgramService.transcribeWithRetry( + '/path/to/audio/file.m4a', + ); + + print('Transcript: ${result.transcript}'); + print('Confidence: ${result.confidencePercent}%'); + print('Duration: ${result.durationSeconds}s'); +} catch (e) { + print('Error: $e'); +} +``` + +#### With Custom Configuration +```dart +final result = await deepgramService.transcribeWithRetry( + audioPath, + model: 'nova-2', // Deepgram model + language: 'en', // Language code + includeConfidence: true, // Include confidence scores + retryConfig: RetryConfig.critical, // Retry config + timeoutDuration: const Duration(seconds: 60), +); +``` + +#### File Validation +The service automatically validates: +- โœ… File exists +- โœ… File format supported +- โœ… File size (<150MB) +- โœ… File not empty + +```dart +// Triggers validation automatically +final result = await deepgramService.transcribeWithRetry( + '/path/to/file.m4a', // Validates before transcription +); +``` + +### Response Format + +```dart +class TranscriptionResult { + final String transcript; // Transcribed text + final double? confidence; // 0.0 to 1.0 + final double? durationSeconds; // Audio duration + final String? model; // Model used + final String? language; // Detected language +} +``` + +### API Response Structure + +```json +{ + "results": { + "channels": [ + { + "alternatives": [ + { + "transcript": "This is the transcribed text", + "confidence": 0.9532 + } + ] + } + ], + "metadata": { + "duration": 45.23, + "model": "nova-2" + } + } +} +``` + +### Common Errors + +``` +โŒ 401 Unauthorized: Invalid API key + โ†’ Verify DEEPGRAM_API_KEY in .env + +โŒ 413 Payload Too Large: File >150MB + โ†’ Use shorter audio files + โ†’ Split large files + +โŒ 415 Unsupported Media Type: Wrong format + โ†’ Use supported formats: MP3, WAV, M4A, FLAC, OGG + โ†’ Convert audio file if needed + +โŒ 429 Rate Limited: Too many requests + โ†’ Built-in retry handles this + โ†’ Space out requests if manual + +โŒ Timeout: Transcription taking too long + โ†’ Check file size + โ†’ Ensure stable internet + โ†’ Increase timeout duration +``` + +## Network Connectivity Management + +### Checking Connectivity + +```dart +// Quick check (uses cache if available) +final isConnected = await NetworkUtility.isConnected(); + +// Detailed check +final networkInfo = await NetworkUtility.checkConnectivity(); +print('Status: ${networkInfo.status}'); +print('Response time: ${networkInfo.responseTimeMs}ms'); + +// Force fresh check (bypass cache) +final freshInfo = await NetworkUtility.forceCheck(); + +// Multi-host check +final bestInfo = await NetworkUtility.checkMultipleHosts(); +``` + +### Waiting for Connectivity + +```dart +// Wait up to 2 minutes for connection +bool recovered = await NetworkUtility.waitForConnectivity( + maxWaitTime: Duration(minutes: 2), + onCheck: (info) { + print('Connection check: ${info.status}'); + }, +); + +if (recovered) { + // Connectivity restored, retry operation +} else { + // Still no connection after waiting +} +``` + +## Implementing Retry Logic + +### Simple Retry + +```dart +// Uses default API configuration +await RetryUtility.execute( + () => apiCall(), + config: RetryConfig.apiDefault, +); +``` + +### Custom Retry Configuration + +```dart +await RetryUtility.execute( + () => criticalOperation(), + config: const RetryConfig( + maxAttempts: 5, + baseDelay: Duration(milliseconds: 1000), + backoffMultiplier: 2.0, + maxDelay: Duration(seconds: 30), + useJitter: true, + ), +); +``` + +### Conditional Retry + +```dart +await RetryUtility.execute( + () => apiCall(), + config: RetryConfig.apiDefault, + retryIf: (exception) { + // Custom retry conditions + if (exception.toString().contains('rate limit')) return true; + if (exception.toString().contains('timeout')) return true; + return RetryUtility.isRetryableException(exception); + }, +); +``` + +### Progress Tracking + +```dart +await RetryUtility.execute( + () => apiCall(), + config: RetryConfig.apiDefault, + onRetry: (exception, attempt) { + print('Attempt $attempt failed: $exception'); + print('Retrying in ${delay}ms...'); + }, +); +``` + +## Implementation Patterns + +### Pattern 1: Service Wrapper + +```dart +class ApiWrapper { + Future call(Future Function() operation) { + return RetryUtility.execute( + operation, + config: RetryConfig.apiDefault, + retryIf: RetryUtility.apiRetryCondition, + ); + } +} + +// Usage +final wrapper = ApiWrapper(); +final result = await wrapper.call(() => myService.operation()); +``` + +### Pattern 2: Decorated Service + +```dart +class ResilientChatbotService extends ChatbotService { + @override + Future getGeminiResponse(String prompt) { + return RetryUtility.execute( + () => super.getGeminiResponse(prompt), + config: RetryConfig.apiDefault, + retryIf: RetryUtility.apiRetryCondition, + ); + } +} +``` + +### Pattern 3: Middleware + +```dart +class NetworkMiddleware { + Future execute(Future Function() operation) async { + // Check network first + final connected = await NetworkUtility.isConnected(); + if (!connected) { + throw NetworkException('No internet connection'); + } + + // Retry if needed + return await RetryUtility.execute( + operation, + config: RetryConfig.apiDefault, + ); + } +} +``` + +## Best Practices + +### โœ… Do's +- Check network connectivity before expensive operations +- Use appropriate retry configurations for different operations +- Handle specific exceptions with clear error messages +- Log API calls for debugging +- Dispose of resources properly + +### โŒ Don'ts +- Don't retry non-idempotent operations +- Don't ignore rate limit errors +- Don't hardcode API keys +- Don't retry authentication errors +- Don't make unnecessary API calls + +## Troubleshooting + +### Issue: "Missing API Key" Error + +**Solution**: +```bash +# 1. Check .env file exists +ls -la .env + +# 2. Verify key in .env +cat .env | grep GEMINI_API_KEY + +# 3. Reload app +flutter run +``` + +### Issue: API Request Timeout + +**Solution**: +```dart +// 1. Increase timeout +await service.operation( + timeoutDuration: Duration(seconds: 60), // Default 30s +); + +// 2. Check network quality +final info = await NetworkUtility.checkConnectivity(); +print('Response time: ${info.responseTimeMs}ms'); + +// 3. Try shorter requests +``` + +### Issue: Rate Limiting + +**Solution**: The retry logic handles this automatically with exponential backoff. If manual retries needed: + +```dart +// Implement manual rate limit handling +const rateLimitDelay = Duration(minutes: 1); +await Future.delayed(rateLimitDelay); +// Retry operation +``` + +## Resources + +- [Gemini API Docs](https://ai.google.dev) +- [Deepgram API Docs](https://developers.deepgram.com) +- [API Security Best Practices](https://owasp.org) +- [OAuth Implementation Guide](https://oauth.net) + +--- + +For questions or issues, see the [Contributing Guide](CONTRIBUTING.md). \ No newline at end of file diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..fb8d089 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,401 @@ +# DocPilot Architecture + +## Overview + +DocPilot is built using Flutter with a layered architecture that separates concerns and promotes maintainability, testability, and scalability. + +## Architecture Layers + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ UI/Presentation Layer โ”‚ Screens, Widgets, State Management +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ Business Logic Layer โ”‚ Controllers, ViewModels, Use Cases +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ Service Layer โ”‚ API Services, Data Processing +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ Utility Layer โ”‚ Retry Logic, Network Utils, Helpers +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ Data Layer โ”‚ Models, API Clients, Local Storage +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +## Project Structure + +``` +lib/ +โ”œโ”€โ”€ main.dart # App entry point +โ”œโ”€โ”€ screens/ # UI Screens +โ”‚ โ”œโ”€โ”€ transcription_screen.dart +โ”‚ โ”œโ”€โ”€ summary_screen.dart +โ”‚ โ”œโ”€โ”€ prescription_screen.dart +โ”‚ โ””โ”€โ”€ transcription_detail_screen.dart +โ”œโ”€โ”€ features/ # Feature modules with isolated logic +โ”‚ โ””โ”€โ”€ transcription/ +โ”‚ โ”œโ”€โ”€ data/ # Data layer for transcription +โ”‚ โ”‚ โ”œโ”€โ”€ deepgram_service.dart +โ”‚ โ”‚ โ”œโ”€โ”€ enhanced_deepgram_service.dart +โ”‚ โ”‚ โ””โ”€โ”€ gemini_service.dart +โ”‚ โ”œโ”€โ”€ domain/ # Domain models and entities +โ”‚ โ”‚ โ””โ”€โ”€ transcription_model.dart +โ”‚ โ””โ”€โ”€ presentation/ # UI layer for transcription +โ”‚ โ”œโ”€โ”€ transcription_controller.dart +โ”‚ โ””โ”€โ”€ transcription_screen.dart +โ”œโ”€โ”€ services/ # Core services +โ”‚ โ”œโ”€โ”€ chatbot_service.dart +โ”‚ โ”œโ”€โ”€ enhanced_chatbot_service.dart +โ”‚ โ”œโ”€โ”€ pdf_service.dart +โ”‚ โ””โ”€โ”€ pdf_settings_service.dart +โ”œโ”€โ”€ utils/ # Utility functions and helpers +โ”‚ โ”œโ”€โ”€ retry_utility.dart # Retry logic with exponential backoff +โ”‚ โ”œโ”€โ”€ network_utility.dart # Network connectivity management +โ”‚ โ””โ”€โ”€ [other utilities] +โ”œโ”€โ”€ models/ # Data models +โ”‚ โ””โ”€โ”€ pdf_settings.dart +โ”œโ”€โ”€ examples/ # Example implementations +โ”‚ โ””โ”€โ”€ resilient_service_example.dart +โ””โ”€โ”€ widgets/ # Reusable widgets +``` + +## Design Patterns + +### 1. **Layered Architecture** +Each layer has a specific responsibility: +- **UI Layer**: Displays data and captures user input +- **Business Logic**: Orchestrates services and implements use cases +- **Service Layer**: Handles external integrations (APIs, databases) +- **Utility Layer**: Provides cross-cutting concerns (retry, logging, network) +- **Data Layer**: Manages data access and transformation + +### 2. **Dependency Injection** +```dart +// Using Provider pattern +final chatbotServiceProvider = Provider((ref) { + return ChatbotService(apiKey: dotenv.env['GEMINI_API_KEY']); +}); +``` + +### 3. **Repository Pattern** +Services act as repositories for external data: +```dart +class ChatbotService { + Future getResponse(String prompt) async { + // Fetch from external API + } +} +``` + +### 4. **Error Handling** +Custom exceptions for different error types: +```dart +class NetworkException implements Exception { } +class ValidationException implements Exception { } +class TranscriptionException implements Exception { } +``` + +### 5. **Retry Strategy** +Configurable retry logic with exponential backoff: +```dart +await RetryUtility.execute( + () => apiCall(), + config: RetryConfig.apiDefault, + retryIf: RetryUtility.apiRetryCondition, +); +``` + +## Key Components + +### Services + +#### ChatbotService & EnhancedChatbotService +- Manages communication with Gemini AI API +- Handles API key resolution +- Enhanced version includes retry logic and error recovery + +#### DeepgramService & EnhancedDeepgramService +- Processes audio transcription +- Supports multiple audio formats +- Enhanced version with file validation and retry logic + +#### PdfService +- Generates PDF documents from text +- Handles markdown parsing +- Supports customizable templates + +#### PdfSettingsService +- Persists user preferences using SharedPreferences +- Manages doctor info, clinic info, and PDF templates + +### Utilities + +#### RetryUtility +- Implements exponential backoff with jitter +- Supports multiple retry configuration profiles +- Provides intelligent error categorization + +#### NetworkUtility +- Checks network connectivity +- Supports multi-host validation +- Implements smart caching + +### Models + +#### Domain Models +- `TranscriptionModel`: Represents transcription data +- `DoctorInfo`: Doctor information for PDF generation +- `ClinicInfo`: Clinic information for PDF generation +- `PdfTemplate`: PDF template configuration + +### Controllers + +#### TranscriptionController +- Manages transcription state +- Handles recording and processing +- Orchestrates service calls + +## Data Flow + +### Typical User Interaction Flow + +``` +1. User Input (UI) + โ†“ +2. Controller/ViewModel processes input + โ†“ +3. Service layer resolves which service to use + โ†“ +4. Service makes API call with RetryUtility + โ†“ +5. NetworkUtility checks connectivity + โ†“ +6. API call with exponential backoff retry + โ†“ +7. Response processed and model created + โ†“ +8. Result returned to UI + โ†“ +9. UI updates with data or error message +``` + +### Example: Audio Transcription Flow + +``` +User records audio + โ†“ +TranscriptionScreen triggers recording + โ†“ +TranscriptionController calls transcribeAudio() + โ†“ +EnhancedDeepgramService.transcribeWithRetry() + โ†“ +RetryUtility.execute with critical config + โ†“ (attempt 1, 2, 3, etc.) +NetworkUtility.checkConnectivity() + โ†“ +HTTP POST to Deepgram API + โ†“ +Response parsing and TranscriptionResult creation + โ†“ +UI displays transcript with confidence score +``` + +## State Management + +### Provider Pattern +Uses the `provider` package for dependency injection and state management: + +```dart +// Define provider +final transcriptionControllerProvider = + ChangeNotifierProvider((ref) { + return TranscriptionController(); + }); + +// Use in UI +final controller = ref.watch(transcriptionControllerProvider); +``` + +### ChangeNotifier Pattern +Services extend `ChangeNotifier` for reactive state: + +```dart +class TranscriptionController extends ChangeNotifier { + String _status = 'idle'; + + void updateStatus(String newStatus) { + _status = newStatus; + notifyListeners(); // Triggers UI rebuild + } +} +``` + +## Error Handling Strategy + +### Hierarchical Error Handling + +``` +User-Facing Error Message + โ†“ +Service-Level Exception (specific to domain) + โ†“ +Network/HTTP Exception (transport layer) + โ†“ +Platform Exception (OS level) +``` + +### Recovery Strategies + +1. **Network Errors**: Retry with exponential backoff +2. **Rate Limiting**: Wait and retry +3. **Authentication Errors**: Prompt for credential update +4. **Validation Errors**: Show user-friendly message +5. **Server Errors**: Display status and suggest retry + +## Testing Architecture + +### Test Organization + +``` +test/ +โ”œโ”€โ”€ services/ +โ”‚ โ”œโ”€โ”€ chatbot_service_test.dart +โ”‚ โ”œโ”€โ”€ deepgram_service_test.dart +โ”‚ โ””โ”€โ”€ [service tests] +โ”œโ”€โ”€ models/ +โ”‚ โ””โ”€โ”€ pdf_settings_test.dart +โ””โ”€โ”€ utils/ + โ”œโ”€โ”€ retry_utility_test.dart + โ””โ”€โ”€ network_utility_test.dart +``` + +### Mocking Strategy + +```dart +// Mock external dependencies +@GenerateMocks([http.Client, SharedPreferences]) +void main() { + group('Service Tests', () { + late MockHttpClient mockHttpClient; + + setUp(() { + mockHttpClient = MockHttpClient(); + }); + + test('should call API with correct parameters', () { + // Verify calls to mocked client + }); + }); +} +``` + +## Performance Considerations + +### Optimization Strategies + +1. **Caching** + - Network responses cached in memory + - Connectivity checks cached for 30 seconds + - User preferences cached in SharedPreferences + +2. **Lazy Loading** + - Screens load data on demand + - Large lists use ListView with lazy loading + - Heavy computations deferred to background + +3. **Memory Management** + - Audio files processed in chunks + - PDF generation streamed when possible + - Proper resource disposal in lifecycle methods + +4. **Network Optimization** + - Connection pooling in HTTP client + - Request timeout configuration + - Response compression support + +## Security Considerations + +### API Key Management +- API keys stored in environment variables +- Never hardcoded in source code +- Sensitive data not logged + +### Data Privacy +- User data processed locally when possible +- API communication over HTTPS +- Audio data not cached permanently + +### Authentication +- API key validation before requests +- Token refresh handling +- Secure error messages (no sensitive data leaked) + +## Deployment Architecture + +### Build Pipeline + +``` +Source Code + โ†“ +CI Pipeline (GitHub Actions) + โ†“ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +Android iOS Web Linux +Build Build Build Build + โ”‚ โ”‚ โ”‚ โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ†“ + Artifact Generation + โ†“ + GitHub Releases +``` + +### Platform-Specific Considerations + +#### Android +- Multi-APK support (split by ABI) +- Proguard/R8 optimization +- Keystore for signing + +#### iOS +- Code signing configuration +- Framework linking +- Simulator vs device builds + +#### Web +- CanvasKit renderer for performance +- Service worker caching +- PWA capabilities + +## Future Architectural Improvements + +### Planned Enhancements +1. **Clean Architecture**: Stricter separation of concerns +2. **MVVM Pattern**: For complex UI logic +3. **Bloc Pattern**: Advanced state management +4. **Feature-First Structure**: Enhance modularity +5. **Micro-frontends**: Decompose into independent features + +### Scalability Plans +1. **Service Layer Expansion**: Add more AI providers +2. **Offline Support**: Local processing capabilities +3. **Real-time Features**: WebSocket integration +4. **Analytics Integration**: User behavior tracking +5. **Internationalization**: Multi-language support + +## Architecture Decision Records (ADRs) + +### ADR-001: Use RetryUtility for All API Calls +**Decision**: All external API calls use RetryUtility with exponential backoff +**Rationale**: Improves reliability and user experience in poor network conditions +**Consequences**: Increased latency for failed requests, but much better UX + +### ADR-002: Provider for State Management +**Decision**: Use Provider package for dependency injection and state management +**Rationale**: Simple, lightweight, and integrates well with Riverpod ecosystem +**Consequences**: Requires understanding of Provider patterns + +### ADR-003: Feature Module Organization +**Decision**: Organize code by features rather than layers +**Rationale**: Makes feature development independent and maintainable +**Consequences**: Slightly more complex folder structure initially \ No newline at end of file diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..41fd679 --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,632 @@ +# Development Guide + +This guide provides comprehensive information for developing DocPilot. + +## Quick Start + +### Prerequisites +- Flutter 3.22.0 or later +- Dart 3.6.0 or later +- Git + +### Setup in 5 Minutes + +```bash +# Clone repository +git clone https://github.com/AOSSIE-Org/DocPilot.git +cd DocPilot + +# Install dependencies +flutter pub get +cd ios && pod install && cd .. # macOS only + +# Run the app +flutter run +``` + +## Project Structure + +### Core Directories + +**`lib/`** - Main application code +- **`main.dart`** - App initialization and routing +- **`screens/`** - UI screens (transcription, summary, prescription) +- **`features/`** - Feature modules with isolated logic +- **`services/`** - External service integrations (APIs, storage) +- **`utils/`** - Shared utilities (retry logic, networking, helpers) +- **`models/`** - Data models and domain entities +- **`widgets/`** - Reusable UI widgets + +**`test/`** - Test files +- Unit tests for services +- Widget tests for screens +- Integration tests + +**`docs/`** - Documentation +- Architecture guide +- Feature documentation +- API integration guides + +**`.github/workflows/`** - CI/CD pipelines +- Continuous integration (testing, analysis, building) +- Continuous deployment (releases) +- PR quality checks + +## Development Workflow + +### 1. Creating a Feature + +**Step 1: Create Feature Branch** +```bash +git checkout -b feature/your-feature-name main +``` + +**Step 2: Create Feature Structure** +``` +lib/features/your_feature/ +โ”œโ”€โ”€ data/ +โ”‚ โ”œโ”€โ”€ services/ +โ”‚ โ””โ”€โ”€ models/ +โ”œโ”€โ”€ domain/ +โ”‚ โ””โ”€โ”€ models/ +โ””โ”€โ”€ presentation/ + โ”œโ”€โ”€ screens/ + โ”œโ”€โ”€ widgets/ + โ””โ”€โ”€ controllers/ +``` + +**Step 3: Implement Feature** +- Start with domain models (entities) +- Implement services/data layer +- Create UI screens and widgets +- Add business logic controllers + +**Step 4: Add Tests** +```dart +// test/features/your_feature/... +void main() { + group('YourFeature', () { + test('should do something', () { + // Test implementation + }); + }); +} +``` + +**Step 5: Documentation** +- Update README with new feature +- Add code comments for complex logic +- Update API docs if applicable + +### 2. Fixing a Bug + +**Step 1: Reproduce the Bug** +- Create minimal reproduction steps +- Note error messages and stack traces +- Test on different devices/platforms if possible + +**Step 2: Identify Root Cause** +- Use debugger or logging +- Review related code +- Check recent changes + +**Step 3: Implement Fix** +- Make minimal, focused changes +- Add a test that reproduces the bug +- Verify test fails before fix, passes after + +**Step 4: Verify Fix** +```bash +flutter clean +flutter pub get +flutter test +flutter analyze +``` + +### 3. Refactoring Code + +**Best Practices** +- Refactor in small, incremental steps +- Keep tests passing throughout +- Don't mix refactoring with feature development +- Document any architectural changes + +**Process** +```bash +# 1. Run tests before refactoring +flutter test + +# 2. Make small changes +# ... refactor code ... + +# 3. Run tests after each change +flutter test + +# 4. Commit incremental changes +git commit -m "refactor: simplify [component] logic" +``` + +## Common Development Tasks + +### Adding a New Service + +```dart +// services/my_service.dart +import 'dart:developer' as developer; +import 'utils/retry_utility.dart'; +import 'utils/network_utility.dart'; + +class MyService { + final String _apiKey; + final http.Client _httpClient; + + MyService({required String apiKey, http.Client? httpClient}) + : _apiKey = apiKey?.trim(), + _httpClient = httpClient ?? http.Client(); + + Future performOperation(String input) async { + developer.log('Starting operation', name: 'MyService'); + + return await RetryUtility.execute( + () => _performRequest(input), + config: RetryConfig.apiDefault, + retryIf: RetryUtility.apiRetryCondition, + ); + } + + Future _performRequest(String input) async { + // Check network connectivity + final networkInfo = await NetworkUtility.checkConnectivity(); + if (!networkInfo.isReachable) { + throw NetworkException('No internet connection'); + } + + // Make API call + final response = await _httpClient.post(/* ... */); + + // Handle response + if (response.statusCode == 200) { + return response.body; + } else { + throw Exception('API error: ${response.statusCode}'); + } + } + + void dispose() { + _httpClient.close(); + } +} +``` + +### Adding Unit Tests + +```dart +// test/services/my_service_test.dart +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; + +@GenerateMocks([http.Client]) +void main() { + group('MyService', () { + late MyService service; + late MockHttpClient mockClient; + + setUp(() { + mockClient = MockHttpClient(); + service = MyService(apiKey: 'test-key', httpClient: mockClient); + }); + + tearDown(() { + service.dispose(); + }); + + test('should return result on success', () async { + // Arrange + when(mockClient.post(any)).thenAnswer( + (_) async => http.Response('success', 200), + ); + + // Act + final result = await service.performOperation('input'); + + // Assert + expect(result, equals('success')); + }); + + test('should retry on failure', () async { + // Arrange + when(mockClient.post(any)) + .thenThrow(SocketException('Connection failed')) + .thenAnswer((_) async => http.Response('success', 200)); + + // Act + final result = await service.performOperation('input'); + + // Assert + expect(result, equals('success')); + verify(mockClient.post(any)).called(2); // Called twice due to retry + }); + }); +} +``` + +### Integrating with UI + +```dart +// lib/screens/my_screen.dart +import 'package:provider/provider.dart'; + +class MyScreen extends StatefulWidget { + @override + _MyScreenState createState() => _MyScreenState(); +} + +class _MyScreenState extends State { + String _result = ''; + bool _isLoading = false; + String _error = ''; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('My Feature')), + body: Padding( + padding: EdgeInsets.all(16), + child: Column( + children: [ + if (_error.isNotEmpty) + Container( + color: Colors.red.shade100, + padding: EdgeInsets.all(8), + child: Text(_error, style: TextStyle(color: Colors.red)), + ), + if (_isLoading) + CircularProgressIndicator() + else if (_result.isNotEmpty) + Text(_result) + else + Text('No data yet'), + SizedBox(height: 16), + ElevatedButton( + onPressed: _performOperation, + child: Text('Perform Operation'), + ), + ], + ), + ), + ); + } + + Future _performOperation() async { + setState(() { + _isLoading = true; + _error = ''; + }); + + try { + final service = context.read(); + final result = await service.performOperation('input'); + + setState(() { + _result = result; + }); + } catch (e) { + setState(() { + _error = 'Error: $e'; + }); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} +``` + +## Running Tests + +### Unit Tests +```bash +# All tests +flutter test + +# Specific test file +flutter test test/services/my_service_test.dart + +# With coverage +flutter test --coverage + +# Generate HTML coverage report +genhtml coverage/lcov.info -o coverage/html +open coverage/html/index.html +``` + +### Widget Tests +```bash +# Run only widget tests +flutter test --tags widget + +# Run with specific pattern +flutter test test/screens/ +``` + +### Integration Tests +```bash +# Run integration tests (device required) +flutter drive --target=test_driver/app.dart +``` + +## Debugging + +### Using Debugger + +```dart +// Add breakpoint in VS Code by clicking line number +Future myFunction() { + int myVar = 5; // Click here to set breakpoint + print(myVar); +} +``` + +### Logging + +```dart +import 'dart:developer' as developer; + +// Log messages +developer.log('Debug message', name: 'my_service'); +developer.log('Error occurred: $error', name: 'my_service'); + +// Use Timeline profiling +developer.Timeline.startSync('operation_name'); +// ... operation ... +developer.Timeline.finishSync(); +``` + +### Using DevTools + +```bash +# Launch DevTools +flutter pub global activate devtools +devtools + +# Connect running app +# Visit http://localhost:9100 in browser +``` + +### Common Debug Commands + +```bash +# Run with verbose logging +flutter run -v + +# Run with checked mode on release +flutter run -c release --debug-symbols-dir=symbols + +# Attach to existing app +flutter attach + +# Show build output details +flutter build apk -v +``` + +## Code Quality + +### Static Analysis + +```bash +# Run analyzer +flutter analyze + +# Fix issues automatically +dart fix --apply +``` + +### Code Formatting + +```bash +# Check formatting +dart format --set-exit-if-changed lib test + +# Auto-format code +dart format lib test + +# Format in VS Code +Ctrl+Shift+P โ†’ Format Document +``` + +### Linting + +```bash +# See all linting issues +flutter analyze --fatal-warnings + +# Fix common issues +dart fix --apply +``` + +## Performance Profiling + +### Memory Profiling + +```bash +# Run app with memory profiling +flutter run --profile + +# Use DevTools Memory tab to: +# - Monitor memory usage +# - Detect memory leaks +# - Take heap snapshots +``` + +### CPU Profiling + +```bash +# View CPU usage in DevTools +# Use Timeline tab to profile frame rendering +# Identify janky frames and optimize +``` + +### Build Performance + +```bash +# Analyze build time +flutter build apk --analyze-size + +# View release build size +flutter build apk --release --split-per-abi +``` + +## Troubleshooting + +### Common Issues + +**Issue: `flutter pub get` fails** +```bash +# Solution 1: Update pub cache +flutter pub cache repair + +# Solution 2: Clean and retry +flutter clean +flutter pub get +``` + +**Issue: Build fails with pod install error** +```bash +# Solution: Reinstall pods +cd ios +rm -rf Pods +pod install +cd .. +``` + +**Issue: Tests fail locally but pass in CI** +```bash +# Causes: +# - Platform differences (mock behavior) +# - Environment variables not set +# - Race conditions in async code +# - File system differences + +# Debug: +flutter test -v # See detailed output +flutter test --concurrency=1 # Disable parallel execution +``` + +**Issue: App crashes on startup** +```bash +# Debug: +flutter run -v # See verbose output +flutter logs # Monitor log output +flutter attach # Debug running app +``` + +## Git Workflow + +### Feature Development + +```bash +# Start new feature +git checkout main +git pull upstream main +git checkout -b feature/my-feature + +# Make changes and commit +git add . +git commit -m "feat: add new feature description" + +# Push to remote +git push -u origin feature/my-feature + +# Create pull request +gh pr create --title "feat: feature title" --body "Description" +``` + +### Keeping Branch Updated + +```bash +# Fetch latest from main +git fetch upstream main + +# Rebase on main +git rebase upstream/main + +# If conflicts occur, resolve them +git add resolved_file.dart +git rebase --continue +``` + +### Squashing Commits + +```bash +# Interactive rebase +git rebase -i HEAD~3 # Last 3 commits + +# In editor: change 'pick' to 'squash' for commits to merge +# Save and merge commit messages +``` + +## Release Process + +### Creating a Release + +```bash +# Update version in pubspec.yaml +# Update CHANGELOG.md +# Create version tag +git tag v1.2.0 + +# Push tag (triggers CD pipeline) +git push origin v1.2.0 + +# GitHub Actions automatically: +# 1. Builds all platforms +# 2. Generates release notes +# 3. Creates GitHub Release +# 4. Uploads artifacts +``` + +### Hotfix Process + +```bash +# Create hotfix branch from main +git checkout -b hotfix/bug-fix main + +# Fix bug and test +# Create PR with hotfix label +# Merge to main +# Tag release + +git tag v1.2.1 +git push origin v1.2.1 +``` + +## Resources + +### Documentation +- [Flutter Documentation](https://flutter.dev/docs) +- [Dart Documentation](https://dart.dev) +- [Provider Package](https://pub.dev/packages/provider) +- [Mockito Package](https://pub.dev/packages/mockito) + +### Tools +- [VS Code Flutter Extension](https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter) +- [Android Studio](https://developer.android.com/studio) +- [Xcode](https://developer.apple.com/xcode/) + +### Learning Resources +- [Flutter Codelabs](https://flutter.dev/docs/codelabs) +- [Dart Language Tour](https://dart.dev/guides/language/language-tour) +- [Architecture Patterns](https://resocoder.com/flutter-clean-architecture) + +## Getting Help + +- **Issues**: Check existing GitHub issues +- **Discussions**: Ask in GitHub Discussions +- **Docs**: Read project documentation +- **Code Examples**: Check `lib/examples/` directory + +--- + +Happy coding! ๐Ÿš€ \ No newline at end of file