diff --git a/config/assets/icons/applets/redshift-status-off.svg b/config/assets/icons/applets/redshift-status-off.svg
new file mode 100644
index 0000000..e81d366
--- /dev/null
+++ b/config/assets/icons/applets/redshift-status-off.svg
@@ -0,0 +1,94 @@
+
+
diff --git a/config/assets/icons/applets/redshift-status-on.svg b/config/assets/icons/applets/redshift-status-on.svg
new file mode 100644
index 0000000..aaa2959
--- /dev/null
+++ b/config/assets/icons/applets/redshift-status-on.svg
@@ -0,0 +1,86 @@
+
+
diff --git a/modules/controlcenter/main.py b/modules/controlcenter/main.py
index 3a1643e..cd1d9fb 100644
--- a/modules/controlcenter/main.py
+++ b/modules/controlcenter/main.py
@@ -14,6 +14,7 @@ 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.nightlight import create_night_light_widget
from modules.controlcenter.per_app_volume import PerAppVolumeControl
from modules.controlcenter.player import PlayerBoxStack
from modules.controlcenter.wifi import WifiConnections
@@ -298,17 +299,18 @@ class ModusControlCenter(Window):
self.flight_widget = Button(
name="flight-widget",
child=Box(
- orientation="h",
- spacing=4,
- h_align="start",
- v_align="center",
+ orientation="v",
h_expand=True,
+ v_expand=True,
+ spacing=8,
+ h_align="center",
+ v_align="center",
children=[
self.flight_icon,
Label(
label="Flight",
- style_classes="title",
- h_align="start",
+ style_classes="title-widget",
+ h_align="center",
),
],
),
@@ -334,32 +336,37 @@ class ModusControlCenter(Window):
self.caffeine_widget = Button(
name="caffeine-widget",
child=Box(
- orientation="h",
- spacing=4,
- h_align="start",
+ orientation="v",
+ spacing=8,
+ h_expand=True,
+ v_expand=True,
+ h_align="center",
v_align="center",
children=[
self.caffeine_icon,
- Box(
- orientation="vertical",
- v_expand=True,
- v_align="center",
- h_align="start",
- h_expand=True,
- children=[
- Label(
- label="Caffeine",
- style_classes="title-widget",
- h_align="start",
- ),
- self.caffeine_status_label,
- ],
+ Label(
+ label="Caffeine",
+ style_classes="title-widget",
+ h_align="center",
),
+ # Box(
+ # orientation="vertical",
+ # v_expand=True,
+ # v_align="center",
+ # h_align="center",
+ # h_expand=True,
+ # children=[
+ # # self.caffeine_status_label,
+ # ],
+ # ),
],
),
on_clicked=self.toggle_caffeine,
)
+ # Create night light widget
+ self.night_light_widget = create_night_light_widget(self)
+
# Create main widgets directly without XML
self.widgets = Box(
orientation="vertical",
@@ -381,6 +388,7 @@ class ModusControlCenter(Window):
children=[
self.wlan_widget,
self.bluetooth_widget,
+ self.night_light_widget,
],
),
# Right side: DND, Flight Mode, and Caffeine
@@ -403,19 +411,21 @@ class ModusControlCenter(Window):
orientation="horizontal",
name="flight-caffeine-row",
children=[
- # Box(
- # orientation="vertical",
- # name="flight-widget-container",
- # style_classes="menu",
- # h_expand=True,
- # children=[
- # self.flight_widget,
- # ],
- # ),
+ Box(
+ orientation="vertical",
+ name="flight-widget-container",
+ style_classes="menu",
+ h_expand=True,
+ v_expand=True,
+ children=[
+ self.flight_widget,
+ ],
+ ),
Box(
orientation="vertical",
name="caffeine-widget-container",
h_expand=True,
+ v_expand=True,
style_classes="menu",
children=[
self.caffeine_widget,
diff --git a/modules/controlcenter/nightlight.py b/modules/controlcenter/nightlight.py
new file mode 100644
index 0000000..c5414c2
--- /dev/null
+++ b/modules/controlcenter/nightlight.py
@@ -0,0 +1,146 @@
+# Standard library imports
+import subprocess
+
+# Fabric imports
+from fabric.utils.helpers import get_relative_path
+from fabric.widgets.box import Box
+from fabric.widgets.button import Button
+from fabric.widgets.label import Label
+from fabric.widgets.svg import Svg
+
+# Local imports
+from loguru import logger
+
+
+class NightLightControl:
+ """Control night light using hyprsunset"""
+
+ def __init__(self):
+ self.is_active = False
+ self._check_initial_state()
+
+ def _check_initial_state(self):
+ """Check if hyprsunset is currently running"""
+ try:
+ result = subprocess.run(
+ ["pgrep", "-f", "hyprsunset"], capture_output=True, text=True
+ )
+ self.is_active = bool(result.stdout.strip())
+ except Exception as e:
+ logger.warning(f"Failed to check hyprsunset status: {e}")
+ self.is_active = False
+
+ def toggle(self):
+ """Toggle night light on/off"""
+ try:
+ if self.is_active:
+ # Turn off night light by killing hyprsunset
+ subprocess.run(["pkill", "hyprsunset"], check=False)
+ self.is_active = False
+ logger.debug("Night light turned off")
+ else:
+ # Turn on night light with default temperature (3000K)
+ subprocess.Popen(["hyprsunset", "-t", "4500"], start_new_session=True)
+ self.is_active = True
+ logger.debug("Night light turned on")
+ return True
+ except Exception as e:
+ logger.warning(f"Failed to toggle night light: {e}")
+ return False
+
+ def set_temperature(self, temperature: int):
+ """Set night light temperature (1000-6500K)"""
+ try:
+ # Kill existing process
+ subprocess.run(["pkill", "hyprsunset"], check=False)
+
+ # Start with new temperature
+ subprocess.Popen(
+ ["hyprsunset", "-t", str(temperature)], start_new_session=True
+ )
+ self.is_active = True
+ logger.debug(f"Night light temperature set to {temperature}K")
+ return True
+ except Exception as e:
+ logger.warning(f"Failed to set night light temperature: {e}")
+ return False
+
+
+def create_night_light_widget(control_center):
+ """Create night light widget for control center"""
+
+ # Initialize night light control
+ night_light = NightLightControl()
+
+ # Create icon
+ night_light_icon = Svg(
+ name="nightlight-icon",
+ svg_file=get_relative_path(
+ "../../config/assets/icons/applets/redshift-status-on.svg"
+ if night_light.is_active
+ else "../../config/assets/icons/applets/redshift-status-off.svg"
+ ),
+ size=42,
+ )
+
+ # Create status label
+ night_light_status_label = Label(
+ label="On" if night_light.is_active else "Off",
+ name="nightlight-widget-label",
+ style_classes="status-label",
+ max_chars_width=15,
+ ellipsization="end",
+ h_align="start",
+ )
+
+ def toggle_night_light(*_):
+ """Toggle night light and update UI"""
+ if night_light.toggle():
+ # Update icon
+ night_light_icon.set_from_file(
+ get_relative_path(
+ "../../config/assets/icons/applets/redshift-status-on.svg"
+ if night_light.is_active
+ else "../../config/assets/icons/applets/redshift-status-off.svg"
+ )
+ )
+ # Update status label
+ night_light_status_label.set_label("On" if night_light.is_active else "Off")
+
+ # Create widget box (similar to bluetooth_widget structure)
+ night_light_widget = Box(
+ name="nightlight-widget",
+ orientation="h",
+ h_expand=True,
+ children=[
+ Button(
+ name="nightlight-icon-button",
+ child=night_light_icon,
+ on_clicked=toggle_night_light,
+ ),
+ Button(
+ name="nightlight-info-button",
+ child=Box(
+ name="nightlight-widget-info",
+ h_expand=True,
+ v_expand=True,
+ v_align="center",
+ h_align="start",
+ orientation="vertical",
+ children=[
+ Label(
+ name="nightlight-widget-name",
+ label="Night Light",
+ style_classes="ct",
+ h_align="start",
+ ),
+ night_light_status_label,
+ ],
+ ),
+ on_clicked=toggle_night_light,
+ ),
+ ],
+ )
+
+ return night_light_widget
+
diff --git a/modules/controlcenter/player.py b/modules/controlcenter/player.py
index 6587b86..d5a6fd4 100644
--- a/modules/controlcenter/player.py
+++ b/modules/controlcenter/player.py
@@ -720,16 +720,17 @@ class PlayerBox(Box):
# ],
)
- self.box = Box(
+ self.box = CenterBox(
name="box-c",
orientation="h",
h_align="center",
- h_expand=True,
- children=[
+ start_children=[
self.outer_box,
- self.button_box,
# self.stack_buttons_box,
],
+ end_children=[
+ self.button_box,
+ ],
)
self.children = [
diff --git a/styles/controlcenter.css b/styles/controlcenter.css
index 95bf359..a60738d 100644
--- a/styles/controlcenter.css
+++ b/styles/controlcenter.css
@@ -50,9 +50,10 @@
}
/* Widgets */
#wifi-widget,
-#bluetooth-widget {
+#bluetooth-widget,
+#nightlight-widget {
min-width: 140px;
- padding: 10px 0 0px 0;
+ padding: 5px 0 0px 0;
}
.icon {
@@ -62,7 +63,8 @@
}
#bluetooth-widget-label,
-#wifi-widget-label {
+#wifi-widget-label,
+#nightlight-widget-label {
font-size: 12px;
margin-left: 5px;
font-weight: 500;
@@ -283,7 +285,8 @@
}
#bluetooth-widget-name,
-#wifi-widget-name {
+#wifi-widget-name,
+#nightlight-widget-name {
margin-top: 6px;
font-size: 14px;
font-weight: bold;
@@ -953,9 +956,9 @@
/* margin-right: 8px; */
}
-#flight-icon {
- margin-left: -10px;
-}
+/* #flight-icon { */
+/* margin-left: -10px; */
+/* } */
.title-widget {
/* margin-top: -14px; */
@@ -978,3 +981,8 @@
#app-control-box {
min-width: 100px;
}
+#caffeine-widget,
+#flight-widget {
+ padding: 0px 0 5px 0;
+ min-width: 50px;
+}
diff --git a/styles/player.css b/styles/player.css
index 8e6398d..bae0196 100644
--- a/styles/player.css
+++ b/styles/player.css
@@ -56,7 +56,7 @@
margin-bottom: 0.5rem;
min-height: 50px;
- min-width: 220px;
+ min-width: 330px;
/* border-radius: 8px; */
/* margin: 0 6px 10px; */
/* border: 0.5px solid alpha(#000, 0.4); */