This commit is contained in:
Flummi 2025-05-31 16:48:33 +02:00
parent 6830de4e75
commit 018581e4d2

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
import 'package:f0ckapp/models/mediaitem_detail.dart'; import 'package:f0ckapp/models/mediaitem_detail.dart';
import 'package:f0ckapp/services/api.dart'; // API Call für neue Items import 'package:f0ckapp/services/api.dart';
class DetailView extends StatefulWidget { class DetailView extends StatefulWidget {
final MediaItemDetail details; final MediaItemDetail details;
@ -21,15 +21,20 @@ class _DetailViewState extends State<DetailView> {
void initState() { void initState() {
super.initState(); super.initState();
isAudio = widget.details.mime.startsWith("audio/"); isAudio = widget.details.mime.startsWith("audio/");
_controller = VideoPlayerController.networkUrl(Uri.parse(widget.details.mediaUrl)); _controller = VideoPlayerController.networkUrl(
Uri.parse(widget.details.mediaUrl),
);
if (!widget.details.mime.startsWith("image/")) { if (!widget.details.mime.startsWith("image/")) {
_initializeVideoPlayer = _controller.initialize().then((_) { _initializeVideoPlayer = _controller
.initialize()
.then((_) {
setState(() { setState(() {
_controller.play(); _controller.play();
_controller.setLooping(true); _controller.setLooping(true);
}); });
}).catchError((error) { })
.catchError((error) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Fehler beim Laden des Videos: $error")), SnackBar(content: Text("Fehler beim Laden des Videos: $error")),
); );
@ -45,21 +50,29 @@ class _DetailViewState extends State<DetailView> {
Future<void> _loadNewMediaItem(int itemId, bool swipeLeft) async { Future<void> _loadNewMediaItem(int itemId, bool swipeLeft) async {
try { try {
var newDetails = await fetchMediaDetail(itemId); // API Call var newDetails = await fetchMediaDetail(itemId);
Navigator.of(context).pushReplacement(PageRouteBuilder( Navigator.of(context).pushReplacement(
pageBuilder: (context, animation, secondaryAnimation) => DetailView(details: newDetails), PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
DetailView(details: newDetails),
transitionsBuilder: (context, animation, secondaryAnimation, child) { transitionsBuilder: (context, animation, secondaryAnimation, child) {
Offset begin = swipeLeft ? const Offset(-1.0, 0.0) : const Offset(1.0, 0.0); // Richtung des Swipes Offset begin = swipeLeft
? const Offset(-1.0, 0.0)
: const Offset(1.0, 0.0);
const Offset end = Offset.zero; const Offset end = Offset.zero;
const curve = Curves.easeInOut; const curve = Curves.easeInOut;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); var tween = Tween(
begin: begin,
end: end,
).chain(CurveTween(curve: curve));
var offsetAnimation = animation.drive(tween); var offsetAnimation = animation.drive(tween);
return SlideTransition(position: offsetAnimation, child: child); return SlideTransition(position: offsetAnimation, child: child);
}, },
)); ),
);
} catch (error) { } catch (error) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Fehler beim Laden des Items: $error")), SnackBar(content: Text("Fehler beim Laden des Items: $error")),
@ -87,20 +100,27 @@ class _DetailViewState extends State<DetailView> {
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
if (widget.details.mime.contains(RegExp(r'image/(jpeg|png|gif|webp)'))) ...[ if (widget.details.mime.contains(
RegExp(r'image/(jpeg|png|gif|webp)'),
)) ...[
Image.network(widget.details.mediaUrl), Image.network(widget.details.mediaUrl),
] else ...[ ] else ...[
Stack( Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
if (isAudio) if (isAudio)
Image.network('https://f0ck.me/ca/${widget.details.id}.webp'), Image.network(
'https://f0ck.me/ca/${widget.details.id}.webp',
),
FutureBuilder( FutureBuilder(
future: _initializeVideoPlayer, future: _initializeVideoPlayer,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done && _controller.value.isInitialized) { if (snapshot.connectionState == ConnectionState.done &&
_controller.value.isInitialized) {
return AspectRatio( return AspectRatio(
aspectRatio: isAudio ? 1 : _controller.value.aspectRatio, aspectRatio: isAudio
? 1
: _controller.value.aspectRatio,
child: VideoPlayer(_controller), child: VideoPlayer(_controller),
); );
} else { } else {
@ -123,21 +143,33 @@ class _DetailViewState extends State<DetailView> {
IconButton( IconButton(
icon: const Icon(Icons.replay_10), icon: const Icon(Icons.replay_10),
onPressed: () { onPressed: () {
_controller.seekTo(_controller.value.position - const Duration(seconds: 10)); _controller.seekTo(
_controller.value.position -
const Duration(seconds: 10),
);
}, },
), ),
IconButton( IconButton(
icon: Icon(_controller.value.isPlaying ? Icons.pause : Icons.play_arrow), icon: Icon(
_controller.value.isPlaying
? Icons.pause
: Icons.play_arrow,
),
onPressed: () { onPressed: () {
setState(() { setState(() {
_controller.value.isPlaying ? _controller.pause() : _controller.play(); _controller.value.isPlaying
? _controller.pause()
: _controller.play();
}); });
}, },
), ),
IconButton( IconButton(
icon: const Icon(Icons.forward_10), icon: const Icon(Icons.forward_10),
onPressed: () { onPressed: () {
_controller.seekTo(_controller.value.position + const Duration(seconds: 10)); _controller.seekTo(
_controller.value.position +
const Duration(seconds: 10),
);
}, },
), ),
], ],
@ -149,9 +181,18 @@ class _DetailViewState extends State<DetailView> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('${widget.details.mime}', style: const TextStyle(fontSize: 16, color: Colors.white)), Text(
Text("Benutzername: ${widget.details.username}", style: const TextStyle(fontSize: 16, color: Colors.white)), '${widget.details.mime}',
Text("Zeitstempel: ${widget.details.stamp}", style: const TextStyle(fontSize: 16, color: Colors.white)), 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),
),
], ],
), ),
), ),