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:
parent
1c0b469020
commit
7373805ea7
87
lib/api.dart
87
lib/api.dart
@ -109,13 +109,11 @@ class InvenTreeAPI {
|
|||||||
|
|
||||||
String makeUrl(String endpoint) => _makeUrl(endpoint);
|
String makeUrl(String endpoint) => _makeUrl(endpoint);
|
||||||
|
|
||||||
UserProfile _profile;
|
UserProfile profile;
|
||||||
|
|
||||||
// Authentication token (initially empty, must be requested)
|
// Authentication token (initially empty, must be requested)
|
||||||
String _token = "";
|
String _token = "";
|
||||||
|
|
||||||
bool isConnected() => _token.isNotEmpty;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check server connection and display messages if not connected.
|
* Check server connection and display messages if not connected.
|
||||||
* Useful as a precursor check before performing operations.
|
* Useful as a precursor check before performing operations.
|
||||||
@ -154,8 +152,14 @@ class InvenTreeAPI {
|
|||||||
// Connection status flag - set once connection has been validated
|
// Connection status flag - set once connection has been validated
|
||||||
bool _connected = false;
|
bool _connected = false;
|
||||||
|
|
||||||
bool get connected {
|
bool _connecting = true;
|
||||||
return _connected && baseUrl.isNotEmpty && _token.isNotEmpty;
|
|
||||||
|
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
|
// Ensure we only ever create a single instance of the API class
|
||||||
@ -167,35 +171,15 @@ class InvenTreeAPI {
|
|||||||
|
|
||||||
InvenTreeAPI._internal();
|
InvenTreeAPI._internal();
|
||||||
|
|
||||||
Future<bool> connect(BuildContext context) async {
|
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 {
|
|
||||||
|
|
||||||
/* Address is the base address for the InvenTree server,
|
/* Address is the base address for the InvenTree server,
|
||||||
* e.g. http://127.0.0.1:8000
|
* e.g. http://127.0.0.1:8000
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (_profile == null) return false;
|
String address = profile.server.trim();
|
||||||
|
String username = profile.username.trim();
|
||||||
String errorMessage = "";
|
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) {
|
if (address.isEmpty || username.isEmpty || password.isEmpty) {
|
||||||
await showErrorDialog(
|
await showErrorDialog(
|
||||||
@ -220,19 +204,18 @@ class InvenTreeAPI {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
_BASE_URL = address;
|
_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) {
|
var response = await get("").timeout(Duration(seconds: 5)).catchError((error) {
|
||||||
|
|
||||||
print("Error connecting to server: ${error.toString()}");
|
print("Error connecting to server: ${error.toString()}");
|
||||||
|
|
||||||
if (error is SocketException) {
|
if (error is SocketException) {
|
||||||
errorMessage = "Could not connect to server";
|
showServerError(context, "Connection Refused");
|
||||||
return null;
|
return null;
|
||||||
} else if (error is TimeoutException) {
|
} else if (error is TimeoutException) {
|
||||||
errorMessage = "Server timeout";
|
showTimeoutDialog(context);
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
// Unknown error type - re-throw the error and Sentry will catch it
|
// Unknown error type - re-throw the error and Sentry will catch it
|
||||||
@ -242,8 +225,6 @@ class InvenTreeAPI {
|
|||||||
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
// Null (or error) response: Show dialog and exit
|
// Null (or error) response: Show dialog and exit
|
||||||
|
|
||||||
await showServerError(context, errorMessage);
|
|
||||||
return false;
|
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
|
// Perform a PATCH request
|
||||||
Future<http.Response> patch(String url, {Map<String, String> body}) async {
|
Future<http.Response> patch(String url, {Map<String, String> body}) async {
|
||||||
var _url = makeApiUrl(url);
|
var _url = makeApiUrl(url);
|
||||||
@ -405,7 +418,9 @@ class InvenTreeAPI {
|
|||||||
Map<String, String> defaultHeaders() {
|
Map<String, String> defaultHeaders() {
|
||||||
var headers = Map<String, String>();
|
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;
|
return headers;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
|
|||||||
_reload();
|
_reload();
|
||||||
|
|
||||||
// Attempt server login (this will load the newly selected profile
|
// Attempt server login (this will load the newly selected profile
|
||||||
InvenTreeAPI().connect(context);
|
InvenTreeAPI().connectToServer(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deleteProfile(UserProfile profile) async {
|
void _deleteProfile(UserProfile profile) async {
|
||||||
@ -220,7 +220,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
|
|||||||
|
|
||||||
List<Widget> children = [];
|
List<Widget> children = [];
|
||||||
|
|
||||||
if (profiles.length > 0) {
|
if (profiles != null && profiles.length > 0) {
|
||||||
for (int idx = 0; idx < profiles.length; idx++) {
|
for (int idx = 0; idx < profiles.length; idx++) {
|
||||||
UserProfile profile = profiles[idx];
|
UserProfile profile = profiles[idx];
|
||||||
|
|
||||||
|
@ -44,109 +44,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
|
|||||||
// Selected user profile
|
// Selected user profile
|
||||||
UserProfile _profile;
|
UserProfile _profile;
|
||||||
|
|
||||||
void _loadProfile() async {
|
BuildContext _context;
|
||||||
|
|
||||||
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(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _search() {
|
void _search() {
|
||||||
if (!InvenTreeAPI().checkConnection(context)) return;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
_context = context;
|
||||||
|
|
||||||
|
_loadProfile();
|
||||||
|
|
||||||
// This method is rerun every time setState is called, for instance as done
|
// This method is rerun every time setState is called, for instance as done
|
||||||
// by the _incrementCounter method above.
|
// by the _incrementCounter method above.
|
||||||
//
|
//
|
||||||
@ -369,6 +389,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
|
|||||||
),
|
),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
*/
|
*/
|
||||||
|
Spacer(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user