From 957a035659ce180dab90b8f4d78a6e952e62d28c Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Thu, 24 Sep 2026 17:31:13 +0530 Subject: [PATCH 01/13] chore(flake.lock): bump flake.lock inputs --- flake.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/flake.lock b/flake.lock index 531d7a71..6cd86598 100644 --- a/flake.lock +++ b/flake.lock @@ -250,11 +250,11 @@ ] }, "locked": { - "lastModified": 1790128814, - "narHash": "sha256-6Gm9q+wW3E4Ey4F6wEbJAwaMsEK6hvCYfTW7yY64ZfA=", + "lastModified": 1790225410, + "narHash": "sha256-BOyZoliWfm/beS4m3FxFKlu5at6npZen1PsWtvzzihk=", "owner": "nix-community", "repo": "home-manager", - "rev": "0b2f1129177f70c5f0f5d88bb53c49ca47d0bfc0", + "rev": "4900baf1e219645e4a2acba35723852b2091bc20", "type": "github" }, "original": { @@ -339,11 +339,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1790080419, - "narHash": "sha256-ltWq63fW4EsgkSS0w7H2cdjsQhlQ5v0JzTXFM4K5aTA=", + "lastModified": 1790173459, + "narHash": "sha256-GR2NqjxK1C+Z2JxuwmpyaSvTwBCuKFqiznuQKRfSLYQ=", "ref": "refs/heads/main", - "rev": "23118f9f7f24db7447069949c2df7fcd8ba380d0", - "revCount": 7827, + "rev": "e368c13c27a42a173b9e08fa0bf413f9f7073187", + "revCount": 7828, "submodules": true, "type": "git", "url": "https://github.com/hyprwm/Hyprland" @@ -587,11 +587,11 @@ }, "mnw": { "locked": { - "lastModified": 1780772958, - "narHash": "sha256-VKKe8r4pwCGWZ3Yr9CPN129R4S3CKLSrlYqdYz3vKpM=", + "lastModified": 1784154424, + "narHash": "sha256-HRn4O1X2ShYtbq5Egji72/aemyc2cIQicjRZD9hBqM8=", "owner": "Gerg-L", "repo": "mnw", - "rev": "0871dbf63a53610c95db04439ed8ea4d6ec9c160", + "rev": "0151d9fa87992cbeb67c86616fb9170dcec830b6", "type": "github" }, "original": { @@ -765,11 +765,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1790046670, - "narHash": "sha256-MYiI+CzL0tuWgRPjGsKCDHqYs2T3OzMlMQWOYWG0qso=", + "lastModified": 1790185690, + "narHash": "sha256-xJ+X4hBtOcAFGBOe5nAMyMUeF9foJBmIOu3NjBqBycU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6774f7bc253789b113a4f39285dc0fa100abeacc", + "rev": "4975466d324710c576dc11ad614684e6bd8cad8e", "type": "github" }, "original": { @@ -788,11 +788,11 @@ ] }, "locked": { - "lastModified": 1789854559, - "narHash": "sha256-6GDssza3F+ukpUujSuTL50vW5AHaoG+4vjsDgWqRyeQ=", + "lastModified": 1790221470, + "narHash": "sha256-TzyWd4i7YCpqoF9xB8mfgDJ2sviAZysKH9R8YbQGjqA=", "owner": "notashelf", "repo": "nvf", - "rev": "85bf39cd0409ad8a7fa5b3ad0d29e89e9da97a0e", + "rev": "95afe7a794216f53e217c5148c6fbe0b668192cf", "type": "github" }, "original": { @@ -847,11 +847,11 @@ ] }, "locked": { - "lastModified": 1789890976, - "narHash": "sha256-GKwH3zpy7tartuJMG0Rv/xUsdetG1QLmTVv8UKgJLmA=", + "lastModified": 1790247521, + "narHash": "sha256-TNfgoHsqsYYvaJImlWctfRkh4PseTagzegU1Dgdbehw=", "owner": "Mic92", "repo": "sops-nix", - "rev": "7214124c20c1542c90deb54af50e2f53ae02711f", + "rev": "2bd00bd9bb35fe6d114888c8f1c2e946c541dd8f", "type": "github" }, "original": { @@ -979,11 +979,11 @@ ] }, "locked": { - "lastModified": 1790160881, - "narHash": "sha256-VTHBBI0EvApXSssCthrYLsrGN4/0nM/tW9A17NEmKEU=", + "lastModified": 1790234305, + "narHash": "sha256-zgshjjI5uhmRQor+bmXH4EYx/E0LUdJEqv0L8WnTFOw=", "owner": "0xc000022070", "repo": "zen-browser-flake", - "rev": "1b16ef2b81078b5f363e6bb689d2193f8eccadb7", + "rev": "2b7fec6557495d97736f1b31904f79312671ca2a", "type": "github" }, "original": { From 0f389bb26ab7ff80005155cb3e05f528884441af Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:25:32 +0530 Subject: [PATCH 02/13] fix(calendar): add SystemClock bindings for reactive midnight updates Replace one-shot new Date() calls with SystemClock (minute precision) for reactive todayYear/todayMonth/todayDate properties. The grid now recalculates at midnight and the footer date auto-updates. Also resets to today when the popup is reopened via onVisibleChanged. --- .../surfaces/components/CalendarPopup.qml | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/shell/desktop/surfaces/components/CalendarPopup.qml b/shell/desktop/surfaces/components/CalendarPopup.qml index 91310272..b592ce24 100644 --- a/shell/desktop/surfaces/components/CalendarPopup.qml +++ b/shell/desktop/surfaces/components/CalendarPopup.qml @@ -46,14 +46,30 @@ Rectangle { // Calendar State & Calculations // ========================================================================= - property int viewYear: (new Date()).getFullYear() - property int viewMonth: (new Date()).getMonth() + SystemClock { + id: systemClock + + precision: SystemClock.Minute + } + + property int todayYear: systemClock.date.getFullYear() + property int todayMonth: systemClock.date.getMonth() + property int todayDate: systemClock.date.getDate() + + property int viewYear: todayYear + property int viewMonth: todayMonth readonly property var monthNames: ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"] readonly property var dayHeaders: ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"] - readonly property var gridCells: generateCalendarCells(root.viewYear, root.viewMonth) + readonly property var gridCells: generateCalendarCells(root.viewYear, root.viewMonth, root.todayYear, root.todayMonth, root.todayDate) + + onVisibleChanged: { + if (visible) { + resetToToday(); + } + } function previousMonth(): void { if (viewMonth === 0) { @@ -74,17 +90,12 @@ Rectangle { } function resetToToday(): void { - const now = new Date(); - viewYear = now.getFullYear(); - viewMonth = now.getMonth(); + viewYear = todayYear; + viewMonth = todayMonth; } - function generateCalendarCells(year: int, month: int): var { + function generateCalendarCells(year: int, month: int, tYear: int, tMonth: int, tDate: int): var { const cells = []; - const today = new Date(); - const todayYear = today.getFullYear(); - const todayMonth = today.getMonth(); - const todayDate = today.getDate(); const firstDay = new Date(year, month, 1); const firstDayIndex = (firstDay.getDay() + 6) % 7; @@ -111,7 +122,7 @@ Rectangle { cellYear = month === 11 ? year + 1 : year; } - const isToday = (cellYear === todayYear && cellMonth === todayMonth && dayNum === todayDate && isCurrentMonth); + const isToday = (cellYear === tYear && cellMonth === tMonth && dayNum === tDate && isCurrentMonth); cells.push({ day: dayNum, @@ -361,7 +372,7 @@ Rectangle { color: Theme.textMuted font.family: Theme.fontFamilyMonospace font.pixelSize: Theme.fontSizeCaption - text: "// " + Qt.formatDateTime(new Date(), "yyyy-MM-dd") + text: "// " + Qt.formatDateTime(systemClock.date, "yyyy-MM-dd") } Rectangle { From b8bd4959644b9d81d0301aa948dce2f2d47a0e3c Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:25:37 +0530 Subject: [PATCH 03/13] feat(settings): add notificationCooldownSeconds setting Add configurable cooldown window (default 30s) for notification deduplication. Wired into save, parse, and resetToDefaults logic. --- shell/desktop/core/Settings.qml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shell/desktop/core/Settings.qml b/shell/desktop/core/Settings.qml index 46f73cc5..a98d3d5c 100644 --- a/shell/desktop/core/Settings.qml +++ b/shell/desktop/core/Settings.qml @@ -38,6 +38,8 @@ Singleton { readonly property bool defaultWidgetTargetProfilerVisible: true property bool featuresCommandDeck: true property bool featuresNotifications: true + property int notificationCooldownSeconds: 30 + readonly property int defaultNotificationCooldownSeconds: 30 property bool featuresSystemRail: true // Indicator if configuration was successfully loaded from disk @@ -132,6 +134,14 @@ Singleton { featuresNotifications = defaultFeaturesNotifications; } + if (typeof data.notificationCooldownSeconds === "number" && Number.isInteger(data.notificationCooldownSeconds) && data.notificationCooldownSeconds >= 0) { + notificationCooldownSeconds = data.notificationCooldownSeconds; + } else if (data.features && typeof data.features.notificationCooldownSeconds === "number" && Number.isInteger(data.features.notificationCooldownSeconds) && data.features.notificationCooldownSeconds >= 0) { + notificationCooldownSeconds = data.features.notificationCooldownSeconds; + } else { + notificationCooldownSeconds = defaultNotificationCooldownSeconds; + } + // barHeight: supports flat key or nested bar.height if (typeof data.barHeight === "number" && Number.isInteger(data.barHeight) && data.barHeight > 0) { barHeight = data.barHeight; @@ -311,6 +321,7 @@ Singleton { data.featuresCommandDeck = root.featuresCommandDeck; data.featuresSystemRail = root.featuresSystemRail; data.featuresNotifications = root.featuresNotifications; + data.notificationCooldownSeconds = root.notificationCooldownSeconds; data.barHeight = root.barHeight; data.theme = root.theme; data.wallpaper = root.wallpaper; @@ -511,6 +522,7 @@ Singleton { featuresCommandDeck = defaultFeaturesCommandDeck; featuresSystemRail = defaultFeaturesSystemRail; featuresNotifications = defaultFeaturesNotifications; + notificationCooldownSeconds = defaultNotificationCooldownSeconds; barHeight = defaultBarHeight; theme = defaultTheme; wallpaper = defaultWallpaper; From 82503adce23f5378fda8d1bf4c3be4a34c791033 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:25:44 +0530 Subject: [PATCH 04/13] fix(notifications): add dedup filter to suppress rapid-fire toasts Track recently shown notifications by appName|summary key. If the same pair fires again within the cooldown window, suppress the toast popup while still recording to history. Prevents bluetooth mouse sleep/wake notification spam from external daemons. --- .../desktop/services/NotificationService.qml | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/shell/desktop/services/NotificationService.qml b/shell/desktop/services/NotificationService.qml index 532f878a..c61c4e52 100644 --- a/shell/desktop/services/NotificationService.qml +++ b/shell/desktop/services/NotificationService.qml @@ -53,6 +53,9 @@ Singleton { // Map of notifId -> raw Notification object property var _notificationObjects: ({}) + // Map of "appName|summary" -> timestamp + property var _recentNotifications: ({}) + // Component for instantiating per-toast auto-expiry timers Component { id: toastTimerComponent @@ -178,6 +181,25 @@ Singleton { } catch (e) {} } + const dedupKey = appName + "|" + summary; + const now = Date.now(); + + // Clean up expired entries to prevent memory leak + const cutoff = now - Settings.notificationCooldownSeconds * 1000; + for (let key in root._recentNotifications) { + if (root._recentNotifications[key] < cutoff) { + delete root._recentNotifications[key]; + } + } + + let isDuplicate = false; + if (root._recentNotifications[dedupKey] !== undefined) { + if (now - root._recentNotifications[dedupKey] < Settings.notificationCooldownSeconds * 1000) { + isDuplicate = true; + } + } + root._recentNotifications[dedupKey] = now; + const record = { notifId: notifId, id: notifId, @@ -199,7 +221,7 @@ Singleton { } historyModel.insert(0, record); - if (!root.doNotDisturb) { + if (!root.doNotDisturb && !isDuplicate) { for (let t = activeToastsModel.count - 1; t >= 0; --t) { const existingToast = activeToastsModel.get(t); if (existingToast && (existingToast.notifId === notifId || existingToast.id === notifId)) { From f07413022304f97fe26afe04239e42befbf8dd7e Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:25:51 +0530 Subject: [PATCH 05/13] fix(lifecycle): replace pkill with flock-based single-instance lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous pkill wrapper was racy and could fight with systemd's restart policy. Use flock on a lockfile instead — if another instance is already running, exit 0 silently (no systemd restart loop). This properly prevents duplicate bars on logout/login cycles. --- shell/nix/package.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shell/nix/package.nix b/shell/nix/package.nix index 590dda5a..ce806297 100644 --- a/shell/nix/package.nix +++ b/shell/nix/package.nix @@ -23,8 +23,13 @@ stdenvNoCC.mkDerivation { mkdir -p "$out/bin" cat << 'EOF' > "$out/bin/ctos-shell" #!/bin/sh - # Kill any existing instances to prevent duplicates - pkill -f "quickshell.*shell.qml" || true + LOCKFILE="''${XDG_RUNTIME_DIR:-/tmp}/ctos-shell.lock" + exec 9>"$LOCKFILE" + if ! flock -n 9; then + echo "ctos-shell: another instance is already running" >&2 + exit 0 + fi + echo $$ >&9 EOF cat << BIN >> "$out/bin/ctos-shell" exec ${pkgs.quickshell}/bin/quickshell -n -p "$out/share/ctos/shell.qml" "\$@" From ac4374df0d0edf503a83516d2e499a7e85a7baad Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:25:58 +0530 Subject: [PATCH 06/13] fix(lifecycle): remove redundant ctos-shell exec from compositors Remove direct ctos-shell launch from Hyprland and Niri startup configs. The systemd user service already auto-starts via graphical-session.target, making these duplicate triggers the source of the startup race condition. --- modules/features/desktop/hyprland.nix | 1 - modules/features/desktop/niri.nix | 3 --- 2 files changed, 4 deletions(-) diff --git a/modules/features/desktop/hyprland.nix b/modules/features/desktop/hyprland.nix index 7c315b00..ad8ea276 100644 --- a/modules/features/desktop/hyprland.nix +++ b/modules/features/desktop/hyprland.nix @@ -45,7 +45,6 @@ let hl.on("hyprland.start", function() hl.exec_cmd("dbus-update-activation-environment --systemd DISPLAY HYPRLAND_INSTANCE_SIGNATURE WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE && systemctl --user stop hyprland-session.target && systemctl --user start hyprland-session.target") hl.exec_cmd("systemctl --user start hyprpolkitagent") - hl.exec_cmd("ctos-shell") end) hl.config({ diff --git a/modules/features/desktop/niri.nix b/modules/features/desktop/niri.nix index 78f799e5..aa063243 100644 --- a/modules/features/desktop/niri.nix +++ b/modules/features/desktop/niri.nix @@ -52,9 +52,6 @@ let "systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP DISPLAY GTK_USE_PORTAL NIRI_SOCKET && systemctl --user start nixos-fake-graphical-session.target" ]; } - { - command = [ "ctos-shell" ]; - } { command = [ "hypridle" ]; } From 7e97ef77178d4f303986b1935709a6800cd778a6 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:26:04 +0530 Subject: [PATCH 07/13] fix(lifecycle): tighten systemd service config Set Type=simple explicitly and increase RestartSec from 2 to 3 for more breathing room between restart attempts. --- shell/nix/home-manager.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/nix/home-manager.nix b/shell/nix/home-manager.nix index 9c859782..3149cef2 100644 --- a/shell/nix/home-manager.nix +++ b/shell/nix/home-manager.nix @@ -23,9 +23,10 @@ in }; Service = { + Type = "simple"; ExecStart = "${ctosPackage}/bin/ctos-shell"; Restart = "on-failure"; - RestartSec = 2; + RestartSec = 3; StartLimitBurst = 5; StartLimitIntervalSec = 30; }; From 1e22626ad1d329c36f332703d1a1668b5ec8f062 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:26:12 +0530 Subject: [PATCH 08/13] fix(greeter): fix employee ID card SVG alignment and add ACCESS field - Fix user.svg overflow: add anchors.fill + fillMode PreserveAspectFit - Reduce ColumnLayout/RowLayout spacing from 15/10 to 6/6 to fit card - Add valueColor property to InfoField component - Add red ACCESS RESTRICTED field to the identity card row - Wire employeeAccess into the reveal animation sequence --- shell/greeter/components/IdentityCard.qml | 25 +++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/shell/greeter/components/IdentityCard.qml b/shell/greeter/components/IdentityCard.qml index 8d9ea73f..c8438b85 100644 --- a/shell/greeter/components/IdentityCard.qml +++ b/shell/greeter/components/IdentityCard.qml @@ -12,6 +12,7 @@ Item { id: field property string label: "FIELD" property string value: "VALUE" + property color valueColor: Theme.textPrimary property alias fieldValueOpacity: fieldValue.opacity Text { @@ -27,7 +28,7 @@ Item { Text { id: fieldValue text: field.value - color: Theme.textPrimary + color: field.valueColor font { family: Settings.fontFamily pixelSize: 22 @@ -40,11 +41,11 @@ Item { width: parent.width * 0.55 height: parent.height - spacing: 15 + spacing: 6 RowLayout { id: row - spacing: 10 + spacing: 6 InfoField { id: employeeId @@ -71,6 +72,14 @@ Item { return "OPERATOR"; } } + InfoField { + id: employeeAccess + Layout.fillWidth: true + Layout.preferredWidth: 1 + label: "ACCESS" + value: "RESTRICTED" + valueColor: "#ff3333" + } } InfoField { @@ -110,6 +119,8 @@ Item { Image { source: "../resources/user.svg" opacity: 0.9 + anchors.fill: parent + fillMode: Image.PreserveAspectFit } } @@ -125,7 +136,7 @@ Item { value: 0 } PropertyAction { - targets: [employeeId, employeeClass, employeeName] + targets: [employeeId, employeeClass, employeeAccess, employeeName] property: "fieldValueOpacity" value: 0 } @@ -157,6 +168,12 @@ Item { to: 1 duration: 150 } + NumberAnimation { + target: employeeAccess + property: "fieldValueOpacity" + to: 1 + duration: 150 + } SequentialAnimation { PauseAnimation { From eb8db4dfe6d14966c71bf94c63f01879e6627073 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:26:19 +0530 Subject: [PATCH 09/13] feat(greeter): green accent flash on successful authentication Add tintColor property to Accents component with ColorOverlay on each corner bracket SVG. On auth success, set tint to #00ff41 (hacker green) during the identity card reveal, then reset to transparent when transitioning back to the field group. --- shell/greeter/common/components/Accents.qml | 20 ++++++++++++++++++++ shell/greeter/components/MainLayout.qml | 2 ++ 2 files changed, 22 insertions(+) diff --git a/shell/greeter/common/components/Accents.qml b/shell/greeter/common/components/Accents.qml index 4652a95c..efcbe842 100644 --- a/shell/greeter/common/components/Accents.qml +++ b/shell/greeter/common/components/Accents.qml @@ -2,6 +2,8 @@ import QtQuick import qs.greeter.config +import Qt5Compat.GraphicalEffects + Item { id: root @@ -12,6 +14,8 @@ Item { property bool animate: true property int individualSize: 4 + property color tintColor: "transparent" + property int startingHorizontalOffset: 0 property int startingVerticalOffset: 0 @@ -44,6 +48,10 @@ Item { top: root.top topMargin: root._verticalOffset } + layer.enabled: !Qt.colorEqual(root.tintColor, "transparent") + layer.effect: ColorOverlay { + color: root.tintColor + } } Image { @@ -58,6 +66,10 @@ Item { bottomMargin: root._verticalOffset } rotation: 270 + layer.enabled: !Qt.colorEqual(root.tintColor, "transparent") + layer.effect: ColorOverlay { + color: root.tintColor + } } Image { @@ -72,6 +84,10 @@ Item { topMargin: root._verticalOffset } rotation: 90 + layer.enabled: !Qt.colorEqual(root.tintColor, "transparent") + layer.effect: ColorOverlay { + color: root.tintColor + } } Image { @@ -86,6 +102,10 @@ Item { bottomMargin: root._verticalOffset } rotation: 180 + layer.enabled: !Qt.colorEqual(root.tintColor, "transparent") + layer.effect: ColorOverlay { + color: root.tintColor + } } ParallelAnimation { diff --git a/shell/greeter/components/MainLayout.qml b/shell/greeter/components/MainLayout.qml index 3ca2b62e..f720f2b3 100644 --- a/shell/greeter/components/MainLayout.qml +++ b/shell/greeter/components/MainLayout.qml @@ -345,6 +345,7 @@ Item { script: { fieldGroup.opacity = 0; accents.state = "identity_card"; + accents.tintColor = "#00ff41"; identityCard.start(); } } @@ -355,6 +356,7 @@ Item { script: { identityCard.opacity = 0; accents.state = "field_group"; + accents.tintColor = "transparent"; fieldGroup.opacity = 1; fieldGroup.start(); } From 4bde477a66c03f19a5852b36b7c59f121898083a Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:26:49 +0530 Subject: [PATCH 10/13] fix(calendar): re-establish reactive binding on resetToToday Use Qt.binding() in resetToToday() so viewYear/viewMonth track the clock reactively after reset. This way if the popup stays open past midnight after a reset, the view continues to follow the system date. --- shell/desktop/surfaces/components/CalendarPopup.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/desktop/surfaces/components/CalendarPopup.qml b/shell/desktop/surfaces/components/CalendarPopup.qml index b592ce24..26f2d9a9 100644 --- a/shell/desktop/surfaces/components/CalendarPopup.qml +++ b/shell/desktop/surfaces/components/CalendarPopup.qml @@ -90,8 +90,8 @@ Rectangle { } function resetToToday(): void { - viewYear = todayYear; - viewMonth = todayMonth; + viewYear = Qt.binding(function() { return todayYear; }); + viewMonth = Qt.binding(function() { return todayMonth; }); } function generateCalendarCells(year: int, month: int, tYear: int, tMonth: int, tDate: int): var { From 943e4fed468ed4a436bdb4aadfb3b811a2271930 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 04:35:23 +0530 Subject: [PATCH 11/13] feat(boot): enable os-prober in grub bootloader config --- modules/features/core/boot.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/features/core/boot.nix b/modules/features/core/boot.nix index 2ded8d8e..c39c97ed 100644 --- a/modules/features/core/boot.nix +++ b/modules/features/core/boot.nix @@ -31,6 +31,7 @@ in enable = true; efiSupport = true; device = "nodev"; + useOSProber = true; dedsec-theme = { enable = true; style = "legion"; From 9183aec602c8b38c4fa45639f9e0262f2a29ff77 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 11:30:07 +0530 Subject: [PATCH 12/13] fix(greeter): rewrite IdentityCard layout to fix SVG alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace broken disconnected ColumnLayout+anchored-Item approach with a clean unified RowLayout filling the full card: - Single RowLayout splits left info column (fillWidth) from right photo panel (fixed 32% of card width) — eliminates the 51px dead space gap - Barcode height constrained by its 241:72 aspect ratio via Layout.preferredHeight so it never overflows or collapses - Font sizes now scale with Units.vh for HiDPI consistency - user.svg properly anchored with inset margin inside photo panel - ACCESS field uses Theme.accentRed instead of hardcoded #ff3333 - All layout positions anchors.fill: parent so nothing floats at (0,0) --- shell/greeter/components/IdentityCard.qml | 159 ++++++++++++---------- 1 file changed, 90 insertions(+), 69 deletions(-) diff --git a/shell/greeter/components/IdentityCard.qml b/shell/greeter/components/IdentityCard.qml index c8438b85..f487460a 100644 --- a/shell/greeter/components/IdentityCard.qml +++ b/shell/greeter/components/IdentityCard.qml @@ -8,6 +8,10 @@ import qs.greeter.services Item { id: root + // ========================================================================= + // InfoField inline component + // ========================================================================= + component InfoField: Column { id: field property string label: "FIELD" @@ -21,7 +25,7 @@ Item { color: Theme.textPrimaryDim font { family: Settings.fontFamily - pixelSize: 14 + pixelSize: Math.round(11 * Units.vh) } } @@ -31,99 +35,116 @@ Item { color: field.valueColor font { family: Settings.fontFamily - pixelSize: 22 + pixelSize: Math.round(17 * Units.vh) weight: 500 } + elide: Text.ElideRight } } - ColumnLayout { - width: parent.width * 0.55 - height: parent.height + // ========================================================================= + // Card layout — unified RowLayout splitting left info from right photo + // ========================================================================= - spacing: 6 + RowLayout { + anchors.fill: parent + spacing: 0 - RowLayout { - id: row - spacing: 6 + // ── Left column: fields + barcode ──────────────────────────────────── + ColumnLayout { + id: infoColumn + Layout.fillWidth: true + Layout.fillHeight: true + spacing: Math.round(4 * Units.vh) - InfoField { - id: employeeId + // Row 1: EMPID / CLASS / ACCESS + RowLayout { Layout.fillWidth: true - Layout.preferredWidth: 1 - label: "EMPID ##" - value: SessionManager.activeUser ? ("UID-" + SessionManager.activeUser.uid) : "UID-STANDBY" - } - InfoField { - id: employeeClass - Layout.fillWidth: true - Layout.preferredWidth: 1 - label: "CLASS" - value: { - if (!SessionManager.activeUser) { - return "STANDBY"; - } - if (SessionManager.activeUser.uid === 0) { - return "L0_ROOT"; - } - if (SessionManager.activeUser.uid === 1000) { - return "L5_ADMIN"; + spacing: Math.round(6 * Units.vh) + + InfoField { + id: employeeId + Layout.fillWidth: true + Layout.preferredWidth: 1 + label: "EMPID ##" + value: SessionManager.activeUser ? ("UID-" + SessionManager.activeUser.uid) : "UID-STANDBY" + } + InfoField { + id: employeeClass + Layout.fillWidth: true + Layout.preferredWidth: 1 + label: "CLASS" + value: { + if (!SessionManager.activeUser) { + return "STANDBY"; + } + if (SessionManager.activeUser.uid === 0) { + return "L0_ROOT"; + } + if (SessionManager.activeUser.uid === 1000) { + return "L5_ADMIN"; + } + return "OPERATOR"; } - return "OPERATOR"; + } + InfoField { + id: employeeAccess + Layout.fillWidth: true + Layout.preferredWidth: 1 + label: "ACCESS" + value: "RESTRICTED" + valueColor: Theme.accentRed } } + + // Row 2: Full name InfoField { - id: employeeAccess + id: employeeName Layout.fillWidth: true - Layout.preferredWidth: 1 - label: "ACCESS" - value: "RESTRICTED" - valueColor: "#ff3333" + label: "FULL NAME" + value: SessionManager.activeUser ? SessionManager.activeUser.username.toUpperCase() : "UNKNOWN" } - } - InfoField { - id: employeeName - Layout.fillWidth: true - label: "FULL NAME" - value: SessionManager.activeUser ? SessionManager.activeUser.username.toUpperCase() : "UNKNOWN" + // Spacer + Item { + Layout.fillHeight: true + } + + // Row 3: Barcode — constrain height by aspect ratio of the SVG (241:72) + Image { + Layout.fillWidth: true + Layout.preferredHeight: Math.round(width * (72 / 241)) + fillMode: Image.Stretch + source: "../resources/id-barcode.svg" + } } + // ── Right column: profile picture ───────────────────────────────────── Item { + id: profilePicture + // Keep the photo panel square-ish: take 32% of total card width + Layout.preferredWidth: Math.round(root.width * 0.32) Layout.fillHeight: true - } - - Image { - Layout.bottomMargin: 2 // optical compensation - Layout.fillWidth: true - fillMode: Image.PreserveAspectFit - source: "../resources/id-barcode.svg" - } - } - Item { - id: profilePicture - // width: parent.width * 0.40 - width: parent.height / 5 * 4 - height: parent.height - - anchors { - right: parent.right - } - - Rectangle { - anchors.fill: parent - color: '#1effffff' - } + Rectangle { + anchors.fill: parent + color: "#1effffff" + } - Image { - source: "../resources/user.svg" - opacity: 0.9 - anchors.fill: parent - fillMode: Image.PreserveAspectFit + Image { + source: "../resources/user.svg" + opacity: 0.9 + anchors.fill: parent + fillMode: Image.PreserveAspectFit + anchors.margins: Math.round(4 * Units.vh) + } } } + // ========================================================================= + // Reveal animation + // ========================================================================= + SequentialAnimation { id: revealAnimation running: true From 87fe0177858a516211300fe59bbeec2513759ce0 Mon Sep 17 00:00:00 2001 From: reze-dev <25588579+reze-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 11:33:42 +0530 Subject: [PATCH 13/13] chore(flake.lock): bump flake.lock inputs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 6cd86598..8fd68aae 100644 --- a/flake.lock +++ b/flake.lock @@ -250,11 +250,11 @@ ] }, "locked": { - "lastModified": 1790225410, - "narHash": "sha256-BOyZoliWfm/beS4m3FxFKlu5at6npZen1PsWtvzzihk=", + "lastModified": 1790292277, + "narHash": "sha256-z+knvdMItRrMonmG4RIsqKYIa/hwYUzKjotDTfC5DDc=", "owner": "nix-community", "repo": "home-manager", - "rev": "4900baf1e219645e4a2acba35723852b2091bc20", + "rev": "4b9add8645d5e2b0f7de18f7a442d08fe2bdcc91", "type": "github" }, "original": {