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

Refactor API connection code

This commit is contained in:
Oliver Walters 2021-02-09 14:16:31 +11:00
parent 1c0b469020
commit 7373805ea7
3 changed files with 177 additions and 141 deletions

View File

@ -109,13 +109,11 @@ class InvenTreeAPI {
String makeUrl(String endpoint) => _makeUrl(endpoint);
UserProfile _profile;
UserProfile profile;
// Authentication token (initially empty, must be requested)
String _token = "";
bool isConnected() => _token.isNotEmpty;
/*
* Check server connection and display messages if not connected.
* Useful as a precursor check before performing operations.
@ -154,8 +152,14 @@ class InvenTreeAPI {
// Connection status flag - set once connection has been validated
bool _connected = false;
bool get connected {
return _connected && baseUrl.isNotEmpty && _token.isNotEmpty;
bool _connecting = true;
bool isConnected() {
return profile != null && _connected && baseUrl.isNotEmpty && _token.isNotEmpty;
}
bool isConnecting() {
return !isConnected() && _connecting;
}
// Ensure we only ever create a single instance of the API class
@ -167,35 +171,15 @@ class InvenTreeAPI {
InvenTreeAPI._internal();
Future<bool> connect(BuildContext context) async {
_profile = await UserProfileDBManager().getSelectedProfile();
if (_profile == null) {
await showErrorDialog(
context,
"Select Profile",
"User profile not selected"
);
return false;
}
return connectToServer(context);
}
Future<bool> connectToServer(BuildContext context) async {
Future<bool> _connect(BuildContext context) async {
/* Address is the base address for the InvenTree server,
* e.g. http://127.0.0.1:8000
*/
if (_profile == null) return false;
String errorMessage = "";
String address = _profile.server.trim();
String username = _profile.username.trim();
String password = _profile.password.trim();
String address = profile.server.trim();
String username = profile.username.trim();
String password = profile.password.trim();
if (address.isEmpty || username.isEmpty || password.isEmpty) {
await showErrorDialog(
@ -220,19 +204,18 @@ class InvenTreeAPI {
*/
_BASE_URL = address;
_connected = false;
print("Connecting to " + apiUrl + " -> " + username + ":" + password);
print("Connecting to ${apiUrl} -> ${username}:${password}");
var response = await get("").timeout(Duration(seconds: 5)).catchError((error) {
print("Error connecting to server: ${error.toString()}");
if (error is SocketException) {
errorMessage = "Could not connect to server";
showServerError(context, "Connection Refused");
return null;
} else if (error is TimeoutException) {
errorMessage = "Server timeout";
showTimeoutDialog(context);
return null;
} else {
// Unknown error type - re-throw the error and Sentry will catch it
@ -242,8 +225,6 @@ class InvenTreeAPI {
if (response == null) {
// Null (or error) response: Show dialog and exit
await showServerError(context, errorMessage);
return false;
}
@ -322,6 +303,38 @@ class InvenTreeAPI {
};
}
Future<bool> connectToServer(BuildContext context) async {
print("InvenTreeAPI().connectToServer()");
// Clear connection flag
_connected = false;
// Clear token
_token = '';
// Load selected profile
profile = await UserProfileDBManager().getSelectedProfile();
if (profile == null) {
await showErrorDialog(
context,
"Select Profile",
"User profile not selected"
);
return false;
}
_connecting = true;
_connect(context).then((result) {
print("_connect() returned result: ${result}");
_connecting = false;
return result;
});
}
// Perform a PATCH request
Future<http.Response> patch(String url, {Map<String, String> body}) async {
var _url = makeApiUrl(url);
@ -405,7 +418,9 @@ class InvenTreeAPI {
Map<String, String> defaultHeaders() {
var headers = Map<String, String>();
headers[HttpHeaders.authorizationHeader] = _authorizationHeader(_profile.username, _profile.password);
if (profile != null) {
headers[HttpHeaders.authorizationHeader] = _authorizationHeader(profile.username, profile.password);
}
return headers;
}

View File

@ -180,7 +180,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
_reload();
// Attempt server login (this will load the newly selected profile
InvenTreeAPI().connect(context);
InvenTreeAPI().connectToServer(context);
}
void _deleteProfile(UserProfile profile) async {
@ -220,7 +220,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
List<Widget> children = [];
if (profiles.length > 0) {
if (profiles != null && profiles.length > 0) {
for (int idx = 0; idx < profiles.length; idx++) {
UserProfile profile = profiles[idx];

View File

@ -44,109 +44,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
// Selected user profile
UserProfile _profile;
void _loadProfile() async {
final profile = await UserProfileDBManager().getSelectedProfile();
print("Loaded selected profile");
// If a different profile is selected, re-connect
if (_profile == null || (_profile.key != profile.key)) {
// TODO
}
_profile = profile;
setState(() {
});
}
ListTile _serverTile() {
// No profile selected
// Tap to select / create a profile
if (_profile == null) {
return ListTile(
title: Text("No Profile Selected"),
subtitle: Text("Tap to create or select a profile"),
leading: FaIcon(FontAwesomeIcons.user),
onTap: () {
_selectProfile();
},
);
}
// Profile is selected ...
if (InvenTreeAPI().isConnected()) {
return ListTile(
title: Text("Connected to ${_profile.server}"),
);
} else {
return ListTile(
title: Text("Could not connect to server"),
subtitle: Text("Error connecting to ${_profile.server}"),
leading: FaIcon(FontAwesomeIcons.times),
onTap: () {
_selectProfile();
},
);
}
}
void onConnectSuccess(String msg) async {
final profile = await UserProfileDBManager().getSelectedProfile();
String address = profile?.server ?? 'unknown server address';
_serverConnection = true;
_serverMessage = msg;
_serverStatus = "Connected to ${address}";
_serverStatusColor = Color.fromARGB(255, 50, 250, 50);
_serverIcon = new FaIcon(FontAwesomeIcons.checkCircle, color: _serverStatusColor);
setState(() {});
}
void onConnectFailure(String msg) async {
final profile = await UserProfileDBManager().getSelectedProfile();
_serverConnection = false;
_serverMessage = msg;
_serverStatus = "Could not connect to ${profile?.server}";
_serverStatusColor = Color.fromARGB(255, 250, 50, 50);
_serverIcon = new FaIcon(FontAwesomeIcons.timesCircle, color: _serverStatusColor);
setState(() {});
}
/*
* Test the server connection
*/
void _checkServerConnection(BuildContext context) async {
// Reset the connection status variables
_serverStatus = "Connecting to server";
_serverMessage = "";
_serverConnection = false;
_serverIcon = new FaIcon(FontAwesomeIcons.spinner);
_serverStatusColor = Color.fromARGB(255, 50, 50, 250);
InvenTreeAPI().connect(context).then((bool result) {
if (result) {
onConnectSuccess("");
} else {
onConnectFailure("Could not connect to server");
}
});
// Update widget state
setState(() {});
}
BuildContext _context;
void _search() {
if (!InvenTreeAPI().checkConnection(context)) return;
@ -210,8 +108,130 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
);
}
void _loadProfile() async {
final profile = await UserProfileDBManager().getSelectedProfile();
// If a different profile is selected, re-connect
if (_profile == null || (_profile.key != profile.key)) {
if (_context != null) {
print("Connecting Profile: ${profile.name} - ${profile.server}");
InvenTreeAPI().connectToServer(_context).then((result) {
setState(() {
});
});
setState(() {
});
}
}
_profile = profile;
setState(() {
});
}
ListTile _serverTile() {
// No profile selected
// Tap to select / create a profile
if (_profile == null) {
return ListTile(
title: Text("No Profile Selected"),
subtitle: Text("Tap to create or select a profile"),
leading: FaIcon(FontAwesomeIcons.server),
trailing: FaIcon(
FontAwesomeIcons.user,
color: Color.fromRGBO(250, 50, 50, 1),
),
onTap: () {
_selectProfile();
},
);
}
// Profile is selected ...
if (InvenTreeAPI().isConnecting()) {
return ListTile(
title: Text("Connecting to server..."),
subtitle: Text("${InvenTreeAPI().baseUrl}"),
leading: FaIcon(FontAwesomeIcons.server),
trailing: FaIcon(
FontAwesomeIcons.spinner,
color: Color.fromRGBO(50, 50, 250, 1),
)
);
} else if (InvenTreeAPI().isConnected()) {
return ListTile(
title: Text("Connected to server"),
subtitle: Text("${InvenTreeAPI().baseUrl}"),
leading: FaIcon(FontAwesomeIcons.server),
trailing: FaIcon(
FontAwesomeIcons.checkCircle,
color: Color.fromRGBO(50, 250, 50, 1)
),
onTap: () {
_selectProfile();
},
);
} else {
return ListTile(
title: Text("Could not connect to server"),
subtitle: Text("${_profile.server}"),
leading: FaIcon(FontAwesomeIcons.server),
trailing: FaIcon(
FontAwesomeIcons.timesCircle,
color: Color.fromRGBO(250, 50, 50, 1),
),
onTap: () {
_selectProfile();
},
);
}
}
void onConnectSuccess(String msg) async {
final profile = await UserProfileDBManager().getSelectedProfile();
String address = profile?.server ?? 'unknown server address';
_serverConnection = true;
_serverMessage = msg;
_serverStatus = "Connected to ${address}";
_serverStatusColor = Color.fromARGB(255, 50, 250, 50);
_serverIcon = new FaIcon(FontAwesomeIcons.checkCircle, color: _serverStatusColor);
setState(() {});
}
void onConnectFailure(String msg) async {
final profile = await UserProfileDBManager().getSelectedProfile();
_serverConnection = false;
_serverMessage = msg;
_serverStatus = "Could not connect to ${profile?.server}";
_serverStatusColor = Color.fromARGB(255, 250, 50, 50);
_serverIcon = new FaIcon(FontAwesomeIcons.timesCircle, color: _serverStatusColor);
setState(() {});
}
@override
Widget build(BuildContext context) {
_context = context;
_loadProfile();
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
@ -369,6 +389,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
),
Spacer(),
*/
Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,