✨ feat(controlcenter): add flight mode and caffeine toggle functionality
This commit is contained in:
1 parent
c554b109f4
commit
fccb44b208
6 files changed
+254
-20
No files matched your search
@@ -0,0 +1,13 @@
|
||||
<svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<style id="current-color-scheme" type="text/css">
|
||||
.ColorScheme-Text { color:#f2f2f2; } .ColorScheme-Highlight { color:#4285f4; }
|
||||
</style>
|
||||
</defs>
|
||||
<g transform="translate(4,4)" class="ColorScheme-Text" fill="currentColor">
|
||||
<path d="m1 7v3c0 3 2 5 5 5h2c3 0 4.76-1.566 4.959-4h0.541c1.5 0 1.5-1.5 1.5-1.5v-1c0-1.5-1.5-1.5-1.5-1.5h-0.5zm1 1h10v2c0 2.216-1.784 4-4 4h-2c-2.216 0-4-1.784-4-4zm11.5 0c0.5-0.032 0.516 0.531 0.516 0.531v1c0 0.469-0.516 0.469-0.516 0.469h-0.5l0.01-1.985z"/>
|
||||
<path d="m7.193-1e-3c-1.098 1.385-1.428 2.066-1.032 2.948 0.36 0.798 1.288 1.205 0.821 3.052 0.767-0.9 1.376-2.042 0.774-2.964-0.612-0.938-0.948-1.508-0.563-3.036z" opacity=".35"/>
|
||||
<path d="m4.193-1e-3c-1.098 1.385-1.428 2.066-1.032 2.948 0.36 0.798 1.288 1.205 0.821 3.052 0.767-0.9 1.376-2.042 0.774-2.964-0.612-0.938-0.948-1.508-0.563-3.036z" opacity=".35"/>
|
||||
<path d="m10.193-1e-3c-1.098 1.385-1.428 2.066-1.032 2.948 0.36 0.798 1.288 1.205 0.821 3.052 0.767-0.9 1.376-2.042 0.774-2.964-0.612-0.938-0.948-1.508-0.563-3.036z" opacity=".35"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<style id="current-color-scheme" type="text/css">
|
||||
.ColorScheme-Text { color:#f2f2f2; } .ColorScheme-Highlight { color:#4285f4; }
|
||||
</style>
|
||||
</defs>
|
||||
<g transform="translate(4,4)" class="ColorScheme-Text" fill="currentColor">
|
||||
<path d="m1 7v3c0 3 2 5 5 5h2c3 0 4.76-1.566 4.959-4h0.541c1.5 0 1.5-1.5 1.5-1.5v-1c0-1.5-1.5-1.5-1.5-1.5h-0.5zm1 1h10v2c0 2.216-1.784 4-4 4h-2c-2.216 0-4-1.784-4-4zm11.5 0c0.5-0.032 0.516 0.531 0.516 0.531v1c0 0.469-0.516 0.469-0.516 0.469h-0.5l0.01-1.985z"/>
|
||||
<path d="m7.193-1e-3c-1.098 1.385-1.428 2.066-1.032 2.948 0.36 0.798 1.288 1.205 0.821 3.052 0.767-0.9 1.376-2.042 0.774-2.964-0.612-0.938-0.948-1.508-0.563-3.036z"/>
|
||||
<path d="m4.193-1e-3c-1.098 1.385-1.428 2.066-1.032 2.948 0.36 0.798 1.288 1.205 0.821 3.052 0.767-0.9 1.376-2.042 0.774-2.964-0.612-0.938-0.948-1.508-0.563-3.036z"/>
|
||||
<path d="m10.193-1e-3c-1.098 1.385-1.428 2.066-1.032 2.948 0.36 0.798 1.288 1.205 0.821 3.052 0.767-0.9 1.376-2.042 0.774-2.964-0.612-0.938-0.948-1.508-0.563-3.036z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,12 @@
|
||||
<svg width="22" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<style id="current-color-scheme" type="text/css">.ColorScheme-Text {
|
||||
color:#f2f2f2;
|
||||
}
|
||||
.ColorScheme-NegativeText{
|
||||
color:#e74c3c;
|
||||
}</style>
|
||||
</defs>
|
||||
<path class="ColorScheme-Text" d="m19.893 11c-0.0078-0.91918-1.262-1.6436-2.7965-1.6436h-3.2015c-0.43623 0-0.59984-0.0779-0.86466-0.36611l-5.2814-5.7098c-0.17137-0.18695-0.3739-0.28043-0.5998-0.28043h-1.0049c-0.20254 0-0.31937 0.18695-0.22591 0.39727l2.7342 5.9513-3.9961 0.444-1.4255-2.5394c-0.10906-0.19475-0.27264-0.28043-0.5297-0.28043h-0.35054c-0.21032 0-0.35053 0.14021-0.35053 0.35053v7.3534c0 0.21032 0.14022 0.35053 0.35053 0.35053h0.35054c0.25706 0 0.42064-0.0856 0.5297-0.28042l1.4255-2.5472 3.9961 0.45183-2.7342 5.9513c-0.09347 0.21031 0.02337 0.39732 0.22591 0.39732h1.0049c0.2259 0 0.42842-0.1013 0.5998-0.28042l5.2814-5.7098c0.26482-0.28822 0.42843-0.36613 0.86466-0.36613h3.2015c1.5345 0 2.7887-0.73225 2.7965-1.6436z" fill="currentColor" opacity=".35"/>
|
||||
<rect class="ColorScheme-Text" transform="rotate(45)" x="4.5563" y="-.5" width="22" height="1" rx=".5" ry=".5" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="22" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<style id="current-color-scheme" type="text/css">.ColorScheme-Text {
|
||||
color:#f2f2f2;
|
||||
}</style>
|
||||
</defs>
|
||||
<path class="ColorScheme-Text" d="m19.893 11c-0.0078-0.91918-1.262-1.6436-2.7965-1.6436h-3.2015c-0.43623 0-0.59984-0.0779-0.86466-0.36611l-5.2814-5.7098c-0.17137-0.18695-0.3739-0.28043-0.5998-0.28043h-1.0049c-0.20254 0-0.31937 0.18695-0.22591 0.39727l2.7342 5.9513-3.9961 0.444-1.4255-2.5394c-0.10906-0.19475-0.27264-0.28043-0.5297-0.28043h-0.35054c-0.21032 0-0.35053 0.14021-0.35053 0.35053v7.3534c0 0.21032 0.14022 0.35053 0.35053 0.35053h0.35054c0.25706 0 0.42064-0.0856 0.5297-0.28042l1.4255-2.5472 3.9961 0.45183-2.7342 5.9513c-0.09347 0.21031 0.02337 0.39732 0.22591 0.39732h1.0049c0.2259 0 0.42842-0.1013 0.5998-0.28042l5.2814-5.7098c0.26482-0.28822 0.42843-0.36613 0.86466-0.36613h3.2015c1.5345 0 2.7887-0.73225 2.7965-1.6436z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 971 B |
+207
-19
@@ -1,4 +1,4 @@
|
||||
from gi.repository import Gdk, GLib
|
||||
import subprocess
|
||||
|
||||
from fabric.utils import idle_add
|
||||
from fabric.utils.helpers import (
|
||||
@@ -6,30 +6,25 @@ from fabric.utils.helpers import (
|
||||
)
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from loguru import logger
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.scale import Scale
|
||||
from fabric.widgets.svg import Svg
|
||||
from fabric.widgets.revealer import Revealer
|
||||
from gi.repository import Gdk, GLib
|
||||
from loguru import logger
|
||||
from modules.controlcenter.bluetooth import BluetoothConnections
|
||||
from modules.controlcenter.expanded_player import EmbeddedExpandedPlayer
|
||||
from modules.controlcenter.per_app_volume import PerAppVolumeControl
|
||||
from modules.controlcenter.player import PlayerBoxStack
|
||||
from modules.controlcenter.wifi import WifiConnections
|
||||
from services.brightness import Brightness
|
||||
from utils.roam import audio_service, modus_service
|
||||
from widgets.wayland import WaylandWindow as Window
|
||||
from modules.controlcenter.player import PlayerBoxStack
|
||||
from modules.controlcenter.per_app_volume import PerAppVolumeControl
|
||||
from modules.controlcenter.expanded_player import EmbeddedExpandedPlayer
|
||||
from services.mpris import MprisPlayerManager
|
||||
from services.network import NetworkClient
|
||||
from fabric.widgets.svg import Svg
|
||||
from fabric.utils.helpers import get_relative_path
|
||||
from utils.roam import audio_service, modus_service
|
||||
from widgets.wayland import WaylandWindow as Window
|
||||
|
||||
brightness_service = Brightness.get_initial()
|
||||
|
||||
# FIX: Icon not showing up in control center
|
||||
# TODO: Add Player
|
||||
|
||||
|
||||
class ModusControlCenter(Window):
|
||||
def __init__(self, **kwargs):
|
||||
@@ -48,6 +43,11 @@ class ModusControlCenter(Window):
|
||||
self._updating_brightness = False
|
||||
self._updating_volume = False
|
||||
|
||||
# Flight mode and caffeine states
|
||||
self.flight_mode = False
|
||||
self.caffeine_mode = False
|
||||
self._caffeine_process = None
|
||||
|
||||
# Lazy loading flags
|
||||
self._music_initialized = False
|
||||
self._per_app_volume_initialized = False
|
||||
@@ -64,6 +64,9 @@ class ModusControlCenter(Window):
|
||||
self.network_service = NetworkClient()
|
||||
self.wifi_service = None
|
||||
|
||||
# Initialize flight mode and caffeine states
|
||||
self._check_initial_states()
|
||||
|
||||
# Wait for network service to be ready
|
||||
|
||||
self.add_keybinding("Escape", self.hide_controlcenter)
|
||||
@@ -149,7 +152,9 @@ class ModusControlCenter(Window):
|
||||
|
||||
# Create placeholder music widget - lazy load content when needed
|
||||
self.music_widget = Box(
|
||||
name="music-widget", h_align="start", children=[] # Empty initially
|
||||
name="music-widget",
|
||||
h_align="start",
|
||||
children=[], # Empty initially
|
||||
)
|
||||
|
||||
self.has_bluetooth_open = False
|
||||
@@ -256,17 +261,77 @@ class ModusControlCenter(Window):
|
||||
on_clicked=self.set_dont_disturb,
|
||||
)
|
||||
|
||||
self.flight_icon = Svg(
|
||||
name="flight-icon",
|
||||
svg_file=get_relative_path(
|
||||
"../../config/assets/icons/applets/network-flightmode-on.svg"
|
||||
if self.flight_mode
|
||||
else "../../config/assets/icons/applets/network-flightmode-off.svg"
|
||||
),
|
||||
size=24,
|
||||
)
|
||||
|
||||
self.flight_widget = Button(
|
||||
name="flight-widget",
|
||||
child=Box(
|
||||
orientation="vertical",
|
||||
spacing=4,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
children=[
|
||||
self.flight_icon,
|
||||
Label(
|
||||
label="Flight",
|
||||
style_classes="title",
|
||||
h_align="center",
|
||||
),
|
||||
],
|
||||
),
|
||||
on_clicked=self.toggle_flight_mode,
|
||||
)
|
||||
|
||||
self.caffeine_icon = Svg(
|
||||
name="caffeine-icon",
|
||||
svg_file=get_relative_path(
|
||||
"../../config/assets/icons/applets/caffeine-cup-full.svg"
|
||||
if self.caffeine_mode
|
||||
else "../../config/assets/icons/applets/caffeine-cup-empty.svg"
|
||||
),
|
||||
size=24,
|
||||
)
|
||||
|
||||
self.caffeine_widget = Button(
|
||||
name="caffeine-widget",
|
||||
child=Box(
|
||||
orientation="vertical",
|
||||
spacing=4,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
children=[
|
||||
self.caffeine_icon,
|
||||
Label(
|
||||
label="Caffeine",
|
||||
style_classes="title",
|
||||
h_align="center",
|
||||
),
|
||||
],
|
||||
),
|
||||
on_clicked=self.toggle_caffeine,
|
||||
)
|
||||
|
||||
# Create main widgets directly without XML
|
||||
self.widgets = Box(
|
||||
orientation="vertical",
|
||||
h_expand=True,
|
||||
name="control-center-widgets",
|
||||
children=[
|
||||
# Top section: Wi-Fi + Bluetooth on left, DND + Flight Mode + Caffeine on right
|
||||
Box(
|
||||
orientation="horizontal",
|
||||
name="top-widget",
|
||||
h_expand=True,
|
||||
name="top-widget",
|
||||
children=[
|
||||
# Left side: Wi-Fi and Bluetooth
|
||||
Box(
|
||||
orientation="vertical",
|
||||
name="wb-widget",
|
||||
@@ -277,13 +342,44 @@ class ModusControlCenter(Window):
|
||||
self.bluetooth_widget,
|
||||
],
|
||||
),
|
||||
# Right side: DND, Flight Mode, and Caffeine
|
||||
Box(
|
||||
orientation="horizontal",
|
||||
name="dnd-widget",
|
||||
style_classes="menu",
|
||||
orientation="vertical",
|
||||
h_expand=True,
|
||||
name="right-side-widget",
|
||||
children=[
|
||||
self.focus_widget,
|
||||
# DND widget
|
||||
Box(
|
||||
orientation="vertical",
|
||||
name="dnd-widget",
|
||||
style_classes="menu",
|
||||
children=[
|
||||
self.focus_widget,
|
||||
],
|
||||
),
|
||||
# Flight Mode and Caffeine row
|
||||
Box(
|
||||
orientation="horizontal",
|
||||
name="flight-caffeine-row",
|
||||
children=[
|
||||
Box(
|
||||
orientation="vertical",
|
||||
name="flight-widget-container",
|
||||
style_classes="menu",
|
||||
children=[
|
||||
self.flight_widget,
|
||||
],
|
||||
),
|
||||
Box(
|
||||
orientation="vertical",
|
||||
name="caffeine-widget-container",
|
||||
style_classes="menu",
|
||||
children=[
|
||||
self.caffeine_widget,
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -521,6 +617,25 @@ class ModusControlCenter(Window):
|
||||
)
|
||||
self.expanded_player_center_box.set_size_request(300, -1)
|
||||
|
||||
def _check_initial_states(self):
|
||||
# Check if caffeine is already running
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["pgrep", "-f", "modus-inhibit"], capture_output=True, text=True
|
||||
)
|
||||
self.caffeine_mode = bool(result.stdout.strip())
|
||||
except Exception:
|
||||
self.caffeine_mode = False
|
||||
|
||||
# Flight mode starts as False (normal mode)
|
||||
self.flight_mode = False
|
||||
|
||||
# Update initial labels (will be set after widgets are created)
|
||||
GLib.timeout_add(100, self._update_initial_labels)
|
||||
|
||||
def _update_initial_labels(self):
|
||||
return False
|
||||
|
||||
def set_dont_disturb(self, *_):
|
||||
self.focus_mode = not self.focus_mode
|
||||
modus_service.dont_disturb = self.focus_mode
|
||||
@@ -532,6 +647,71 @@ class ModusControlCenter(Window):
|
||||
)
|
||||
)
|
||||
|
||||
def toggle_flight_mode(self, *_):
|
||||
try:
|
||||
self.flight_mode = not self.flight_mode
|
||||
|
||||
if self.flight_mode:
|
||||
# Turn off WiFi and Bluetooth
|
||||
if self.wifi_service:
|
||||
self.wifi_service.wireless_enabled = False
|
||||
if hasattr(self, "bluetooth_man") and hasattr(
|
||||
self.bluetooth_man, "client"
|
||||
):
|
||||
self.bluetooth_man.client.set_enabled(False)
|
||||
else:
|
||||
# Turn on WiFi and Bluetooth
|
||||
if self.wifi_service:
|
||||
self.wifi_service.wireless_enabled = True
|
||||
if hasattr(self, "bluetooth_man") and hasattr(
|
||||
self.bluetooth_man, "client"
|
||||
):
|
||||
self.bluetooth_man.client.set_enabled(True)
|
||||
|
||||
# Update icon
|
||||
self.flight_icon.set_from_file(
|
||||
get_relative_path(
|
||||
"../../config/assets/icons/applets/network-flightmode-on.svg"
|
||||
if self.flight_mode
|
||||
else "../../config/assets/icons/applets/network-flightmode-off.svg"
|
||||
)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to toggle flight mode: {e}")
|
||||
|
||||
def toggle_caffeine(self, *_):
|
||||
try:
|
||||
if self.caffeine_mode:
|
||||
# Turn off caffeine
|
||||
inhibit_script = get_relative_path("../../utils/inhibit.py")
|
||||
subprocess.run(["python3", inhibit_script, "off"], check=False)
|
||||
self.caffeine_mode = False
|
||||
if self._caffeine_process:
|
||||
try:
|
||||
self._caffeine_process.terminate()
|
||||
except:
|
||||
pass
|
||||
self._caffeine_process = None
|
||||
else:
|
||||
# Turn on caffeine
|
||||
inhibit_script = get_relative_path("../../utils/inhibit.py")
|
||||
self._caffeine_process = subprocess.Popen(
|
||||
["python3", inhibit_script, "on"], start_new_session=True
|
||||
)
|
||||
self.caffeine_mode = True
|
||||
|
||||
self.caffeine_icon.set_from_file(
|
||||
get_relative_path(
|
||||
"../../config/assets/icons/applets/caffeine-cup-full.svg"
|
||||
if self.caffeine_mode
|
||||
else "../../config/assets/icons/applets/caffeine-cup-empty.svg"
|
||||
)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to toggle caffeine: {e}")
|
||||
|
||||
def set_volume(self, _, __, volume):
|
||||
self._updating_volume = True
|
||||
audio_service.speaker.volume = round(volume)
|
||||
@@ -803,6 +983,14 @@ class ModusControlCenter(Window):
|
||||
except:
|
||||
pass
|
||||
|
||||
# Clean up caffeine process
|
||||
if self._caffeine_process:
|
||||
try:
|
||||
self._caffeine_process.terminate()
|
||||
except:
|
||||
pass
|
||||
self._caffeine_process = None
|
||||
|
||||
# Clean up heavy components
|
||||
if hasattr(self, "wifi_man") and self.wifi_man:
|
||||
self.wifi_man.destroy()
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
|
||||
#outer-player-box-c {
|
||||
min-height: 55px;
|
||||
min-width: 260px;
|
||||
min-width: 282px;
|
||||
border-radius: 8px;
|
||||
/* margin: 0 6px; */
|
||||
/* background-color: alpha(#000, 0.3); */
|
||||
|
||||
Reference in new issue
Block a user