264 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/widgets.dart';
 | |
| import 'package:flutter_hbb/common.dart';
 | |
| import 'package:flutter_hbb/common/hbbs/hbbs.dart';
 | |
| import 'package:flutter_hbb/common/widgets/peers_view.dart';
 | |
| import 'package:flutter_hbb/models/model.dart';
 | |
| import 'package:flutter_hbb/models/peer_model.dart';
 | |
| import 'package:flutter_hbb/models/platform_model.dart';
 | |
| import 'package:get/get.dart';
 | |
| import 'dart:convert';
 | |
| import '../utils/http_service.dart' as http;
 | |
| 
 | |
| class GroupModel {
 | |
|   final RxBool groupLoading = false.obs;
 | |
|   final RxString groupLoadError = "".obs;
 | |
|   final RxList<UserPayload> users = RxList.empty(growable: true);
 | |
|   final RxList<Peer> peers = RxList.empty(growable: true);
 | |
|   final RxString selectedUser = ''.obs;
 | |
|   final RxString searchUserText = ''.obs;
 | |
|   WeakReference<FFI> parent;
 | |
|   var initialized = false;
 | |
|   var _cacheLoadOnceFlag = false;
 | |
|   var _statusCode = 200;
 | |
| 
 | |
|   bool get emtpy => users.isEmpty && peers.isEmpty;
 | |
| 
 | |
|   GroupModel(this.parent);
 | |
| 
 | |
|   Future<void> pull({force = true, quiet = false}) async {
 | |
|     if (bind.isDisableGroupPanel()) return;
 | |
|     if (!gFFI.userModel.isLogin || groupLoading.value) return;
 | |
|     if (!force && initialized) return;
 | |
|     if (!quiet) {
 | |
|       groupLoading.value = true;
 | |
|       groupLoadError.value = "";
 | |
|     }
 | |
|     try {
 | |
|       await _pull();
 | |
|     } catch (_) {}
 | |
|     groupLoading.value = false;
 | |
|     initialized = true;
 | |
|     platformFFI.tryHandle({'name': LoadEvent.group});
 | |
|     if (_statusCode == 401) {
 | |
|       gFFI.userModel.reset(resetOther: true);
 | |
|     } else {
 | |
|       _saveCache();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _pull() async {
 | |
|     List<UserPayload> tmpUsers = List.empty(growable: true);
 | |
|     if (!await _getUsers(tmpUsers)) {
 | |
|       return;
 | |
|     }
 | |
|     List<Peer> tmpPeers = List.empty(growable: true);
 | |
|     if (!await _getPeers(tmpPeers)) {
 | |
|       return;
 | |
|     }
 | |
|     // me first
 | |
|     var index = tmpUsers
 | |
|         .indexWhere((user) => user.name == gFFI.userModel.userName.value);
 | |
|     if (index != -1) {
 | |
|       var user = tmpUsers.removeAt(index);
 | |
|       tmpUsers.insert(0, user);
 | |
|     }
 | |
|     users.value = tmpUsers;
 | |
|     if (!users.any((u) => u.name == selectedUser.value)) {
 | |
|       selectedUser.value = '';
 | |
|     }
 | |
|     // recover online
 | |
|     final oldOnlineIDs = peers.where((e) => e.online).map((e) => e.id).toList();
 | |
|     peers.value = tmpPeers;
 | |
|     peers
 | |
|         .where((e) => oldOnlineIDs.contains(e.id))
 | |
|         .map((e) => e.online = true)
 | |
|         .toList();
 | |
|     groupLoadError.value = '';
 | |
|   }
 | |
| 
 | |
|   Future<bool> _getUsers(List<UserPayload> tmpUsers) async {
 | |
|     final api = "${await bind.mainGetApiServer()}/api/users";
 | |
|     try {
 | |
|       var uri0 = Uri.parse(api);
 | |
|       final pageSize = 100;
 | |
|       var total = 0;
 | |
|       int current = 0;
 | |
|       do {
 | |
|         current += 1;
 | |
|         var uri = Uri(
 | |
|             scheme: uri0.scheme,
 | |
|             host: uri0.host,
 | |
|             path: uri0.path,
 | |
|             port: uri0.port,
 | |
|             queryParameters: {
 | |
|               'current': current.toString(),
 | |
|               'pageSize': pageSize.toString(),
 | |
|               'accessible': '',
 | |
|               'status': '1',
 | |
|             });
 | |
|         final resp = await http.get(uri, headers: getHttpHeaders());
 | |
|         _statusCode = resp.statusCode;
 | |
|         Map<String, dynamic> json =
 | |
|             _jsonDecodeResp(utf8.decode(resp.bodyBytes), resp.statusCode);
 | |
|         if (json.containsKey('error')) {
 | |
|           if (json['error'] == 'Admin required!' ||
 | |
|               json['error']
 | |
|                   .toString()
 | |
|                   .contains('ambiguous column name: status')) {
 | |
|             throw translate('upgrade_rustdesk_server_pro_to_{1.1.10}_tip');
 | |
|           } else {
 | |
|             throw json['error'];
 | |
|           }
 | |
|         }
 | |
|         if (resp.statusCode != 200) {
 | |
|           throw 'HTTP ${resp.statusCode}';
 | |
|         }
 | |
|         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);
 | |
|                 int index = tmpUsers.indexWhere((e) => e.name == u.name);
 | |
|                 if (index < 0) {
 | |
|                   tmpUsers.add(u);
 | |
|                 } else {
 | |
|                   tmpUsers[index] = u;
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       } while (current * pageSize < total);
 | |
|       return true;
 | |
|     } catch (err) {
 | |
|       debugPrint('get accessible users: $err');
 | |
|       groupLoadError.value =
 | |
|           '${translate('pull_group_failed_tip')}: ${translate(err.toString())}';
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   Future<bool> _getPeers(List<Peer> tmpPeers) async {
 | |
|     try {
 | |
|       final api = "${await bind.mainGetApiServer()}/api/peers";
 | |
|       var uri0 = Uri.parse(api);
 | |
|       final pageSize = 100;
 | |
|       var total = 0;
 | |
|       int current = 0;
 | |
|       do {
 | |
|         current += 1;
 | |
|         var queryParameters = {
 | |
|           'current': current.toString(),
 | |
|           'pageSize': pageSize.toString(),
 | |
|           'accessible': '',
 | |
|           'status': '1',
 | |
|         };
 | |
|         var uri = Uri(
 | |
|             scheme: uri0.scheme,
 | |
|             host: uri0.host,
 | |
|             path: uri0.path,
 | |
|             port: uri0.port,
 | |
|             queryParameters: queryParameters);
 | |
|         final resp = await http.get(uri, headers: getHttpHeaders());
 | |
|         _statusCode = resp.statusCode;
 | |
| 
 | |
|         Map<String, dynamic> json =
 | |
|             _jsonDecodeResp(utf8.decode(resp.bodyBytes), resp.statusCode);
 | |
|         if (json.containsKey('error')) {
 | |
|           throw json['error'];
 | |
|         }
 | |
|         if (resp.statusCode != 200) {
 | |
|           throw 'HTTP ${resp.statusCode}';
 | |
|         }
 | |
|         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 peerPayload = PeerPayload.fromJson(p);
 | |
|                 final peer = PeerPayload.toPeer(peerPayload);
 | |
|                 int index = tmpPeers.indexWhere((e) => e.id == peer.id);
 | |
|                 if (index < 0) {
 | |
|                   tmpPeers.add(peer);
 | |
|                 } else {
 | |
|                   tmpPeers[index] = peer;
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       } while (current * pageSize < total);
 | |
|       return true;
 | |
|     } catch (err) {
 | |
|       debugPrint('get accessible peers: $err');
 | |
|       groupLoadError.value =
 | |
|           '${translate('pull_group_failed_tip')}: ${translate(err.toString())}';
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   Map<String, dynamic> _jsonDecodeResp(String body, int statusCode) {
 | |
|     try {
 | |
|       Map<String, dynamic> json = jsonDecode(body);
 | |
|       return json;
 | |
|     } catch (e) {
 | |
|       final err = body.isNotEmpty && body.length < 128 ? body : e.toString();
 | |
|       if (statusCode != 200) {
 | |
|         throw 'HTTP $statusCode, $err';
 | |
|       }
 | |
|       throw err;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void _saveCache() {
 | |
|     try {
 | |
|       final map = (<String, dynamic>{
 | |
|         "access_token": bind.mainGetLocalOption(key: 'access_token'),
 | |
|         "users": users.map((e) => e.toGroupCacheJson()).toList(),
 | |
|         'peers': peers.map((e) => e.toGroupCacheJson()).toList()
 | |
|       });
 | |
|       bind.mainSaveGroup(json: jsonEncode(map));
 | |
|     } catch (e) {
 | |
|       debugPrint('group save:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> loadCache() async {
 | |
|     try {
 | |
|       if (_cacheLoadOnceFlag || groupLoading.value || initialized) return;
 | |
|       _cacheLoadOnceFlag = true;
 | |
|       final access_token = bind.mainGetLocalOption(key: 'access_token');
 | |
|       if (access_token.isEmpty) return;
 | |
|       final cache = await bind.mainLoadGroup();
 | |
|       if (groupLoading.value) return;
 | |
|       final data = jsonDecode(cache);
 | |
|       if (data == null || data['access_token'] != access_token) return;
 | |
|       users.clear();
 | |
|       peers.clear();
 | |
|       if (data['users'] is List) {
 | |
|         for (var u in data['users']) {
 | |
|           users.add(UserPayload.fromJson(u));
 | |
|         }
 | |
|       }
 | |
|       if (data['peers'] is List) {
 | |
|         for (final peer in data['peers']) {
 | |
|           peers.add(Peer.fromJson(peer));
 | |
|         }
 | |
|       }
 | |
|     } catch (e) {
 | |
|       debugPrint("load group cache: $e");
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   reset() async {
 | |
|     groupLoadError.value = '';
 | |
|     users.clear();
 | |
|     peers.clear();
 | |
|     selectedUser.value = '';
 | |
|     await bind.mainClearGroup();
 | |
|   }
 | |
| }
 |