Add all/sub/block etc. filters to mags/users/domains list

This commit is contained in:
John Wesley 2024-01-11 12:14:50 -05:00
parent 89b35d7852
commit df850e65e0
6 changed files with 216 additions and 70 deletions

View File

@ -4,14 +4,20 @@ import 'package:http/http.dart' as http;
import 'package:interstellar/src/models/domain.dart';
import 'package:interstellar/src/utils/utils.dart';
enum DomainsFilter { all, subscribed, blocked }
Future<DomainListModel> fetchDomains(
http.Client client,
String instanceHost, {
int? page,
DomainsFilter? filter,
String? search,
}) async {
final response = await client.get(Uri.https(
instanceHost, '/api/domains', {'p': page?.toString(), 'q': search}));
final response = (filter == null || filter == DomainsFilter.all)
? await client.get(Uri.https(
instanceHost, '/api/domains', {'p': page?.toString(), 'q': search}))
: await client.get(Uri.https(instanceHost, '/api/domains/${filter.name}',
{'p': page?.toString()}));
httpErrorHandler(response, message: 'Failed to load domains');

View File

@ -4,17 +4,23 @@ import 'package:http/http.dart' as http;
import 'package:interstellar/src/models/magazine.dart';
import 'package:interstellar/src/utils/utils.dart';
enum MagazinesFilter { all, subscribed, moderated, blocked }
enum MagazinesSort { active, hot, newest }
Future<MagazineListModel> fetchMagazines(
http.Client client,
String instanceHost, {
int? page,
MagazinesFilter? filter,
MagazinesSort? sort,
String? search,
}) async {
final response = await client.get(Uri.https(instanceHost, '/api/magazines',
{'p': page?.toString(), 'sort': sort?.name, 'q': search}));
final response = (filter == null || filter == MagazinesFilter.all)
? await client.get(Uri.https(instanceHost, '/api/magazines',
{'p': page?.toString(), 'sort': sort?.name, 'q': search}))
: await client.get(Uri.https(instanceHost,
'/api/magazines/${filter.name}', {'p': page?.toString()}));
httpErrorHandler(response, message: 'Failed to load magazines');

View File

@ -4,14 +4,20 @@ import 'package:http/http.dart' as http;
import 'package:interstellar/src/models/user.dart';
import 'package:interstellar/src/utils/utils.dart';
enum UsersFilter { all, followed, followers, blocked }
Future<UserListModel> fetchUsers(
http.Client client,
String instanceHost, {
int? page,
UsersFilter? filter,
}) async {
final response = await client.get(Uri.https(instanceHost, '/api/users', {
'p': page?.toString(),
}));
final response = (filter == null || filter == UsersFilter.all)
? await client.get(Uri.https(instanceHost, '/api/users', {
'p': page?.toString(),
}))
: await client.get(Uri.https(
instanceHost, '/api/users/${filter.name}', {'p': page?.toString()}));
httpErrorHandler(response, message: 'Failed to load users');

View File

@ -17,6 +17,7 @@ class DomainsScreen extends StatefulWidget {
}
class _DomainsScreenState extends State<DomainsScreen> {
api_domains.DomainsFilter filter = api_domains.DomainsFilter.all;
String search = "";
final PagingController<int, DomainModel> _pagingController =
@ -34,10 +35,12 @@ class _DomainsScreenState extends State<DomainsScreen> {
Future<void> _fetchPage(int pageKey) async {
try {
final newPage = await api_domains.fetchDomains(
context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost,
page: pageKey,
search: search.isEmpty ? null : search);
context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost,
page: pageKey,
filter: filter,
search: search.isEmpty ? null : search,
);
final isLastPage =
newPage.pagination.currentPage == newPage.pagination.maxPage;
@ -66,20 +69,53 @@ class _DomainsScreenState extends State<DomainsScreen> {
padding: const EdgeInsets.all(12),
child: Row(
children: [
SizedBox(
width: 128,
child: TextFormField(
initialValue: search,
onChanged: (newSearch) {
setState(() {
search = newSearch;
_pagingController.refresh();
});
},
decoration: const InputDecoration(
border: OutlineInputBorder(), label: Text('Search')),
),
)
...whenLoggedIn(context, [
Padding(
padding: const EdgeInsets.only(right: 12),
child: DropdownButton<api_domains.DomainsFilter>(
value: filter,
onChanged: (newFilter) {
if (newFilter != null) {
setState(() {
filter = newFilter;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_domains.DomainsFilter.all,
child: Text('All'),
),
DropdownMenuItem(
value: api_domains.DomainsFilter.subscribed,
child: Text('Subscribed'),
),
DropdownMenuItem(
value: api_domains.DomainsFilter.blocked,
child: Text('Blocked'),
),
],
),
)
]) ??
[],
if (filter != api_domains.DomainsFilter.all)
SizedBox(
width: 128,
child: TextFormField(
initialValue: search,
onChanged: (newSearch) {
setState(() {
search = newSearch;
_pagingController.refresh();
});
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
label: Text('Search')),
),
)
],
),
),

View File

@ -18,6 +18,7 @@ class MagazinesScreen extends StatefulWidget {
}
class _MagazinesScreenState extends State<MagazinesScreen> {
api_magazines.MagazinesFilter filter = api_magazines.MagazinesFilter.all;
api_magazines.MagazinesSort sort = api_magazines.MagazinesSort.hot;
String search = "";
@ -36,11 +37,13 @@ class _MagazinesScreenState extends State<MagazinesScreen> {
Future<void> _fetchPage(int pageKey) async {
try {
final newPage = await api_magazines.fetchMagazines(
context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost,
page: pageKey,
sort: sort,
search: search.isEmpty ? null : search);
context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost,
page: pageKey,
filter: filter,
sort: sort,
search: search.isEmpty ? null : search,
);
final isLastPage =
newPage.pagination.currentPage == newPage.pagination.maxPage;
@ -69,46 +72,88 @@ class _MagazinesScreenState extends State<MagazinesScreen> {
padding: const EdgeInsets.all(12),
child: Row(
children: [
DropdownButton<api_magazines.MagazinesSort>(
value: sort,
onChanged: (newSort) {
if (newSort != null) {
setState(() {
sort = newSort;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_magazines.MagazinesSort.hot,
child: Text('Hot'),
),
DropdownMenuItem(
value: api_magazines.MagazinesSort.active,
child: Text('Active'),
),
DropdownMenuItem(
value: api_magazines.MagazinesSort.newest,
child: Text('Newest'),
),
],
),
const SizedBox(width: 12),
SizedBox(
width: 128,
child: TextFormField(
initialValue: search,
onChanged: (newSearch) {
setState(() {
search = newSearch;
_pagingController.refresh();
});
},
decoration: const InputDecoration(
border: OutlineInputBorder(), label: Text('Search')),
),
)
...whenLoggedIn(context, [
Padding(
padding: const EdgeInsets.only(right: 12),
child: DropdownButton<api_magazines.MagazinesFilter>(
value: filter,
onChanged: (newFilter) {
if (newFilter != null) {
setState(() {
filter = newFilter;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_magazines.MagazinesFilter.all,
child: Text('All'),
),
DropdownMenuItem(
value: api_magazines.MagazinesFilter.subscribed,
child: Text('Subscribed'),
),
DropdownMenuItem(
value: api_magazines.MagazinesFilter.moderated,
child: Text('Moderated'),
),
DropdownMenuItem(
value: api_magazines.MagazinesFilter.blocked,
child: Text('Blocked'),
),
],
),
)
]) ??
[],
...(filter == api_magazines.MagazinesFilter.all
? [
Padding(
padding: const EdgeInsets.only(right: 12),
child: DropdownButton<api_magazines.MagazinesSort>(
value: sort,
onChanged: (newSort) {
if (newSort != null) {
setState(() {
sort = newSort;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_magazines.MagazinesSort.hot,
child: Text('Hot'),
),
DropdownMenuItem(
value: api_magazines.MagazinesSort.active,
child: Text('Active'),
),
DropdownMenuItem(
value: api_magazines.MagazinesSort.newest,
child: Text('Newest'),
),
],
),
),
SizedBox(
width: 128,
child: TextFormField(
initialValue: search,
onChanged: (newSearch) {
setState(() {
search = newSearch;
_pagingController.refresh();
});
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
label: Text('Search')),
),
),
]
: []),
],
),
),

View File

@ -18,6 +18,8 @@ class UsersScreen extends StatefulWidget {
}
class _UsersScreenState extends State<UsersScreen> {
api_users.UsersFilter filter = api_users.UsersFilter.all;
final PagingController<int, DetailedUserModel> _pagingController =
PagingController(firstPageKey: 1);
@ -36,6 +38,7 @@ class _UsersScreenState extends State<UsersScreen> {
context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost,
page: pageKey,
filter: filter,
);
final isLastPage =
@ -60,6 +63,50 @@ class _UsersScreenState extends State<UsersScreen> {
),
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
...whenLoggedIn(context, [
Padding(
padding: const EdgeInsets.only(right: 12),
child: DropdownButton<api_users.UsersFilter>(
value: filter,
onChanged: (newFilter) {
if (newFilter != null) {
setState(() {
filter = newFilter;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_users.UsersFilter.all,
child: Text('All'),
),
DropdownMenuItem(
value: api_users.UsersFilter.followed,
child: Text('Followed'),
),
DropdownMenuItem(
value: api_users.UsersFilter.followers,
child: Text('Followers'),
),
DropdownMenuItem(
value: api_users.UsersFilter.blocked,
child: Text('Blocked'),
),
],
),
)
]) ??
[],
],
),
),
),
PagedSliverList<int, DetailedUserModel>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<DetailedUserModel>(