internal: clean up old lock files
This commit is contained in:
parent
019f8b9570
commit
1665228cd9
7 changed files with 0 additions and 1614 deletions
|
|
@ -1,480 +0,0 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.components
|
||||
import qs.services
|
||||
import qs.config
|
||||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
import QtQuick.Effects
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property bool locked
|
||||
required property real weatherWidth
|
||||
required property real buttonsWidth
|
||||
required property real buttonsHeight
|
||||
required property real statusWidth
|
||||
required property real statusHeight
|
||||
required property bool isNormal
|
||||
required property bool isLarge
|
||||
|
||||
readonly property real clockBottom: innerMask.anchors.margins + clockPath.height
|
||||
readonly property real inputTop: innerMask.anchors.margins + inputPath.height
|
||||
readonly property real weatherTop: innerMask.anchors.margins + weatherPath.height
|
||||
readonly property real weatherRight: innerMask.anchors.margins + weatherPath.width
|
||||
readonly property real buttonsTop: innerMask.anchors.margins + buttonsPath.height
|
||||
readonly property real buttonsLeft: innerMask.anchors.margins + buttonsPath.width
|
||||
readonly property real statusBottom: innerMask.anchors.margins + statusPath.height
|
||||
readonly property real statusLeft: innerMask.anchors.margins + statusPath.width
|
||||
|
||||
readonly property real mediaX: innerMask.anchors.margins + mediaPath.width
|
||||
readonly property real mediaY: innerMask.anchors.margins + mediaPath.height
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
StyledRect {
|
||||
id: base
|
||||
|
||||
anchors.fill: parent
|
||||
color: Colours.tPalette.m3surface
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskSource: mask
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mask
|
||||
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
visible: false
|
||||
|
||||
Rectangle {
|
||||
id: innerMask
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.locked ? Config.lock.sizes.border : -radius / 2
|
||||
radius: Appearance.rounding.large * 2
|
||||
|
||||
Behavior on anchors.margins {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Math.floor(innerMask.anchors.margins)
|
||||
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
|
||||
ShapePath {
|
||||
id: clockPath
|
||||
|
||||
readonly property int width: Config.lock.sizes.clockWidth
|
||||
property real height: root.locked ? Config.lock.sizes.clockHeight : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 4
|
||||
readonly property bool flatten: height < rounding * 2
|
||||
readonly property real roundingY: flatten ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: Colours.tPalette.m3surface
|
||||
|
||||
startX: (innerMask.width - width) / 2 - rounding
|
||||
|
||||
PathArc {
|
||||
relativeX: clockPath.rounding
|
||||
relativeY: clockPath.roundingY
|
||||
radiusX: clockPath.rounding
|
||||
radiusY: Math.min(clockPath.rounding, clockPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: clockPath.height - clockPath.roundingY * 2
|
||||
}
|
||||
PathArc {
|
||||
relativeX: clockPath.rounding
|
||||
relativeY: clockPath.roundingY
|
||||
radiusX: clockPath.rounding
|
||||
radiusY: Math.min(clockPath.rounding, clockPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: clockPath.width - clockPath.rounding * 2
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: clockPath.rounding
|
||||
relativeY: -clockPath.roundingY
|
||||
radiusX: clockPath.rounding
|
||||
radiusY: Math.min(clockPath.rounding, clockPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: -(clockPath.height - clockPath.roundingY * 2)
|
||||
}
|
||||
PathArc {
|
||||
relativeX: clockPath.rounding
|
||||
relativeY: -clockPath.roundingY
|
||||
radiusX: clockPath.rounding
|
||||
radiusY: Math.min(clockPath.rounding, clockPath.height)
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
id: inputPath
|
||||
|
||||
readonly property int width: Config.lock.sizes.inputWidth
|
||||
property real height: root.locked ? Config.lock.sizes.inputHeight : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 2
|
||||
readonly property bool flatten: height < rounding * 2
|
||||
readonly property real roundingY: flatten ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: Colours.tPalette.m3surface
|
||||
|
||||
startX: (innerMask.width - width) / 2 - rounding
|
||||
startY: Math.ceil(innerMask.height)
|
||||
|
||||
PathArc {
|
||||
relativeX: inputPath.rounding
|
||||
relativeY: -inputPath.roundingY
|
||||
radiusX: inputPath.rounding
|
||||
radiusY: Math.min(inputPath.rounding, inputPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: -(inputPath.height - inputPath.roundingY * 2)
|
||||
}
|
||||
PathArc {
|
||||
relativeX: inputPath.rounding
|
||||
relativeY: -inputPath.roundingY
|
||||
radiusX: inputPath.rounding
|
||||
radiusY: Math.min(inputPath.rounding, inputPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: inputPath.width - inputPath.rounding * 2
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: inputPath.rounding
|
||||
relativeY: inputPath.roundingY
|
||||
radiusX: inputPath.rounding
|
||||
radiusY: Math.min(inputPath.rounding, inputPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: inputPath.height - inputPath.roundingY * 2
|
||||
}
|
||||
PathArc {
|
||||
relativeX: inputPath.rounding
|
||||
relativeY: inputPath.roundingY
|
||||
radiusX: inputPath.rounding
|
||||
radiusY: Math.min(inputPath.rounding, inputPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
id: weatherPath
|
||||
|
||||
property int width: root.locked ? root.weatherWidth - Config.lock.sizes.border / 4 : 0
|
||||
property real height: root.locked ? Config.lock.sizes.weatherHeight : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 2
|
||||
readonly property real roundingX: width < rounding * 2 ? width / 2 : rounding
|
||||
readonly property real roundingY: height < rounding * 2 ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: Colours.tPalette.m3surface
|
||||
|
||||
startY: Math.ceil(innerMask.height) - height - roundingY
|
||||
|
||||
PathArc {
|
||||
relativeX: weatherPath.roundingX
|
||||
relativeY: weatherPath.roundingY
|
||||
radiusX: Math.min(weatherPath.rounding, weatherPath.width)
|
||||
radiusY: Math.min(weatherPath.rounding, weatherPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: weatherPath.width - weatherPath.roundingX * 2
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: weatherPath.roundingX
|
||||
relativeY: weatherPath.roundingY
|
||||
radiusX: Math.min(weatherPath.rounding, weatherPath.width)
|
||||
radiusY: Math.min(weatherPath.rounding, weatherPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: weatherPath.height - weatherPath.roundingY * 2
|
||||
}
|
||||
PathArc {
|
||||
relativeX: weatherPath.roundingX
|
||||
relativeY: weatherPath.roundingY
|
||||
radiusX: Math.min(weatherPath.rounding, weatherPath.width)
|
||||
radiusY: Math.min(weatherPath.rounding, weatherPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: -weatherPath.width - weatherPath.roundingX
|
||||
relativeY: 0
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
id: mediaPath
|
||||
|
||||
property int width: root.locked ? (root.isLarge ? Config.lock.sizes.mediaWidth : Config.lock.sizes.mediaWidthSmall) - Config.lock.sizes.border / 4 : 0
|
||||
property real height: root.locked ? (root.isLarge ? Config.lock.sizes.mediaHeight : Config.lock.sizes.mediaHeightSmall) : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 2
|
||||
readonly property real roundingX: width < rounding * 2 ? width / 2 : rounding
|
||||
readonly property real roundingY: height < rounding * 2 ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: root.isNormal ? Colours.tPalette.m3surface : "transparent"
|
||||
|
||||
startX: root.isLarge ? 0 : Math.ceil(innerMask.width)
|
||||
startY: root.isLarge ? height + roundingY : Math.ceil(innerMask.height) - height - roundingY
|
||||
|
||||
PathArc {
|
||||
relativeX: mediaPath.roundingX * (root.isLarge ? 1 : -1)
|
||||
relativeY: mediaPath.roundingY * (root.isLarge ? -1 : 1)
|
||||
radiusX: Math.min(mediaPath.rounding, mediaPath.width)
|
||||
radiusY: Math.min(mediaPath.rounding, mediaPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: (mediaPath.width - mediaPath.roundingX * 2) * (root.isLarge ? 1 : -1)
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: mediaPath.roundingX * (root.isLarge ? 1 : -1)
|
||||
relativeY: mediaPath.roundingY * (root.isLarge ? -1 : 1)
|
||||
radiusX: Math.min(mediaPath.rounding, mediaPath.width)
|
||||
radiusY: Math.min(mediaPath.rounding, mediaPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: (mediaPath.height - mediaPath.roundingY * 2) * (root.isLarge ? -1 : 1)
|
||||
}
|
||||
PathArc {
|
||||
relativeX: mediaPath.roundingX * (root.isLarge ? 1 : -1)
|
||||
relativeY: mediaPath.roundingY * (root.isLarge ? -1 : 1)
|
||||
radiusX: Math.min(mediaPath.rounding, mediaPath.width)
|
||||
radiusY: Math.min(mediaPath.rounding, mediaPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: (-mediaPath.width - mediaPath.roundingX) * (root.isLarge ? 1 : -1)
|
||||
relativeY: 0
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
id: buttonsPath
|
||||
|
||||
property int width: root.locked ? root.buttonsWidth - Config.lock.sizes.border / 4 : 0
|
||||
property real height: root.locked ? root.buttonsHeight - Config.lock.sizes.border / 4 : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 2
|
||||
readonly property real roundingX: width < rounding * 2 ? width / 2 : rounding
|
||||
readonly property real roundingY: height < rounding * 2 ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: root.isLarge ? Colours.tPalette.m3surface : "transparent"
|
||||
|
||||
startX: Math.ceil(innerMask.width)
|
||||
startY: Math.ceil(innerMask.height) - height - rounding
|
||||
|
||||
PathArc {
|
||||
relativeX: -buttonsPath.roundingX
|
||||
relativeY: buttonsPath.rounding
|
||||
radiusX: Math.min(buttonsPath.rounding, buttonsPath.width)
|
||||
radiusY: buttonsPath.rounding, buttonsPath.height
|
||||
}
|
||||
PathLine {
|
||||
relativeX: -(buttonsPath.width - buttonsPath.roundingX * 2)
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: -buttonsPath.roundingX
|
||||
relativeY: buttonsPath.roundingY
|
||||
radiusX: Math.min(buttonsPath.rounding, buttonsPath.width)
|
||||
radiusY: Math.min(buttonsPath.rounding, buttonsPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: buttonsPath.height - buttonsPath.roundingY * 2
|
||||
}
|
||||
PathArc {
|
||||
relativeX: -buttonsPath.roundingX
|
||||
relativeY: buttonsPath.roundingY
|
||||
radiusX: Math.min(buttonsPath.rounding, buttonsPath.width)
|
||||
radiusY: Math.min(buttonsPath.rounding, buttonsPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: buttonsPath.width + buttonsPath.roundingX
|
||||
relativeY: 0
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
id: statusPath
|
||||
|
||||
property int width: root.locked ? root.statusWidth - Config.lock.sizes.border / 4 : 0
|
||||
property real height: root.locked ? root.statusHeight - Config.lock.sizes.border / 4 : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 2
|
||||
readonly property real roundingX: width < rounding * 2 ? width / 2 : rounding
|
||||
readonly property real roundingY: height < rounding * 2 ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: root.isLarge ? Colours.tPalette.m3surface : "transparent"
|
||||
|
||||
startX: Math.ceil(innerMask.width)
|
||||
startY: height + rounding
|
||||
|
||||
PathArc {
|
||||
relativeX: -statusPath.roundingX
|
||||
relativeY: -statusPath.rounding
|
||||
radiusX: Math.min(statusPath.rounding, statusPath.width)
|
||||
radiusY: statusPath.rounding
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: -(statusPath.width - statusPath.roundingX * 2)
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: -statusPath.roundingX
|
||||
relativeY: -statusPath.roundingY
|
||||
radiusX: Math.min(statusPath.rounding, statusPath.width)
|
||||
radiusY: Math.min(statusPath.rounding, statusPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: -(statusPath.height - statusPath.roundingY * 2)
|
||||
}
|
||||
PathArc {
|
||||
relativeX: -statusPath.roundingX
|
||||
relativeY: -statusPath.roundingY
|
||||
radiusX: Math.min(statusPath.rounding, statusPath.width)
|
||||
radiusY: Math.min(statusPath.rounding, statusPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: statusPath.width + statusPath.roundingX
|
||||
relativeY: 0
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.components
|
||||
import qs.services
|
||||
import qs.config
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
readonly property real nonAnimMargin: handler.hovered ? Appearance.padding.large * 1.5 : Appearance.padding.large
|
||||
readonly property real nonAnimWidth: handler.hovered ? Config.lock.sizes.buttonsWidth : Config.lock.sizes.buttonsWidthSmall
|
||||
readonly property real nonAnimHeight: (nonAnimWidth + nonAnimMargin * 2) / 4
|
||||
|
||||
implicitWidth: nonAnimWidth
|
||||
implicitHeight: nonAnimHeight
|
||||
|
||||
Behavior on implicitWidth {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on implicitHeight {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: handler
|
||||
|
||||
target: parent
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.nonAnimMargin
|
||||
anchors.rightMargin: 0
|
||||
anchors.bottomMargin: 0
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
SessionButton {
|
||||
icon: "logout"
|
||||
command: Config.session.commands.logout
|
||||
}
|
||||
|
||||
SessionButton {
|
||||
icon: "power_settings_new"
|
||||
command: Config.session.commands.shutdown
|
||||
}
|
||||
|
||||
SessionButton {
|
||||
icon: "downloading"
|
||||
command: Config.session.commands.hibernate
|
||||
}
|
||||
|
||||
SessionButton {
|
||||
icon: "cached"
|
||||
command: Config.session.commands.reboot
|
||||
}
|
||||
|
||||
Behavior on anchors.margins {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component SessionButton: StyledRect {
|
||||
required property string icon
|
||||
required property list<string> command
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: width
|
||||
|
||||
radius: Appearance.rounding.large * 1.2
|
||||
color: Colours.palette.m3secondaryContainer
|
||||
|
||||
StateLayer {
|
||||
id: stateLayer
|
||||
|
||||
color: Colours.palette.m3onSecondaryContainer
|
||||
|
||||
function onClicked(): void {
|
||||
Quickshell.execDetached(parent.command);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
anchors.centerIn: parent
|
||||
|
||||
text: parent.icon
|
||||
color: Colours.palette.m3onSecondaryContainer
|
||||
font.pointSize: (parent.width * 0.4) || 1
|
||||
font.weight: handler.hovered ? 500 : 400
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.components
|
||||
import qs.services
|
||||
import qs.config
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
spacing: 0
|
||||
|
||||
readonly property list<string> timeComponents: Time.format(Config.services.useTwelveHourClock ? "hh:mm:A" : "hh:mm").split(":")
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: Appearance.spacing.small
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: root.timeComponents[0]
|
||||
color: Colours.palette.m3secondary
|
||||
font.pointSize: Appearance.font.size.extraLarge * 4
|
||||
font.family: Appearance.font.family.mono
|
||||
font.weight: 800
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: ":"
|
||||
color: Colours.palette.m3primary
|
||||
font.pointSize: Appearance.font.size.extraLarge * 4
|
||||
font.family: Appearance.font.family.mono
|
||||
font.weight: 800
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: root.timeComponents[1]
|
||||
color: Colours.palette.m3secondary
|
||||
font.pointSize: Appearance.font.size.extraLarge * 4
|
||||
font.family: Appearance.font.family.mono
|
||||
font.weight: 800
|
||||
}
|
||||
|
||||
Loader {
|
||||
Layout.leftMargin: Appearance.spacing.normal
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
asynchronous: true
|
||||
active: Config.services.useTwelveHourClock
|
||||
visible: active
|
||||
|
||||
sourceComponent: StyledText {
|
||||
text: root.timeComponents[2] ?? ""
|
||||
color: Colours.palette.m3primary
|
||||
font.pointSize: Appearance.font.size.extraLarge * 3
|
||||
font.weight: 700
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: Appearance.padding.large * 3
|
||||
|
||||
text: Time.format("dddd, d MMMM yyyy")
|
||||
color: Colours.palette.m3tertiary
|
||||
font.pointSize: Appearance.font.size.extraLarge
|
||||
font.family: Appearance.font.family.mono
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
import qs.components
|
||||
import qs.components.images
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.utils
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Services.Pam
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
required property var lock
|
||||
|
||||
property string passwordBuffer
|
||||
|
||||
Layout.preferredWidth: Config.lock.sizes.faceSize * 2
|
||||
Layout.fillWidth: false
|
||||
spacing: Appearance.spacing.large * 2
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: user.implicitHeight + Appearance.padding.small * 2
|
||||
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
radius: Appearance.rounding.small
|
||||
|
||||
RowLayout {
|
||||
id: user
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
MaterialIcon {
|
||||
text: "account_circle"
|
||||
font.pointSize: Appearance.font.size.large * 1.4
|
||||
font.weight: 500
|
||||
}
|
||||
|
||||
StyledText {
|
||||
// Layout.fillWidth: true
|
||||
text: Quickshell.env("USER")
|
||||
font.pointSize: Appearance.font.size.large
|
||||
// font.capitalization: Font.Capitalize
|
||||
font.weight: 500
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: charList.implicitWidth + Appearance.padding.large * 2
|
||||
Layout.preferredHeight: Appearance.font.size.normal + Appearance.padding.large * 2
|
||||
|
||||
focus: true
|
||||
color: Colours.tPalette.m3surfaceContainer
|
||||
radius: Appearance.rounding.small
|
||||
clip: true
|
||||
|
||||
onFocusChanged: {
|
||||
if (!focus)
|
||||
focus = true;
|
||||
}
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (pam.active)
|
||||
return;
|
||||
|
||||
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
|
||||
placeholder.animate = false;
|
||||
pam.start();
|
||||
} else if (event.key === Qt.Key_Backspace) {
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
charList.implicitWidth = charList.implicitWidth; // Break binding
|
||||
root.passwordBuffer = "";
|
||||
} else {
|
||||
root.passwordBuffer = root.passwordBuffer.slice(0, -1);
|
||||
}
|
||||
} else if (" abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?".includes(event.text.toLowerCase())) {
|
||||
charList.bindImWidth();
|
||||
root.passwordBuffer += event.text;
|
||||
}
|
||||
}
|
||||
|
||||
PamContext {
|
||||
id: pam
|
||||
|
||||
onResponseRequiredChanged: {
|
||||
if (!responseRequired)
|
||||
return;
|
||||
|
||||
respond(root.passwordBuffer);
|
||||
charList.implicitWidth = charList.implicitWidth; // Break binding
|
||||
root.passwordBuffer = "";
|
||||
placeholder.animate = true;
|
||||
}
|
||||
|
||||
onCompleted: res => {
|
||||
if (res === PamResult.Success)
|
||||
return root.lock.lock.unlock();
|
||||
|
||||
if (res === PamResult.Error)
|
||||
placeholder.pamState = "error";
|
||||
else if (res === PamResult.MaxTries)
|
||||
placeholder.pamState = "max";
|
||||
else if (res === PamResult.Failed)
|
||||
placeholder.pamState = "fail";
|
||||
|
||||
placeholderDelay.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: placeholderDelay
|
||||
|
||||
interval: 3000
|
||||
onTriggered: placeholder.pamState = ""
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: placeholder
|
||||
|
||||
property string pamState
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
text: {
|
||||
if (pam.active)
|
||||
return qsTr("Loading...");
|
||||
if (pamState === "error")
|
||||
return qsTr("An error occured");
|
||||
if (pamState === "max")
|
||||
return qsTr("You have reached the maximum number of tries");
|
||||
if (pamState === "fail")
|
||||
return qsTr("Incorrect password");
|
||||
return qsTr("Enter your password");
|
||||
}
|
||||
|
||||
animate: true
|
||||
color: pam.active ? Colours.palette.m3secondary : pamState ? Colours.palette.m3error : Colours.palette.m3outline
|
||||
font.pointSize: Appearance.font.size.larger
|
||||
|
||||
opacity: root.passwordBuffer ? 0 : 1
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: charList
|
||||
|
||||
function bindImWidth(): void {
|
||||
imWidthBehavior.enabled = false;
|
||||
implicitWidth = Qt.binding(() => Math.min(count * (Appearance.font.size.normal + spacing) - spacing, Config.lock.sizes.inputWidth - Appearance.rounding.large * 2 - Appearance.padding.large * 5));
|
||||
imWidthBehavior.enabled = true;
|
||||
}
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
implicitWidth: Math.min(count * (Appearance.font.size.normal + spacing) - spacing, Config.lock.sizes.inputWidth - Appearance.rounding.large * 2 - Appearance.padding.large * 5)
|
||||
implicitHeight: Appearance.font.size.normal
|
||||
|
||||
orientation: Qt.Horizontal
|
||||
spacing: Appearance.spacing.small / 2
|
||||
interactive: false
|
||||
|
||||
model: ScriptModel {
|
||||
values: root.passwordBuffer.split("")
|
||||
}
|
||||
|
||||
delegate: StyledRect {
|
||||
id: ch
|
||||
|
||||
implicitWidth: Appearance.font.size.normal
|
||||
implicitHeight: Appearance.font.size.normal
|
||||
|
||||
color: Colours.palette.m3onSurface
|
||||
radius: Appearance.rounding.full
|
||||
|
||||
opacity: 0
|
||||
scale: 0.5
|
||||
Component.onCompleted: {
|
||||
opacity = 1;
|
||||
scale = 1;
|
||||
}
|
||||
ListView.onRemove: removeAnim.start()
|
||||
|
||||
SequentialAnimation {
|
||||
id: removeAnim
|
||||
|
||||
PropertyAction {
|
||||
target: ch
|
||||
property: "ListView.delayRemove"
|
||||
value: true
|
||||
}
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
target: ch
|
||||
property: "opacity"
|
||||
to: 0
|
||||
}
|
||||
Anim {
|
||||
target: ch
|
||||
property: "scale"
|
||||
to: 0.5
|
||||
}
|
||||
}
|
||||
PropertyAction {
|
||||
target: ch
|
||||
property: "ListView.delayRemove"
|
||||
value: false
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on implicitWidth {
|
||||
id: imWidthBehavior
|
||||
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
import qs.components
|
||||
import qs.components.controls
|
||||
import qs.services
|
||||
import qs.config
|
||||
import Quickshell.Widgets
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
required property bool isLarge
|
||||
|
||||
spacing: Appearance.spacing.large * (isLarge ? 2 : 1.5)
|
||||
width: isLarge ? Config.lock.sizes.mediaWidth : Config.lock.sizes.mediaWidthSmall
|
||||
|
||||
property real playerProgress: {
|
||||
const active = Players.active;
|
||||
return active?.length ? active.position / active.length : 0;
|
||||
}
|
||||
|
||||
Behavior on playerProgress {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
running: Players.active?.isPlaying ?? false
|
||||
interval: Config.dashboard.mediaUpdateInterval
|
||||
triggeredOnStart: true
|
||||
repeat: true
|
||||
onTriggered: Players.active?.positionChanged()
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: root.isLarge ? 0 : Config.lock.sizes.border / 2
|
||||
Layout.bottomMargin: root.isLarge ? Config.lock.sizes.border / 2 : 0
|
||||
Layout.leftMargin: root.isLarge ? 0 : Config.lock.sizes.border / 2
|
||||
|
||||
implicitWidth: root.isLarge ? Config.lock.sizes.mediaCoverSize : Config.lock.sizes.mediaCoverSizeSmall
|
||||
implicitHeight: root.isLarge ? Config.lock.sizes.mediaCoverSize : Config.lock.sizes.mediaCoverSizeSmall
|
||||
|
||||
ClippingWrapperRectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
color: Colours.tPalette.m3surfaceContainerHigh
|
||||
radius: Appearance.rounding.small
|
||||
rotation: 9
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
|
||||
source: Players.active?.trackArtUrl ?? ""
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -1
|
||||
border.width: Config.lock.sizes.mediaCoverBorder
|
||||
border.color: Colours.palette.m3primary
|
||||
color: "transparent"
|
||||
radius: Appearance.rounding.small
|
||||
rotation: 9
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledClippingRect {
|
||||
anchors.fill: parent
|
||||
|
||||
color: Colours.tPalette.m3surfaceContainerHigh
|
||||
radius: Appearance.rounding.small
|
||||
|
||||
border.width: Config.lock.sizes.mediaCoverBorder
|
||||
border.color: Colours.palette.m3primary
|
||||
|
||||
MaterialIcon {
|
||||
anchors.centerIn: parent
|
||||
|
||||
grade: 200
|
||||
text: "art_track"
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
font.pointSize: (root.isLarge ? Config.lock.sizes.mediaCoverSize : Config.lock.sizes.mediaCoverSizeSmall) * 0.4
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
|
||||
source: Players.active?.trackArtUrl ?? ""
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: root.isLarge ? 0 : Config.lock.sizes.border / 2
|
||||
Layout.bottomMargin: root.isLarge ? Config.lock.sizes.border / 2 : 0
|
||||
Layout.rightMargin: root.isLarge ? Config.lock.sizes.border / 2 : 0
|
||||
Layout.fillWidth: true
|
||||
|
||||
spacing: root.isLarge ? Appearance.spacing.small : Appearance.spacing.small / 2
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
animate: true
|
||||
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
|
||||
color: Colours.palette.m3primary
|
||||
font.pointSize: root.isLarge ? Appearance.font.size.large : Appearance.font.size.larger
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
animate: true
|
||||
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
|
||||
color: Colours.palette.m3outline
|
||||
font.pointSize: root.isLarge ? Appearance.font.size.larger : Appearance.font.size.normal
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
animate: true
|
||||
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
|
||||
color: Colours.palette.m3secondary
|
||||
font.pointSize: root.isLarge ? Appearance.font.size.larger : Appearance.font.size.normal
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: controls
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
spacing: Appearance.spacing.small
|
||||
|
||||
StyledSlider {
|
||||
id: slider
|
||||
|
||||
Layout.rightMargin: root.isLarge ? Appearance.spacing.small : 0
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: Appearance.padding.normal * 3
|
||||
|
||||
value: root.playerProgress
|
||||
onMoved: {
|
||||
const active = Players.active;
|
||||
if (active?.canSeek && active?.positionSupported)
|
||||
active.position = value * active.length;
|
||||
}
|
||||
}
|
||||
|
||||
Control {
|
||||
icon: "skip_previous"
|
||||
canUse: Players.active?.canGoPrevious ?? false
|
||||
fontSize: root.isLarge ? Appearance.font.size.extraLarge : Appearance.font.size.large * 1.2
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.previous();
|
||||
}
|
||||
}
|
||||
|
||||
Control {
|
||||
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
|
||||
canUse: Players.active?.canTogglePlaying ?? false
|
||||
fontSize: root.isLarge ? Appearance.font.size.extraLarge : Appearance.font.size.large * 1.2
|
||||
primary: true
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.togglePlaying();
|
||||
}
|
||||
}
|
||||
|
||||
Control {
|
||||
icon: "skip_next"
|
||||
canUse: Players.active?.canGoNext ?? false
|
||||
fontSize: root.isLarge ? Appearance.font.size.extraLarge : Appearance.font.size.large * 1.2
|
||||
|
||||
function onClicked(): void {
|
||||
Players.active?.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Control: StyledRect {
|
||||
id: control
|
||||
|
||||
required property string icon
|
||||
required property bool canUse
|
||||
required property int fontSize
|
||||
property int padding
|
||||
property bool fill: true
|
||||
property bool primary
|
||||
function onClicked(): void {
|
||||
}
|
||||
|
||||
implicitWidth: Math.max(icon.implicitWidth, icon.implicitHeight) + padding * 2
|
||||
implicitHeight: implicitWidth
|
||||
|
||||
radius: Appearance.rounding.full
|
||||
color: Qt.alpha(Colours.palette.m3primary, primary && canUse ? 1 : 0)
|
||||
|
||||
StateLayer {
|
||||
disabled: !control.canUse
|
||||
radius: parent.radius
|
||||
color: control.primary ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
|
||||
|
||||
function onClicked(): void {
|
||||
control.onClicked();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
id: icon
|
||||
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: -font.pointSize * 0.02
|
||||
anchors.verticalCenterOffset: font.pointSize * 0.02
|
||||
|
||||
animate: true
|
||||
fill: control.fill ? 1 : 0
|
||||
text: control.icon
|
||||
color: control.canUse ? control.primary ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface : Colours.palette.m3outline
|
||||
font.pointSize: control.fontSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.components
|
||||
import qs.components.effects
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.utils
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Services.Notifications
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
StyledRect {
|
||||
id: root
|
||||
|
||||
required property Notifs.Notif modelData
|
||||
readonly property bool hasImage: modelData.image.length > 0
|
||||
readonly property bool hasAppIcon: modelData.appIcon.length > 0
|
||||
readonly property int nonAnimHeight: Math.max(image.height, details.implicitHeight) + Appearance.padding.normal * 2
|
||||
|
||||
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3secondaryContainer : Colours.tPalette.m3surfaceContainer
|
||||
radius: Appearance.rounding.normal
|
||||
implicitWidth: Config.notifs.sizes.width
|
||||
|
||||
Component.onCompleted: implicitHeight = Qt.binding(() => nonAnimHeight)
|
||||
|
||||
Behavior on implicitHeight {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
|
||||
}
|
||||
}
|
||||
|
||||
RetainableLock {
|
||||
object: root.modelData.notification
|
||||
locked: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: pressed ? Qt.ClosedHandCursor : undefined
|
||||
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
||||
preventStealing: true
|
||||
|
||||
onEntered: root.modelData.timer.stop()
|
||||
onExited: root.modelData.timer.start()
|
||||
|
||||
drag.target: parent
|
||||
drag.axis: Drag.XAxis
|
||||
|
||||
onPressed: event => {
|
||||
if (event.button === Qt.MiddleButton)
|
||||
root.modelData.notification.dismiss();
|
||||
}
|
||||
onReleased: event => {
|
||||
if (Math.abs(root.x) < Config.notifs.sizes.width * Config.notifs.clearThreshold)
|
||||
root.x = 0;
|
||||
else
|
||||
root.modelData.notification.dismiss(); // TODO: change back to popup when notif dock impled
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: image
|
||||
|
||||
active: root.hasImage
|
||||
asynchronous: true
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: Appearance.padding.normal
|
||||
|
||||
width: Config.notifs.sizes.image
|
||||
height: Config.notifs.sizes.image
|
||||
visible: root.hasImage || root.hasAppIcon
|
||||
|
||||
sourceComponent: ClippingRectangle {
|
||||
radius: Appearance.rounding.full
|
||||
implicitWidth: Config.notifs.sizes.image
|
||||
implicitHeight: Config.notifs.sizes.image
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl(root.modelData.image)
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
cache: false
|
||||
asynchronous: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: appIcon
|
||||
|
||||
active: root.hasAppIcon || !root.hasImage
|
||||
asynchronous: true
|
||||
|
||||
anchors.horizontalCenter: root.hasImage ? undefined : image.horizontalCenter
|
||||
anchors.verticalCenter: root.hasImage ? undefined : image.verticalCenter
|
||||
anchors.right: root.hasImage ? image.right : undefined
|
||||
anchors.bottom: root.hasImage ? image.bottom : undefined
|
||||
|
||||
sourceComponent: StyledRect {
|
||||
radius: Appearance.rounding.full
|
||||
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.tPalette.m3surfaceContainerHighest : Colours.palette.m3tertiaryContainer
|
||||
implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
|
||||
implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
|
||||
|
||||
Loader {
|
||||
id: icon
|
||||
|
||||
active: root.hasAppIcon
|
||||
asynchronous: true
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: Math.round(parent.width * 0.6)
|
||||
height: Math.round(parent.width * 0.6)
|
||||
|
||||
sourceComponent: IconImage {
|
||||
anchors.fill: parent
|
||||
source: Quickshell.iconPath(root.modelData.appIcon)
|
||||
asynchronous: true
|
||||
|
||||
layer.enabled: root.modelData.appIcon.endsWith("symbolic")
|
||||
layer.effect: Colouriser {
|
||||
colorizationColor: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: !root.hasAppIcon
|
||||
asynchronous: true
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: -Appearance.font.size.large * 0.02
|
||||
anchors.verticalCenterOffset: Appearance.font.size.large * 0.02
|
||||
|
||||
sourceComponent: MaterialIcon {
|
||||
text: Icons.getNotifIcon(root.modelData.summary.toLowerCase(), root.modelData.urgency)
|
||||
|
||||
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer
|
||||
font.pointSize: Appearance.font.size.large
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: details
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: image.right
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Appearance.spacing.smaller
|
||||
anchors.rightMargin: Appearance.padding.larger
|
||||
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
spacing: Appearance.spacing.small
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: implicitWidth
|
||||
|
||||
animate: true
|
||||
text: root.modelData.summary
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "•"
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
|
||||
StyledText {
|
||||
animate: true
|
||||
text: root.modelData.timeStr
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
font.pointSize: Appearance.font.size.small
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
animate: true
|
||||
text: root.modelData.body
|
||||
color: Colours.palette.m3onSurfaceVariant
|
||||
font.pointSize: Appearance.font.size.small
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
import qs.components
|
||||
import qs.components.widgets
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.utils
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Bluetooth
|
||||
import Quickshell.Services.UPower
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
WrapperItem {
|
||||
property alias showNotifs: notifs.active
|
||||
|
||||
readonly property real nonAnimWidth: (notifs.item?.count > 0 ? Config.notifs.sizes.width : status.implicitWidth) + margin
|
||||
readonly property real nonAnimHeight: {
|
||||
if (notifs.active && notifs.item.count > 0) {
|
||||
const count = Math.min(notifs.item.count, Config.lock.maxNotifs);
|
||||
let height = status.implicitHeight + Appearance.spacing.normal + Appearance.spacing.smaller * (count - 1);
|
||||
for (let i = 0; i < count; i++)
|
||||
height += notifs.item.itemAtIndex(i)?.nonAnimHeight ?? 0;
|
||||
return height + margin;
|
||||
}
|
||||
|
||||
return status.implicitHeight + margin;
|
||||
}
|
||||
|
||||
implicitWidth: nonAnimWidth
|
||||
implicitHeight: nonAnimHeight
|
||||
|
||||
margin: Appearance.padding.large * 2
|
||||
rightMargin: 0
|
||||
topMargin: 0
|
||||
|
||||
Timer {
|
||||
running: true
|
||||
interval: 10
|
||||
onTriggered: notifs.item?.countChanged()
|
||||
}
|
||||
|
||||
Behavior on implicitWidth {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on implicitHeight {
|
||||
Anim {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
RowLayout {
|
||||
id: status
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: Appearance.spacing.small
|
||||
|
||||
Loader {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
active: UPower.displayDevice.isLaptopBattery
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: StyledText {
|
||||
animate: true
|
||||
text: qsTr("%1%2% remaining").arg(UPower.onBattery ? "" : "(+) ").arg(Math.round(UPower.displayDevice.percentage * 100))
|
||||
color: !UPower.onBattery || UPower.displayDevice.percentage > 0.2 ? Colours.palette.m3onSurface : Colours.palette.m3error
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
animate: true
|
||||
text: Network.active ? Icons.getNetworkIcon(Network.active.strength ?? 0) : "wifi_off"
|
||||
font.pointSize: Appearance.font.size.large
|
||||
}
|
||||
|
||||
Loader {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: item?.implicitWidth ?? 0
|
||||
|
||||
active: !UPower.displayDevice.isLaptopBattery
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: StyledText {
|
||||
animate: true
|
||||
text: Network.active?.ssid ?? ""
|
||||
font.pointSize: Appearance.font.size.normal
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
animate: true
|
||||
text: Bluetooth.defaultAdapter.enabled ? "bluetooth" : "bluetooth_disabled"
|
||||
font.pointSize: Appearance.font.size.large
|
||||
}
|
||||
|
||||
Loader {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
active: !UPower.displayDevice.isLaptopBattery
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: StyledText {
|
||||
animate: true
|
||||
text: qsTr("%n device(s) connected", "", Bluetooth.devices.values.filter(d => d.connected).length)
|
||||
font.pointSize: Appearance.font.size.normal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: notifs
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
sourceComponent: ListView {
|
||||
model: ScriptModel {
|
||||
values: [...Notifs.list].reverse()
|
||||
}
|
||||
|
||||
orientation: Qt.Vertical
|
||||
spacing: 0
|
||||
clip: true
|
||||
interactive: false
|
||||
|
||||
delegate: Item {
|
||||
id: wrapper
|
||||
|
||||
required property Notifs.Notif modelData
|
||||
required property int index
|
||||
readonly property alias nonAnimHeight: notif.nonAnimHeight
|
||||
property int idx
|
||||
|
||||
onIndexChanged: {
|
||||
if (index !== -1)
|
||||
idx = index;
|
||||
}
|
||||
|
||||
implicitWidth: notif.implicitWidth
|
||||
implicitHeight: notif.nonAnimHeight + (idx === 0 ? 0 : Appearance.spacing.smaller)
|
||||
|
||||
ListView.onRemove: removeAnim.start()
|
||||
|
||||
SequentialAnimation {
|
||||
id: removeAnim
|
||||
|
||||
PropertyAction {
|
||||
target: wrapper
|
||||
property: "ListView.delayRemove"
|
||||
value: true
|
||||
}
|
||||
PropertyAction {
|
||||
target: wrapper
|
||||
property: "enabled"
|
||||
value: false
|
||||
}
|
||||
PropertyAction {
|
||||
target: wrapper
|
||||
property: "implicitHeight"
|
||||
value: 0
|
||||
}
|
||||
PropertyAction {
|
||||
target: wrapper
|
||||
property: "z"
|
||||
value: 1
|
||||
}
|
||||
Anim {
|
||||
target: notif
|
||||
property: "x"
|
||||
to: (notif.x >= 0 ? Config.notifs.sizes.width : -Config.notifs.sizes.width) * 2
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
PropertyAction {
|
||||
target: wrapper
|
||||
property: "ListView.delayRemove"
|
||||
value: false
|
||||
}
|
||||
}
|
||||
|
||||
ClippingRectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: wrapper.idx === 0 ? 0 : Appearance.spacing.smaller
|
||||
|
||||
color: "transparent"
|
||||
radius: notif.radius
|
||||
implicitWidth: notif.implicitWidth
|
||||
implicitHeight: notif.nonAnimHeight
|
||||
|
||||
Notification {
|
||||
id: notif
|
||||
|
||||
modelData: wrapper.modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
Anim {
|
||||
property: "y"
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
Anim {
|
||||
property: "y"
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
ExtraIndicator {
|
||||
anchors.bottom: parent.bottom
|
||||
extra: Notifs.list.length - Config.lock.maxNotifs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue