mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-08-15 18:43:59 +00:00
WallpaperPanel: add keyboard controls thanks to pC
LockScreen: add cursor to password field, clear password after login attempt i18n: small cleanup autoformat
This commit is contained in:
@@ -47,6 +47,9 @@ Loader {
|
||||
lockScreen.scheduleUnloadAfterUnlock()
|
||||
lockContext.currentText = ""
|
||||
}
|
||||
onFailed: {
|
||||
lockContext.currentText = ""
|
||||
}
|
||||
}
|
||||
|
||||
WlSessionLock {
|
||||
@@ -228,6 +231,47 @@ Loader {
|
||||
}
|
||||
}
|
||||
|
||||
// Error notification
|
||||
Rectangle {
|
||||
width: 400 * scaling
|
||||
height: 50 * scaling
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 300 * scaling
|
||||
radius: 25 * scaling
|
||||
color: Color.mError
|
||||
border.color: Color.mError
|
||||
border.width: 1
|
||||
visible: lockContext.showFailure && lockContext.errorMessage
|
||||
opacity: visible ? 1.0 : 0.0
|
||||
|
||||
RowLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 8 * scaling
|
||||
|
||||
NIcon {
|
||||
icon: "alert-circle"
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnError
|
||||
}
|
||||
|
||||
NText {
|
||||
text: lockContext.errorMessage || "Authentication failed"
|
||||
color: Color.mOnError
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom container with weather, password input and controls
|
||||
Rectangle {
|
||||
width: 700 * scaling
|
||||
@@ -554,12 +598,57 @@ Loader {
|
||||
Component.onCompleted: forceActiveFocus()
|
||||
}
|
||||
|
||||
NText {
|
||||
text: passwordInput.text.length > 0 ? "•".repeat(passwordInput.text.length) : I18n.tr("lock-screen.password")
|
||||
color: passwordInput.text.length > 0 ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
width: 560 * scaling
|
||||
opacity: passwordInput.text.length > 0 ? 1.0 : 0.6
|
||||
Row {
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
width: 2 * scaling
|
||||
height: 20 * scaling
|
||||
color: Color.mPrimary
|
||||
visible: passwordInput.activeFocus && passwordInput.text.length === 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
loops: Animation.Infinite
|
||||
running: passwordInput.activeFocus && passwordInput.text.length === 0
|
||||
NumberAnimation {
|
||||
to: 0
|
||||
duration: 530
|
||||
}
|
||||
NumberAnimation {
|
||||
to: 1
|
||||
duration: 530
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: passwordInput.text.length > 0 ? "•".repeat(passwordInput.text.length) : ""
|
||||
color: passwordInput.text.length > 0 ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
opacity: passwordInput.text.length > 0 ? 1.0 : 0.6
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 2 * scaling
|
||||
height: 20 * scaling
|
||||
color: Color.mPrimary
|
||||
visible: passwordInput.activeFocus && passwordInput.text.length > 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
loops: Animation.Infinite
|
||||
running: passwordInput.activeFocus && passwordInput.text.length > 0
|
||||
NumberAnimation {
|
||||
to: 0
|
||||
duration: 530
|
||||
}
|
||||
NumberAnimation {
|
||||
to: 1
|
||||
duration: 530
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,48 +834,6 @@ Loader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Status message
|
||||
NText {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 150 * scaling
|
||||
text: {
|
||||
if (lockContext.unlockInProgress)
|
||||
return lockContext.infoMessage || "Authenticating..."
|
||||
if (lockContext.showFailure && lockContext.errorMessage)
|
||||
return lockContext.errorMessage
|
||||
if (lockContext.showFailure)
|
||||
return "Authentication failed. Please try again."
|
||||
return ""
|
||||
}
|
||||
color: lockContext.unlockInProgress ? Color.mPrimary : (lockContext.showFailure ? Color.mError : Color.transparent)
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
opacity: text.length > 0 ? 1.0 : 0.0
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
running: lockContext.unlockInProgress
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation {
|
||||
to: 0.6
|
||||
duration: 1000
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
NumberAnimation {
|
||||
to: 1.0
|
||||
duration: 1000
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,13 @@ NPanel {
|
||||
searchDebounceTimer.restart()
|
||||
}
|
||||
|
||||
Keys.onDownPressed: {
|
||||
let currentView = screenRepeater.itemAt(currentScreenIndex)
|
||||
if (currentView && currentView.gridView) {
|
||||
currentView.gridView.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (searchInput.inputItem && searchInput.inputItem.visible) {
|
||||
searchInput.inputItem.forceActiveFocus()
|
||||
@@ -231,6 +238,7 @@ NPanel {
|
||||
// Component for each screen's wallpaper view
|
||||
component WallpaperScreenView: Item {
|
||||
property var targetScreen
|
||||
property alias gridView: wallpaperGridView
|
||||
|
||||
// Local reactive state for this screen
|
||||
property list<string> wallpapersList: []
|
||||
@@ -310,6 +318,9 @@ NPanel {
|
||||
visible: !WallpaperService.scanning
|
||||
interactive: true // Enable delegate recycling and native scrolling
|
||||
clip: true
|
||||
focus: true
|
||||
keyNavigationEnabled: true
|
||||
keyNavigationWraps: false
|
||||
|
||||
model: filteredWallpapers
|
||||
|
||||
@@ -324,6 +335,47 @@ NPanel {
|
||||
topMargin: Style.marginS * scaling
|
||||
bottomMargin: Style.marginS * scaling
|
||||
|
||||
highlightFollowsCurrentItem: true
|
||||
highlightMoveDuration: 150
|
||||
|
||||
highlight: Rectangle {
|
||||
color: Color.mSecondary
|
||||
opacity: 0.3
|
||||
radius: Style.radiusS * scaling
|
||||
z: 0
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
// Synchronize scroll with current item position
|
||||
if (currentIndex >= 0 && scrollView.contentItem) {
|
||||
let row = Math.floor(currentIndex / columns)
|
||||
let itemY = row * cellHeight
|
||||
let viewportTop = scrollView.contentItem.contentY
|
||||
let viewportBottom = viewportTop + scrollView.height
|
||||
|
||||
// If item is out of view, scroll
|
||||
if (itemY < viewportTop) {
|
||||
scrollView.contentItem.contentY = Math.max(0, itemY - cellHeight)
|
||||
} else if (itemY + cellHeight > viewportBottom) {
|
||||
scrollView.contentItem.contentY = itemY + cellHeight - scrollView.height + cellHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (event.key === Qt.Key_Return || event.key === Qt.Key_Space) {
|
||||
if (currentIndex >= 0 && currentIndex < filteredWallpapers.length) {
|
||||
let path = filteredWallpapers[currentIndex]
|
||||
if (Settings.data.wallpaper.setWallpaperOnAllMonitors) {
|
||||
WallpaperService.changeWallpaper(path, undefined)
|
||||
} else {
|
||||
WallpaperService.changeWallpaper(path, targetScreen.name)
|
||||
}
|
||||
}
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
@@ -399,6 +451,7 @@ NPanel {
|
||||
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
wallpaperGridView.currentIndex = index
|
||||
if (Settings.data.wallpaper.setWallpaperOnAllMonitors) {
|
||||
WallpaperService.changeWallpaper(wallpaperPath, undefined)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user