import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_cache_manager/file.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:get/get.dart'; import 'package:share_plus/share_plus.dart'; import 'package:f0ckapp/utils/animatedtransition.dart'; import 'package:f0ckapp/controller/authcontroller.dart'; import 'package:f0ckapp/widgets/actiontag.dart'; import 'package:f0ckapp/widgets/favorite_avatars.dart'; import 'package:f0ckapp/screens/fullscreen.dart'; import 'package:f0ckapp/widgets/end_drawer.dart'; import 'package:f0ckapp/controller/mediacontroller.dart'; import 'package:f0ckapp/models/item.dart'; import 'package:f0ckapp/widgets/video_widget.dart'; class MediaDetailScreen extends StatefulWidget { final int initialId; const MediaDetailScreen({super.key, required this.initialId}); @override State createState() => _MediaDetailScreenState(); } class _MediaDetailScreenState extends State { late PageController _pageController; final MediaController mediaController = Get.find(); final AuthController authController = Get.find(); int? _currentIndex; @override void initState() { super.initState(); final int idx = mediaController.items.indexWhere( (item) => item.id == widget.initialId, ); _currentIndex = idx >= 0 ? idx : 0; _pageController = PageController(initialPage: _currentIndex!); } void _showMsg(String message) { if (!mounted) return; Get ..closeAllSnackbars() ..snackbar('hehe', message, snackPosition: SnackPosition.BOTTOM); } void _onPageChanged(int idx) { if (idx != _currentIndex) { setState(() => _currentIndex = idx); } if (idx >= mediaController.items.length - 2 && !mediaController.loading.value && !mediaController.atEnd.value) { mediaController.fetchMore(); } if (idx <= 1 && !mediaController.loading.value && !mediaController.atStart.value) { mediaController.fetchNewer(); } } Future _downloadMedia(MediaItem item) async { final File file = await DefaultCacheManager().getSingleFile(item.mediaUrl); final MethodChannel methodChannel = const MethodChannel('MediaShit'); bool? success = await methodChannel.invokeMethod('saveFile', { 'filePath': file.path, 'fileName': item.dest, }); success == true ? _showMsg('${item.dest} wurde in Downloads/fApp neigespeichert.') : _showMsg('${item.dest} konnte nicht heruntergeladen werden.'); } @override void dispose() { _pageController.dispose(); super.dispose(); } Widget _buildMedia(MediaItem item, bool isActive) { if (item.mime.startsWith('image/')) { return CachedNetworkImage( imageUrl: item.mediaUrl, fit: BoxFit.contain, errorWidget: (c, e, s) => const Icon(Icons.broken_image, size: 100), ); } else if (item.mime.startsWith('video/') || item.mime.startsWith('audio/')) { return VideoWidget(details: item, isActive: isActive); } else { return const Icon(Icons.help_outline, size: 100); } } @override Widget build(BuildContext context) { return Obx( () => PageView.builder( controller: _pageController, itemCount: mediaController.items.length, onPageChanged: _onPageChanged, itemBuilder: (context, index) { final MediaItem item = mediaController.items[index]; final bool isActive = index == _currentIndex; final bool isFavorite = item.favorites?.any( (f) => f.userId == authController.userId.value, ) ?? false; return Scaffold( endDrawer: EndDrawer(), endDrawerEnableOpenDragGesture: mediaController.drawerSwipeEnabled.value, body: CustomScrollView( slivers: [ SliverAppBar( floating: false, pinned: true, title: Text('f0ck #${item.id}'), actions: [ IconButton( icon: const Icon(Icons.fullscreen), onPressed: () { Get.to( FullScreenMediaView(item: item), fullscreenDialog: true, ); }, ), IconButton( icon: const Icon(Icons.download), onPressed: () async { await _downloadMedia(item); }, ), PopupMenuButton( onSelected: (value) async { switch (value) { case 'media': File file = await DefaultCacheManager() .getSingleFile(item.mediaUrl); Uint8List bytes = await file.readAsBytes(); final params = ShareParams( files: [ XFile.fromData(bytes, mimeType: item.mime), ], ); await SharePlus.instance.share(params); break; case 'direct_link': await SharePlus.instance.share( ShareParams(text: item.mediaUrl), ); break; case 'post_link': await SharePlus.instance.share( ShareParams(text: item.postUrl), ); break; } }, itemBuilder: (context) => [ PopupMenuItem( value: 'media', child: ListTile( leading: const Icon(Icons.image), title: const Text('Als Datei'), ), ), PopupMenuItem( value: 'direct_link', child: ListTile( leading: const Icon(Icons.link), title: const Text('Link zur Datei'), ), ), PopupMenuItem( value: 'post_link', child: ListTile( leading: const Icon(Icons.article), title: const Text('Link zum f0ck'), ), ), ], icon: const Icon(Icons.share), ), Builder( builder: (context) => IconButton( icon: const Icon(Icons.menu), onPressed: () { Scaffold.of(context).openEndDrawer(); }, ), ), ], ), SliverToBoxAdapter( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ AnimatedBuilder( animation: _pageController, builder: (context, child) { return buildAnimatedTransition( context: context, pageController: _pageController, index: index, controller: mediaController, child: child!, ); }, child: _buildMedia(item, isActive), ), const SizedBox(height: 16), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ...item.tags?.map( (tag) => Padding( padding: const EdgeInsets.only(right: 6), child: ActionTag(tag, (onTagTap) { if (tag.tag == 'sfw' || tag.tag == 'nsfw') { return; } mediaController.setTag(onTagTap); Get.offAllNamed('/'); }), ), ) ?? [], ], ), if (authController.isLoggedIn) ...[ const SizedBox(height: 20), Row( children: [ Expanded( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: FavoriteAvatars( favorites: item.favorites ?? [], brightness: Theme.of( context, ).brightness, ), ), ), IconButton( icon: isFavorite ? const Icon(Icons.favorite) : const Icon(Icons.favorite_outline), color: Colors.red, onPressed: () async { final List? newFavorites = await mediaController.toggleFavorite( item, isFavorite, ); if (newFavorites != null) { mediaController.items[index] = item .copyWith(favorites: newFavorites); mediaController.items.refresh(); } setState(() {}); }, ), ], ), ], ], ), ), ], ), ), ], ), persistentFooterButtons: [ Obx(() { if (mediaController.tag.value != null) { return Center( child: InputChip( label: Text(mediaController.tag.value!), onDeleted: () { mediaController.setTag(null); Get.offAllNamed('/'); }, ), ); } else { return SizedBox.shrink(); } }), ], ); }, ), ); } }