Skip to content
This repository was archived by the owner on Dec 4, 2025. It is now read-only.

feat: Add quick record with automated model download during onboarding - #5

Merged
stanvx merged 138 commits into
mainfrom
feature/quick-record-shortcut
Jul 27, 2025
Merged

feat: Add quick record with automated model download during onboarding#5
stanvx merged 138 commits into
mainfrom
feature/quick-record-shortcut

Conversation

@stanvx

@stanvx stanvx commented Jul 19, 2025

Copy link
Copy Markdown
Owner

Summary

This PR implements quick record functionality with automated model download during onboarding. The changes reduce the recording workflow from 7+ clicks to 2 clicks and eliminate first-use delays by downloading the Whisper model during app setup.

Key Features

Quick Record Flow

  • SpeedDialFAB component provides one-touch recording access
  • Automated workflow: record → transcribe → create note without manual intervention
  • Background transcription processing maintains UI responsiveness
  • Auto-navigation skips intermediate screens for streamlined experience
  • Latest: Shared audio player ViewModel and enhanced quick recording UI with improved state management

Model Download Integration

  • Whisper model download integrated as final onboarding step
  • New users complete setup before using transcription features
  • Existing users receive automatic model validation on app launch
  • Eliminates download interruptions during first transcription attempt

Architecture Changes

Core Components

  • BackgroundTranscriptionService: Handles automated transcription workflow
  • TranscriptionRepository: Repository pattern implementation for background threading
  • ModelAvailabilityService: Centralized model state management
  • SpeedDialFAB: Material 3 compliant expandable FAB component
  • SharedAudioPlayerViewModel: Unified audio playback state management

Threading & Performance (Tasks 016-018)

  • TranscriptionRepository moves LibWhisper initialization to background thread
  • All UI callbacks execute on main thread via MainScope/Dispatchers.Main
  • Enhanced resource cleanup prevents native memory leaks
  • Race condition handling for recording path availability

Technical Implementation

Project Modernization (Task 015)

  • Migrated from deprecated Android source directory structure to KMP Layout V2
  • Updated androidTest → androidInstrumentedTest for future Gradle compatibility

Material 3 Design System Overhaul

  • Complete migration from Material Icons to Material Symbols font-based system
  • Enhanced typography system with Poppins font family integration
  • Material 3 expressive design components and unified surface system
  • Dynamic color support and improved theming architecture

State Management

  • QuickRecordState enum for comprehensive state tracking
  • Effect-based communication between ViewModels and UI
  • Integration with existing InsertNoteUseCase for note creation
  • Shared audio player state across components

Error Handling

  • Comprehensive error recovery in background transcription
  • Graceful degradation preserves audio even if transcription fails
  • Retry mechanisms for model download failures

Files Added/Modified

Major Additions

New Core Features:
- ModelAvailabilityService.kt
- ModelSetupPage.kt  
- BackgroundTranscriptionService.kt
- SpeedDialFAB.kt
- QuickRecordState.kt
- TranscriptionRepository.kt + Implementation
- SharedAudioPlayerViewModel integration

Material 3 System:
- Material3ExpressiveTypography.kt
- Material3ExpressiveShapes.kt
- Material3ColorScheme.kt
- MaterialSymbols.kt (Font-based icon system)
- PoppinsFontFamily.kt
- Material 3 compliant UI components

Enhanced UI Components:
- ModernAudioPlayer.kt
- OptimizedNoteCard.kt
- UnifiedNoteCard.kt
- SmartNotePreview.kt
- Rich text editor enhancements

Enhanced Components

- OnboardingViewModel.kt (model download coordination)
- TranscriptionViewModel.kt (repository pattern)
- NoteListViewModel.kt (quick record state)
- App.kt (navigation and model setup flow)
- CalendarScreen.kt (Material 3 design updates)
- RecordingScreen.kt (enhanced quick recording UI)

Migration & Cleanup

- androidTest/ → androidInstrumentedTest/ (KMP Layout V2)
- Transcriper*.kt → Transcriber*.kt (spelling correction)
- Material Icons → Material Symbols migration
- Enhanced font system with Poppins integration

