Merge pull request #5404 from 21pages/ab
fix ab ui not updating immediately
This commit is contained in:
commit
1141b99cf4
@ -48,13 +48,14 @@ class _AddressBookState extends State<AddressBook> {
|
|||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
_buildNotEmptyLoading(),
|
_buildNotEmptyLoading(),
|
||||||
|
_buildRetryProgress(),
|
||||||
_buildErrorBanner(
|
_buildErrorBanner(
|
||||||
err: gFFI.abModel.pullError,
|
err: gFFI.abModel.pullError,
|
||||||
retry: null,
|
retry: null,
|
||||||
close: () => gFFI.abModel.pullError.value = ''),
|
close: () => gFFI.abModel.pullError.value = ''),
|
||||||
_buildErrorBanner(
|
_buildErrorBanner(
|
||||||
err: gFFI.abModel.pushError,
|
err: gFFI.abModel.pushError,
|
||||||
retry: () => gFFI.abModel.pushAb(),
|
retry: () => gFFI.abModel.pushAb(isRetry: true),
|
||||||
close: () => gFFI.abModel.pushError.value = ''),
|
close: () => gFFI.abModel.pushError.value = ''),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: isDesktop
|
child: isDesktop
|
||||||
@ -136,6 +137,13 @@ class _AddressBookState extends State<AddressBook> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildRetryProgress() {
|
||||||
|
return Obx(() => Offstage(
|
||||||
|
offstage: !gFFI.abModel.retrying.value,
|
||||||
|
child: LinearProgressIndicator(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildAddressBookDesktop() {
|
Widget _buildAddressBookDesktop() {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
@ -339,7 +347,7 @@ class _AddressBookState extends State<AddressBook> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gFFI.abModel.addId(id, aliasController.text.trim(), selectedTag);
|
gFFI.abModel.addId(id, aliasController.text.trim(), selectedTag);
|
||||||
await gFFI.abModel.pushAb();
|
gFFI.abModel.pushAb();
|
||||||
this.setState(() {});
|
this.setState(() {});
|
||||||
// final currentPeers
|
// final currentPeers
|
||||||
}
|
}
|
||||||
@ -448,7 +456,7 @@ class _AddressBookState extends State<AddressBook> {
|
|||||||
for (final tag in tags) {
|
for (final tag in tags) {
|
||||||
gFFI.abModel.addTag(tag);
|
gFFI.abModel.addTag(tag);
|
||||||
}
|
}
|
||||||
await gFFI.abModel.pushAb();
|
gFFI.abModel.pushAb();
|
||||||
// final currentPeers
|
// final currentPeers
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/dialog.dart';
|
import 'package:flutter_hbb/common/widgets/dialog.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
|
import 'package:flutter_hbb/models/ab_model.dart';
|
||||||
import 'package:flutter_hbb/models/peer_tab_model.dart';
|
import 'package:flutter_hbb/models/peer_tab_model.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@ -582,6 +584,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
proc: () {
|
proc: () {
|
||||||
bind.mainCreateShortcut(id: id);
|
bind.mainCreateShortcut(id: id);
|
||||||
|
showToast(translate('Successful'));
|
||||||
},
|
},
|
||||||
padding: menuPadding,
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
@ -597,6 +600,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
await bind.mainSetPeerOption(
|
await bind.mainSetPeerOption(
|
||||||
id: id, key: key, value: bool2option(key, v));
|
id: id, key: key, value: bool2option(key, v));
|
||||||
|
showToast(translate('Successful'));
|
||||||
},
|
},
|
||||||
padding: menuPadding,
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
@ -633,6 +637,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
id: id,
|
id: id,
|
||||||
key: kOptionForceAlwaysRelay,
|
key: kOptionForceAlwaysRelay,
|
||||||
value: bool2option(kOptionForceAlwaysRelay, v));
|
value: bool2option(kOptionForceAlwaysRelay, v));
|
||||||
|
showToast(translate('Successful'));
|
||||||
},
|
},
|
||||||
padding: menuPadding,
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
@ -657,6 +662,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
gFFI.abModel.pushAb();
|
gFFI.abModel.pushAb();
|
||||||
} else {
|
} else {
|
||||||
await bind.mainSetPeerAlias(id: id, alias: newName);
|
await bind.mainSetPeerAlias(id: id, alias: newName);
|
||||||
|
showToast(translate('Successful'));
|
||||||
_update();
|
_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -706,11 +712,25 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
break;
|
break;
|
||||||
case PeerTabIndex.ab:
|
case PeerTabIndex.ab:
|
||||||
gFFI.abModel.deletePeer(id);
|
gFFI.abModel.deletePeer(id);
|
||||||
await gFFI.abModel.pushAb();
|
final future = gFFI.abModel.pushAb();
|
||||||
|
if (shouldSyncAb() && await bind.mainPeerExists(id: peer.id)) {
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
|
final succ = await future;
|
||||||
|
if (succ) {
|
||||||
|
await Future.delayed(Duration(seconds: 2)); // success msg
|
||||||
|
BotToast.showText(
|
||||||
|
contentColor: Colors.lightBlue,
|
||||||
|
text: translate('synced_peer_readded_tip'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PeerTabIndex.group:
|
case PeerTabIndex.group:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (tab != PeerTabIndex.ab) {
|
||||||
|
showToast(translate('Successful'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deletePeerConfirmDialog(onSubmit,
|
deletePeerConfirmDialog(onSubmit,
|
||||||
@ -730,6 +750,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
proc: () {
|
proc: () {
|
||||||
bind.mainForgetPassword(id: id);
|
bind.mainForgetPassword(id: id);
|
||||||
|
showToast(translate('Successful'));
|
||||||
},
|
},
|
||||||
padding: menuPadding,
|
padding: menuPadding,
|
||||||
dismissOnClicked: true,
|
dismissOnClicked: true,
|
||||||
@ -762,6 +783,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
favs.add(id);
|
favs.add(id);
|
||||||
await bind.mainStoreFav(favs: favs);
|
await bind.mainStoreFav(favs: favs);
|
||||||
}
|
}
|
||||||
|
showToast(translate('Successful'));
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
padding: menuPadding,
|
padding: menuPadding,
|
||||||
@ -796,6 +818,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
await bind.mainStoreFav(favs: favs);
|
await bind.mainStoreFav(favs: favs);
|
||||||
await reloadFunc();
|
await reloadFunc();
|
||||||
}
|
}
|
||||||
|
showToast(translate('Successful'));
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
padding: menuPadding,
|
padding: menuPadding,
|
||||||
@ -817,7 +840,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
if (!gFFI.abModel.idContainBy(peer.id)) {
|
if (!gFFI.abModel.idContainBy(peer.id)) {
|
||||||
gFFI.abModel.addPeer(peer);
|
gFFI.abModel.addPeer(peer);
|
||||||
await gFFI.abModel.pushAb();
|
gFFI.abModel.pushAb();
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
},
|
},
|
||||||
@ -1049,7 +1072,7 @@ class AddressBookPeerCard extends BasePeerCard {
|
|||||||
proc: () {
|
proc: () {
|
||||||
editAbTagDialog(gFFI.abModel.getPeerTags(id), (selectedTag) async {
|
editAbTagDialog(gFFI.abModel.getPeerTags(id), (selectedTag) async {
|
||||||
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
||||||
await gFFI.abModel.pushAb();
|
gFFI.abModel.pushAb();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
padding: super.menuPadding,
|
padding: super.menuPadding,
|
||||||
@ -1121,6 +1144,7 @@ void _rdpDialog(String id) async {
|
|||||||
id: id, key: 'rdp_username', value: username);
|
id: id, key: 'rdp_username', value: username);
|
||||||
await bind.mainSetPeerOption(
|
await bind.mainSetPeerOption(
|
||||||
id: id, key: 'rdp_password', value: password);
|
id: id, key: 'rdp_password', value: password);
|
||||||
|
showToast(translate('Successful'));
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/address_book.dart';
|
import 'package:flutter_hbb/common/widgets/address_book.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/dialog.dart';
|
import 'package:flutter_hbb/common/widgets/dialog.dart';
|
||||||
@ -7,6 +8,7 @@ import 'package:flutter_hbb/common/widgets/peer_card.dart';
|
|||||||
import 'package:flutter_hbb/common/widgets/animated_rotation_widget.dart';
|
import 'package:flutter_hbb/common/widgets/animated_rotation_widget.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
import 'package:flutter_hbb/desktop/widgets/popup_menu.dart';
|
import 'package:flutter_hbb/desktop/widgets/popup_menu.dart';
|
||||||
|
import 'package:flutter_hbb/models/ab_model.dart';
|
||||||
|
|
||||||
import 'package:flutter_hbb/models/peer_tab_model.dart';
|
import 'package:flutter_hbb/models/peer_tab_model.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@ -126,8 +128,7 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.tag_rounded,
|
Icons.tag_rounded,
|
||||||
size: 18,
|
size: 18,
|
||||||
))
|
)))),
|
||||||
)),
|
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await bind.mainSetLocalOption(
|
await bind.mainSetLocalOption(
|
||||||
key: "hideAbTagsPanel",
|
key: "hideAbTagsPanel",
|
||||||
@ -226,8 +227,7 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
Icons.refresh,
|
Icons.refresh,
|
||||||
size: 18,
|
size: 18,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
))
|
)))),
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -264,8 +264,7 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
: Icons.grid_view_rounded,
|
: Icons.grid_view_rounded,
|
||||||
size: 18,
|
size: 18,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
))
|
)))),
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,14 +333,36 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
await bind.mainLoadLanPeers();
|
await bind.mainLoadLanPeers();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
{
|
||||||
|
bool hasSynced = false;
|
||||||
|
if (shouldSyncAb()) {
|
||||||
|
for (var p in peers) {
|
||||||
|
if (await bind.mainPeerExists(id: p.id)) {
|
||||||
|
hasSynced = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
gFFI.abModel.deletePeers(peers.map((p) => p.id).toList());
|
gFFI.abModel.deletePeers(peers.map((p) => p.id).toList());
|
||||||
await gFFI.abModel.pushAb();
|
final future = gFFI.abModel.pushAb();
|
||||||
|
if (hasSynced) {
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
|
final succ = await future;
|
||||||
|
if (succ) {
|
||||||
|
await Future.delayed(
|
||||||
|
Duration(seconds: 2)); // success msg
|
||||||
|
BotToast.showText(
|
||||||
|
contentColor: Colors.lightBlue,
|
||||||
|
text: translate('synced_peer_readded_tip'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gFFI.peerTabModel.setMultiSelectionMode(false);
|
gFFI.peerTabModel.setMultiSelectionMode(false);
|
||||||
showToast(translate('Successful'));
|
if (model.currentTab != 3) showToast(translate('Successful'));
|
||||||
}
|
}
|
||||||
|
|
||||||
deletePeerConfirmDialog(onSubmit, translate('Delete'));
|
deletePeerConfirmDialog(onSubmit, translate('Delete'));
|
||||||
@ -384,11 +405,18 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
!gFFI.userModel.isLogin || model.currentTab == PeerTabIndex.ab.index,
|
!gFFI.userModel.isLogin || model.currentTab == PeerTabIndex.ab.index,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
if (gFFI.abModel.isFull(true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final peers = model.selectedPeers;
|
final peers = model.selectedPeers;
|
||||||
gFFI.abModel.addPeers(peers);
|
gFFI.abModel.addPeers(peers);
|
||||||
gFFI.abModel.pushAb();
|
final future = gFFI.abModel.pushAb();
|
||||||
model.setMultiSelectionMode(false);
|
model.setMultiSelectionMode(false);
|
||||||
showToast(translate('Successful'));
|
Future.delayed(Duration.zero, () async {
|
||||||
|
await future;
|
||||||
|
await Future.delayed(Duration(seconds: 2)); // toast
|
||||||
|
gFFI.abModel.isFull(true);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: translate('Add to Address Book'),
|
message: translate('Add to Address Book'),
|
||||||
@ -483,8 +511,7 @@ class _PeerSearchBarState extends State<PeerSearchBar> {
|
|||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.search_rounded,
|
Icons.search_rounded,
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
))
|
)));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSearchBar() {
|
Widget _buildSearchBar() {
|
||||||
@ -554,8 +581,7 @@ class _PeerSearchBarState extends State<PeerSearchBar> {
|
|||||||
},
|
},
|
||||||
icon: Tooltip(
|
icon: Tooltip(
|
||||||
message: translate('Close'),
|
message: translate('Close'),
|
||||||
child:
|
child: Icon(
|
||||||
Icon(
|
|
||||||
Icons.close,
|
Icons.close,
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
)),
|
)),
|
||||||
|
@ -30,6 +30,7 @@ class AbModel {
|
|||||||
final tags = [].obs;
|
final tags = [].obs;
|
||||||
final peers = List<Peer>.empty(growable: true).obs;
|
final peers = List<Peer>.empty(growable: true).obs;
|
||||||
final sortTags = shouldSortTags().obs;
|
final sortTags = shouldSortTags().obs;
|
||||||
|
final retrying = false.obs;
|
||||||
bool get emtpy => peers.isEmpty && tags.isEmpty;
|
bool get emtpy => peers.isEmpty && tags.isEmpty;
|
||||||
|
|
||||||
final selectedTags = List<String>.empty(growable: true).obs;
|
final selectedTags = List<String>.empty(growable: true).obs;
|
||||||
@ -55,10 +56,11 @@ class AbModel {
|
|||||||
if (gFFI.userModel.userName.isEmpty) return;
|
if (gFFI.userModel.userName.isEmpty) return;
|
||||||
if (abLoading.value) return;
|
if (abLoading.value) return;
|
||||||
if (!force && initialized) return;
|
if (!force && initialized) return;
|
||||||
|
DateTime startTime = DateTime.now();
|
||||||
if (pushError.isNotEmpty) {
|
if (pushError.isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
// push to retry
|
// push to retry
|
||||||
pushAb(toast: false);
|
pushAb(toastIfFail: false, toastIfSucc: false);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
@ -112,14 +114,14 @@ class AbModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (initialized) {
|
var ms =
|
||||||
// make loading effect obvious
|
(Duration(milliseconds: 300) - DateTime.now().difference(startTime))
|
||||||
Future.delayed(Duration(milliseconds: 300), () {
|
.inMilliseconds;
|
||||||
|
ms = ms > 0 ? ms : 0;
|
||||||
|
Future.delayed(Duration(milliseconds: ms), () {
|
||||||
abLoading.value = false;
|
abLoading.value = false;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
abLoading.value = false;
|
|
||||||
}
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
_syncAllFromRecent = true;
|
_syncAllFromRecent = true;
|
||||||
_timerCounter = 0;
|
_timerCounter = 0;
|
||||||
@ -161,11 +163,17 @@ class AbModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPeers(List<Peer> ps) {
|
bool addPeers(List<Peer> ps) {
|
||||||
|
bool allAdded = true;
|
||||||
for (var p in ps) {
|
for (var p in ps) {
|
||||||
|
if (!isFull(false)) {
|
||||||
addPeer(p);
|
addPeer(p);
|
||||||
|
} else {
|
||||||
|
allAdded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return allAdded;
|
||||||
|
}
|
||||||
|
|
||||||
void addTag(String tag) async {
|
void addTag(String tag) async {
|
||||||
if (tagContainBy(tag)) {
|
if (tagContainBy(tag)) {
|
||||||
@ -198,13 +206,22 @@ class AbModel {
|
|||||||
it.first.alias = alias;
|
it.first.alias = alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pushAb({bool toast = true}) async {
|
Future<bool> pushAb(
|
||||||
debugPrint("pushAb");
|
{bool toastIfFail = true,
|
||||||
|
bool toastIfSucc = true,
|
||||||
|
bool isRetry = false}) async {
|
||||||
|
debugPrint(
|
||||||
|
"pushAb: toastIfFail:$toastIfFail, toastIfSucc:$toastIfSucc, isRetry:$isRetry");
|
||||||
pushError.value = '';
|
pushError.value = '';
|
||||||
|
if (isRetry) retrying.value = true;
|
||||||
|
DateTime startTime = DateTime.now();
|
||||||
|
bool ret = false;
|
||||||
try {
|
try {
|
||||||
// avoid double pushes in a row
|
// avoid double pushes in a row
|
||||||
_syncAllFromRecent = true;
|
_syncAllFromRecent = true;
|
||||||
syncFromRecent(push: false);
|
await syncFromRecent(push: false);
|
||||||
|
//https: //stackoverflow.com/questions/68249333/flutter-getx-updating-item-in-children-list-is-not-reactive
|
||||||
|
peers.refresh();
|
||||||
final api = "${await bind.mainGetApiServer()}/api/ab";
|
final api = "${await bind.mainGetApiServer()}/api/ab";
|
||||||
var authHeaders = getHttpHeaders();
|
var authHeaders = getHttpHeaders();
|
||||||
authHeaders['Content-Type'] = "application/json";
|
authHeaders['Content-Type'] = "application/json";
|
||||||
@ -224,12 +241,14 @@ class AbModel {
|
|||||||
}
|
}
|
||||||
if (resp.statusCode == 200 &&
|
if (resp.statusCode == 200 &&
|
||||||
(resp.body.isEmpty || resp.body.toLowerCase() == 'null')) {
|
(resp.body.isEmpty || resp.body.toLowerCase() == 'null')) {
|
||||||
|
ret = true;
|
||||||
_saveCache();
|
_saveCache();
|
||||||
} else {
|
} else {
|
||||||
Map<String, dynamic> json = _jsonDecode(resp.body, resp.statusCode);
|
Map<String, dynamic> json = _jsonDecode(resp.body, resp.statusCode);
|
||||||
if (json.containsKey('error')) {
|
if (json.containsKey('error')) {
|
||||||
throw json['error'];
|
throw json['error'];
|
||||||
} else if (resp.statusCode == 200) {
|
} else if (resp.statusCode == 200) {
|
||||||
|
ret = true;
|
||||||
_saveCache();
|
_saveCache();
|
||||||
} else {
|
} else {
|
||||||
throw 'HTTP ${resp.statusCode}';
|
throw 'HTTP ${resp.statusCode}';
|
||||||
@ -238,12 +257,25 @@ class AbModel {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
pushError.value =
|
pushError.value =
|
||||||
'${translate('push_ab_failed_tip')}: ${translate(e.toString())}';
|
'${translate('push_ab_failed_tip')}: ${translate(e.toString())}';
|
||||||
if (toast && gFFI.peerTabModel.currentTab != PeerTabIndex.ab.index) {
|
}
|
||||||
|
_syncAllFromRecent = true;
|
||||||
|
if (isRetry) {
|
||||||
|
var ms =
|
||||||
|
(Duration(milliseconds: 200) - DateTime.now().difference(startTime))
|
||||||
|
.inMilliseconds;
|
||||||
|
ms = ms > 0 ? ms : 0;
|
||||||
|
Future.delayed(Duration(milliseconds: ms), () {
|
||||||
|
retrying.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret && toastIfFail) {
|
||||||
BotToast.showText(contentColor: Colors.red, text: pushError.value);
|
BotToast.showText(contentColor: Colors.red, text: pushError.value);
|
||||||
}
|
}
|
||||||
} finally {
|
if (ret && toastIfSucc) {
|
||||||
_syncAllFromRecent = true;
|
showToast(translate('Successful'));
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Peer? find(String id) {
|
Peer? find(String id) {
|
||||||
@ -333,42 +365,37 @@ class AbModel {
|
|||||||
rdpUsername: r.rdpUsername);
|
rdpUsername: r.rdpUsername);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncFromRecent({bool push = true}) async {
|
Future<void> syncFromRecent({bool push = true}) async {
|
||||||
if (!_syncFromRecentLock) {
|
if (!_syncFromRecentLock) {
|
||||||
_syncFromRecentLock = true;
|
_syncFromRecentLock = true;
|
||||||
_syncFromRecentWithoutLock(push: push);
|
await _syncFromRecentWithoutLock(push: push);
|
||||||
_syncFromRecentLock = false;
|
_syncFromRecentLock = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _syncFromRecentWithoutLock({bool push = true}) async {
|
Future<void> _syncFromRecentWithoutLock({bool push = true}) async {
|
||||||
bool shouldSync(Peer a, Peer b) {
|
bool shouldSync(Peer r, Peer p) {
|
||||||
return a.hash != b.hash ||
|
return r.hash != p.hash ||
|
||||||
a.username != b.username ||
|
r.username != p.username ||
|
||||||
a.platform != b.platform ||
|
r.platform != p.platform ||
|
||||||
a.hostname != b.hostname ||
|
r.hostname != p.hostname ||
|
||||||
a.alias != b.alias;
|
(p.alias.isEmpty && r.alias.isNotEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Peer>> getRecentPeers() async {
|
Future<List<Peer>> getRecentPeers() async {
|
||||||
try {
|
try {
|
||||||
if (peers.isEmpty) [];
|
|
||||||
List<String> filteredPeerIDs;
|
List<String> filteredPeerIDs;
|
||||||
if (_syncAllFromRecent) {
|
if (_syncAllFromRecent) {
|
||||||
_syncAllFromRecent = false;
|
_syncAllFromRecent = false;
|
||||||
filteredPeerIDs = peers.map((e) => e.id).toList();
|
filteredPeerIDs = [];
|
||||||
} else {
|
} else {
|
||||||
final new_stored_str = await bind.mainGetNewStoredPeers();
|
final new_stored_str = await bind.mainGetNewStoredPeers();
|
||||||
if (new_stored_str.isEmpty) return [];
|
if (new_stored_str.isEmpty) return [];
|
||||||
List<String> new_stores =
|
filteredPeerIDs = (jsonDecode(new_stored_str) as List<dynamic>)
|
||||||
(jsonDecode(new_stored_str) as List<dynamic>)
|
|
||||||
.map((e) => e.toString())
|
.map((e) => e.toString())
|
||||||
.toList();
|
.toList();
|
||||||
final abPeerIds = peers.map((e) => e.id).toList();
|
|
||||||
filteredPeerIDs =
|
|
||||||
new_stores.where((e) => abPeerIds.contains(e)).toList();
|
|
||||||
}
|
|
||||||
if (filteredPeerIDs.isEmpty) return [];
|
if (filteredPeerIDs.isEmpty) return [];
|
||||||
|
}
|
||||||
final loadStr = await bind.mainLoadRecentPeersForAb(
|
final loadStr = await bind.mainLoadRecentPeersForAb(
|
||||||
filter: jsonEncode(filteredPeerIDs));
|
filter: jsonEncode(filteredPeerIDs));
|
||||||
if (loadStr.isEmpty) {
|
if (loadStr.isEmpty) {
|
||||||
@ -390,28 +417,34 @@ class AbModel {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (!shouldSyncAb()) return;
|
if (!shouldSyncAb()) return;
|
||||||
final oldPeers = peers.toList();
|
|
||||||
final recents = await getRecentPeers();
|
final recents = await getRecentPeers();
|
||||||
if (recents.isEmpty) return;
|
if (recents.isEmpty) return;
|
||||||
for (var i = 0; i < peers.length; i++) {
|
bool syncChanged = false;
|
||||||
var p = peers[i];
|
bool uiChanged = false;
|
||||||
var r = recents.firstWhereOrNull((r) => p.id == r.id);
|
for (var i = 0; i < recents.length; i++) {
|
||||||
if (r != null) {
|
var r = recents[i];
|
||||||
peers[i] = merge(r, p);
|
var index = peers.indexWhere((e) => e.id == r.id);
|
||||||
|
if (index < 0) {
|
||||||
|
if (!isFull(false)) {
|
||||||
|
peers.add(r);
|
||||||
|
syncChanged = true;
|
||||||
|
uiChanged = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!r.equal(peers[index])) {
|
||||||
|
uiChanged = true;
|
||||||
}
|
}
|
||||||
bool changed = false;
|
if (shouldSync(r, peers[index])) {
|
||||||
for (var i = 0; i < peers.length; i++) {
|
syncChanged = true;
|
||||||
final o = oldPeers[i];
|
}
|
||||||
final p = peers[i];
|
peers[index] = merge(r, peers[index]);
|
||||||
if (shouldSync(o, p)) {
|
|
||||||
changed = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Be careful with loop calls
|
// Be careful with loop calls
|
||||||
if (changed && push) {
|
if (syncChanged && push) {
|
||||||
pushAb();
|
pushAb(toastIfSucc: false);
|
||||||
|
} else if (uiChanged) {
|
||||||
|
peers.refresh();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('syncFromRecent:$e');
|
debugPrint('syncFromRecent:$e');
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'platform_model.dart';
|
import 'platform_model.dart';
|
||||||
|
// ignore: depend_on_referenced_packages
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
class Peer {
|
class Peer {
|
||||||
final String id;
|
final String id;
|
||||||
@ -87,6 +89,18 @@ class Peer {
|
|||||||
rdpPort: '',
|
rdpPort: '',
|
||||||
rdpUsername: '',
|
rdpUsername: '',
|
||||||
);
|
);
|
||||||
|
bool equal(Peer other) {
|
||||||
|
return id == other.id &&
|
||||||
|
hash == other.hash &&
|
||||||
|
username == other.username &&
|
||||||
|
hostname == other.hostname &&
|
||||||
|
platform == other.platform &&
|
||||||
|
alias == other.alias &&
|
||||||
|
tags.equals(other.tags) &&
|
||||||
|
forceAlwaysRelay == other.forceAlwaysRelay &&
|
||||||
|
rdpPort == other.rdpPort &&
|
||||||
|
rdpUsername == other.rdpUsername;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpdateEvent { online, load }
|
enum UpdateEvent { online, load }
|
||||||
|
@ -1079,6 +1079,10 @@ impl PeerConfig {
|
|||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exists(id: &str) -> bool {
|
||||||
|
Self::path(id).exists()
|
||||||
|
}
|
||||||
|
|
||||||
serde_field_string!(
|
serde_field_string!(
|
||||||
default_view_style,
|
default_view_style,
|
||||||
deserialize_view_style,
|
deserialize_view_style,
|
||||||
|
@ -841,6 +841,10 @@ pub fn main_peer_has_password(id: String) -> bool {
|
|||||||
peer_has_password(id)
|
peer_has_password(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main_peer_exists(id: String) -> bool {
|
||||||
|
peer_exists(&id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_load_recent_peers() {
|
pub fn main_load_recent_peers() {
|
||||||
if !config::APP_DIR.read().unwrap().is_empty() {
|
if !config::APP_DIR.read().unwrap().is_empty() {
|
||||||
let peers: Vec<HashMap<&str, String>> = PeerConfig::peers(None)
|
let peers: Vec<HashMap<&str, String>> = PeerConfig::peers(None)
|
||||||
@ -883,8 +887,13 @@ pub fn main_load_recent_peers_sync() -> SyncReturn<String> {
|
|||||||
|
|
||||||
pub fn main_load_recent_peers_for_ab(filter: String) -> String {
|
pub fn main_load_recent_peers_for_ab(filter: String) -> String {
|
||||||
let id_filters = serde_json::from_str::<Vec<String>>(&filter).unwrap_or_default();
|
let id_filters = serde_json::from_str::<Vec<String>>(&filter).unwrap_or_default();
|
||||||
|
let id_filters = if id_filters.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(id_filters)
|
||||||
|
};
|
||||||
if !config::APP_DIR.read().unwrap().is_empty() {
|
if !config::APP_DIR.read().unwrap().is_empty() {
|
||||||
let peers: Vec<HashMap<&str, String>> = PeerConfig::peers(Some(id_filters))
|
let peers: Vec<HashMap<&str, String>> = PeerConfig::peers(id_filters)
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|(id, _, p)| peer_to_map_ab(id, p))
|
.map(|(id, _, p)| peer_to_map_ab(id, p))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", "未成功获取地址簿"),
|
("pull_ab_failed_tip", "未成功获取地址簿"),
|
||||||
("push_ab_failed_tip", "未成功上传地址簿"),
|
("push_ab_failed_tip", "未成功上传地址簿"),
|
||||||
|
("synced_peer_readded_tip", "最近会话中存在的设备将会被重新添加到地址簿。"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", "Tags umschalten"),
|
("Toggle Tags", "Tags umschalten"),
|
||||||
("pull_ab_failed_tip", "Aktualisierung des Adressbuchs fehlgeschlagen"),
|
("pull_ab_failed_tip", "Aktualisierung des Adressbuchs fehlgeschlagen"),
|
||||||
("push_ab_failed_tip", "Synchronisierung des Adressbuchs mit dem Server fehlgeschlagen"),
|
("push_ab_failed_tip", "Synchronisierung des Adressbuchs mit dem Server fehlgeschlagen"),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -76,5 +76,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("exceed_max_devices", "You have reached the maximum number of managed devices."),
|
("exceed_max_devices", "You have reached the maximum number of managed devices."),
|
||||||
("pull_ab_failed_tip", "Failed to refresh address book"),
|
("pull_ab_failed_tip", "Failed to refresh address book"),
|
||||||
("push_ab_failed_tip", "Failed to sync address book to server"),
|
("push_ab_failed_tip", "Failed to sync address book to server"),
|
||||||
|
("synced_peer_readded_tip", "The devices present in the recent sessions will be re-added to the address book."),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", "Alternar Etiquetas"),
|
("Toggle Tags", "Alternar Etiquetas"),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", "Attiva/disattiva tag"),
|
("Toggle Tags", "Attiva/disattiva tag"),
|
||||||
("pull_ab_failed_tip", "Impossibile aggiornare la rubrica"),
|
("pull_ab_failed_tip", "Impossibile aggiornare la rubrica"),
|
||||||
("push_ab_failed_tip", "Impossibile sincronizzare la rubrica con il server"),
|
("push_ab_failed_tip", "Impossibile sincronizzare la rubrica con il server"),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", "Переключить метки"),
|
("Toggle Tags", "Переключить метки"),
|
||||||
("pull_ab_failed_tip", "Невозможно обновить адресную книгу"),
|
("pull_ab_failed_tip", "Невозможно обновить адресную книгу"),
|
||||||
("push_ab_failed_tip", "Невозможно синхронизировать адресную книгу с сервером"),
|
("push_ab_failed_tip", "Невозможно синхронизировать адресную книгу с сервером"),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", "未成功獲取地址簿"),
|
("pull_ab_failed_tip", "未成功獲取地址簿"),
|
||||||
("push_ab_failed_tip", "未成功上傳地址簿"),
|
("push_ab_failed_tip", "未成功上傳地址簿"),
|
||||||
|
("synced_peer_readded_tip", "最近會話中存在的設備將會被重新添加到地址簿。"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -537,5 +537,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Toggle Tags", ""),
|
("Toggle Tags", ""),
|
||||||
("pull_ab_failed_tip", ""),
|
("pull_ab_failed_tip", ""),
|
||||||
("push_ab_failed_tip", ""),
|
("push_ab_failed_tip", ""),
|
||||||
|
("synced_peer_readded_tip", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -648,6 +648,11 @@ pub fn peer_to_map_ab(id: String, p: PeerConfig) -> HashMap<&'static str, String
|
|||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
pub fn peer_exists(id: &str) -> bool {
|
||||||
|
PeerConfig::exists(id)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_lan_peers() -> Vec<HashMap<&'static str, String>> {
|
pub fn get_lan_peers() -> Vec<HashMap<&'static str, String>> {
|
||||||
config::LanPeers::load()
|
config::LanPeers::load()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user