actiondrawer: Share components between portrait and landscape

This avoids having to completely load the quicksettings, status bar,
media widget, and notifications list from scratch when the view changes.
We now have a single instance of each component which is reparented to
the new view (portrait/landscape).

Fixes https://invent.kde.org/plasma/plasma-mobile/-/issues/406
This commit is contained in:
Devin Lin 2024-10-30 22:05:44 -07:00
parent 6da6f3fd55
commit 76882f5b5d
11 changed files with 234 additions and 203 deletions

View file

@ -19,7 +19,13 @@ import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS
Item { Item {
id: root id: root
visible: false /*
* The intended visiblity of the action drawer.
*
* This is separate from "visible" in order to avoid having to set
* item visiblity when its on its own window (wasteful since the window itself can be shown/hidden).
*/
property bool intendedToBeVisible: false
/** /**
* The model for the notification widget. * The model for the notification widget.
@ -34,7 +40,7 @@ Item {
/** /**
* The model for the quick settings. * The model for the quick settings.
*/ */
property var quickSettingsModel: QS.QuickSettingsModel {} property QS.QuickSettingsModel quickSettingsModel: QS.QuickSettingsModel {}
/** /**
* The notification settings object to be used in the notification widget. * The notification settings object to be used in the notification widget.
@ -77,7 +83,7 @@ Item {
/** /**
* The notifications widget being shown. May be null. * The notifications widget being shown. May be null.
*/ */
property var notificationsWidget: contentContainerLoader.item.notificationsWidget property var notificationsWidget: contentContainer.notificationsWidget
/** /**
* The mode of the action drawer (portrait or landscape). * The mode of the action drawer (portrait or landscape).
@ -178,17 +184,17 @@ Item {
if (root.offset <= 0) { if (root.offset <= 0) {
// close immediately, so that we don't have to wait Kirigami.Units.longDuration // close immediately, so that we don't have to wait Kirigami.Units.longDuration
root.visible = false; root.intendedToBeVisible = false;
close(); close();
} else if (root.direction === MobileShell.Direction.None || !root.opened) { } else if (root.direction === MobileShell.Direction.None || !root.opened) {
// if the panel has not been opened yet, run open animation only if drag passed threshold // if the panel has not been opened yet, run open animation only if drag passed threshold
(root.offset < openThreshold) ? close() : open(); (root.offset < openThreshold) ? close() : open();
} else if (root.offset > contentContainerLoader.maximizedQuickSettingsOffset) { } else if (root.offset > contentContainer.maximizedQuickSettingsOffset) {
// if drag has gone past the fully expanded view // if drag has gone past the fully expanded view
expand(); expand();
} else if (root.offset > contentContainerLoader.minimizedQuickSettingsOffset) { } else if (root.offset > contentContainer.minimizedQuickSettingsOffset) {
// if drag is between pinned view and fully expanded view // if drag is between pinned view and fully expanded view
if (root.direction === MobileShell.Direction.Down) { if (root.direction === MobileShell.Direction.Down) {
expand(); expand();
@ -229,13 +235,13 @@ Item {
State { State {
name: "open" name: "open"
PropertyChanges { PropertyChanges {
target: root; offset: contentContainerLoader.minimizedQuickSettingsOffset target: root; offset: contentContainer.minimizedQuickSettingsOffset
} }
}, },
State { State {
name: "expand" name: "expand"
PropertyChanges { PropertyChanges {
target: root; offset: contentContainerLoader.maximizedQuickSettingsOffset target: root; offset: contentContainer.maximizedQuickSettingsOffset
} }
} }
] ]
@ -250,7 +256,7 @@ Item {
script: { script: {
if (root.state != "") { if (root.state != "") {
if (root.offset <= 0) { if (root.offset <= 0) {
root.visible = false; root.intendedToBeVisible = false;
root.opened = false; root.opened = false;
root.state = ""; root.state = "";
} else { } else {
@ -289,35 +295,12 @@ Item {
onTouchpadScrollEnded: endSwipe() onTouchpadScrollEnded: endSwipe()
onTouchpadScrollMove: (totalDeltaX, totalDeltaY, deltaX, deltaY) => moveSwipe(totalDeltaX, totalDeltaY, deltaX, deltaY) onTouchpadScrollMove: (totalDeltaX, totalDeltaY, deltaX, deltaY) => moveSwipe(totalDeltaX, totalDeltaY, deltaX, deltaY)
Loader { ContentContainer {
id: contentContainerLoader id: contentContainer
anchors.fill: parent anchors.fill: parent
property real minimizedQuickSettingsOffset: item ? item.minimizedQuickSettingsOffset : 0 actionDrawer: root
property real maximizedQuickSettingsOffset: item ? item.maximizedQuickSettingsOffset : 0 quickSettingsModel: root.quickSettingsModel
asynchronous: true
sourceComponent: root.mode == ActionDrawer.Portrait ? portraitContentContainer : landscapeContentContainer
}
Component {
id: portraitContentContainer
PortraitContentContainer {
actionDrawer: root
width: root.width
height: root.height
quickSettingsModel: root.quickSettingsModel
}
}
Component {
id: landscapeContentContainer
LandscapeContentContainer {
actionDrawer: root
width: root.width
height: root.height
quickSettingsModel: root.quickSettingsModel
}
} }
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Devin Lin <devin@kde.org> * SPDX-FileCopyrightText: 2021-2024 Devin Lin <devin@kde.org>
* *
* SPDX-License-Identifier: LGPL-2.0-or-later * SPDX-License-Identifier: LGPL-2.0-or-later
*/ */
@ -19,7 +19,7 @@ MobileShell.SwipeArea {
required property ActionDrawer actionDrawer required property ActionDrawer actionDrawer
function startSwipe() { function startSwipe() {
if (actionDrawer.visible) { if (actionDrawer.intendedToBeVisible) {
// ensure the action drawer state is consistent // ensure the action drawer state is consistent
actionDrawer.closeImmediately(); actionDrawer.closeImmediately();
} }
@ -30,7 +30,7 @@ MobileShell.SwipeArea {
// must be after properties other are set, we cannot have actionDrawer.updateState() be called // must be after properties other are set, we cannot have actionDrawer.updateState() be called
actionDrawer.offset = 0; actionDrawer.offset = 0;
actionDrawer.oldOffset = 0; actionDrawer.oldOffset = 0;
actionDrawer.visible = true; actionDrawer.intendedToBeVisible = true;
} }
function startSwipeWithPoint(point) { function startSwipeWithPoint(point) {

View file

@ -26,7 +26,7 @@ NanoShell.FullScreenOverlay {
*/ */
property alias actionDrawer: drawer property alias actionDrawer: drawer
visible: drawer.visible visible: drawer.intendedToBeVisible
width: Screen.width width: Screen.width
height: Screen.height height: Screen.height

View file

@ -0,0 +1,130 @@
// SPDX-FileCopyrightText: 2021-2024 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.private.mobileshell as MobileShell
import org.kde.plasma.components 3.0 as PC3
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS
/**
* Root element that contains all the ActionDrawer's contents, and is anchored to the screen.
*/
Rectangle {
id: root
required property var actionDrawer
required property QS.QuickSettingsModel quickSettingsModel
readonly property real minimizedQuickSettingsOffset: contentContainerLoader.minimizedQuickSettingsOffset
readonly property real maximizedQuickSettingsOffset: contentContainerLoader.maximizedQuickSettingsOffset
function applyMinMax(val) {
return Math.max(0, Math.min(1, val));
}
// Background color
color: Qt.rgba(Kirigami.Theme.backgroundColor.r,
Kirigami.Theme.backgroundColor.g,
Kirigami.Theme.backgroundColor.b,
(root.actionDrawer.mode == ActionDrawer.Portrait || notificationWidget.hasNotifications) ? 0.95 : 0.9)
Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration } }
opacity: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset))
// Layout that switches between landscape and portrait mode
Loader {
id: contentContainerLoader
anchors.fill: parent
readonly property real minimizedQuickSettingsOffset: item ? item.minimizedQuickSettingsOffset : 0
readonly property real maximizedQuickSettingsOffset: item ? item.maximizedQuickSettingsOffset : 0
readonly property real offsetDist: root.actionDrawer.offset - minimizedQuickSettingsOffset
readonly property real totalOffsetDist: maximizedQuickSettingsOffset - minimizedQuickSettingsOffset
readonly property real minimizedToFullProgress: root.actionDrawer.openToPinnedMode ? (root.actionDrawer.opened ? applyMinMax(offsetDist / totalOffsetDist) : 0) : 1
asynchronous: true
sourceComponent: root.actionDrawer.mode == ActionDrawer.Portrait ? portraitContentContainer : landscapeContentContainer
}
Component {
id: portraitContentContainer
PortraitContentContainer {
actionDrawer: root.actionDrawer
width: root.width
height: root.height
quickSettings: root.quickSettings
statusBar: root.statusBar
mediaControlsWidget: root.mediaControlsWidget
notificationsWidget: root.notificationsWidget
}
}
Component {
id: landscapeContentContainer
LandscapeContentContainer {
actionDrawer: root.actionDrawer
width: root.width
height: root.height
quickSettings: root.quickSettings
statusBar: root.statusBar
mediaControlsWidget: root.mediaControlsWidget
notificationsWidget: root.notificationsWidget
}
}
// Components shared between the two layouts.
// This allows us to avoid having to reload the components every time the screen size changes.
property MobileShell.QuickSettings quickSettings: MobileShell.QuickSettings {
id: quickSettings
actionDrawer: root.actionDrawer
quickSettingsModel: root.quickSettingsModel
fullViewProgress: (root.actionDrawer.mode == ActionDrawer.Portrait) ? contentContainerLoader.minimizedToFullProgress : 1.0
}
property MobileShell.StatusBar statusBar: MobileShell.StatusBar {
id: statusBar
Kirigami.Theme.colorSet: Kirigami.Theme.Window
Kirigami.Theme.inherit: false
backgroundColor: "transparent"
showSecondRow: root.actionDrawer.mode == ActionDrawer.Portrait
showDropShadow: false
showTime: root.actionDrawer.mode == ActionDrawer.Portrait
// security reasons, system tray also doesn't work on lockscreen
disableSystemTray: root.actionDrawer.restrictedPermissions
}
property MobileShell.MediaControlsWidget mediaControlsWidget: MobileShell.MediaControlsWidget {
id: mediaWidget
inActionDrawer: true
}
property MobileShell.NotificationsWidget notificationsWidget: 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();
}
}
onBackgroundClicked: root.actionDrawer.close();
}
}

