Merge pull request #4723 from dignow/fix/user_login_state
Fix/user login state
This commit is contained in:
		
						commit
						eb686e2728
					
				| @ -3,6 +3,7 @@ import 'package:flutter_hbb/common/formatter/id_formatter.dart'; | ||||
| import 'package:flutter_hbb/common/widgets/peer_card.dart'; | ||||
| import 'package:flutter_hbb/common/widgets/peers_view.dart'; | ||||
| import 'package:flutter_hbb/desktop/widgets/popup_menu.dart'; | ||||
| import 'package:flutter_hbb/models/state_model.dart'; | ||||
| import '../../consts.dart'; | ||||
| import '../../desktop/widgets/material_mod_popup_menu.dart' as mod_menu; | ||||
| import 'package:get/get.dart'; | ||||
| @ -29,15 +30,18 @@ class _AddressBookState extends State<AddressBook> { | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) => FutureBuilder<Widget>( | ||||
|       future: buildBody(context), | ||||
|       builder: (context, snapshot) { | ||||
|         if (snapshot.hasData) { | ||||
|           return snapshot.data!; | ||||
|         } else { | ||||
|           return const Offstage(); | ||||
|         } | ||||
|       }); | ||||
|   Widget build(BuildContext context) => Obx(() => Offstage( | ||||
|         offstage: stateGlobal.svcStatus.value != SvcStatus.ready, | ||||
|         child: FutureBuilder<Widget>( | ||||
|             future: buildBody(context), | ||||
|             builder: (context, snapshot) { | ||||
|               if (snapshot.hasData) { | ||||
|                 return snapshot.data!; | ||||
|               } else { | ||||
|                 return const Offstage(); | ||||
|               } | ||||
|             }), | ||||
|       )); | ||||
| 
 | ||||
