Compare commits
10 commits
cf3c0d823d
...
44b257ce85
| Author | SHA1 | Date | |
|---|---|---|---|
| 44b257ce85 | |||
| 53c5833de0 | |||
| f21e5b5eaf | |||
| 83c6b62c13 | |||
| c4738ae974 | |||
| f6a2584d31 | |||
| dcce2440f6 | |||
| 16de3f16fe | |||
| 7c06b808ae | |||
| 83d5de1ba3 |
65 changed files with 766 additions and 407 deletions
BIN
assets/nosignal-logo.png
Normal file
BIN
assets/nosignal-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
|
|
@ -12,10 +12,10 @@ ColumnLayout {
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
animate: true
|
animate: true
|
||||||
text: root.icon
|
icon: 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ Rectangle {
|
||||||
|
|
||||||
implicitWidth: 38
|
implicitWidth: 38
|
||||||
implicitHeight: 22
|
implicitHeight: 22
|
||||||
radius: 11
|
radius: 0
|
||||||
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: 8
|
radius: 0
|
||||||
color: root.on ? Theme.onAccent : Theme.text
|
color: root.on ? Theme.onAccent : Theme.text
|
||||||
|
|
||||||
Behavior on x {
|
Behavior on x {
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "expand_more"
|
icon: "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
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,11 @@ RowLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: upIcon
|
id: upIcon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "keyboard_arrow_up"
|
icon: "keyboard_arrow_up"
|
||||||
color: Colours.palette.m3onPrimary
|
color: Colours.palette.m3onPrimary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,11 +145,11 @@ RowLayout {
|
||||||
onReleased: timer.stop()
|
onReleased: timer.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: downIcon
|
id: downIcon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "keyboard_arrow_down"
|
icon: "keyboard_arrow_down"
|
||||||
color: Colours.palette.m3onPrimary
|
color: Colours.palette.m3onPrimary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ Slider {
|
||||||
|
|
||||||
background: StyledRect {
|
background: StyledRect {
|
||||||
color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
|
color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
|
||||||
radius: Tokens.rounding.full
|
radius: 0
|
||||||
|
|
||||||
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: Tokens.rounding.full
|
radius: 0
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: handleInteraction
|
id: handleInteraction
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import qs.services
|
||||||
ButtonBase {
|
ButtonBase {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias icon: label.text
|
property alias icon: label.icon
|
||||||
readonly property alias label: label
|
readonly property alias label: label
|
||||||
|
|
||||||
font: Tokens.font.icon.medium
|
font: Tokens.font.icon.medium
|
||||||
|
|
@ -34,11 +34,10 @@ ButtonBase {
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import qs.services
|
||||||
ButtonBase {
|
ButtonBase {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias icon: iconLabel.text
|
property string icon
|
||||||
property alias text: label.text
|
property alias text: label.text
|
||||||
|
|
||||||
readonly property alias iconLabel: iconLabel
|
readonly property alias iconLabel: iconLabel
|
||||||
|
|
@ -44,9 +44,10 @@ ButtonBase {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Tokens.spacing.small
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -157,9 +157,9 @@ MouseArea {
|
||||||
anchors.margins: Tokens.padding.medium
|
anchors.margins: Tokens.padding.medium
|
||||||
spacing: Tokens.spacing.small
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
text: item.modelData?.icon ?? ""
|
icon: 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: MaterialIcon {
|
sourceComponent: NsIcon {
|
||||||
text: item.modelData.trailingIcon
|
icon: item.modelData.trailingIcon
|
||||||
color: item.active ? Colours.palette.m3onTertiaryContainer : Colours.palette.m3onSurfaceVariant
|
color: item.active ? Colours.palette.m3onTertiaryContainer : Colours.palette.m3onSurfaceVariant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: iconLabel
|
id: iconLabel
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
animate: true
|
animate: true
|
||||||
text: root.active?.activeIcon ?? root.fallbackIcon
|
icon: 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
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
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)
|
||||||
|
|
||||||
text: "expand_more"
|
icon: "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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,12 @@ StyledRect {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: toggleBtnIcon
|
id: toggleBtnIcon
|
||||||
|
|
||||||
visible: !!text
|
visible: !!text
|
||||||
fill: root.toggled ? 1 : 0
|
fill: root.toggled ? 1 : 0
|
||||||
text: root.icon
|
icon: 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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,11 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
||||||
grade: 200
|
grade: 200
|
||||||
text: image.status === Image.Error ? "broken_image" : "art_track"
|
icon: 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
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,9 @@ Scope {
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if (root.hasFullscreen)
|
if (root.hasFullscreen)
|
||||||
return;
|
return;
|
||||||
const visibilities = Visibilities.getForActive();
|
// NoSignal: drive the redesigned full-screen Power Menu (NsOverlay),
|
||||||
visibilities.session = !visibilities.session;
|
// not the old caelestia session panel (now dead code).
|
||||||
|
NsShell.toggle("power", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ Item {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.margins: Tokens.padding.large
|
anchors.margins: Tokens.padding.large
|
||||||
|
|
||||||
radius: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Flickable {
|
Flickable {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ GridLayout {
|
||||||
Layout.preferredWidth: Tokens.sizes.dashboard.userWidth
|
Layout.preferredWidth: Tokens.sizes.dashboard.userWidth
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.extraLarge * 1.5
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.extraLarge * 2
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
Media {
|
Media {
|
||||||
id: media
|
id: media
|
||||||
|
|
|
||||||
|
|
@ -102,11 +102,11 @@ Item {
|
||||||
CAnim {}
|
CAnim {}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "queue_music"
|
icon: "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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@ Item {
|
||||||
sourceComponent: ColumnLayout {
|
sourceComponent: ColumnLayout {
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "tune"
|
icon: "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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ Item {
|
||||||
implicitHeight: parent.implicitHeight * 2
|
implicitHeight: parent.implicitHeight * 2
|
||||||
|
|
||||||
color: Colours.palette.m3primary
|
color: Colours.palette.m3primary
|
||||||
radius: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
}
|
}
|
||||||
|
|
||||||
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: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.bottom: label.top
|
anchors.bottom: label.top
|
||||||
|
|
||||||
text: tab.iconName
|
icon: 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
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: bigInfoRow.implicitHeight + Tokens.padding.small
|
implicitHeight: bigInfoRow.implicitHeight + Tokens.padding.small
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge * 2
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
text: Weather.icon
|
icon: 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: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|
@ -180,9 +180,9 @@ Item {
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: forecastItem.modelData.icon
|
icon: 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: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: detailRoot.icon
|
icon: 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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: weatherStat.icon
|
icon: weatherStat.icon
|
||||||
fontStyle: Tokens.font.icon.extraLarge
|
fontStyle: Tokens.font.icon.extraLarge
|
||||||
color: weatherStat.colour
|
color: weatherStat.colour
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ CustomMouseArea {
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
color: Colours.palette.m3primary
|
color: Colours.palette.m3primary
|
||||||
radius: pressed ? Tokens.rounding.small : Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
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();
|
||||||
|
|
|
||||||
|
|
@ -65,10 +65,10 @@ Item {
|
||||||
Anim {}
|
Anim {}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: res.icon
|
icon: res.icon
|
||||||
font: Tokens.font.icon.large
|
fontStyle: Tokens.font.icon.large
|
||||||
color: res.fgColour
|
color: res.fgColour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@ Item {
|
||||||
|
|
||||||
Component.onCompleted: Weather.reload()
|
Component.onCompleted: Weather.reload()
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
||||||
animate: true
|
animate: true
|
||||||
text: Weather.icon
|
icon: 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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,8 @@ Item {
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
active: pfp.status !== Image.Ready
|
active: pfp.status !== Image.Ready
|
||||||
|
|
||||||
sourceComponent: MaterialIcon {
|
sourceComponent: NsIcon {
|
||||||
text: "person_add"
|
icon: "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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "person_edit"
|
icon: "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 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "clock_arrow_up"
|
icon: "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: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.palette.m3secondaryContainer
|
color: Colours.palette.m3secondaryContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ Item {
|
||||||
|
|
||||||
implicitWidth: 15
|
implicitWidth: 15
|
||||||
implicitHeight: 15
|
implicitHeight: 15
|
||||||
radius: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
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: Tokens.rounding.largeIncreased
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: wmIcon
|
id: wmIcon
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: "select_window"
|
icon: "select_window"
|
||||||
color: Colours.palette.m3onSecondaryContainer
|
color: Colours.palette.m3onSecondaryContainer
|
||||||
fontStyle: wmText.font
|
fontStyle: wmText.font
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
LoadingIndicator {
|
LoadingIndicator {
|
||||||
id: shape
|
id: shape
|
||||||
|
|
@ -212,9 +212,9 @@ Item {
|
||||||
sourceComponent: ColumnLayout {
|
sourceComponent: ColumnLayout {
|
||||||
spacing: Tokens.spacing.small
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "sentiment_sad"
|
icon: "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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ Item {
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
z: 1
|
z: 1
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.topMargin: Math.round(fontInfo.pointSize * 0.12)
|
Layout.topMargin: Math.round(fontInfo.pointSize * 0.12)
|
||||||
text: "lyrics"
|
icon: "lyrics"
|
||||||
fontStyle: Tokens.font.icon.medium
|
fontStyle: Tokens.font.icon.medium
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "more_vert"
|
icon: "more_vert"
|
||||||
fontStyle: Tokens.font.icon.medium
|
fontStyle: Tokens.font.icon.medium
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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: Tokens.rounding.extraSmall
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
Contents {
|
Contents {
|
||||||
|
|
@ -65,9 +65,9 @@ StyledClippingRect {
|
||||||
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.leftMargin: -Tokens.padding.extraSmall
|
Layout.leftMargin: -Tokens.padding.extraSmall
|
||||||
text: "battery_full"
|
icon: "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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "bolt"
|
icon: "bolt"
|
||||||
color: contents.accentColour
|
color: contents.accentColour
|
||||||
fontStyle: Tokens.font.icon.large
|
fontStyle: Tokens.font.icon.large
|
||||||
fill: 1
|
fill: 1
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ StyledRect {
|
||||||
required property real temperature
|
required property real temperature
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: root.icon
|
icon: 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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.topMargin: Math.round(fontInfo.pointSize * 0.08)
|
Layout.topMargin: Math.round(fontInfo.pointSize * 0.08)
|
||||||
text: root.temperature > 90 ? "thermometer_alert" : "thermometer"
|
icon: 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
|
||||||
|
|
|
||||||
|
|
@ -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: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "memory_alt"
|
icon: "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
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ StyledRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "swap_vert"
|
icon: "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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "download"
|
icon: "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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "upload"
|
icon: "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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "history"
|
icon: "history"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
fontStyle: Tokens.font.icon.medium
|
fontStyle: Tokens.font.icon.medium
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: Tokens.rounding.extraExtraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "hard_drive"
|
icon: "hard_drive"
|
||||||
color: root.accent
|
color: root.accent
|
||||||
fontStyle: Tokens.font.icon.medium
|
fontStyle: Tokens.font.icon.medium
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,9 @@ StyledWindow {
|
||||||
id: osdBg
|
id: osdBg
|
||||||
|
|
||||||
panel: panels.osdWrapper
|
panel: panels.osdWrapper
|
||||||
deformAmount: 0.25
|
deformAmount: 0 // NoSignal: square OSD (no organic blob deformation)
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
@ -207,6 +209,12 @@ 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 {
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ Item {
|
||||||
sessionPanel: sessionWrapper
|
sessionPanel: sessionWrapper
|
||||||
utilitiesPanel: utilities
|
utilitiesPanel: utilities
|
||||||
|
|
||||||
anchors.top: parent.top
|
y: 46 // NoSignal: drop the toasts below the 38px NsBar (+ gap)
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,14 +58,14 @@ Item {
|
||||||
|
|
||||||
implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
|
implicitHeight: Math.max(searchIcon.implicitHeight, search.implicitHeight, clearIcon.implicitHeight)
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
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
|
||||||
|
|
||||||
text: "search"
|
icon: "search"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: clearIcon
|
id: clearIcon
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
@ -163,7 +163,7 @@ Item {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
text: "close"
|
icon: "close"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,8 @@ Item {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: root.state === "wallpapers" ? "wallpaper_slideshow" : "manage_search"
|
icon: 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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: root.modelData?.icon ?? ""
|
icon: 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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: MaterialIcon {
|
sourceComponent: NsIcon {
|
||||||
text: "favorite"
|
icon: "favorite"
|
||||||
fill: 1
|
fill: 1
|
||||||
color: Colours.palette.m3primary
|
color: Colours.palette.m3primary
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ Item {
|
||||||
|
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: "function"
|
icon: "function"
|
||||||
fontStyle: Tokens.font.icon.extraLarge
|
fontStyle: Tokens.font.icon.extraLarge
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
@ -105,14 +105,14 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
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
|
||||||
|
|
||||||
text: "open_in_new"
|
icon: "open_in_new"
|
||||||
color: Colours.palette.m3onTertiary
|
color: Colours.palette.m3onTertiary
|
||||||
fontStyle: Tokens.font.icon.large
|
fontStyle: Tokens.font.icon.large
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,8 @@ Item {
|
||||||
|
|
||||||
active: `${root.modelData?.name} ${root.modelData?.flavour}` === Schemes.currentScheme
|
active: `${root.modelData?.name} ${root.modelData?.flavour}` === Schemes.currentScheme
|
||||||
|
|
||||||
sourceComponent: MaterialIcon {
|
sourceComponent: NsIcon {
|
||||||
text: "check"
|
icon: "check"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
fontStyle: Tokens.font.icon.large
|
fontStyle: Tokens.font.icon.large
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
text: root.modelData?.icon ?? ""
|
icon: 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: MaterialIcon {
|
sourceComponent: NsIcon {
|
||||||
text: "check"
|
icon: "check"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
fontStyle: Tokens.font.icon.large
|
fontStyle: Tokens.font.icon.large
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,9 @@ Item {
|
||||||
implicitWidth: Tokens.sizes.launcher.wallpaperWidth
|
implicitWidth: Tokens.sizes.launcher.wallpaperWidth
|
||||||
implicitHeight: implicitWidth / 16 * 9
|
implicitHeight: implicitWidth / 16 * 9
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "image"
|
icon: "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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,22 @@
|
||||||
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
|
||||||
|
|
@ -13,153 +24,26 @@ WlSessionLockSurface {
|
||||||
required property WlSessionLock lock
|
required property WlSessionLock lock
|
||||||
required property Pam pam
|
required property Pam pam
|
||||||
|
|
||||||
readonly property alias unlocking: unlockAnim.running
|
readonly property bool errored: root.pam.state === "error" || root.pam.state === "fail"
|
||||||
|
|
||||||
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 {
|
||||||
unlockAnim.start();
|
root.lock.locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
target: root.lock
|
target: root.lock
|
||||||
}
|
}
|
||||||
|
|
||||||
SequentialAnimation {
|
// ── Blurred wallpaper + scrim ──────────────────────────────────────────
|
||||||
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 {
|
||||||
|
|
@ -168,57 +52,265 @@ 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 {
|
||||||
id: lockContent
|
anchors.fill: parent
|
||||||
|
focus: true
|
||||||
|
Component.onCompleted: forceActiveFocus()
|
||||||
|
Keys.onPressed: event => root.pam.handleKey(event)
|
||||||
|
}
|
||||||
|
|
||||||
readonly property int size: lockIcon.implicitHeight + Tokens.padding.large * 4
|
// ── Top status row ─────────────────────────────────────────────────────
|
||||||
readonly property int radius: size / 4 * Tokens.rounding.scale
|
RowLayout {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 22
|
||||||
|
anchors.leftMargin: 28
|
||||||
|
anchors.rightMargin: 28
|
||||||
|
|
||||||
anchors.centerIn: parent
|
RowLayout {
|
||||||
implicitWidth: size
|
spacing: 7
|
||||||
implicitHeight: size
|
NsIcon {
|
||||||
|
icon: "lock"
|
||||||
rotation: 180
|
color: Theme.textMuted
|
||||||
scale: 0
|
size: 15
|
||||||
|
}
|
||||||
StyledRect {
|
StyledText {
|
||||||
id: lockBg
|
text: "Locked"
|
||||||
|
color: Theme.textMuted
|
||||||
anchors.fill: parent
|
font.family: Theme.font.family
|
||||||
color: Colours.palette.m3surface
|
font.pixelSize: Theme.font.bar
|
||||||
radius: parent.radius
|
|
||||||
opacity: Colours.transparency.enabled ? Colours.transparency.base : 1
|
|
||||||
|
|
||||||
layer.enabled: true
|
|
||||||
layer.effect: MultiEffect {
|
|
||||||
shadowEnabled: true
|
|
||||||
blurMax: 15
|
|
||||||
shadowColor: Qt.alpha(Colours.palette.m3shadow, 0.7)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
Item {
|
||||||
id: lockIcon
|
Layout.fillWidth: true
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "lock"
|
|
||||||
fontStyle: Tokens.font.icon.builders.extraLarge.scale(4).weight(Font.Bold).build()
|
|
||||||
rotation: 180
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Content {
|
RowLayout {
|
||||||
id: content
|
spacing: 14
|
||||||
|
|
||||||
anchors.centerIn: parent
|
NsIcon {
|
||||||
width: (root.screen?.height ?? 0) * Tokens.sizes.lock.heightMult * Tokens.sizes.lock.ratio - Tokens.padding.extraLargeIncreased
|
icon: Nmcli.active ? Icons.getNetworkIcon(Nmcli.active.strength ?? 0) : "wifi_off"
|
||||||
height: (root.screen?.height ?? 0) * Tokens.sizes.lock.heightMult - Tokens.padding.extraLargeIncreased
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock: root
|
// ── Centre block ───────────────────────────────────────────────────────
|
||||||
opacity: 0
|
ColumnLayout {
|
||||||
scale: 0
|
anchors.centerIn: parent
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: Time.format("hh:mm")
|
||||||
|
color: Theme.text
|
||||||
|
font.family: Theme.font.family
|
||||||
|
font.pixelSize: 108
|
||||||
|
font.weight: Font.ExtraLight
|
||||||
|
font.letterSpacing: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: Time.format("ddd, d MMMM yyyy")
|
||||||
|
color: Theme.textMuted
|
||||||
|
font.family: Theme.font.family
|
||||||
|
font.pixelSize: 15
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.topMargin: 64
|
||||||
|
implicitWidth: 74
|
||||||
|
implicitHeight: 74
|
||||||
|
radius: 0
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Vertical
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: Theme.accent
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: Theme.blue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NsIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
icon: "person"
|
||||||
|
color: Theme.onAccent
|
||||||
|
size: 34
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.topMargin: 14
|
||||||
|
text: SysInfo.user || "user"
|
||||||
|
color: Theme.text
|
||||||
|
font.family: Theme.font.family
|
||||||
|
font.pixelSize: 14
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
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.fill: parent
|
||||||
|
anchors.leftMargin: 14
|
||||||
|
anchors.rightMargin: 12
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
NsIcon {
|
||||||
|
icon: "key"
|
||||||
|
color: Theme.textMuted
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
73
modules/nexus/common/CachyRepoToggleRow.qml
Normal file
73
modules/nexus/common/CachyRepoToggleRow.qml
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
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
|
||||||
|
|
@ -61,22 +62,27 @@ PageBase {
|
||||||
width: parent.width - Tokens.padding.largeIncreased * 2
|
width: parent.width - Tokens.padding.largeIncreased * 2
|
||||||
spacing: Tokens.spacing.small
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
AnimatedLogo {
|
Image {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.preferredWidth: implicitWidth
|
Layout.preferredWidth: 104
|
||||||
Layout.preferredHeight: implicitHeight
|
Layout.preferredHeight: 104
|
||||||
|
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: "Caelestia"
|
text: "NoSignal"
|
||||||
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: CUtils.version ? `v${CUtils.version}` : "…"
|
text: "V1"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
font: Tokens.font.body.medium
|
font: Tokens.font.body.medium
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,41 +92,71 @@ PageBase {
|
||||||
text: qsTr("Weather")
|
text: qsTr("Weather")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder until the map-based location picker lands
|
// Location for the weather service. Weather.qml accepts a city name
|
||||||
|
// (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: comingSoon.implicitHeight + Tokens.padding.extraLarge * 2
|
implicitHeight: weatherLayout.implicitHeight + weatherLayout.anchors.margins * 2
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: comingSoon
|
id: weatherLayout
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.fill: parent
|
||||||
width: parent.width - Tokens.padding.largeIncreased * 2
|
anchors.margins: Tokens.padding.medium
|
||||||
spacing: Tokens.padding.extraSmall
|
anchors.leftMargin: Tokens.padding.largeIncreased
|
||||||
|
anchors.rightMargin: Tokens.padding.largeIncreased
|
||||||
NsIcon {
|
spacing: Tokens.spacing.small
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
icon: "map"
|
|
||||||
color: Colours.palette.m3outlineVariant
|
|
||||||
fontStyle: Tokens.font.icon.extraLarge
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.fillWidth: true
|
||||||
text: qsTr("Location picker coming soon")
|
text: qsTr("Location")
|
||||||
color: Colours.palette.m3outlineVariant
|
font: Tokens.font.body.small
|
||||||
font: Tokens.font.title.small
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: locField.implicitHeight + Tokens.padding.medium * 2
|
||||||
|
|
||||||
|
radius: Tokens.rounding.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("Choose your weather location on a map in a future update")
|
text: qsTr("Leave empty to detect your location automatically.")
|
||||||
color: Colours.palette.m3outlineVariant
|
color: Colours.palette.m3outline
|
||||||
font: Tokens.font.body.small
|
font: Tokens.font.label.small
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,11 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ Item {
|
||||||
anchors.rightMargin: root.clampedPadding
|
anchors.rightMargin: root.clampedPadding
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: Tokens.rounding.large
|
radius: 0
|
||||||
|
|
||||||
StyledListView {
|
StyledListView {
|
||||||
id: list
|
id: list
|
||||||
|
|
|
||||||
|
|
@ -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: Tokens.rounding.large
|
radius: 0
|
||||||
|
|
||||||
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: Tokens.rounding.full
|
radius: 0
|
||||||
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: Tokens.rounding.full
|
radius: 0
|
||||||
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: MaterialIcon {
|
sourceComponent: NsIcon {
|
||||||
text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
|
icon: 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: Tokens.rounding.full
|
radius: 0
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: expandIcon
|
id: expandIcon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.verticalCenterOffset: root.expanded ? -1 : 1
|
anchors.verticalCenterOffset: root.expanded ? -1 : 1
|
||||||
text: "expand_more"
|
icon: "expand_more"
|
||||||
fontStyle: Tokens.font.icon.medium
|
fontStyle: Tokens.font.icon.medium
|
||||||
rotation: root.expanded ? 180 : 0
|
rotation: root.expanded ? 180 : 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ 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
|
||||||
|
|
@ -139,10 +140,12 @@ Variants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// System tray
|
// System tray — only shown when an app actually registers a 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)
|
||||||
|
|
@ -164,7 +167,7 @@ Variants {
|
||||||
anchors.topMargin: 1
|
anchors.topMargin: 1
|
||||||
implicitWidth: 6
|
implicitWidth: 6
|
||||||
implicitHeight: 6
|
implicitHeight: 6
|
||||||
radius: 3
|
radius: 0
|
||||||
color: Theme.accent
|
color: Theme.accent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,13 +122,13 @@ NsPanel {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: 6
|
implicitHeight: 6
|
||||||
radius: 3
|
radius: 0
|
||||||
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: 3
|
radius: 0
|
||||||
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: 7
|
radius: 0
|
||||||
color: Theme.accent
|
color: Theme.accent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ NsPanel {
|
||||||
visible: parent.modelData > 0
|
visible: parent.modelData > 0
|
||||||
implicitWidth: 26
|
implicitWidth: 26
|
||||||
implicitHeight: 26
|
implicitHeight: 26
|
||||||
radius: 13
|
radius: 0
|
||||||
color: parent.today ? Theme.accent : "transparent"
|
color: parent.today ? Theme.accent : "transparent"
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ NsPanel {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
implicitWidth: 26
|
implicitWidth: 26
|
||||||
implicitHeight: 26
|
implicitHeight: 26
|
||||||
radius: 13
|
radius: 0
|
||||||
color: Notifs.dnd ? Theme.accentSoft : dndMa.containsMouse ? Theme.hover : "transparent"
|
color: Notifs.dnd ? Theme.accentSoft : dndMa.containsMouse ? Theme.hover : "transparent"
|
||||||
|
|
||||||
NsIcon {
|
NsIcon {
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ 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 / Airplane / VPN are stateful toggles for now.
|
// Brightness, Players). Night Light drives hyprsunset; Airplane drives the
|
||||||
|
// 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
|
||||||
|
|
@ -20,6 +23,35 @@ 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
|
||||||
|
|
@ -28,7 +60,7 @@ NsPanel {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
implicitWidth: 40
|
implicitWidth: 40
|
||||||
implicitHeight: 40
|
implicitHeight: 40
|
||||||
radius: 20
|
radius: 0
|
||||||
gradient: Gradient {
|
gradient: Gradient {
|
||||||
orientation: Gradient.Vertical
|
orientation: Gradient.Vertical
|
||||||
GradientStop {
|
GradientStop {
|
||||||
|
|
@ -75,7 +107,7 @@ NsPanel {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
implicitWidth: 34
|
implicitWidth: 34
|
||||||
implicitHeight: 34
|
implicitHeight: 34
|
||||||
radius: 17
|
radius: 0
|
||||||
color: pwrMa.containsMouse ? Theme.accentSoft : Theme.fillSubtle
|
color: pwrMa.containsMouse ? Theme.accentSoft : Theme.fillSubtle
|
||||||
|
|
||||||
NsIcon {
|
NsIcon {
|
||||||
|
|
@ -128,21 +160,31 @@ NsPanel {
|
||||||
icon: "nightlight"
|
icon: "nightlight"
|
||||||
label: "Night Light"
|
label: "Night Light"
|
||||||
sub: on ? "Warm 3500K" : "Off"
|
sub: on ? "Warm 3500K" : "Off"
|
||||||
onToggled: on = !on
|
on: root.nightLightOn
|
||||||
|
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"
|
||||||
sub: on ? "On" : "Off"
|
// Reflects the real radio state: airplane is "On" when both Wi-Fi and
|
||||||
onToggled: on = !on
|
// Bluetooth are down. Network.wifiEnabled tracks nmcli; the adapter
|
||||||
}
|
// tracks BlueZ, so the tile self-corrects if radios change elsewhere.
|
||||||
QSToggle {
|
readonly property bool radiosOff: !Network.wifiEnabled && !(Bluetooth.defaultAdapter?.enabled ?? false)
|
||||||
id: vpnTog
|
sub: radiosOff ? "On" : "Off"
|
||||||
icon: "vpn_key"
|
on: radiosOff
|
||||||
label: "VPN"
|
onToggled: {
|
||||||
sub: on ? "On" : "Off"
|
if (radiosOff)
|
||||||
onToggled: on = !on
|
Quickshell.execDetached(["sh", "-c", "nmcli radio all on; bluetoothctl power on"]);
|
||||||
|
else
|
||||||
|
Quickshell.execDetached(["sh", "-c", "nmcli radio all off; bluetoothctl power off"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,7 +306,7 @@ NsPanel {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
implicitWidth: 30
|
implicitWidth: 30
|
||||||
implicitHeight: 30
|
implicitHeight: 30
|
||||||
radius: 15
|
radius: 0
|
||||||
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 {
|
||||||
|
|
@ -319,13 +361,13 @@ NsPanel {
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: 6
|
implicitHeight: 6
|
||||||
radius: 3
|
radius: 0
|
||||||
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: 3
|
radius: 0
|
||||||
color: Theme.accent
|
color: Theme.accent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -334,7 +376,7 @@ NsPanel {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
implicitWidth: 14
|
implicitWidth: 14
|
||||||
implicitHeight: 14
|
implicitHeight: 14
|
||||||
radius: 7
|
radius: 0
|
||||||
color: Theme.accent
|
color: Theme.accent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -362,7 +404,7 @@ NsPanel {
|
||||||
|
|
||||||
implicitWidth: 28
|
implicitWidth: 28
|
||||||
implicitHeight: 28
|
implicitHeight: 28
|
||||||
radius: 14
|
radius: 0
|
||||||
color: mbm.containsMouse ? Theme.hover : "transparent"
|
color: mbm.containsMouse ? Theme.hover : "transparent"
|
||||||
|
|
||||||
NsIcon {
|
NsIcon {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,15 @@ 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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,9 +160,9 @@ Item {
|
||||||
Component {
|
Component {
|
||||||
id: iconBtn
|
id: iconBtn
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
animate: action.modelData.isCopy ?? false
|
animate: action.modelData.isCopy ?? false
|
||||||
text: action.modelData.isCopy ? "content_copy" : "close"
|
icon: action.modelData.isCopy ? "content_copy" : "close"
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,8 +110,8 @@ StyledRect {
|
||||||
Component {
|
Component {
|
||||||
id: materialIconComp
|
id: materialIconComp
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
text: Icons.getNotifIcon(root.activeNotifs[0]?.summary, root.urgency)
|
icon: 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
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.rightMargin: -Tokens.padding.extraSmall / 2
|
Layout.rightMargin: -Tokens.padding.extraSmall / 2
|
||||||
text: "expand_more"
|
icon: "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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "coffee"
|
icon: "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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.verticalCenterOffset: 1
|
anchors.verticalCenterOffset: 1
|
||||||
text: "screen_record"
|
icon: "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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ ColumnLayout {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
text: "list"
|
icon: "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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "scan_delete"
|
icon: "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
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "scan_delete"
|
icon: "scan_delete"
|
||||||
color: Colours.palette.m3outline
|
color: Colours.palette.m3outline
|
||||||
|
|
||||||
opacity: !root.props.recordingListExpanded ? 1 : 0
|
opacity: !root.props.recordingListExpanded ? 1 : 0
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,11 @@ StyledRect {
|
||||||
implicitWidth: implicitHeight
|
implicitWidth: implicitHeight
|
||||||
implicitHeight: icon.implicitHeight + Tokens.padding.large
|
implicitHeight: icon.implicitHeight + Tokens.padding.large
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: root.modelData.icon
|
icon: 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;
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,13 @@ ColumnLayout {
|
||||||
onClicked: root.moveToWsExpanded = !root.moveToWsExpanded
|
onClicked: root.moveToWsExpanded = !root.moveToWsExpanded
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: moveToWsIcon
|
id: moveToWsIcon
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
||||||
animate: true
|
animate: true
|
||||||
text: root.moveToWsExpanded ? "expand_more" : "keyboard_arrow_right"
|
icon: 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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,11 +135,11 @@ ColumnLayout {
|
||||||
|
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
id: icon
|
id: icon
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
text: detail.icon
|
icon: detail.icon
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ Item {
|
||||||
sourceComponent: ColumnLayout {
|
sourceComponent: ColumnLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
MaterialIcon {
|
NsIcon {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: "web_asset_off"
|
icon: "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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 range), via String.fromCharCode so the source stays
|
// codepoint (Font Awesome + MDI ranges), via String.fromCodePoint so the source
|
||||||
// pure ASCII. Used by components/NsIcon. Covers bar/panel icons + the dynamic
|
// stays 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,7 +14,9 @@ Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
function cp(code: int): string {
|
function cp(code: int): string {
|
||||||
return String.fromCharCode(code);
|
// fromCodePoint (not fromCharCode) so astral-plane glyphs (Nerd Font
|
||||||
|
// MDI range, > 0xFFFF) emit correct surrogate pairs, not truncated.
|
||||||
|
return String.fromCodePoint(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var map: {
|
readonly property var map: {
|
||||||
|
|
@ -143,16 +145,21 @@ 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)
|
// weather (Icons.getWeatherIcon) — Material-weather family, every
|
||||||
"clear_day": root.cp(0xf185),
|
// codepoint verified present in JetBrainsMono Nerd Font Mono. The old
|
||||||
"clear_night": root.cp(0xf186),
|
// Font-Awesome mapping had several glyphs absent from the font (rendered
|
||||||
"partly_cloudy_day": root.cp(0xf6c4),
|
// as "?" boxes) and was missing thunderstorm/snowing_heavy (F-D1).
|
||||||
"cloudy": root.cp(0xf0c2),
|
"clear_day": root.cp(0xf0599),
|
||||||
"cloud": root.cp(0xf0c2),
|
"clear_night": root.cp(0xf0594),
|
||||||
"rainy": root.cp(0xf73d),
|
"partly_cloudy_day": root.cp(0xf0595),
|
||||||
"cloudy_snowing": root.cp(0xf2dc),
|
"cloudy": root.cp(0xf0590),
|
||||||
"foggy": root.cp(0xf75f),
|
"cloud": root.cp(0xf0590),
|
||||||
"air": root.cp(0xf72e),
|
"rainy": root.cp(0xf0597),
|
||||||
|
"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),
|
||||||
|
|
@ -197,7 +204,55 @@ 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 {
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,43 @@ Singleton {
|
||||||
fetchCoordsFromCity(configLocation);
|
fetchCoordsFromCity(configLocation);
|
||||||
}
|
}
|
||||||
} else if (!loc || timer.elapsed() > 900) {
|
} else if (!loc || timer.elapsed() > 900) {
|
||||||
Requests.get("https://ipinfo.io/json", text => {
|
fetchLocationFromIp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
|
@ -131,8 +159,10 @@ 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: json.daily.temperature_2m_max[i],
|
maxTempC: Math.round(json.daily.temperature_2m_max[i]),
|
||||||
minTempC: json.daily.temperature_2m_min[i],
|
minTempC: Math.round(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])
|
||||||
});
|
});
|
||||||
|
|
@ -210,6 +240,11 @@ 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();
|
||||||
|
|
@ -222,7 +257,7 @@ Singleton {
|
||||||
interval: 3600000 // 1 hour
|
interval: 3600000 // 1 hour
|
||||||
running: true
|
running: true
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: fetchWeatherData()
|
onTriggered: reload() // re-detect an auto/IP location too, not just refetch a known one
|
||||||
}
|
}
|
||||||
|
|
||||||
ElapsedTimer {
|
ElapsedTimer {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue