From 22356940d9d0d6c4dbb74ae6f641cf4573a6bae1 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 27 Mar 2024 21:28:21 +0800 Subject: [PATCH] ab show loading LinearProgressIndicator (#7538) * Display the LinearProgressIndicator at the top of ab if the current ab is both empty and in a loading state. * Add pull error like the legacy ab. * When forcefully reading the 'ab' list, retrieve the personal ab guid to judge the current mode to prevent server upgrades while the main window remains open Signed-off-by: 21pages --- flutter/lib/common/widgets/address_book.dart | 4 ++ flutter/lib/models/ab_model.dart | 58 +++++++++++++------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/flutter/lib/common/widgets/address_book.dart b/flutter/lib/common/widgets/address_book.dart index 22caf8c28..eae305bff 100644 --- a/flutter/lib/common/widgets/address_book.dart +++ b/flutter/lib/common/widgets/address_book.dart @@ -48,6 +48,10 @@ class _AddressBookState extends State { } else { return Column( children: [ + // NOT use Offstage to wrap LinearProgressIndicator + if (gFFI.abModel.currentAbLoading.value && + gFFI.abModel.currentAbEmpty) + const LinearProgressIndicator(), buildErrorBanner(context, loading: gFFI.abModel.currentAbLoading, err: gFFI.abModel.currentAbPullError, diff --git a/flutter/lib/models/ab_model.dart b/flutter/lib/models/ab_model.dart index ac836a189..1fdb297c7 100644 --- a/flutter/lib/models/ab_model.dart +++ b/flutter/lib/models/ab_model.dart @@ -49,11 +49,11 @@ class AbModel { RxList get selectedTags => current.selectedTags; RxBool get currentAbLoading => current.abLoading; + bool get currentAbEmpty => current.peers.isEmpty && current.tags.isEmpty; RxString get currentAbPullError => current.pullError; RxString get currentAbPushError => current.pushError; String? _personalAbGuid; RxBool legacyMode = true.obs; - var _modeTested = false; // whether the mode has been tested final sortTags = shouldSortTags().obs; final filterByIntersection = filterAbTagByIntersection().obs; @@ -83,7 +83,6 @@ class AbModel { reset() async { print("reset ab model"); - _modeTested = false; addressbooks.clear(); setCurrentName(''); await bind.mainClearAb(); @@ -114,23 +113,16 @@ class AbModel { debugPrint("pullAb, force: $force, quiet: $quiet"); if (!gFFI.userModel.isLogin) return; if (force == null && listInitialized && current.initialized) return; - try { - if (!_modeTested) { - // Get personal address book guid + if (!listInitialized || force == ForcePullAb.listAndCurrent) { + try { + // Read personal guid every time to avoid upgrading the server without closing the main window _personalAbGuid = null; await _getPersonalAbGuid(); // Determine legacy mode based on whether _personalAbGuid is null legacyMode.value = _personalAbGuid == null; - _modeTested = true; - if (!legacyMode.value) { + if (!legacyMode.value && _maxPeerOneAb == 0) { await _getAbSettings(); } - } - } catch (e) { - debugPrint("test ab mode error: $e"); - } - if (!listInitialized || force == ForcePullAb.listAndCurrent) { - try { if (_personalAbGuid != null) { debugPrint("pull ab list"); List abProfiles = List.empty(growable: true); @@ -664,7 +656,7 @@ class AbModel { } } if (!current.initialized) { - await current.pullAb(quiet: true); + await current.pullAb(quiet: false); _saveCache(); } _refreshTab(); @@ -755,7 +747,9 @@ abstract class BaseAb { pullError.value = ""; } initialized = false; - initialized = await pullAbImpl(quiet: quiet); + try { + initialized = await pullAbImpl(quiet: quiet); + } catch (_) {} abLoading.value = false; } @@ -1257,12 +1251,12 @@ class Ab extends BaseAb { Future pullAbImpl({quiet = false}) async { bool ret = true; List tmpPeers = []; - if (!await _fetchPeers(tmpPeers)) { + if (!await _fetchPeers(tmpPeers, quiet: quiet)) { ret = false; } peers.value = tmpPeers; List tmpTags = []; - if (!await _fetchTags(tmpTags)) { + if (!await _fetchTags(tmpTags, quiet: quiet)) { ret = false; } tags.value = tmpTags.map((e) => e.name).toList(); @@ -1274,8 +1268,9 @@ class Ab extends BaseAb { return ret; } - Future _fetchPeers(List tmpPeers) async { + Future _fetchPeers(List tmpPeers, {quiet = false}) async { final api = "${await bind.mainGetApiServer()}/api/ab/peers"; + int? statusCode; try { var uri0 = Uri.parse(api); final pageSize = 100; @@ -1296,6 +1291,7 @@ class Ab extends BaseAb { var headers = getHttpHeaders(); headers['Content-Type'] = "application/json"; final resp = await http.post(uri, headers: headers); + statusCode = resp.statusCode; Map json = _jsonDecodeRespMap(utf8.decode(resp.bodyBytes), resp.statusCode); if (json.containsKey('error')) { @@ -1324,13 +1320,23 @@ class Ab extends BaseAb { } while (current * pageSize < total); return true; } catch (err) { - debugPrint('_fetchPeers err: ${err.toString()}'); + if (!quiet) { + pullError.value = + '${translate('pull_ab_failed_tip')}: ${translate(err.toString())}'; + } + } finally { + if (pullError.isNotEmpty) { + if (statusCode == 401) { + gFFI.userModel.reset(resetOther: true); + } + } } return false; } - Future _fetchTags(List tmpTags) async { + Future _fetchTags(List tmpTags, {quiet = false}) async { final api = "${await bind.mainGetApiServer()}/api/ab/tags/${profile.guid}"; + int? statusCode; try { var uri0 = Uri.parse(api); var uri = Uri( @@ -1342,6 +1348,7 @@ class Ab extends BaseAb { var headers = getHttpHeaders(); headers['Content-Type'] = "application/json"; final resp = await http.post(uri, headers: headers); + statusCode = resp.statusCode; List json = _jsonDecodeRespList(utf8.decode(resp.bodyBytes), resp.statusCode); if (resp.statusCode != 200) { @@ -1359,7 +1366,16 @@ class Ab extends BaseAb { } return true; } catch (err) { - debugPrint('_fetchTags err: ${err.toString()}'); + if (!quiet) { + pullError.value = + '${translate('pull_ab_failed_tip')}: ${translate(err.toString())}'; + } + } finally { + if (pullError.isNotEmpty) { + if (statusCode == 401) { + gFFI.userModel.reset(resetOther: true); + } + } } return false; }