mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-26 13:07:49 -04:00
358 lines
10 KiB
QML
358 lines
10 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import QtQuick.Window
|
|
import qs.Common
|
|
import qs.Modals
|
|
import qs.Modules.ControlCenter.Widgets
|
|
import qs.Modules.DankDash.Overview
|
|
import qs.Modules.Plugins
|
|
import qs.Modules.Settings.DesktopWidgetSettings
|
|
import qs.Modules.Settings.Widgets
|
|
import qs.Services
|
|
import qs.Widgets
|
|
import qs.DankCommon.Session
|
|
|
|
FocusScope {
|
|
id: root
|
|
readonly property var log: Log.scoped("LockScreenContent")
|
|
|
|
property string passwordBuffer: ""
|
|
property bool inputRevealed: false
|
|
signal inputRevealRequested(bool revealed)
|
|
|
|
function setInputRevealed(revealed) {
|
|
inputRevealRequested(revealed);
|
|
}
|
|
property bool demoMode: false
|
|
property var pam: demoPam
|
|
property string screenName: ""
|
|
property bool unlocking: false
|
|
property string pamState: ""
|
|
property bool lockerReadySent: false
|
|
property bool lockerReadyArmed: false
|
|
property var sessionLock: null
|
|
property Item authWidget: null
|
|
readonly property Item backgroundItem: background
|
|
readonly property bool backgroundReady: background.ready
|
|
readonly property string backgroundKey: background.renderKey
|
|
|
|
signal unlockRequested
|
|
signal passwordEdited(string text)
|
|
signal authFailed
|
|
|
|
function resetLockState() {
|
|
widgetLayer.refreshPlacement();
|
|
lockerReadySent = false;
|
|
lockerReadyArmed = true;
|
|
unlocking = false;
|
|
pamState = "";
|
|
if (pam)
|
|
pam.lockMessage = "";
|
|
}
|
|
|
|
function focusPasswordField() {
|
|
if (demoMode)
|
|
return;
|
|
authWidget?.focusPasswordField();
|
|
}
|
|
|
|
function showPowerMenu() {
|
|
if (demoMode)
|
|
return;
|
|
powerMenu.show();
|
|
}
|
|
|
|
function contentColor(mode, custom) {
|
|
switch (mode) {
|
|
case "primary":
|
|
return Theme.primary;
|
|
case "secondary":
|
|
return Theme.secondary;
|
|
case "custom":
|
|
return custom;
|
|
}
|
|
return Theme.lockScreenContentColor;
|
|
}
|
|
|
|
function addLockWidget(widgetType) {
|
|
const def = DesktopWidgetRegistry.getWidget(widgetType);
|
|
const instance = SettingsData.createDesktopWidgetInstance(widgetType, def?.name ?? widgetType, DesktopWidgetRegistry.getDefaultConfig(widgetType), "lockScreenWidgetInstances");
|
|
widgetLayer.pendingIds = widgetLayer.pendingIds.concat([instance.id]);
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
WeatherService.addRef();
|
|
UserInfoService.getUserInfo();
|
|
|
|
lockerReadyArmed = true;
|
|
}
|
|
|
|
Component.onDestruction: {
|
|
WeatherService.removeRef();
|
|
}
|
|
|
|
function sendLockerReadyOnce() {
|
|
if (root.demoMode)
|
|
return;
|
|
if (lockerReadySent)
|
|
return;
|
|
if (root.unlocking)
|
|
return;
|
|
lockerReadySent = true;
|
|
if (SessionService.loginctlAvailable && DMSService.apiVersion >= 2) {
|
|
DMSService.sendRequest("loginctl.lockerReady", null, resp => {
|
|
if (resp?.error)
|
|
log.warn("lockerReady failed:", resp.error);
|
|
else
|
|
log.debug("lockerReady sent (afterAnimating/afterRendering)");
|
|
});
|
|
}
|
|
}
|
|
|
|
function maybeSend() {
|
|
if (!lockerReadyArmed)
|
|
return;
|
|
if (root.unlocking)
|
|
return;
|
|
if (!root.visible || root.opacity <= 0)
|
|
return;
|
|
if (root.sessionLock && !root.sessionLock.secure)
|
|
return;
|
|
Qt.callLater(() => {
|
|
if (root.visible && root.opacity > 0 && !root.unlocking)
|
|
sendLockerReadyOnce();
|
|
});
|
|
}
|
|
|
|
Connections {
|
|
target: root.sessionLock
|
|
enabled: target !== null
|
|
function onSecureChanged() {
|
|
root.maybeSend();
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root.Window.window
|
|
enabled: target !== null
|
|
|
|
function onAfterAnimating() {
|
|
maybeSend();
|
|
}
|
|
function onAfterRendering() {
|
|
maybeSend();
|
|
}
|
|
}
|
|
|
|
onVisibleChanged: maybeSend()
|
|
onOpacityChanged: maybeSend()
|
|
|
|
LockScreenBackground {
|
|
id: background
|
|
anchors.fill: parent
|
|
screenName: root.screenName
|
|
}
|
|
|
|
// Grid keys live here because a selected widget holds active focus inside the layer, not the editor.
|
|
Keys.onPressed: event => {
|
|
if (!demoMode)
|
|
return;
|
|
switch (event.key) {
|
|
case Qt.Key_G:
|
|
widgetLayer.toggleGrid();
|
|
break;
|
|
case Qt.Key_Z:
|
|
widgetLayer.stepGrid(-10);
|
|
break;
|
|
case Qt.Key_X:
|
|
widgetLayer.stepGrid(10);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
event.accepted = true;
|
|
}
|
|
|
|
LockWidgetLayer {
|
|
id: widgetLayer
|
|
anchors.fill: parent
|
|
focus: true
|
|
screenName: root.screenName
|
|
lockHost: root
|
|
editMode: root.demoMode
|
|
bottomInset: editorLoader.item?.fabReserved ?? 0
|
|
onFocusStolen: root.focusPasswordField()
|
|
onOptionsRequested: instanceData => editorLoader.item?.showOptions(instanceData)
|
|
}
|
|
|
|
Pam {
|
|
id: demoPam
|
|
lockSecured: false
|
|
}
|
|
|
|
Connections {
|
|
target: root.pam
|
|
|
|
function onUnlockRequested() {
|
|
root.unlocking = true;
|
|
lockerReadyArmed = false;
|
|
root.passwordEdited("");
|
|
root.unlockRequested();
|
|
}
|
|
|
|
function onStateChanged() {
|
|
root.pamState = root.pam.state;
|
|
if (root.pam.state === "")
|
|
return;
|
|
root.unlocking = false;
|
|
root.authFailed();
|
|
placeholderDelay.restart();
|
|
root.passwordEdited("");
|
|
}
|
|
|
|
function onUnlockInProgressChanged() {
|
|
if (!root.pam.unlockInProgress && root.unlocking)
|
|
root.unlocking = false;
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: placeholderDelay
|
|
|
|
interval: 4000
|
|
onTriggered: root.pamState = ""
|
|
}
|
|
|
|
Loader {
|
|
id: editorLoader
|
|
anchors.fill: parent
|
|
active: root.demoMode
|
|
|
|
sourceComponent: FocusScope {
|
|
id: editor
|
|
|
|
property bool libraryOpen: false
|
|
readonly property real fabReserved: fabBar.reservedHeight
|
|
|
|
function closeLibrary() {
|
|
libraryOpen = false;
|
|
forceActiveFocus();
|
|
}
|
|
|
|
function showOptions(instanceData) {
|
|
optionsSheet.instanceId = instanceData?.id ?? "";
|
|
optionsSheet.opened = true;
|
|
}
|
|
|
|
focus: true
|
|
Component.onCompleted: forceActiveFocus()
|
|
|
|
Keys.onEscapePressed: {
|
|
if (editControls.pendingAction !== "") {
|
|
editControls.cancelConfirmation();
|
|
return;
|
|
}
|
|
if (libraryOpen) {
|
|
closeLibrary();
|
|
return;
|
|
}
|
|
root.unlockRequested();
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
visible: editor.libraryOpen
|
|
acceptedButtons: Qt.AllButtons
|
|
onClicked: editor.closeLibrary()
|
|
}
|
|
|
|
Loader {
|
|
anchors.centerIn: parent
|
|
active: editor.libraryOpen
|
|
|
|
sourceComponent: CcWidgetLibrary {
|
|
width: Math.min(implicitWidth, editor.width - Theme.spacingL * 2)
|
|
height: Math.min(implicitHeight, editor.height - Theme.spacingL * 2)
|
|
widgets: DesktopWidgetRegistry.registeredWidgetsList.filter(widget => widget.id !== "lockAuth" || !SettingsData.lockWidgetInstance("lockAuth")).map(widget => ({
|
|
id: widget.id,
|
|
text: widget.name,
|
|
icon: widget.icon,
|
|
description: widget.description
|
|
}))
|
|
Component.onCompleted: reset()
|
|
onChosen: widgetId => {
|
|
root.addLockWidget(widgetId);
|
|
editor.closeLibrary();
|
|
}
|
|
onDismissed: editor.closeLibrary()
|
|
}
|
|
}
|
|
|
|
DankBottomSheet {
|
|
id: optionsSheet
|
|
|
|
property string instanceId: ""
|
|
readonly property var instanceData: SettingsData.getDesktopWidgetInstance(instanceId)
|
|
readonly property var widgetDef: DesktopWidgetRegistry.getWidget(instanceData?.widgetType ?? "")
|
|
|
|
maximumWidth: Math.min(Theme.mediumBreakpoint, editor.width - Theme.spacingXL * 2)
|
|
topMargin: editor.height * 0.3
|
|
returnFocusItem: editor
|
|
title: instanceData?.name || widgetDef?.name || ""
|
|
onDismissRequested: opened = false
|
|
onActiveChanged: {
|
|
if (!active)
|
|
instanceId = "";
|
|
}
|
|
|
|
DesktopWidgetTypeSettings {
|
|
width: parent.width
|
|
instanceId: optionsSheet.instanceId
|
|
instanceData: optionsSheet.instanceData
|
|
widgetDef: optionsSheet.widgetDef
|
|
}
|
|
}
|
|
|
|
DesktopWidgetGridHint {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: fabBar.reservedHeight + Theme.spacingL
|
|
visible: fabBar.shown && (widgetLayer.selectedInstanceId !== "" || widgetLayer.interactingItem !== null)
|
|
gridEnabled: widgetLayer.gridEnabled
|
|
gridSize: widgetLayer.gridSize
|
|
}
|
|
|
|
SettingsFabBar {
|
|
id: fabBar
|
|
shown: !editor.libraryOpen && !optionsSheet.active
|
|
|
|
DashEditControls {
|
|
id: editControls
|
|
canClear: false
|
|
onAddRequested: editor.libraryOpen = true
|
|
onResetRequested: SettingsData.resetLockScreenWidgets()
|
|
onFinished: root.unlockRequested()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LockPowerMenu {
|
|
id: powerMenu
|
|
expressive: true
|
|
showLogout: true
|
|
onClosed: {
|
|
if (!demoMode)
|
|
Qt.callLater(() => root.focusPasswordField());
|
|
}
|
|
onSwitchUserRequested: {
|
|
switchUserPicker.showFromLockScreen();
|
|
}
|
|
}
|
|
|
|
SwitchUserModal {
|
|
id: switchUserPicker
|
|
}
|
|
}
|