susops 3.0.0rc3.dev7__tar.gz → 3.0.0rc3.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/PKG-INFO +1 -1
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/pyproject.toml +7 -2
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/rpc_server.py +1 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/facade.py +9 -0
- susops-3.0.0rc3.dev8/src/susops/tui/app.tcss +63 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/screens/dashboard.py +24 -4
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops.egg-info/PKG-INFO +1 -1
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops.egg-info/SOURCES.txt +1 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/LICENSE +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/README.md +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/setup.cfg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/__init__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icon.png +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/dark/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/dark/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/dark/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/dark/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/light/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/light/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/light/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/light/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/dark/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/dark/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/dark/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/dark/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/light/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/light/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/light/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/light/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/status/error.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/status/running.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/status/stopped.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/status/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/client.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/__init__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/browsers.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/config.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/log_style.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/pac.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/ports.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/process.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/rpc_protocol.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/services_daemon.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/share.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/socat.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/ssh.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/ssh_config.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/status.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/core/types.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tray/__init__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tray/base.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tray/linux.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tray/mac.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/__init__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/__main__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/app.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/cli.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/screens/__init__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/screens/connections.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/screens/shares.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/widgets/__init__.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/tui/widgets/connection_card.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/version.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops.egg-info/dependency_links.txt +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops.egg-info/entry_points.txt +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops.egg-info/requires.txt +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops.egg-info/top_level.txt +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_bw_totals.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_cli.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_client.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_config.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_conftest_smoke.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_facade.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_openapi.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_pac.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_packaging.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_process.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_rpc_protocol.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_rpc_server.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_scripts.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_services_daemon.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_share.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_share_aiohttp.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_socat.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_ssh.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_status.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_update_homebrew_sha.py +0 -0
- {susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/tests/test_version.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "susops"
|
|
7
|
-
version = "3.0.0-rc3.
|
|
7
|
+
version = "3.0.0-rc3.dev8"
|
|
8
8
|
description = "SusOps — SSH SOCKS5 proxy manager with PAC server, Textual TUI, and system tray apps"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -51,7 +51,12 @@ susops-tray = "susops.tray:main"
|
|
|
51
51
|
where = ["src"]
|
|
52
52
|
|
|
53
53
|
[tool.setuptools.package-data]
|
|
54
|
-
susops = [
|
|
54
|
+
susops = [
|
|
55
|
+
"assets/*.png",
|
|
56
|
+
"assets/icons/**/*.svg",
|
|
57
|
+
"assets/icons/**/*.png",
|
|
58
|
+
"tui/**/*.tcss",
|
|
59
|
+
]
|
|
55
60
|
|
|
56
61
|
[tool.pytest.ini_options]
|
|
57
62
|
testpaths = ["tests"]
|
|
@@ -45,6 +45,7 @@ _ALLOWED_METHODS: set[str] = {
|
|
|
45
45
|
"get_pac_url", "get_status_url",
|
|
46
46
|
# Bandwidth
|
|
47
47
|
"get_bandwidth", "get_bandwidth_totals", "get_bandwidth_global",
|
|
48
|
+
"get_bandwidth_history",
|
|
48
49
|
# Reconnect introspection
|
|
49
50
|
"reconnect_monitor_info",
|
|
50
51
|
# Process introspection
|
|
@@ -376,6 +376,11 @@ class _BandwidthSampler:
|
|
|
376
376
|
with self._lock:
|
|
377
377
|
return self._totals.get(tag, (0.0, 0.0))
|
|
378
378
|
|
|
379
|
+
def get_history(self, tag: str) -> list[list[float]]:
|
|
380
|
+
"""Return the persisted (rx_bps, tx_bps) samples for *tag* (newest last)."""
|
|
381
|
+
with self._lock:
|
|
382
|
+
return list(self._history.get(tag, []))
|
|
383
|
+
|
|
379
384
|
def reset_totals(self, tag: str | None = None) -> None:
|
|
380
385
|
"""Reset cumulative counters. Pass tag=None to reset all."""
|
|
381
386
|
with self._lock:
|
|
@@ -2143,6 +2148,10 @@ class SusOpsManager:
|
|
|
2143
2148
|
"""Return cumulative (rx_bytes, tx_bytes) since last start. Resets on stop."""
|
|
2144
2149
|
return self._bw_sampler.get_totals(tag)
|
|
2145
2150
|
|
|
2151
|
+
def get_bandwidth_history(self, tag: str) -> list[list[float]]:
|
|
2152
|
+
"""Return persisted [rx_bps, tx_bps] samples for *tag* (oldest → newest)."""
|
|
2153
|
+
return self._bw_sampler.get_history(tag)
|
|
2154
|
+
|
|
2146
2155
|
def get_bandwidth_global(self) -> tuple[float, float]:
|
|
2147
2156
|
"""Return (rx_bps, tx_bps) summed across every connection."""
|
|
2148
2157
|
rx_total = 0.0
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* SusOps TUI — global theme */
|
|
2
|
+
|
|
3
|
+
/* ── Base ── */
|
|
4
|
+
Screen { background: $background; }
|
|
5
|
+
Header { background: $primary-darken-3; }
|
|
6
|
+
Footer { background: $surface-darken-2; }
|
|
7
|
+
.footer-row { dock: bottom; height: 1; }
|
|
8
|
+
.footer-row Footer { dock: none; width: 1fr; height: 1; }
|
|
9
|
+
.footer-version { width: auto; padding: 0 1; background: $surface-darken-2; color: $text-muted; content-align: center middle; }
|
|
10
|
+
.footer-edit-config { width: auto; padding: 0 1; background: $surface-darken-2; color: $accent; content-align: center middle; }
|
|
11
|
+
.footer-logo { width: auto; padding: 0 1; background: $surface-darken-2; content-align: center middle; }
|
|
12
|
+
|
|
13
|
+
/* ── Dashboard ── */
|
|
14
|
+
#conn-list > ListItem { height: 1; padding: 0 1; }
|
|
15
|
+
|
|
16
|
+
/* ── Connection editor ── */
|
|
17
|
+
.tab-actions { height: 3; layout: horizontal; padding: 0 1; background: $surface-darken-1; }
|
|
18
|
+
.tab-actions Button { margin-right: 1; }
|
|
19
|
+
#detail-preview { height: 6; border: round $primary-darken-1; border-title-align: left; padding: 0 1; margin: 0 1 1 1; color: $text-muted; }
|
|
20
|
+
|
|
21
|
+
/* ── Share ── */
|
|
22
|
+
#share-toolbar { height: 3; layout: horizontal; padding: 0 1; background: $surface-darken-1; }
|
|
23
|
+
#share-toolbar Button { margin-right: 1; }
|
|
24
|
+
#share-list-panel { width: 35; background: $surface-darken-1; border-right: solid $primary-darken-2; }
|
|
25
|
+
#share-list { height: 1fr; margin: 1; border: round $primary-darken-1; border-title-align: left; }
|
|
26
|
+
#share-list > ListItem { height: 1; padding: 0 1; }
|
|
27
|
+
#share-detail { width: 1fr; padding: 1 2; height: 1fr; }
|
|
28
|
+
#share-status { height: 1; padding: 0 1; background: $surface-darken-2; color: $text-muted; }
|
|
29
|
+
|
|
30
|
+
/* ── Logs ── */
|
|
31
|
+
#log-toolbar { height: 3; layout: horizontal; padding: 0 1; background: $surface-darken-1; align: left middle; }
|
|
32
|
+
#log-toolbar Label { margin-right: 1; height: 1; }
|
|
33
|
+
#log-toolbar Switch { margin-right: 2; }
|
|
34
|
+
#log-toolbar Button { margin-left: 2; }
|
|
35
|
+
#log-view { height: 1fr; border: round $primary-darken-1; border-title-align: left; margin: 0 1 1 1; }
|
|
36
|
+
|
|
37
|
+
/* ── Config ── */
|
|
38
|
+
#config-toolbar { height: 3; layout: horizontal; padding: 0 1; background: $surface-darken-1; }
|
|
39
|
+
#config-toolbar Button { margin-right: 1; }
|
|
40
|
+
#config-area { height: 1fr; border: round $primary-darken-1; border-title-align: left; margin: 0 1 1 1; }
|
|
41
|
+
|
|
42
|
+
/* ── PAC viewer ── */
|
|
43
|
+
#pac-area { height: 1fr; border: round $primary-darken-1; border-title-align: left; margin: 0 1 1 1; }
|
|
44
|
+
|
|
45
|
+
/* ── Modals ── */
|
|
46
|
+
ModalScreen { align: center middle; background: rgba(0, 0, 0, 0.75); }
|
|
47
|
+
.modal-dialog { width: 76; height: auto; border: round $primary; padding: 1 2; background: $surface; }
|
|
48
|
+
.modal-dialog Label { margin-top: 1; }
|
|
49
|
+
.modal-dialog > Label:first-child { margin-top: 0; }
|
|
50
|
+
.modal-dialog Input { margin-bottom: 1; }
|
|
51
|
+
.modal-dialog Select { margin-bottom: 1; }
|
|
52
|
+
.modal-dialog .modal-error { color: $error; margin-top: 0; }
|
|
53
|
+
.modal-dialog .modal-hint { margin-top: 0; }
|
|
54
|
+
.modal-btn-row { layout: horizontal; height: auto; margin-top: 1; }
|
|
55
|
+
.modal-btn-row Button { margin-right: 1; }
|
|
56
|
+
/* 2-column form rows */
|
|
57
|
+
.modal-form-row { height: auto; margin-top: 1; }
|
|
58
|
+
.modal-proto-row { height: auto; }
|
|
59
|
+
.modal-field { width: 1fr; height: auto; layout: vertical; padding-right: 1; }
|
|
60
|
+
.modal-field:last-child { padding-right: 0; }
|
|
61
|
+
.modal-field Label { margin-top: 0; }
|
|
62
|
+
.modal-field Input { margin-bottom: 0; }
|
|
63
|
+
.modal-field Select { margin-bottom: 0; }
|
|
@@ -290,11 +290,19 @@ class DashboardScreen(Screen):
|
|
|
290
290
|
bw: dict[str, tuple[float, float]] = {}
|
|
291
291
|
bw_totals: dict[str, tuple[float, float]] = {}
|
|
292
292
|
uptimes: dict[str, float | None] = {}
|
|
293
|
+
bw_history_seed: dict[str, list] = {}
|
|
293
294
|
for cs in result.connection_statuses:
|
|
294
295
|
extras[cs.tag] = mgr.get_process_info(cs.tag)
|
|
295
296
|
bw[cs.tag] = mgr.get_bandwidth(cs.tag)
|
|
296
297
|
bw_totals[cs.tag] = mgr.get_bandwidth_totals(cs.tag)
|
|
297
298
|
uptimes[cs.tag] = mgr.get_uptime(cs.tag)
|
|
299
|
+
# Only fetch persisted history for tags we haven't seeded
|
|
300
|
+
# yet — saves an RPC per tick once the chart is rolling.
|
|
301
|
+
if cs.tag not in self._rx_history:
|
|
302
|
+
try:
|
|
303
|
+
bw_history_seed[cs.tag] = mgr.get_bandwidth_history(cs.tag) or []
|
|
304
|
+
except Exception:
|
|
305
|
+
bw_history_seed[cs.tag] = []
|
|
298
306
|
|
|
299
307
|
shares = mgr.list_shares()
|
|
300
308
|
config = mgr.list_config()
|
|
@@ -312,7 +320,8 @@ class DashboardScreen(Screen):
|
|
|
312
320
|
)
|
|
313
321
|
return
|
|
314
322
|
self.app.call_from_thread(
|
|
315
|
-
self._apply_status, result, extras, bw, bw_totals, uptimes, shares,
|
|
323
|
+
self._apply_status, result, extras, bw, bw_totals, uptimes, shares,
|
|
324
|
+
config, reconnect, bw_history_seed,
|
|
316
325
|
)
|
|
317
326
|
|
|
318
327
|
def _apply_status(
|
|
@@ -325,7 +334,9 @@ class DashboardScreen(Screen):
|
|
|
325
334
|
shares: list,
|
|
326
335
|
config,
|
|
327
336
|
reconnect: dict,
|
|
337
|
+
bw_history_seed: dict | None = None,
|
|
328
338
|
) -> None:
|
|
339
|
+
bw_history_seed = bw_history_seed or {}
|
|
329
340
|
self._last_config = config
|
|
330
341
|
self._last_shares = shares
|
|
331
342
|
|
|
@@ -352,13 +363,22 @@ class DashboardScreen(Screen):
|
|
|
352
363
|
}
|
|
353
364
|
self._conn_data = new_conn_data
|
|
354
365
|
|
|
355
|
-
# Update rolling bandwidth history (60 samples)
|
|
366
|
+
# Update rolling bandwidth history (60 samples). Seed from the
|
|
367
|
+
# daemon's persisted history (pre-fetched by refresh_status) on
|
|
368
|
+
# first encounter so reopening the TUI doesn't reset the chart to
|
|
369
|
+
# flatlined zeros.
|
|
356
370
|
for cs in result.connection_statuses:
|
|
357
371
|
tag = cs.tag
|
|
358
372
|
rx, tx = bw.get(tag, (0.0, 0.0))
|
|
359
373
|
if tag not in self._rx_history:
|
|
360
|
-
|
|
361
|
-
|
|
374
|
+
rx_seed = [0.0] * 60
|
|
375
|
+
tx_seed = [0.0] * 60
|
|
376
|
+
persisted = (bw_history_seed.get(tag) or [])[-60:]
|
|
377
|
+
if persisted:
|
|
378
|
+
rx_seed[-len(persisted):] = [s[0] for s in persisted]
|
|
379
|
+
tx_seed[-len(persisted):] = [s[1] for s in persisted]
|
|
380
|
+
self._rx_history[tag] = deque(rx_seed, maxlen=60)
|
|
381
|
+
self._tx_history[tag] = deque(tx_seed, maxlen=60)
|
|
362
382
|
self._rx_history[tag].append(rx)
|
|
363
383
|
self._tx_history[tag].append(tx)
|
|
364
384
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_glasses/dark/error.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/error.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/running.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/dark/stopped.svg
RENAMED
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/error.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/running.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/colored_s/light/stopped.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/light/running.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/gear/light/stopped.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev7 → susops-3.0.0rc3.dev8}/src/susops/assets/icons/status/stopped_partially.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|