Problem Resolution

  • Task 016: UI freeze during transcription → Background threading via repository
  • Task 017: IllegalStateException → Main thread compliance for UI operations
  • Task 018: Resource leaks → Enhanced cleanup and error handling
  • Task 015: Deprecated source layout → Migration to KMP Layout V2
  • Material 3 Migration: Complete design system overhaul with expressive components
  • First-use friction: Download interruptions → Onboarding integration
  • Audio Player Integration: Unified playback state management

Testing & Validation

  • ✅ Android debug APK builds successfully
  • ✅ All compilation checks pass
  • ✅ End-to-end quick record flow tested
  • ✅ Thread safety manually verified
  • ✅ Material 3 design system integration validated
  • ✅ Existing functionality preserved during migration

Known Issues to Address Post-Merge

  1. AndroidManifest.xml: Remove deprecated package attribute (build warning)
  2. Gradle Deprecations: Address Gradle 9.0 compatibility warnings
  3. Documentation: Update component documentation for new Material 3 system

Breaking Changes

None - all changes are backward compatible with existing functionality.

Performance Impact

  • Positive: Background threading eliminates UI freezes during transcription
  • Positive: Material Symbols font reduces APK size compared to individual icon assets
  • Positive: Optimized note card rendering with improved layout efficiency
  • Monitoring: Enhanced resource cleanup prevents memory leaks

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

stanvx added 15 commits July 20, 2025 07:01
- Added Quick Record functionality to navigate and record audio notes.
- Integrated BackgroundTranscriptionService for automatic transcription after recording.
- Enhanced PreferencesRepository to manage accent color settings.
- Updated MyApplicationTheme to apply selected accent colors.
- Introduced SpeedDialFAB for quick access to note creation and recording.
- Modified NoteListViewModel to handle quick record state and intents.
- Created QuickRecordState to manage the UI state during quick recording.
- Added tests for theme system and accent color validation.
@claude

claude Bot commented Jul 19, 2025

Copy link
Copy Markdown

Claude finished @stanvx's task —— View job


PR Review for Quick Record Feature

Comprehensive review completed of this large Kotlin Multiplatform PR. This is an impressive implementation with strong architectural patterns, but there are several areas for improvement.

✅ Strengths

Architecture & Clean Code

  • Excellent Clean Architecture adherence: Clear separation between Data → Domain → Presentation → UI layers
  • Repository pattern implementation: TranscriptionRepositoryImpl properly abstracts platform-specific logic
  • Background service design: BackgroundTranscriptionService follows good encapsulation and lifecycle management
  • Resource management: Proper disposal patterns with isDisposed flag and serviceScope.cancel()

Threading & Concurrency

  • Background threading: Moving LibWhisper initialization to Dispatchers.IO resolves UI freezes
  • Thread safety: Proper use of withContext(Dispatchers.Main) for UI callbacks
  • Structured concurrency: Good use of viewModelScope and supervised jobs

Security & Validation

  • Audio file validation: AudioFileValidator includes comprehensive security checks
  • Path traversal protection: Guards against directory traversal attacks
  • Secure logging: getSecureFileName() prevents sensitive path exposure

UI/UX Design

  • Material 3 compliance: Proper use of color tokens and elevation
  • Accessibility: Good semantic descriptions and custom accessibility actions
  • Animation system: Well-structured with proper timing and easing functions

⚠️ Issues & Recommendations

1. Threading Anti-Pattern in Transcriber.android.kt:138-162

// ISSUE: runBlocking inside withContext(Dispatchers.IO) 
runBlocking {
    withContext(Dispatchers.Main) {
        onNewSegment(startMs, endMs, text)
    }
}

Problem: This blocks the IO thread and defeats the purpose of structured concurrency.

Solution: Pass a coroutine scope to the callback and use launch:

// In TranscriptionRepositoryImpl, pass scope to transcriber
private val callbackScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

// In transcriber
callbackScope.launch {
    onNewSegment(startMs, endMs, text)
}

2. Resource Leak Risk in WhisperModelManager

