import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; import 'package:f0ckapp/models/mediaitem_detail.dart'; import 'package:f0ckapp/services/api.dart'; // API Call für neue Items class DetailView extends StatefulWidget { final MediaItemDetail details; const DetailView({super.key, required this.details}); @override State createState() => _DetailViewState(); } class _DetailViewState extends State { late VideoPlayerController _controller; late Future _initializeVideoPlayer; bool isAudio = false; @override void initState() { super.initState(); isAudio = widget.details.mime.startsWith("audio/"); _controller = VideoPlayerController.networkUrl(Uri.parse(widget.details.mediaUrl)); if (!widget.details.mime.startsWith("image/")) { _initializeVideoPlayer = _controller.initialize().then((_) { setState(() { _controller.play(); _controller.setLooping(true); }); }).catchError((error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Fehler beim Laden des Videos: $error")), ); }); } } @override void dispose() { _controller.dispose(); super.dispose(); } Future _loadNewMediaItem(int itemId, bool swipeLeft) async { try { var newDetails = await fetchMediaDetail(itemId); // API Call Navigator.of(context).pushReplacement(PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => DetailView(details: newDetails), transitionsBuilder: (context, animation, secondaryAnimation, child) { Offset begin = swipeLeft ? const Offset(-1.0, 0.0) : const Offset(1.0, 0.0); // Richtung des Swipes const Offset end = Offset.zero; const curve = Curves.easeInOut; var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); var offsetAnimation = animation.drive(tween); return SlideTransition(position: offsetAnimation, child: child); }, )); } catch (error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Fehler beim Laden des Items: $error")), ); } } @override Widget build(BuildContext context) { return GestureDetector( onHorizontalDragEnd: (details) { if (details.velocity.pixelsPerSecond.dx > 0) { _loadNewMediaItem(widget.details.next, true); } else if (details.velocity.pixelsPerSecond.dx < 0) { _loadNewMediaItem(widget.details.prev, false); } }, child: Scaffold( appBar: AppBar( backgroundColor: const Color(0xFF2B2B2B), foregroundColor: Colors.white, title: Text('f0ck #${widget.details.id}'), centerTitle: true, ), body: SingleChildScrollView( child: Column( children: [ if (widget.details.mime.contains(RegExp(r'image/(jpeg|png|gif|webp)'))) ...[ Image.network(widget.details.mediaUrl), ] else ...[ Stack( alignment: Alignment.center, children: [ if (isAudio) Image.network('https://f0ck.me/ca/${widget.details.id}.webp'), FutureBuilder( future: _initializeVideoPlayer, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && _controller.value.isInitialized) { return AspectRatio( aspectRatio: isAudio ? 1 : _controller.value.aspectRatio, child: VideoPlayer(_controller), ); } else { return const CircularProgressIndicator(); } }, ), ], ), Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: VideoProgressIndicator( _controller, allowScrubbing: true, ), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.replay_10), onPressed: () { _controller.seekTo(_controller.value.position - const Duration(seconds: 10)); }, ), IconButton( icon: Icon(_controller.value.isPlaying ? Icons.pause : Icons.play_arrow), onPressed: () { setState(() { _controller.value.isPlaying ? _controller.pause() : _controller.play(); }); }, ), IconButton( icon: const Icon(Icons.forward_10), onPressed: () { _controller.seekTo(_controller.value.position + const Duration(seconds: 10)); }, ), ], ), ], const SizedBox(height: 16), Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('${widget.details.mime}', style: const TextStyle(fontSize: 16, color: Colors.white)), Text("Benutzername: ${widget.details.username}", style: const TextStyle(fontSize: 16, color: Colors.white)), Text("Zeitstempel: ${widget.details.stamp}", style: const TextStyle(fontSize: 16, color: Colors.white)), ], ), ), ], ), ), ), ); } }