Compare commits

..

No commits in common. "44b257ce8554ec55485b389cb5b0b7a482931ffb" and "cf3c0d823dadc762d8ac873264e9fa627ca41734" have entirely different histories.

65 changed files with 402 additions and 761 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View file

@ -12,10 +12,10 @@ ColumnLayout {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
animate: true animate: true
icon: root.icon text: root.icon
fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).weight(Font.Bold).build() fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).weight(Font.Bold).build()
} }

View file

@ -13,7 +13,7 @@ Rectangle {
implicitWidth: 38 implicitWidth: 38
implicitHeight: 22 implicitHeight: 22
radius: 0 radius: 11
color: on ? Theme.accent : Theme.fillSubtle color: on ? Theme.accent : Theme.fillSubtle
Behavior on color { Behavior on color {
@ -27,7 +27,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitWidth: 16 implicitWidth: 16
implicitHeight: 16 implicitHeight: 16
radius: 0 radius: 8
color: root.on ? Theme.onAccent : Theme.text color: root.on ? Theme.onAccent : Theme.text
Behavior on x { Behavior on x {

View file

@ -45,8 +45,8 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
} }
NsIcon { MaterialIcon {
icon: "expand_more" text: "expand_more"
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium

View file

@ -110,11 +110,11 @@ RowLayout {
} }
} }
NsIcon { MaterialIcon {
id: upIcon id: upIcon
anchors.centerIn: parent anchors.centerIn: parent
icon: "keyboard_arrow_up" text: "keyboard_arrow_up"
color: Colours.palette.m3onPrimary color: Colours.palette.m3onPrimary
} }
} }
@ -145,11 +145,11 @@ RowLayout {
onReleased: timer.stop() onReleased: timer.stop()
} }
NsIcon { MaterialIcon {
id: downIcon id: downIcon
anchors.centerIn: parent anchors.centerIn: parent
icon: "keyboard_arrow_down" text: "keyboard_arrow_down"
color: Colours.palette.m3onPrimary color: Colours.palette.m3onPrimary
} }
} }

View file