The BackgroundTranscriptionService:76-96 shows concerning patterns around resource cleanup:

  • No clear lifecycle for WhisperModelManager
  • Missing timeout handling for model initialization
  • Potential memory leaks if service is disposed during transcription

Recommendation: Implement proper resource lifecycle management and add timeout controls.

3. Error Handling Gaps

  • BackgroundTranscriptionService:102 collects indefinitely without timeout
  • Missing cancellation handling in transcription flow
  • No retry mechanism for transient failures

4. State Management Issues

TranscriptionViewModel:67-97 updates state without proper synchronization:

_uiState.update { current ->
    current.copy(
        originalText = "${_uiState.value.originalText}$delimiter${text.trim()}".trim(),
        // ^^^ Race condition: reading _uiState.value while updating
    )
}

Fix: Use the current parameter:

_uiState.update { current ->
    current.copy(
        originalText = "${current.originalText}$delimiter${text.trim()}".trim(),
    )
}

5. Koin Module Organization

Modules.kt:104-105 mixes service types in useCaseModule:

factory { ModelAvailabilityService(get(), get()) }
factory { BackgroundTranscriptionService(get(), get()) }

Recommendation: Create a dedicated serviceModule for better organization.

6. Platform Abstraction Concerns

  • Missing iOS implementation of AudioFileValidator
  • Transcriber.android.kt has hardcoded Android paths
  • No proper expect/actual for platform-specific validation

7. Testing Coverage Gaps

While BackgroundTranscriptionServiceTest exists, coverage is incomplete:

  • No integration tests for the full transcription flow
  • Missing tests for error scenarios in TranscriptionRepositoryImpl
  • No platform-specific tests for audio validation

🔒 Security Assessment

Overall: Good with minor improvements needed:

Strong: Path traversal protection, secure filename logging, audio format validation
⚠️ Moderate: File access validation could use more robust checks
Missing: Input sanitization for transcribed text content

🎯 Performance Considerations

Positive

  • Background threading prevents UI blocks
  • Proper resource disposal prevents leaks
  • Lazy initialization patterns

Areas for Improvement

  • SpeedDialFAB creates new HapticFeedback() instance on every recomposition
  • Material Symbols font loading could be optimized
  • Consider pagination for large transcription results

📝 Minor Issues

  1. Inconsistent naming: Files still contain TranscriperTranscriber renaming artifacts
  2. Magic numbers: Hard-coded animation durations should use constants
  3. Missing documentation: Complex classes like WhisperModelManager need KDoc
  4. Deprecated warnings: AndroidManifest.xml package attribute needs removal

✨ Overall Assessment

This is a well-architected PR that successfully implements complex features while maintaining clean code principles. The quick record functionality, background transcription, and Material 3 migration show excellent technical execution.

Key strengths: Clean Architecture, proper threading, comprehensive security validation, excellent UI/UX design.

Recommendation: Address the threading anti-patterns and state management race conditions before merging. The rest are improvements that can be addressed in follow-up PRs.

Score: 8.5/10 - Excellent work with room for refinement in concurrency patterns.


stanvx and others added 14 commits July 20, 2025 08:40
- Convert initRecognizer() to suspending function with mutex protection
- Add timeout safety (30s) for model initialization
- Implement proper sequential execution in BackgroundTranscriptionService
- Add comprehensive error handling and graceful failure modes
- Fix double cleanup issues preventing resource warnings
- Add idempotent initialization with state tracking
- Update TranscriptionScreen to use LaunchedEffect for suspend calls
- Rename Transcriper -> Transcriber for consistency

Resolves race condition where startRecognizer() was called before model
loading completed, causing "Cannot start - canTranscribe: false" errors
and "A resource failed to call close" warnings.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Migrate from deprecated androidTest to androidInstrumentedTest directory
- Follow KMP best practices for source set organization
- Resolve deprecation warnings for Android Style source directory
- Update documentation with current versions and source layout info
- Ensure compatibility with future Gradle versions

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

