nosignal-shell/modules/nexus/pages/WallpaperAndStyle.qml
2026-06-05 01:01:43 +10:00

171 lines
4.8 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import Caelestia.Components
import Caelestia.Config
import qs.components
import qs.components.controls
import qs.components.images
import qs.services
import qs.modules.nexus
import qs.modules.nexus.common
ColumnLayout {
id: root
required property NexusState nState
readonly property int cappedWidth: Math.min(800, width)
spacing: Tokens.spacing.large
StyledText {
text: qsTr("Wallpaper & style")
font: Tokens.font.title.large
}
StyledClippingRect {
id: wallWrapper
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Tokens.spacing.extraLarge
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.palette.m3surfaceContainer
radius: Tokens.rounding.large
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
onClicked: ; // TODO
}
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: ; // TODO
}
}
ToggleRow {
Layout.alignment: Qt.AlignHCenter
implicitWidth: root.cappedWidth
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.alignment: Qt.AlignHCenter
implicitWidth: root.cappedWidth
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.alignment: Qt.AlignHCenter
implicitWidth: root.cappedWidth
last: true
text: qsTr("Dark theme")
checked: !Colours.light
onToggled: Colours.setMode(checked ? "dark" : "light")
}
Item {
Layout.fillHeight: true
}
}