Add feed filter options
This commit is contained in:
parent
9801b20a61
commit
27915caf5f
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:feet/widgets/centered_page_hint.dart';
|
import 'package:feet/widgets/centered_page_hint.dart';
|
||||||
|
import 'package:feet/widgets/filter_menu.dart';
|
||||||
import 'package:feet/widgets/homepage_post.dart';
|
import 'package:feet/widgets/homepage_post.dart';
|
||||||
import 'package:feet/widgets/login_prompt.dart';
|
import 'package:feet/widgets/login_prompt.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -83,9 +84,15 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
var _fetched = false;
|
var _fetched = false;
|
||||||
var _fetchedCount = 0;
|
var _fetchedCount = 0;
|
||||||
var _knownPostsSize = -1;
|
var _knownPostsSize = -1;
|
||||||
|
List<int> _feedFilter = [];
|
||||||
|
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
widget.api.cache.clear();
|
widget.api.cache.clear();
|
||||||
|
setState(() {
|
||||||
|
_fetchedCount = 0;
|
||||||
|
_knownPostsSize = -1;
|
||||||
|
_feedFilter = [];
|
||||||
|
});
|
||||||
|
|
||||||
print("Starting refresh");
|
print("Starting refresh");
|
||||||
|
|
||||||
|
@ -97,10 +104,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
.sinceId(0)
|
.sinceId(0)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
while (
|
while ((data['items'] as List<dynamic>).isNotEmpty &&
|
||||||
(data['items'] as List<dynamic>).isNotEmpty &&
|
_fetchedCount < FETCH_MAX_POSTS) {
|
||||||
_fetchedCount < FETCH_MAX_POSTS
|
|
||||||
) {
|
|
||||||
print("Fetching more items");
|
print("Fetching more items");
|
||||||
|
|
||||||
var ids = widget.api.cache.items
|
var ids = widget.api.cache.items
|
||||||
|
@ -134,7 +139,10 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var loggedIn = widget.api.loggedIn();
|
var loggedIn = widget.api.loggedIn();
|
||||||
var posts = widget.api.cache.items.getAll().values;
|
var posts = widget.api.cache.items.getAll().values.where(
|
||||||
|
(element) => _feedFilter.isEmpty || _feedFilter.contains(element.feedId)
|
||||||
|
);
|
||||||
|
|
||||||
var savedPosts = posts.where((element) => element.isSaved);
|
var savedPosts = posts.where((element) => element.isSaved);
|
||||||
var unreadPosts = posts.where((element) => !element.isRead);
|
var unreadPosts = posts.where((element) => !element.isRead);
|
||||||
|
|
||||||
|
@ -173,7 +181,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
text: "Nothing here yet. Try saving some posts!"),
|
text: "Nothing here yet. Try saving some posts!"),
|
||||||
];
|
];
|
||||||
|
|
||||||
// I'm aware that this is stupid, but I'm sick and tired and really don't care as long as it works
|
// I'm aware that this is stupid, but I'm sick and tired and
|
||||||
|
// really don't care as long as it works
|
||||||
if (!loggedIn) {
|
if (!loggedIn) {
|
||||||
Timer.periodic(const Duration(seconds: 1), (timer) {
|
Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -248,7 +257,33 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: "filter",
|
||||||
|
child: Text(
|
||||||
|
_feedFilter.isEmpty
|
||||||
|
? "Filter..."
|
||||||
|
: "Filter (${_feedFilter.length}/${widget.api.cache.feeds.size})"
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Future.delayed(
|
||||||
|
Duration.zero,
|
||||||
|
() => showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => FilterMenu(
|
||||||
|
api: widget.api,
|
||||||
|
initData: _feedFilter,
|
||||||
|
onConfirm: (items) {
|
||||||
|
setState(() {
|
||||||
|
_feedFilter = items;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
97
lib/widgets/filter_menu.dart
Normal file
97
lib/widgets/filter_menu.dart
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import 'package:feet/api/api.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FilterMenu extends StatefulWidget {
|
||||||
|
final FeverAPI api;
|
||||||
|
final List<int> initData;
|
||||||
|
final void Function(List<int> items) onConfirm;
|
||||||
|
const FilterMenu({
|
||||||
|
super.key,
|
||||||
|
required this.api,
|
||||||
|
required this.initData,
|
||||||
|
required this.onConfirm,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<FilterMenu> createState() => _FilterMenuState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FilterMenuState extends State<FilterMenu> {
|
||||||
|
final Map<int, bool> _checked = {};
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
for (var feed in widget.api.cache.feeds.getAll().values) {
|
||||||
|
_checked[feed.id] = widget.initData.contains(feed.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
int selected = _checked.values.where((e) => e == true).length;
|
||||||
|
|
||||||
|
return SimpleDialog(
|
||||||
|
title: const Text("Filter"),
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 4.0),
|
||||||
|
child: Text(
|
||||||
|
selected == 0
|
||||||
|
? "All feeds will be shown"
|
||||||
|
: "$selected out of ${_checked.length} feeds will be shown",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 300,
|
||||||
|
height: 280,
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ListView(
|
||||||
|
children: widget.api.cache.feeds
|
||||||
|
.getAll()
|
||||||
|
.values
|
||||||
|
.map((feed) => Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: _checked[feed.id] ?? false,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_checked[feed.id] = value ?? true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text(feed.title),
|
||||||
|
],
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
List<int> items = _checked.keys
|
||||||
|
.where((element) => _checked[element]!)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
widget.onConfirm(items);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: const Text("Done"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_checked.forEach((key, value) {
|
||||||
|
_checked[key] = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: const Text("Reset")),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue