215 lines
6.9 KiB
Dart
215 lines
6.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:f0ckapp/screens/DetailView.dart';
|
|
import 'package:f0ckapp/providers/MediaProvider.dart';
|
|
import 'package:f0ckapp/utils/AppVersion.dart';
|
|
|
|
class MediaGrid extends StatefulWidget {
|
|
const MediaGrid({super.key});
|
|
|
|
@override
|
|
State createState() => _MediaGridState();
|
|
}
|
|
|
|
class _MediaGridState extends State<MediaGrid> {
|
|
final ScrollController _scrollController = ScrollController();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
final provider = Provider.of<MediaProvider>(context, listen: false);
|
|
|
|
Future.microtask(() {
|
|
provider.loadMedia();
|
|
});
|
|
|
|
_scrollController.addListener(() {
|
|
if (_scrollController.position.pixels >=
|
|
_scrollController.position.maxScrollExtent - 200) {
|
|
provider.loadMedia(notify: false);
|
|
}
|
|
});
|
|
}
|
|
|
|
void scrollToTop() {
|
|
_scrollController.jumpTo(0);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final provider = Provider.of<MediaProvider>(context);
|
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
|
|
|
return Scaffold(
|
|
key: scaffoldKey,
|
|
appBar: AppBar(
|
|
//centerTitle: true,
|
|
title: Text('fApp v${AppVersion.version}'),
|
|
actions: [
|
|
IconButton(
|
|
icon: Icon(
|
|
provider.random ? Icons.shuffle_on_outlined : Icons.shuffle,
|
|
),
|
|
onPressed: () {
|
|
provider.toggleRandom();
|
|
_scrollController.jumpTo(0);
|
|
},
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.menu),
|
|
onPressed: () {
|
|
scaffoldKey.currentState?.openEndDrawer();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
bottomNavigationBar: BottomAppBar(
|
|
height: 50,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: [
|
|
Text('type: '),
|
|
DropdownButton<String>(
|
|
// type
|
|
value: provider.type,
|
|
isDense: true,
|
|
//icon: SizedBox.shrink(),
|
|
items: provider.types.map((String value) {
|
|
return DropdownMenuItem<String>(
|
|
value: value,
|
|
child: Text(value, style: TextStyle(color: Colors.white)),
|
|
);
|
|
}).toList(),
|
|
onChanged: (String? newValue) {
|
|
if (newValue != null) {
|
|
provider.setType(newValue);
|
|
_scrollController.jumpTo(0);
|
|
}
|
|
},
|
|
),
|
|
Text('mode: '),
|
|
DropdownButton<String>(
|
|
// mode
|
|
value: provider.modes[provider.mode],
|
|
isDense: true,
|
|
//icon: SizedBox.shrink(),
|
|
items: provider.modes.map((String value) {
|
|
return DropdownMenuItem<String>(
|
|
value: value,
|
|
child: Text(value),
|
|
);
|
|
}).toList(),
|
|
onChanged: (String? newValue) {
|
|
if (newValue != null) {
|
|
provider.setMode(provider.modes.indexOf(newValue));
|
|
_scrollController.jumpTo(0);
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
endDrawer: Drawer(
|
|
child: ListView(
|
|
padding: EdgeInsets.zero,
|
|
children: [
|
|
DrawerHeader(
|
|
padding: EdgeInsets.all(0),
|
|
child: Image.asset('assets/images/menu.webp', fit: BoxFit.cover),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
persistentFooterButtons: provider.tag != null
|
|
? [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text('tag: '),
|
|
InputChip(
|
|
label: Text(provider.tag!),
|
|
backgroundColor: const Color(0xFF090909),
|
|
labelStyle: const TextStyle(color: Colors.white),
|
|
onDeleted: () {
|
|
provider.setTag(null);
|
|
_scrollController.jumpTo(0);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
]
|
|
: null,
|
|
body: RefreshIndicator(
|
|
onRefresh: () async {
|
|
await provider.resetMedia();
|
|
_scrollController.jumpTo(0);
|
|
},
|
|
child: Consumer<MediaProvider>(
|
|
builder: (context, mediaProvider, child) {
|
|
return GridView.builder(
|
|
key: PageStorageKey('mediaGrid'),
|
|
controller: _scrollController,
|
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
|
crossAxisCount: mediaProvider.crossAxisCount == 0
|
|
? (MediaQuery.of(context).size.width / 110)
|
|
.clamp(3, 5)
|
|
.toInt()
|
|
: mediaProvider.crossAxisCount,
|
|
crossAxisSpacing: 5.0,
|
|
mainAxisSpacing: 5.0,
|
|
),
|
|
itemCount:
|
|
provider.mediaItems.length + (provider.isLoading ? 1 : 0),
|
|
itemBuilder: (context, index) {
|
|
if (index >= provider.mediaItems.length) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
final item = provider.mediaItems[index];
|
|
|
|
return InkWell(
|
|
onTap: () async {
|
|
bool test = await Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => DetailView(initialItemId: item.id),
|
|
),
|
|
);
|
|
if (test) {
|
|
scrollToTop();
|
|
}
|
|
},
|
|
child: Stack(
|
|
fit: StackFit.expand,
|
|
children: <Widget>[
|
|
CachedNetworkImage(
|
|
imageUrl: item.thumbnailUrl,
|
|
fit: BoxFit.cover,
|
|
placeholder: (context, url) => SizedBox.shrink(),
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
),
|
|
Align(
|
|
alignment: FractionalOffset.bottomRight,
|
|
child: Icon(
|
|
Icons.square,
|
|
color: switch (item.mode) {
|
|
1 => Colors.green,
|
|
2 => Colors.red,
|
|
_ => Colors.yellow,
|
|
},
|
|
size: 15.0,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|