Add caching to session filter and remove some redundant providers

This commit is contained in:
Nutcake 2023-07-11 18:44:20 +02:00
parent 56350ea2c7
commit e87521df9d
11 changed files with 639 additions and 590 deletions

View file

@ -1,17 +1,28 @@
import 'package:collection/collection.dart';
import 'package:contacts_plus_plus/apis/session_api.dart';
import 'package:contacts_plus_plus/clients/api_client.dart';
import 'package:contacts_plus_plus/clients/settings_client.dart';
import 'package:contacts_plus_plus/models/session.dart';
import 'package:flutter/foundation.dart';
class SessionClient extends ChangeNotifier {
final ApiClient apiClient;
final SettingsClient settingsClient;
Future<List<Session>>? _sessionsFuture;
SessionFilterSettings _filterSettings = SessionFilterSettings.empty();
SessionClient({required this.apiClient});
SessionClient({required this.apiClient, required this.settingsClient}) {
_filterSettings = SessionFilterSettings(
name: "",
hostName: "",
includeEnded: settingsClient.currentSettings.sessionViewLastIncludeEnded.valueOrDefault,
includeIncompatible: settingsClient.currentSettings.sessionViewLastIncludeIncompatible.valueOrDefault,
minActiveUsers: settingsClient.currentSettings.sessionViewLastMinimumUsers.valueOrDefault,
includeEmptyHeadless: settingsClient.currentSettings.sessionViewLastIncludeEmpty.valueOrDefault,
);
}
SessionFilterSettings get filterSettings => _filterSettings;
@ -22,12 +33,16 @@ class SessionClient extends ChangeNotifier {
reloadSessions();
}
void reloadSessions() {
void initSessions() {
_sessionsFuture = SessionApi.getSessions(apiClient, filterSettings: _filterSettings).then(
(value) => value.sorted(
(a, b) => b.sessionUsers.length.compareTo(a.sessionUsers.length),
),
);
}
void reloadSessions() {
initSessions();
notifyListeners();
}
}

View file

@ -8,17 +8,12 @@ import 'package:contacts_plus_plus/clients/messaging_client.dart';
import 'package:contacts_plus_plus/clients/session_client.dart';
import 'package:contacts_plus_plus/clients/settings_client.dart';
import 'package:contacts_plus_plus/models/sem_ver.dart';
import 'package:contacts_plus_plus/widgets/friends/friends_list_app_bar.dart';
import 'package:contacts_plus_plus/widgets/homepage.dart';
import 'package:contacts_plus_plus/widgets/inventory/inventory_browser_app_bar.dart';
import 'package:contacts_plus_plus/widgets/login_screen.dart';
import 'package:contacts_plus_plus/widgets/sessions/session_list_app_bar.dart';
import 'package:contacts_plus_plus/widgets/settings_app_bar.dart';
import 'package:contacts_plus_plus/widgets/update_notifier.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
import 'package:hive_flutter/hive_flutter.dart';
@ -35,8 +30,6 @@ void main() async {
debug: kDebugMode,
);
Provider.debugCheckInvalidValueType = null;
await Hive.initFlutter();
final dateFormat = DateFormat.Hms();
@ -156,19 +149,19 @@ class _ContactsPlusPlusState extends State<ContactsPlusPlus> {
return _authData.isAuthenticated
? MultiProvider(
providers: [
Provider(
ChangeNotifierProvider(
create: (context) => MessagingClient(
apiClient: clientHolder.apiClient,
notificationClient: clientHolder.notificationClient,
),
dispose: (context, value) => value.dispose(),
),
Provider(
ChangeNotifierProvider(
create: (context) => SessionClient(
apiClient: clientHolder.apiClient,
settingsClient: clientHolder.settingsClient,
),
),
Provider(
ChangeNotifierProvider(
create: (context) => InventoryClient(
apiClient: clientHolder.apiClient,
),

View file

@ -40,31 +40,47 @@ class Settings {
final SettingsEntry<String> lastDismissedVersion;
final SettingsEntry<String> machineId;
final SettingsEntry<int> themeMode;
final SettingsEntry<int> sessionViewLastMinimumUsers;
final SettingsEntry<bool> sessionViewLastIncludeEnded;
final SettingsEntry<bool> sessionViewLastIncludeEmpty;
final SettingsEntry<bool> sessionViewLastIncludeIncompatible;
Settings({
SettingsEntry<bool>? notificationsDenied,
SettingsEntry<int>? lastOnlineStatus,
SettingsEntry<int>? themeMode,
SettingsEntry<String>? lastDismissedVersion,
SettingsEntry<String>? machineId
})
: notificationsDenied = notificationsDenied ?? const SettingsEntry<bool>(deflt: false),
SettingsEntry<String>? machineId,
SettingsEntry<int>? sessionViewLastMinimumUsers,
SettingsEntry<bool>? sessionViewLastIncludeEnded,
SettingsEntry<bool>? sessionViewLastIncludeEmpty,
SettingsEntry<bool>? sessionViewLastIncludeIncompatible,
}) : notificationsDenied = notificationsDenied ?? const SettingsEntry<bool>(deflt: false),
lastOnlineStatus = lastOnlineStatus ?? SettingsEntry<int>(deflt: OnlineStatus.online.index),
themeMode = themeMode ?? SettingsEntry<int>(deflt: ThemeMode.dark.index),
lastDismissedVersion = lastDismissedVersion ?? SettingsEntry<String>(deflt: SemVer.zero().toString()),
machineId = machineId ?? SettingsEntry<String>(deflt: const Uuid().v4());
machineId = machineId ?? SettingsEntry<String>(deflt: const Uuid().v4()),
sessionViewLastMinimumUsers = sessionViewLastMinimumUsers ?? const SettingsEntry<int>(deflt: 0),
sessionViewLastIncludeEnded = sessionViewLastIncludeEnded ?? const SettingsEntry<bool>(deflt: false),
sessionViewLastIncludeEmpty = sessionViewLastIncludeEmpty ?? const SettingsEntry<bool>(deflt: true),
sessionViewLastIncludeIncompatible =
sessionViewLastIncludeIncompatible ?? const SettingsEntry<bool>(deflt: false);
factory Settings.fromMap(Map map) {
return Settings(
notificationsDenied: retrieveEntryOrNull<bool>(map["notificationsDenied"]),
lastOnlineStatus: retrieveEntryOrNull<int>(map["lastOnlineStatus"]),
themeMode: retrieveEntryOrNull<int>(map["themeMode"]),
lastDismissedVersion: retrieveEntryOrNull<String>(map["lastDismissedVersion"]),
machineId: retrieveEntryOrNull<String>(map["machineId"]),
notificationsDenied: getEntryOrNull<bool>(map["notificationsDenied"]),
lastOnlineStatus: getEntryOrNull<int>(map["lastOnlineStatus"]),
themeMode: getEntryOrNull<int>(map["themeMode"]),
lastDismissedVersion: getEntryOrNull<String>(map["lastDismissedVersion"]),
machineId: getEntryOrNull<String>(map["machineId"]),
sessionViewLastMinimumUsers: getEntryOrNull<int>(map["sessionViewLastMinimumUsers"]),
sessionViewLastIncludeEnded: getEntryOrNull<bool>(map["sessionViewLastIncludeEnded"]),
sessionViewLastIncludeEmpty: getEntryOrNull<bool>(map["sessionViewLastIncludeEmpty"]),
sessionViewLastIncludeIncompatible: getEntryOrNull<bool>(map["sessionViewLastIncludeIncompatible"]),
);
}
static SettingsEntry<T>? retrieveEntryOrNull<T>(Map? map) {
static SettingsEntry<T>? getEntryOrNull<T>(Map? map) {
if (map == null) return null;
try {
return SettingsEntry<T>.fromMap(map);
@ -80,6 +96,10 @@ class Settings {
"themeMode": themeMode.toMap(),
"lastDismissedVersion": lastDismissedVersion.toMap(),
"machineId": machineId.toMap(),
"sessionViewLastMinimumUsers": sessionViewLastMinimumUsers.toMap(),
"sessionViewLastIncludeEnded": sessionViewLastIncludeEnded.toMap(),
"sessionViewLastIncludeEmpty": sessionViewLastIncludeEmpty.toMap(),
"sessionViewLastIncludeIncompatible": sessionViewLastIncludeIncompatible.toMap(),
};
}
@ -91,6 +111,10 @@ class Settings {
int? themeMode,
String? lastDismissedVersion,
String? machineId,
int? sessionViewLastMinimumUsers,
bool? sessionViewLastIncludeEnded,
bool? sessionViewLastIncludeEmpty,
bool? sessionViewLastIncludeIncompatible,
}) {
return Settings(
notificationsDenied: this.notificationsDenied.passThrough(notificationsDenied),
@ -98,6 +122,11 @@ class Settings {
themeMode: this.themeMode.passThrough(themeMode),
lastDismissedVersion: this.lastDismissedVersion.passThrough(lastDismissedVersion),
machineId: this.machineId.passThrough(machineId),
sessionViewLastMinimumUsers: this.sessionViewLastMinimumUsers.passThrough(sessionViewLastMinimumUsers),
sessionViewLastIncludeEnded: this.sessionViewLastIncludeEnded.passThrough(sessionViewLastIncludeEnded),
sessionViewLastIncludeEmpty: this.sessionViewLastIncludeEmpty.passThrough(sessionViewLastIncludeEmpty),
sessionViewLastIncludeIncompatible:
this.sessionViewLastIncludeIncompatible.passThrough(sessionViewLastIncludeIncompatible),
);
}
}

View file

@ -5,7 +5,6 @@ import 'package:contacts_plus_plus/widgets/friends/friend_list_tile.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class FriendsList extends StatefulWidget {
const FriendsList({super.key});
@ -19,12 +18,13 @@ class _FriendsListState extends State<FriendsList> with AutomaticKeepAliveClient
@override
Widget build(BuildContext context) {
super.build(context);
return ChangeNotifierProvider.value(
value: Provider.of<MessagingClient>(context, listen: false),
child: Stack(
return Consumer<MessagingClient>(
builder: (context, mClient, _) {
return Stack(
alignment: Alignment.topCenter,
children: [
Consumer<MessagingClient>(builder: (context, mClient, _) {
Builder(
builder: (context) {
if (mClient.initStatus == null) {
return const LinearProgressIndicator();
} else if (mClient.initStatus!.isNotEmpty) {
@ -62,7 +62,8 @@ class _FriendsListState extends State<FriendsList> with AutomaticKeepAliveClient
},
);
}
}),
},
),
Align(
alignment: Alignment.bottomCenter,
child: ExpandingInputFab(
@ -81,7 +82,8 @@ class _FriendsListState extends State<FriendsList> with AutomaticKeepAliveClient
),
),
],
),
);
},
);
}

View file

@ -47,9 +47,7 @@ class _FriendsListAppBarState extends State<FriendsListAppBar> with AutomaticKee
@override
Widget build(BuildContext context) {
super.build(context);
return ChangeNotifierProvider.value(
value: Provider.of<MessagingClient>(context, listen: false),
child: AppBar(
return AppBar(
title: const Text("Contacts++"),
actions: [
FutureBuilder(
@ -198,7 +196,6 @@ class _FriendsListAppBarState extends State<FriendsListAppBar> with AutomaticKee
),
)
],
),
);
}

View file

@ -36,9 +36,7 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
@override
Widget build(BuildContext context) {
super.build(context);
return ChangeNotifierProvider.value(
value: Provider.of<InventoryClient>(context),
child: Consumer<InventoryClient>(builder: (BuildContext context, InventoryClient iClient, Widget? child) {
return Consumer<InventoryClient>(builder: (BuildContext context, InventoryClient iClient, Widget? child) {
return FutureBuilder<NeosDirectory>(
future: iClient.directoryFuture,
builder: (context, snapshot) {
@ -224,8 +222,7 @@ class _InventoryBrowserState extends State<InventoryBrowser> with AutomaticKeepA
),
);
});
}),
);
});
}
@override

View file

@ -48,9 +48,7 @@ class _InventoryBrowserAppBarState extends State<InventoryBrowserAppBar> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: Provider.of<InventoryClient>(context),
child: Consumer<InventoryClient>(
return Consumer<InventoryClient>(
builder: (BuildContext context, InventoryClient iClient, Widget? child) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 350),
@ -243,7 +241,6 @@ class _InventoryBrowserAppBarState extends State<InventoryBrowserAppBar> {
),
);
},
),
);
}
}

