feat: revamp dash user card

This commit is contained in:
2 * r + 2 * t 2026-04-22 23:18:52 +10:00
parent 3443b6fee3
commit a674b6836f
5 changed files with 181 additions and 153 deletions

View file

@ -71,3 +71,15 @@ if("shell" IN_LIST ENABLE_MODULES)
install(FILES LICENSE DESTINATION "${INSTALL_QSCONFDIR}") install(FILES LICENSE DESTINATION "${INSTALL_QSCONFDIR}")
endif() endif()
if("plugin" IN_LIST ENABLE_MODULES OR "shell" IN_LIST ENABLE_MODULES)
message(STATUS "Fetching M3Shapes module")
include(FetchContent)
FetchContent_Declare(
m3shapes_external
GIT_REPOSITORY https://github.com/soramanew/m3shapes.git
GIT_TAG main
)
FetchContent_MakeAvailable(m3shapes_external)
message(STATUS "Done fetching M3Shapes module")
endif()

View file

@ -18,8 +18,8 @@ GridLayout {
Rect { Rect {
Layout.column: 2 Layout.column: 2
Layout.columnSpan: 3 Layout.columnSpan: 3
Layout.preferredWidth: user.implicitWidth Layout.preferredWidth: Tokens.sizes.dashboard.userWidth
Layout.preferredHeight: user.implicitHeight Layout.fillHeight: true
radius: Tokens.rounding.extraLarge radius: Tokens.rounding.extraLarge
@ -35,11 +35,13 @@ GridLayout {
Layout.row: 0 Layout.row: 0
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth
Layout.fillHeight: true Layout.preferredHeight: weather.implicitHeight
radius: Tokens.rounding.extraLarge * 1.5 radius: Tokens.rounding.extraLarge * 1.5
SmallWeather {} SmallWeather {
id: weather
}
} }
Rect { Rect {

View file

@ -9,6 +9,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
implicitWidth: icon.implicitWidth + info.implicitWidth + info.anchors.leftMargin implicitWidth: icon.implicitWidth + info.implicitWidth + info.anchors.leftMargin
implicitHeight: Math.max(icon.implicitHeight, info.implicitHeight) + Tokens.padding.largeIncreased
Component.onCompleted: Weather.reload() Component.onCompleted: Weather.reload()

View file

@ -1,4 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts
import QtQuick.Effects
import M3Shapes
import Caelestia.Config import Caelestia.Config
import qs.components import qs.components
import qs.components.effects import qs.components.effects
@ -7,30 +10,37 @@ import qs.components.images
import qs.services import qs.services
import qs.utils import qs.utils
Row { Item {
id: root id: root
required property DrawerVisibilities visibilities required property DrawerVisibilities visibilities
required property FileDialog facePicker required property FileDialog facePicker
padding: Tokens.padding.large anchors.fill: parent
spacing: Tokens.spacing.medium anchors.margins: Tokens.padding.large
StyledClippingRect { Item {
implicitWidth: info.implicitHeight id: pfpContainer
implicitHeight: info.implicitHeight
radius: Tokens.rounding.extraLarge anchors.top: parent.top
color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2) anchors.bottom: parent.bottom
anchors.left: logoShape.right
anchors.topMargin: Tokens.padding.extraSmall
anchors.leftMargin: -Tokens.padding.extraLarge
implicitWidth: height
MaterialShape {
id: shape
MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
implicitSize: parent.height
shape: MaterialShape.Pill
color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
layer.enabled: true
text: "person" Behavior on color {
fill: 1 CAnim {}
grade: 200 }
fontStyle: Tokens.font.icon.size(Math.floor(info.implicitHeight / 2) || 1).build()
visible: pfp.status !== Image.Ready
} }
CachingImage { CachingImage {
@ -38,155 +48,156 @@ Row {
anchors.fill: parent anchors.fill: parent
path: `${Paths.home}/.face` path: `${Paths.home}/.face`
} layer.enabled: true
layer.effect: MultiEffect {
MouseArea { maskEnabled: true
anchors.fill: parent maskSource: shape
hoverEnabled: true maskThresholdMin: 0.5
maskSpreadAtMin: 1
StyledRect {
anchors.fill: parent
color: Qt.alpha(Colours.palette.m3scrim, 0.5)
opacity: parent.containsMouse ? 1 : 0
Behavior on opacity {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
} }
} }
} }
StyledRect { MaterialShape {
id: logoShape
x: Tokens.padding.extraSmall
implicitSize: Tokens.sizes.dashboard.logoSize + Tokens.padding.small * 2
shape: MaterialShape.Gem
color: Colours.palette.m3primaryContainer
Behavior on color {
CAnim {}
}
Loader {
anchors.centerIn: parent anchors.centerIn: parent
sourceComponent: SysInfo.isDefaultLogo ? caelestiaLogo : osLogo
implicitWidth: selectIcon.implicitHeight + Tokens.padding.small
implicitHeight: selectIcon.implicitHeight + Tokens.padding.small
radius: Tokens.rounding.large
color: Colours.palette.m3primary
scale: parent.containsMouse ? 1 : 0.5
opacity: parent.containsMouse ? 1 : 0
StateLayer {
color: Colours.palette.m3onPrimary
onClicked: {
root.visibilities.launcher = false;
root.facePicker.open();
} }
} }
MaterialIcon { Component {
id: selectIcon id: osLogo
anchors.centerIn: parent
anchors.horizontalCenterOffset: -font.pointSize * 0.02
text: "frame_person"
color: Colours.palette.m3onPrimary
fontStyle: Tokens.font.icon.extraLarge
}
Behavior on scale {
Anim {
type: Anim.FastSpatial
}
}
Behavior on opacity {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
}
}
}
}
}
Column {
id: info
anchors.verticalCenter: parent.verticalCenter
spacing: Tokens.spacing.medium
Item {
id: line
implicitWidth: icon.implicitWidth + text.width + text.anchors.leftMargin
implicitHeight: Math.max(icon.implicitHeight, text.implicitHeight)
ColouredIcon { ColouredIcon {
id: icon id: icon
anchors.left: parent.left
anchors.leftMargin: (Tokens.sizes.dashboard.infoIconSize - implicitWidth) / 2
source: SysInfo.osLogo source: SysInfo.osLogo
implicitSize: Math.floor(Tokens.font.body.medium.pointSize * 1.34) implicitSize: Tokens.sizes.dashboard.logoSize
colour: Colours.palette.m3primary colour: Colours.palette.m3onPrimaryContainer
}
StyledText {
id: text
anchors.verticalCenter: icon.verticalCenter
anchors.left: icon.right
anchors.leftMargin: icon.anchors.leftMargin
text: `: ${SysInfo.osPrettyName || SysInfo.osName}`
font: Tokens.font.body.medium
width: Tokens.sizes.dashboard.infoWidth
elide: Text.ElideRight
} }
} }
InfoLine { Component {
icon: "select_window_2" id: caelestiaLogo
text: SysInfo.wm
colour: Colours.palette.m3secondary
}
InfoLine { Logo {
id: uptime implicitWidth: Tokens.sizes.dashboard.logoSize
implicitHeight: Tokens.sizes.dashboard.logoSize
icon: "timer" topColour: Colours.palette.m3primary
text: qsTr("up %1").arg(SysInfo.uptime) bottomColour: Colours.palette.m3onPrimaryContainer
colour: Colours.palette.m3tertiary
} }
} }
component InfoLine: Item { MaterialShape {
id: line id: uptimeShape
required property string icon anchors.bottom: parent.bottom
required property string text anchors.left: pfpContainer.right
required property color colour anchors.leftMargin: -Tokens.padding.extraLargeIncreased
implicitSize: Tokens.sizes.dashboard.uptimeSize + Tokens.padding.small * 2
shape: MaterialShape.ClamShell
color: Colours.palette.m3tertiaryContainer
implicitWidth: icon.implicitWidth + text.width + text.anchors.leftMargin Behavior on color {
implicitHeight: Math.max(icon.implicitHeight, text.implicitHeight) CAnim {}
}
MaterialIcon { MaterialIcon {
id: icon anchors.centerIn: parent
text: "clock_arrow_up"
anchors.left: parent.left color: Colours.palette.m3onTertiaryContainer
anchors.leftMargin: (Tokens.sizes.dashboard.infoIconSize - implicitWidth) / 2
fill: 1
text: line.icon
color: line.colour
fontStyle: Tokens.font.icon.medium fontStyle: Tokens.font.icon.medium
} }
}
StyledText { StyledText {
id: text anchors.left: uptimeShape.right
anchors.verticalCenter: uptimeShape.verticalCenter
anchors.leftMargin: Tokens.spacing.small
anchors.verticalCenterOffset: Math.round(fontInfo.pointSize * 0.1)
anchors.verticalCenter: icon.verticalCenter text: "up " + SysInfo.uptime.split(",").slice(0, 2).join(",") // Max 2 components
anchors.left: icon.right font: Tokens.font.label.medium
anchors.leftMargin: icon.anchors.leftMargin width: Tokens.sizes.dashboard.userWidth - x - Tokens.padding.extraLarge
text: `: ${line.text}` elide: Text.ElideRight
font: Tokens.font.body.medium }
width: Tokens.sizes.dashboard.infoWidth StyledRect {
id: bubble1
anchors.left: pfpContainer.right
anchors.top: bubble2.bottom
anchors.leftMargin: Tokens.spacing.small
anchors.topMargin: -Tokens.spacing.extraSmall
implicitWidth: 10
implicitHeight: 10
radius: Tokens.rounding.full
color: Colours.palette.m3secondaryContainer
}
StyledRect {
id: bubble2
anchors.left: bubble1.right
anchors.verticalCenter: wmContainer.bottom
anchors.leftMargin: Tokens.spacing.extraSmall
implicitWidth: 15
implicitHeight: 15
radius: Tokens.rounding.full
color: Colours.palette.m3secondaryContainer
}
StyledRect {
id: wmContainer
anchors.left: bubble2.left
anchors.leftMargin: -Tokens.padding.medium
y: Tokens.padding.extraSmall
radius: Tokens.rounding.largeIncreased
color: Colours.palette.m3secondaryContainer
implicitWidth: wmLabel.implicitWidth + Tokens.padding.medium * 2
implicitHeight: wmLabel.implicitHeight + Tokens.padding.small * 2
Row {
id: wmLabel
anchors.centerIn: parent
spacing: Tokens.spacing.extraSmall
MaterialIcon {
id: wmIcon
anchors.verticalCenter: parent.verticalCenter
text: "select_window"
color: Colours.palette.m3onSecondaryContainer
fontStyle: wmText.font
}
StyledText {
id: wmText
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: Math.round(fontInfo.pointSize * 0.1)
text: SysInfo.wm + "..."
color: Colours.palette.m3onSecondaryContainer
font: Tokens.font.body.builders.small.vaxis("slnt", -4).build()
width: Math.min(implicitWidth, Tokens.sizes.dashboard.userWidth - wmContainer.x - Tokens.padding.medium * 2 - wmIcon.implicitWidth - wmLabel.spacing - Tokens.padding.extraLarge)
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
} }
}

View file

@ -177,8 +177,10 @@ class DashboardTokens : public ConfigObject {
CONFIG_PROPERTY(int, tabIndicatorHeight, 3) CONFIG_PROPERTY(int, tabIndicatorHeight, 3)
CONFIG_PROPERTY(int, tabIndicatorSpacing, 5) CONFIG_PROPERTY(int, tabIndicatorSpacing, 5)
CONFIG_PROPERTY(int, infoWidth, 200) CONFIG_PROPERTY(int, userWidth, 320)
CONFIG_PROPERTY(int, infoIconSize, 25) CONFIG_PROPERTY(int, logoSize, 30)
CONFIG_PROPERTY(int, uptimeSize, 30)
CONFIG_PROPERTY(int, bubbleSize, 8)
CONFIG_PROPERTY(int, dateTimeWidth, 110) CONFIG_PROPERTY(int, dateTimeWidth, 110)
CONFIG_PROPERTY(int, mediaWidth, 200) CONFIG_PROPERTY(int, mediaWidth, 200)
CONFIG_PROPERTY(int, mediaProgressSweep, 180) CONFIG_PROPERTY(int, mediaProgressSweep, 180)