fix ab tag flashing when refreshing (#7471)

* opt isFull, fix web console menu

Signed-off-by: 21pages <pages21@163.com>

* fix ab tag flashing when refreshing

Signed-off-by: 21pages <pages21@163.com>

---------

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2024-03-22 11:02:22 +08:00 committed by GitHub
parent 57b17b1798
commit 285e298a8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 57 deletions

View File

@ -376,13 +376,14 @@ class _AddressBookState extends State<AddressBook> {
sortMenuItem(), sortMenuItem(),
syncMenuItem(), syncMenuItem(),
filterMenuItem(), filterMenuItem(),
MenuEntryDivider<String>(), if (!gFFI.abModel.legacyMode.value) MenuEntryDivider<String>(),
getEntry(translate("ab_web_console_tip"), () async { if (!gFFI.abModel.legacyMode.value)
final url = await bind.mainGetApiServer(); getEntry(translate("ab_web_console_tip"), () async {
if (await canLaunchUrlString(url)) { final url = await bind.mainGetApiServer();
launchUrlString(url); if (await canLaunchUrlString(url)) {
} launchUrlString(url);
}), }
}),
]; ];
mod_menu.showMenu( mod_menu.showMenu(

View File

@ -54,16 +54,12 @@ class AbModel {
final sortTags = shouldSortTags().obs; final sortTags = shouldSortTags().obs;
final filterByIntersection = filterAbTagByIntersection().obs; final filterByIntersection = filterAbTagByIntersection().obs;
// licensedDevices is obtained from personal ab, shared ab restrict it in server
var licensedDevices = 0;
var _syncAllFromRecent = true; var _syncAllFromRecent = true;
var _syncFromRecentLock = false; var _syncFromRecentLock = false;
var _allInitialized = false; var _allInitialized = false;
var _timerCounter = 0; var _timerCounter = 0;
var _cacheLoadOnceFlag = false; var _cacheLoadOnceFlag = false;
var _everPulledProfiles = false; var _everPulledProfiles = false;
// ignore: unused_field
var _maxPeerOneAb = 0; var _maxPeerOneAb = 0;
WeakReference<FFI> parent; WeakReference<FFI> parent;
@ -88,7 +84,6 @@ class AbModel {
addressbooks.clear(); addressbooks.clear();
setCurrentName(''); setCurrentName('');
await bind.mainClearAb(); await bind.mainClearAb();
licensedDevices = 0;
_everPulledProfiles = false; _everPulledProfiles = false;
} }
@ -104,6 +99,7 @@ class AbModel {
if (!force && _allInitialized) return; if (!force && _allInitialized) return;
_allInitialized = false; _allInitialized = false;
try { try {
final tmpAddressbooks = Map<String, BaseAb>.fromEntries([]).obs;
// Get personal address book guid // Get personal address book guid
_personalAbGuid = null; _personalAbGuid = null;
await _getPersonalAbGuid(); await _getPersonalAbGuid();
@ -117,16 +113,21 @@ class AbModel {
// get all address book name // get all address book name
await _getSharedAbProfiles(tmpAbProfiles); await _getSharedAbProfiles(tmpAbProfiles);
abProfiles = tmpAbProfiles; abProfiles = tmpAbProfiles;
addressbooks.clear();
for (int i = 0; i < abProfiles.length; i++) { for (int i = 0; i < abProfiles.length; i++) {
AbProfile p = abProfiles[i]; AbProfile p = abProfiles[i];
addressbooks[p.name] = Ab(p, p.guid == _personalAbGuid); tmpAddressbooks[p.name] = Ab(p, p.guid == _personalAbGuid);
} }
} else { } else {
// only legacy address book // only legacy address book
addressbooks.clear(); tmpAddressbooks[_legacyAddressBookName] = LegacyAb();
addressbooks[_legacyAddressBookName] = LegacyAb();
} }
addressbooks
.removeWhere((key, value) => !tmpAddressbooks.containsKey(key));
tmpAddressbooks.forEach((key, value) {
if (!addressbooks.containsKey(key)) {
addressbooks[key] = value;
}
});
// set current address book name // set current address book name
if (!_everPulledProfiles) { if (!_everPulledProfiles) {
_everPulledProfiles = true; _everPulledProfiles = true;
@ -630,7 +631,12 @@ class AbModel {
} }
bool isCurrentAbFull(bool warn) { bool isCurrentAbFull(bool warn) {
return current.isFull(warn); final res = current.isFull();
if (res && warn) {
BotToast.showText(
contentColor: Colors.red, text: translate('exceed_max_devices'));
}
return res;
} }
void _refreshTab() { void _refreshTab() {
@ -646,7 +652,7 @@ class AbModel {
} else if (name != _legacyAddressBookName) { } else if (name != _legacyAddressBookName) {
final ab = addressbooks[name]; final ab = addressbooks[name];
if (ab != null) { if (ab != null) {
return ab.pullAb(force: true, quiet: true); return await ab.pullAb(force: true, quiet: true);
} }
} }
} }
@ -710,7 +716,7 @@ abstract class BaseAb {
abLoading.value = true; abLoading.value = true;
pullError.value = ""; pullError.value = "";
} }
final ret = pullAbImpl(force: force, quiet: quiet); final ret = await pullAbImpl(force: force, quiet: quiet);
abLoading.value = false; abLoading.value = false;
return ret; return ret;
} }
@ -748,16 +754,7 @@ abstract class BaseAb {
Future<bool> deleteTag(String tag); Future<bool> deleteTag(String tag);
bool isFull(bool warn) { bool isFull();
bool res;
res = gFFI.abModel.licensedDevices > 0 &&
peers.length >= gFFI.abModel.licensedDevices;
if (res && warn) {
BotToast.showText(
contentColor: Colors.red, text: translate("exceed_max_devices"));
}
return res;
}
AbProfile? sharedProfile(); AbProfile? sharedProfile();
@ -765,8 +762,6 @@ abstract class BaseAb {
bool fullControl(); bool fullControl();
bool allowUpdateSettingsOrDelete();
Future<void> syncFromRecent(List<Peer> recents); Future<void> syncFromRecent(List<Peer> recents);
} }
@ -774,6 +769,8 @@ class LegacyAb extends BaseAb {
final sortTags = shouldSortTags().obs; final sortTags = shouldSortTags().obs;
final filterByIntersection = filterAbTagByIntersection().obs; final filterByIntersection = filterAbTagByIntersection().obs;
bool get emtpy => peers.isEmpty && tags.isEmpty; bool get emtpy => peers.isEmpty && tags.isEmpty;
// licensedDevices is obtained from personal ab, shared ab restrict it in server
var licensedDevices = 0;
LegacyAb(); LegacyAb();
@ -793,8 +790,8 @@ class LegacyAb extends BaseAb {
} }
@override @override
bool allowUpdateSettingsOrDelete() { bool isFull() {
return false; return licensedDevices > 0 && peers.length >= licensedDevices;
} }
@override @override
@ -824,7 +821,7 @@ class LegacyAb extends BaseAb {
throw json['error']; throw json['error'];
} else if (json.containsKey('data')) { } else if (json.containsKey('data')) {
try { try {
gFFI.abModel.licensedDevices = json['licensed_devices']; licensedDevices = json['licensed_devices'];
// ignore: empty_catches // ignore: empty_catches
} catch (e) {} } catch (e) {}
final data = jsonDecode(json['data']); final data = jsonDecode(json['data']);
@ -862,7 +859,7 @@ class LegacyAb extends BaseAb {
final body = jsonEncode({"data": jsonEncode(_serialize())}); final body = jsonEncode({"data": jsonEncode(_serialize())});
http.Response resp; http.Response resp;
// support compression // support compression
if (gFFI.abModel.licensedDevices > 0 && body.length > 1024) { if (licensedDevices > 0 && body.length > 1024) {
authHeaders['Content-Encoding'] = "gzip"; authHeaders['Content-Encoding'] = "gzip";
resp = await http.post(Uri.parse(api), resp = await http.post(Uri.parse(api),
headers: authHeaders, body: GZipCodec().encode(utf8.encode(body))); headers: authHeaders, body: GZipCodec().encode(utf8.encode(body)));
@ -903,7 +900,7 @@ class LegacyAb extends BaseAb {
Future<String?> addPeers(List<Map<String, dynamic>> ps) async { Future<String?> addPeers(List<Map<String, dynamic>> ps) async {
bool full = false; bool full = false;
for (var p in ps) { for (var p in ps) {
if (!isFull(false)) { if (!isFull()) {
p.remove('password'); // legacy ab ignore password p.remove('password'); // legacy ab ignore password
final index = peers.indexWhere((e) => e.id == p['id']); final index = peers.indexWhere((e) => e.id == p['id']);
if (index >= 0) { if (index >= 0) {
@ -981,7 +978,7 @@ class LegacyAb extends BaseAb {
var r = recents[i]; var r = recents[i];
var index = peers.indexWhere((e) => e.id == r.id); var index = peers.indexWhere((e) => e.id == r.id);
if (index < 0) { if (index < 0) {
if (!isFull(false)) { if (!isFull()) {
peers.add(r); peers.add(r);
needSync = true; needSync = true;
} }
@ -1128,8 +1125,8 @@ class LegacyAb extends BaseAb {
peers.add(Peer.fromJson(peer)); peers.add(Peer.fromJson(peer));
} }
} }
if (isFull(false)) { if (isFull()) {
peers.removeRange(gFFI.abModel.licensedDevices, peers.length); peers.removeRange(licensedDevices, peers.length);
} }
// restore online // restore online
peers peers
@ -1172,9 +1169,10 @@ class Ab extends BaseAb {
return profile; return profile;
} }
bool creatorOrAdmin() { @override
return profile.owner == gFFI.userModel.userName.value || bool isFull() {
gFFI.userModel.isAdmin.value; return gFFI.abModel._maxPeerOneAb > 0 &&
peers.length >= gFFI.abModel._maxPeerOneAb;
} }
@override @override
@ -1196,15 +1194,6 @@ class Ab extends BaseAb {
} }
} }
@override
bool allowUpdateSettingsOrDelete() {
if (personal) {
return false;
} else {
return creatorOrAdmin();
}
}
@override @override
Future<void> pullAbImpl({force = true, quiet = false}) async { Future<void> pullAbImpl({force = true, quiet = false}) async {
List<Peer> tmpPeers = []; List<Peer> tmpPeers = [];
@ -1322,7 +1311,7 @@ class Ab extends BaseAb {
if (peers.firstWhereOrNull((e) => e.id == p['id']) != null) { if (peers.firstWhereOrNull((e) => e.id == p['id']) != null) {
continue; continue;
} }
if (isFull(false)) { if (isFull()) {
return translate("exceed_max_devices"); return translate("exceed_max_devices");
} }
if (personal) { if (personal) {
@ -1624,6 +1613,11 @@ class Ab extends BaseAb {
// DummyAb is for current ab is null // DummyAb is for current ab is null
class DummyAb extends BaseAb { class DummyAb extends BaseAb {
@override
bool isFull() {
return false;
}
@override @override
Future<String?> addPeers(List<Map<String, dynamic>> ps) async { Future<String?> addPeers(List<Map<String, dynamic>> ps) async {
return "Unreachable"; return "Unreachable";
@ -1645,11 +1639,6 @@ class DummyAb extends BaseAb {
return false; return false;
} }
@override
bool allowUpdateSettingsOrDelete() {
return false;
}
@override @override
Future<bool> changeAlias({required String id, required String alias}) async { Future<bool> changeAlias({required String id, required String alias}) async {
return false; return false;