View file

@ -1,6 +1,8 @@
import 'dart:math';
import 'package:contacts_plus_plus/client_holder.dart';
import 'package:contacts_plus_plus/clients/session_client.dart';
import 'package:contacts_plus_plus/clients/settings_client.dart';
import 'package:contacts_plus_plus/models/session.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -44,9 +46,20 @@ class _SessionFilterDialogState extends State<SessionFilterDialog> {
super.dispose();
}
Future<void> _updateSettings() async {
final settingsClient = ClientHolder.of(context).settingsClient;
await settingsClient.changeSettings(settingsClient.currentSettings.copyWith(
sessionViewLastMinimumUsers: _currentFilter.minActiveUsers,
sessionViewLastIncludeEnded: _currentFilter.includeEnded,
sessionViewLastIncludeEmpty: _currentFilter.includeEmptyHeadless,
sessionViewLastIncludeIncompatible: _currentFilter.includeIncompatible,
));
}
@override
Widget build(BuildContext context) {
return AlertDialog(
insetPadding: const EdgeInsets.all(24),
title: const Text("Filter"),
content: SizedBox(
width: double.infinity,
@ -109,7 +122,8 @@ class _SessionFilterDialogState extends State<SessionFilterDialog> {
IconButton(
onPressed: () {
setState(() {
_currentFilter = _currentFilter.copyWith(minActiveUsers: _currentFilter.minActiveUsers + 1, includeEmptyHeadless: false);
_currentFilter = _currentFilter.copyWith(
minActiveUsers: _currentFilter.minActiveUsers + 1, includeEmptyHeadless: false);
});
},
icon: const Icon(Icons.add_circle_outline),
@ -128,7 +142,9 @@ class _SessionFilterDialogState extends State<SessionFilterDialog> {
SessionFilterCheckbox(
label: "Include Empty Headless",
value: _currentFilter.includeEmptyHeadless && _currentFilter.minActiveUsers == 0,
onChanged: _currentFilter.minActiveUsers > 0 ? null : (value) {
onChanged: _currentFilter.minActiveUsers > 0
? null
: (value) {
setState(() {
_currentFilter = _currentFilter.copyWith(includeEmptyHeadless: value);
});
@ -155,9 +171,10 @@ class _SessionFilterDialogState extends State<SessionFilterDialog> {
child: const Text("Cancel"),
),
TextButton(
onPressed: () {
onPressed: () async {
Provider.of<SessionClient>(context, listen: false).filterSettings = _currentFilter;
Navigator.of(context).pop();
await _updateSettings();
},
child: const Text("Okay"),
),

View file

@ -21,7 +21,7 @@ class _SessionListState extends State<SessionList> with AutomaticKeepAliveClient
super.didChangeDependencies();
final sClient = Provider.of<SessionClient>(context, listen: false);
if (sClient.sessionsFuture == null) {
sClient.reloadSessions();
sClient.initSessions();
}
}

View file

@ -1,4 +1,6 @@
import 'package:contacts_plus_plus/client_holder.dart';
import 'package:contacts_plus_plus/clients/session_client.dart';
import 'package:contacts_plus_plus/clients/settings_client.dart';
import 'package:contacts_plus_plus/widgets/sessions/session_filter_dialog.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -23,7 +25,7 @@ class _SessionListAppBarState extends State<SessionListAppBar> {
final sessionClient = Provider.of<SessionClient>(context, listen: false);
await showDialog(
context: context,
builder: (context) => Provider.value(
builder: (context) => ChangeNotifierProvider.value(
value: sessionClient,
child: SessionFilterDialog(
lastFilter: sessionClient.filterSettings,

View file

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.4.1+1
version: 1.4.2+1
environment:
sdk: '>=3.0.1'