susops 3.0.0rc3.dev8__tar.gz → 3.0.0rc3.dev9__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.dev8 → susops-3.0.0rc3.dev9}/PKG-INFO +1 -1
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/pyproject.toml +1 -1
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/client.py +18 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/rpc_server.py +2 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/facade.py +50 -13
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tray/base.py +9 -1
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/app.py +10 -3
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops.egg-info/PKG-INFO +1 -1
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/LICENSE +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/README.md +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/setup.cfg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/__init__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icon.png +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/dark/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/dark/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/dark/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/dark/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/light/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/light/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/light/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_glasses/light/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/light/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/light/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/light/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/light/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/dark/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/dark/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/dark/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/dark/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/light/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/light/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/light/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/light/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/status/error.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/status/running.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/status/stopped.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/status/stopped_partially.svg +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/__init__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/browsers.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/config.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/log_style.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/pac.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/ports.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/process.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/rpc_protocol.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/services_daemon.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/share.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/socat.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/ssh.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/ssh_config.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/status.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/core/types.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tray/__init__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tray/linux.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tray/mac.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/__init__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/__main__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/app.tcss +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/cli.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/screens/__init__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/screens/connections.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/screens/dashboard.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/screens/shares.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/widgets/__init__.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/tui/widgets/connection_card.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/version.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops.egg-info/SOURCES.txt +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops.egg-info/dependency_links.txt +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops.egg-info/entry_points.txt +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops.egg-info/requires.txt +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops.egg-info/top_level.txt +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_bw_totals.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_cli.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_client.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_config.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_conftest_smoke.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_facade.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_openapi.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_pac.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_packaging.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_process.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_rpc_protocol.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_rpc_server.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_scripts.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_services_daemon.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_share.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_share_aiohttp.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_socat.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_ssh.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_status.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/tests/test_update_homebrew_sha.py +0 -0
- {susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/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.dev9"
|
|
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" }
|
|
@@ -69,6 +69,24 @@ def ensure_daemon_running(workspace: Path = _WORKSPACE_DEFAULT) -> int:
|
|
|
69
69
|
port = _read_port(workspace)
|
|
70
70
|
if port:
|
|
71
71
|
return port
|
|
72
|
+
# Daemon claimed its PID file but hasn't published the port yet.
|
|
73
|
+
# Wait for it instead of spawning a competitor that would race the
|
|
74
|
+
# O_EXCL claim and exit rc=2 ("another daemon is already running").
|
|
75
|
+
deadline = time.monotonic() + _DAEMON_SPAWN_TIMEOUT
|
|
76
|
+
while time.monotonic() < deadline:
|
|
77
|
+
if not _is_daemon_alive(workspace):
|
|
78
|
+
break # died mid-startup, fall through to spawn a new one
|
|
79
|
+
port = _read_port(workspace)
|
|
80
|
+
if port:
|
|
81
|
+
return port
|
|
82
|
+
time.sleep(0.1)
|
|
83
|
+
else:
|
|
84
|
+
raise DaemonUnavailableError(
|
|
85
|
+
"An existing susops-services daemon is alive but never "
|
|
86
|
+
"published an RPC port. Try `kill " +
|
|
87
|
+
(_pid_path(workspace).read_text().strip() or "<pid>") +
|
|
88
|
+
"` and start again."
|
|
89
|
+
)
|
|
72
90
|
|
|
73
91
|
proc = subprocess.Popen(
|
|
74
92
|
[sys.executable, "-m", "susops.core.services_daemon",
|
|
@@ -46,6 +46,8 @@ _ALLOWED_METHODS: set[str] = {
|
|
|
46
46
|
# Bandwidth
|
|
47
47
|
"get_bandwidth", "get_bandwidth_totals", "get_bandwidth_global",
|
|
48
48
|
"get_bandwidth_history",
|
|
49
|
+
# Frontend coordination
|
|
50
|
+
"sse_client_count",
|
|
49
51
|
# Reconnect introspection
|
|
50
52
|
"reconnect_monitor_info",
|
|
51
53
|
# Process introspection
|
|
@@ -625,25 +625,53 @@ class SusOpsManager:
|
|
|
625
625
|
print(full, file=sys.stderr)
|
|
626
626
|
|
|
627
627
|
def _notify(self, title: str, body: str) -> None:
|
|
628
|
-
"""Send a desktop notification. Best-effort
|
|
628
|
+
"""Send a desktop notification with the SusOps icon. Best-effort."""
|
|
629
629
|
import platform
|
|
630
|
-
import
|
|
630
|
+
from pathlib import Path
|
|
631
|
+
icon = Path(__file__).parent / "assets" / "icon.png"
|
|
631
632
|
try:
|
|
632
633
|
if platform.system() == "Darwin":
|
|
633
|
-
|
|
634
|
-
["osascript", "-e",
|
|
635
|
-
f'display notification "{body}" with title "{title}"'],
|
|
636
|
-
stdout=subprocess.DEVNULL,
|
|
637
|
-
stderr=subprocess.DEVNULL,
|
|
638
|
-
)
|
|
634
|
+
self._notify_macos(title, body, icon)
|
|
639
635
|
elif platform.system() == "Linux":
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
636
|
+
self._notify_linux(title, body, icon)
|
|
637
|
+
except Exception:
|
|
638
|
+
pass
|
|
639
|
+
|
|
640
|
+
@staticmethod
|
|
641
|
+
def _notify_macos(title: str, body: str, icon: "Path") -> None:
|
|
642
|
+
# NSUserNotification's setContentImage_ puts the SusOps icon on the
|
|
643
|
+
# right side of the banner. The source-app slot (left side) reflects
|
|
644
|
+
# the running process — bundled .app shows SusOps, raw pip install
|
|
645
|
+
# shows Python. osascript can't set either, so it loses both.
|
|
646
|
+
try:
|
|
647
|
+
from Foundation import NSUserNotification, NSUserNotificationCenter # type: ignore
|
|
648
|
+
from AppKit import NSImage # type: ignore
|
|
649
|
+
n = NSUserNotification.alloc().init()
|
|
650
|
+
n.setTitle_(title)
|
|
651
|
+
n.setInformativeText_(body)
|
|
652
|
+
if icon.exists():
|
|
653
|
+
img = NSImage.alloc().initWithContentsOfFile_(str(icon))
|
|
654
|
+
if img is not None:
|
|
655
|
+
n.setContentImage_(img)
|
|
656
|
+
NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification_(n)
|
|
657
|
+
return
|
|
645
658
|
except Exception:
|
|
646
659
|
pass
|
|
660
|
+
# Fallback for non-PyObjC environments
|
|
661
|
+
import subprocess
|
|
662
|
+
subprocess.Popen(
|
|
663
|
+
["osascript", "-e", f'display notification "{body}" with title "{title}"'],
|
|
664
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
@staticmethod
|
|
668
|
+
def _notify_linux(title: str, body: str, icon: "Path") -> None:
|
|
669
|
+
import subprocess
|
|
670
|
+
cmd = ["notify-send"]
|
|
671
|
+
if icon.exists():
|
|
672
|
+
cmd += ["-i", str(icon)]
|
|
673
|
+
cmd += [title, body]
|
|
674
|
+
subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
647
675
|
|
|
648
676
|
def _emit(self, event: str, data: dict) -> None:
|
|
649
677
|
"""Emit an SSE event and log it when verbose (bandwidth excluded — too noisy)."""
|
|
@@ -2152,6 +2180,15 @@ class SusOpsManager:
|
|
|
2152
2180
|
"""Return persisted [rx_bps, tx_bps] samples for *tag* (oldest → newest)."""
|
|
2153
2181
|
return self._bw_sampler.get_history(tag)
|
|
2154
2182
|
|
|
2183
|
+
def sse_client_count(self) -> int:
|
|
2184
|
+
"""Live SSE subscriber count. Used by frontends to decide whether
|
|
2185
|
+
a stop-on-quit should actually stop, or skip because another
|
|
2186
|
+
frontend is still attached to the same daemon."""
|
|
2187
|
+
try:
|
|
2188
|
+
return int(self._status_server.client_count())
|
|
2189
|
+
except Exception:
|
|
2190
|
+
return 0
|
|
2191
|
+
|
|
2155
2192
|
def get_bandwidth_global(self) -> tuple[float, float]:
|
|
2156
2193
|
"""Return (rx_bps, tx_bps) summed across every connection."""
|
|
2157
2194
|
rx_total = 0.0
|
|
@@ -641,7 +641,15 @@ class AbstractTrayApp(ABC):
|
|
|
641
641
|
|
|
642
642
|
def do_quit(self) -> None:
|
|
643
643
|
if self.manager.app_config.stop_on_quit:
|
|
644
|
-
|
|
644
|
+
# Skip the destructive stop when another frontend (e.g. TUI)
|
|
645
|
+
# is still attached, otherwise it ends up with its SSH
|
|
646
|
+
# masters / PAC / reconnect torn out from under it.
|
|
647
|
+
try:
|
|
648
|
+
other_clients = int(self.manager.sse_client_count()) - 1
|
|
649
|
+
except Exception:
|
|
650
|
+
other_clients = 0
|
|
651
|
+
if other_clients <= 0:
|
|
652
|
+
self.manager.stop()
|
|
645
653
|
# else: the daemon is a separate process — it keeps running with
|
|
646
654
|
# PAC server, status SSE, and reconnect monitor independent of the
|
|
647
655
|
# tray's lifetime. No detach calls needed.
|
|
@@ -121,9 +121,16 @@ class SusOpsTuiApp(App):
|
|
|
121
121
|
|
|
122
122
|
def action_quit(self) -> None:
|
|
123
123
|
if self.manager.app_config.stop_on_quit:
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
|
|
124
|
+
# Skip the destructive stop when another frontend (e.g. tray)
|
|
125
|
+
# is still attached. Otherwise the still-running frontend
|
|
126
|
+
# finds its SSH masters / PAC / reconnect monitor torn out
|
|
127
|
+
# from under it and looks broken until it's restarted.
|
|
128
|
+
try:
|
|
129
|
+
other_clients = int(self.manager.sse_client_count()) - 1
|
|
130
|
+
except Exception:
|
|
131
|
+
other_clients = 0
|
|
132
|
+
if other_clients <= 0:
|
|
133
|
+
self.manager.stop_quick()
|
|
127
134
|
# No detach calls — the daemon is already a separate process and
|
|
128
135
|
# outlives the TUI.
|
|
129
136
|
self.exit()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/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.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/error.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/running.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/dark/stopped.svg
RENAMED
|
File without changes
|
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/light/error.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/colored_s/light/running.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/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.dev8 → susops-3.0.0rc3.dev9}/src/susops/assets/icons/gear/light/running.svg
RENAMED
|
File without changes
|
{susops-3.0.0rc3.dev8 → susops-3.0.0rc3.dev9}/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.dev8 → susops-3.0.0rc3.dev9}/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
|