video_preview.dart 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import 'dart:typed_data';
  2. import 'package:flutter/material.dart';
  3. import 'package:veloe_kemono_party_flutter/video_thumbnail_generator';
  4. class VideoPreview extends StatefulWidget {
  5. final String videoUrl;
  6. final VoidCallback onTap;
  7. const VideoPreview({
  8. super.key,
  9. required this.videoUrl,
  10. required this.onTap,
  11. });
  12. @override
  13. State<VideoPreview> createState() => _VideoPreviewState();
  14. }
  15. class _VideoPreviewState extends State<VideoPreview> {
  16. Future<Uint8List?>? _thumbnailFuture;
  17. bool _isGenerating = false;
  18. @override
  19. void initState() {
  20. super.initState();
  21. _loadThumbnail();
  22. }
  23. void _loadThumbnail() {
  24. setState(() => _isGenerating = true);
  25. _thumbnailFuture = VideoThumbnailGenerator.getFirstFrameThumbnail(widget.videoUrl)
  26. .whenComplete(() => setState(() => _isGenerating = false));
  27. }
  28. @override
  29. Widget build(BuildContext context) {
  30. return GestureDetector(
  31. onTap: widget.onTap,
  32. child: FutureBuilder<Uint8List?>(
  33. future: _thumbnailFuture,
  34. builder: (context, snapshot) {
  35. return AspectRatio(
  36. aspectRatio: 16/9,
  37. child: Stack(
  38. fit: StackFit.expand,
  39. children: [
  40. // Thumbnail display
  41. if (snapshot.hasData)
  42. Image.memory(snapshot.data!, fit: BoxFit.cover)
  43. else if (_isGenerating)
  44. const Center(child: CircularProgressIndicator())
  45. else
  46. Container(color: Colors.black),
  47. // Play button overlay
  48. const Center(
  49. child: Icon(Icons.play_circle_filled,
  50. size: 64,
  51. color: Colors.white70,
  52. ),
  53. ),
  54. // Video indicator
  55. Positioned(
  56. bottom: 8,
  57. right: 8,
  58. child: Container(
  59. padding: const EdgeInsets.all(4),
  60. color: Colors.black54,
  61. child: const Text('VIDEO',
  62. style: TextStyle(color: Colors.white)),
  63. ),
  64. )
  65. ],
  66. ),
  67. );
  68. },
  69. ),
  70. );
  71. }
  72. }