|   Future<Widget> buildBody(BuildContext context) async { | ||||
|     return Obx(() { | ||||
| @ -54,6 +58,9 @@ class _AddressBookState extends State<AddressBook> { | ||||
|         if (gFFI.abModel.abError.isNotEmpty) { | ||||
|           return _buildShowError(gFFI.abModel.abError.value); | ||||
|         } | ||||
|         if (gFFI.abModel.fromServer.isFalse) { | ||||
|           return Offstage(); | ||||
|         } | ||||
|         return isDesktop | ||||
|             ? _buildAddressBookDesktop() | ||||
|             : _buildAddressBookMobile(); | ||||
|  | ||||
| @ -96,7 +96,7 @@ class ConfigOP { | ||||
| class WidgetOP extends StatefulWidget { | ||||
|   final ConfigOP config; | ||||
|   final RxString curOP; | ||||
|   final Function(String) cbLogin; | ||||
|   final Function(Map<String, dynamic>) cbLogin; | ||||
|   const WidgetOP({ | ||||
|     Key? key, | ||||
|     required this.config, | ||||
| @ -153,9 +153,8 @@ class _WidgetOPState extends State<WidgetOP> { | ||||
|         } | ||||
|         if (authBody != null) { | ||||
|           _updateTimer?.cancel(); | ||||
|           final String username = authBody['user']['name']; | ||||
|           widget.curOP.value = ''; | ||||
|           widget.cbLogin(username); | ||||
|           widget.cbLogin(authBody as Map<String, dynamic>); | ||||
|         } | ||||
| 
 | ||||
|         setState(() { | ||||
| @ -255,7 +254,7 @@ class _WidgetOPState extends State<WidgetOP> { | ||||
| class LoginWidgetOP extends StatelessWidget { | ||||
|   final List<ConfigOP> ops; | ||||
|   final RxString curOP; | ||||
|   final Function(String) cbLogin; | ||||
|   final Function(Map<String, dynamic>) cbLogin; | ||||
| 
 | ||||
|   LoginWidgetOP({ | ||||
|     Key? key, | ||||
| @ -368,7 +367,8 @@ const kAuthReqTypeOidc = 'oidc/'; | ||||
| /// common login dialog for desktop | ||||
| /// call this directly | ||||
| Future<bool?> loginDialog() async { | ||||
|   var username = TextEditingController(); | ||||
|   var username = | ||||
|       TextEditingController(text: UserModel.getLocalUserInfo()?['name'] ?? ''); | ||||
|   var password = TextEditingController(); | ||||
|   final userFocusNode = FocusNode()..requestFocus(); | ||||
|   Timer(Duration(milliseconds: 100), () => userFocusNode..requestFocus()); | ||||
| @ -480,8 +480,17 @@ Future<bool?> loginDialog() async { | ||||
|                     .where((op) => oidcOptions.contains(op.op.toLowerCase())) | ||||
|                     .toList(), | ||||
|                 curOP: curOP, | ||||
|                 cbLogin: (String username) { | ||||
|                   gFFI.userModel.userName.value = username; | ||||
|                 cbLogin: (Map<String, dynamic> authBody) { | ||||
|                   try { | ||||
|                     final loginResp = | ||||
|                         gFFI.userModel.getLoginResponseFromAuthBody(authBody); | ||||
|                     if (loginResp.access_token != null) { | ||||
|                       bind.mainSetLocalOption( | ||||
|                           key: 'access_token', value: loginResp.access_token!); | ||||
|                     } | ||||
|                   } catch (e) { | ||||
|                     debugPrint('Failed too parse oidc login body: "$authBody"'); | ||||
|                   } | ||||
|                   close(true); | ||||
|                 }, | ||||
|               ), | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_hbb/common/hbbs/hbbs.dart'; | ||||
| import 'package:flutter_hbb/common/widgets/peers_view.dart'; | ||||
| import 'package:flutter_hbb/models/state_model.dart'; | ||||
| import 'package:get/get.dart'; | ||||
| 
 | ||||
| import '../../common.dart'; | ||||
| @ -26,15 +27,20 @@ class _MyGroupState extends State<MyGroup> { | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) => FutureBuilder<Widget>( | ||||
|       future: buildBody(context), | ||||
|       builder: (context, snapshot) { | ||||
|         if (snapshot.hasData) { | ||||
|           return snapshot.data!; | ||||
|         } else { | ||||
|           return const Offstage(); | ||||
|         } | ||||
|       }); | ||||
|   Widget build(BuildContext context) { | ||||
|     return Obx(() => Offstage( | ||||
|           offstage: stateGlobal.svcStatus.value != SvcStatus.ready, | ||||
|           child: FutureBuilder<Widget>( | ||||
|               future: buildBody(context), | ||||
|               builder: (context, snapshot) { | ||||
|                 if (snapshot.hasData) { | ||||
|                   return snapshot.data!; | ||||
|                 } else { | ||||
|                   return const Offstage(); | ||||
|                 } | ||||
|               }), | ||||
|         )); | ||||
|   } | ||||
| 
 | ||||
|   Future<Widget> buildBody(BuildContext context) async { | ||||
|     return Obx(() { | ||||
|  | ||||
| @ -42,7 +42,6 @@ class _ConnectionPageState extends State<ConnectionPage> | ||||
|   final FocusNode _idFocusNode = FocusNode(); | ||||
| 
 | ||||
|   var svcStopped = Get.find<RxBool>(tag: 'stop-service'); | ||||
|   var svcStatusCode = 0.obs; | ||||
|   var svcIsUsingPublicServer = true.obs; | ||||
| 
 | ||||
|   bool isWindowMinimized = false; | ||||
| @ -253,9 +252,9 @@ class _ConnectionPageState extends State<ConnectionPage> | ||||
|                 width: 8, | ||||
|                 decoration: BoxDecoration( | ||||
|                   borderRadius: BorderRadius.circular(4), | ||||
|                   color: svcStopped.value || svcStatusCode.value == 0 | ||||
|                   color: svcStopped.value || stateGlobal.svcStatus.value == SvcStatus.connecting | ||||
|                       ? kColorWarn | ||||
|                       : (svcStatusCode.value == 1 | ||||
|                       : (stateGlobal.svcStatus.value == SvcStatus.ready | ||||
|                           ? Color.fromARGB(255, 50, 190, 166) | ||||
|                           : Color.fromARGB(255, 224, 79, 95)), | ||||
|                 ), | ||||
| @ -263,9 +262,9 @@ class _ConnectionPageState extends State<ConnectionPage> | ||||
|               Text( | ||||
|                   svcStopped.value | ||||
|                       ? translate("Service is not running") | ||||
|                       : svcStatusCode.value == 0 | ||||
|                       : stateGlobal.svcStatus.value == SvcStatus.connecting | ||||
|                           ? translate("connecting_status") | ||||
|                           : svcStatusCode.value == -1 | ||||
|                           : stateGlobal.svcStatus.value == SvcStatus.notReady | ||||
|                               ? translate("not_ready_status") | ||||
|                               : translate('Ready'), | ||||
|                   style: TextStyle(fontSize: em)), | ||||
| @ -286,7 +285,7 @@ class _ConnectionPageState extends State<ConnectionPage> | ||||
|               Flexible( | ||||
|                 child: Offstage( | ||||
|                   offstage: !(!svcStopped.value && | ||||
|                       svcStatusCode.value == 1 && | ||||
|                       stateGlobal.svcStatus.value == SvcStatus.ready && | ||||
|                       svcIsUsingPublicServer.value), | ||||
|                   child: Row( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.center, | ||||
| @ -330,7 +329,25 @@ class _ConnectionPageState extends State<ConnectionPage> | ||||
|   updateStatus() async { | ||||
|     final status = | ||||
|         jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>; | ||||
|     svcStatusCode.value = status["status_num"]; | ||||
|     final statusNum = status['status_num'] as int; | ||||
|     final preStatus = stateGlobal.svcStatus.value; | ||||
|     if (statusNum == 0) { | ||||
|       stateGlobal.svcStatus.value = SvcStatus.connecting; | ||||
|     } else if (statusNum == -1) { | ||||
|       stateGlobal.svcStatus.value = SvcStatus.notReady; | ||||
|     } else if (statusNum == 1) { | ||||
|       stateGlobal.svcStatus.value = SvcStatus.ready; | ||||
|       if (preStatus != SvcStatus.ready) { | ||||
|         gFFI.userModel.refreshCurrentUser(); | ||||
|         gFFI.groupModel.pull(); | ||||
|       } | ||||
|     } else { | ||||
|       stateGlobal.svcStatus.value = SvcStatus.notReady; | ||||
|     } | ||||
|     if (stateGlobal.svcStatus.value != SvcStatus.ready) { | ||||
|       gFFI.userModel.isAdmin.value = false; | ||||
|       gFFI.groupModel.reset(); | ||||
|     } | ||||
|     svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -10,12 +10,13 @@ import 'package:http/http.dart' as http; | ||||
| import '../common.dart'; | ||||
| 
 | ||||
| class AbModel { | ||||
|   var abLoading = false.obs; | ||||
|   var abError = "".obs; | ||||
|   var tags = [].obs; | ||||
|   var peers = List<Peer>.empty(growable: true).obs; | ||||
|   final abLoading = false.obs; | ||||
|   final abError = "".obs; | ||||
|   final tags = [].obs; | ||||
|   final RxBool fromServer = false.obs; | ||||
|   final peers = List<Peer>.empty(growable: true).obs; | ||||
| 
 | ||||
|   var selectedTags = List<String>.empty(growable: true).obs; | ||||
|   final selectedTags = List<String>.empty(growable: true).obs; | ||||
| 
 | ||||
|   WeakReference<FFI> parent; | ||||
| 
 | ||||
| @ -49,8 +50,10 @@ class AbModel { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         fromServer.value = true; | ||||
|         return resp.body; | ||||
|       } else { | ||||
|         fromServer.value = true; | ||||
|         return ""; | ||||
|       } | ||||
|     } catch (err) { | ||||
|  | ||||
| @ -6,6 +6,8 @@ import 'package:get/get.dart'; | ||||
| 
 | ||||
| import '../consts.dart'; | ||||
| 
 | ||||
| enum SvcStatus { notReady, connecting, ready } | ||||
| 
 | ||||
| class StateGlobal { | ||||
|   int _windowId = -1; | ||||
|   bool _fullscreen = false; | ||||
| @ -16,6 +18,7 @@ class StateGlobal { | ||||
|   final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth); | ||||
|   final RxBool showRemoteToolBar = false.obs; | ||||
|   final RxInt displaysCount = 0.obs; | ||||
|   final svcStatus = SvcStatus.notReady.obs; | ||||
| 
 | ||||
|   // Use for desktop -> remote toolbar -> resolution | ||||
|   final Map<String, Map<int, String?>> _lastResolutionGroupValues = {}; | ||||
|  | ||||
| @ -24,6 +24,7 @@ class UserModel { | ||||
|       await _updateOtherModels(); | ||||
|       return; | ||||
|     } | ||||
|     _updateLocalUserInfo(); | ||||
|     final url = await bind.mainGetApiServer(); | ||||
|     final body = { | ||||
|       'id': await bind.mainGetMyId(), | ||||
| @ -48,7 +49,7 @@ class UserModel { | ||||
|       } | ||||
| 
 | ||||
|       final user = UserPayload.fromJson(data); | ||||
|       await _parseAndUpdateUser(user); | ||||
|       _parseAndUpdateUser(user); | ||||
|     } catch (e) { | ||||
|       print('Failed to refreshCurrentUser: $e'); | ||||
|     } finally { | ||||
| @ -56,6 +57,22 @@ class UserModel { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   static Map<String, dynamic>? getLocalUserInfo() { | ||||
|     try { | ||||
|       return json.decode(bind.mainGetLocalOption(key: 'user_info')); | ||||
|     } catch (e) { | ||||
|       print('Failed to get local user info: $e'); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   _updateLocalUserInfo() { | ||||
|     final userInfo = getLocalUserInfo(); | ||||
|     if (userInfo != null) { | ||||
|       userName.value = userInfo['name']; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Future<void> reset() async { | ||||
|     await bind.mainSetLocalOption(key: 'access_token', value: ''); | ||||
|     await gFFI.abModel.reset(); | ||||
| @ -64,7 +81,7 @@ class UserModel { | ||||
|     gFFI.peerTabModel.check_dynamic_tabs(); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> _parseAndUpdateUser(UserPayload user) async { | ||||
|   _parseAndUpdateUser(UserPayload user) { | ||||
|     userName.value = user.name; | ||||
|     isAdmin.value = user.isAdmin; | ||||
|   } | ||||
| @ -110,11 +127,14 @@ class UserModel { | ||||
|       print("login: jsonDecode resp body failed: ${e.toString()}"); | ||||
|       rethrow; | ||||
|     } | ||||
| 
 | ||||
|     if (resp.statusCode != 200) { | ||||
|       throw RequestException(resp.statusCode, body['error'] ?? ''); | ||||
|     } | ||||
| 
 | ||||
|     return getLoginResponseFromAuthBody(body); | ||||
|   } | ||||
| 
 | ||||
|   LoginResponse getLoginResponseFromAuthBody(Map<String, dynamic> body) { | ||||
|     final LoginResponse loginResponse; | ||||
|     try { | ||||
|       loginResponse = LoginResponse.fromJson(body); | ||||
| @ -124,7 +144,7 @@ class UserModel { | ||||
|     } | ||||
| 
 | ||||
|     if (loginResponse.user != null) { | ||||
|       await _parseAndUpdateUser(loginResponse.user!); | ||||
|       _parseAndUpdateUser(loginResponse.user!); | ||||
|     } | ||||
| 
 | ||||
|     return loginResponse; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user