2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 13:36:50 +00:00

Main screen loading indicator (#183)

* Bug fix for login screen

- Prevent setState() from being called if the widget is no longer loaded

* Add callback function when API status changes

- Home screen uses this function to update connection status indicator

* Linting fixes
This commit is contained in:
Oliver 2022-07-19 23:10:06 +10:00 committed by GitHub
parent 7f3dfe7dd7
commit e03a8561b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 5 deletions

View File

@ -9,6 +9,7 @@
- Indicate available quantity in stock detail view - Indicate available quantity in stock detail view
- Adds configurable filtering to various list views - Adds configurable filtering to various list views
- Allow stock location to be "scanned" into another location using barcode - Allow stock location to be "scanned" into another location using barcode
- Improves server connection status indicator on home screen
### 0.7.3 - June 2022 ### 0.7.3 - June 2022
--- ---

View File

@ -135,6 +135,9 @@ class InvenTreeFileService extends FileService {
*/ */
/*
* API class which manages all communication with the InvenTree server
*/
class InvenTreeAPI { class InvenTreeAPI {
factory InvenTreeAPI() { factory InvenTreeAPI() {
@ -143,6 +146,19 @@ class InvenTreeAPI {
InvenTreeAPI._internal(); InvenTreeAPI._internal();
// List of callback functions to trigger when the connection status changes
List<Function()> _statusCallbacks = [];
// Register a callback function to be notified when the connection status changes
void registerCallback(Function() func) => _statusCallbacks.add(func);
void _connectionStatusChanged() {
for (Function() func in _statusCallbacks) {
// Call the function
func();
}
}
// Minimum required API version for server // Minimum required API version for server
static const _minApiVersion = 20; static const _minApiVersion = 20;
@ -202,6 +218,10 @@ class InvenTreeAPI {
// Authentication token (initially empty, must be requested) // Authentication token (initially empty, must be requested)
String _token = ""; String _token = "";
String? get serverAddress {
return profile?.server;
}
bool get hasToken => _token.isNotEmpty; bool get hasToken => _token.isNotEmpty;
/* /*
@ -457,6 +477,8 @@ class InvenTreeAPI {
// Clear received settings // Clear received settings
_globalSettings.clear(); _globalSettings.clear();
_userSettings.clear(); _userSettings.clear();
_connectionStatusChanged();
} }
/* /*
@ -481,6 +503,8 @@ class InvenTreeAPI {
_connecting = true; _connecting = true;
_connectionStatusChanged();
_connected = await _connect(); _connected = await _connect();
_connecting = false; _connecting = false;
@ -493,6 +517,8 @@ class InvenTreeAPI {
); );
} }
_connectionStatusChanged();
return _connected; return _connected;
} }

View File

@ -908,6 +908,9 @@
"serverNotConnected": "Server not connected", "serverNotConnected": "Server not connected",
"@serverNotConnected": {}, "@serverNotConnected": {},
"serverNotSelected": "Server not selected",
"@serverNotSelected": {},
"sounds": "Sounds", "sounds": "Sounds",
"@sounds": {}, "@sounds": {},

View File

@ -29,6 +29,10 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
profiles = await UserProfileDBManager().getAllProfiles(); profiles = await UserProfileDBManager().getAllProfiles();
if (!mounted) {
return;
}
setState(() { setState(() {
}); });
} }
@ -58,6 +62,10 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
await UserProfileDBManager().selectProfile(key); await UserProfileDBManager().selectProfile(key);
if (!mounted) {
return;
}
_reload(); _reload();
// Attempt server login (this will load the newly selected profile // Attempt server login (this will load the newly selected profile
@ -72,6 +80,10 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
await UserProfileDBManager().deleteProfile(profile); await UserProfileDBManager().deleteProfile(profile);
if (!mounted) {
return;
}
_reload(); _reload();
if (InvenTreeAPI().isConnected() && profile.key == (InvenTreeAPI().profile?.key ?? "")) { if (InvenTreeAPI().isConnected() && profile.key == (InvenTreeAPI().profile?.key ?? "")) {

View File

@ -23,6 +23,7 @@ import "package:inventree/widget/part_list.dart";
import "package:inventree/widget/purchase_order_list.dart"; import "package:inventree/widget/purchase_order_list.dart";
import "package:inventree/widget/search.dart"; import "package:inventree/widget/search.dart";
import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/snacks.dart";
import "package:inventree/widget/spinner.dart";
class InvenTreeHomePage extends StatefulWidget { class InvenTreeHomePage extends StatefulWidget {
@ -51,6 +52,13 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
), (timer) { ), (timer) {
_refreshNotifications(); _refreshNotifications();
}); });
InvenTreeAPI().registerCallback(() {
setState(() {
// Reload the widget
});
});
} }
// Index of bottom navigation bar // Index of bottom navigation bar
@ -352,6 +360,24 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
* display a connection status widget * display a connection status widget
*/ */
Widget _connectionStatusWidget(BuildContext context) { Widget _connectionStatusWidget(BuildContext context) {
String? serverAddress = InvenTreeAPI().serverAddress;
bool validAddress = serverAddress != null;
bool connecting = !InvenTreeAPI().isConnected() && InvenTreeAPI().isConnecting();
Widget leading = FaIcon(FontAwesomeIcons.exclamationCircle, color: COLOR_DANGER);
Widget trailing = FaIcon(FontAwesomeIcons.server, color: COLOR_CLICK);
String title = L10().serverNotConnected;
String subtitle = L10().profileSelectOrCreate;
if (!validAddress) {
title = L10().serverNotSelected;
} else if (connecting) {
title = L10().serverConnecting;
subtitle = serverAddress;
leading = Spinner(icon: FontAwesomeIcons.spinner, color: COLOR_PROGRESS);
}
return Center( return Center(
child: Column( child: Column(
children: [ children: [
@ -363,10 +389,10 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
), ),
Spacer(), Spacer(),
ListTile( ListTile(
title: Text(L10().serverNotConnected), title: Text(title),
subtitle: Text(L10().profileSelectOrCreate), subtitle: Text(subtitle),
trailing: FaIcon(FontAwesomeIcons.server, color: COLOR_CLICK), trailing: trailing,
leading: FaIcon(FontAwesomeIcons.exclamationCircle, color: COLOR_DANGER), leading: leading,
onTap: _selectProfile, onTap: _selectProfile,
) )
] ]
@ -456,6 +482,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var connected = InvenTreeAPI().isConnected(); var connected = InvenTreeAPI().isConnected();
var connecting = !connected && InvenTreeAPI().isConnecting();
return Scaffold( return Scaffold(
key: _homeKey, key: _homeKey,
@ -465,7 +492,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
IconButton( IconButton(
icon: FaIcon( icon: FaIcon(
FontAwesomeIcons.server, FontAwesomeIcons.server,
color: connected ? COLOR_SUCCESS : COLOR_DANGER, color: connected ? COLOR_SUCCESS : (connecting ? COLOR_PROGRESS: COLOR_DANGER),
), ),
onPressed: _selectProfile, onPressed: _selectProfile,
) )