diff --git a/flutter/lib/common/hbbs/hbbs.dart b/flutter/lib/common/hbbs/hbbs.dart index 4717143fd..3e44c2e36 100644 --- a/flutter/lib/common/hbbs/hbbs.dart +++ b/flutter/lib/common/hbbs/hbbs.dart @@ -15,19 +15,19 @@ class HttpType { } class UserPayload { + String id = ''; String name = ''; String email = ''; String note = ''; int? status; - String grp = ''; bool isAdmin = false; UserPayload.fromJson(Map json) - : name = json['name'] ?? '', + : id = json['id'] ?? '', + name = json['name'] ?? '', email = json['email'] ?? '', note = json['note'] ?? '', status = json['status'], - grp = json['grp'] ?? '', isAdmin = json['is_admin'] == true; } diff --git a/flutter/lib/common/widgets/my_group.dart b/flutter/lib/common/widgets/my_group.dart index 65eaba40f..5ba6bbfad 100644 --- a/flutter/lib/common/widgets/my_group.dart +++ b/flutter/lib/common/widgets/my_group.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_hbb/common/hbbs/hbbs.dart'; import 'package:flutter_hbb/common/widgets/peers_view.dart'; import 'package:get/get.dart'; @@ -37,13 +38,13 @@ class _MyGroupState extends State { Future buildBody(BuildContext context) async { return Obx(() { - if (gFFI.groupModel.userLoading.value) { + if (gFFI.groupModel.groupLoading.value) { return const Center( child: CircularProgressIndicator(), ); } - if (gFFI.groupModel.userLoadError.isNotEmpty) { - return _buildShowError(gFFI.groupModel.userLoadError.value); + if (gFFI.groupModel.groupLoadError.isNotEmpty) { + return _buildShowError(gFFI.groupModel.groupLoadError.value); } if (isDesktop) { return _buildDesktop(); @@ -187,16 +188,17 @@ class _MyGroupState extends State { } return true; }) - .map((e) => _buildUserItem(e.name)) + .map((e) => _buildUserItem(e)) .toList()); }); } - Widget _buildUserItem(String username) { + Widget _buildUserItem(UserPayload user) { + final username = user.name; return InkWell(onTap: () { if (selectedUser.value != username) { selectedUser.value = username; - gFFI.groupModel.pullUserPeers(username); + gFFI.groupModel.pullUserPeers(user); } }, child: Obx( () { diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index f21211ad5..0361ba511 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -231,7 +231,9 @@ class _PeerTabPageState extends State if (model.visibleOrderedTabs.contains(model.currentTab)) { child = entries[model.currentTab].widget; } else { - model.setCurrentTab(model.visibleOrderedTabs[0]); + Future.delayed(Duration.zero, () { + model.setCurrentTab(model.visibleOrderedTabs[0]); + }); child = entries[0].widget; } } diff --git a/flutter/lib/models/group_model.dart b/flutter/lib/models/group_model.dart index 5e2b85f90..c7164c42d 100644 --- a/flutter/lib/models/group_model.dart +++ b/flutter/lib/models/group_model.dart @@ -1,6 +1,5 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_hbb/common.dart'; -import 'package:flutter_hbb/common/widgets/peer_tab_page.dart'; import 'package:flutter_hbb/common/hbbs/hbbs.dart'; import 'package:flutter_hbb/models/model.dart'; import 'package:flutter_hbb/models/peer_model.dart'; @@ -10,10 +9,12 @@ import 'dart:convert'; import 'package:http/http.dart' as http; class GroupModel { - final RxBool userLoading = false.obs; - final RxString userLoadError = "".obs; + final RxBool groupLoading = false.obs; + final RxString groupLoadError = "".obs; final RxBool peerLoading = false.obs; //to-do: not used final RxString peerLoadError = "".obs; + final RxString groupName = ''.obs; + final RxString groupId = ''.obs; final RxList users = RxList.empty(growable: true); final RxList peerPayloads = RxList.empty(growable: true); final RxList peersShow = RxList.empty(growable: true); @@ -22,10 +23,12 @@ class GroupModel { GroupModel(this.parent); Future reset() async { - userLoading.value = false; - userLoadError.value = ""; + groupLoading.value = false; + groupLoadError.value = ""; peerLoading.value = false; peerLoadError.value = ""; + groupName.value = ''; + groupId.value = ''; users.clear(); peerPayloads.clear(); peersShow.clear(); @@ -33,13 +36,26 @@ class GroupModel { Future pull() async { await reset(); + if (bind.mainGetLocalOption(key: 'access_token') == '') { + return; + } + try { + if (!await _getGroup()) { + reset(); + return; + } + } catch (e) { + debugPrintStack(label: '$e'); + reset(); + return; + } if (gFFI.userModel.userName.isEmpty || - (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isEmpty)) { + (gFFI.userModel.isAdmin.isFalse && groupName.isEmpty)) { gFFI.peerTabModel.check_dynamic_tabs(); return; } - userLoading.value = true; - userLoadError.value = ""; + groupLoading.value = true; + groupLoadError.value = ""; final api = "${await bind.mainGetApiServer()}/api/users"; try { var uri0 = Uri.parse(api); @@ -56,8 +72,7 @@ class GroupModel { queryParameters: { 'current': current.toString(), 'pageSize': pageSize.toString(), - if (gFFI.userModel.isAdmin.isFalse) - 'grp': gFFI.userModel.groupName.value, + if (gFFI.userModel.isAdmin.isFalse) 'grp': groupId.value, }); final resp = await http.get(uri, headers: getHttpHeaders()); if (resp.body.isNotEmpty && resp.body.toLowerCase() != "null") { @@ -65,12 +80,17 @@ class GroupModel { if (json.containsKey('error')) { throw json['error']; } else { - if (total == 0) total = json['total']; - if (json.containsKey('data')) { - final data = json['data']; - if (data is List) { - for (final user in data) { - users.add(UserPayload.fromJson(user)); + if (json.containsKey('total')) { + if (total == 0) total = json['total']; + if (json.containsKey('data')) { + final data = json['data']; + if (data is List) { + for (final user in data) { + final u = UserPayload.fromJson(user); + if (!users.any((e) => e.name == u.name)) { + users.add(u); + } + } } } } @@ -78,15 +98,43 @@ class GroupModel { } } while (current * pageSize < total); } catch (err) { - debugPrint('$err'); - userLoadError.value = err.toString(); + debugPrintStack(label: '$err'); + groupLoadError.value = err.toString(); } finally { - userLoading.value = false; + groupLoading.value = false; gFFI.peerTabModel.check_dynamic_tabs(); } } - Future pullUserPeers(String username) async { + Future _getGroup() async { + final url = await bind.mainGetApiServer(); + final body = { + 'id': await bind.mainGetMyId(), + 'uuid': await bind.mainGetUuid() + }; + try { + final response = await http.post(Uri.parse('$url/api/currentGroup'), + headers: getHttpHeaders(), body: json.encode(body)); + final status = response.statusCode; + if (status == 401 || status == 400) { + return false; + } + final data = json.decode(response.body); + final error = data['error']; + if (error != null) { + throw error; + } + groupName.value = data['name'] ?? ''; + groupId.value = data['id'] ?? ''; + return groupId.value.isNotEmpty && groupName.isNotEmpty; + } catch (e) { + debugPrintStack(label: '$e'); + } finally {} + + return false; + } + + Future pullUserPeers(UserPayload user) async { peerPayloads.clear(); peersShow.clear(); peerLoading.value = true; @@ -107,8 +155,7 @@ class GroupModel { queryParameters: { 'current': current.toString(), 'pageSize': pageSize.toString(), - 'grp': gFFI.userModel.groupName.value, - 'target_user': username + 'target_user': user.id, }); final resp = await http.get(uri, headers: getHttpHeaders()); if (resp.body.isNotEmpty && resp.body.toLowerCase() != "null") { @@ -116,14 +163,16 @@ class GroupModel { if (json.containsKey('error')) { throw json['error']; } else { - if (total == 0) total = json['total']; - if (json.containsKey('data')) { - final data = json['data']; - if (data is List) { - for (final p in data) { - final peer = PeerPayload.fromJson(p); - peerPayloads.add(peer); - peersShow.add(PeerPayload.toPeer(peer)); + if (json.containsKey('total')) { + if (total == 0) total = json['total']; + if (json.containsKey('data')) { + final data = json['data']; + if (data is List) { + for (final p in data) { + final peer = PeerPayload.fromJson(p); + peerPayloads.add(peer); + peersShow.add(PeerPayload.toPeer(peer)); + } } } } @@ -131,7 +180,7 @@ class GroupModel { } } while (current * pageSize < total); } catch (err) { - debugPrint('$err'); + debugPrintStack(label: '$err'); peerLoadError.value = err.toString(); } finally { peerLoading.value = false; diff --git a/flutter/lib/models/peer_tab_model.dart b/flutter/lib/models/peer_tab_model.dart index 7c6211682..715da0c9c 100644 --- a/flutter/lib/models/peer_tab_model.dart +++ b/flutter/lib/models/peer_tab_model.dart @@ -88,8 +88,9 @@ class PeerTabModel with ChangeNotifier { groupTabIndex) { _currentTab = groupTabIndex; } - if (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isNotEmpty) { - tabNames[groupTabIndex] = gFFI.userModel.groupName.value; + if (gFFI.userModel.isAdmin.isFalse && + gFFI.groupModel.groupName.isNotEmpty) { + tabNames[groupTabIndex] = gFFI.groupModel.groupName.value; } else { tabNames[groupTabIndex] = defaultGroupTabname; } @@ -221,7 +222,7 @@ class PeerTabModel with ChangeNotifier { // return true if hide group card bool _filterGroupCard() { if (gFFI.groupModel.users.isEmpty || - (gFFI.userModel.isAdmin.isFalse && gFFI.userModel.groupName.isEmpty)) { + (gFFI.userModel.isAdmin.isFalse && gFFI.groupModel.groupName.isEmpty)) { return true; } else { return false; diff --git a/flutter/lib/models/user_model.dart b/flutter/lib/models/user_model.dart index e9da856d4..e7159a4de 100644 --- a/flutter/lib/models/user_model.dart +++ b/flutter/lib/models/user_model.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:flutter/material.dart'; import 'package:flutter_hbb/common/hbbs/hbbs.dart'; import 'package:flutter_hbb/common/widgets/peer_tab_page.dart'; import 'package:get/get.dart'; @@ -12,7 +13,6 @@ import 'platform_model.dart'; class UserModel { final RxString userName = ''.obs; - final RxString groupName = ''.obs; final RxBool isAdmin = false.obs; WeakReference parent; @@ -61,13 +61,11 @@ class UserModel { await gFFI.abModel.reset(); await gFFI.groupModel.reset(); userName.value = ''; - groupName.value = ''; gFFI.peerTabModel.check_dynamic_tabs(); } Future _parseAndUpdateUser(UserPayload user) async { userName.value = user.name; - groupName.value = user.grp; isAdmin.value = user.isAdmin; } @@ -133,9 +131,9 @@ class UserModel { } static Future> queryLoginOptions() async { - final url = await bind.mainGetApiServer(); - final resp = await http.get(Uri.parse('$url/api/login-options')); try { + final url = await bind.mainGetApiServer(); + final resp = await http.get(Uri.parse('$url/api/login-options')); return jsonDecode(resp.body); } catch (e) { print("queryLoginOptions: jsonDecode resp body failed: ${e.toString()}");