Merge branch 'noctalia-dev:main' into fix/heuristic-lookup
This commit is contained in:
commit
38e3d9909f
25 changed files with 389 additions and 92 deletions
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
|
|
@ -22,7 +22,14 @@ jobs:
|
||||||
- name: Create release archive
|
- name: Create release archive
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ../noctalia-release
|
mkdir -p ../noctalia-release
|
||||||
rsync -av --exclude='.git' --exclude='.github' ./ ../noctalia-release/
|
rsync -av \
|
||||||
|
--exclude='.git' \
|
||||||
|
--exclude='.github' \
|
||||||
|
--exclude='nix' \
|
||||||
|
--exclude='flake.nix' \
|
||||||
|
--exclude='flake.lock' \
|
||||||
|
--exclude='result*' \
|
||||||
|
./ ../noctalia-release/
|
||||||
cd ..
|
cd ..
|
||||||
tar -czf noctalia-${{ github.ref_name }}.tar.gz noctalia-release/
|
tar -czf noctalia-${{ github.ref_name }}.tar.gz noctalia-release/
|
||||||
cp noctalia-${{ github.ref_name }}.tar.gz noctalia-latest.tar.gz
|
cp noctalia-${{ github.ref_name }}.tar.gz noctalia-latest.tar.gz
|
||||||
|
|
@ -58,4 +65,4 @@ jobs:
|
||||||
noctalia-latest.tar.gz
|
noctalia-latest.tar.gz
|
||||||
body_path: release_notes.md
|
body_path: release_notes.md
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,8 @@ output_path = "~/.config/qt6ct/colors/noctalia.conf"
|
||||||
|
|
||||||
[templates.qt5]
|
[templates.qt5]
|
||||||
input_path = "templates/qtct.conf"
|
input_path = "templates/qtct.conf"
|
||||||
output_path = "~/.config/qt5ct/colors/noctalia.conf"
|
output_path = "~/.config/qt5ct/colors/noctalia.conf"
|
||||||
|
|
||||||
|
[templates.kitty]
|
||||||
|
input_path = "templates/kitty.conf"
|
||||||
|
output_path = "~/.config/kitty/noctalia.conf"
|
||||||
23
Assets/Matugen/templates/kitty.conf
Normal file
23
Assets/Matugen/templates/kitty.conf
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
background {{colors.surface.default.hex}}
|
||||||
|
foreground {{colors.on_surface.default.hex}}
|
||||||
|
cursor_color {{colors.primary.default.hex}}
|
||||||
|
selection_background {{colors.surface_container.default.hex}}
|
||||||
|
selection_foreground {{colors.on_surface.default.hex}}
|
||||||
|
url_color {{colors.primary.default.hex}}
|
||||||
|
|
||||||
|
color0 {{colors.surface.default.hex}}
|
||||||
|
color1 {{colors.error.default.hex}}
|
||||||
|
color2 {{colors.tertiary.default.hex}}
|
||||||
|
color3 {{colors.secondary.default.hex}}
|
||||||
|
color4 {{colors.primary.default.hex}}
|
||||||
|
color5 {{colors.surface_container_highest.default.hex}}
|
||||||
|
color6 {{colors.secondary.default.hex}}
|
||||||
|
color7 {{colors.on_background.default.hex}}
|
||||||
|
color8 {{colors.outline.default.hex}}
|
||||||
|
color9 {{colors.error_container.default.hex}}
|
||||||
|
color10 {{colors.tertiary_container.default.hex}}
|
||||||
|
color11 {{colors.surface_container.default.hex}}
|
||||||
|
color12 {{colors.primary_container.default.hex}}
|
||||||
|
color13 {{colors.on_primary_container.default.hex}}
|
||||||
|
color14 {{colors.surface_variant.default.hex}}
|
||||||
|
color15 {{colors.on_background.default.hex}}
|
||||||
|
|
@ -13,6 +13,7 @@ Singleton {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Font size
|
// Font size
|
||||||
|
property real fontSizeXXS: 8
|
||||||
property real fontSizeXS: 9
|
property real fontSizeXS: 9
|
||||||
property real fontSizeS: 10
|
property real fontSizeS: 10
|
||||||
property real fontSizeM: 11
|
property real fontSizeM: 11
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ Singleton {
|
||||||
dayName = dayName.charAt(0).toUpperCase() + dayName.slice(1)
|
dayName = dayName.charAt(0).toUpperCase() + dayName.slice(1)
|
||||||
let day = date.getDate()
|
let day = date.getDate()
|
||||||
let month = date.toLocaleDateString(Qt.locale(), "MMM")
|
let month = date.toLocaleDateString(Qt.locale(), "MMM")
|
||||||
return timeString + " - " + dayName + ", " + day + " " + month
|
|
||||||
|
return timeString + " - " + (Settings.data.location.reverseDayMonth ? `${dayName}, ${month} ${day}` : `${dayName}, ${day} ${month}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return timeString
|
return timeString
|
||||||
|
|
|
||||||
|
|
@ -13,19 +13,9 @@ NPanel {
|
||||||
panelHeight: 500 * scaling
|
panelHeight: 500 * scaling
|
||||||
panelAnchorRight: true
|
panelAnchorRight: true
|
||||||
|
|
||||||
// Auto-refresh when service updates
|
// When the panel opens
|
||||||
Connections {
|
onOpened: {
|
||||||
target: ArchUpdaterService
|
ArchUpdaterService.doPoll()
|
||||||
function onUpdatePackagesChanged() {
|
|
||||||
// Force UI update when packages change
|
|
||||||
if (root.visible) {
|
|
||||||
// Small delay to ensure data is fully updated
|
|
||||||
Qt.callLater(() => {
|
|
||||||
// Force a UI update by triggering a property change
|
|
||||||
ArchUpdaterService.updatePackages = ArchUpdaterService.updatePackages
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panelContent: Rectangle {
|
panelContent: Rectangle {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ PopupWindow {
|
||||||
implicitWidth: menuWidth * scaling
|
implicitWidth: menuWidth * scaling
|
||||||
|
|
||||||
// Use the content height of the Flickable for implicit height
|
// Use the content height of the Flickable for implicit height
|
||||||
implicitHeight: Math.min(Screen.height * 0.9, flickable.contentHeight + (Style.marginM * 2 * scaling))
|
implicitHeight: Math.min(Screen.height * 0.9, flickable.contentHeight + (Style.marginS * 2 * scaling))
|
||||||
visible: false
|
visible: false
|
||||||
color: Color.transparent
|
color: Color.transparent
|
||||||
anchor.item: anchorItem
|
anchor.item: anchorItem
|
||||||
|
|
|
||||||
|
|
@ -8,21 +8,59 @@ import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property ShellScreen screen
|
property ShellScreen screen
|
||||||
property real scaling: ScalingService.scale(screen)
|
property real scaling: ScalingService.scale(screen)
|
||||||
|
|
||||||
implicitWidth: pill.width
|
implicitWidth: pill.width
|
||||||
implicitHeight: pill.height
|
implicitHeight: pill.height
|
||||||
|
|
||||||
|
// Track if we've already notified to avoid spam
|
||||||
|
property bool hasNotifiedLowBattery: false
|
||||||
|
|
||||||
|
// Helper to evaluate and possibly notify
|
||||||
|
function maybeNotify(percent, charging) {
|
||||||
|
const p = Math.round(percent)
|
||||||
|
// Only notify exactly at 15%, not at 0% or any other percentage
|
||||||
|
if (!charging && p === 15 && !root.hasNotifiedLowBattery) {
|
||||||
|
Quickshell.execDetached(
|
||||||
|
["notify-send", "-u", "critical", "-i", "battery-caution", "Low Battery", `Battery is at ${p}%. Please connect charger.`])
|
||||||
|
root.hasNotifiedLowBattery = true
|
||||||
|
}
|
||||||
|
// Reset when charging starts or when battery recovers above 20%
|
||||||
|
if (charging || p > 20) {
|
||||||
|
root.hasNotifiedLowBattery = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch for battery changes
|
||||||
|
Connections {
|
||||||
|
target: UPower.displayDevice
|
||||||
|
function onPercentageChanged() {
|
||||||
|
let battery = UPower.displayDevice
|
||||||
|
let isReady = battery && battery.ready && battery.isLaptopBattery && battery.isPresent
|
||||||
|
let percent = isReady ? (battery.percentage * 100) : 0
|
||||||
|
let charging = isReady ? battery.state === UPowerDeviceState.Charging : false
|
||||||
|
|
||||||
|
root.maybeNotify(percent, charging)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStateChanged() {
|
||||||
|
let battery = UPower.displayDevice
|
||||||
|
let isReady = battery && battery.ready && battery.isLaptopBattery && battery.isPresent
|
||||||
|
let charging = isReady ? battery.state === UPowerDeviceState.Charging : false
|
||||||
|
|
||||||
|
// Reset notification flag when charging starts
|
||||||
|
if (charging) {
|
||||||
|
root.hasNotifiedLowBattery = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NPill {
|
NPill {
|
||||||
id: pill
|
id: pill
|
||||||
|
|
||||||
// Test mode
|
// Test mode
|
||||||
property bool testMode: false
|
property bool testMode: false
|
||||||
property int testPercent: 49
|
property int testPercent: 20
|
||||||
property bool testCharging: false
|
property bool testCharging: false
|
||||||
|
|
||||||
property var battery: UPower.displayDevice
|
property var battery: UPower.displayDevice
|
||||||
property bool isReady: testMode ? true : (battery && battery.ready && battery.isLaptopBattery && battery.isPresent)
|
property bool isReady: testMode ? true : (battery && battery.ready && battery.isLaptopBattery && battery.isPresent)
|
||||||
property real percent: testMode ? testPercent : (isReady ? (battery.percentage * 100) : 0)
|
property real percent: testMode ? testPercent : (isReady ? (battery.percentage * 100) : 0)
|
||||||
|
|
@ -30,16 +68,12 @@ Item {
|
||||||
|
|
||||||
// Choose icon based on charge and charging state
|
// Choose icon based on charge and charging state
|
||||||
function batteryIcon() {
|
function batteryIcon() {
|
||||||
|
|
||||||
if (!isReady || !battery.isLaptopBattery)
|
if (!isReady || !battery.isLaptopBattery)
|
||||||
return "battery_android_alert"
|
return "battery_android_alert"
|
||||||
|
|
||||||
if (charging)
|
if (charging)
|
||||||
return "battery_android_bolt"
|
return "battery_android_bolt"
|
||||||
|
|
||||||
if (percent >= 95)
|
if (percent >= 95)
|
||||||
return "battery_android_full"
|
return "battery_android_full"
|
||||||
|
|
||||||
// Hardcoded battery symbols
|
// Hardcoded battery symbols
|
||||||
if (percent >= 85)
|
if (percent >= 85)
|
||||||
return "battery_android_6"
|
return "battery_android_6"
|
||||||
|
|
@ -60,28 +94,26 @@ Item {
|
||||||
icon: batteryIcon()
|
icon: batteryIcon()
|
||||||
text: (isReady && battery.isLaptopBattery) ? Math.round(percent) + "%" : "-"
|
text: (isReady && battery.isLaptopBattery) ? Math.round(percent) + "%" : "-"
|
||||||
textColor: charging ? Color.mPrimary : Color.mOnSurface
|
textColor: charging ? Color.mPrimary : Color.mOnSurface
|
||||||
forceOpen: isReady && battery.isLaptopBattery && Settings.data.bar.alwaysShowBatteryPercentage
|
iconCircleColor: Color.mPrimary
|
||||||
disableOpen: (!isReady || !battery.isLaptopBattery)
|
collapsedIconColor: Color.mOnSurface
|
||||||
|
autoHide: false
|
||||||
|
forceOpen: isReady && (testMode || battery.isLaptopBattery) && Settings.data.bar.alwaysShowBatteryPercentage
|
||||||
|
disableOpen: (!isReady || (!testMode && !battery.isLaptopBattery))
|
||||||
tooltipText: {
|
tooltipText: {
|
||||||
let lines = []
|
let lines = []
|
||||||
|
|
||||||
if (testMode) {
|
if (testMode) {
|
||||||
lines.push("Time Left: " + Time.formatVagueHumanReadableDuration(12345))
|
lines.push("Time Left: " + Time.formatVagueHumanReadableDuration(12345))
|
||||||
return lines.join("\n")
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isReady || !battery.isLaptopBattery) {
|
if (!isReady || !battery.isLaptopBattery) {
|
||||||
return "No Battery Detected"
|
return "No Battery Detected"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (battery.timeToEmpty > 0) {
|
if (battery.timeToEmpty > 0) {
|
||||||
lines.push("Time Left: " + Time.formatVagueHumanReadableDuration(battery.timeToEmpty))
|
lines.push("Time Left: " + Time.formatVagueHumanReadableDuration(battery.timeToEmpty))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (battery.timeToFull > 0) {
|
if (battery.timeToFull > 0) {
|
||||||
lines.push("Time Until Full: " + Time.formatVagueHumanReadableDuration(battery.timeToFull))
|
lines.push("Time Until Full: " + Time.formatVagueHumanReadableDuration(battery.timeToFull))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (battery.changeRate !== undefined) {
|
if (battery.changeRate !== undefined) {
|
||||||
const rate = battery.changeRate
|
const rate = battery.changeRate
|
||||||
if (rate > 0) {
|
if (rate > 0) {
|
||||||
|
|
@ -95,7 +127,6 @@ Item {
|
||||||
} else {
|
} else {
|
||||||
lines.push(charging ? "Charging" : "Discharging")
|
lines.push(charging ? "Charging" : "Discharging")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (battery.healthPercentage !== undefined && battery.healthPercentage > 0) {
|
if (battery.healthPercentage !== undefined && battery.healthPercentage > 0) {
|
||||||
lines.push("Health: " + Math.round(battery.healthPercentage) + "%")
|
lines.push("Health: " + Math.round(battery.healthPercentage) + "%")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ NPanel {
|
||||||
}
|
}
|
||||||
// Defer selectedIndex reset to avoid binding loops
|
// Defer selectedIndex reset to avoid binding loops
|
||||||
Qt.callLater(() => selectedIndex = 0)
|
Qt.callLater(() => selectedIndex = 0)
|
||||||
|
|
||||||
// Reset cursor position if needed
|
// Reset cursor position if needed
|
||||||
if (shouldResetCursor && text === "") {
|
if (shouldResetCursor && text === "") {
|
||||||
cursorPosition = 0
|
cursorPosition = 0
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ Variants {
|
||||||
margins.right: Style.marginM * scaling
|
margins.right: Style.marginM * scaling
|
||||||
implicitWidth: 360 * scaling
|
implicitWidth: 360 * scaling
|
||||||
implicitHeight: Math.min(notificationStack.implicitHeight, (NotificationService.maxVisible * 120) * scaling)
|
implicitHeight: Math.min(notificationStack.implicitHeight, (NotificationService.maxVisible * 120) * scaling)
|
||||||
WlrLayershell.layer: WlrLayer.Overlay
|
//WlrLayershell.layer: WlrLayer.Overlay
|
||||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||||
|
|
||||||
// Connect to animation signal from service
|
// Connect to animation signal from service
|
||||||
|
|
@ -202,6 +202,8 @@ Variants {
|
||||||
maximumLineCount: 5
|
maximumLineCount: 5
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actions removed
|
||||||
}
|
}
|
||||||
|
|
||||||
NIconButton {
|
NIconButton {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property real scaling: 1
|
readonly property real scaling: ScalingService.scale(screen)
|
||||||
readonly property string tabIcon: "brightness_6"
|
readonly property string tabIcon: "brightness_6"
|
||||||
readonly property string tabLabel: "Brightness"
|
readonly property string tabLabel: "Brightness"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
|
||||||
|
|
@ -128,10 +128,10 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GTK/QT theming
|
// App theming
|
||||||
NToggle {
|
NToggle {
|
||||||
label: "Theme external apps (GTK & Qt)"
|
label: "Theme external apps (GTK, Qt & kitty)"
|
||||||
description: "Writes GTK (gtk.css) and Qt (qt6ct) themes based on your colors."
|
description: "Writes GTK (gtk.css), Qt5/6 (noctalia.conf) and Kitty (noctalia.conf) themes based on your colors."
|
||||||
checked: Settings.data.colorSchemes.themeApps
|
checked: Settings.data.colorSchemes.themeApps
|
||||||
onToggled: checked => {
|
onToggled: checked => {
|
||||||
Settings.data.colorSchemes.themeApps = checked
|
Settings.data.colorSchemes.themeApps = checked
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ Item {
|
||||||
contentWidth: parent.width
|
contentWidth: parent.width
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
width: parent.width
|
id: contentColumn
|
||||||
|
width: Math.max(parent.width, 300) // Minimum reasonable width without scaling
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.margins: Style.marginL * scaling
|
Layout.margins: Style.marginL * scaling
|
||||||
|
|
@ -58,6 +60,8 @@ Item {
|
||||||
model: Quickshell.screens || []
|
model: Quickshell.screens || []
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
// Remove the scaling-based minimum width that causes issues at low scaling
|
||||||
|
// Layout.minimumWidth: 400 * scaling
|
||||||
radius: Style.radiusM * scaling
|
radius: Style.radiusM * scaling
|
||||||
color: Color.mSurface
|
color: Color.mSurface
|
||||||
border.color: Color.mOutline
|
border.color: Color.mOutline
|
||||||
|
|
@ -69,6 +73,7 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Style.marginL * scaling
|
anchors.margins: Style.marginL * scaling
|
||||||
spacing: Style.marginXXS * scaling
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.minimumWidth: 0
|
||||||
|
|
||||||
NText {
|
NText {
|
||||||
text: (modelData.name || "Unknown")
|
text: (modelData.name || "Unknown")
|
||||||
|
|
@ -85,8 +90,12 @@ Item {
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
Layout.minimumWidth: 0
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 0
|
||||||
label: "Bar"
|
label: "Bar"
|
||||||
description: "Enable the bar on this monitor."
|
description: "Enable the bar on this monitor."
|
||||||
checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1
|
checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1
|
||||||
|
|
@ -100,6 +109,8 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 0
|
||||||
label: "Notifications"
|
label: "Notifications"
|
||||||
description: "Enable notifications on this monitor."
|
description: "Enable notifications on this monitor."
|
||||||
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
|
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
|
||||||
|
|
@ -115,6 +126,8 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 0
|
||||||
label: "Dock"
|
label: "Dock"
|
||||||
description: "Enable the dock on this monitor."
|
description: "Enable the dock on this monitor."
|
||||||
checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1
|
checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1
|
||||||
|
|
@ -130,11 +143,16 @@ Item {
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginXXS * scaling
|
spacing: Style.marginXXS * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 0
|
||||||
|
|
||||||
NText {
|
NText {
|
||||||
text: "Scale"
|
text: "Scale"
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
|
@ -149,14 +167,19 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NText {
|
NText {
|
||||||
text: `${Math.round(ScalingService.scaleByName(modelData.name) * 100)}%`
|
text: `${Math.round(ScalingService.scaleByName(modelData.name) * 100)}%`
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.minimumWidth: implicitWidth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: Style.marginS * scaling
|
spacing: Style.marginS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 0
|
||||||
|
|
||||||
NSlider {
|
NSlider {
|
||||||
id: scaleSlider
|
id: scaleSlider
|
||||||
from: 0.6
|
from: 0.6
|
||||||
|
|
@ -169,12 +192,15 @@ Item {
|
||||||
Settings.data.monitorsScaling = data
|
Settings.data.monitorsScaling = data
|
||||||
}
|
}
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumWidth: 50 // Ensure minimum slider width
|
||||||
}
|
}
|
||||||
|
|
||||||
NIconButton {
|
NIconButton {
|
||||||
icon: "refresh"
|
icon: "refresh"
|
||||||
tooltipText: "Reset Scaling"
|
tooltipText: "Reset Scaling"
|
||||||
fontPointSize: Style.fontSizeL * scaling
|
fontPointSize: Style.fontSizeL * scaling
|
||||||
|
Layout.preferredWidth: implicitWidth
|
||||||
|
Layout.minimumWidth: implicitWidth
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var data = Settings.data.monitorsScaling || {}
|
var data = Settings.data.monitorsScaling || {}
|
||||||
data[modelData.name] = 1.0
|
data[modelData.name] = 1.0
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property real scaling: 1
|
readonly property real scaling: ScalingService.scale(screen)
|
||||||
readonly property string tabIcon: "photo_library"
|
readonly property string tabIcon: "photo_library"
|
||||||
readonly property string tabLabel: "Wallpaper Selector"
|
readonly property string tabLabel: "Wallpaper Selector"
|
||||||
readonly property int tabIndex: 7
|
readonly property int tabIndex: 7
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ NPanel {
|
||||||
font.weight: Style.fontWeightBold
|
font.weight: Style.fontWeightBold
|
||||||
color: Color.mOnSurface
|
color: Color.mOnSurface
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: Style.marginS * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
NIconButton {
|
NIconButton {
|
||||||
|
|
@ -72,6 +73,16 @@ NPanel {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show errors at the very top
|
||||||
|
NText {
|
||||||
|
visible: NetworkService.connectStatus === "error" && NetworkService.connectError.length > 0
|
||||||
|
text: NetworkService.connectError
|
||||||
|
color: Color.mError
|
||||||
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
@ -127,69 +138,65 @@ NPanel {
|
||||||
|
|
||||||
// Network list
|
// Network list
|
||||||
ListView {
|
ListView {
|
||||||
id: networkList
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: Settings.data.network.wifiEnabled && !NetworkService.isLoading
|
visible: Settings.data.network.wifiEnabled && !NetworkService.isLoading
|
||||||
model: Object.values(NetworkService.networks)
|
model: Object.values(NetworkService.networks)
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginS * scaling
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
width: parent ? parent.width : 0
|
width: parent ? parent.width : 0
|
||||||
height: modelData.ssid === passwordPromptSsid
|
height: modelData.ssid === passwordPromptSsid
|
||||||
&& showPasswordPrompt ? 108 * scaling : Style.baseWidgetSize * 1.5 * scaling
|
&& showPasswordPrompt ? 130 * scaling : Style.baseWidgetSize * 1.75 * scaling
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: rect
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: Style.baseWidgetSize * 1.5 * scaling
|
Layout.fillHeight: true
|
||||||
radius: Style.radiusS * scaling
|
radius: Style.radiusS * scaling
|
||||||
color: modelData.connected ? Color.mPrimary : (networkMouseArea.containsMouse ? Color.mTertiary : Color.transparent)
|
color: networkMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||||
|
border.color: modelData.connected ? Color.mPrimary : Color.transparent
|
||||||
|
border.width: Math.max(1, Style.borderM * scaling)
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.fill: parent
|
anchors {
|
||||||
anchors.margins: Style.marginS * scaling
|
fill: parent
|
||||||
|
leftMargin: Style.marginL * scaling
|
||||||
|
rightMargin: Style.marginL * scaling
|
||||||
|
}
|
||||||
spacing: Style.marginS * scaling
|
spacing: Style.marginS * scaling
|
||||||
|
|
||||||
NIcon {
|
NIcon {
|
||||||
text: NetworkService.signalIcon(modelData.signal)
|
text: NetworkService.signalIcon(modelData.signal)
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
font.pointSize: Style.fontSizeXXL * scaling
|
||||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: Style.marginXS * scaling
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
// SSID
|
// SSID
|
||||||
NText {
|
NText {
|
||||||
|
Layout.fillWidth: true
|
||||||
text: modelData.ssid || "Unknown Network"
|
text: modelData.ssid || "Unknown Network"
|
||||||
font.pointSize: Style.fontSizeNormal * scaling
|
font.pointSize: Style.fontSizeNormal * scaling
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
Layout.fillWidth: true
|
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Security Protocol
|
// Security Protocol
|
||||||
NText {
|
NText {
|
||||||
text: modelData.security && modelData.security !== "--" ? modelData.security : "Open"
|
text: modelData.security && modelData.security !== "--" ? modelData.security : "Open"
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
font.pointSize: Style.fontSizeXXS * scaling
|
||||||
elide: Text.ElideRight
|
|
||||||
Layout.fillWidth: true
|
|
||||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
visible: NetworkService.connectStatusSsid === modelData.ssid
|
|
||||||
&& NetworkService.connectStatus === "error" && NetworkService.connectError.length > 0
|
|
||||||
text: NetworkService.connectError
|
|
||||||
color: Color.mError
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,17 +210,25 @@ NPanel {
|
||||||
NBusyIndicator {
|
NBusyIndicator {
|
||||||
visible: NetworkService.connectingSsid === modelData.ssid
|
visible: NetworkService.connectingSsid === modelData.ssid
|
||||||
running: NetworkService.connectingSsid === modelData.ssid
|
running: NetworkService.connectingSsid === modelData.ssid
|
||||||
color: Color.mPrimary
|
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
size: Style.baseWidgetSize * 0.7 * scaling
|
size: Style.baseWidgetSize * 0.7 * scaling
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NText {
|
RowLayout {
|
||||||
visible: modelData.connected
|
visible: modelData.connected
|
||||||
text: "connected"
|
NText {
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
text: "Connected"
|
||||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
NIcon {
|
||||||
|
text: "check"
|
||||||
|
font.pointSize: Style.fontSizeXXL * scaling
|
||||||
|
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,6 +239,7 @@ NPanel {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (modelData.connected) {
|
if (modelData.connected) {
|
||||||
NetworkService.disconnectNetwork(modelData.ssid)
|
NetworkService.disconnectNetwork(modelData.ssid)
|
||||||
|
showPasswordPrompt = false
|
||||||
} else if (NetworkService.isSecured(modelData.security) && !modelData.existing) {
|
} else if (NetworkService.isSecured(modelData.security) && !modelData.existing) {
|
||||||
passwordPromptSsid = modelData.ssid
|
passwordPromptSsid = modelData.ssid
|
||||||
showPasswordPrompt = true
|
showPasswordPrompt = true
|
||||||
|
|
@ -240,11 +256,11 @@ NPanel {
|
||||||
|
|
||||||
// Password prompt section
|
// Password prompt section
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: passwordPromptSection
|
visible: modelData.ssid === passwordPromptSsid && showPasswordPrompt
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: modelData.ssid === passwordPromptSsid && showPasswordPrompt ? 60 : 0
|
Layout.preferredHeight: modelData.ssid === passwordPromptSsid && showPasswordPrompt ? 60 : 0
|
||||||
Layout.margins: Style.marginS * scaling
|
Layout.margins: Style.marginS * scaling
|
||||||
visible: modelData.ssid === passwordPromptSsid && showPasswordPrompt
|
|
||||||
color: Color.mSurfaceVariant
|
color: Color.mSurfaceVariant
|
||||||
radius: Style.radiusS * scaling
|
radius: Style.radiusS * scaling
|
||||||
|
|
||||||
|
|
@ -280,8 +296,10 @@ NPanel {
|
||||||
echoMode: TextInput.Password
|
echoMode: TextInput.Password
|
||||||
onTextChanged: passwordInput = text
|
onTextChanged: passwordInput = text
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
NetworkService.submitPassword(passwordPromptSsid, passwordInput)
|
if (passwordInput !== "") {
|
||||||
showPasswordPrompt = false
|
NetworkService.submitPassword(passwordPromptSsid, passwordInput)
|
||||||
|
showPasswordPrompt = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
@ -315,8 +333,10 @@ NPanel {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
NetworkService.submitPassword(passwordPromptSsid, passwordInput)
|
if (passwordInput !== "") {
|
||||||
showPasswordPrompt = false
|
NetworkService.submitPassword(passwordPromptSsid, passwordInput)
|
||||||
|
showPasswordPrompt = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
@ -324,6 +344,13 @@ NPanel {
|
||||||
onExited: parent.color = Color.mPrimary
|
onExited: parent.color = Color.mPrimary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NIconButton {
|
||||||
|
icon: "close"
|
||||||
|
onClicked: {
|
||||||
|
showPasswordPrompt = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
import qs.Commons
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: updateService
|
id: updateService
|
||||||
|
|
@ -15,20 +16,23 @@ Singleton {
|
||||||
property int selectedPackagesCount: 0
|
property int selectedPackagesCount: 0
|
||||||
property bool updateInProgress: false
|
property bool updateInProgress: false
|
||||||
|
|
||||||
|
// Initial check
|
||||||
|
Component.onCompleted: doPoll()
|
||||||
|
|
||||||
// Process for checking updates
|
// Process for checking updates
|
||||||
Process {
|
Process {
|
||||||
id: checkupdatesProcess
|
id: checkupdatesProcess
|
||||||
command: ["checkupdates"]
|
command: ["checkupdates"]
|
||||||
onExited: function (exitCode) {
|
onExited: function (exitCode) {
|
||||||
if (exitCode !== 0 && exitCode !== 2) {
|
if (exitCode !== 0 && exitCode !== 2) {
|
||||||
console.warn("[UpdateService] checkupdates failed (code:", exitCode, ")")
|
Logger.warn("ArchUpdater", "checkupdates failed (code:", exitCode, ")")
|
||||||
updatePackages = []
|
updatePackages = []
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
parseCheckupdatesOutput(text)
|
parseCheckupdatesOutput(text)
|
||||||
|
Logger.log("ArchUpdater", "found", updatePackages.length, "upgradable package(s)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +154,4 @@ Singleton {
|
||||||
running: true
|
running: true
|
||||||
onTriggered: doPoll()
|
onTriggered: doPoll()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial check
|
|
||||||
Component.onCompleted: doPoll()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ Singleton {
|
||||||
// Widget registry object mapping widget names to components
|
// Widget registry object mapping widget names to components
|
||||||
property var widgets: ({
|
property var widgets: ({
|
||||||
"ActiveWindow": activeWindowComponent,
|
"ActiveWindow": activeWindowComponent,
|
||||||
// "ArchUpdater": archUpdaterComponent,
|
"ArchUpdater": archUpdaterComponent,
|
||||||
"Battery": batteryComponent,
|
"Battery": batteryComponent,
|
||||||
"Bluetooth": bluetoothComponent,
|
"Bluetooth": bluetoothComponent,
|
||||||
"Brightness": brightnessComponent,
|
"Brightness": brightnessComponent,
|
||||||
|
|
@ -32,9 +32,9 @@ Singleton {
|
||||||
property Component activeWindowComponent: Component {
|
property Component activeWindowComponent: Component {
|
||||||
ActiveWindow {}
|
ActiveWindow {}
|
||||||
}
|
}
|
||||||
// property Component archUpdaterComponent: Component {
|
property Component archUpdaterComponent: Component {
|
||||||
// ArchUpdater {}
|
ArchUpdater {}
|
||||||
// }
|
}
|
||||||
property Component batteryComponent: Component {
|
property Component batteryComponent: Component {
|
||||||
Battery {}
|
Battery {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ Singleton {
|
||||||
|
|
||||||
function setBluetoothEnabled(enabled) {
|
function setBluetoothEnabled(enabled) {
|
||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
console.warn("BluetoothService: No adapter available")
|
Logger.warn("Bluetooth", "No adapter available")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,7 @@ Singleton {
|
||||||
Logger.log("Wallpapers", "Listing wallpapers")
|
Logger.log("Wallpapers", "Listing wallpapers")
|
||||||
scanning = true
|
scanning = true
|
||||||
wallpaperList = []
|
wallpaperList = []
|
||||||
// Unsetting, then setting the folder will re-trigger the parsing!
|
// Set the folder directly to avoid model reset issues
|
||||||
folderModel.folder = ""
|
|
||||||
folderModel.folder = "file://" + (Settings.data.wallpaper.directory !== undefined ? Settings.data.wallpaper.directory : "")
|
folderModel.folder = "file://" + (Settings.data.wallpaper.directory !== undefined ? Settings.data.wallpaper.directory : "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,6 @@ Loader {
|
||||||
signal closed
|
signal closed
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
// console.log("Oh Yeah")
|
|
||||||
// console.log(objectName)
|
|
||||||
PanelService.registerPanel(root)
|
PanelService.registerPanel(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,7 @@ Text {
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
font.weight: Style.fontWeightMedium
|
font.weight: Style.fontWeightMedium
|
||||||
color: Color.mOnSurface
|
color: Color.mOnSurface
|
||||||
|
renderType: Text.QtRendering
|
||||||
|
font.hintingPreference: Font.PreferNoHinting
|
||||||
|
font.kerning: true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Commons
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
|
||||||
64
flake.lock
generated
Normal file
64
flake.lock
generated
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1755615617,
|
||||||
|
"narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "20075955deac2583bb12f07151c2df830ef346b4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quickshell": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1753595452,
|
||||||
|
"narHash": "sha256-vqkSDvh7hWhPvNjMjEDV4KbSCv2jyl2Arh73ZXe274k=",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"rev": "a5431dd02dc23d9ef1680e67777fed00fe5f7cda",
|
||||||
|
"revCount": 665,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"quickshell": "quickshell",
|
||||||
|
"systems": "systems"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
35
flake.nix
Normal file
35
flake.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
description = "Desktop shell for Caelestia dots";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
|
||||||
|
quickshell = {
|
||||||
|
url = "git+https://git.outfoxxed.me/outfoxxed/quickshell";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
systems,
|
||||||
|
...
|
||||||
|
} @ inputs: let
|
||||||
|
eachSystem = nixpkgs.lib.genAttrs (import systems);
|
||||||
|
in {
|
||||||
|
formatter = eachSystem (pkgs: pkgs.alejandra);
|
||||||
|
|
||||||
|
packages = eachSystem (system: rec {
|
||||||
|
noctalia-shell = nixpkgs.legacyPackages.${system}.callPackage ./nix {
|
||||||
|
rev = self.rev or self.dirtyRev;
|
||||||
|
quickshell = inputs.quickshell.packages.${system}.default.override {
|
||||||
|
withX11 = false;
|
||||||
|
withI3 = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = noctalia-shell;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
84
nix/default.nix
Normal file
84
nix/default.nix
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
{
|
||||||
|
rev,
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
makeWrapper,
|
||||||
|
makeFontsConf,
|
||||||
|
ddcutil,
|
||||||
|
brightnessctl,
|
||||||
|
cava,
|
||||||
|
networkmanager,
|
||||||
|
wl-clipboard,
|
||||||
|
libnotify,
|
||||||
|
bluez,
|
||||||
|
bash,
|
||||||
|
coreutils,
|
||||||
|
findutils,
|
||||||
|
file,
|
||||||
|
material-symbols,
|
||||||
|
roboto,
|
||||||
|
inter-nerdfont,
|
||||||
|
matugen,
|
||||||
|
cliphist,
|
||||||
|
swww,
|
||||||
|
gpu-screen-recorder,
|
||||||
|
gcc,
|
||||||
|
qt6,
|
||||||
|
quickshell,
|
||||||
|
xkeyboard-config,
|
||||||
|
extraRuntimeDeps ? [],
|
||||||
|
}: let
|
||||||
|
runtimeDeps =
|
||||||
|
[
|
||||||
|
bash
|
||||||
|
bluez
|
||||||
|
brightnessctl
|
||||||
|
cava
|
||||||
|
cliphist
|
||||||
|
coreutils
|
||||||
|
ddcutil
|
||||||
|
file
|
||||||
|
findutils
|
||||||
|
gpu-screen-recorder
|
||||||
|
libnotify
|
||||||
|
matugen
|
||||||
|
networkmanager
|
||||||
|
swww
|
||||||
|
wl-clipboard
|
||||||
|
]
|
||||||
|
++ extraRuntimeDeps;
|
||||||
|
|
||||||
|
fontconfig = makeFontsConf {
|
||||||
|
fontDirectories = [
|
||||||
|
material-symbols
|
||||||
|
roboto
|
||||||
|
inter-nerdfont
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "noctalia-shell";
|
||||||
|
version = "${rev}";
|
||||||
|
src = ./..;
|
||||||
|
|
||||||
|
nativeBuildInputs = [gcc makeWrapper qt6.wrapQtAppsHook];
|
||||||
|
buildInputs = [quickshell xkeyboard-config qt6.qtbase];
|
||||||
|
propagatedBuildInputs = runtimeDeps;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/share/noctalia-shell
|
||||||
|
cp -r ./* $out/share/noctalia-shell
|
||||||
|
|
||||||
|
makeWrapper ${quickshell}/bin/qs $out/bin/noctalia-shell \
|
||||||
|
--prefix PATH : "${lib.makeBinPath runtimeDeps}" \
|
||||||
|
--set FONTCONFIG_FILE "${fontconfig}" \
|
||||||
|
--add-flags "-p $out/share/noctalia-shell"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "A sleek and minimal desktop shell thoughtfully crafted for Wayland, built with Quickshell.";
|
||||||
|
homepage = "https://github.com/noctalia-dev/noctalia-shell";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
mainProgram = "noctalia-shell";
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue