fApp/lib/screens/detail.dart
2025-05-31 16:40:25 +02:00

165 lines
6.0 KiB
Dart

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<DetailView> createState() => _DetailViewState();
}
class _DetailViewState extends State<DetailView> {
late VideoPlayerController _controller;
late Future<void> _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<void> _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)),
],
),
),
],
),
),
),
);
}
}