@ -16,7 +16,7 @@ Slider {
background: StyledRect { background: StyledRect {
color: Colours.layer(Colours.palette.m3surfaceContainer, 2) color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
radius: 0 radius: Tokens.rounding.full
StyledRect { StyledRect {
anchors.left: parent.left anchors.left: parent.left
@ -51,7 +51,7 @@ Slider {
anchors.fill: parent anchors.fill: parent
color: Colours.palette.m3inverseSurface color: Colours.palette.m3inverseSurface
radius: 0 radius: Tokens.rounding.full
MouseArea { MouseArea {
id: handleInteraction id: handleInteraction

View file

@ -6,7 +6,7 @@ import qs.services
ButtonBase { ButtonBase {
id: root id: root
property alias icon: label.icon property alias icon: label.text
readonly property alias label: label readonly property alias label: label
font: Tokens.font.icon.medium font: Tokens.font.icon.medium
@ -34,10 +34,11 @@ ButtonBase {
return h; return h;
} }
NsIcon { MaterialIcon {
id: label id: label
anchors.centerIn: parent anchors.centerIn: parent
anchors.verticalCenterOffset: 1 // AHHHHHHH material symbols whyyyy
color: root.onColour color: root.onColour
fontStyle: root.font fontStyle: root.font
fill: !root.isToggle || root.internalChecked ? 1 : 0 fill: !root.isToggle || root.internalChecked ? 1 : 0

View file

@ -7,7 +7,7 @@ import qs.services
ButtonBase { ButtonBase {
id: root id: root
property string icon property alias icon: iconLabel.text
property alias text: label.text property alias text: label.text
readonly property alias iconLabel: iconLabel readonly property alias iconLabel: iconLabel
@ -44,10 +44,9 @@ ButtonBase {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
id: iconLabel id: iconLabel
icon: root.icon
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.topMargin: Math.round(fontInfo.pointSize * 0.0575) Layout.topMargin: Math.round(fontInfo.pointSize * 0.0575)
color: root.onColour color: root.onColour

View file

@ -157,9 +157,9 @@ MouseArea {
anchors.margins: Tokens.padding.medium anchors.margins: Tokens.padding.medium
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
icon: item.modelData?.icon ?? "" text: item.modelData?.icon ?? ""
color: item.active ? Colours.palette.m3onTertiaryContainer : Colours.palette.m3onSurfaceVariant color: item.active ? Colours.palette.m3onTertiaryContainer : Colours.palette.m3onSurfaceVariant
} }
@ -176,8 +176,8 @@ MouseArea {
active: item.modelData?.trailingIcon.length > 0 active: item.modelData?.trailingIcon.length > 0
visible: active visible: active
sourceComponent: NsIcon { sourceComponent: MaterialIcon {
icon: item.modelData.trailingIcon text: item.modelData.trailingIcon
color: item.active ? Colours.palette.m3onTertiaryContainer : Colours.palette.m3onSurfaceVariant color: item.active ? Colours.palette.m3onTertiaryContainer : Colours.palette.m3onSurfaceVariant
} }
} }

View file

@ -64,12 +64,12 @@ Row {
anchors.horizontalCenterOffset: Math.floor(root.verticalPadding / 4) anchors.horizontalCenterOffset: Math.floor(root.verticalPadding / 4)
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
id: iconLabel id: iconLabel
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
animate: true animate: true
icon: root.active?.activeIcon ?? root.fallbackIcon text: root.active?.activeIcon ?? root.fallbackIcon
color: root.disabled ? root.disabledTextColour : root.textColour color: root.disabled ? root.disabledTextColour : root.textColour
fill: 1 fill: 1
} }
@ -116,13 +116,13 @@ Row {
onClicked: root.expanded = !root.expanded onClicked: root.expanded = !root.expanded
} }
NsIcon { MaterialIcon {
id: expandIcon id: expandIcon
anchors.centerIn: parent anchors.centerIn: parent
anchors.horizontalCenterOffset: root.expanded ? 0 : -Math.floor(root.verticalPadding / 4) anchors.horizontalCenterOffset: root.expanded ? 0 : -Math.floor(root.verticalPadding / 4)
icon: "expand_more" text: "expand_more"
color: root.disabled ? root.disabledTextColour : root.textColour color: root.disabled ? root.disabledTextColour : root.textColour
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0

View file

@ -54,12 +54,12 @@ StyledRect {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
id: toggleBtnIcon id: toggleBtnIcon
visible: !!text visible: !!text
fill: root.toggled ? 1 : 0 fill: root.toggled ? 1 : 0
icon: root.icon text: root.icon
color: root.toggled ? Colours.palette[`m3on${root.accent}`] : Colours.palette[`m3on${root.accent}Container`] color: root.toggled ? Colours.palette[`m3on${root.accent}`] : Colours.palette[`m3on${root.accent}Container`]
fontStyle: Tokens.font.icon.size(root.iconSize).build() fontStyle: Tokens.font.icon.size(root.iconSize).build()

View file

@ -57,11 +57,11 @@ Item {
} }
} }
NsIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
grade: 200 grade: 200
icon: image.status === Image.Error ? "broken_image" : "art_track" text: image.status === Image.Error ? "broken_image" : "art_track"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.size((parent.width * 0.35) || 1).build() fontStyle: Tokens.font.icon.size((parent.width * 0.35) || 1).build()
opacity: image.status === Image.Null || image.status === Image.Error ? 1 : 0 opacity: image.status === Image.Null || image.status === Image.Error ? 1 : 0

View file

@ -54,9 +54,8 @@ Scope {
onPressed: { onPressed: {
if (root.hasFullscreen) if (root.hasFullscreen)
return; return;
// NoSignal: drive the redesigned full-screen Power Menu (NsOverlay), const visibilities = Visibilities.getForActive();
// not the old caelestia session panel (now dead code). visibilities.session = !visibilities.session;
NsShell.toggle("power", 0);
} }
} }

View file

@ -75,7 +75,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.margins: Tokens.padding.large anchors.margins: Tokens.padding.large
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.large
color: "transparent" color: "transparent"
Flickable { Flickable {

View file

@ -21,7 +21,7 @@ GridLayout {
Layout.preferredWidth: Tokens.sizes.dashboard.userWidth Layout.preferredWidth: Tokens.sizes.dashboard.userWidth
Layout.fillHeight: true Layout.fillHeight: true
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge
User { User {
id: user id: user
@ -37,7 +37,7 @@ GridLayout {
Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth
Layout.preferredHeight: weather.implicitHeight Layout.preferredHeight: weather.implicitHeight
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge * 1.5
SmallWeather { SmallWeather {
id: weather id: weather
@ -49,7 +49,7 @@ GridLayout {
Layout.preferredWidth: dateTime.implicitWidth Layout.preferredWidth: dateTime.implicitWidth
Layout.fillHeight: true Layout.fillHeight: true
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.large
DateTime { DateTime {
id: dateTime id: dateTime
@ -63,7 +63,7 @@ GridLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: calendar.implicitHeight Layout.preferredHeight: calendar.implicitHeight
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge
Calendar { Calendar {
id: calendar id: calendar
@ -78,7 +78,7 @@ GridLayout {
Layout.preferredWidth: resources.implicitWidth Layout.preferredWidth: resources.implicitWidth
Layout.fillHeight: true Layout.fillHeight: true
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.large
Resources { Resources {
id: resources id: resources
@ -92,7 +92,7 @@ GridLayout {
Layout.preferredWidth: media.implicitWidth Layout.preferredWidth: media.implicitWidth
Layout.fillHeight: true Layout.fillHeight: true
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge * 2
Media { Media {
id: media id: media

View file

@ -102,11 +102,11 @@ Item {
CAnim {} CAnim {}
} }
NsIcon { MaterialIcon {
id: icon id: icon
anchors.centerIn: parent anchors.centerIn: parent
icon: "queue_music" text: "queue_music"
fontStyle: Tokens.font.icon.builders.large.scale(2).build() fontStyle: Tokens.font.icon.builders.large.scale(2).build()
color: Colours.palette.m3onPrimaryContainer color: Colours.palette.m3onPrimaryContainer
} }

View file

@ -23,9 +23,9 @@ Item {
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: "tune" text: "tune"
fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).build() fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).build()
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
} }

View file

@ -86,7 +86,7 @@ Item {
implicitHeight: parent.implicitHeight * 2 implicitHeight: parent.implicitHeight * 2
color: Colours.palette.m3primary color: Colours.palette.m3primary
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.full
} }
Behavior on x { Behavior on x {
@ -148,18 +148,18 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2 implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.medium
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
onClicked: root.dashState.currentTab = tab.TabBar.index onClicked: root.dashState.currentTab = tab.TabBar.index
} }
NsIcon { MaterialIcon {
id: icon id: icon
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: label.top anchors.bottom: label.top
icon: tab.iconName text: tab.iconName
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
fill: tab.current ? 1 : 0 fill: tab.current ? 1 : 0
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium

View file

@ -67,7 +67,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: bigInfoRow.implicitHeight + Tokens.padding.small implicitHeight: bigInfoRow.implicitHeight + Tokens.padding.small
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge * 2
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
RowLayout { RowLayout {
@ -76,9 +76,9 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Tokens.spacing.largeIncreased spacing: Tokens.spacing.largeIncreased
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
icon: Weather.icon text: Weather.icon
fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).build() fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).build()
color: Colours.palette.m3secondary color: Colours.palette.m3secondary
animate: true animate: true
@ -155,7 +155,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: forecastItemColumn.implicitHeight + Tokens.padding.medium * 2 implicitHeight: forecastItemColumn.implicitHeight + Tokens.padding.medium * 2
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.large
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
ColumnLayout { ColumnLayout {
@ -180,9 +180,9 @@ Item {
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
} }
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: forecastItem.modelData.icon text: forecastItem.modelData.icon
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge
color: Colours.palette.m3secondary color: Colours.palette.m3secondary
} }
@ -209,15 +209,15 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 60 Layout.preferredHeight: 60
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.medium
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
icon: detailRoot.icon text: detailRoot.icon
color: detailRoot.colour color: detailRoot.colour
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -252,8 +252,8 @@ Item {
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
icon: weatherStat.icon text: weatherStat.icon
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge
color: weatherStat.colour color: weatherStat.colour
} }

View file

@ -62,7 +62,7 @@ CustomMouseArea {
StateLayer { StateLayer {
color: Colours.palette.m3primary color: Colours.palette.m3primary
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: pressed ? Tokens.rounding.small : Tokens.rounding.large
disabled: { disabled: {
const now = new Date(); const now = new Date();
return root.currMonth === now.getMonth() && root.currYear === now.getFullYear(); return root.currMonth === now.getMonth() && root.currYear === now.getFullYear();

View file

@ -65,10 +65,10 @@ Item {
Anim {} Anim {}
} }
NsIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
icon: res.icon text: res.icon
fontStyle: Tokens.font.icon.large font: Tokens.font.icon.large
color: res.fgColour color: res.fgColour
} }
} }

View file

@ -13,14 +13,14 @@ Item {
Component.onCompleted: Weather.reload() Component.onCompleted: Weather.reload()
NsIcon { MaterialIcon {
id: icon id: icon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
animate: true animate: true
icon: Weather.icon text: Weather.icon
color: Colours.palette.m3secondary color: Colours.palette.m3secondary
fontStyle: Tokens.font.icon.builders.extraLarge.scale(1.6).build() fontStyle: Tokens.font.icon.builders.extraLarge.scale(1.6).build()
} }

View file

@ -75,8 +75,8 @@ Item {
asynchronous: true asynchronous: true
active: pfp.status !== Image.Ready active: pfp.status !== Image.Ready
sourceComponent: NsIcon { sourceComponent: MaterialIcon {
icon: "person_add" text: "person_add"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge
fill: 1 fill: 1
@ -120,9 +120,9 @@ Item {
} }
} }
NsIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
icon: "person_edit" text: "person_edit"
color: Colours.palette.m3onPrimary color: Colours.palette.m3onPrimary
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }
@ -187,9 +187,9 @@ Item {
CAnim {} CAnim {}
} }
NsIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
icon: "clock_arrow_up" text: "clock_arrow_up"
color: Colours.palette.m3onTertiaryContainer color: Colours.palette.m3onTertiaryContainer
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -216,7 +216,7 @@ Item {
implicitWidth: 10 implicitWidth: 10
implicitHeight: 10 implicitHeight: 10
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.full
color: Colours.palette.m3secondaryContainer color: Colours.palette.m3secondaryContainer
} }
@ -229,7 +229,7 @@ Item {
implicitWidth: 15 implicitWidth: 15
implicitHeight: 15 implicitHeight: 15
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.full
color: Colours.palette.m3secondaryContainer color: Colours.palette.m3secondaryContainer
} }
@ -240,7 +240,7 @@ Item {
anchors.leftMargin: -Tokens.padding.medium anchors.leftMargin: -Tokens.padding.medium
y: Tokens.padding.extraSmall y: Tokens.padding.extraSmall
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.largeIncreased
color: Colours.palette.m3secondaryContainer color: Colours.palette.m3secondaryContainer
implicitWidth: wmLabel.implicitWidth + Tokens.padding.medium * 2 implicitWidth: wmLabel.implicitWidth + Tokens.padding.medium * 2
implicitHeight: wmLabel.implicitHeight + Tokens.padding.small * 2 implicitHeight: wmLabel.implicitHeight + Tokens.padding.small * 2
@ -251,11 +251,11 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Tokens.spacing.extraSmall spacing: Tokens.spacing.extraSmall
NsIcon { MaterialIcon {
id: wmIcon id: wmIcon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
icon: "select_window" text: "select_window"
color: Colours.palette.m3onSecondaryContainer color: Colours.palette.m3onSecondaryContainer
fontStyle: wmText.font fontStyle: wmText.font
} }

View file

@ -176,7 +176,7 @@ Item {
implicitWidth: shape.implicitSize + Tokens.padding.medium * 2 implicitWidth: shape.implicitSize + Tokens.padding.medium * 2
implicitHeight: shape.implicitSize + Tokens.padding.medium * 2 implicitHeight: shape.implicitSize + Tokens.padding.medium * 2
color: Colours.palette.m3primaryContainer color: Colours.palette.m3primaryContainer
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.full
LoadingIndicator { LoadingIndicator {
id: shape id: shape
@ -212,9 +212,9 @@ Item {
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: "sentiment_sad" text: "sentiment_sad"
fontStyle: Tokens.font.icon.builders.large.scale(2).build() fontStyle: Tokens.font.icon.builders.large.scale(2).build()
color: Colours.palette.m3outline color: Colours.palette.m3outline
} }

View file

@ -20,9 +20,9 @@ Item {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
z: 1 z: 1
NsIcon { MaterialIcon {
Layout.topMargin: Math.round(fontInfo.pointSize * 0.12) Layout.topMargin: Math.round(fontInfo.pointSize * 0.12)
icon: "lyrics" text: "lyrics"
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }

View file

@ -33,7 +33,7 @@ Item {
anchors.fill: parent anchors.fill: parent
anchors.margins: !btn.pressed && btn.containsMouse ? -Tokens.padding.extraSmall : 0 anchors.margins: !btn.pressed && btn.containsMouse ? -Tokens.padding.extraSmall : 0
group: blobGroup group: blobGroup
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.medium
Behavior on anchors.margins { Behavior on anchors.margins {
Anim {} Anim {}
@ -50,7 +50,7 @@ Item {
implicitHeight: parent.height implicitHeight: parent.height
group: blobGroup group: blobGroup
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.medium
deformScale: 0.00001 deformScale: 0.00001
states: State { states: State {
@ -197,11 +197,11 @@ Item {
hoverEnabled: true hoverEnabled: true
onClicked: root.open = !root.open onClicked: root.open = !root.open
NsIcon { MaterialIcon {
id: icon id: icon
anchors.centerIn: parent anchors.centerIn: parent
icon: "more_vert" text: "more_vert"
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
} }

View file

@ -12,7 +12,7 @@ StyledClippingRect {
property real animPerc: UPower.displayDevice.percentage property real animPerc: UPower.displayDevice.percentage
color: Colours.palette.m3secondaryContainer color: Colours.palette.m3secondaryContainer
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.large
implicitWidth: Config.dashboard.performance.showCpu || (Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) || Config.dashboard.performance.showStorage || Config.dashboard.performance.showMemory ? Tokens.sizes.dashboard.perfBattWidth : Tokens.sizes.dashboard.perfBattWidthSingle implicitWidth: Config.dashboard.performance.showCpu || (Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) || Config.dashboard.performance.showStorage || Config.dashboard.performance.showMemory ? Tokens.sizes.dashboard.perfBattWidth : Tokens.sizes.dashboard.perfBattWidthSingle
implicitHeight: Tokens.sizes.dashboard.perfBattHeight implicitHeight: Tokens.sizes.dashboard.perfBattHeight
@ -39,7 +39,7 @@ StyledClippingRect {
implicitHeight: parent.height * root.animPerc implicitHeight: parent.height * root.animPerc
color: Colours.palette.m3secondary color: Colours.palette.m3secondary
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraSmall
clip: true clip: true
Contents { Contents {
@ -65,9 +65,9 @@ StyledClippingRect {
spacing: 0 spacing: 0
NsIcon { MaterialIcon {
Layout.leftMargin: -Tokens.padding.extraSmall Layout.leftMargin: -Tokens.padding.extraSmall
icon: "battery_full" text: "battery_full"
color: contents.accentColour color: contents.accentColour
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }
@ -115,8 +115,8 @@ StyledClippingRect {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
spacing: Tokens.spacing.extraSmall spacing: Tokens.spacing.extraSmall
NsIcon { MaterialIcon {
icon: "bolt" text: "bolt"
color: contents.accentColour color: contents.accentColour
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
fill: 1 fill: 1

View file

@ -17,7 +17,7 @@ StyledRect {
required property real temperature required property real temperature
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge
implicitWidth: Tokens.sizes.dashboard.perfHeroCardWidth implicitWidth: Tokens.sizes.dashboard.perfHeroCardWidth
implicitHeight: Math.max(tempProg.implicitHeight + detailsRow.implicitHeight + Tokens.spacing.large, usageShape.implicitHeight + usageLabel.implicitHeight) + Tokens.padding.large * 2 implicitHeight: Math.max(tempProg.implicitHeight + detailsRow.implicitHeight + Tokens.spacing.large, usageShape.implicitHeight + usageLabel.implicitHeight) + Tokens.padding.large * 2
@ -40,11 +40,11 @@ StyledRect {
Anim {} Anim {}
} }
NsIcon { MaterialIcon {
id: icon id: icon
anchors.centerIn: parent anchors.centerIn: parent
icon: root.icon text: root.icon
color: root.accent color: root.accent
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -84,9 +84,9 @@ StyledRect {
Layout.leftMargin: -Tokens.padding.extraSmall Layout.leftMargin: -Tokens.padding.extraSmall
spacing: Tokens.spacing.extraSmall spacing: Tokens.spacing.extraSmall
NsIcon { MaterialIcon {
Layout.topMargin: Math.round(fontInfo.pointSize * 0.08) Layout.topMargin: Math.round(fontInfo.pointSize * 0.08)
icon: root.temperature > 90 ? "thermometer_alert" : "thermometer" text: root.temperature > 90 ? "thermometer_alert" : "thermometer"
color: root.temperature > 90 ? Colours.palette.m3error : root.accent color: root.temperature > 90 ? Colours.palette.m3error : root.accent
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
fill: 1 fill: 1

View file

@ -12,7 +12,7 @@ StyledRect {
readonly property color accent: Colours.palette.m3tertiary readonly property color accent: Colours.palette.m3tertiary
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.medium
implicitWidth: layout.implicitWidth + Tokens.padding.extraLargeIncreased * 2 implicitWidth: layout.implicitWidth + Tokens.padding.extraLargeIncreased * 2
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2 implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
@ -31,8 +31,8 @@ StyledRect {
Layout.leftMargin: -Tokens.padding.extraSmall Layout.leftMargin: -Tokens.padding.extraSmall
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
icon: "memory_alt" text: "memory_alt"
fill: 1 fill: 1
color: root.accent color: root.accent
fontStyle: Tokens.font.icon.builders.medium.weight(Font.DemiBold).build() // DemiBold to fix fill issues fontStyle: Tokens.font.icon.builders.medium.weight(Font.DemiBold).build() // DemiBold to fix fill issues

View file

@ -10,7 +10,7 @@ StyledRect {
id: root id: root
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraLarge
implicitWidth: Tokens.sizes.dashboard.perfNetworkCardWidth implicitWidth: Tokens.sizes.dashboard.perfNetworkCardWidth
implicitHeight: Tokens.sizes.dashboard.perfNetworkCardHeight implicitHeight: Tokens.sizes.dashboard.perfNetworkCardHeight
@ -30,8 +30,8 @@ StyledRect {
RowLayout { RowLayout {
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
icon: "swap_vert" text: "swap_vert"
color: Colours.palette.m3primary color: Colours.palette.m3primary
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -105,8 +105,8 @@ StyledRect {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
icon: "download" text: "download"
color: Colours.palette.m3tertiary color: Colours.palette.m3tertiary
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -136,8 +136,8 @@ StyledRect {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
icon: "upload" text: "upload"
color: Colours.palette.m3secondary color: Colours.palette.m3secondary
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -167,8 +167,8 @@ StyledRect {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
icon: "history" text: "history"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }

View file

@ -14,7 +14,7 @@ StyledRect {
readonly property real percentage: Storage.primaryDisk?.perc ?? 0 readonly property real percentage: Storage.primaryDisk?.perc ?? 0
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1) radius: Tokens.rounding.extraExtraLarge
implicitWidth: layout.implicitWidth + layout.anchors.margins * 2 implicitWidth: layout.implicitWidth + layout.anchors.margins * 2
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2 implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
@ -55,9 +55,9 @@ StyledRect {
anchors.centerIn: parent anchors.centerIn: parent
spacing: 0 spacing: 0
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: "hard_drive" text: "hard_drive"
color: root.accent color: root.accent
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }

View file

@ -198,9 +198,7 @@ StyledWindow {
id: osdBg id: osdBg
panel: panels.osdWrapper panel: panels.osdWrapper
deformAmount: 0 // NoSignal: square OSD (no organic blob deformation) deformAmount: 0.25
radius: 0
opacity: 0 // NoSignal: OSD draws its own flat square glass bg (osd/Content)
x: panels.osdWrapper.x + panels.osd.x + root.borderThickness x: panels.osdWrapper.x + panels.osd.x + root.borderThickness
implicitWidth: panels.osd.width implicitWidth: panels.osd.width
} }
@ -209,12 +207,6 @@ StyledWindow {
id: notifsBg id: notifsBg
panel: panels.notifications panel: panels.notifications
deformAmount: 0 // NoSignal: square notification toasts
radius: 0
opacity: 0
visible: false
implicitWidth: 0 // collapse the blob entirely (toasts draw their own square cards)
implicitHeight: 0
} }
PanelBg { PanelBg {

View file

@ -70,7 +70,7 @@ Item {
sessionPanel: sessionWrapper sessionPanel: sessionWrapper
utilitiesPanel: utilities utilitiesPanel: utilities
y: 46 // NoSignal: drop the toasts below the 38px NsBar (+ gap) anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
} }

View file

@ -58,14 +58,14 @@ Item {
implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight) implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
NsIcon { MaterialIcon {
id: searchIcon id: searchIcon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: root.padding anchors.leftMargin: root.padding
icon: "search" text: "search"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
} }
@ -145,7 +145,7 @@ Item {
} }
} }
NsIcon { MaterialIcon {
id: clearIcon id: clearIcon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -163,7 +163,7 @@ Item {
return 1; return 1;
} }
icon: "close" text: "close"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
MouseArea { MouseArea {

View file

@ -116,8 +116,8 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
NsIcon { MaterialIcon {
icon: root.state === "wallpapers" ? "wallpaper_slideshow" : "manage_search" text: root.state === "wallpapers" ? "wallpaper_slideshow" : "manage_search"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge

View file

@ -25,11 +25,11 @@ Item {
anchors.rightMargin: Tokens.padding.medium anchors.rightMargin: Tokens.padding.medium
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.small
NsIcon { MaterialIcon {
id: icon id: icon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
icon: root.modelData?.icon ?? "" text: root.modelData?.icon ?? ""
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.builders.large.scale(1.3).build() fontStyle: Tokens.font.icon.builders.large.scale(1.3).build()
} }

View file

@ -79,8 +79,8 @@ Item {
anchors.right: parent.right anchors.right: parent.right
active: root.modelData && Strings.testRegexList(GlobalConfig.launcher.favouriteApps, root.modelData.id) active: root.modelData && Strings.testRegexList(GlobalConfig.launcher.favouriteApps, root.modelData.id)
sourceComponent: NsIcon { sourceComponent: MaterialIcon {
icon: "favorite" text: "favorite"
fill: 1 fill: 1
color: Colours.palette.m3primary color: Colours.palette.m3primary
} }

View file

@ -40,8 +40,8 @@ Item {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
icon: "function" text: "function"
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@ -105,14 +105,14 @@ Item {
} }
} }
NsIcon { MaterialIcon {
id: icon id: icon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Tokens.padding.medium anchors.rightMargin: Tokens.padding.medium
icon: "open_in_new" text: "open_in_new"
color: Colours.palette.m3onTertiary color: Colours.palette.m3onTertiary
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }

View file

@ -92,8 +92,8 @@ Item {
active: `${root.modelData?.name} ${root.modelData?.flavour}` === Schemes.currentScheme active: `${root.modelData?.name} ${root.modelData?.flavour}` === Schemes.currentScheme
sourceComponent: NsIcon { sourceComponent: MaterialIcon {
icon: "check" text: "check"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }

View file

@ -26,10 +26,10 @@ Item {
anchors.rightMargin: Tokens.padding.medium anchors.rightMargin: Tokens.padding.medium
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.small
NsIcon { MaterialIcon {
id: icon id: icon
icon: root.modelData?.icon ?? "" text: root.modelData?.icon ?? ""
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -68,8 +68,8 @@ Item {
active: root.modelData?.variant === Schemes.currentVariant active: root.modelData?.variant === Schemes.currentVariant
sourceComponent: NsIcon { sourceComponent: MaterialIcon {
icon: "check" text: "check"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }

View file

@ -57,9 +57,9 @@ Item {
implicitWidth: Tokens.sizes.launcher.wallpaperWidth implicitWidth: Tokens.sizes.launcher.wallpaperWidth
implicitHeight: implicitWidth / 16 * 9 implicitHeight: implicitWidth / 16 * 9
NsIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
icon: "image" text: "image"
color: Colours.tPalette.m3outline color: Colours.tPalette.m3outline
fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).weight(Font.DemiBold).build() fontStyle: Tokens.font.icon.builders.extraLarge.scale(2).weight(Font.DemiBold).build()
} }

View file

@ -1,22 +1,11 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
// NoSignal lock screen surface (interface redesign 2026-06-14).
// Secure ext-session-lock content: blurred wallpaper + scrim, top status row,
// centred clock/date/avatar/username/password, bottom now-playing strip.
// Reuses caelestia's Pam (buffer + handleKey + state) for PAM auth and the
// WlSessionLock unlock signal input is fed to pam.handleKey, never compared
// in QML. JetBrains Mono / Nerd Font / NoSignal Theme tokens.
import QtQuick import QtQuick
import QtQuick.Layouts
import QtQuick.Effects import QtQuick.Effects
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Bluetooth
import Quickshell.Services.UPower
import Caelestia.Config import Caelestia.Config
import qs.components import qs.components
import qs.services import qs.services
import qs.utils
WlSessionLockSurface { WlSessionLockSurface {
id: root id: root
@ -24,26 +13,153 @@ WlSessionLockSurface {
required property WlSessionLock lock required property WlSessionLock lock
required property Pam pam required property Pam pam
readonly property bool errored: root.pam.state === "error" || root.pam.state === "fail" readonly property alias unlocking: unlockAnim.running
contentItem.Config.screen: screen?.name ?? "" contentItem.Config.screen: screen.name
contentItem.Tokens.screen: screen?.name ?? "" contentItem.Tokens.screen: screen.name
color: "transparent" color: "transparent"
Connections { Connections {
function onUnlock(): void { function onUnlock(): void {
root.lock.locked = false; unlockAnim.start();
} }
target: root.lock target: root.lock
} }
// Blurred wallpaper + scrim SequentialAnimation {
id: unlockAnim
ParallelAnimation {
Anim {
target: lockContent
properties: "implicitWidth,implicitHeight"
to: lockContent.size
}
Anim {
target: lockBg
property: "radius"
to: lockContent.radius
}
Anim {
target: content
property: "scale"
to: 0
}
Anim {
target: content
property: "opacity"
to: 0
type: Anim.StandardSmall
}
Anim {
target: lockIcon
property: "opacity"
to: 1
type: Anim.StandardLarge
}
Anim {
target: background
property: "opacity"
to: 0
type: Anim.StandardLarge
}
SequentialAnimation {
PauseAnimation {
duration: Tokens.anim.durations.small
}
Anim {
type: Anim.Standard
target: lockContent
property: "opacity"
to: 0
}
}
}
PropertyAction {
target: root.lock
property: "locked"
value: false
}
}
ParallelAnimation {
id: initAnim
running: true
Anim {
target: background
property: "opacity"
to: 1
type: Anim.StandardLarge
}
SequentialAnimation {
ParallelAnimation {
Anim {
target: lockContent
property: "scale"
to: 1
type: Anim.FastSpatial
}
Anim {
target: lockContent
property: "rotation"
to: 360
duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.standardAccel
}
}
ParallelAnimation {
Anim {
target: lockIcon
property: "rotation"
to: 360
easing: Tokens.anim.standardDecel
}
Anim {
type: Anim.DefaultEffects
target: lockIcon
property: "opacity"
to: 0
}
Anim {
type: Anim.DefaultEffects
target: content
property: "opacity"
to: 1
}
Anim {
target: content
property: "scale"
to: 1
}
Anim {
target: lockBg
property: "radius"
to: lockContent.Tokens.rounding.extraLarge * 1.5
}
Anim {
target: lockContent
property: "implicitWidth"
to: (root.screen?.height ?? 0) * lockContent.Tokens.sizes.lock.heightMult * lockContent.Tokens.sizes.lock.ratio
}
Anim {
target: lockContent
property: "implicitHeight"
to: (root.screen?.height ?? 0) * lockContent.Tokens.sizes.lock.heightMult
}
}
}
}
ScreencopyView { ScreencopyView {
id: background id: background
anchors.fill: parent anchors.fill: parent
captureSource: root.screen captureSource: root.screen
opacity: 0
layer.enabled: true layer.enabled: true
layer.effect: MultiEffect { layer.effect: MultiEffect {
@ -52,265 +168,57 @@ WlSessionLockSurface {
blur: 1 blur: 1
blurMax: 64 blurMax: 64
blurMultiplier: 1 blurMultiplier: 1
brightness: -0.38
saturation: 0.1
} }
} }
Rectangle {
anchors.fill: parent
color: Qt.rgba(8 / 255, 10 / 255, 14 / 255, 0.5)
}
// Keyboard capture (feed PAM; Escape does nothing)
Item { Item {
anchors.fill: parent id: lockContent
focus: true
Component.onCompleted: forceActiveFocus()
Keys.onPressed: event => root.pam.handleKey(event)
}
// Top status row readonly property int size: lockIcon.implicitHeight + Tokens.padding.large * 4
RowLayout { readonly property int radius: size / 4 * Tokens.rounding.scale
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 22
anchors.leftMargin: 28
anchors.rightMargin: 28
RowLayout {
spacing: 7
NsIcon {
icon: "lock"
color: Theme.textMuted
size: 15
}
StyledText {
text: "Locked"
color: Theme.textMuted
font.family: Theme.font.family
font.pixelSize: Theme.font.bar
}
}
Item {
Layout.fillWidth: true
}
RowLayout {
spacing: 14
NsIcon {
icon: Nmcli.active ? Icons.getNetworkIcon(Nmcli.active.strength ?? 0) : "wifi_off"
color: Theme.textMuted
size: 15
}
NsIcon {
icon: Bluetooth.defaultAdapter?.enabled ? "bluetooth_connected" : "bluetooth_disabled"
color: Theme.textMuted
size: 15
}
RowLayout {
spacing: 6
visible: UPower.displayDevice.isLaptopBattery
NsIcon {
icon: Icons.getBatteryIcon(UPower.displayDevice.percentage, [UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged].includes(UPower.displayDevice.state))
color: Theme.textMuted
size: 15
}
StyledText {
text: Math.round(UPower.displayDevice.percentage * 100) + "%"
color: Theme.textMuted
font.family: Theme.font.family
font.pixelSize: Theme.font.bar
}
}
}
}
// Centre block
ColumnLayout {
anchors.centerIn: parent anchors.centerIn: parent
spacing: 0 implicitWidth: size
implicitHeight: size
StyledText { rotation: 180
Layout.alignment: Qt.AlignHCenter scale: 0
text: Time.format("hh:mm")
color: Theme.text
font.family: Theme.font.family
font.pixelSize: 108
font.weight: Font.ExtraLight
font.letterSpacing: 3
}
StyledText { StyledRect {
Layout.alignment: Qt.AlignHCenter id: lockBg
text: Time.format("ddd, d MMMM yyyy")
color: Theme.textMuted
font.family: Theme.font.family
font.pixelSize: 15
}
Rectangle { anchors.fill: parent
Layout.alignment: Qt.AlignHCenter color: Colours.palette.m3surface
Layout.topMargin: 64 radius: parent.radius
implicitWidth: 74 opacity: Colours.transparency.enabled ? Colours.transparency.base : 1
implicitHeight: 74
radius: 0 layer.enabled: true
gradient: Gradient { layer.effect: MultiEffect {
orientation: Gradient.Vertical shadowEnabled: true
GradientStop { blurMax: 15
position: 0 shadowColor: Qt.alpha(Colours.palette.m3shadow, 0.7)
color: Theme.accent
}
GradientStop {
position: 1
color: Theme.blue
}
}
NsIcon {
anchors.centerIn: parent
icon: "person"
color: Theme.onAccent
size: 34
} }
} }
StyledText { MaterialIcon {
Layout.alignment: Qt.AlignHCenter id: lockIcon
Layout.topMargin: 14
text: SysInfo.user || "user" anchors.centerIn: parent
color: Theme.text text: "lock"
font.family: Theme.font.family fontStyle: Tokens.font.icon.builders.extraLarge.scale(4).weight(Font.Bold).build()
font.pixelSize: 14 rotation: 180
} }
Rectangle { Content {
Layout.alignment: Qt.AlignHCenter id: content
Layout.topMargin: 16
implicitWidth: 312
implicitHeight: 44
radius: Theme.radius.panel
color: Qt.rgba(17 / 255, 20 / 255, 26 / 255, 0.55)
border.width: 1
border.color: root.errored ? Qt.rgba(224 / 255, 116 / 255, 106 / 255, 0.6) : Qt.rgba(1, 1, 1, 0.1)
RowLayout { anchors.centerIn: parent
anchors.fill: parent width: (root.screen?.height ?? 0) * Tokens.sizes.lock.heightMult * Tokens.sizes.lock.ratio - Tokens.padding.extraLargeIncreased
anchors.leftMargin: 14 height: (root.screen?.height ?? 0) * Tokens.sizes.lock.heightMult - Tokens.padding.extraLargeIncreased
anchors.rightMargin: 12
spacing: 10
NsIcon { lock: root
icon: "key" opacity: 0
color: Theme.textMuted scale: 0
size: 15
}
StyledText {
Layout.fillWidth: true
text: root.pam.buffer.length > 0 ? "•".repeat(root.pam.buffer.length) : "Enter password"
color: root.pam.buffer.length > 0 ? Theme.text : Theme.textFaint
elide: Text.ElideRight
font.family: Theme.font.family
font.pixelSize: Theme.font.body
font.letterSpacing: root.pam.buffer.length > 0 ? 2 : 0
}
NsIcon {
icon: "login"
color: root.pam.buffer.length > 0 ? Theme.accent : Theme.textFaint
size: 16
MouseArea {
anchors.fill: parent
anchors.margins: -6
cursorShape: Qt.PointingHandCursor
onClicked: if (root.pam.buffer.length > 0)
root.pam.passwd.start()
}
}
}
}
StyledText {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 8
Layout.preferredHeight: 14
text: root.errored ? "Incorrect — try again" : (root.pam.lockMessage || "")
color: Theme.danger
font.family: Theme.font.family
font.pixelSize: 12
}
}
// Bottom strip
RowLayout {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottomMargin: 26
anchors.leftMargin: 28
anchors.rightMargin: 28
RowLayout {
spacing: 10
visible: Players.active !== null
Rectangle {
implicitWidth: 42
implicitHeight: 42
radius: Theme.radius.panel
gradient: Gradient {
orientation: Gradient.Vertical
GradientStop {
position: 0
color: Theme.accent
}
GradientStop {
position: 1
color: Theme.blue
}
}
NsIcon {
anchors.centerIn: parent
icon: "music_note"
color: Theme.onAccent
size: 18
}
}
ColumnLayout {
spacing: 0
StyledText {
text: Players.active?.trackTitle || ""
color: Theme.text
elide: Text.ElideRight
Layout.maximumWidth: 280
font.family: Theme.font.family
font.pixelSize: Theme.font.bodySmall
}
StyledText {
text: Players.active?.trackArtist || ""
color: Theme.textMuted
elide: Text.ElideRight
Layout.maximumWidth: 280
font.family: Theme.font.family
font.pixelSize: Theme.font.meta
}
}
}
Item {
Layout.fillWidth: true
}
StyledText {
text: "Press Enter to unlock"
color: Theme.textFaint
font.family: Theme.font.family
font.pixelSize: 11
} }
} }
} }

View file

@ -1,73 +0,0 @@
// CachyRepoToggleRow.qml (NoSignal) Settings -> Services toggle to enable /
// disable the CachyOS pacman repositories. Auto-detects the best x86-64 microarch
// tier the CPU supports (v4 > v3). Live state polls `nosignal-cachy-repo status`
// (no root). enable/disable run in a floating terminal so the pacman/download
// output stays visible; the grant is passwordless via sudo -n
// (/etc/sudoers.d/02-nosignal-cachy). enable adds repos, converts userspace to
// the optimized builds (pacman -Suu, pacman pinned stock), and installs the
// linux-cachyos kernel; disable reverts to stock and removes the cachy kernel
// (keeping stock `linux` bootable). A reboot switches the running kernel.
//
// Untracked file under modules/nexus/common auto-discovered as the type
// `CachyRepoToggleRow` via `import qs.modules.nexus.common`. Survives caelestia
// upgrades; pairs with the one-line insert in ServicesPage.qml.
import QtQuick
import Quickshell.Io
import qs.modules.nexus.common
ToggleRow {
id: root
property bool repoOn: false // NB: not `enabled` (reserved Item property)
text: qsTr("CachyOS repositories")
subtext: repoOn
? qsTr("On — CachyOS optimized builds + linux-cachyos kernel (reboot to run it)")
: qsTr("Switch to CachyOS optimized builds + linux-cachyos kernel (reboot after)")
onToggled: {
if (checked)
enableProc.running = true;
else
disableProc.running = true;
reconcile.restart();
}
// --- live state -----------------------------------------------------------
Process {
id: statusProc
command: ["/usr/local/bin/nosignal-cachy-repo", "status"]
stdout: StdioCollector {
onStreamFinished: {
root.repoOn = text.trim() === "enabled";
root.checked = root.repoOn; // drive switch from real state
}
}
}
// --- actions (passwordless; shown in a terminal for pacman output) ---------
Process {
id: enableProc
command: ["kitty", "--class", "TUI.float", "-e", "sh", "-c", "sudo -n /usr/local/bin/nosignal-cachy-repo enable; printf '\\nPress Enter to close...'; read _"]
onExited: reconcile.restart()
}
Process {
id: disableProc
command: ["kitty", "--class", "TUI.float", "-e", "sh", "-c", "sudo -n /usr/local/bin/nosignal-cachy-repo disable; printf '\\nPress Enter to close...'; read _"]
onExited: reconcile.restart()
}
// --- polling --------------------------------------------------------------
Timer {
interval: 5000
repeat: true
running: true
triggeredOnStart: true
onTriggered: statusProc.running = true
}
Timer {
id: reconcile
interval: 2000
onTriggered: statusProc.running = true
}
}

View file

@ -1,6 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell
import Quickshell.Io import Quickshell.Io
import Caelestia import Caelestia
import Caelestia.Config import Caelestia.Config
@ -62,27 +61,22 @@ PageBase {
width: parent.width - Tokens.padding.largeIncreased * 2 width: parent.width - Tokens.padding.largeIncreased * 2
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
Image { AnimatedLogo {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 104 Layout.preferredWidth: implicitWidth
Layout.preferredHeight: 104 Layout.preferredHeight: implicitHeight
source: Quickshell.shellDir + "/assets/nosignal-logo.png"
sourceSize.width: 208
sourceSize.height: 208
fillMode: Image.PreserveAspectFit
smooth: true
} }
StyledText { StyledText {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Tokens.spacing.small Layout.topMargin: Tokens.spacing.small
text: "NoSignal" text: "Caelestia"
font: Tokens.font.headline.builders.large.width(110).build() font: Tokens.font.headline.builders.large.width(110).build()
} }
StyledText { StyledText {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: "V1" text: CUtils.version ? `v${CUtils.version}` : "…"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
font: Tokens.font.body.medium font: Tokens.font.body.medium
} }

View file

@ -92,71 +92,41 @@ PageBase {
text: qsTr("Weather") text: qsTr("Weather")
} }
// Location for the weather service. Weather.qml accepts a city name // Placeholder until the map-based location picker lands
// (geocoded) or a "lat,lon" string, and auto-detects via IP when empty.
ConnectedRect { ConnectedRect {
Layout.fillWidth: true Layout.fillWidth: true
first: true first: true
last: true last: true
implicitHeight: weatherLayout.implicitHeight + weatherLayout.anchors.margins * 2 implicitHeight: comingSoon.implicitHeight + Tokens.padding.extraLarge * 2
ColumnLayout { ColumnLayout {
id: weatherLayout id: comingSoon
anchors.fill: parent anchors.centerIn: parent
anchors.margins: Tokens.padding.medium width: parent.width - Tokens.padding.largeIncreased * 2
anchors.leftMargin: Tokens.padding.largeIncreased spacing: Tokens.padding.extraSmall
anchors.rightMargin: Tokens.padding.largeIncreased
spacing: Tokens.spacing.small
StyledText { NsIcon {
Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter
text: qsTr("Location") icon: "map"
font: Tokens.font.body.small color: Colours.palette.m3outlineVariant
elide: Text.ElideRight fontStyle: Tokens.font.icon.extraLarge
} }
StyledRect { StyledText {
Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter
implicitHeight: locField.implicitHeight + Tokens.padding.medium * 2 text: qsTr("Location picker coming soon")
color: Colours.palette.m3outlineVariant
radius: Tokens.rounding.small font: Tokens.font.title.small
color: Colours.tPalette.m3surfaceContainerLowest
border.color: Colours.palette.m3outlineVariant
Behavior on border.color {
CAnim {}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.IBeamCursor
onClicked: locField.focus = true
}
StyledTextField {
id: locField
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Tokens.padding.large
anchors.rightMargin: Tokens.padding.large
text: GlobalConfig.services.weatherLocation
placeholderText: qsTr("City name or lat,long — empty = auto (IP)")
placeholderTextColor: Colours.palette.m3onSurfaceVariant
color: Colours.palette.m3onSurface
onEditingFinished: GlobalConfig.services.weatherLocation = text
}
} }
StyledText { StyledText {
Layout.fillWidth: true Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: qsTr("Leave empty to detect your location automatically.") text: qsTr("Choose your weather location on a map in a future update")
color: Colours.palette.m3outline color: Colours.palette.m3outlineVariant
font: Tokens.font.label.small font: Tokens.font.body.small
} }
} }
} }

View file

@ -216,11 +216,6 @@ PageBase {
Layout.fillWidth: true Layout.fillWidth: true
} }
// NoSignal: CachyOS repos enable/disable (sudoless, auto-tier)
CachyRepoToggleRow {
Layout.fillWidth: true
}
SelectRow { SelectRow {
Layout.fillWidth: true Layout.fillWidth: true
last: true last: true

View file

@ -63,7 +63,7 @@ Item {
anchors.rightMargin: root.clampedPadding anchors.rightMargin: root.clampedPadding
color: "transparent" color: "transparent"
radius: 0 radius: Tokens.rounding.large
StyledListView { StyledListView {
id: list id: list

View file

@ -23,7 +23,7 @@ StyledRect {
property bool expanded: Config.notifs.openExpanded property bool expanded: Config.notifs.openExpanded
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3secondaryContainer : Colours.tPalette.m3surfaceContainer color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3secondaryContainer : Colours.tPalette.m3surfaceContainer
radius: 0 radius: Tokens.rounding.large
implicitHeight: inner.implicitHeight implicitHeight: inner.implicitHeight
@ -116,7 +116,7 @@ StyledRect {
visible: root.hasImage || root.hasAppIcon visible: root.hasImage || root.hasAppIcon
sourceComponent: StyledClippingRect { sourceComponent: StyledClippingRect {
radius: 0 radius: Tokens.rounding.full
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer
implicitWidth: TokenConfig.sizes.notifs.image implicitWidth: TokenConfig.sizes.notifs.image
implicitHeight: TokenConfig.sizes.notifs.image implicitHeight: TokenConfig.sizes.notifs.image
@ -147,7 +147,7 @@ StyledRect {
anchors.bottom: root.hasImage ? image.bottom : undefined anchors.bottom: root.hasImage ? image.bottom : undefined
sourceComponent: StyledRect { sourceComponent: StyledRect {
radius: 0 radius: Tokens.rounding.full
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer
implicitWidth: root.hasImage ? Tokens.sizes.notifs.badge : TokenConfig.sizes.notifs.image implicitWidth: root.hasImage ? Tokens.sizes.notifs.badge : TokenConfig.sizes.notifs.image
implicitHeight: root.hasImage ? Tokens.sizes.notifs.badge : TokenConfig.sizes.notifs.image implicitHeight: root.hasImage ? Tokens.sizes.notifs.badge : TokenConfig.sizes.notifs.image
@ -177,8 +177,8 @@ StyledRect {
anchors.centerIn: parent anchors.centerIn: parent
anchors.verticalCenterOffset: 1 anchors.verticalCenterOffset: 1
sourceComponent: NsIcon { sourceComponent: MaterialIcon {
icon: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency) text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -358,17 +358,17 @@ StyledRect {
implicitHeight: expandIcon.implicitHeight implicitHeight: expandIcon.implicitHeight
StateLayer { StateLayer {
radius: 0 radius: Tokens.rounding.full
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
onClicked: root.expanded = !root.expanded onClicked: root.expanded = !root.expanded
} }
NsIcon { MaterialIcon {
id: expandIcon id: expandIcon
anchors.centerIn: parent anchors.centerIn: parent
anchors.verticalCenterOffset: root.expanded ? -1 : 1 anchors.verticalCenterOffset: root.expanded ? -1 : 1
icon: "expand_more" text: "expand_more"
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0

View file

@ -16,7 +16,6 @@ import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Bluetooth import Quickshell.Bluetooth
import Quickshell.Services.UPower import Quickshell.Services.UPower
import Quickshell.Services.SystemTray
import qs.services import qs.services
import qs.utils import qs.utils
import qs.components import qs.components
@ -140,12 +139,10 @@ Variants {
} }
} }
// System tray only shown when an app actually registers a tray // System tray
// icon, otherwise the pill just opened an empty panel (F-T1).
IconPill { IconPill {
icon: "widgets" icon: "widgets"
panel: "tray" panel: "tray"
visible: SystemTray.items.values.length > 0
} }
// Notifications bell (with unread dot overlaid on the icon) // Notifications bell (with unread dot overlaid on the icon)
@ -167,7 +164,7 @@ Variants {
anchors.topMargin: 1 anchors.topMargin: 1
implicitWidth: 6 implicitWidth: 6
implicitHeight: 6 implicitHeight: 6
radius: 0 radius: 3
color: Theme.accent color: Theme.accent
} }
} }

View file

@ -122,13 +122,13 @@ NsPanel {
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: 6 implicitHeight: 6
radius: 0 radius: 3
color: Theme.fillSubtle color: Theme.fillSubtle
Rectangle { Rectangle {
width: parent.width * Math.max(0, Math.min(1, s.value)) width: parent.width * Math.max(0, Math.min(1, s.value))
height: parent.height height: parent.height
radius: 0 radius: 3
color: Theme.accent color: Theme.accent
} }
@ -137,7 +137,7 @@ NsPanel {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitWidth: 14 implicitWidth: 14
implicitHeight: 14 implicitHeight: 14
radius: 0 radius: 7
color: Theme.accent color: Theme.accent
} }

View file

@ -109,7 +109,7 @@ NsPanel {
visible: parent.modelData > 0 visible: parent.modelData > 0
implicitWidth: 26 implicitWidth: 26
implicitHeight: 26 implicitHeight: 26
radius: 0 radius: 13
color: parent.today ? Theme.accent : "transparent" color: parent.today ? Theme.accent : "transparent"
StyledText { StyledText {

View file

@ -40,7 +40,7 @@ NsPanel {
Rectangle { Rectangle {
implicitWidth: 26 implicitWidth: 26
implicitHeight: 26 implicitHeight: 26
radius: 0 radius: 13
color: Notifs.dnd ? Theme.accentSoft : dndMa.containsMouse ? Theme.hover : "transparent" color: Notifs.dnd ? Theme.accentSoft : dndMa.containsMouse ? Theme.hover : "transparent"
NsIcon { NsIcon {

View file

@ -3,13 +3,10 @@ pragma ComponentBehavior: Bound
// NoSignal Quick Settings popout (off the media / battery pill). Avatar + user + // NoSignal Quick Settings popout (off the media / battery pill). Avatar + user +
// uptime + power button; 2-col toggle grid; brightness + volume sliders; media // uptime + power button; 2-col toggle grid; brightness + volume sliders; media
// card. Wired to the real services (Network, Bluetooth, Notifs, Audio, // card. Wired to the real services (Network, Bluetooth, Notifs, Audio,
// Brightness, Players). Night Light drives hyprsunset; Airplane drives the // Brightness, Players); Night Light / Airplane / VPN are stateful toggles for now.
// NetworkManager + Bluetooth radios. (VPN tile removed pending a real backend.)
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Bluetooth import Quickshell.Bluetooth
import qs.services import qs.services
import qs.utils import qs.utils
@ -23,35 +20,6 @@ NsPanel {
readonly property var brightMon: Brightness.monitors[0] ?? null readonly property var brightMon: Brightness.monitors[0] ?? null
// Night Light state tracks the real hyprsunset process rather than a local
// flag, so the tile stays correct across shell reloads or changes made
// elsewhere. Seeded on load (probe runs immediately), reconciled on a timer,
// and re-checked right after a toggle.
property bool nightLightOn: false
Process {
id: nightProbe
command: ["pgrep", "-x", "hyprsunset"]
running: true
stdout: StdioCollector {
onStreamFinished: root.nightLightOn = text.trim().length > 0
}
}
Timer {
interval: 3000
running: true
repeat: true
onTriggered: nightProbe.running = true
}
Timer {
id: nightRefresh
interval: 500
repeat: false
onTriggered: nightProbe.running = true
}
// Header // Header
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
@ -60,7 +28,7 @@ NsPanel {
Rectangle { Rectangle {
implicitWidth: 40 implicitWidth: 40
implicitHeight: 40 implicitHeight: 40
radius: 0 radius: 20
gradient: Gradient { gradient: Gradient {
orientation: Gradient.Vertical orientation: Gradient.Vertical
GradientStop { GradientStop {
@ -107,7 +75,7 @@ NsPanel {
Rectangle { Rectangle {
implicitWidth: 34 implicitWidth: 34
implicitHeight: 34 implicitHeight: 34
radius: 0 radius: 17
color: pwrMa.containsMouse ? Theme.accentSoft : Theme.fillSubtle color: pwrMa.containsMouse ? Theme.accentSoft : Theme.fillSubtle
NsIcon { NsIcon {
@ -160,31 +128,21 @@ NsPanel {
icon: "nightlight" icon: "nightlight"
label: "Night Light" label: "Night Light"
sub: on ? "Warm 3500K" : "Off" sub: on ? "Warm 3500K" : "Off"
on: root.nightLightOn onToggled: on = !on
onToggled: {
if (root.nightLightOn)
Quickshell.execDetached(["pkill", "-x", "hyprsunset"]);
else
Quickshell.execDetached(["sh", "-c", "pkill -x hyprsunset; hyprsunset -t 3500"]);
nightRefresh.restart();
}
} }
QSToggle { QSToggle {
id: airTog id: airTog
icon: "airplanemode_active" icon: "airplanemode_active"
label: "Airplane" label: "Airplane"
// Reflects the real radio state: airplane is "On" when both Wi-Fi and sub: on ? "On" : "Off"
// Bluetooth are down. Network.wifiEnabled tracks nmcli; the adapter onToggled: on = !on
// tracks BlueZ, so the tile self-corrects if radios change elsewhere. }
readonly property bool radiosOff: !Network.wifiEnabled && !(Bluetooth.defaultAdapter?.enabled ?? false) QSToggle {
sub: radiosOff ? "On" : "Off" id: vpnTog
on: radiosOff icon: "vpn_key"
onToggled: { label: "VPN"
if (radiosOff) sub: on ? "On" : "Off"
Quickshell.execDetached(["sh", "-c", "nmcli radio all on; bluetoothctl power on"]); onToggled: on = !on
else
Quickshell.execDetached(["sh", "-c", "nmcli radio all off; bluetoothctl power off"]);
}
} }
} }
@ -306,7 +264,7 @@ NsPanel {
Rectangle { Rectangle {
implicitWidth: 30 implicitWidth: 30
implicitHeight: 30 implicitHeight: 30
radius: 0 radius: 15
color: tile.on ? Theme.accent : Qt.rgba(1, 1, 1, 0.06) color: tile.on ? Theme.accent : Qt.rgba(1, 1, 1, 0.06)
NsIcon { NsIcon {
@ -361,13 +319,13 @@ NsPanel {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: 6 implicitHeight: 6
radius: 0 radius: 3
color: Theme.fillSubtle color: Theme.fillSubtle
Rectangle { Rectangle {
width: parent.width * Math.max(0, Math.min(1, s.value)) width: parent.width * Math.max(0, Math.min(1, s.value))
height: parent.height height: parent.height
radius: 0 radius: 3
color: Theme.accent color: Theme.accent
} }
@ -376,7 +334,7 @@ NsPanel {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitWidth: 14 implicitWidth: 14
implicitHeight: 14 implicitHeight: 14
radius: 0 radius: 7
color: Theme.accent color: Theme.accent
} }
@ -404,7 +362,7 @@ NsPanel {
implicitWidth: 28 implicitWidth: 28
implicitHeight: 28 implicitHeight: 28
radius: 0 radius: 14
color: mbm.containsMouse ? Theme.hover : "transparent" color: mbm.containsMouse ? Theme.hover : "transparent"
NsIcon { NsIcon {

View file

@ -24,15 +24,6 @@ Item {
implicitWidth: layout.implicitWidth + Tokens.padding.large + layout.anchors.horizontalCenterOffset * 2 implicitWidth: layout.implicitWidth + Tokens.padding.large + layout.anchors.horizontalCenterOffset * 2
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2 implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
// NoSignal: flat square glass background matching the design popouts
Rectangle {
anchors.fill: parent
color: Theme.panelBg
radius: 0
border.width: 1
border.color: Theme.panelBorder
}
ColumnLayout { ColumnLayout {
id: layout id: layout

View file

@ -160,9 +160,9 @@ Item {
Component { Component {
id: iconBtn id: iconBtn
NsIcon { MaterialIcon {
animate: action.modelData.isCopy ?? false animate: action.modelData.isCopy ?? false
icon: action.modelData.isCopy ? "content_copy" : "close" text: action.modelData.isCopy ? "content_copy" : "close"
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
} }
} }

View file

@ -110,8 +110,8 @@ StyledRect {
Component { Component {
id: materialIconComp id: materialIconComp
NsIcon { MaterialIcon {
icon: Icons.getNotifIcon(root.activeNotifs[0]?.summary, root.urgency) text: Icons.getNotifIcon(root.activeNotifs[0]?.summary, root.urgency)
color: root.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer color: root.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
@ -214,9 +214,9 @@ StyledRect {
font: Tokens.font.body.small font: Tokens.font.body.small
} }
NsIcon { MaterialIcon {
Layout.rightMargin: -Tokens.padding.extraSmall / 2 Layout.rightMargin: -Tokens.padding.extraSmall / 2
icon: "expand_more" text: "expand_more"
color: root.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : Colours.palette.m3onSurfaceVariant color: root.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : Colours.palette.m3onSurfaceVariant
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0
Layout.topMargin: root.expanded ? -Math.floor(Tokens.padding.extraSmall) : 0 Layout.topMargin: root.expanded ? -Math.floor(Tokens.padding.extraSmall) : 0

View file

@ -33,11 +33,11 @@ StyledRect {
radius: Tokens.rounding.full radius: Tokens.rounding.full
color: IdleInhibitor.enabled ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer color: IdleInhibitor.enabled ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
NsIcon { MaterialIcon {
id: icon id: icon
anchors.centerIn: parent anchors.centerIn: parent
icon: "coffee" text: "coffee"
color: IdleInhibitor.enabled ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer color: IdleInhibitor.enabled ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }

View file

@ -43,12 +43,12 @@ StyledRect {
radius: Tokens.rounding.full radius: Tokens.rounding.full
color: Recorder.running ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer color: Recorder.running ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
NsIcon { MaterialIcon {
id: icon id: icon
anchors.centerIn: parent anchors.centerIn: parent
anchors.verticalCenterOffset: 1 anchors.verticalCenterOffset: 1
icon: "screen_record" text: "screen_record"
color: Recorder.running ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer color: Recorder.running ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }

View file

@ -29,9 +29,9 @@ ColumnLayout {
RowLayout { RowLayout {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
icon: "list" text: "list"
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }
@ -165,9 +165,9 @@ ColumnLayout {
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: "scan_delete" text: "scan_delete"
color: Colours.palette.m3outline color: Colours.palette.m3outline
fontStyle: Tokens.font.icon.extraLarge fontStyle: Tokens.font.icon.extraLarge
@ -193,9 +193,9 @@ ColumnLayout {
RowLayout { RowLayout {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: "scan_delete" text: "scan_delete"
color: Colours.palette.m3outline color: Colours.palette.m3outline
opacity: !root.props.recordingListExpanded ? 1 : 0 opacity: !root.props.recordingListExpanded ? 1 : 0

View file

@ -70,11 +70,11 @@ StyledRect {
implicitWidth: implicitHeight implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Tokens.padding.large implicitHeight: icon.implicitHeight + Tokens.padding.large
NsIcon { MaterialIcon {
id: icon id: icon
anchors.centerIn: parent anchors.centerIn: parent
icon: root.modelData.icon text: root.modelData.icon
color: { color: {
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return Colours.palette.m3onSuccess; return Colours.palette.m3onSuccess;

View file

@ -41,13 +41,13 @@ ColumnLayout {
onClicked: root.moveToWsExpanded = !root.moveToWsExpanded onClicked: root.moveToWsExpanded = !root.moveToWsExpanded
} }
NsIcon { MaterialIcon {
id: moveToWsIcon id: moveToWsIcon
anchors.centerIn: parent anchors.centerIn: parent
animate: true animate: true
icon: root.moveToWsExpanded ? "expand_more" : "keyboard_arrow_right" text: root.moveToWsExpanded ? "expand_more" : "keyboard_arrow_right"
color: Colours.palette.m3onPrimary color: Colours.palette.m3onPrimary
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.large
} }

View file

@ -135,11 +135,11 @@ ColumnLayout {
spacing: Tokens.spacing.medium spacing: Tokens.spacing.medium
NsIcon { MaterialIcon {
id: icon id: icon
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
icon: detail.icon text: detail.icon
} }
StyledText { StyledText {

View file

@ -40,9 +40,9 @@ Item {
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: 0 spacing: 0
NsIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
icon: "web_asset_off" text: "web_asset_off"
color: Colours.palette.m3outline color: Colours.palette.m3outline
fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).build() fontStyle: Tokens.font.icon.builders.extraLarge.scale(3).build()
} }

View file

@ -2,8 +2,8 @@ pragma Singleton
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
// NoSignal icon remap: Material Symbol name -> Nerd Font (JetBrainsMono NF) // NoSignal icon remap: Material Symbol name -> Nerd Font (JetBrainsMono NF)
// codepoint (Font Awesome + MDI ranges), via String.fromCodePoint so the source // codepoint (Font Awesome range), via String.fromCharCode so the source stays
// stays pure ASCII. Used by components/NsIcon. Covers bar/panel icons + the dynamic // pure ASCII. Used by components/NsIcon. Covers bar/panel icons + the dynamic
// Icons.getX() returns. get() falls back to a question glyph so anything // Icons.getX() returns. get() falls back to a question glyph so anything
// unmapped is visible (easy to spot + add a mapping). // unmapped is visible (easy to spot + add a mapping).
@ -14,9 +14,7 @@ Singleton {
id: root id: root
function cp(code: int): string { function cp(code: int): string {
// fromCodePoint (not fromCharCode) so astral-plane glyphs (Nerd Font return String.fromCharCode(code);
// MDI range, > 0xFFFF) emit correct surrogate pairs, not truncated.
return String.fromCodePoint(code);
} }
readonly property var map: { readonly property var map: {
@ -145,21 +143,16 @@ Singleton {
"warning": root.cp(0xf071), "warning": root.cp(0xf071),
"web_asset_off": root.cp(0xf2d0), "web_asset_off": root.cp(0xf2d0),
"wifi_find": root.cp(0xf1eb), "wifi_find": root.cp(0xf1eb),
// weather (Icons.getWeatherIcon) Material-weather family, every // weather (Icons.getWeatherIcon)
// codepoint verified present in JetBrainsMono Nerd Font Mono. The old "clear_day": root.cp(0xf185),
// Font-Awesome mapping had several glyphs absent from the font (rendered "clear_night": root.cp(0xf186),
// as "?" boxes) and was missing thunderstorm/snowing_heavy (F-D1). "partly_cloudy_day": root.cp(0xf6c4),
"clear_day": root.cp(0xf0599), "cloudy": root.cp(0xf0c2),
"clear_night": root.cp(0xf0594), "cloud": root.cp(0xf0c2),
"partly_cloudy_day": root.cp(0xf0595), "rainy": root.cp(0xf73d),
"cloudy": root.cp(0xf0590), "cloudy_snowing": root.cp(0xf2dc),
"cloud": root.cp(0xf0590), "foggy": root.cp(0xf75f),
"rainy": root.cp(0xf0597), "air": root.cp(0xf72e),
"cloudy_snowing": root.cp(0xf0598),
"snowing_heavy": root.cp(0xf0f37),
"thunderstorm": root.cp(0xf0593),
"foggy": root.cp(0xf0591),
"air": root.cp(0xf059d),
// apps / devices (Icons.get*) // apps / devices (Icons.get*)
"code": root.cp(0xf121), "code": root.cp(0xf121),
"forum": root.cp(0xf086), "forum": root.cp(0xf086),
@ -204,55 +197,7 @@ Singleton {
"update": root.cp(0xf021), "update": root.cp(0xf021),
"wallpaper": root.cp(0xf03e), "wallpaper": root.cp(0xf03e),
"workspaces": root.cp(0xf009), "workspaces": root.cp(0xf009),
"dock": root.cp(0xf2d1), "dock": root.cp(0xf2d1)
// lock screen
"login": root.cp(0xf090),
"key": root.cp(0xf084),
// dashboard / utilities / launcher leftovers
"account_tree": root.cp(0xf0e8),
"android": root.cp(0xf17b),
"category": root.cp(0xf02c),
"clear_all": root.cp(0xf2ed),
"compare": root.cp(0xf362),
"compare_arrows": root.cp(0xf362),
"contrast": root.cp(0xf042),
"delete_forever": root.cp(0xf1f8),
"filter_b_and_w": root.cp(0xf0b0),
"fullscreen": root.cp(0xf065),
"gamepad": root.cp(0xf11b),
"gradient": root.cp(0xf043),
"hard_disk": root.cp(0xf0a0),
"keep": root.cp(0xf08d),
"location_on": root.cp(0xf041),
"location_searching": root.cp(0xf05b),
"looks": root.cp(0xf53f),
"memory": root.cp(0xf2db),
"notifications_off": root.cp(0xf1f6),
"nutrition": root.cp(0xf787),
"page_header": root.cp(0xf036),
"picture_in_picture_center": root.cp(0xf2d0),
"resize": root.cp(0xf065),
"screenshot_region": root.cp(0xf247),
"select_to_speak": root.cp(0xf028),
"sentiment_calm": root.cp(0xf118),
"sentiment_very_dissatisfied": root.cp(0xf119),
"stop": root.cp(0xf04d),
"thermostat": root.cp(0xf2c9),
"water_drop": root.cp(0xf043),
"wb_twilight": root.cp(0xf185),
// additions-page icons (nexus Additional Software)
"brush": root.cp(0xf1fc), // fa-paintbrush
"cloud_sync": root.cp(0xf063f), // md-cloud_sync
"data_object": root.cp(0xf0169), // md-code_braces
"deployed_code": root.cp(0xf1b2), // fa-cube
"movie_edit": root.cp(0xf008), // fa-film
"neurology": root.cp(0xee9c), // fa-brain
"psychology": root.cp(0xf133c), // md-head_cog
"robot_2": root.cp(0xee0d), // fa-robot
"smart_toy": root.cp(0xf06a9), // md-robot
"sports_esports": root.cp(0xf11b), // fa-gamepad
"videocam": root.cp(0xf03d), // fa-video_camera
"vpn_lock": root.cp(0xf099d) // md-shield_lock
} }
function get(name: string): string { function get(name: string): string {

View file

@ -41,43 +41,15 @@ Singleton {
fetchCoordsFromCity(configLocation); fetchCoordsFromCity(configLocation);
} }
} else if (!loc || timer.elapsed() > 900) { } else if (!loc || timer.elapsed() > 900) {
fetchLocationFromIp(); Requests.get("https://ipinfo.io/json", text => {
}
}
// Auto-detect location from the public IP (used when weatherLocation is
// empty). Stock caelestia only queried ipinfo.io with no error handling;
// on the 2026-06-15 hardware test that call never populated `loc` (the
// city path works via the same Requests.get, so it is provider-specific
// finding F-W2). Repair: wrap parsing defensively and fall back to a second
// provider (geojs.io, which returns separate latitude/longitude fields) on
// any error or empty response.
function fetchLocationFromIp(): void {
const useGeoJs = () => {
Requests.get("https://get.geojs.io/v1/ip/geo.json", text => {
try {
const g = JSON.parse(text);
if (g.latitude && g.longitude) {
loc = g.latitude + "," + g.longitude;
city = g.city ?? "";
timer.restart();
}
} catch (e) {}
});
};
Requests.get("https://ipinfo.io/json", text => {
try {
const response = JSON.parse(text); const response = JSON.parse(text);
if (response.loc) { if (response.loc) {
loc = response.loc; loc = response.loc;
city = response.city ?? ""; city = response.city ?? "";
timer.restart(); timer.restart();
return;
} }
} catch (e) {} });
useGeoJs(); }
}, useGeoJs);
} }
function fetchCityFromCoords(coords: string): void { function fetchCityFromCoords(coords: string): void {
@ -159,10 +131,8 @@ Singleton {
for (let i = 0; i < json.daily.time.length; i++) for (let i = 0; i < json.daily.time.length; i++)
forecastList.push({ forecastList.push({
date: json.daily.time[i].replace(/-/g, "/"), date: json.daily.time[i].replace(/-/g, "/"),
maxTempC: Math.round(json.daily.temperature_2m_max[i]), maxTempC: json.daily.temperature_2m_max[i],
minTempC: Math.round(json.daily.temperature_2m_min[i]), minTempC: json.daily.temperature_2m_min[i],
maxTempF: Math.round(toFahrenheit(json.daily.temperature_2m_max[i])),
minTempF: Math.round(toFahrenheit(json.daily.temperature_2m_min[i])),
weatherCode: json.daily.weather_code[i], weatherCode: json.daily.weather_code[i],
icon: Icons.getWeatherIcon(json.daily.weather_code[i]) icon: Icons.getWeatherIcon(json.daily.weather_code[i])
}); });
@ -240,11 +210,6 @@ Singleton {
onLocChanged: fetchWeatherData() onLocChanged: fetchWeatherData()
// Stock caelestia only called reload() on a config CHANGE, never at startup,
// so a saved location blanked after a reboot and an empty (auto/IP) location
// never populated on a fresh boot (finding F-W1). Fetch once on load.
Component.onCompleted: reload()
Connections { Connections {
function onWeatherLocationChanged(): void { function onWeatherLocationChanged(): void {
root.reload(); root.reload();
@ -257,7 +222,7 @@ Singleton {
interval: 3600000 // 1 hour interval: 3600000 // 1 hour
running: true running: true
repeat: true repeat: true
onTriggered: reload() // re-detect an auto/IP location too, not just refetch a known one onTriggered: fetchWeatherData()
} }
ElapsedTimer { ElapsedTimer {