mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-30 21:05:42 +00:00 
			
		
		
		
	Better use of async functions for API
- Use local_preferences for storing data
This commit is contained in:
		
							
								
								
									
										100
									
								
								lib/api.dart
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								lib/api.dart
									
									
									
									
									
								
							| @@ -8,6 +8,8 @@ import 'package:http/http.dart' as http; | |||||||
|  |  | ||||||
| class InvenTreeAPI { | class InvenTreeAPI { | ||||||
|  |  | ||||||
|  |   static const _URL_GET_TOKEN = "user/token/"; | ||||||
|  |  | ||||||
|   // Ensure we only ever create a single instance of the API class |   // Ensure we only ever create a single instance of the API class | ||||||
|   static final InvenTreeAPI _api = new InvenTreeAPI._internal(); |   static final InvenTreeAPI _api = new InvenTreeAPI._internal(); | ||||||
|  |  | ||||||
| @@ -56,6 +58,11 @@ class InvenTreeAPI { | |||||||
|  |  | ||||||
|   // Construct an API URL |   // Construct an API URL | ||||||
|   String _makeUrl(String url) { |   String _makeUrl(String url) { | ||||||
|  |  | ||||||
|  |     if (url.startsWith('/')) { | ||||||
|  |       url = url.substring(1); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return path.join(_base_url, url); |     return path.join(_base_url, url); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -65,27 +72,36 @@ class InvenTreeAPI { | |||||||
|  |  | ||||||
|   // Request the raw /api/ endpoing to see if there is an InvenTree server listening |   // Request the raw /api/ endpoing to see if there is an InvenTree server listening | ||||||
|   void _tryConnection() async { |   void _tryConnection() async { | ||||||
|     final response = get(""); |  | ||||||
|  |     print("Testing connection to server"); | ||||||
|  |  | ||||||
|  |     final response = await get("").then((http.Response response) { | ||||||
|  |       print("response!"); | ||||||
|  |       print(response.body); | ||||||
|  |     }).catchError((error) { | ||||||
|  |       print("Error trying connection"); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     // TODO - Add timeout handler | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Request an API token from the server. |   // Request an API token from the server. | ||||||
|   // A valid username/password combination must be provided |   // A valid username/password combination must be provided | ||||||
|   void _secureToken() async { |   void _secureToken() async { | ||||||
|  |  | ||||||
|     if (_token.isNotEmpty) { |     if (_token.isNotEmpty) { | ||||||
|       print("Discarding old token - " + _token); |       print("Discarding old token - " + _token); | ||||||
|     } |     } | ||||||
|     _token = ""; |     _token = ""; | ||||||
|  |  | ||||||
|     var _url = _makeUrl("user/token/"); |     var response = post(_URL_GET_TOKEN, | ||||||
|     final response = await http.post(_url, |  | ||||||
|         body: { |         body: { | ||||||
|           "username": _username, |           "username": _username, | ||||||
|           "password": _password |           "password": _password, | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |     response.then((http.Response response) { | ||||||
|       if (response.statusCode != 200) { |       if (response.statusCode != 200) { | ||||||
|       print("Invalid status code:" + String.fromCharCode(response.statusCode)); |         print("Invalid status code: " + response.statusCode.toString()); | ||||||
|       } else { |       } else { | ||||||
|         var _json = json.decode(response.body); |         var _json = json.decode(response.body); | ||||||
|  |  | ||||||
| @@ -94,21 +110,75 @@ class InvenTreeAPI { | |||||||
|           print("Received token: " + _token); |           print("Received token: " + _token); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |     }).catchError((error) { | ||||||
|  |       print("Error retrieving token"); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<http.Response> get(String url) async { |   // Perform a PATCH request | ||||||
|  |   Future<http.Response> patch(String url, {Map<String, String> body}) async { | ||||||
|  |  | ||||||
|     var _url = _makeUrl(url); |     var _url = _makeUrl(url); | ||||||
|     final response = await http.get(_url, |     var _headers = _defaultHeaders(); | ||||||
|       headers: { |     var _body = Map<String, String>(); | ||||||
|           HttpHeaders.authorizationHeader: "Token: " + _token |  | ||||||
|         } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     print("Making request to " + _url); |     // Copy across provided data | ||||||
|     print(response.statusCode); |     body.forEach((K, V) => _body[K] = V); | ||||||
|     print(response.body); |  | ||||||
|  |     print("PATCH: " + _url); | ||||||
|  |  | ||||||
|  |     final response = await http.patch(_url, | ||||||
|  |       headers: _headers, | ||||||
|  |       body: _body, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     return response; |     return response; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Perform a POST request | ||||||
|  |   Future<http.Response> post(String url, {Map<String, String> body}) async { | ||||||
|  |  | ||||||
|  |     var _url = _makeUrl(url); | ||||||
|  |     var _headers = _defaultHeaders(); | ||||||
|  |     var _body = Map<String, String>(); | ||||||
|  |  | ||||||
|  |     // Copy across provided data | ||||||
|  |     body.forEach((K, V) => _body[K] = V); | ||||||
|  |  | ||||||
|  |     print("POST: " + _url); | ||||||
|  |  | ||||||
|  |     final response = await http.post(_url, | ||||||
|  |       headers: _headers, | ||||||
|  |       body: _body, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     return response; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Perform a GET request | ||||||
|  |   Future<http.Response> get(String url) async { | ||||||
|  |  | ||||||
|  |     var _url = _makeUrl(url); | ||||||
|  |     var _headers = _defaultHeaders(); | ||||||
|  |  | ||||||
|  |     print("GET: " + _url); | ||||||
|  |  | ||||||
|  |     final response = await http.get(_url, | ||||||
|  |       headers: _headers, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     return response; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Map<String, String> _defaultHeaders() { | ||||||
|  |  | ||||||
|  |     var headers = Map<String, String>(); | ||||||
|  |  | ||||||
|  |     if (_token.isNotEmpty) { | ||||||
|  |       headers[HttpHeaders.authorizationHeader] = "Token " + _token; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return headers; | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; | |||||||
| import 'package:shared_preferences/shared_preferences.dart'; | import 'package:shared_preferences/shared_preferences.dart'; | ||||||
|  |  | ||||||
| import 'api.dart'; | import 'api.dart'; | ||||||
|  | import 'preferences.dart'; | ||||||
|  |  | ||||||
| class InvenTreeLoginSettingsWidget extends StatefulWidget { | class InvenTreeLoginSettingsWidget extends StatefulWidget { | ||||||
|  |  | ||||||
| @@ -133,13 +134,9 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> { | |||||||
|     if (_formKey.currentState.validate()) { |     if (_formKey.currentState.validate()) { | ||||||
|       _formKey.currentState.save(); |       _formKey.currentState.save(); | ||||||
|  |  | ||||||
|       SharedPreferences prefs = await SharedPreferences.getInstance(); |       await InvenTreeUserPreferences().saveLoginDetails(_addr, _user, _pass); | ||||||
|  |  | ||||||
|       await prefs.setString('server', _addr); |       print("Saved"); | ||||||
|       await prefs.setString('username', _user); |  | ||||||
|       await prefs.setString('password', _pass); |  | ||||||
|  |  | ||||||
|       InvenTreeAPI().connect(_addr, _user, _pass); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -2,11 +2,13 @@ import 'package:flutter/material.dart'; | |||||||
|  |  | ||||||
| import 'settings.dart'; | import 'settings.dart'; | ||||||
| import 'api.dart'; | import 'api.dart'; | ||||||
|  | import 'preferences.dart'; | ||||||
|  |  | ||||||
| void main() => runApp(MyApp()); | void main() => runApp(MyApp()); | ||||||
|  |  | ||||||
| class MyApp extends StatelessWidget { | class MyApp extends StatelessWidget { | ||||||
|   // This widget is the root of your application. |   // This widget is the root of your application. | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return MaterialApp( |     return MaterialApp( | ||||||
| @@ -21,7 +23,7 @@ class MyApp extends StatelessWidget { | |||||||
|         // or simply save your changes to "hot reload" in a Flutter IDE). |         // or simply save your changes to "hot reload" in a Flutter IDE). | ||||||
|         // Notice that the counter didn't reset back to zero; the application |         // Notice that the counter didn't reset back to zero; the application | ||||||
|         // is not restarted. |         // is not restarted. | ||||||
|         primarySwatch: Colors.blue, |         primarySwatch: Colors.lightGreen, | ||||||
|       ), |       ), | ||||||
|       home: MyHomePage(title: 'InvenTree'), |       home: MyHomePage(title: 'InvenTree'), | ||||||
|     ); |     ); | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								lib/preferences.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								lib/preferences.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | import 'package:shared_preferences/shared_preferences.dart'; | ||||||
|  | import 'api.dart'; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class InvenTreeUserPreferences { | ||||||
|  |  | ||||||
|  |   static const String _SERVER = 'server'; | ||||||
|  |   static const String _USERNAME = 'username'; | ||||||
|  |   static const String _PASSWORD = 'password'; | ||||||
|  |  | ||||||
|  |   // Ensure we only ever create a single instance of the preferences class | ||||||
|  |   static final InvenTreeUserPreferences _api = new InvenTreeUserPreferences._internal(); | ||||||
|  |  | ||||||
|  |   factory InvenTreeUserPreferences() { | ||||||
|  |     return _api; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   InvenTreeUserPreferences._internal(); | ||||||
|  |  | ||||||
|  |   // Load saved login details, and attempt connection | ||||||
|  |   void loadLoginDetails() async { | ||||||
|  |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|  |  | ||||||
|  |     var server = prefs.getString(_SERVER); | ||||||
|  |     var username = prefs.getString(_USERNAME); | ||||||
|  |     var password = prefs.getString(_PASSWORD); | ||||||
|  |  | ||||||
|  |     await InvenTreeAPI().connect(server, username, password); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void saveLoginDetails(String server, String username, String password) async { | ||||||
|  |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|  |  | ||||||
|  |     await prefs.setString(_SERVER, server); | ||||||
|  |     await prefs.setString(_USERNAME, username); | ||||||
|  |     await prefs.setString(_PASSWORD, password); | ||||||
|  |  | ||||||
|  |     // Reconnect the API | ||||||
|  |     await InvenTreeAPI().connect(server, username, password); | ||||||
|  |   } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user