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:
parent
7f3dfe7dd7
commit
e03a8561b9
@ -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
|
||||||
---
|
---
|
||||||
|
26
lib/api.dart
26
lib/api.dart
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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": {},
|
||||||
|
|
||||||
|
@ -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 ?? "")) {
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user