mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
actiondrawer: Add restricted permission mode, and implement on lockscreen
This commit is contained in:
parent
3969973e51
commit
57192b772b
18 changed files with 323 additions and 116 deletions
|
|
@ -68,6 +68,7 @@ void MobileShellPlugin::registerTypes(const char *uri)
|
|||
// /actiondrawer
|
||||
qmlRegisterType(resolvePath("actiondrawer/ActionDrawer.qml"), uri, 1, 0, "ActionDrawer");
|
||||
qmlRegisterType(resolvePath("actiondrawer/ActionDrawerOpenSurface.qml"), uri, 1, 0, "ActionDrawerOpenSurface");
|
||||
qmlRegisterType(resolvePath("actiondrawer/ActionDrawerWindow.qml"), uri, 1, 0, "ActionDrawerWindow");
|
||||
|
||||
// /components
|
||||
qmlRegisterType(resolvePath("components/BaseItem.qml"), uri, 1, 0, "BaseItem");
|
||||
|
|
|
|||
|
|
@ -13,29 +13,35 @@ import QtQuick.Window 2.2
|
|||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
|
||||
import "../components" as Components
|
||||
|
||||
/**
|
||||
* Swipe top left - minimized quick settings, fully shown notifications list
|
||||
* Swipe top right - full quick settings, minimized notifications list
|
||||
* Swiping up and down on notifications list toggle minimized/maximized
|
||||
* Swiping up and down on panel hides and shows the panel
|
||||
*/
|
||||
|
||||
NanoShell.FullScreenOverlay {
|
||||
id: window
|
||||
Item {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* The model for the notification widget.
|
||||
*/
|
||||
property var notificationModel
|
||||
|
||||
/**
|
||||
* The model type for the notification widget.
|
||||
*/
|
||||
property var notificationModelType: MobileShell.NotificationsModelType.NotificationsModel
|
||||
|
||||
/**
|
||||
* The notification settings object to be used in the notification widget.
|
||||
*/
|
||||
property var notificationSettings
|
||||
|
||||
/**
|
||||
* Whether actions should be subject to restricted permissions (ex. lockscreen).
|
||||
*
|
||||
* The permissionsRequested() signal emits when authentication is requested.
|
||||
*/
|
||||
property bool restrictedPermissions: false
|
||||
|
||||
/**
|
||||
* The amount of pixels moved by touch/mouse in the process of opening/closing the panel.
|
||||
*/
|
||||
|
|
@ -56,6 +62,9 @@ NanoShell.FullScreenOverlay {
|
|||
*/
|
||||
property int direction: Components.Direction.None
|
||||
|
||||
/**
|
||||
* The mode of the action drawer (portrait or landscape).
|
||||
*/
|
||||
property int mode: (height > width && width <= largePortraitThreshold) ? ActionDrawer.Portrait : ActionDrawer.Landscape
|
||||
|
||||
/**
|
||||
|
|
@ -68,34 +77,48 @@ NanoShell.FullScreenOverlay {
|
|||
Landscape
|
||||
}
|
||||
|
||||
width: Screen.width
|
||||
height: Screen.height
|
||||
/**
|
||||
* Emitted when the drawer has closed.
|
||||
*/
|
||||
signal drawerClosed()
|
||||
|
||||
color: "transparent"
|
||||
/**
|
||||
* Emitted when the drawer has opened.
|
||||
*/
|
||||
signal drawerOpened()
|
||||
|
||||
/**
|
||||
* Emitted when permissions are requested (ex. unlocking the phone).
|
||||
*
|
||||
* Only gets emitted when restrictedPermissions is set to true.
|
||||
*/
|
||||
signal permissionsRequested()
|
||||
|
||||
/**
|
||||
* Runs the held notification action that was pending for authentication.
|
||||
*
|
||||
* Should be called by users if authentication is successful after permissionsRequested() was emitted.
|
||||
*/
|
||||
signal runPendingNotificationAction()
|
||||
|
||||
onOpenedChanged: {
|
||||
if (opened) flickable.focus = true;
|
||||
}
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
property real oldOffset
|
||||
onOffsetChanged: {
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
window.direction = (oldOffset === offset)
|
||||
root.direction = (oldOffset === offset)
|
||||
? Components.Direction.None
|
||||
: (offset > oldOffset ? Components.Direction.Down : Components.Direction.Up);
|
||||
|
||||
oldOffset = offset;
|
||||
|
||||
// close panel immediately after panel is not shown, and the flickable is not being dragged
|
||||
if (opened && window.offset <= 0 && !flickable.dragging && !closeAnim.running && !openAnim.running) {
|
||||
window.updateState();
|
||||
if (opened && root.offset <= 0 && !flickable.dragging && !closeAnim.running && !openAnim.running) {
|
||||
root.updateState();
|
||||
focus = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -125,25 +148,25 @@ NanoShell.FullScreenOverlay {
|
|||
cancelAnimations();
|
||||
let openThreshold = PlasmaCore.Units.gridUnit;
|
||||
|
||||
if (window.offset <= 0) {
|
||||
if (root.offset <= 0) {
|
||||
// close immediately, so that we don't have to wait PlasmaCore.Units.longDuration
|
||||
window.visible = false;
|
||||
root.visible = false;
|
||||
close();
|
||||
} else if (window.direction === Components.Direction.None || !window.opened) {
|
||||
if (window.offset < openThreshold) {
|
||||
} else if (root.direction === Components.Direction.None || !root.opened) {
|
||||
if (root.offset < openThreshold) {
|
||||
close();
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
} else if (window.offset > contentContainerLoader.maximizedQuickSettingsOffset) {
|
||||
} else if (root.offset > contentContainerLoader.maximizedQuickSettingsOffset) {
|
||||
expand();
|
||||
} else if (window.offset > contentContainerLoader.minimizedQuickSettingsOffset) {
|
||||
if (window.direction === Components.Direction.Down) {
|
||||
} else if (root.offset > contentContainerLoader.minimizedQuickSettingsOffset) {
|
||||
if (root.direction === Components.Direction.Down) {
|
||||
expand();
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
} else if (window.direction === Components.Direction.Down) {
|
||||
} else if (root.direction === Components.Direction.Down) {
|
||||
open();
|
||||
} else {
|
||||
close();
|
||||
|
|
@ -161,8 +184,8 @@ NanoShell.FullScreenOverlay {
|
|||
easing.type: Easing.InOutQuad
|
||||
to: 0
|
||||
onFinished: {
|
||||
window.visible = false;
|
||||
window.opened = false;
|
||||
root.visible = false;
|
||||
root.opened = false;
|
||||
}
|
||||
}
|
||||
PropertyAnimation on offset {
|
||||
|
|
@ -170,31 +193,31 @@ NanoShell.FullScreenOverlay {
|
|||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
to: contentContainerLoader.minimizedQuickSettingsOffset
|
||||
onFinished: window.opened = true
|
||||
onFinished: root.opened = true
|
||||
}
|
||||
PropertyAnimation on offset {
|
||||
id: expandAnim
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
to: contentContainerLoader.maximizedQuickSettingsOffset
|
||||
onFinished: window.opened = true;
|
||||
onFinished: root.opened = true;
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickable
|
||||
anchors.fill: parent
|
||||
|
||||
contentWidth: window.width
|
||||
contentHeight: window.height + 999999
|
||||
contentWidth: root.width
|
||||
contentHeight: root.height + 999999
|
||||
contentY: contentHeight / 2
|
||||
|
||||
// if the recent window.offset change was due to this flickable
|
||||
// if the recent root.offset change was due to this flickable
|
||||
property bool offsetChangedDueToContentY: false
|
||||
Connections {
|
||||
target: window
|
||||
target: root
|
||||
function onOffsetChanged() {
|
||||
if (!flickable.offsetChangedDueToContentY) {
|
||||
// ensure the flickable's contentY is not moving when other sources change window.offset
|
||||
// ensure the flickable's contentY is not moving when other sources change root.offset
|
||||
flickable.cancelFlick();
|
||||
}
|
||||
flickable.offsetChangedDueToContentY = false;
|
||||
|
|
@ -204,34 +227,34 @@ NanoShell.FullScreenOverlay {
|
|||
property real oldContentY
|
||||
onContentYChanged: {
|
||||
offsetChangedDueToContentY = true;
|
||||
window.offset += oldContentY - contentY;
|
||||
root.offset += oldContentY - contentY;
|
||||
oldContentY = contentY;
|
||||
}
|
||||
|
||||
onMovementStarted: {
|
||||
window.cancelAnimations();
|
||||
window.dragging = true;
|
||||
root.cancelAnimations();
|
||||
root.dragging = true;
|
||||
}
|
||||
onFlickStarted: window.dragging = true;
|
||||
onFlickStarted: root.dragging = true;
|
||||
onMovementEnded: {
|
||||
window.dragging = false;
|
||||
window.updateState();
|
||||
root.dragging = false;
|
||||
root.updateState();
|
||||
}
|
||||
onFlickEnded: {
|
||||
window.dragging = true;
|
||||
window.updateState();
|
||||
root.dragging = true;
|
||||
root.updateState();
|
||||
}
|
||||
|
||||
onDraggingChanged: {
|
||||
if (!dragging) {
|
||||
window.dragging = false;
|
||||
root.dragging = false;
|
||||
flickable.cancelFlick();
|
||||
window.updateState();
|
||||
root.updateState();
|
||||
}
|
||||
}
|
||||
|
||||
// the flickable is only used to measure drag changes, we implement our own UI component movements
|
||||
// the window element is not affected by contentY changes (it's effectively anchored to the flickable)
|
||||
// the root element is not affected by contentY changes (it's effectively anchored to the flickable)
|
||||
Loader {
|
||||
id: contentContainerLoader
|
||||
|
||||
|
|
@ -239,27 +262,27 @@ NanoShell.FullScreenOverlay {
|
|||
property real maximizedQuickSettingsOffset: item ? item.maximizedQuickSettingsOffset : 0
|
||||
|
||||
y: flickable.contentY
|
||||
width: window.width
|
||||
height: window.height
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
sourceComponent: window.mode == ActionDrawer.Portrait ? portraitContentContainer : landscapeContentContainer
|
||||
sourceComponent: root.mode == ActionDrawer.Portrait ? portraitContentContainer : landscapeContentContainer
|
||||
}
|
||||
|
||||
Component {
|
||||
id: portraitContentContainer
|
||||
PortraitContentContainer {
|
||||
actionDrawer: window
|
||||
width: window.width
|
||||
height: window.height
|
||||
actionDrawer: root
|
||||
width: root.width
|
||||
height: root.height
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: landscapeContentContainer
|
||||
LandscapeContentContainer {
|
||||
actionDrawer: window
|
||||
width: window.width
|
||||
height: window.height
|
||||
actionDrawer: root
|
||||
width: root.width
|
||||
height: root.height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
import "../components" as Components
|
||||
|
||||
/**
|
||||
* Window with the ActionDrawer component embedded in it.
|
||||
*
|
||||
* Used for overlaying the ActionDrawer if the original window does not cover
|
||||
* the whole screen.
|
||||
*/
|
||||
NanoShell.FullScreenOverlay {
|
||||
id: window
|
||||
|
||||
/**
|
||||
* The ActionDrawer component.
|
||||
*/
|
||||
property alias actionDrawer: drawer
|
||||
|
||||
visible: drawer.visible
|
||||
width: Screen.width
|
||||
height: Screen.height
|
||||
|
||||
color: "transparent"
|
||||
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
drawer.close();
|
||||
}
|
||||
}
|
||||
|
||||
ActionDrawer {
|
||||
id: drawer
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,18 @@ PlasmaCore.ColorScope {
|
|||
MobileShell.NotificationsWidget {
|
||||
id: notificationWidget
|
||||
historyModel: root.actionDrawer.notificationModel
|
||||
historyModelType: root.actionDrawer.notificationModelType
|
||||
notificationSettings: root.actionDrawer.notificationSettings
|
||||
actionsRequireUnlock: root.actionDrawer.restrictedPermissions
|
||||
onUnlockRequested: root.actionDrawer.permissionsRequested()
|
||||
|
||||
Connections {
|
||||
target: root.actionDrawer
|
||||
|
||||
function onRunPendingNotificationAction() {
|
||||
notificationWidget.runPendingAction();
|
||||
}
|
||||
}
|
||||
|
||||
// don't allow notifications widget to get too wide
|
||||
Layout.maximumWidth: PlasmaCore.Units.gridUnit * 25
|
||||
|
|
|
|||
|
|
@ -79,7 +79,18 @@ PlasmaCore.ColorScope {
|
|||
MobileShell.NotificationsWidget {
|
||||
id: notificationWidget
|
||||
historyModel: root.actionDrawer.notificationModel
|
||||
historyModelType: root.actionDrawer.notificationModelType
|
||||
notificationSettings: root.actionDrawer.notificationSettings
|
||||
actionsRequireUnlock: root.actionDrawer.restrictedPermissions
|
||||
onUnlockRequested: root.actionDrawer.permissionsRequested()
|
||||
|
||||
Connections {
|
||||
target: root.actionDrawer
|
||||
|
||||
function onRunPendingNotificationAction() {
|
||||
notificationWidget.runPendingAction();
|
||||
}
|
||||
}
|
||||
|
||||
anchors {
|
||||
top: quickSettings.top
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ Item {
|
|||
padding: PlasmaCore.Units.smallSpacing
|
||||
|
||||
contentItem: QuickSettingsFullDelegate {
|
||||
restrictedPermissions: actionDrawer.restrictedPermissions
|
||||
|
||||
text: modelData.text
|
||||
status: modelData.status
|
||||
icon: modelData.icon
|
||||
|
|
@ -119,6 +121,8 @@ Item {
|
|||
visible: index <= root.minimizedColumns
|
||||
|
||||
contentItem: QuickSettingsMinimizedDelegate {
|
||||
restrictedPermissions: actionDrawer.restrictedPermissions
|
||||
|
||||
text: modelData.text
|
||||
status: modelData.status
|
||||
icon: modelData.icon
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import "../../components" as Components
|
|||
Components.BaseItem {
|
||||
id: root
|
||||
|
||||
required property bool restrictedPermissions
|
||||
|
||||
// Model interface
|
||||
required property string text
|
||||
required property string status
|
||||
|
|
@ -61,7 +63,7 @@ Components.BaseItem {
|
|||
root.toggle();
|
||||
} else if (root.toggleFunction) {
|
||||
root.toggleFunction();
|
||||
} else if (root.settingsCommand) {
|
||||
} else if (root.settingsCommand && !root.restrictedPermissions) {
|
||||
closeRequested();
|
||||
MobileShell.HomeScreenControls.openAppLaunchAnimation(
|
||||
root.icon,
|
||||
|
|
@ -74,7 +76,7 @@ Components.BaseItem {
|
|||
}
|
||||
|
||||
function delegatePressAndHold() {
|
||||
if (root.settingsCommand) {
|
||||
if (root.settingsCommand && !root.restrictedPermissions) {
|
||||
closeRequested();
|
||||
MobileShell.HomeScreenControls.openAppLaunchAnimation(
|
||||
root.icon,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ Components.BaseItem {
|
|||
backgroundColor: "transparent"
|
||||
showSecondRow: true
|
||||
showDropShadow: false
|
||||
|
||||
// security reasons, system tray also doesn't work on lockscreen
|
||||
disableSystemTray: actionDrawer.restrictedPermissions
|
||||
}
|
||||
|
||||
QuickSettings {
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ Components.BaseItem {
|
|||
showSecondRow: false
|
||||
showDropShadow: false
|
||||
showTime: false
|
||||
|
||||
// security reasons, system tray also doesn't work on lockscreen
|
||||
disableSystemTray: actionDrawer.restrictedPermissions
|
||||
}
|
||||
|
||||
PlasmaComponents.ScrollView {
|
||||
|
|
|
|||
|
|
@ -60,8 +60,17 @@ Item {
|
|||
WatchedNotificationsModel // used on the lockscreen
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal emitted when authentication is requested for an action.
|
||||
* Listeners should call runPendingAction() if authentication is successful.
|
||||
*
|
||||
* Only emitted if actionsRequireUnlock is enabled.
|
||||
*/
|
||||
signal unlockRequested()
|
||||
|
||||
/**
|
||||
* Run pending action that was pending for authentication when unlockRequested() was emitted.
|
||||
*/
|
||||
function runPendingAction() {
|
||||
list.pendingNotificationWithAction.runPendingAction();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
<file>qml/actiondrawer/ActionDrawer.qml</file>
|
||||
<file>qml/actiondrawer/ActionDrawerOpenSurface.qml</file>
|
||||
<file>qml/actiondrawer/ActionDrawerWindow.qml</file>
|
||||
<file>qml/actiondrawer/LandscapeContentContainer.qml</file>
|
||||
<file>qml/actiondrawer/PortraitContentContainer.qml</file>
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Item {
|
|||
Binding {
|
||||
target: MobileShell.TopPanelControls
|
||||
property: "inSwipe"
|
||||
value: drawer.dragging
|
||||
value: drawer.actionDrawer.dragging
|
||||
}
|
||||
Binding {
|
||||
target: MobileShell.TopPanelControls
|
||||
|
|
@ -62,10 +62,10 @@ Item {
|
|||
swipeArea.updateOffset(offsetY);
|
||||
}
|
||||
function onCloseActionDrawer() {
|
||||
drawer.close();
|
||||
drawer.actionDrawer.close();
|
||||
}
|
||||
function onOpenActionDrawer() {
|
||||
drawer.open();
|
||||
drawer.actionDrawer.open();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,30 +88,30 @@ Item {
|
|||
|
||||
MobileShell.ActionDrawerOpenSurface {
|
||||
id: swipeArea
|
||||
actionDrawer: drawer
|
||||
actionDrawer: drawer.actionDrawer
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
// swipe-down drawer component
|
||||
MobileShell.ActionDrawer {
|
||||
MobileShell.ActionDrawerWindow {
|
||||
id: drawer
|
||||
|
||||
notificationSettings: NotificationManager.Settings {}
|
||||
actionDrawer.notificationSettings: NotificationManager.Settings {}
|
||||
|
||||
notificationModel: NotificationManager.Notifications {
|
||||
actionDrawer.notificationModel: NotificationManager.Notifications {
|
||||
showExpired: true
|
||||
showDismissed: true
|
||||
showJobs: drawer.notificationSettings.jobsInNotifications
|
||||
showJobs: drawer.actionDrawer.notificationSettings.jobsInNotifications
|
||||
sortMode: NotificationManager.Notifications.SortByTypeAndUrgency
|
||||
groupMode: NotificationManager.Notifications.GroupApplicationsFlat
|
||||
groupLimit: 2
|
||||
expandUnread: true
|
||||
blacklistedDesktopEntries: drawer.notificationSettings.historyBlacklistedApplications
|
||||
blacklistedNotifyRcNames: drawer.notificationSettings.historyBlacklistedServices
|
||||
blacklistedDesktopEntries: drawer.actionDrawer.notificationSettings.historyBlacklistedApplications
|
||||
blacklistedNotifyRcNames: drawer.actionDrawer.notificationSettings.historyBlacklistedServices
|
||||
urgencies: {
|
||||
var urgencies = NotificationManager.Notifications.CriticalUrgency
|
||||
| NotificationManager.Notifications.NormalUrgency;
|
||||
if (drawer.notificationSettings.lowPriorityHistory) {
|
||||
if (drawer.actionDrawer.notificationSettings.lowPriorityHistory) {
|
||||
urgencies |= NotificationManager.Notifications.LowUrgency;
|
||||
}
|
||||
return urgencies;
|
||||
|
|
|
|||
87
look-and-feel/contents/lockscreen/HeaderComponent.qml
Normal file
87
look-and-feel/contents/lockscreen/HeaderComponent.qml
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
|
||||
import org.kde.notificationmanager 1.0 as NotificationManager
|
||||
|
||||
Loader {
|
||||
id: root
|
||||
|
||||
required property real openFactor
|
||||
|
||||
readonly property real statusBarHeight: PlasmaCore.Units.gridUnit * 1.25
|
||||
|
||||
property var notificationsModel: []
|
||||
|
||||
signal passwordRequested()
|
||||
|
||||
active: true
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: Item {
|
||||
MobileShell.StatusBar {
|
||||
id: statusBar
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
height: root.statusBarHeight
|
||||
|
||||
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
||||
backgroundColor: "transparent"
|
||||
|
||||
showSecondRow: false
|
||||
showDropShadow: true
|
||||
showTime: false
|
||||
disableSystemTray: true // HACK: prevent SIGABRT
|
||||
}
|
||||
|
||||
MobileShell.ActionDrawerOpenSurface {
|
||||
id: swipeArea
|
||||
actionDrawer: drawer
|
||||
anchors.fill: statusBar
|
||||
}
|
||||
|
||||
// swipe-down drawer component
|
||||
MobileShell.ActionDrawer {
|
||||
id: drawer
|
||||
anchors.fill: parent
|
||||
|
||||
restrictedPermissions: true
|
||||
|
||||
notificationSettings: NotificationManager.Settings {}
|
||||
notificationModel: root.notificationsModel
|
||||
notificationModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel
|
||||
|
||||
property bool requestNotificationAction: false
|
||||
|
||||
onPermissionsRequested: {
|
||||
requestNotificationAction = true;
|
||||
root.passwordRequested();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: authenticator
|
||||
function onSucceeded() {
|
||||
// run pending action if successfully unlocked
|
||||
if (drawer.requestNotificationAction) {
|
||||
drawer.runPendingAction();
|
||||
drawer.requestNotificationAction = false;
|
||||
}
|
||||
}
|
||||
function onFailed() {
|
||||
drawer.requestNotificationAction = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,17 @@ PlasmaCore.ColorScope {
|
|||
blur: root.notificationsShown || root.drawerOpen // only blur once animation finished for performance
|
||||
}
|
||||
}
|
||||
|
||||
// header bar and action drawer
|
||||
HeaderComponent {
|
||||
id: headerBar
|
||||
z: 1 // on top of flick area
|
||||
anchors.fill: parent
|
||||
|
||||
openFactor: flickable.openFactor
|
||||
notificationsModel: notifModel
|
||||
onPasswordRequested: root.askPassword()
|
||||
}
|
||||
|
||||
FlickContainer {
|
||||
id: flickable
|
||||
|
|
@ -69,23 +80,20 @@ PlasmaCore.ColorScope {
|
|||
height: flickable.height
|
||||
y: flickable.contentY // effectively anchored to the screen
|
||||
|
||||
// header bar
|
||||
StatusBarComponent {
|
||||
id: statusBar
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
opacity: 1 - flickable.openFactor
|
||||
}
|
||||
|
||||
LockScreenNarrowContent {
|
||||
id: phoneComponent
|
||||
|
||||
visible: !isWidescreen
|
||||
active: visible
|
||||
opacity: 1 - flickable.openFactor
|
||||
|
||||
fullHeight: root.height
|
||||
|
||||
notificationsModel: notifModel
|
||||
onNotificationsShownChanged: root.notificationsShown = notificationsShown
|
||||
|
||||
onPasswordRequested: root.askPassword()
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: scrollUpIcon.top
|
||||
anchors.left: parent.left
|
||||
|
|
@ -101,7 +109,13 @@ PlasmaCore.ColorScope {
|
|||
active: visible
|
||||
opacity: 1 - flickable.openFactor
|
||||
|
||||
anchors.top: statusBar.bottom
|
||||
notificationsModel: notifModel
|
||||
onNotificationsShownChanged: root.notificationsShown = notificationsShown
|
||||
|
||||
onPasswordRequested: root.askPassword()
|
||||
|
||||
anchors.topMargin: headerBar.statusBarHeight
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: scrollUpIcon.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
|
|
|||
|
|
@ -14,11 +14,15 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
|||
|
||||
Loader {
|
||||
id: root
|
||||
asynchronous: true
|
||||
|
||||
property var notificationsModel: []
|
||||
|
||||
property real fullHeight
|
||||
property bool notificationsShown: false
|
||||
|
||||
property real fullHeight
|
||||
|
||||
signal passwordRequested()
|
||||
|
||||
// avoid topMargin animation when item is being loaded
|
||||
onLoaded: loadTimer.restart();
|
||||
Timer {
|
||||
|
|
@ -29,6 +33,7 @@ Loader {
|
|||
// move while swiping up
|
||||
transform: Translate { y: Math.round((1 - phoneComponent.opacity) * (-root.height / 6)) }
|
||||
|
||||
asynchronous: true
|
||||
sourceComponent: Item {
|
||||
ColumnLayout {
|
||||
id: column
|
||||
|
|
@ -62,6 +67,8 @@ Loader {
|
|||
|
||||
NotificationsComponent {
|
||||
id: notificationComponent
|
||||
notificationsModel: root.notificationsModel
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: PlasmaCore.Units.gridUnit * (25 + 2) // clip margins
|
||||
|
|
@ -69,6 +76,7 @@ Loader {
|
|||
leftMargin: PlasmaCore.Units.gridUnit
|
||||
rightMargin: PlasmaCore.Units.gridUnit
|
||||
|
||||
onPasswordRequested: root.passwordRequested()
|
||||
onNotificationsShownChanged: root.notificationsShown = notificationsShown
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,14 +13,18 @@ import org.kde.notificationmanager 1.1 as Notifications
|
|||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
|
||||
Loader {
|
||||
id: tabletComponent
|
||||
asynchronous: true
|
||||
id: root
|
||||
|
||||
property var notificationsModel: []
|
||||
|
||||
property bool notificationsShown: false
|
||||
|
||||
signal passwordRequested()
|
||||
|
||||
asynchronous: true
|
||||
sourceComponent: Item {
|
||||
Item {
|
||||
id: tabletClockComponent
|
||||
id: clock
|
||||
width: parent.width / 2
|
||||
anchors {
|
||||
top: parent.top
|
||||
|
|
@ -54,13 +58,14 @@ Loader {
|
|||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: tabletClockComponent.right
|
||||
left: clock.right
|
||||
right: parent.right
|
||||
rightMargin: PlasmaCore.Units.gridUnit
|
||||
}
|
||||
|
||||
NotificationsComponent {
|
||||
id: notificationComponent
|
||||
notificationsModel: root.notificationsModel
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -75,6 +80,7 @@ Loader {
|
|||
bottomMargin: PlasmaCore.Units.gridUnit
|
||||
topMargin: PlasmaCore.Units.gridUnit
|
||||
|
||||
onPasswordRequested: root.passwordRequested()
|
||||
onNotificationsShownChanged: root.notificationsShown = notificationsShown
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,12 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
|||
Rectangle {
|
||||
id: rect
|
||||
|
||||
property var notificationsModel: []
|
||||
|
||||
readonly property bool notificationsShown: notificationsList.hasNotifications
|
||||
|
||||
signal passwordRequested()
|
||||
|
||||
property real leftMargin: 0
|
||||
property real rightMargin: 0
|
||||
property real topMargin: 0
|
||||
|
|
@ -54,13 +58,13 @@ Rectangle {
|
|||
|
||||
historyModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel
|
||||
actionsRequireUnlock: true
|
||||
historyModel: notifModel
|
||||
historyModel: rect.notificationsModel
|
||||
|
||||
property bool requestNotificationAction: false
|
||||
|
||||
onUnlockRequested: {
|
||||
requestNotificationAction = true;
|
||||
root.askPassword();
|
||||
root.passwordRequested();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
|
||||
Loader {
|
||||
active: true
|
||||
asynchronous: true
|
||||
height: PlasmaCore.Units.gridUnit * 1.25
|
||||
|
||||
sourceComponent: MobileShell.StatusBar {
|
||||
id: statusBar
|
||||
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
||||
backgroundColor: "transparent"
|
||||
|
||||
showSecondRow: false
|
||||
showDropShadow: true
|
||||
showTime: false
|
||||
disableSystemTray: true // HACK: prevent SIGABRT
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue