155 lines
4.8 KiB
Dart
155 lines
4.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import 'package:f0ckapp/providers/media_provider.dart';
|
|
import 'package:f0ckapp/utils/customsearchdelegate_util.dart';
|
|
import 'package:f0ckapp/widgets/media_tile.dart';
|
|
import 'package:f0ckapp/widgets/filter_bar.dart';
|
|
import 'package:f0ckapp/widgets/end_drawer.dart';
|
|
|
|
class MediaGrid extends ConsumerStatefulWidget {
|
|
const MediaGrid({super.key});
|
|
|
|
@override
|
|
ConsumerState<MediaGrid> createState() => _MediaGridState();
|
|
}
|
|
|
|
class _MediaGridState extends ConsumerState<MediaGrid> {
|
|
final ScrollController _scrollController = ScrollController();
|
|
|
|
@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();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final MediaState mediaState = ref.watch(mediaProvider);
|
|
final MediaNotifier mediaNotifier = ref.read(mediaProvider.notifier);
|
|
|
|
return Scaffold(
|
|
body: RefreshIndicator(
|
|
onRefresh: () async {
|
|
mediaNotifier.setTag(null);
|
|
_scrollController.jumpTo(0);
|
|
await mediaNotifier.loadMedia();
|
|
},
|
|
child: CustomScrollView(
|
|
controller: _scrollController,
|
|
slivers: [
|
|
SliverAppBar(
|
|
floating: true,
|
|
snap: true,
|
|
title: GestureDetector(
|
|
onTap: () {
|
|
mediaNotifier.setTag(null);
|
|
_scrollController.jumpTo(0);
|
|
},
|
|
child: Row(
|
|
children: [
|
|
Image.asset(
|
|
'assets/images/f0ck_small.webp',
|
|
fit: BoxFit.fitHeight,
|
|
),
|
|
const SizedBox(width: 10),
|
|
const Text('fApp', style: TextStyle(fontSize: 24)),
|
|
],
|
|
),
|
|
),
|
|
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);
|
|
},
|
|
),
|
|
Builder(
|
|
builder: (context) {
|
|
return IconButton(
|
|
icon: const Icon(Icons.menu),
|
|
onPressed: () {
|
|
Scaffold.of(context).openEndDrawer();
|
|
},
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
SliverPadding(
|
|
padding: const EdgeInsets.all(5.0),
|
|
sliver: SliverGrid(
|
|
delegate: SliverChildBuilderDelegate(
|
|
(context, index) {
|
|
if (index >= mediaState.mediaItems.length) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
return MediaTile(item: mediaState.mediaItems[index]);
|
|
},
|
|
childCount:
|
|
mediaState.mediaItems.length +
|
|
(mediaState.isLoading ? 1 : 0),
|
|
),
|
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
|
maxCrossAxisExtent: 150,
|
|
crossAxisSpacing: 5,
|
|
mainAxisSpacing: 5,
|
|
childAspectRatio: 1,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
bottomNavigationBar: FilterBar(
|
|
mediaNotifier: mediaNotifier,
|
|
mediaState: mediaState,
|
|
scrollController: _scrollController,
|
|
),
|
|
endDrawer: EndDrawer(ref: ref),
|
|
persistentFooterButtons: mediaState.tag != null
|
|
? [
|
|
Center(
|
|
child: InputChip(
|
|
label: Text(mediaState.tag!),
|
|
onDeleted: () {
|
|
mediaNotifier.setTag(null);
|
|
_scrollController.jumpTo(0);
|
|
},
|
|
),
|
|
),
|
|
]
|
|
: null,
|
|
);
|
|
}
|
|
}
|