nosignal-shell/modules/nexus/pages/WallpaperAndStyle.qml
28allday cf3c0d823d feat(nosignal): Nerd Font icon remap — nexus (Settings)
Convert caelestia's nexus Settings to Nerd Font icons (drop-in NsIcon).

- NsIcon hardened into a MaterialIcon drop-in: accepts fontStyle (sizes from
  it, keeps the NF Mono family), plus no-op fill/grade/animate for API parity.
- Glyphs map extended with caelestia core names: nexus static icons, nav/page
  icons (palette, wallpaper, dashboard, devices_other, extension, globe, info,
  monitor, shuffle, workspaces, ...), weather + app/device icons.
- Converted all MaterialIcon in modules/nexus/ to NsIcon; fixed icon aliases
  (NavRow/SliderRow .text -> .icon); reverted IconButton font: (it has font,
  not fontStyle, and renders its own icon).

Remaining core surfaces still Material Symbols (no breakage): launcher, osd,
lock, sidebar, utilities — to convert next with any further Glyphs entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 11:16:01 +01:00

202 lines
6.5 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Caelestia.Components
import Caelestia.Config
import qs.components
import qs.components.controls
import qs.components.images
import qs.services
import qs.modules.nexus.common
PageBase {
id: root
title: qsTr("Wallpaper & style")
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: root.cappedWidth
spacing: Tokens.spacing.large
StyledClippingRect {
id: wallWrapper
Layout.alignment: Qt.AlignHCenter
implicitWidth: {
const screen = root.nState.screen;
return implicitHeight / screen.height * screen.width;
}
implicitHeight: {
const screen = root.nState.screen;
const cWidth = root.cappedWidth;
return Math.min(Math.round(cWidth * 0.4), cWidth / screen.width * screen.height);
}
color: Colours.tPalette.m3surfaceContainer
radius: Tokens.rounding.large
Loader {
anchors.centerIn: parent
opacity: Config.background.wallpaperEnabled ? 0 : 1
active: opacity > 0
sourceComponent: ColumnLayout {
spacing: Tokens.spacing.extraSmall
NsIcon {
Layout.alignment: Qt.AlignHCenter
icon: "hide_image"
color: Colours.palette.m3onSurfaceVariant
fontStyle: Tokens.font.icon.extraLarge
}
StyledText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Wallpaper disabled")
color: Colours.palette.m3onSurfaceVariant
font: Tokens.font.body.large
}
}
Behavior on opacity {
Anim {
type: Anim.SlowEffects
}
}
}
Item {
anchors.fill: parent
opacity: Config.background.wallpaperEnabled ? 1 : 0
Behavior on opacity {
Anim {
type: Anim.SlowEffects
}
}
Loader {
id: wallIndicatorLoader
anchors.centerIn: parent
opacity: 0
active: opacity > 0
sourceComponent: StyledRect {
implicitWidth: wallLoadingIndicator.implicitSize + Tokens.padding.largeIncreased * 2
implicitHeight: wallLoadingIndicator.implicitSize + Tokens.padding.largeIncreased * 2
color: Colours.palette.m3primaryContainer
radius: Tokens.rounding.full
LoadingIndicator {
id: wallLoadingIndicator
anchors.centerIn: parent
containsIcon: true
implicitSize: Math.min(wallWrapper.implicitWidth, wallWrapper.implicitHeight) * 0.4
}
}
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
Timer {
id: wallLoadDebounceTimer
interval: 100
onTriggered: {
if (wallImg.status !== Image.Ready)
wallIndicatorLoader.opacity = 1;
}
}
FadeImage {
id: wallImg
anchors.fill: parent
source: Wallpapers.current
preventInit: wallIndicatorLoader.opacity > 0
fadeOutAnim: Anim.DefaultEffects
fadeInAnim: Anim.SlowEffects
onSourceChanged: wallLoadDebounceTimer.restart()
onStatusChanged: {
if (status === Image.Ready) {
wallLoadDebounceTimer.stop();
wallIndicatorLoader.opacity = 0;
}
}
}
}
}
ButtonRow {
Layout.alignment: Qt.AlignHCenter
spacing: Tokens.spacing.small
IconTextButton {
icon: "wallpaper"
text: qsTr("Wallpapers")
font: Tokens.font.body.large
isRound: true
shapeMorph: true
type: IconTextButton.Tonal
horizontalPadding: Tokens.padding.extraLarge
verticalPadding: Tokens.padding.medium
disabled: !Config.background.wallpaperEnabled
onClicked: root.nState.openSubPage(1) // Wallpaper page
}
IconTextButton {
icon: "palette"
text: qsTr("Colours")
font: Tokens.font.body.large
isRound: true
shapeMorph: true
type: IconTextButton.Tonal
horizontalPadding: Tokens.padding.extraLarge
verticalPadding: Tokens.padding.medium
onClicked: root.nState.openSubPage(3) // Colours page
}
}
ToggleRow {
Layout.fillWidth: true
first: true
text: qsTr("Display wallpaper")
checked: Config.background.wallpaperEnabled
onToggled: GlobalConfig.background.wallpaperEnabled = checked
}
ToggleRow {
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
Layout.fillWidth: true
text: qsTr("Transparency")
subtext: qsTr("Base %1, layers %2").arg(Colours.transparency.base).arg(Colours.transparency.layers)
checked: Colours.transparency.enabled
onToggled: GlobalConfig.appearance.transparency.enabled = checked
}
ToggleRow {
Layout.topMargin: Tokens.spacing.extraSmall / 2 - parent.spacing
Layout.fillWidth: true
last: true
text: qsTr("Dark theme")
checked: !Colours.light
onToggled: Colours.setMode(checked ? "dark" : "light")
}
}
}