View file

@ -1,13 +1,10 @@
/* // SPDX-FileCopyrightText: 2021-2024 Devin Lin <devin@kde.org>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org> // SPDX-License-Identifier: LGPL-2.0-or-later
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.15 import QtQuick
import QtQuick.Controls 2.15 import QtQuick.Controls as QQC2
import QtQuick.Layouts 1.1 import QtQuick.Layouts
import QtQuick.Window 2.2 import QtQuick.Window
import org.kde.kirigami 2.12 as Kirigami import org.kde.kirigami 2.12 as Kirigami
@ -24,32 +21,21 @@ Item {
id: root id: root
required property var actionDrawer required property var actionDrawer
property QS.QuickSettingsModel quickSettingsModel
property alias notificationsWidget: notificationWidget property alias quickSettings: quickSettingsPanel.quickSettings
property alias statusBar: quickSettingsPanel.statusBar
property alias mediaControlsWidget: mediaControlsWidgetProxy.contentItem
property alias notificationsWidget: notificationWidgetProxy.contentItem
readonly property real minimizedQuickSettingsOffset: height readonly property real minimizedQuickSettingsOffset: height
readonly property real maximizedQuickSettingsOffset: height readonly property real maximizedQuickSettingsOffset: height
readonly property bool isOnLargeScreen: width > quickSettings.width * 2.5 readonly property bool isOnLargeScreen: width > quickSettingsPanel.width * 2.5
readonly property real minWidthHeight: Math.min(root.width, root.height) readonly property real minWidthHeight: Math.min(root.width, root.height)
readonly property real opacityValue: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset)) readonly property real opacityValue: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset))
Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
// fullscreen background
Rectangle {
anchors.fill: parent
// darken if there are notifications
color: Qt.rgba(Kirigami.Theme.backgroundColor.r,
Kirigami.Theme.backgroundColor.g,
Kirigami.Theme.backgroundColor.b,
notificationWidget.hasNotifications ? 0.95 : 0.9)
Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration } }
opacity: opacityValue
}
P5Support.DataSource { P5Support.DataSource {
id: timeSource id: timeSource
engine: "time" engine: "time"
@ -71,32 +57,17 @@ Item {
spacing: 0 spacing: 0
anchors { anchors {
top: mediaWidget.bottom top: mediaControlsWidgetProxy.bottom
topMargin: 0 topMargin: 0
bottom: parent.bottom bottom: parent.bottom
bottomMargin: 0 bottomMargin: 0
right: quickSettings.left right: quickSettingsPanel.left
left: parent.left left: parent.left
} }
anchors.margins: minWidthHeight * 0.06 anchors.margins: minWidthHeight * 0.06
MobileShell.NotificationsWidget { MobileShell.BaseItem {
id: notificationWidget id: notificationWidgetProxy
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();
}
}
onBackgroundClicked: root.actionDrawer.close();
// don't allow notifications widget to get too wide // don't allow notifications widget to get too wide
Layout.maximumWidth: Kirigami.Units.gridUnit * 25 Layout.maximumWidth: Kirigami.Units.gridUnit * 25
@ -134,7 +105,7 @@ Item {
anchors { anchors {
left: parent.left left: parent.left
top: clock.bottom top: clock.bottom
bottom: isOnLargeScreen ? columnLayout.top : mediaWidget.top bottom: isOnLargeScreen ? columnLayout.top : mediaControlsWidgetProxy.top
topMargin: Kirigami.Units.smallSpacing topMargin: Kirigami.Units.smallSpacing
leftMargin: columnLayout.anchors.margins leftMargin: columnLayout.anchors.margins
} }
@ -143,38 +114,35 @@ Item {
font.weight: Font.Light font.weight: Font.Light
} }
MobileShell.MediaControlsWidget { MobileShell.BaseItem {
id: mediaWidget id: mediaControlsWidgetProxy
property real fullHeight: visible ? height + Kirigami.Units.smallSpacing * 6 : 0 property real fullHeight: visible ? height + Kirigami.Units.smallSpacing * 6 : 0
y: isOnLargeScreen ? date.y - height + date.implicitHeight : date.y + date.implicitHeight + columnLayout.anchors.margins / 2 y: isOnLargeScreen ? date.y - height + date.implicitHeight : date.y + date.implicitHeight + columnLayout.anchors.margins / 2
inActionDrawer: true
opacity: columnLayout.opacity opacity: columnLayout.opacity
anchors { anchors {
right: quickSettings.left right: quickSettingsPanel.left
left: isOnLargeScreen ? date.right : parent.left left: isOnLargeScreen ? date.right : parent.left
leftMargin: columnLayout.anchors.margins leftMargin: columnLayout.anchors.margins
rightMargin: columnLayout.anchors.margins - quickSettings.leftPadding rightMargin: columnLayout.anchors.margins - quickSettingsPanel.leftPadding
} }
} }
// right sidebar // right sidebar
MobileShell.QuickSettingsPanel { MobileShell.QuickSettingsPanel {
id: quickSettings id: quickSettingsPanel
height: quickSettings.contentImplicitHeight + quickSettings.topPadding + quickSettings.bottomPadding height: quickSettingsPanel.contentImplicitHeight + quickSettingsPanel.topPadding + quickSettingsPanel.bottomPadding
width: intendedWidth width: intendedWidth
readonly property real intendedWidth: 360 readonly property real intendedWidth: 360
property real offsetRatio: quickSettings.height / root.height property real offsetRatio: quickSettingsPanel.height / root.height
anchors.topMargin: Math.min(root.actionDrawer.offset * offsetRatio - quickSettings.height, 0) anchors.topMargin: Math.min(root.actionDrawer.offset * offsetRatio - quickSettingsPanel.height, 0)
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
actionDrawer: root.actionDrawer actionDrawer: root.actionDrawer
quickSettingsModel: root.quickSettingsModel
fullScreenHeight: root.height fullScreenHeight: root.height
} }
} }

View file

@ -1,12 +1,9 @@
/* // SPDX-FileCopyrightText: 2021-2024 Devin Lin <devin@kde.org>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org> // SPDX-License-Identifier: LGPL-2.0-or-later
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.1 import QtQuick.Layouts
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
@ -21,15 +18,17 @@ Item {
id: root id: root
required property var actionDrawer required property var actionDrawer
property QS.QuickSettingsModel quickSettingsModel
property alias notificationsWidget: notificationWidget
// pinned position (disabled when openToPinnedMode is false) // pinned position (disabled when openToPinnedMode is false)
readonly property real minimizedQuickSettingsOffset: quickSettings.minimizedHeight readonly property real minimizedQuickSettingsOffset: quickSettingsDrawer.minimizedHeight
// fully open position // fully open position
readonly property real maximizedQuickSettingsOffset: minimizedQuickSettingsOffset + quickSettings.maxAddedHeight readonly property real maximizedQuickSettingsOffset: minimizedQuickSettingsOffset + quickSettingsDrawer.maxAddedHeight
property alias quickSettings: quickSettingsDrawer.quickSettings
property alias statusBar: quickSettingsDrawer.statusBar
property alias mediaControlsWidget: quickSettingsDrawer.mediaControlsWidget
property alias notificationsWidget: notificationWidgetProxy.contentItem
Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
@ -38,20 +37,8 @@ Item {
return Math.max(0, Math.min(1, val)); return Math.max(0, Math.min(1, val));
} }
// fullscreen background
Rectangle {
anchors.fill: parent
// darken if there are notifications
color: Qt.rgba(Kirigami.Theme.backgroundColor.r,
Kirigami.Theme.backgroundColor.g,
Kirigami.Theme.backgroundColor.b,
0.95)
Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration } }
opacity: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset))
}
MobileShell.QuickSettingsDrawer { MobileShell.QuickSettingsDrawer {
id: quickSettings id: quickSettingsDrawer
z: 1 // ensure it's above notifications z: 1 // ensure it's above notifications
// physically move the drawer when between closed <-> pinned mode // physically move the drawer when between closed <-> pinned mode
@ -62,7 +49,6 @@ Item {
anchors.right: parent.right anchors.right: parent.right
actionDrawer: root.actionDrawer actionDrawer: root.actionDrawer
quickSettingsModel: root.quickSettingsModel
// opacity and move animation (disabled when openToPinnedMode is false) // opacity and move animation (disabled when openToPinnedMode is false)
property real offsetDist: actionDrawer.offset - minimizedQuickSettingsOffset property real offsetDist: actionDrawer.offset - minimizedQuickSettingsOffset
@ -79,44 +65,29 @@ Item {
addedHeight: { addedHeight: {
if (!actionDrawer.openToPinnedMode) { if (!actionDrawer.openToPinnedMode) {
// if pinned mode disabled, just go to full height // if pinned mode disabled, just go to full height
let progress = (root.actionDrawer.offset - maximizedQuickSettingsOffset) / (quickSettings.maxAddedHeight * 4); let progress = (root.actionDrawer.offset - maximizedQuickSettingsOffset) / (quickSettingsDrawer.maxAddedHeight * 4);
let effectProgress = Math.atan(Math.max(0, progress)); let effectProgress = Math.atan(Math.max(0, progress));
return (quickSettings.maxAddedHeight * effectProgress) + quickSettings.maxAddedHeight; return (quickSettingsDrawer.maxAddedHeight * effectProgress) + quickSettingsDrawer.maxAddedHeight;
} else if (!actionDrawer.opened) { } else if (!actionDrawer.opened) {
// over-scroll effect for initial opening // over-scroll effect for initial opening
let progress = (root.actionDrawer.offset - minimizedQuickSettingsOffset) / quickSettings.maxAddedHeight; let progress = (root.actionDrawer.offset - minimizedQuickSettingsOffset) / quickSettingsDrawer.maxAddedHeight;
let effectProgress = Math.atan(Math.max(0, progress)); let effectProgress = Math.atan(Math.max(0, progress));
return quickSettings.maxAddedHeight * 0.25 * effectProgress; return quickSettingsDrawer.maxAddedHeight * 0.25 * effectProgress;
} else { } else {
// over-scroll effect for full drawer // over-scroll effect for full drawer
let progress = (root.actionDrawer.offset - maximizedQuickSettingsOffset) / (quickSettings.maxAddedHeight * 4); let progress = (root.actionDrawer.offset - maximizedQuickSettingsOffset) / (quickSettingsDrawer.maxAddedHeight * 4);
let effectProgress = Math.atan(Math.max(0, progress)); let effectProgress = Math.atan(Math.max(0, progress));
// as the drawer opens, add height to the rectangle, revealing content // as the drawer opens, add height to the rectangle, revealing content
return (quickSettings.maxAddedHeight * effectProgress) + Math.max(0, Math.min(quickSettings.maxAddedHeight, root.actionDrawer.offset - minimizedQuickSettingsOffset)); return (quickSettingsDrawer.maxAddedHeight * effectProgress) + Math.max(0, Math.min(quickSettingsDrawer.maxAddedHeight, root.actionDrawer.offset - minimizedQuickSettingsOffset));
} }
} }
} }
MobileShell.NotificationsWidget { MobileShell.BaseItem {
id: notificationWidget id: notificationWidgetProxy
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();
}
}
onBackgroundClicked: root.actionDrawer.close();
anchors { anchors {
top: quickSettings.bottom top: quickSettingsDrawer.bottom
bottom: parent.bottom bottom: parent.bottom
left: parent.left left: parent.left
right: parent.right right: parent.right

View file

@ -20,11 +20,12 @@ import org.kde.kirigami 2.20 as Kirigami
*/ */
Item { Item {
id: root id: root
layer.enabled: true
clip: true clip: true
required property var actionDrawer required property var actionDrawer
property QS.QuickSettingsModel quickSettingsModel required property QS.QuickSettingsModel quickSettingsModel
readonly property real columns: Math.round(Math.min(6, Math.max(3, width / intendedColumnWidth))) readonly property real columns: Math.round(Math.min(6, Math.max(3, width / intendedColumnWidth)))
readonly property real columnWidth: Math.floor(width / columns) readonly property real columnWidth: Math.floor(width / columns)
@ -89,9 +90,10 @@ Item {
anchors.right: parent.right anchors.right: parent.right
Repeater { Repeater {
id: repeater
model: QS.PaginateModel { model: QS.PaginateModel {
sourceModel: quickSettingsModel sourceModel: root.quickSettingsModel
pageSize: minimizedColumns pageSize: Math.min(root.pageSize, root.minimizedColumns) // HACK: just root.minimizedColumns appears to end up with an empty model?
} }
delegate: MobileShell.BaseItem { delegate: MobileShell.BaseItem {
required property var modelData required property var modelData

View file

@ -1,8 +1,5 @@
/* // SPDX-FileCopyrightText: 2021-2024 Devin Lin <devin@kde.org>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org> // SPDX-License-Identifier: LGPL-2.0-or-later
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick import QtQuick
import QtQuick.Controls as QQC2 import QtQuick.Controls as QQC2
@ -24,8 +21,6 @@ MobileShell.BaseItem {
required property var actionDrawer required property var actionDrawer
property QS.QuickSettingsModel quickSettingsModel
/** /**
* The amount of height to add to the panel (increasing the height of the quick settings area). * The amount of height to add to the panel (increasing the height of the quick settings area).
*/ */
@ -39,7 +34,7 @@ MobileShell.BaseItem {
/** /**
* Height of panel when in minimized mode. * Height of panel when in minimized mode.
*/ */
readonly property real minimizedHeight: bottomPadding + topPadding + statusBar.height + minimizedQuickSettingsHeight + mediaWidget.height + handle.fullHeight readonly property real minimizedHeight: bottomPadding + topPadding + statusBarProxy.height + minimizedQuickSettingsHeight + mediaControlsWidgetProxy.height + handle.fullHeight
/** /**
* Height of just the QuickSettings component in minimized mode. * Height of just the QuickSettings component in minimized mode.
@ -51,6 +46,10 @@ MobileShell.BaseItem {
*/ */
property real minimizedToFullProgress: 1 property real minimizedToFullProgress: 1
property alias quickSettings: quickSettingsProxy.contentItem
property alias statusBar: statusBarProxy.contentItem
property alias mediaControlsWidget: mediaControlsWidgetProxy.contentItem
// we need extra padding if the background side border is enabled // we need extra padding if the background side border is enabled
topPadding: Kirigami.Units.smallSpacing topPadding: Kirigami.Units.smallSpacing
leftPadding: Kirigami.Units.smallSpacing leftPadding: Kirigami.Units.smallSpacing
@ -74,39 +73,25 @@ MobileShell.BaseItem {
anchors.top: parent.top anchors.top: parent.top
spacing: 0 spacing: 0
MobileShell.StatusBar { MobileShell.BaseItem {
id: statusBar id: statusBarProxy
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: MobileShell.Constants.topPanelHeight + Kirigami.Units.gridUnit * 0.8 Layout.preferredHeight: MobileShell.Constants.topPanelHeight + Kirigami.Units.gridUnit * 0.8
Kirigami.Theme.colorSet: Kirigami.Theme.Window
Kirigami.Theme.inherit: false
backgroundColor: "transparent"
showSecondRow: true
showDropShadow: false
// security reasons, system tray also doesn't work on lockscreen
disableSystemTray: actionDrawer.restrictedPermissions
} }
MobileShell.QuickSettings { MobileShell.BaseItem {
id: quickSettings id: quickSettingsProxy
Layout.preferredHeight: root.minimizedQuickSettingsHeight + root.addedHeight Layout.preferredHeight: root.minimizedQuickSettingsHeight + root.addedHeight
Layout.topMargin: Kirigami.Units.smallSpacing Layout.topMargin: Kirigami.Units.smallSpacing
Layout.fillWidth: true Layout.fillWidth: true
actionDrawer: root.actionDrawer
quickSettingsModel: root.quickSettingsModel
fullViewProgress: root.minimizedToFullProgress
height: root.minimizedQuickSettingsHeight + root.addedHeight height: root.minimizedQuickSettingsHeight + root.addedHeight
width: parent.width width: parent.width
} }
MobileShell.MediaControlsWidget { MobileShell.BaseItem {
id: mediaWidget id: mediaControlsWidgetProxy
property real fullHeight: height + Layout.topMargin property real fullHeight: height + Layout.topMargin
inActionDrawer: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.smallSpacing Layout.topMargin: Kirigami.Units.smallSpacing
Layout.leftMargin: Kirigami.Units.largeSpacing Layout.leftMargin: Kirigami.Units.largeSpacing

View file

@ -1,8 +1,5 @@
/* // SPDX-FileCopyrightText: 2021-2024 Devin Lin <devin@kde.org>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org> // SPDX-License-Identifier: LGPL-2.0-or-later
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick import QtQuick
import QtQuick.Controls as QQC2 import QtQuick.Controls as QQC2
@ -36,6 +33,9 @@ MobileShell.BaseItem {
*/ */
readonly property real contentImplicitHeight: column.implicitHeight readonly property real contentImplicitHeight: column.implicitHeight
property alias quickSettings: quickSettingsProxy.contentItem
property alias statusBar: statusBarProxy.contentItem
// we need extra padding since the background side border is enabled // we need extra padding since the background side border is enabled
topPadding: Kirigami.Units.smallSpacing * 4 topPadding: Kirigami.Units.smallSpacing * 4
leftPadding: Kirigami.Units.smallSpacing * 4 leftPadding: Kirigami.Units.smallSpacing * 4
@ -59,8 +59,8 @@ MobileShell.BaseItem {
height: root.fullScreenHeight height: root.fullScreenHeight
spacing: 0 spacing: 0
MobileShell.StatusBar { MobileShell.BaseItem {
id: statusBar id: statusBarProxy
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true Layout.fillWidth: true
// Align these to double pixels to aid vertical alignment and sharper icon rendering // Align these to double pixels to aid vertical alignment and sharper icon rendering
@ -69,30 +69,17 @@ MobileShell.BaseItem {
Kirigami.Theme.colorSet: Kirigami.Theme.Window Kirigami.Theme.colorSet: Kirigami.Theme.Window
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
backgroundColor: "transparent"
showSecondRow: false
showDropShadow: false
showTime: false
// security reasons, system tray also doesn't work on lockscreen
disableSystemTray: actionDrawer.restrictedPermissions
} }
MobileShell.QuickSettings { MobileShell.BaseItem {
id: quickSettings id: quickSettingsProxy
quickSettingsModel: root.quickSettingsModel
width: column.width width: column.width
implicitHeight: quickSettings.fullHeight implicitHeight: quickSettings.fullHeight
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumHeight: root.fullScreenHeight - root.topPadding - root.bottomPadding - statusBar.height - Kirigami.Units.smallSpacing Layout.maximumHeight: root.fullScreenHeight - root.topPadding - root.bottomPadding - statusBarProxy.height - Kirigami.Units.smallSpacing
Layout.maximumWidth: column.width Layout.maximumWidth: column.width
actionDrawer: root.actionDrawer
fullViewProgress: 1.0
} }
Item { Layout.fillHeight: true } Item { Layout.fillHeight: true }

View file

@ -31,13 +31,17 @@ Item {
implicitWidth: leftPadding + rightPadding + contentItem.implicitWidth implicitWidth: leftPadding + rightPadding + contentItem.implicitWidth
onContentItemChanged: { onContentItemChanged: {
contentItem.parent = contentItemLoader; if (contentItem !== null && contentItem !== undefined) {
contentItem.anchors.fill = contentItemLoader; contentItem.parent = contentItemLoader;
contentItem.anchors.fill = contentItemLoader;
}
} }
onBackgroundChanged: { onBackgroundChanged: {
background.parent = backgroundLoader; if (background !== null && background !== undefined) {
background.anchors.fill = backgroundLoader; background.parent = backgroundLoader;
background.anchors.fill = backgroundLoader;
}
} }
Item { Item {

View file

@ -63,6 +63,7 @@ ApplicationWindow {
id: drawer id: drawer
z: 1 z: 1
anchors.fill: parent anchors.fill: parent
visible: offset !== 0
notificationSettings: NotificationManager.Settings {} notificationSettings: NotificationManager.Settings {}
notificationModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel notificationModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel