import 'package:flutter/material.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:f0ckapp/models/MediaItem.dart'; import 'package:f0ckapp/services/Api.dart'; import 'package:f0ckapp/widgets/VideoWidget.dart'; import 'package:f0ckapp/utils/SmartRefreshIndicator.dart'; import 'package:f0ckapp/utils/PageTransformer.dart'; class DetailView extends StatefulWidget { final int initialItemId; final List mediaItems; final String type; final int mode; final bool random; final String? tagname; const DetailView({ super.key, required this.initialItemId, required this.mediaItems, required this.type, required this.mode, required this.random, required this.tagname, }); @override State createState() => _DetailViewState(); } class _DetailViewState extends State { late PageController _pageController; late List mediaItems; String? _tagname; int currentItemId = 0; bool isLoading = false; @override void initState() { super.initState(); mediaItems = widget.mediaItems; _tagname = widget.tagname; final initialIndex = mediaItems.indexWhere( (item) => item.id == widget.initialItemId, ); _pageController = PageController(initialPage: initialIndex); currentItemId = mediaItems[initialIndex].id; _pageController.addListener(_onPageScroll); } void _onPageScroll() { final newIndex = _pageController.page?.round(); if (newIndex != null && newIndex < mediaItems.length) { setState(() => currentItemId = mediaItems[newIndex].id); } if (_pageController.position.pixels >= _pageController.position.maxScrollExtent - 100) { _loadMoreMedia(); } } Future _loadMoreMedia() async { if (isLoading) return; setState(() => isLoading = true); try { final newMedia = await fetchMedia( older: mediaItems.last.id.toString(), type: widget.type, mode: widget.mode, random: widget.random, tag: _tagname, ); if (mounted && newMedia.isNotEmpty) { setState(() => mediaItems.addAll(newMedia)); } } catch (e) { _showError("Fehler beim Laden weiterer Medien: $e"); } finally { setState(() => isLoading = false); } } Future _refreshMediaItem() async { try { final updatedItem = await fetchMediaDetail(currentItemId); if (mounted) { final index = mediaItems.indexWhere((item) => item.id == currentItemId); if (index != -1) { setState(() => mediaItems[index] = updatedItem); } } } catch (e) { _showError("Fehler beim Aktualisieren des Items: $e"); } } void _showError(String message) { if (mounted) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(message))); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF171717), appBar: AppBar( backgroundColor: const Color(0xFF2B2B2B), foregroundColor: Colors.white, title: Text('f0ck #$currentItemId (${widget.type})'), centerTitle: true, ), body: Stack( children: [ PageTransformer( controller: _pageController, pages: mediaItems.map((item) { return Scaffold( body: SafeArea( child: SmartRefreshIndicator( onRefresh: _refreshMediaItem, child: _buildMediaItem(item), ), ), ); }).toList(), ), if (_tagname != null) Positioned( bottom: 60, left: MediaQuery.of(context).size.width * 0.2, right: MediaQuery.of(context).size.width * 0.2, child: Container( padding: const EdgeInsets.symmetric( vertical: 10, horizontal: 20, ), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.8), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Tag: $_tagname', style: const TextStyle(color: Colors.white), ), IconButton( icon: const Icon(Icons.close, color: Colors.white), onPressed: () { setState(() { _tagname = '___empty___'; Navigator.pop(context, _tagname); }); }, ), ], ), ), ), ], ), ); } Widget _buildMediaItem(MediaItem item) { return SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (item.mime.startsWith('image')) CachedNetworkImage( imageUrl: item.mediaUrl, fit: BoxFit.contain, placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), ) else VideoWidget(details: item), const SizedBox(height: 20), Text( item.mime, style: const TextStyle(color: Colors.white, fontSize: 18), ), const SizedBox(height: 10, width: double.infinity), Wrap( alignment: WrapAlignment.center, spacing: 5.0, children: item.tags.map((tag) { return GestureDetector( onTap: () { if (tag.tag == 'sfw' || tag.tag == 'nsfw') return; setState(() { _tagname = tag.tag; Navigator.pop(context, _tagname); }); }, child: Chip( label: Text(tag.tag), backgroundColor: switch (tag.id) { 1 => Colors.green, 2 => Colors.red, _ => const Color(0xFF090909), }, labelStyle: const TextStyle(color: Colors.white), ), ); }).toList(), ), const SizedBox(height: 20), ], ), ); } }