ab: opt reaction and message hint
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
553a3798a1
commit
1e75b172d6
@ -48,13 +48,14 @@ class _AddressBookState extends State<AddressBook> {
|
||||
return Column(
|
||||
children: [
|
||||
_buildNotEmptyLoading(),
|
||||
_buildRetryProgress(),
|
||||
_buildErrorBanner(
|
||||
err: gFFI.abModel.pullError,
|
||||
retry: null,
|
||||
close: () => gFFI.abModel.pullError.value = ''),
|
||||
_buildErrorBanner(
|
||||
err: gFFI.abModel.pushError,
|
||||
retry: () => gFFI.abModel.pushAb(),
|
||||
retry: () => gFFI.abModel.pushAb(isRetry: true),
|
||||
close: () => gFFI.abModel.pushError.value = ''),
|
||||
Expanded(
|
||||
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() {
|
||||
return Row(
|
||||
children: [
|
||||
@ -339,7 +347,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
return;
|
||||
}
|
||||
gFFI.abModel.addId(id, aliasController.text.trim(), selectedTag);
|
||||
await gFFI.abModel.pushAb();
|
||||
gFFI.abModel.pushAb();
|
||||
this.setState(() {});
|
||||
// final currentPeers
|
||||
}
|
||||
@ -448,7 +456,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
for (final tag in tags) {
|
||||
gFFI.abModel.addTag(tag);
|
||||
}
|
||||
await gFFI.abModel.pushAb();
|
||||
gFFI.abModel.pushAb();
|
||||
// final currentPeers
|
||||
}
|
||||
close();
|
||||
|
@ -584,6 +584,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
),
|
||||
proc: () {
|
||||
bind.mainCreateShortcut(id: id);
|
||||
showToast(translate('Successful'));
|
||||
},
|
||||
padding: menuPadding,
|
||||
dismissOnClicked: true,
|
||||
@ -599,6 +600,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
setter: (bool v) async {
|
||||
await bind.mainSetPeerOption(
|
||||
id: id, key: key, value: bool2option(key, v));
|
||||
showToast(translate('Successful'));
|
||||
},
|
||||
padding: menuPadding,
|
||||
dismissOnClicked: true,
|
||||
@ -635,6 +637,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
id: id,
|
||||
key: kOptionForceAlwaysRelay,
|
||||
value: bool2option(kOptionForceAlwaysRelay, v));
|
||||
showToast(translate('Successful'));
|
||||
},
|
||||
padding: menuPadding,
|
||||
dismissOnClicked: true,
|
||||
@ -659,6 +662,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
gFFI.abModel.pushAb();
|
||||
} else {
|
||||
await bind.mainSetPeerAlias(id: id, alias: newName);
|
||||
showToast(translate('Successful'));
|
||||
_update();
|
||||
}
|
||||
}
|
||||
@ -708,16 +712,25 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
break;
|
||||
case PeerTabIndex.ab:
|
||||
gFFI.abModel.deletePeer(id);
|
||||
await gFFI.abModel.pushAb();
|
||||
final future = gFFI.abModel.pushAb();
|
||||
if (shouldSyncAb() && await bind.mainPeerExists(id: peer.id)) {
|
||||
BotToast.showText(
|
||||
contentColor: Colors.lightBlue,
|
||||
text: translate('synced_peer_readded_tip'));
|
||||
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;
|
||||
case PeerTabIndex.group:
|
||||
break;
|
||||
}
|
||||
if (tab != PeerTabIndex.ab) {
|
||||
showToast(translate('Successful'));
|
||||
}
|
||||
}
|
||||
|
||||
deletePeerConfirmDialog(onSubmit,
|
||||
@ -737,6 +750,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
),
|
||||
proc: () {
|
||||
bind.mainForgetPassword(id: id);
|
||||
showToast(translate('Successful'));
|
||||
},
|
||||
padding: menuPadding,
|
||||
dismissOnClicked: true,
|
||||
@ -769,6 +783,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
favs.add(id);
|
||||
await bind.mainStoreFav(favs: favs);
|
||||
}
|
||||
showToast(translate('Successful'));
|
||||
}();
|
||||
},
|
||||
padding: menuPadding,
|
||||
@ -803,6 +818,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
await bind.mainStoreFav(favs: favs);
|
||||
await reloadFunc();
|
||||
}
|
||||
showToast(translate('Successful'));
|
||||
}();
|
||||
},
|
||||
padding: menuPadding,
|
||||
@ -824,7 +840,7 @@ abstract class BasePeerCard extends StatelessWidget {
|
||||
}
|
||||
if (!gFFI.abModel.idContainBy(peer.id)) {
|
||||
gFFI.abModel.addPeer(peer);
|
||||
await gFFI.abModel.pushAb();
|
||||
gFFI.abModel.pushAb();
|
||||
}
|
||||
}();
|
||||
},
|
||||
@ -1056,7 +1072,7 @@ class AddressBookPeerCard extends BasePeerCard {
|
||||
proc: () {
|
||||
editAbTagDialog(gFFI.abModel.getPeerTags(id), (selectedTag) async {
|
||||
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
||||
await gFFI.abModel.pushAb();
|
||||
gFFI.abModel.pushAb();
|
||||
});
|
||||
},
|
||||
padding: super.menuPadding,
|
||||
@ -1128,6 +1144,7 @@ void _rdpDialog(String id) async {
|
||||
id: id, key: 'rdp_username', value: username);
|
||||
await bind.mainSetPeerOption(
|
||||
id: id, key: 'rdp_password', value: password);
|
||||
showToast(translate('Successful'));
|
||||
close();
|
||||
}
|
||||
|
||||
|
@ -343,12 +343,17 @@ class _PeerTabPageState extends State<PeerTabPage>
|
||||
}
|
||||
}
|
||||
gFFI.abModel.deletePeers(peers.map((p) => p.id).toList());
|
||||
await gFFI.abModel.pushAb();
|
||||
final future = gFFI.abModel.pushAb();
|
||||
if (hasSynced) {
|
||||
Future.delayed(Duration(seconds: 2), () {
|
||||
BotToast.showText(
|
||||
contentColor: Colors.lightBlue,
|
||||
text: translate('synced_peer_readded_tip'));
|
||||
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'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -357,7 +362,7 @@ class _PeerTabPageState extends State<PeerTabPage>
|
||||
break;
|
||||
}
|
||||
gFFI.peerTabModel.setMultiSelectionMode(false);
|
||||
showToast(translate('Successful'));
|
||||
if (model.currentTab != 3) showToast(translate('Successful'));
|
||||
}
|
||||
|
||||
deletePeerConfirmDialog(onSubmit, translate('Delete'));
|
||||
@ -404,7 +409,6 @@ class _PeerTabPageState extends State<PeerTabPage>
|
||||
gFFI.abModel.addPeers(peers);
|
||||
gFFI.abModel.pushAb();
|
||||
model.setMultiSelectionMode(false);
|
||||
showToast(translate('Successful'));
|
||||
},
|
||||
child: Tooltip(
|
||||
message: translate('Add to Address Book'),
|
||||
|
@ -30,6 +30,7 @@ class AbModel {
|
||||
final tags = [].obs;
|
||||
final peers = List<Peer>.empty(growable: true).obs;
|
||||
final sortTags = shouldSortTags().obs;
|
||||
final retrying = false.obs;
|
||||
bool get emtpy => peers.isEmpty && tags.isEmpty;
|
||||
|
||||
final selectedTags = List<String>.empty(growable: true).obs;
|
||||
@ -55,10 +56,11 @@ class AbModel {
|
||||
if (gFFI.userModel.userName.isEmpty) return;
|
||||
if (abLoading.value) return;
|
||||
if (!force && initialized) return;
|
||||
DateTime startTime = DateTime.now();
|
||||
if (pushError.isNotEmpty) {
|
||||
try {
|
||||
// push to retry
|
||||
pushAb(toast: false);
|
||||
pushAb(toastIfFail: false, toastIfSucc: false);
|
||||
} catch (_) {}
|
||||
}
|
||||
if (!quiet) {
|
||||
@ -112,14 +114,14 @@ class AbModel {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (initialized) {
|
||||
// make loading effect obvious
|
||||
Future.delayed(Duration(milliseconds: 300), () {
|
||||
abLoading.value = false;
|
||||
});
|
||||
} else {
|
||||
var ms =
|
||||
(Duration(milliseconds: 300) - DateTime.now().difference(startTime))
|
||||
.inMilliseconds;
|
||||
ms = ms > 0 ? ms : 0;
|
||||
Future.delayed(Duration(milliseconds: ms), () {
|
||||
abLoading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
_syncAllFromRecent = true;
|
||||
_timerCounter = 0;
|
||||
@ -198,9 +200,16 @@ class AbModel {
|
||||
it.first.alias = alias;
|
||||
}
|
||||
|
||||
Future<void> pushAb({bool toast = true}) async {
|
||||
debugPrint("pushAb");
|
||||
Future<bool> pushAb(
|
||||
{bool toastIfFail = true,
|
||||
bool toastIfSucc = true,
|
||||
bool isRetry = false}) async {
|
||||
debugPrint(
|
||||
"pushAb: toastIfFail:$toastIfFail, toastIfSucc:$toastIfSucc, isRetry:$isRetry");
|
||||
pushError.value = '';
|
||||
if (isRetry) retrying.value = true;
|
||||
DateTime startTime = DateTime.now();
|
||||
bool ret = false;
|
||||
try {
|
||||
// avoid double pushes in a row
|
||||
_syncAllFromRecent = true;
|
||||
@ -226,12 +235,14 @@ class AbModel {
|
||||
}
|
||||
if (resp.statusCode == 200 &&
|
||||
(resp.body.isEmpty || resp.body.toLowerCase() == 'null')) {
|
||||
ret = true;
|
||||
_saveCache();
|
||||
} else {
|
||||
Map<String, dynamic> json = _jsonDecode(resp.body, resp.statusCode);
|
||||
if (json.containsKey('error')) {
|
||||
throw json['error'];
|
||||
} else if (resp.statusCode == 200) {
|
||||
ret = true;
|
||||
_saveCache();
|
||||
} else {
|
||||
throw 'HTTP ${resp.statusCode}';
|
||||
@ -240,12 +251,25 @@ class AbModel {
|
||||
} catch (e) {
|
||||
pushError.value =
|
||||
'${translate('push_ab_failed_tip')}: ${translate(e.toString())}';
|
||||
if (toast && gFFI.peerTabModel.currentTab != PeerTabIndex.ab.index) {
|
||||
BotToast.showText(contentColor: Colors.red, text: pushError.value);
|
||||
}
|
||||
} finally {
|
||||
_syncAllFromRecent = true;
|
||||
}
|
||||
_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);
|
||||
}
|
||||
if (ret && toastIfSucc) {
|
||||
showToast(translate('Successful'));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Peer? find(String id) {
|
||||
@ -410,7 +434,7 @@ class AbModel {
|
||||
}
|
||||
// Be careful with loop calls
|
||||
if (syncChanged && push) {
|
||||
pushAb();
|
||||
pushAb(toastIfSucc: false);
|
||||
} else if (uiChanged) {
|
||||
peers.refresh();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user