Compare commits
10 commits
4684e8a24f
...
a16c957a8b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a16c957a8b | ||
|
|
b80b9475ac | ||
|
|
deb40a6536 | ||
|
|
92a4273cf5 | ||
|
|
3c7df45505 | ||
|
|
362c1ec670 | ||
|
|
c46593d438 | ||
|
|
3457164e19 | ||
|
|
a1124c8228 | ||
|
|
63b522648e |
14 changed files with 280 additions and 129 deletions
|
|
@ -75,10 +75,12 @@ endif()
|
||||||
if("m3shapes" IN_LIST ENABLE_MODULES)
|
if("m3shapes" IN_LIST ENABLE_MODULES)
|
||||||
message(STATUS "Fetching M3Shapes module")
|
message(STATUS "Fetching M3Shapes module")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
set(M3SHAPES_REV bdc327b29f95394a732baf3c9b19658ba23755b6)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
m3shapes_external
|
m3shapes_external
|
||||||
GIT_REPOSITORY https://github.com/soramanew/m3shapes.git
|
GIT_REPOSITORY https://github.com/soramanew/m3shapes.git
|
||||||
GIT_TAG 356825d31f16052a782735cce264331cba0cb71b
|
GIT_TAG ${M3SHAPES_REV}
|
||||||
|
SOURCE_DIR "${CMAKE_BINARY_DIR}/_deps/m3shapes-${M3SHAPES_REV}"
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(m3shapes_external)
|
FetchContent_MakeAvailable(m3shapes_external)
|
||||||
message(STATUS "Done fetching M3Shapes module")
|
message(STATUS "Done fetching M3Shapes module")
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ For example, to disable the bar on DP-1:
|
||||||
"maxWindowIcons": 5,
|
"maxWindowIcons": 5,
|
||||||
"activeTrail": false,
|
"activeTrail": false,
|
||||||
"perMonitorWorkspaces": true,
|
"perMonitorWorkspaces": true,
|
||||||
"label": " ",
|
"label": " ",
|
||||||
"occupiedLabel": "",
|
"occupiedLabel": "",
|
||||||
"activeLabel": "",
|
"activeLabel": "",
|
||||||
"capitalisation": "preserve",
|
"capitalisation": "preserve",
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,12 @@ MouseArea {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onWheel: e => e.accepted = true
|
||||||
|
}
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
|
|
|
||||||
7
flake.lock
generated
7
flake.lock
generated
|
|
@ -24,16 +24,17 @@
|
||||||
"m3shapes": {
|
"m3shapes": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777812556,
|
"lastModified": 1781017666,
|
||||||
"narHash": "sha256-E5nqOucRQBWKuT31AMekmfgMywRdHgSbU86R7t4BKKA=",
|
"narHash": "sha256-kfHyzZaPHgqZML48OA+5JwBOsLdQJ2ci/aGPShvUB4Y=",
|
||||||
"owner": "soramanew",
|
"owner": "soramanew",
|
||||||
"repo": "m3shapes",
|
"repo": "m3shapes",
|
||||||
"rev": "356825d31f16052a782735cce264331cba0cb71b",
|
"rev": "bdc327b29f95394a732baf3c9b19658ba23755b6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "soramanew",
|
"owner": "soramanew",
|
||||||
"repo": "m3shapes",
|
"repo": "m3shapes",
|
||||||
|
"rev": "bdc327b29f95394a732baf3c9b19658ba23755b6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
m3shapes = {
|
m3shapes = {
|
||||||
url = "github:soramanew/m3shapes/356825d31f16052a782735cce264331cba0cb71b";
|
url = "github:soramanew/m3shapes/bdc327b29f95394a732baf3c9b19658ba23755b6";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,11 @@ Item {
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: GlobalConfig.services.useFahrenheit ? forecastItem.modelData.maxTempF + "°" + " / " + forecastItem.modelData.minTempF + "°" : forecastItem.modelData.maxTempC + "°" + " / " + forecastItem.modelData.minTempC + "°"
|
text: {
|
||||||
|
const min = Weather.formatTemp(forecastItem.modelData.minTempC).slice(0, -1);
|
||||||
|
const max = Weather.formatTemp(forecastItem.modelData.maxTempC).slice(0, -1);
|
||||||
|
return `${min} / ${max}`;
|
||||||
|
}
|
||||||
font: Tokens.font.body.builders.small.weight(Font.DemiBold).build()
|
font: Tokens.font.body.builders.small.weight(Font.DemiBold).build()
|
||||||
color: Colours.palette.m3tertiary
|
color: Colours.palette.m3tertiary
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ StyledWindow {
|
||||||
|
|
||||||
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
|
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
|
||||||
readonly property bool hasSpecialWorkspace: (monitor?.lastIpcObject.specialWorkspace?.name.length ?? 0) > 0
|
readonly property bool hasSpecialWorkspace: (monitor?.lastIpcObject.specialWorkspace?.name.length ?? 0) > 0
|
||||||
|
readonly property bool hasFullscreenOnNormalWs: monitor?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1) ?? false
|
||||||
readonly property bool hasFullscreen: {
|
readonly property bool hasFullscreen: {
|
||||||
if (hasSpecialWorkspace) {
|
if (hasSpecialWorkspace) {
|
||||||
const specialName = monitor?.lastIpcObject.specialWorkspace?.name;
|
const specialName = monitor?.lastIpcObject.specialWorkspace?.name;
|
||||||
|
|
@ -29,7 +30,7 @@ StyledWindow {
|
||||||
const specialWs = Hypr.workspaces.values.find(ws => ws.name === specialName);
|
const specialWs = Hypr.workspaces.values.find(ws => ws.name === specialName);
|
||||||
return specialWs?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1) ?? false;
|
return specialWs?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1) ?? false;
|
||||||
}
|
}
|
||||||
return monitor?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1) ?? false;
|
return hasFullscreenOnNormalWs;
|
||||||
}
|
}
|
||||||
|
|
||||||
property real fsTransitionProg: hasFullscreen ? 1 : 0
|
property real fsTransitionProg: hasFullscreen ? 1 : 0
|
||||||
|
|
@ -64,7 +65,7 @@ StyledWindow {
|
||||||
|
|
||||||
name: "drawers"
|
name: "drawers"
|
||||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||||
WlrLayershell.layer: fsTransitionProg > 0 && contentItem.Config.general.showOverFullscreen ? WlrLayer.Overlay : WlrLayer.Top
|
WlrLayershell.layer: (fsTransitionProg > 0 && contentItem.Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
|
||||||
WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.session ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.session ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||||
|
|
||||||
mask: hasFullscreen ? emptyRegion : regions
|
mask: hasFullscreen ? emptyRegion : regions
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ ColumnLayout {
|
||||||
|
|
||||||
PasswordInput {
|
PasswordInput {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
centerScale: Math.max(0.8, root.centerScale)
|
||||||
centerWidth: root.centerWidth
|
centerWidth: root.centerWidth
|
||||||
lock: root.lock
|
lock: root.lock
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import M3Shapes
|
||||||
import Caelestia.Config
|
import Caelestia.Config
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.services
|
import qs.services
|
||||||
|
|
@ -10,9 +11,19 @@ import qs.modules.lock
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
required property real centerScale
|
||||||
required property Pam pam
|
required property Pam pam
|
||||||
readonly property alias placeholder: placeholder
|
readonly property alias placeholder: placeholder
|
||||||
|
readonly property alias placeholderWidth: nonAnimPlaceholder.width
|
||||||
property string buffer
|
property string buffer
|
||||||
|
readonly property list<int> shapeQueue: {
|
||||||
|
const shapes = [MaterialShape.Slanted, MaterialShape.Arch, MaterialShape.Fan, MaterialShape.Arrow, MaterialShape.SemiCircle, MaterialShape.Triangle, MaterialShape.Diamond, MaterialShape.ClamShell, MaterialShape.Pentagon, MaterialShape.Gem, MaterialShape.Sunny, MaterialShape.VerySunny, MaterialShape.Cookie4Sided, MaterialShape.Ghostish, MaterialShape.SoftBurst];
|
||||||
|
for (let i = shapes.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[shapes[i], shapes[j]] = [shapes[j], shapes[i]];
|
||||||
|
}
|
||||||
|
return shapes;
|
||||||
|
}
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
|
@ -31,22 +42,30 @@ Item {
|
||||||
target: root.pam
|
target: root.pam
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
TextMetrics {
|
||||||
id: placeholder
|
id: nonAnimPlaceholder
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
text: {
|
text: {
|
||||||
if (root.pam.passwd.active)
|
if (root.pam.passwd.active)
|
||||||
return qsTr("Loading...");
|
return qsTr("Loading...");
|
||||||
if (root.pam.state === "max")
|
if (root.pam.state === "max")
|
||||||
return qsTr("You have reached the maximum number of tries");
|
return qsTr("Max tries reached");
|
||||||
return qsTr("Enter your password");
|
return qsTr("Enter your password");
|
||||||
}
|
}
|
||||||
|
font: placeholder.font
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: placeholder
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.verticalCenterOffset: 1
|
||||||
|
|
||||||
|
text: nonAnimPlaceholder.text
|
||||||
|
|
||||||
animate: true
|
animate: true
|
||||||
color: root.pam.passwd.active ? Colours.palette.m3secondary : Colours.palette.m3outline
|
color: root.pam.passwd.active ? Colours.palette.m3secondary : Colours.palette.m3outline
|
||||||
font: Tokens.font.mono.medium
|
font: Tokens.font.body.builders.medium.scale(root.centerScale).width(110).build()
|
||||||
|
|
||||||
opacity: root.buffer ? 0 : 1
|
opacity: root.buffer ? 0 : 1
|
||||||
|
|
||||||
|
|
@ -60,7 +79,12 @@ Item {
|
||||||
ListView {
|
ListView {
|
||||||
id: charList
|
id: charList
|
||||||
|
|
||||||
readonly property int fullWidth: count * (implicitHeight + spacing) - spacing
|
readonly property int fullWidth: {
|
||||||
|
let w = (count - 1) * spacing;
|
||||||
|
for (let i = 0; i < count; i++)
|
||||||
|
w += ((itemAtIndex(i) as CharItem)?.nonAnimWidthScale ?? 1) * implicitHeight;
|
||||||
|
return w + implicitHeight; // Extra padding at ends
|
||||||
|
}
|
||||||
|
|
||||||
function bindImWidth(): void {
|
function bindImWidth(): void {
|
||||||
imWidthBehavior.enabled = false;
|
imWidthBehavior.enabled = false;
|
||||||
|
|
@ -82,63 +106,7 @@ Item {
|
||||||
values: root.buffer.split("")
|
values: root.buffer.split("")
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: StyledRect {
|
delegate: CharItem {}
|
||||||
id: ch
|
|
||||||
|
|
||||||
implicitWidth: implicitHeight
|
|
||||||
implicitHeight: charList.implicitHeight
|
|
||||||
|
|
||||||
color: Colours.palette.m3onSurface
|
|
||||||
radius: Tokens.rounding.medium / 2
|
|
||||||
|
|
||||||
opacity: 0
|
|
||||||
scale: 0
|
|
||||||
Component.onCompleted: {
|
|
||||||
opacity = 1;
|
|
||||||
scale = 1;
|
|
||||||
}
|
|
||||||
ListView.onRemove: removeAnim.start()
|
|
||||||
|
|
||||||
SequentialAnimation {
|
|
||||||
id: removeAnim
|
|
||||||
|
|
||||||
PropertyAction {
|
|
||||||
target: ch
|
|
||||||
property: "ListView.delayRemove"
|
|
||||||
value: true
|
|
||||||
}
|
|
||||||
ParallelAnimation {
|
|
||||||
Anim {
|
|
||||||
type: Anim.DefaultEffects
|
|
||||||
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 {
|
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
|
||||||
Anim {
|
|
||||||
type: Anim.FastSpatial
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on implicitWidth {
|
Behavior on implicitWidth {
|
||||||
id: imWidthBehavior
|
id: imWidthBehavior
|
||||||
|
|
@ -146,4 +114,121 @@ Item {
|
||||||
Anim {}
|
Anim {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
component CharItem: Item {
|
||||||
|
id: char
|
||||||
|
|
||||||
|
required property int index
|
||||||
|
property real nonAnimWidthScale: 1
|
||||||
|
|
||||||
|
implicitHeight: charList.implicitHeight
|
||||||
|
|
||||||
|
ListView.onRemove: {
|
||||||
|
initAnim.stop();
|
||||||
|
removeAnim.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialShape {
|
||||||
|
id: charShape
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
implicitSize: charList.implicitHeight * 1.5
|
||||||
|
shape: root.shapeQueue[char.index % root.shapeQueue.length] ?? MaterialShape.Circle
|
||||||
|
color: Colours.palette.m3onSurface
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
CAnim {}
|
||||||
|
}
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: initAnim
|
||||||
|
|
||||||
|
running: true
|
||||||
|
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
target: charShape
|
||||||
|
property: "opacity"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
type: Anim.DefaultEffects
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
target: charShape
|
||||||
|
property: "scale"
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
type: Anim.FastSpatial
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
target: char
|
||||||
|
property: "implicitWidth"
|
||||||
|
from: charList.implicitHeight
|
||||||
|
to: charList.implicitHeight * 1.3
|
||||||
|
type: Anim.DefaultEffects
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
target: char
|
||||||
|
property: "nonAnimWidthScale"
|
||||||
|
value: 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PauseAnimation {
|
||||||
|
duration: 180 * Tokens.anim.durations.scale
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
target: charShape
|
||||||
|
property: "shape"
|
||||||
|
value: MaterialShape.Circle
|
||||||
|
}
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
target: charShape
|
||||||
|
property: "scale"
|
||||||
|
to: 2 / 3
|
||||||
|
type: Anim.FastSpatial
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
target: char
|
||||||
|
property: "implicitWidth"
|
||||||
|
to: charList.implicitHeight
|
||||||
|
type: Anim.DefaultEffects
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
target: char
|
||||||
|
property: "nonAnimWidthScale"
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: removeAnim
|
||||||
|
|
||||||
|
PropertyAction {
|
||||||
|
target: char
|
||||||
|
property: "ListView.delayRemove"
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
type: Anim.DefaultEffects
|
||||||
|
target: charShape
|
||||||
|
property: "opacity"
|
||||||
|
to: 0
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
target: charShape
|
||||||
|
property: "scale"
|
||||||
|
to: 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
target: char
|
||||||
|
property: "ListView.delayRemove"
|
||||||
|
value: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import M3Shapes
|
||||||
import Caelestia.Config
|
import Caelestia.Config
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.components.controls
|
import qs.components.controls
|
||||||
|
|
@ -8,10 +11,14 @@ import qs.services
|
||||||
StyledRect {
|
StyledRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
required property real centerScale
|
||||||
required property int centerWidth
|
required property int centerWidth
|
||||||
required property var lock
|
required property var lock
|
||||||
|
|
||||||
implicitWidth: centerWidth * 0.8
|
implicitWidth: {
|
||||||
|
const w = centerWidth * 0.8;
|
||||||
|
return lock.pam.buffer ? w : Math.min(w, inputField.placeholderWidth + iconWrapper.implicitWidth + enterButton.implicitWidth + input.spacing * 2 + Tokens.padding.medium * 2);
|
||||||
|
}
|
||||||
implicitHeight: input.implicitHeight + Tokens.padding.small
|
implicitHeight: input.implicitHeight + Tokens.padding.small
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
|
@ -33,6 +40,10 @@ StyledRect {
|
||||||
root.lock.pam.handleKey(event);
|
root.lock.pam.handleKey(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
hoverEnabled: false
|
hoverEnabled: false
|
||||||
cursorShape: Qt.IBeamCursor
|
cursorShape: Qt.IBeamCursor
|
||||||
|
|
@ -47,44 +58,39 @@ StyledRect {
|
||||||
spacing: Tokens.spacing.medium
|
spacing: Tokens.spacing.medium
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: iconWrapper
|
||||||
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
implicitWidth: height
|
implicitWidth: height
|
||||||
|
|
||||||
MaterialIcon {
|
AnimLoader {
|
||||||
id: fprintIcon
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
animate: true
|
anchors.verticalCenterOffset: sourceComponent === iconComp ? 1 : 0
|
||||||
text: {
|
sourceComp: root.lock.pam.passwd.active ? loadingComp : iconComp
|
||||||
if (root.lock.pam.fprint.tries >= GlobalConfig.lock.maxFprintTries)
|
}
|
||||||
return "fingerprint_off";
|
|
||||||
if (root.lock.pam.fprint.active)
|
|
||||||
return "fingerprint";
|
|
||||||
return "lock";
|
|
||||||
}
|
|
||||||
color: root.lock.pam.fprint.tries >= GlobalConfig.lock.maxFprintTries ? Colours.palette.m3error : Colours.palette.m3onSurface
|
|
||||||
opacity: root.lock.pam.passwd.active ? 0 : 1
|
|
||||||
|
|
||||||
Behavior on opacity {
|
Component {
|
||||||
Anim {
|
id: iconComp
|
||||||
type: Anim.DefaultEffects
|
|
||||||
|
MaterialIcon {
|
||||||
|
animate: true
|
||||||
|
text: {
|
||||||
|
if (root.lock.pam.fprint.tries >= GlobalConfig.lock.maxFprintTries)
|
||||||
|
return "fingerprint_off";
|
||||||
|
if (root.lock.pam.fprint.active)
|
||||||
|
return "fingerprint";
|
||||||
|
return "lock";
|
||||||
}
|
}
|
||||||
|
color: root.lock.pam.fprint.tries >= GlobalConfig.lock.maxFprintTries ? Colours.palette.m3error : Colours.palette.m3onSurfaceVariant
|
||||||
|
fontStyle: Tokens.font.icon.builders.medium.scale(root.centerScale).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Component {
|
||||||
anchors.fill: parent
|
id: loadingComp
|
||||||
anchors.margins: Tokens.padding.small
|
|
||||||
|
|
||||||
active: opacity > 0
|
LoadingIndicator {
|
||||||
opacity: root.lock.pam.passwd.active ? 1 : 0
|
implicitSize: iconWrapper.height - Tokens.padding.small * 2
|
||||||
|
|
||||||
sourceComponent: LoadingIndicator {}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {
|
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,19 +101,45 @@ StyledRect {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
centerScale: root.centerScale
|
||||||
pam: root.lock.pam
|
pam: root.lock.pam
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledRect {
|
Item {
|
||||||
|
id: enterButton
|
||||||
|
|
||||||
implicitWidth: implicitHeight
|
implicitWidth: implicitHeight
|
||||||
implicitHeight: enterIcon.implicitHeight + Tokens.padding.small
|
implicitHeight: {
|
||||||
|
const h = enterIcon.implicitHeight + Tokens.padding.extraSmall * 2;
|
||||||
|
return h % 2 === 0 ? h : h + 1;
|
||||||
|
}
|
||||||
|
|
||||||
color: root.lock.pam.buffer ? Colours.palette.m3primary : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
|
MaterialShape {
|
||||||
radius: Tokens.rounding.full
|
anchors.fill: parent
|
||||||
|
|
||||||
StateLayer {
|
color: root.lock.pam.buffer ? Colours.palette.m3primary : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
|
||||||
color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
|
shape: root.lock.pam.buffer ? MaterialShape.Arrow : MaterialShape.Circle
|
||||||
onClicked: root.lock.pam.passwd.start()
|
scale: !root.lock.pam.buffer ? 1 : mouse.pressed ? 0.6 : mouse.containsMouse ? 0.8 : 0.7
|
||||||
|
rotation: 90
|
||||||
|
|
||||||
|
Behavior on scale {
|
||||||
|
Anim {
|
||||||
|
type: Anim.FastSpatial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
CAnim {}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouse
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: root.lock.pam.buffer ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
onClicked: root.lock.pam.buffer && root.lock.pam.passwd.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialIcon {
|
MaterialIcon {
|
||||||
|
|
@ -115,8 +147,15 @@ StyledRect {
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "arrow_forward"
|
text: "arrow_forward"
|
||||||
color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
fontStyle: Tokens.font.icon.size(Tokens.font.icon.large.pointSize).weight(Font.Medium).build()
|
fontStyle: Tokens.font.icon.builders.medium.scale(root.centerScale * 1.2).build()
|
||||||
|
opacity: root.lock.pam.buffer ? 0 : 1
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
type: Anim.DefaultEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ Item {
|
||||||
opacity: root.stateMsgShouldBeVisible && !root.msg ? 1 : 0
|
opacity: root.stateMsgShouldBeVisible && !root.msg ? 1 : 0
|
||||||
color: Colours.palette.m3onSurfaceVariant
|
color: Colours.palette.m3onSurfaceVariant
|
||||||
|
|
||||||
font: Tokens.font.mono.small
|
font: Tokens.font.body.small
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
lineHeight: 1.2
|
lineHeight: 1.2
|
||||||
|
|
@ -145,7 +145,7 @@ Item {
|
||||||
opacity: 0
|
opacity: 0
|
||||||
color: Colours.palette.m3error
|
color: Colours.palette.m3error
|
||||||
|
|
||||||
font: Tokens.font.mono.small
|
font: Tokens.font.body.small
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ class UserPaths : public ConfigObject {
|
||||||
|
|
||||||
CONFIG_GLOBAL_PROPERTY(
|
CONFIG_GLOBAL_PROPERTY(
|
||||||
QString, wallpaperDir, QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + u"/Wallpapers"_s)
|
QString, wallpaperDir, QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + u"/Wallpapers"_s)
|
||||||
CONFIG_GLOBAL_PROPERTY(QString, lyricsDir, QDir::homePath() + u"/Music/lyrics/"_s)
|
CONFIG_GLOBAL_PROPERTY(
|
||||||
|
QString, lyricsDir, QStandardPaths::writableLocation(QStandardPaths::MusicLocation) + u"/Lyrics/"_s)
|
||||||
CONFIG_PROPERTY(QString, sessionGif, u"root:/assets/kurukuru.gif"_s)
|
CONFIG_PROPERTY(QString, sessionGif, u"root:/assets/kurukuru.gif"_s)
|
||||||
CONFIG_PROPERTY(QString, mediaGif, u"root:/assets/bongocat.gif"_s)
|
CONFIG_PROPERTY(QString, mediaGif, u"root:/assets/bongocat.gif"_s)
|
||||||
CONFIG_PROPERTY(QString, noNotifsPic, u"root:/assets/dino.png"_s)
|
CONFIG_PROPERTY(QString, noNotifsPic, u"root:/assets/dino.png"_s)
|
||||||
|
|
|
||||||
|
|
@ -788,7 +788,6 @@ void Lyrics::onPreferredBackendConfigChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lyrics::onLyricsDirChanged() {
|
void Lyrics::onLyricsDirChanged() {
|
||||||
loadLyricsMap();
|
|
||||||
scheduleLoad();
|
scheduleLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -828,11 +827,7 @@ void Lyrics::persistTrackPrefs() {
|
||||||
}
|
}
|
||||||
m_lyricsMap.insert(key, entry);
|
m_lyricsMap.insert(key, entry);
|
||||||
|
|
||||||
const QString dir = lyricsDir();
|
QDir().mkpath(stateDir());
|
||||||
if (dir.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QDir().mkpath(dir);
|
|
||||||
|
|
||||||
QSaveFile out(lyricsMapPath());
|
QSaveFile out(lyricsMapPath());
|
||||||
if (!out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
if (!out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
|
@ -855,6 +850,11 @@ QString Lyrics::lyricsDir() const {
|
||||||
if (dir.isEmpty()) {
|
if (dir.isEmpty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
if (dir == u"~"_s) {
|
||||||
|
dir = QDir::homePath();
|
||||||
|
} else if (dir.startsWith(u"~/"_s)) {
|
||||||
|
dir.replace(0, 1, QDir::homePath());
|
||||||
|
}
|
||||||
while (dir.endsWith(QLatin1Char('/')) && dir.size() > 1) {
|
while (dir.endsWith(QLatin1Char('/')) && dir.size() > 1) {
|
||||||
dir.chop(1);
|
dir.chop(1);
|
||||||
}
|
}
|
||||||
|
|
@ -862,8 +862,7 @@ QString Lyrics::lyricsDir() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Lyrics::lyricsMapPath() const {
|
QString Lyrics::lyricsMapPath() const {
|
||||||
const QString dir = lyricsDir();
|
return stateDir() + u"/lyrics_map.json"_s;
|
||||||
return dir.isEmpty() ? QString() : dir + u"/lyrics_map.json"_s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Lyrics::trackKey() const {
|
QString Lyrics::trackKey() const {
|
||||||
|
|
@ -876,30 +875,41 @@ QString Lyrics::trackKey() const {
|
||||||
QString Lyrics::backendKey(LyricsBackend::Backend value) {
|
QString Lyrics::backendKey(LyricsBackend::Backend value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case LyricsBackend::Local:
|
case LyricsBackend::Local:
|
||||||
return u"LyricsBackend::Local"_s;
|
return u"Local"_s;
|
||||||
case LyricsBackend::LRCLIB:
|
case LyricsBackend::LRCLIB:
|
||||||
return u"LyricsBackend::LRCLIB"_s;
|
return u"LRCLIB"_s;
|
||||||
case LyricsBackend::NetEase:
|
case LyricsBackend::NetEase:
|
||||||
return u"LyricsBackend::NetEase"_s;
|
return u"NetEase"_s;
|
||||||
case LyricsBackend::Auto:
|
case LyricsBackend::Auto:
|
||||||
default:
|
default:
|
||||||
return u"LyricsBackend::Auto"_s;
|
return u"Auto"_s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LyricsBackend::Backend Lyrics::backendFromKey(const QString& key) {
|
LyricsBackend::Backend Lyrics::backendFromKey(const QString& key) {
|
||||||
if (key.compare(u"LyricsBackend::Local"_s, Qt::CaseInsensitive) == 0) {
|
if (key.compare(u"Local"_s, Qt::CaseInsensitive) == 0) {
|
||||||
return LyricsBackend::Local;
|
return LyricsBackend::Local;
|
||||||
}
|
}
|
||||||
if (key.compare(u"LyricsBackend::LRCLIB"_s, Qt::CaseInsensitive) == 0) {
|
if (key.compare(u"LRCLIB"_s, Qt::CaseInsensitive) == 0) {
|
||||||
return LyricsBackend::LRCLIB;
|
return LyricsBackend::LRCLIB;
|
||||||
}
|
}
|
||||||
if (key.compare(u"LyricsBackend::NetEase"_s, Qt::CaseInsensitive) == 0) {
|
if (key.compare(u"NetEase"_s, Qt::CaseInsensitive) == 0) {
|
||||||
return LyricsBackend::NetEase;
|
return LyricsBackend::NetEase;
|
||||||
}
|
}
|
||||||
return LyricsBackend::Auto;
|
return LyricsBackend::Auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString& Lyrics::stateDir() {
|
||||||
|
static const QString s_dir = [] {
|
||||||
|
QString state = qEnvironmentVariable("XDG_STATE_HOME");
|
||||||
|
if (state.isEmpty()) {
|
||||||
|
state = QDir::homePath() + u"/.local/state"_s;
|
||||||
|
}
|
||||||
|
return state + u"/caelestia/lyrics"_s;
|
||||||
|
}();
|
||||||
|
return s_dir;
|
||||||
|
}
|
||||||
|
|
||||||
const QString& Lyrics::cacheDir() {
|
const QString& Lyrics::cacheDir() {
|
||||||
static const QString s_dir = [] {
|
static const QString s_dir = [] {
|
||||||
QString cache = qEnvironmentVariable("XDG_CACHE_HOME");
|
QString cache = qEnvironmentVariable("XDG_CACHE_HOME");
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ private:
|
||||||
[[nodiscard]] static QString backendKey(LyricsBackend::Backend value);
|
[[nodiscard]] static QString backendKey(LyricsBackend::Backend value);
|
||||||
[[nodiscard]] static LyricsBackend::Backend backendFromKey(const QString& key);
|
[[nodiscard]] static LyricsBackend::Backend backendFromKey(const QString& key);
|
||||||
|
|
||||||
|
[[nodiscard]] static const QString& stateDir();
|
||||||
[[nodiscard]] static const QString& cacheDir();
|
[[nodiscard]] static const QString& cacheDir();
|
||||||
[[nodiscard]] static QString cachePathFor(LyricsBackend::Backend backend, const QString& id);
|
[[nodiscard]] static QString cachePathFor(LyricsBackend::Backend backend, const QString& id);
|
||||||
[[nodiscard]] static QString readCachedLrc(LyricsBackend::Backend backend, const QString& id);
|
[[nodiscard]] static QString readCachedLrc(LyricsBackend::Backend backend, const QString& id);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue