import 'package:flutter/material.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:f0ckapp/models/mediaitem_model.dart'; import 'package:f0ckapp/providers/media_provider.dart'; import 'package:f0ckapp/utils/appversion_util.dart'; import 'package:f0ckapp/providers/theme_provider.dart'; import 'package:f0ckapp/utils/customsearchdelegate_util.dart'; class MediaGrid extends ConsumerStatefulWidget { const MediaGrid({super.key}); @override ConsumerState createState() => _MediaGridState(); } class _MediaGridState extends ConsumerState { final ScrollController _scrollController = ScrollController(); final GlobalKey _scaffoldKey = GlobalKey(); final TextEditingController _usernameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); int _calculateCrossAxisCount(BuildContext context, int defaultCount) { return defaultCount == 0 ? (MediaQuery.of(context).size.width / 110).clamp(3, 5).toInt() : defaultCount; } @override void initState() { super.initState(); Future.microtask(() { ref.read(mediaProvider.notifier).loadMedia(); }); _scrollController.addListener(() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 200) { ref.read(mediaProvider.notifier).loadMedia(); } }); } @override void dispose() { _scrollController.dispose(); _usernameController.dispose(); _passwordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final MediaState mediaState = ref.watch(mediaProvider); final MediaNotifier mediaNotifier = ref.read(mediaProvider.notifier); return Scaffold( key: _scaffoldKey, appBar: AppBar( title: GestureDetector( child: Row( spacing: 10, children: [ Image.asset( 'assets/images/f0ck_small.webp', fit: BoxFit.fitHeight, ), Text('fApp', style: TextStyle(fontSize: 24)), ], ), onTap: () { mediaNotifier.setTag(null); _scrollController.jumpTo(0); }, ), actions: [ IconButton( icon: const Icon(Icons.search), onPressed: () async { await showSearch( context: context, delegate: CustomSearchDelegate(), ); }, ), IconButton( icon: Icon( mediaState.random ? Icons.shuffle_on_outlined : Icons.shuffle, ), onPressed: () { mediaNotifier.toggleRandom(); _scrollController.jumpTo(0); }, ), IconButton( icon: const Icon(Icons.menu), onPressed: () { _scaffoldKey.currentState?.openEndDrawer(); }, ), ], ), bottomNavigationBar: BottomAppBar( height: 50, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ const Text('type: '), DropdownButton( value: mediaTypes[mediaState.typeIndex], isDense: true, items: mediaTypes.map((String value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), onChanged: (String? newValue) { if (newValue != null) { mediaNotifier.setType(newValue); _scrollController.jumpTo(0); } }, ), const Text('mode: '), DropdownButton( value: mediaModes[mediaState.modeIndex], isDense: true, items: mediaModes.map((String value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), onChanged: (String? newValue) { if (newValue != null) { mediaNotifier.setMode(mediaModes.indexOf(newValue)); _scrollController.jumpTo(0); } }, ), ], ), ), endDrawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: [ DrawerHeader( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/menu.webp'), fit: BoxFit.cover, alignment: Alignment.topCenter, ), ), child: null, ), /*ExpansionTile( title: const Text('Login'), children: [ Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( readOnly: true, controller: _usernameController, decoration: const InputDecoration( labelText: 'Benutzername', ), ), const SizedBox(height: 10), TextField( readOnly: true, controller: _passwordController, obscureText: true, decoration: const InputDecoration( labelText: 'Passwort', ), ), const SizedBox(height: 20), ElevatedButton( onPressed: () async { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("noch nicht implementiert lol"), ), final success = await login( _usernameController.text, _passwordController.text, ); if (success) { Navigator.pop(context); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Login fehlgeschlagen!")), ); } ); }, child: const Text('Login'), ), ], ), ), ], ),*/ ExpansionTile( title: const Text('Theme'), children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( children: themeMap.entries.map((entry) { final String themeName = entry.key; final ThemeData themeData = entry.value; final ThemeData currentTheme = ref.watch(themeNotifierProvider); final bool isSelected = currentTheme == themeData; return ListTile( title: Text(themeName), selected: isSelected, selectedTileColor: Colors.blue.withValues(alpha: 0.2), onTap: () async { await ref .read(themeNotifierProvider.notifier) .updateTheme(themeName); }, ); }).toList(), ), ), ], ), ListTile( title: Text('v${AppVersion.version}'), onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('jooong lass das, hier ist nichts'), ), ); }, ), ], ), ), persistentFooterButtons: mediaState.tag != null ? [ Center( child: InputChip( label: Text(mediaState.tag!), onDeleted: () { mediaNotifier.setTag(null); _scrollController.jumpTo(0); }, ), ), ] : null, body: RefreshIndicator( onRefresh: () async { mediaNotifier.resetMedia(); _scrollController.jumpTo(0); }, child: GridView.builder( key: const PageStorageKey('mediaGrid'), controller: _scrollController, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _calculateCrossAxisCount( context, mediaState.crossAxisCount, ), crossAxisSpacing: 5.0, mainAxisSpacing: 5.0, ), itemCount: mediaState.mediaItems.length + (mediaState.isLoading ? 1 : 0), itemBuilder: (BuildContext context, int index) { if (index >= mediaState.mediaItems.length) { return const Center(child: CircularProgressIndicator()); } final MediaItem item = mediaState.mediaItems[index]; return InkWell( onTap: () async { context.push('/${item.id}', extra: true); }, child: Stack( fit: StackFit.expand, children: [ CachedNetworkImage( imageUrl: item.thumbnailUrl, fit: BoxFit.cover, placeholder: (context, url) => const SizedBox.shrink(), errorWidget: (context, url, error) => const Icon(Icons.error), ), Align( alignment: Alignment.bottomRight, child: Icon( Icons.square, color: switch (item.mode) { 1 => Colors.green, 2 => Colors.red, _ => Colors.yellow, }, size: 15.0, ), ), ], ), ); }, ), ), ); } }