From df850e65e0cb9d6f607fc912e277d5c7a1326e3a Mon Sep 17 00:00:00 2001 From: John Wesley Date: Thu, 11 Jan 2024 12:14:50 -0500 Subject: [PATCH] Add all/sub/block etc. filters to mags/users/domains list --- lib/src/api/domains.dart | 10 +- lib/src/api/magazines.dart | 10 +- lib/src/api/users.dart | 12 +- lib/src/screens/explore/domains_screen.dart | 72 +++++++--- lib/src/screens/explore/magazines_screen.dart | 135 ++++++++++++------ lib/src/screens/explore/users_screen.dart | 47 ++++++ 6 files changed, 216 insertions(+), 70 deletions(-) diff --git a/lib/src/api/domains.dart b/lib/src/api/domains.dart index 3f3ab3f..2c51661 100644 --- a/lib/src/api/domains.dart +++ b/lib/src/api/domains.dart @@ -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 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'); diff --git a/lib/src/api/magazines.dart b/lib/src/api/magazines.dart index ce16bb0..a160c1b 100644 --- a/lib/src/api/magazines.dart +++ b/lib/src/api/magazines.dart @@ -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 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'); diff --git a/lib/src/api/users.dart b/lib/src/api/users.dart index ac0bc7a..94aff14 100644 --- a/lib/src/api/users.dart +++ b/lib/src/api/users.dart @@ -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 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'); diff --git a/lib/src/screens/explore/domains_screen.dart b/lib/src/screens/explore/domains_screen.dart index 3d9f26a..283ad75 100644 --- a/lib/src/screens/explore/domains_screen.dart +++ b/lib/src/screens/explore/domains_screen.dart @@ -17,6 +17,7 @@ class DomainsScreen extends StatefulWidget { } class _DomainsScreenState extends State { + api_domains.DomainsFilter filter = api_domains.DomainsFilter.all; String search = ""; final PagingController _pagingController = @@ -34,10 +35,12 @@ class _DomainsScreenState extends State { Future _fetchPage(int pageKey) async { try { final newPage = await api_domains.fetchDomains( - context.read().httpClient, - context.read().instanceHost, - page: pageKey, - search: search.isEmpty ? null : search); + context.read().httpClient, + context.read().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 { 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( + 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')), + ), + ) ], ), ), diff --git a/lib/src/screens/explore/magazines_screen.dart b/lib/src/screens/explore/magazines_screen.dart index 2e3142c..fabd179 100644 --- a/lib/src/screens/explore/magazines_screen.dart +++ b/lib/src/screens/explore/magazines_screen.dart @@ -18,6 +18,7 @@ class MagazinesScreen extends StatefulWidget { } class _MagazinesScreenState extends State { + 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 { Future _fetchPage(int pageKey) async { try { final newPage = await api_magazines.fetchMagazines( - context.read().httpClient, - context.read().instanceHost, - page: pageKey, - sort: sort, - search: search.isEmpty ? null : search); + context.read().httpClient, + context.read().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 { padding: const EdgeInsets.all(12), child: Row( children: [ - DropdownButton( - 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( + 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( + 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')), + ), + ), + ] + : []), ], ), ), diff --git a/lib/src/screens/explore/users_screen.dart b/lib/src/screens/explore/users_screen.dart index 7015089..9dfd2f5 100644 --- a/lib/src/screens/explore/users_screen.dart +++ b/lib/src/screens/explore/users_screen.dart @@ -18,6 +18,8 @@ class UsersScreen extends StatefulWidget { } class _UsersScreenState extends State { + api_users.UsersFilter filter = api_users.UsersFilter.all; + final PagingController _pagingController = PagingController(firstPageKey: 1); @@ -36,6 +38,7 @@ class _UsersScreenState extends State { context.read().httpClient, context.read().instanceHost, page: pageKey, + filter: filter, ); final isLastPage = @@ -60,6 +63,50 @@ class _UsersScreenState extends State { ), 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( + 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( pagingController: _pagingController, builderDelegate: PagedChildBuilderDelegate(