diff --git a/config/assets/launcher.json b/config/assets/launcher.json index 673251d..a153df6 100644 --- a/config/assets/launcher.json +++ b/config/assets/launcher.json @@ -6,6 +6,7 @@ ":td": "launcher.open(\"todo\")", ":bt": "launcher.open(\"bluetooth\")", ":sh": "launcher.open(\"sh\")", - ":pw": "launcher.open(\"power\")" + ":pw": "launcher.open(\"power\")", + ":nw": "launcher.open(\"wifi\")" } } diff --git a/config/config.py b/config/config.py index 0f2c399..46cd4c7 100644 --- a/config/config.py +++ b/config/config.py @@ -44,6 +44,8 @@ bind_vars = { "suffix_launcher": "D", "prefix_power": "SUPER", "suffix_power": "X", + "prefix_wifi": "SUPER", + "suffix_wifi": "N", "prefix_toggle": "SUPER", "suffix_toggle": "H", "prefix_randomwallpaper": "ALT SHIFT", @@ -152,6 +154,7 @@ $scriptsDir = $HOME/Modus/config bind = {bind_vars["prefix_restart"]}, {bind_vars["suffix_restart"]}, exec, killall modus; python {home}/Modus/main.py # Reload Modus | Default: SUPER ALT + T bind = {bind_vars["prefix_bluetooth"]}, {bind_vars["suffix_bluetooth"]}, exec, $fabricSend 'launcher.open("bluetooth")' # Bluetooth | Default: ALT + B +bind = {bind_vars["prefix_wifi"]}, {bind_vars["suffix_wifi"]}, exec, $fabricSend 'launcher.open("wifi")' # Wifi | Default: SUPER + N bind = {bind_vars["prefix_emoji"]}, {bind_vars["suffix_emoji"]}, exec, $fabricSend 'launcher.open("emoji")' # Emoji | Default: SUPER + E bind = {bind_vars["prefix_cliphist"]}, {bind_vars["suffix_cliphist"]}, exec, $fabricSend 'launcher.open("cliphist")' # Cliphist | Default: SUPER + V bind = {bind_vars["prefix_todo"]}, {bind_vars["suffix_todo"]}, exec, $fabricSend 'launcher.open("todo")' # Todo | Default: SUPER + T @@ -163,7 +166,7 @@ bind = {bind_vars["prefix_power"]}, {bind_vars["suffix_power"]}, exec, $fabricSe bind = {bind_vars["prefix_toggle"]}, {bind_vars["suffix_toggle"]}, exec, $fabricSend 'bar.toggle_hidden()' # Toggle Bar | Default: SUPER + H bind = {bind_vars["prefix_screenshotregion"]}, {bind_vars["suffix_screenshotregion"]}, exec, $fabricSend 'sc.screenshot()' # Screenshot Region | Default: SUPER + Z bind = {bind_vars["prefix_screenshot"]}, {bind_vars["suffix_screenshot"]}, exec, $fabricSend 'sc.screenshot(True)' # ScreenshotFullScreen | Default: Print -bind = {bind_vars["prefix_screencast"]}, {bind_vars["suffix_screencast"]}, exec, $fabricSend 'sc.screencast()' # Screencast | Default: SUPER + R +bind = {bind_vars["prefix_screencast"]}, {bind_vars["suffix_screencast"]}, exec, $fabricSend 'sc.screencast_start()' # Screencast | Default: SUPER + R # Wallpapers directory: {bind_vars["wallpapers_dir"]} diff --git a/services/wifi.py b/services/wifi.py index 0b2bb4d..04ebcae 100644 --- a/services/wifi.py +++ b/services/wifi.py @@ -1,12 +1,11 @@ from typing import Any, List, Literal + import gi from fabric.core.service import Property, Service, Signal -from fabric.utils import bulk_connect +from fabric.utils import bulk_connect, exec_shell_command_async from gi.repository import Gio from loguru import logger -from fabric.utils import exec_shell_command_async - try: gi.require_version("NM", "1.0") from gi.repository import NM @@ -15,12 +14,17 @@ except ValueError: class Wifi(Service): + """A service to manage wifi devices""" + @Signal def changed(self) -> None: ... @Signal def enabled(self) -> bool: ... + @Signal + def scanning(self, is_scanning: bool) -> None: ... + def __init__(self, client: NM.Client, device: NM.DeviceWifi, **kwargs): self._client: NM.Client = client self._device: NM.DeviceWifi = device @@ -76,13 +80,18 @@ class Wifi(Service): # self._device.access def scan(self): - self._device.request_scan_async( - None, - lambda device, result: [ - device.request_scan_finish(result), - self.emit("changed"), - ], - ) + """Start scanning for WiFi networks and emit scanning signal""" + if self._device: + self.emit("scanning", True) # Emit signal that scanning has started + self._device.request_scan_async( + None, + lambda device, result: [ + device.request_scan_finish(result), + self.emit( + "scanning", False + ), # Emit signal that scanning has stopped + ], + ) def notifier(self, name: str, *args): self.notify(name) @@ -193,6 +202,8 @@ class Wifi(Service): class Ethernet(Service): + """A service to manage ethernet devices""" + @Signal def changed(self) -> None: ... @@ -234,23 +245,25 @@ class Ethernet(Service): self._client: NM.Client = client self._device: NM.DeviceEthernet = device - for pn in ( + for names in ( "active-connection", "icon-name", "internet", "speed", "state", ): - self._device.connect(f"notify::{pn}", lambda *_: self.notifier(pn)) + self._device.connect(f"notify::{names}", lambda *_: self.notifier(names)) self._device.connect("notify::speed", lambda *_: print(_)) - def notifier(self, pn): - self.notify(pn) + def notifier(self, names): + self.notify(names) self.emit("changed") class NetworkClient(Service): + """A service to manage network devices""" + @Signal def device_ready(self) -> None: ... @@ -289,7 +302,7 @@ class NetworkClient(Service): x for x in devices if x.get_device_type() == device_type - and x.get_active_connection() != None + and x.get_active_connection() is not None ), None, ) @@ -297,6 +310,9 @@ class NetworkClient(Service): def _get_primary_device(self) -> Literal["wifi", "wired"] | None: if not self._client: return None + + if self._client.get_primary_connection() is None: + return "wifi" return ( "wifi" if "wireless" @@ -316,4 +332,3 @@ class NetworkClient(Service): @Property(str, "readable") def primary_device(self) -> Literal["wifi", "wired"] | None: return self._get_primary_device() - diff --git a/styles/bar.css b/styles/bar.css index 028ba7a..95edb20 100644 --- a/styles/bar.css +++ b/styles/bar.css @@ -183,7 +183,8 @@ menu > menuitem:hover > label { } #recording-indicator { - animation: error 0.8s linear infinite alternate; + color: @primary; + animation: error 2s infinite; } @keyframes error { diff --git a/styles/launcher.css b/styles/launcher.css index 9daaeef..7f0ebdc 100644 --- a/styles/launcher.css +++ b/styles/launcher.css @@ -34,6 +34,11 @@ min-width: 464px; } +#launcher-content.wifi { + min-height: 464px; + min-width: 464px; +} + #launcher-content.power { min-height: 52px; } @@ -73,6 +78,20 @@ border-radius: 100%; } +#scrolled-window scrollbar { + border-radius: 10px; + background-color: @surface; + /*padding: 4px;*/ + /*margin-left: 6px;*/ +} + +#scrolled-window slider { + border-radius: 8px; + min-width: 10px; + min-height: 48px; + background-color: @primary; +} + /* * ── applauncher ─────────────────────────────────────────────────────── */ @@ -172,7 +191,7 @@ * ── cliphist ────────────────────────────────────────────────────────── */ #cliphist-history { - min-height: 420px; + min-height: 520px; } #launcher button#clip-img-item { @@ -325,3 +344,69 @@ border-radius: 20px; min-height: 200px; } + +/* + * ── wifi ────────────────────────────────────────────────────────────── +*/ + +#wifi-header { + background-color: @surfaceContainer; + padding: 4px; + border-radius: 20px; +} + +#wifi-device { + background-color: @secondaryContainer; + border-radius: 16px; + padding: 4px; + margin-bottom: 4px; +} + +#wifi-scan, +#wifi-toggle { + background-color: @secondaryContainer; + margin-left: 0px; + min-width: 44px; + min-height: 44px; + border-radius: 100%; +} + +#wifi-scan:hover, +#wifi-toggle:hover { + background-color: @surfaceBright; +} + +#wifi-scan label, +#wifi-toggle label { + font-weight: bold; +} + +#wifi-text, +#wifi-section { + font-weight: bold; +} + +#wifi-text { + color: @primary; +} + +#wifi-connection { + font-size: 20px; +} + +#wifi-connect { + background-color: @surface; + border-radius: 16px; + padding: 8px 16px; +} + +#wifi-connect:hover { + background-color: @surfaceBright; +} + +#wifi-available { + background-color: @surfaceContainer; + padding: 4px; + border-radius: 20px; + min-height: 200px; +}