Fix latency-probe races, stale offline menu, and byte formatting
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@ function scale(n) {
|
||||
// "2.4 MB", human readable with a space.
|
||||
export function formatBytes(n) {
|
||||
const [v, i] = scale(n);
|
||||
const digits = i === 0 ? 0 : v < 10 ? 1 : v < 100 ? 1 : 0;
|
||||
const digits = i === 0 ? 0 : v < 10 ? 2 : v < 100 ? 1 : 0;
|
||||
return `${v.toFixed(digits)} ${UNITS[i]}`;
|
||||
}
|
||||
|
||||
|
||||
+29
-5
@@ -35,6 +35,8 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
this._selectorItems = new Map();
|
||||
this._proxiesMap = {};
|
||||
this._delays = new Map(); // node name -> ms number | 'timeout'
|
||||
this._probing = new Set(); // nodes with a latency probe in flight
|
||||
this._apiUrl = '';
|
||||
this._polling = false;
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
|
||||
@@ -131,14 +133,18 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
// ---- Settings -----------------------------------------------------
|
||||
|
||||
_onSettingsChanged() {
|
||||
// Latencies measured against one instance are meaningless for another.
|
||||
if (this._settings.get_string('api-url') !== this._apiUrl)
|
||||
this._delays.clear();
|
||||
this._applySettings();
|
||||
this._restartPolling();
|
||||
this._poll();
|
||||
}
|
||||
|
||||
_applySettings() {
|
||||
this._apiUrl = this._settings.get_string('api-url');
|
||||
this._api.setEndpoint(
|
||||
this._settings.get_string('api-url'),
|
||||
this._apiUrl,
|
||||
this._settings.get_string('api-secret')
|
||||
);
|
||||
this._interval = this._settings.get_int('refresh-interval');
|
||||
@@ -299,6 +305,9 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
entry.setOrnament(isCurrent
|
||||
? PopupMenu.Ornament.DOT
|
||||
: PopupMenu.Ornament.NONE);
|
||||
// Don't overwrite the "…" placeholder while a probe is running.
|
||||
if (this._probing.has(member))
|
||||
continue;
|
||||
entry.label.text = this._memberLabelText(member, map[member]);
|
||||
}
|
||||
}
|
||||
@@ -340,6 +349,16 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
}
|
||||
}
|
||||
|
||||
// Drop menu content that would otherwise stay clickable while offline.
|
||||
_clearMenuData() {
|
||||
this._selectorsSection.removeAll();
|
||||
this._selectorItems.clear();
|
||||
this._selectorSignature = null;
|
||||
this._probing.clear();
|
||||
this._connItem.menu.removeAll();
|
||||
this._connItem.label.text = `${_('Connections')}: —`;
|
||||
}
|
||||
|
||||
_pickPanelGroup(selectors) {
|
||||
if (selectors.length === 0)
|
||||
return null;
|
||||
@@ -384,6 +403,7 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
if (!stored)
|
||||
return;
|
||||
for (const [member, item] of stored.members) {
|
||||
this._probing.add(member);
|
||||
item.label.text = `${member} · …`;
|
||||
this._api.getDelay(member, {}, this._cancellable)
|
||||
.then(res => {
|
||||
@@ -394,9 +414,14 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
this._delays.set(member, 'timeout');
|
||||
})
|
||||
.finally(() => {
|
||||
this._probing.delete(member);
|
||||
if (this._cancellable.is_cancelled())
|
||||
return;
|
||||
item.label.text = this._memberLabelText(member, this._proxiesMap?.[member]);
|
||||
// Re-resolve the row: the menu may have been rebuilt while
|
||||
// the probe was in flight, disposing the captured actor.
|
||||
const cur = this._selectorItems.get(groupName)?.members.get(member);
|
||||
if (cur)
|
||||
cur.label.text = this._memberLabelText(member, this._proxiesMap?.[member]);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -423,13 +448,12 @@ class SingBoxIndicator extends PanelMenu.Button {
|
||||
break;
|
||||
case STATE.OFFLINE:
|
||||
this._dotFilled = false;
|
||||
this._statusItem.label.text = error
|
||||
? _('sing-box · Unreachable')
|
||||
: _('sing-box · Offline');
|
||||
this._statusItem.label.text = _('sing-box · Unreachable');
|
||||
this._outboundLabel.text = '';
|
||||
this._speedLabel.text = '';
|
||||
this._speedItem.label.text = _('API unreachable — check URL and secret in Settings');
|
||||
this._prevSample = null;
|
||||
this._clearMenuData();
|
||||
break;
|
||||
default:
|
||||
this._dotFilled = false;
|
||||
|
||||
Reference in New Issue
Block a user