4.3 KiB
4.3 KiB
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) - Main widget orchestrating lifecycle, overlays, and navigationSplashVideoPlayer(lib/widgets/splash_video_player_w.dart) - Internal widget handling media_kit Player/VideoControllerSplashVideoController(lib/splash_video_controller.dart) - Public API for play/pause/skip with underlying Player accessVideoConfig(lib/video_config.dart) - Configuration: fitMode, volume, playImmediately, useSafeAreaSource(sealed class in 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:
// 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
# 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:
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.playeronly after widget is built (throwsStateErrorotherwise) - For looping videos, controller is required
Error Handling
- Use
SplashVideoExceptionfor package-specific errors - Provide
onVideoErrorcallback for graceful degradation - In debug mode, diagnostic prints prefixed with
SplashVideoPlayer:orSplashVideo:
Testing Patterns
Tests use Arrange-Act-Assert pattern. Widget tests should handle async initialization:
group('FeatureName', () {
test('should do something', () {
// Arrange - setup
// Act - execute
// Assert - verify with expect()
});
});
See 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
.rstformat, 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