Co-Authored-By: Claude <noreply@anthropic.com>
stanvx and others added 28 commits July 27, 2025 09:29
- Remove OptimizedCalendarNoteCard.kt which has been replaced by UnifiedNoteCard
- Update comment in UnifiedNoteCard to reflect component consolidation
- CalendarScreen now uses UnifiedNoteCard with CALENDAR layout mode
- No compilation errors or functionality loss
- Build verified successfully after cleanup

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

Co-Authored-By: Claude <noreply@anthropic.com>
## Unified Note Card System
- Create reusable NoteActionsDropdown component with Material 3 design
- Implement UnifiedNoteCard with LIST/CALENDAR layout modes
- Add SmartNotePreview for intelligent content display
- Integrate audio playback in Home page note cards
- Replace OptimizedCalendarNoteCard with unified system
- Add Material 3 elevation tokens and Poppins font family
- Include custom vector icons for enhanced UI

## Media Recording Fixes
- Fix TranscriptionViewModel resource cleanup using runBlocking in onCleared()
- Resolve async cleanup issues that could prevent proper resource release
- Improve ViewModel lifecycle management for better stability

## Benefits
- Eliminates code duplication between Calendar and Home views
- Provides consistent audio playback and action menus across views
- Enhanced Material 3 design compliance and accessibility
- Better resource management prevents memory leaks
- Unified component architecture improves maintainability

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add TypographyPerformanceTests for Material 3 typography optimization validation
- Add SecurityTests for HTML sanitization and input validation
- These are draft test files to guide future security implementations
- Update typography to Poppins font family with Material 3 expressive design
- Enhance audio recording with reactive Lottie animations
- Improve UI consistency across note list, calendar, and capture screens
- Add new Material Symbol icons and elevation tokens
- Implement smart note preview component for better content display
- Remove deprecated components and consolidate theme structure
- Add comprehensive validation for audio file processing
- Update build configuration for improved performance

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Update TranscriptionScreen to use MaterialIcon with MaterialSymbols.ArrowBack
- Migrate CaptureHubScreen settings icon to Material Symbols
- Convert LanguageSelectionScreen icons (Search, Clear, Check) to Material Symbols
- Refactor RichTextAdvancedFormatting to use Material Symbols throughout:
  - Text alignment icons (FormatAlignLeft, Center, Right, Justify)
  - List formatting icons (FormatListBulleted, FormatListNumbered)
  - Indentation controls (FormatIndentDecrease, FormatIndentIncrease)
  - Content formatting (FormatQuote, HorizontalRule)
  - Link management (Link, LinkOff)
- Add missing Material Symbol codepoints for rich text formatting
- Update component signatures to accept iconSymbol strings instead of ImageVectors

Progress: Core components migrated, remaining components in other files need migration

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

Co-Authored-By: Claude <noreply@anthropic.com>
Removes the deprecated package attribute that was generating build warnings.
The namespace is now properly configured via Gradle build configuration.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses critical issues identified in comprehensive code review:

Performance & Memory:
- Fix memory leak in AmplitudeCollector by replacing toMutableList() with ArrayDeque
- Move file operations to IO dispatcher in AudioFileValidator
- Add race condition protection in RecordingScreen state collection

Threading & Concurrency:
- Replace MainScope().launch with structured concurrency in Transcriber
- Use collectAsStateWithLifecycle() for proper lifecycle management
- Improve error propagation with withContext patterns

Security Enhancements:
- Comprehensive path security validation with canonical path resolution
- Enhanced directory traversal protection with URL encoding detection
- Control character validation and dangerous pattern detection
- Platform-specific security implementations for Android/iOS

Error Handling:
- Replace generic RuntimeException with specific TranscriptionError types
- Better error recovery strategies and user-friendly messages
- Improved exception handling across transcription pipeline

Code Quality:
- Extract magic numbers to AppConstants with proper categorization
- Add Audio, UI, and timing constants for maintainability
- Consistent dimension and timing management across components

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

Co-Authored-By: Claude <noreply@anthropic.com>
@stanvx
stanvx merged commit 45033aa into main Jul 27, 2025
6 of 7 checks passed
@stanvx
stanvx deleted the feature/quick-record-shortcut branch July 27, 2025 06:45
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant