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
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
|
|
@ -22,7 +22,14 @@ jobs:
|
|||
- name: Create release archive
|
||||
run: |
|
||||
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 ..
|
||||
tar -czf noctalia-${{ github.ref_name }}.tar.gz noctalia-release/
|
||||
cp noctalia-${{ github.ref_name }}.tar.gz noctalia-latest.tar.gz
|
||||
|
|
|
|||
|
|
@ -24,3 +24,7 @@ output_path = "~/.config/qt6ct/colors/noctalia.conf"
|
|||
[templates.qt5]
|
||||
input_path = "templates/qtct.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
|
||||
property real fontSizeXXS: 8
|
||||
property real fontSizeXS: 9
|
||||
property real fontSizeS: 10
|
||||
property real fontSizeM: 11
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ Singleton {
|
|||
dayName = dayName.charAt(0).toUpperCase() + dayName.slice(1)
|
||||
let day = date.getDate()
|
||||
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
|
||||
|
|
|
|||
|
|
@ -13,19 +13,9 @@ NPanel {
|
|||
panelHeight: 500 * scaling
|
||||
panelAnchorRight: true
|
||||
|
||||
// Auto-refresh when service updates
|
||||
Connections {
|
||||
target: ArchUpdaterService
|
||||
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)
|
||||
}
|
||||
}
|
||||
// When the panel opens
|
||||
onOpened: {
|
||||
ArchUpdaterService.doPoll()
|
||||
}
|
||||
|
||||
panelContent: Rectangle {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ PopupWindow {
|
|||
implicitWidth: menuWidth * scaling
|
||||
|
||||
// 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
|
||||
color: Color.transparent
|
||||
anchor.item: anchorItem
|
||||
|
|
|
|||
|
|
@ -8,21 +8,59 @@ import qs.Widgets
|
|||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property ShellScreen screen
|
||||
property real scaling: ScalingService.scale(screen)
|
||||
|
||||
implicitWidth: pill.width
|
||||
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 {
|
||||
id: pill
|
||||
|
||||
// Test mode
|
||||
property bool testMode: false
|
||||
property int testPercent: 49
|
||||
property int testPercent: 20
|
||||
property bool testCharging: false
|
||||
|
||||
property var battery: UPower.displayDevice
|
||||
property bool isReady: testMode ? true : (battery && battery.ready && battery.isLaptopBattery && battery.isPresent)
|
||||
property real percent: testMode ? testPercent : (isReady ? (battery.percentage * 100) : 0)
|
||||
|
|
@ -30,16 +68,12 @@ Item {
|
|||
|
||||
// Choose icon based on charge and charging state
|
||||
function batteryIcon() {
|
||||
|
||||
if (!isReady || !battery.isLaptopBattery)
|
||||
return "battery_android_alert"
|
||||
|
||||
if (charging)
|
||||
return "battery_android_bolt"
|
||||
|
||||
if (percent >= 95)
|
||||
return "battery_android_full"
|
||||
|
||||
// Hardcoded battery symbols
|
||||
if (percent >= 85)
|
||||
return "battery_android_6"
|
||||
|
|
@ -60,28 +94,26 @@ Item {
|
|||
icon: batteryIcon()
|
||||
text: (isReady && battery.isLaptopBattery) ? Math.round(percent) + "%" : "-"
|
||||
textColor: charging ? Color.mPrimary : Color.mOnSurface
|
||||
forceOpen: isReady && battery.isLaptopBattery && Settings.data.bar.alwaysShowBatteryPercentage
|
||||
disableOpen: (!isReady || !battery.isLaptopBattery)
|
||||
iconCircleColor: Color.mPrimary
|
||||
collapsedIconColor: Color.mOnSurface
|
||||
autoHide: false
|
||||
forceOpen: isReady && (testMode || battery.isLaptopBattery) && Settings.data.bar.alwaysShowBatteryPercentage
|
||||
disableOpen: (!isReady || (!testMode && !battery.isLaptopBattery))
|
||||
tooltipText: {
|
||||
let lines = []
|
||||
|
||||
if (testMode) {
|
||||
lines.push("Time Left: " + Time.formatVagueHumanReadableDuration(12345))
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
if (!isReady || !battery.isLaptopBattery) {
|
||||
return "No Battery Detected"
|
||||
}
|
||||
|
||||
if (battery.timeToEmpty > 0) {
|
||||
lines.push("Time Left: " + Time.formatVagueHumanReadableDuration(battery.timeToEmpty))
|
||||
}
|
||||
|
||||
if (battery.timeToFull > 0) {
|
||||
lines.push("Time Until Full: " + Time.formatVagueHumanReadableDuration(battery.timeToFull))
|
||||
}
|
||||
|
||||
if (battery.changeRate !== undefined) {
|
||||
const rate = battery.changeRate
|
||||
if (rate > 0) {
|
||||
|
|
@ -95,7 +127,6 @@ Item {
|
|||
} else {
|
||||
lines.push(charging ? "Charging" : "Discharging")
|
||||
}
|
||||
|
||||
if (battery.healthPercentage !== undefined && battery.healthPercentage > 0) {
|
||||
lines.push("Health: " + Math.round(battery.healthPercentage) + "%")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Variants {
|
|||
margins.right: Style.marginM * scaling
|
||||
implicitWidth: 360 * scaling
|
||||
implicitHeight: Math.min(notificationStack.implicitHeight, (NotificationService.maxVisible * 120) * scaling)
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
//WlrLayershell.layer: WlrLayer.Overlay
|
||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||
|
||||
// Connect to animation signal from service
|
||||
|
|
@ -202,6 +202,8 @@ Variants {
|
|||
maximumLineCount: 5
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Actions removed
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import qs.Services
|
|||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
property real scaling: 1
|
||||
readonly property real scaling: ScalingService.scale(screen)
|
||||
readonly property string tabIcon: "brightness_6"
|
||||
readonly property string tabLabel: "Brightness"
|
||||
Layout.fillWidth: true
|
||||
|
|
|
|||
|
|
@ -128,10 +128,10 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
// GTK/QT theming
|
||||
// App theming
|
||||
NToggle {
|
||||
label: "Theme external apps (GTK & Qt)"
|
||||
description: "Writes GTK (gtk.css) and Qt (qt6ct) themes based on your colors."
|
||||
label: "Theme external apps (GTK, Qt & kitty)"
|
||||
description: "Writes GTK (gtk.css), Qt5/6 (noctalia.conf) and Kitty (noctalia.conf) themes based on your colors."
|
||||
checked: Settings.data.colorSchemes.themeApps
|
||||
onToggled: checked => {
|
||||
Settings.data.colorSchemes.themeApps = checked
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ Item {
|
|||
contentWidth: parent.width
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
id: contentColumn
|
||||
width: Math.max(parent.width, 300) // Minimum reasonable width without scaling
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.margins: Style.marginL * scaling
|
||||
|
|
@ -58,6 +60,8 @@ Item {
|
|||
model: Quickshell.screens || []
|
||||
delegate: Rectangle {
|
||||
Layout.fillWidth: true
|
||||
// Remove the scaling-based minimum width that causes issues at low scaling
|
||||
// Layout.minimumWidth: 400 * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
|
|
@ -69,6 +73,7 @@ Item {
|
|||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL * scaling
|
||||
spacing: Style.marginXXS * scaling
|
||||
Layout.minimumWidth: 0
|
||||
|
||||
NText {
|
||||
text: (modelData.name || "Unknown")
|
||||
|
|
@ -85,8 +90,12 @@ Item {
|
|||
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.minimumWidth: 0
|
||||
Layout.fillWidth: true
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 0
|
||||
label: "Bar"
|
||||
description: "Enable the bar on this monitor."
|
||||
checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1
|
||||
|
|
@ -100,6 +109,8 @@ Item {
|
|||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 0
|
||||
label: "Notifications"
|
||||
description: "Enable notifications on this monitor."
|
||||
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
|
||||
|
|
@ -115,6 +126,8 @@ Item {
|
|||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 0
|
||||
label: "Dock"
|
||||
description: "Enable the dock on this monitor."
|
||||
checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1
|
||||
|
|
@ -130,11 +143,16 @@ Item {
|
|||
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Style.marginXXS * scaling
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 0
|
||||
|
||||
NText {
|
||||
text: "Scale"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
|
|
@ -149,14 +167,19 @@ Item {
|
|||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: `${Math.round(ScalingService.scaleByName(modelData.name) * 100)}%`
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.minimumWidth: implicitWidth
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginS * scaling
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 0
|
||||
|
||||
NSlider {
|
||||
id: scaleSlider
|
||||
from: 0.6
|
||||
|
|
@ -169,12 +192,15 @@ Item {
|
|||
Settings.data.monitorsScaling = data
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 50 // Ensure minimum slider width
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "refresh"
|
||||
tooltipText: "Reset Scaling"
|
||||
fontPointSize: Style.fontSizeL * scaling
|
||||
Layout.preferredWidth: implicitWidth
|
||||
Layout.minimumWidth: implicitWidth
|
||||
onClicked: {
|
||||
var data = Settings.data.monitorsScaling || {}
|
||||
data[modelData.name] = 1.0
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import qs.Services
|
|||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
property real scaling: 1
|
||||
readonly property real scaling: ScalingService.scale(screen)
|
||||
readonly property string tabIcon: "photo_library"
|
||||
readonly property string tabLabel: "Wallpaper Selector"
|
||||
readonly property int tabIndex: 7
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ NPanel {
|
|||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Style.marginS * scaling
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
|
|
@ -72,6 +73,16 @@ NPanel {
|
|||
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 {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
|
@ -127,69 +138,65 @@ NPanel {
|
|||
|
||||
// Network list
|
||||
ListView {
|
||||
id: networkList
|
||||
anchors.fill: parent
|
||||
visible: Settings.data.network.wifiEnabled && !NetworkService.isLoading
|
||||
model: Object.values(NetworkService.networks)
|
||||
spacing: Style.marginM * scaling
|
||||
spacing: Style.marginS * scaling
|
||||
clip: true
|
||||
|
||||
delegate: Item {
|
||||
width: parent ? parent.width : 0
|
||||
height: modelData.ssid === passwordPromptSsid
|
||||
&& showPasswordPrompt ? 108 * scaling : Style.baseWidgetSize * 1.5 * scaling
|
||||
&& showPasswordPrompt ? 130 * scaling : Style.baseWidgetSize * 1.75 * scaling
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
id: rect
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Style.baseWidgetSize * 1.5 * scaling
|
||||
Layout.fillHeight: true
|
||||
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 {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginS * scaling
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: Style.marginL * scaling
|
||||
rightMargin: Style.marginL * scaling
|
||||
}
|
||||
spacing: Style.marginS * scaling
|
||||
|
||||
NIcon {
|
||||
text: NetworkService.signalIcon(modelData.signal)
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
||||
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginXS * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
spacing: 0
|
||||
|
||||
// SSID
|
||||
NText {
|
||||
Layout.fillWidth: true
|
||||
text: modelData.ssid || "Unknown Network"
|
||||
font.pointSize: Style.fontSizeNormal * scaling
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
||||
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||
}
|
||||
|
||||
// Security Protocol
|
||||
NText {
|
||||
text: modelData.security && modelData.security !== "--" ? modelData.security : "Open"
|
||||
font.pointSize: Style.fontSizeXS * 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
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,17 +210,25 @@ NPanel {
|
|||
NBusyIndicator {
|
||||
visible: NetworkService.connectingSsid === modelData.ssid
|
||||
running: NetworkService.connectingSsid === modelData.ssid
|
||||
color: Color.mPrimary
|
||||
color: networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface
|
||||
anchors.centerIn: parent
|
||||
size: Style.baseWidgetSize * 0.7 * scaling
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
RowLayout {
|
||||
visible: modelData.connected
|
||||
text: "connected"
|
||||
NText {
|
||||
text: "Connected"
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
color: modelData.connected ? Color.mSurface : (networkMouseArea.containsMouse ? Color.mSurface : Color.mOnSurface)
|
||||
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: {
|
||||
if (modelData.connected) {
|
||||
NetworkService.disconnectNetwork(modelData.ssid)
|
||||
showPasswordPrompt = false
|
||||
} else if (NetworkService.isSecured(modelData.security) && !modelData.existing) {
|
||||
passwordPromptSsid = modelData.ssid
|
||||
showPasswordPrompt = true
|
||||
|
|
@ -240,11 +256,11 @@ NPanel {
|
|||
|
||||
// Password prompt section
|
||||
Rectangle {
|
||||
id: passwordPromptSection
|
||||
visible: modelData.ssid === passwordPromptSsid && showPasswordPrompt
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: modelData.ssid === passwordPromptSsid && showPasswordPrompt ? 60 : 0
|
||||
Layout.margins: Style.marginS * scaling
|
||||
visible: modelData.ssid === passwordPromptSsid && showPasswordPrompt
|
||||
|
||||
color: Color.mSurfaceVariant
|
||||
radius: Style.radiusS * scaling
|
||||
|
||||
|
|
@ -280,9 +296,11 @@ NPanel {
|
|||
echoMode: TextInput.Password
|
||||
onTextChanged: passwordInput = text
|
||||
onAccepted: {
|
||||
if (passwordInput !== "") {
|
||||
NetworkService.submitPassword(passwordPromptSsid, passwordInput)
|
||||
showPasswordPrompt = false
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: passwordInputMouseArea
|
||||
|
|
@ -315,15 +333,24 @@ NPanel {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (passwordInput !== "") {
|
||||
NetworkService.submitPassword(passwordPromptSsid, passwordInput)
|
||||
showPasswordPrompt = false
|
||||
}
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: parent.color = Qt.darker(Color.mPrimary, 1.1)
|
||||
onExited: parent.color = Color.mPrimary
|
||||
}
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
onClicked: {
|
||||
showPasswordPrompt = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
|
||||
Singleton {
|
||||
id: updateService
|
||||
|
|
@ -15,20 +16,23 @@ Singleton {
|
|||
property int selectedPackagesCount: 0
|
||||
property bool updateInProgress: false
|
||||
|
||||
// Initial check
|
||||
Component.onCompleted: doPoll()
|
||||
|
||||
// Process for checking updates
|
||||
Process {
|
||||
id: checkupdatesProcess
|
||||
command: ["checkupdates"]
|
||||
onExited: function (exitCode) {
|
||||
if (exitCode !== 0 && exitCode !== 2) {
|
||||
console.warn("[UpdateService] checkupdates failed (code:", exitCode, ")")
|
||||
Logger.warn("ArchUpdater", "checkupdates failed (code:", exitCode, ")")
|
||||
updatePackages = []
|
||||
return
|
||||
}
|
||||
}
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
parseCheckupdatesOutput(text)
|
||||
Logger.log("ArchUpdater", "found", updatePackages.length, "upgradable package(s)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -150,7 +154,4 @@ Singleton {
|
|||
running: true
|
||||
onTriggered: doPoll()
|
||||
}
|
||||
|
||||
// Initial check
|
||||
Component.onCompleted: doPoll()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Singleton {
|
|||
// Widget registry object mapping widget names to components
|
||||
property var widgets: ({
|
||||
"ActiveWindow": activeWindowComponent,
|
||||
// "ArchUpdater": archUpdaterComponent,
|
||||
"ArchUpdater": archUpdaterComponent,
|
||||
"Battery": batteryComponent,
|
||||
"Bluetooth": bluetoothComponent,
|
||||
"Brightness": brightnessComponent,
|
||||
|
|
@ -32,9 +32,9 @@ Singleton {
|
|||
property Component activeWindowComponent: Component {
|
||||
ActiveWindow {}
|
||||
}
|
||||
// property Component archUpdaterComponent: Component {
|
||||
// ArchUpdater {}
|
||||
// }
|
||||
property Component archUpdaterComponent: Component {
|
||||
ArchUpdater {}
|
||||
}
|
||||
property Component batteryComponent: Component {
|
||||
Battery {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ Singleton {
|
|||
|
||||
function setBluetoothEnabled(enabled) {
|
||||
if (!adapter) {
|
||||
console.warn("BluetoothService: No adapter available")
|
||||
Logger.warn("Bluetooth", "No adapter available")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ Singleton {
|
|||
Logger.log("Wallpapers", "Listing wallpapers")
|
||||
scanning = true
|
||||
wallpaperList = []
|
||||
// Unsetting, then setting the folder will re-trigger the parsing!
|
||||
folderModel.folder = ""
|
||||
// Set the folder directly to avoid model reset issues
|
||||
folderModel.folder = "file://" + (Settings.data.wallpaper.directory !== undefined ? Settings.data.wallpaper.directory : "")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ Loader {
|
|||
signal closed
|
||||
|
||||
Component.onCompleted: {
|
||||
// console.log("Oh Yeah")
|
||||
// console.log(objectName)
|
||||
PanelService.registerPanel(root)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,4 +10,7 @@ Text {
|
|||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
renderType: Text.QtRendering
|
||||
font.hintingPreference: Font.PreferNoHinting
|
||||
font.kerning: true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Services
|
||||
import qs.Commons
|
||||
|
||||
Item {
|
||||
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