123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- import 'dart:typed_data';
- import 'package:flutter/material.dart';
- import 'package:veloe_kemono_party_flutter/video_thumbnail_generator';
- import '../../main.dart';
- class VideoPreview extends StatefulWidget {
- final String videoUrl;
- final VoidCallback onTap;
-
- const VideoPreview({
- super.key,
- required this.videoUrl,
- required this.onTap,
- });
- @override
- State<VideoPreview> createState() => _VideoPreviewState();
- }
- class _VideoPreviewState extends State<VideoPreview> {
- Future<Uint8List?>? _thumbnailFuture;
- bool _isGenerating = false;
- bool _isCached = false;
- @override
- void initState() {
- super.initState();
- _checkCacheStatus();
- _loadThumbnail();
- }
- void _loadThumbnail() {
- setState(() => _isGenerating = true);
- _thumbnailFuture = VideoThumbnailGenerator.getFirstFrameThumbnail(widget.videoUrl)
- .whenComplete(() => setState(() => _isGenerating = false));
- }
- Future<void> _checkCacheStatus() async {
- final cachedFile = await videoCacheManager.getFileFromCache(widget.videoUrl);
- if (cachedFile != null && mounted) {
- setState(() => _isCached = true);
- }
- }
- @override
- Widget build(BuildContext context) {
- return GestureDetector(
- onTap: widget.onTap,
- child: FutureBuilder<Uint8List?>(
- future: _thumbnailFuture,
- builder: (context, snapshot) {
- return AspectRatio(
- aspectRatio: 16/9,
- child: Stack(
- fit: StackFit.expand,
- children: [
- // Thumbnail display
- if (snapshot.hasData)
- Image.memory(snapshot.data!, fit: BoxFit.cover)
- else if (_isGenerating)
- const Center(child: CircularProgressIndicator())
- else
- Container(color: Colors.black),
-
- // Play button overlay
- const Center(
- child: Icon(Icons.play_circle_filled,
- size: 64,
- color: Colors.white70,
- ),
- ),
-
- // Video indicator
- Positioned(
- bottom: 8,
- right: 8,
- child: Container(
- padding: const EdgeInsets.all(4),
- color: Colors.black54,
- child: const Text('VIDEO',
- style: TextStyle(color: Colors.white)),
- ),
- ),
- if (_isCached)
- Positioned(
- top: 8,
- right: 8,
- child: Container(
- padding: const EdgeInsets.all(4),
- decoration: const BoxDecoration(
- color: Colors.green,
- shape: BoxShape.circle,
- ),
- child: const Icon(Icons.download_done, size: 16, color: Colors.white),
- ),
- ),
- ],
- ),
- );
- },
- ),
- );
- }
- }
|