2022-12-11 21:40:35 +08:00
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
import 'package:flutter_hbb/common.dart';
|
|
|
|
import 'package:flutter_hbb/common/hbbs/hbbs.dart';
|
2023-09-14 10:17:03 +08:00
|
|
|
import 'package:flutter_hbb/common/widgets/peers_view.dart';
|
2022-12-11 21:40:35 +08:00
|
|
|
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 'package:http/http.dart' as http;
|
|
|
|
|
|
|
|
class GroupModel {
|
2023-06-17 20:48:58 +08:00
|
|
|
final RxBool groupLoading = false.obs;
|
|
|
|
final RxString groupLoadError = "".obs;
|
2022-12-11 21:40:35 +08:00
|
|
|
final RxList<UserPayload> users = RxList.empty(growable: true);
|
2023-09-14 10:17:03 +08:00
|
|
|
final RxList<Peer> peers = RxList.empty(growable: true);
|
2023-06-21 09:30:32 +08:00
|
|
|
final RxString selectedUser = ''.obs;
|
|
|
|
final RxString searchUserText = ''.obs;
|
2022-12-11 21:40:35 +08:00
|
|
|
WeakReference<FFI> parent;
|
2023-06-23 15:10:10 +08:00
|
|
|
var initialized = false;
|
2023-09-14 10:17:03 +08:00
|
|
|
var _cacheLoadOnceFlag = false;
|
|
|
|
var _statusCode = 200;
|
2022-12-11 21:40:35 +08:00
|
|
|
|
2023-09-14 10:17:03 +08:00
|
|
|
bool get emtpy => users.isEmpty && peers.isEmpty;
|
2022-12-11 21:40:35 +08:00
|
|
|
|
2023-09-14 10:17:03 +08:00
|
|
|
GroupModel(this.parent);
|
2022-12-11 21:40:35 +08:00
|
|
|
|
2023-06-23 17:05:48 +08:00
|
|
|
Future<void> pull({force = true, quiet = false}) async {
|
2023-09-14 10:17:03 +08:00
|
|
|
if (!gFFI.userModel.isLogin || groupLoading.value) return;
|
2023-06-23 15:10:10 +08:00
|
|
|
if (!force && initialized) return;
|
2023-06-23 17:05:48 +08:00
|
|
|
if (!quiet) {
|
|
|
|
groupLoading.value = true;
|
|
|
|
groupLoadError.value = "";
|
|
|
|
}
|
2023-09-14 10:17:03 +08:00
|
|
|
try {
|
|
|
|
await _pull();
|
|
|
|
} catch (_) {}
|
2023-06-21 16:04:52 +08:00
|
|
|
groupLoading.value = false;
|
2023-06-23 15:10:10 +08:00
|
|
|
initialized = true;
|
2023-09-14 10:17:03 +08:00
|
|
|
platformFFI.tryHandle({'name': LoadEvent.group});
|
|
|
|
if (_statusCode == 401) {
|
|
|
|
gFFI.userModel.reset(resetOther: true);
|
|
|
|
} else {
|
|
|
|
_saveCache();
|
|
|
|
}
|
2023-06-21 16:04:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _pull() async {
|
2023-09-14 10:17:03 +08:00
|
|
|
List<UserPayload> tmpUsers = List.empty(growable: true);
|
|
|
|
if (!await _getUsers(tmpUsers)) {
|
2023-06-17 20:48:58 +08:00
|
|
|
return;
|
|
|
|
}
|
2023-09-14 10:17:03 +08:00
|
|
|
List<Peer> tmpPeers = List.empty(growable: true);
|
|
|
|
if (!await _getPeers(tmpPeers)) {
|
2023-06-17 20:48:58 +08:00
|
|
|
return;
|
|
|
|
}
|
2023-09-14 10:17:03 +08:00
|
|
|
// 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 {
|
2022-12-11 21:40:35 +08:00
|
|
|
final api = "${await bind.mainGetApiServer()}/api/users";
|
|
|
|
try {
|
|
|
|
var uri0 = Uri.parse(api);
|
2023-09-14 10:17:03 +08:00
|
|
|
final pageSize = 100;
|
2022-12-11 21:40:35 +08:00
|
|
|
var total = 0;
|
2022-12-23 10:36:18 +08:00
|
|
|
int current = 0;
|
2022-12-11 21:40:35 +08:00
|
|
|
do {
|
2022-12-23 10:36:18 +08:00
|
|
|
current += 1;
|
2022-12-11 21:40:35 +08:00
|
|
|
var uri = Uri(
|
|
|
|
scheme: uri0.scheme,
|
|
|
|
host: uri0.host,
|
|
|
|
path: uri0.path,
|
|
|
|
port: uri0.port,
|
|
|
|
queryParameters: {
|
|
|
|
'current': current.toString(),
|
|
|
|
'pageSize': pageSize.toString(),
|
2023-09-14 10:17:03 +08:00
|
|
|
'accessible': '',
|
|
|
|
'status': '1',
|
2022-12-11 21:40:35 +08:00
|
|
|
});
|
2023-01-06 18:26:19 +08:00
|
|
|
final resp = await http.get(uri, headers: getHttpHeaders());
|
2023-09-14 10:17:03 +08:00
|
|
|
_statusCode = resp.statusCode;
|
|
|
|
Map<String, dynamic> json =
|
|
|
|
_jsonDecodeResp(utf8.decode(resp.bodyBytes), resp.statusCode);
|
|
|
|
if (json.containsKey('error')) {
|
2023-09-18 14:36:55 +08:00
|
|
|
if (json['error'] == 'Admin required!' ||
|
|
|
|
json['error']
|
|
|
|
.toString()
|
|
|
|
.contains('ambiguous column name: status')) {
|
2023-09-14 10:17:03 +08:00
|
|
|
throw translate('upgrade_rustdesk_server_pro_to_{1.1.10}_tip');
|
2022-12-11 21:40:35 +08:00
|
|
|
} else {
|
2023-09-14 10:17:03 +08:00
|
|
|
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;
|
2022-12-11 21:40:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-12-23 10:36:18 +08:00
|
|
|
} while (current * pageSize < total);
|
2023-09-14 10:17:03 +08:00
|
|
|
return true;
|
2022-12-11 21:40:35 +08:00
|
|
|
} catch (err) {
|
2023-09-14 10:17:03 +08:00
|
|
|
debugPrint('get accessible users: $err');
|
2023-09-24 08:36:53 +08:00
|
|
|
groupLoadError.value =
|
|
|
|
'${translate('pull_group_failed_tip')}: ${translate(err.toString())}';
|
2022-12-11 21:40:35 +08:00
|
|
|
}
|
2023-06-17 20:48:58 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-09-14 10:17:03 +08:00
|
|
|
Future<bool> _getPeers(List<Peer> tmpPeers) async {
|
2022-12-11 21:40:35 +08:00
|
|
|
try {
|
2023-09-14 10:17:03 +08:00
|
|
|
final api = "${await bind.mainGetApiServer()}/api/peers";
|
2022-12-11 21:40:35 +08:00
|
|
|
var uri0 = Uri.parse(api);
|
2023-09-14 10:17:03 +08:00
|
|
|
final pageSize = 100;
|
2022-12-11 21:40:35 +08:00
|
|
|
var total = 0;
|
2022-12-23 10:36:18 +08:00
|
|
|
int current = 0;
|
2022-12-11 21:40:35 +08:00
|
|
|
do {
|
2022-12-23 10:36:18 +08:00
|
|
|
current += 1;
|
2023-09-19 12:03:45 +08:00
|
|
|
var queryParameters = {
|
|
|
|
'current': current.toString(),
|
|
|
|
'pageSize': pageSize.toString(),
|
|
|
|
'accessible': '',
|
|
|
|
'status': '1',
|
|
|
|
};
|
2022-12-11 21:40:35 +08:00
|
|
|
var uri = Uri(
|
|
|
|
scheme: uri0.scheme,
|
|
|
|
host: uri0.host,
|
|
|
|
path: uri0.path,
|
|
|
|
port: uri0.port,
|
2023-06-21 09:30:32 +08:00
|
|
|
queryParameters: queryParameters);
|
2023-01-06 18:26:19 +08:00
|
|
|
final resp = await http.get(uri, headers: getHttpHeaders());
|
2023-09-14 10:17:03 +08:00
|
|
|
_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;
|
|
|
|
}
|
2022-12-11 21:40:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-12-23 10:36:18 +08:00
|
|
|
} while (current * pageSize < total);
|
2023-09-14 10:17:03 +08:00
|
|
|
return true;
|
2022-12-11 21:40:35 +08:00
|
|
|
} catch (err) {
|
2023-09-14 10:17:03 +08:00
|
|
|
debugPrint('get accessible peers: $err');
|
2023-09-24 08:36:53 +08:00
|
|
|
groupLoadError.value =
|
|
|
|
'${translate('pull_group_failed_tip')}: ${translate(err.toString())}';
|
2023-09-14 10:17:03 +08:00
|
|
|
}
|
|
|
|
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');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-24 17:56:35 +08:00
|
|
|
Future<void> loadCache() async {
|
2023-09-14 10:17:03 +08:00
|
|
|
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();
|
2022-12-11 21:40:35 +08:00
|
|
|
}
|
|
|
|
}
|