Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
Plasma Mobile
Commits
57192b77
Commit
57192b77
authored
Apr 07, 2022
by
Devin Lin
🎨
Browse files
actiondrawer: Add restricted permission mode, and implement on lockscreen
parent
3969973e
Pipeline
#160903
passed with stages
in 1 minute and 22 seconds
Changes
18
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
components/mobileshell/mobileshellplugin.cpp
View file @
57192b77
...
...
@@ -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"
);
...
...
components/mobileshell/qml/actiondrawer/ActionDrawer.qml
View file @
57192b77
...
...
@@ -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
}
}
}
...
...
components/mobileshell/qml/actiondrawer/ActionDrawerWindow.qml
0 → 100644
View file @
57192b77
/*
* 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
}
}
components/mobileshell/qml/actiondrawer/LandscapeContentContainer.qml
View file @
57192b77
...
...
@@ -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
...
...
components/mobileshell/qml/actiondrawer/PortraitContentContainer.qml
View file @
57192b77
...
...
@@ -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
...
...
components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml
View file @
57192b77
...
...
@@ -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
...
...
components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDelegate.qml
View file @
57192b77
...
...
@@ -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
,
...
...
components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDrawer.qml
View file @
57192b77
...
...
@@ -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
{
...
...
components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsPanel.qml
View file @
57192b77
...
...
@@ -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
{
...
...
components/mobileshell/qml/widgets/notifications/NotificationsWidget.qml
View file @
57192b77
...
...
@@ -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
();
}
...
...
components/mobileshell/resources.qrc
View file @
57192b77
...
...
@@ -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>
...
...
containments/panel/package/contents/ui/main.qml
View file @
57192b77
...
...
@@ -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.ActionDrawer
Window
{
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
;
...
...
look-and-feel/contents/lockscreen/HeaderComponent.qml
0 → 100644
View file @
57192b77
/*
* 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