110 lines
4.3 KiB
Markdown
110 lines
4.3 KiB
Markdown
# Copilot Instructions for splash_video
|
|
|
|
## Project Overview
|
|
A Flutter package for video splash screens using `media_kit`. Provides smooth transitions from native splash to video playback with overlay support and manual controls.
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
- **`SplashVideo`** ([lib/widgets/splash_video_w.dart](../lib/widgets/splash_video_w.dart)) - Main widget orchestrating lifecycle, overlays, and navigation
|
|
- **`SplashVideoPlayer`** ([lib/widgets/splash_video_player_w.dart](../lib/widgets/splash_video_player_w.dart)) - Internal widget handling media_kit Player/VideoController
|
|
- **`SplashVideoController`** ([lib/splash_video_controller.dart](../lib/splash_video_controller.dart)) - Public API for play/pause/skip with underlying Player access
|
|
- **`VideoConfig`** ([lib/video_config.dart](../lib/video_config.dart)) - Configuration: fitMode, volume, playImmediately, useSafeArea
|
|
- **`Source`** (sealed class in [lib/video_source.dart](../lib/video_source.dart)) - Video sources: `AssetSource`, `NetworkSource`, `DeviceFileSource`, `BytesSource`
|
|
|
|
### Key Pattern: Deferred First Frame
|
|
The package uses Flutter's `deferFirstFrame`/`allowFirstFrame` to prevent jank:
|
|
```dart
|
|
// In main() - call SplashVideo.initialize() ONLY if first screen is SplashVideo
|
|
SplashVideo.initialize(); // Defers frame + initializes MediaKit
|
|
// Later, SplashVideo.resume() is called automatically when video loads
|
|
```
|
|
|
|
### Widget Composition
|
|
```
|
|
SplashVideo (lifecycle, navigation, overlays)
|
|
└── SplashVideoPlayer (media_kit integration)
|
|
└── Video widget from media_kit_video
|
|
```
|
|
|
|
## Development Commands
|
|
|
|
```bash
|
|
# Run all unit tests
|
|
flutter test
|
|
|
|
# Run specific test
|
|
flutter test test/video_source_test.dart
|
|
|
|
# Run with coverage
|
|
flutter test --coverage
|
|
|
|
# Integration tests (from example/)
|
|
cd example && flutter test integration_test/plugin_integration_test.dart
|
|
|
|
# Run example app
|
|
cd example && flutter run
|
|
```
|
|
|
|
## Conventions
|
|
|
|
### Source Types (Sealed Class)
|
|
Always use the appropriate `Source` subclass - the sealed class prevents external subclassing:
|
|
```dart
|
|
AssetSource('assets/videos/splash.mp4') // Bundled assets
|
|
NetworkSource('https://example.com/video.mp4') // URLs (validates format)
|
|
DeviceFileSource('/path/to/video.mp4') // Local files
|
|
BytesSource(Uint8List) // In-memory bytes
|
|
```
|
|
|
|
### VideoFitMode
|
|
Maps to Flutter's `BoxFit`. Default is `cover` for splash screens (fills screen, may crop).
|
|
|
|
### Controller Lifecycle
|
|
- Controller must be disposed by the caller (not the widget)
|
|
- Access `controller.player` only after widget is built (throws `StateError` otherwise)
|
|
- For looping videos, controller is **required**
|
|
|
|
### Error Handling
|
|
- Use `SplashVideoException` for package-specific errors
|
|
- Provide `onVideoError` callback for graceful degradation
|
|
- In debug mode, diagnostic prints prefixed with `SplashVideoPlayer:` or `SplashVideo:`
|
|
|
|
## Testing Patterns
|
|
|
|
Tests use Arrange-Act-Assert pattern. Widget tests should handle async initialization:
|
|
```dart
|
|
group('FeatureName', () {
|
|
test('should do something', () {
|
|
// Arrange - setup
|
|
// Act - execute
|
|
// Assert - verify with expect()
|
|
});
|
|
});
|
|
```
|
|
|
|
See [test/README.md](../test/README.md) for comprehensive testing guide.
|
|
|
|
## File Structure
|
|
```
|
|
lib/
|
|
├── splash_video.dart # Library exports (barrel file)
|
|
├── splash_video_controller.dart
|
|
├── splash_video_enums.dart # VideoFitMode + BoxFit extension
|
|
├── video_config.dart
|
|
├── video_source.dart # Sealed Source class hierarchy
|
|
├── utils.dart # Typedefs, exceptions, extensions
|
|
└── widgets/
|
|
├── splash_video_w.dart # Main public widget
|
|
└── splash_video_player_w.dart # Internal player widget
|
|
```
|
|
|
|
## Platform Support
|
|
All platforms via media_kit: Android, iOS, macOS, Windows, Linux. Platform-specific libs are in pubspec.yaml dependencies.
|
|
|
|
## Workflow Rules
|
|
- **Documentation format**: Create all documentation with lowercase filenames and `.rst` format, no emojis
|
|
- **End of task**: Always ask if tests and documentation should be updated (README.md is critical)
|
|
- **No auto-docs**: Do not create a document for every feature/change - ask if comprehensive documentation is wanted at task end
|
|
- **No silent removal**: Never remove functionality without explicit user confirmation
|