Add filter to subscription-list
This commit is contained in:
@@ -54,6 +54,20 @@ class MessageFilter {
|
||||
});
|
||||
}
|
||||
|
||||
class SubscriptionFilter {
|
||||
static final SubscriptionFilter ALL = SubscriptionFilter('both', 'all', 'all');
|
||||
static final SubscriptionFilter OWNED_INACTIVE = SubscriptionFilter('outgoing', 'unconfirmed', 'false');
|
||||
static final SubscriptionFilter OWNED_ACTIVE = SubscriptionFilter('outgoing', 'confirmed', 'false');
|
||||
static final SubscriptionFilter EXTERNAL_ALL = SubscriptionFilter('outgoing', 'all', 'true');
|
||||
static final SubscriptionFilter INCOMING_ALL = SubscriptionFilter('incoming', 'all', 'true');
|
||||
|
||||
final String direction; // 'outgoing' | 'incoming' | 'both'
|
||||
final String confirmation; // 'confirmed' | 'unconfirmed' | 'all'
|
||||
final String external; // 'true' | 'false' | 'all'
|
||||
|
||||
SubscriptionFilter(this.direction, this.confirmation, this.external) {}
|
||||
}
|
||||
|
||||
class APIClient {
|
||||
static const String _base = 'https://simplecloudnotifier.de';
|
||||
static const String _prefix = '/api/v2';
|
||||
@@ -345,15 +359,15 @@ class APIClient {
|
||||
);
|
||||
}
|
||||
|
||||
static Future<List<Subscription>> getSubscriptionList(TokenSource auth) async {
|
||||
static Future<List<Subscription>> getSubscriptionList(TokenSource auth, SubscriptionFilter filter) async {
|
||||
return await _request(
|
||||
name: 'getSubscriptionList',
|
||||
method: 'GET',
|
||||
relURL: 'users/${auth.getUserID()}/subscriptions',
|
||||
query: {
|
||||
'direction': ['both'],
|
||||
'confirmation': ['all'],
|
||||
'external': ['all'],
|
||||
'direction': [filter.direction],
|
||||
'confirmation': [filter.confirmation],
|
||||
'external': [filter.external],
|
||||
},
|
||||
fn: (json) => Subscription.fromJsonArray(json['subscriptions'] as List<dynamic>),
|
||||
authToken: auth.getToken(),
|
||||
|
||||
47
flutter/lib/components/filter_chips/filter_chips.dart
Normal file
47
flutter/lib/components/filter_chips/filter_chips.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FilterChips<T extends Enum> extends StatelessWidget {
|
||||
final List<(T, String)> options;
|
||||
final T value;
|
||||
final void Function(T)? onChanged;
|
||||
|
||||
const FilterChips({
|
||||
Key? key,
|
||||
required this.options,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (var opt in options) _buildChiplet(context, opt.$1, opt.$2),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildChiplet(BuildContext context, T optValue, String optText) {
|
||||
final isSelected = optValue == value;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 2, 4, 2),
|
||||
child: InputChip(
|
||||
label: Text(
|
||||
optText,
|
||||
style: isSelected ? TextStyle(color: Theme.of(context).colorScheme.onPrimary) : null,
|
||||
),
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
isEnabled: true,
|
||||
selected: true,
|
||||
showCheckmark: false,
|
||||
onPressed: () {
|
||||
if (!isSelected) onChanged?.call(optValue);
|
||||
},
|
||||
selectedColor: isSelected ? Theme.of(context).colorScheme.primary : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
|
||||
_futureSubscriptionCount = ImmediateFuture.ofFuture(() async {
|
||||
if (!userAcc.isAuth()) throw new Exception('not logged in');
|
||||
final subs = await APIClient.getSubscriptionList(userAcc);
|
||||
final subs = await APIClient.getSubscriptionList(userAcc, SubscriptionFilter.ALL);
|
||||
return subs.length;
|
||||
}());
|
||||
|
||||
@@ -153,7 +153,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
// refresh all data and then replace teh futures used in build()
|
||||
|
||||
final channelsAll = await APIClient.getChannelList(userAcc, ChannelSelector.all);
|
||||
final subs = await APIClient.getSubscriptionList(userAcc);
|
||||
final subs = await APIClient.getSubscriptionList(userAcc, SubscriptionFilter.ALL);
|
||||
final clients = await APIClient.getClientList(userAcc);
|
||||
final keys = await APIClient.getKeyTokenList(userAcc);
|
||||
final senderNames = await APIClient.getSenderNameList(userAcc);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/filter_chips/filter_chips.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/subscription.dart';
|
||||
@@ -13,6 +14,29 @@ import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/subscription_list/subscription_list_item.dart';
|
||||
import 'package:simplecloudnotifier/state/scn_data_cache.dart';
|
||||
|
||||
enum SubscriptionListFilter {
|
||||
ALL,
|
||||
INACTIVE,
|
||||
OWN,
|
||||
EXTERNAL,
|
||||
INCOMING;
|
||||
|
||||
SubscriptionFilter toAPIFilter() {
|
||||
switch (this) {
|
||||
case ALL:
|
||||
return SubscriptionFilter.ALL;
|
||||
case INACTIVE:
|
||||
return SubscriptionFilter.OWNED_INACTIVE;
|
||||
case OWN:
|
||||
return SubscriptionFilter.OWNED_ACTIVE;
|
||||
case EXTERNAL:
|
||||
return SubscriptionFilter.EXTERNAL_ALL;
|
||||
case INCOMING:
|
||||
return SubscriptionFilter.INCOMING_ALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriptionListPage extends StatefulWidget {
|
||||
const SubscriptionListPage({super.key});
|
||||
|
||||
@@ -26,6 +50,8 @@ class _SubscriptionListPageState extends State<SubscriptionListPage> {
|
||||
final userCache = Map<String, UserPreview>();
|
||||
final channelCache = Map<String, ChannelPreview>();
|
||||
|
||||
SubscriptionListFilter filter = SubscriptionListFilter.ALL;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -60,7 +86,7 @@ class _SubscriptionListPageState extends State<SubscriptionListPage> {
|
||||
}
|
||||
|
||||
try {
|
||||
final items = (await APIClient.getSubscriptionList(acc)).toList();
|
||||
final items = (await APIClient.getSubscriptionList(acc, filter.toAPIFilter())).toList();
|
||||
|
||||
items.sort((a, b) => -1 * a.timestampCreated.compareTo(b.timestampCreated));
|
||||
|
||||
@@ -106,6 +132,22 @@ class _SubscriptionListPageState extends State<SubscriptionListPage> {
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
FilterChips<SubscriptionListFilter>(
|
||||
options: [
|
||||
(SubscriptionListFilter.ALL, 'All'),
|
||||
(SubscriptionListFilter.OWN, 'Own'),
|
||||
(SubscriptionListFilter.EXTERNAL, 'External'),
|
||||
(SubscriptionListFilter.INCOMING, 'Incoming'),
|
||||
(SubscriptionListFilter.INACTIVE, 'Inactive'),
|
||||
],
|
||||
value: filter,
|
||||
onChanged: (newFilter) {
|
||||
setState(() {
|
||||
filter = newFilter;
|
||||
_pagingController.refresh();
|
||||
});
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: _buildList(context),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user