From 76882f5b5d0e5e61b9e17137daec8ec746901652 Mon Sep 17 00:00:00 2001 From: Devin Lin Date: Wed, 30 Oct 2024 22:05:44 -0700 Subject: [PATCH] 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 --- .../qml/actiondrawer/ActionDrawer.qml | 55 +++----- .../actiondrawer/ActionDrawerOpenSurface.qml | 6 +- .../qml/actiondrawer/ActionDrawerWindow.qml | 2 +- .../qml/actiondrawer/ContentContainer.qml | 130 ++++++++++++++++++ .../LandscapeContentContainer.qml | 80 ++++------- .../actiondrawer/PortraitContentContainer.qml | 69 +++------- .../quicksettings/QuickSettings.qml | 8 +- .../quicksettings/QuickSettingsDrawer.qml | 41 ++---- .../quicksettings/QuickSettingsPanel.qml | 33 ++--- .../mobileshell/qml/components/BaseItem.qml | 12 +- tests/ActionDrawerTest.qml | 1 + 11 files changed, 234 insertions(+), 203 deletions(-) create mode 100644 components/mobileshell/qml/actiondrawer/ContentContainer.qml diff --git a/components/mobileshell/qml/actiondrawer/ActionDrawer.qml b/components/mobileshell/qml/actiondrawer/ActionDrawer.qml index 1078b58e..dcf43fec 100644 --- a/components/mobileshell/qml/actiondrawer/ActionDrawer.qml +++ b/components/mobileshell/qml/actiondrawer/ActionDrawer.qml @@ -19,7 +19,13 @@ import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS Item { 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. @@ -34,7 +40,7 @@ Item { /** * 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. @@ -77,7 +83,7 @@ Item { /** * 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). @@ -178,17 +184,17 @@ Item { if (root.offset <= 0) { // close immediately, so that we don't have to wait Kirigami.Units.longDuration - root.visible = false; + root.intendedToBeVisible = false; close(); } 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 (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 expand(); - } else if (root.offset > contentContainerLoader.minimizedQuickSettingsOffset) { + } else if (root.offset > contentContainer.minimizedQuickSettingsOffset) { // if drag is between pinned view and fully expanded view if (root.direction === MobileShell.Direction.Down) { expand(); @@ -229,13 +235,13 @@ Item { State { name: "open" PropertyChanges { - target: root; offset: contentContainerLoader.minimizedQuickSettingsOffset + target: root; offset: contentContainer.minimizedQuickSettingsOffset } }, State { name: "expand" PropertyChanges { - target: root; offset: contentContainerLoader.maximizedQuickSettingsOffset + target: root; offset: contentContainer.maximizedQuickSettingsOffset } } ] @@ -250,7 +256,7 @@ Item { script: { if (root.state != "") { if (root.offset <= 0) { - root.visible = false; + root.intendedToBeVisible = false; root.opened = false; root.state = ""; } else { @@ -289,35 +295,12 @@ Item { onTouchpadScrollEnded: endSwipe() onTouchpadScrollMove: (totalDeltaX, totalDeltaY, deltaX, deltaY) => moveSwipe(totalDeltaX, totalDeltaY, deltaX, deltaY) - Loader { - id: contentContainerLoader + ContentContainer { + id: contentContainer anchors.fill: parent - property real minimizedQuickSettingsOffset: item ? item.minimizedQuickSettingsOffset : 0 - property real maximizedQuickSettingsOffset: item ? item.maximizedQuickSettingsOffset : 0 - - 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 - } + actionDrawer: root + quickSettingsModel: root.quickSettingsModel } } } diff --git a/components/mobileshell/qml/actiondrawer/ActionDrawerOpenSurface.qml b/components/mobileshell/qml/actiondrawer/ActionDrawerOpenSurface.qml index 167ba8f1..1c5d18fb 100644 --- a/components/mobileshell/qml/actiondrawer/ActionDrawerOpenSurface.qml +++ b/components/mobileshell/qml/actiondrawer/ActionDrawerOpenSurface.qml @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Devin Lin + * SPDX-FileCopyrightText: 2021-2024 Devin Lin * * SPDX-License-Identifier: LGPL-2.0-or-later */ @@ -19,7 +19,7 @@ MobileShell.SwipeArea { required property ActionDrawer actionDrawer function startSwipe() { - if (actionDrawer.visible) { + if (actionDrawer.intendedToBeVisible) { // ensure the action drawer state is consistent actionDrawer.closeImmediately(); } @@ -30,7 +30,7 @@ MobileShell.SwipeArea { // must be after properties other are set, we cannot have actionDrawer.updateState() be called actionDrawer.offset = 0; actionDrawer.oldOffset = 0; - actionDrawer.visible = true; + actionDrawer.intendedToBeVisible = true; } function startSwipeWithPoint(point) { diff --git a/components/mobileshell/qml/actiondrawer/ActionDrawerWindow.qml b/components/mobileshell/qml/actiondrawer/ActionDrawerWindow.qml index 8d3eb9eb..4fef46da 100644 --- a/components/mobileshell/qml/actiondrawer/ActionDrawerWindow.qml +++ b/components/mobileshell/qml/actiondrawer/ActionDrawerWindow.qml @@ -26,7 +26,7 @@ NanoShell.FullScreenOverlay { */ property alias actionDrawer: drawer - visible: drawer.visible + visible: drawer.intendedToBeVisible width: Screen.width height: Screen.height diff --git a/components/mobileshell/qml/actiondrawer/ContentContainer.qml b/components/mobileshell/qml/actiondrawer/ContentContainer.qml new file mode 100644 index 00000000..7de35f8d --- /dev/null +++ b/components/mobileshell/qml/actiondrawer/ContentContainer.qml @@ -0,0 +1,130 @@ +// SPDX-FileCopyrightText: 2021-2024 Devin Lin +// 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(); + } +} \ No newline at end of file diff --git a/components/mobileshell/qml/actiondrawer/LandscapeContentContainer.qml b/components/mobileshell/qml/actiondrawer/LandscapeContentContainer.qml index 64c688a5..d81b9732 100644 --- a/components/mobileshell/qml/actiondrawer/LandscapeContentContainer.qml +++ b/components/mobileshell/qml/actiondrawer/LandscapeContentContainer.qml @@ -1,13 +1,10 @@ -/* - * SPDX-FileCopyrightText: 2021 Devin Lin - * - * SPDX-License-Identifier: LGPL-2.0-or-later - */ +// SPDX-FileCopyrightText: 2021-2024 Devin Lin +// 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 QtQuick +import QtQuick.Controls as QQC2 +import QtQuick.Layouts +import QtQuick.Window import org.kde.kirigami 2.12 as Kirigami @@ -24,32 +21,21 @@ Item { id: root 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 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 opacityValue: Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset)) Kirigami.Theme.colorSet: Kirigami.Theme.View 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 { id: timeSource engine: "time" @@ -71,32 +57,17 @@ Item { spacing: 0 anchors { - top: mediaWidget.bottom + top: mediaControlsWidgetProxy.bottom topMargin: 0 bottom: parent.bottom bottomMargin: 0 - right: quickSettings.left + right: quickSettingsPanel.left left: parent.left } anchors.margins: minWidthHeight * 0.06 - 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(); + MobileShell.BaseItem { + id: notificationWidgetProxy // don't allow notifications widget to get too wide Layout.maximumWidth: Kirigami.Units.gridUnit * 25 @@ -134,7 +105,7 @@ Item { anchors { left: parent.left top: clock.bottom - bottom: isOnLargeScreen ? columnLayout.top : mediaWidget.top + bottom: isOnLargeScreen ? columnLayout.top : mediaControlsWidgetProxy.top topMargin: Kirigami.Units.smallSpacing leftMargin: columnLayout.anchors.margins } @@ -143,38 +114,35 @@ Item { font.weight: Font.Light } - MobileShell.MediaControlsWidget { - id: mediaWidget + MobileShell.BaseItem { + id: mediaControlsWidgetProxy 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 - - inActionDrawer: true opacity: columnLayout.opacity anchors { - right: quickSettings.left + right: quickSettingsPanel.left left: isOnLargeScreen ? date.right : parent.left leftMargin: columnLayout.anchors.margins - rightMargin: columnLayout.anchors.margins - quickSettings.leftPadding + rightMargin: columnLayout.anchors.margins - quickSettingsPanel.leftPadding } } // right sidebar MobileShell.QuickSettingsPanel { - id: quickSettings - height: quickSettings.contentImplicitHeight + quickSettings.topPadding + quickSettings.bottomPadding + id: quickSettingsPanel + height: quickSettingsPanel.contentImplicitHeight + quickSettingsPanel.topPadding + quickSettingsPanel.bottomPadding width: intendedWidth readonly property real intendedWidth: 360 - property real offsetRatio: quickSettings.height / root.height - anchors.topMargin: Math.min(root.actionDrawer.offset * offsetRatio - quickSettings.height, 0) + property real offsetRatio: quickSettingsPanel.height / root.height + anchors.topMargin: Math.min(root.actionDrawer.offset * offsetRatio - quickSettingsPanel.height, 0) anchors.top: parent.top anchors.right: parent.right actionDrawer: root.actionDrawer - quickSettingsModel: root.quickSettingsModel fullScreenHeight: root.height } } diff --git a/components/mobileshell/qml/actiondrawer/PortraitContentContainer.qml b/components/mobileshell/qml/actiondrawer/PortraitContentContainer.qml index 2e2cd8b2..250dd9e3 100644 --- a/components/mobileshell/qml/actiondrawer/PortraitContentContainer.qml +++ b/components/mobileshell/qml/actiondrawer/PortraitContentContainer.qml @@ -1,12 +1,9 @@ -/* - * SPDX-FileCopyrightText: 2021 Devin Lin - * - * SPDX-License-Identifier: LGPL-2.0-or-later - */ +// SPDX-FileCopyrightText: 2021-2024 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later import QtQuick 2.15 import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.1 +import QtQuick.Layouts import QtQuick.Window 2.2 import org.kde.plasma.private.mobileshell as MobileShell @@ -21,15 +18,17 @@ Item { id: root required property var actionDrawer - property QS.QuickSettingsModel quickSettingsModel - - property alias notificationsWidget: notificationWidget // pinned position (disabled when openToPinnedMode is false) - readonly property real minimizedQuickSettingsOffset: quickSettings.minimizedHeight + readonly property real minimizedQuickSettingsOffset: quickSettingsDrawer.minimizedHeight // 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.inherit: false @@ -38,20 +37,8 @@ Item { 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 { - id: quickSettings + id: quickSettingsDrawer z: 1 // ensure it's above notifications // physically move the drawer when between closed <-> pinned mode @@ -62,7 +49,6 @@ Item { anchors.right: parent.right actionDrawer: root.actionDrawer - quickSettingsModel: root.quickSettingsModel // opacity and move animation (disabled when openToPinnedMode is false) property real offsetDist: actionDrawer.offset - minimizedQuickSettingsOffset @@ -79,44 +65,29 @@ Item { addedHeight: { if (!actionDrawer.openToPinnedMode) { // 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)); - return (quickSettings.maxAddedHeight * effectProgress) + quickSettings.maxAddedHeight; + return (quickSettingsDrawer.maxAddedHeight * effectProgress) + quickSettingsDrawer.maxAddedHeight; } else if (!actionDrawer.opened) { // 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)); - return quickSettings.maxAddedHeight * 0.25 * effectProgress; + return quickSettingsDrawer.maxAddedHeight * 0.25 * effectProgress; } else { // 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)); // 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 { - 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(); + MobileShell.BaseItem { + id: notificationWidgetProxy anchors { - top: quickSettings.bottom + top: quickSettingsDrawer.bottom bottom: parent.bottom left: parent.left right: parent.right diff --git a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml index c1c5eb9c..630c75b8 100644 --- a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml +++ b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml @@ -20,11 +20,12 @@ import org.kde.kirigami 2.20 as Kirigami */ Item { id: root + layer.enabled: true clip: true 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 columnWidth: Math.floor(width / columns) @@ -89,9 +90,10 @@ Item { anchors.right: parent.right Repeater { + id: repeater model: QS.PaginateModel { - sourceModel: quickSettingsModel - pageSize: minimizedColumns + sourceModel: root.quickSettingsModel + pageSize: Math.min(root.pageSize, root.minimizedColumns) // HACK: just root.minimizedColumns appears to end up with an empty model? } delegate: MobileShell.BaseItem { required property var modelData diff --git a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDrawer.qml b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDrawer.qml index 64f649df..c7f4e1a2 100644 --- a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDrawer.qml +++ b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDrawer.qml @@ -1,8 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2021 Devin Lin - * - * SPDX-License-Identifier: LGPL-2.0-or-later - */ +// SPDX-FileCopyrightText: 2021-2024 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later import QtQuick import QtQuick.Controls as QQC2 @@ -24,8 +21,6 @@ MobileShell.BaseItem { 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). */ @@ -39,7 +34,7 @@ MobileShell.BaseItem { /** * 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. @@ -51,6 +46,10 @@ MobileShell.BaseItem { */ 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 topPadding: Kirigami.Units.smallSpacing leftPadding: Kirigami.Units.smallSpacing @@ -74,39 +73,25 @@ MobileShell.BaseItem { anchors.top: parent.top spacing: 0 - MobileShell.StatusBar { - id: statusBar + MobileShell.BaseItem { + id: statusBarProxy Layout.fillWidth: true 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 { - id: quickSettings + MobileShell.BaseItem { + id: quickSettingsProxy Layout.preferredHeight: root.minimizedQuickSettingsHeight + root.addedHeight Layout.topMargin: Kirigami.Units.smallSpacing Layout.fillWidth: true - actionDrawer: root.actionDrawer - quickSettingsModel: root.quickSettingsModel - fullViewProgress: root.minimizedToFullProgress height: root.minimizedQuickSettingsHeight + root.addedHeight width: parent.width } - MobileShell.MediaControlsWidget { - id: mediaWidget + MobileShell.BaseItem { + id: mediaControlsWidgetProxy property real fullHeight: height + Layout.topMargin - inActionDrawer: true Layout.fillWidth: true Layout.topMargin: Kirigami.Units.smallSpacing Layout.leftMargin: Kirigami.Units.largeSpacing diff --git a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsPanel.qml b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsPanel.qml index 2d140b69..7281ecf1 100644 --- a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsPanel.qml +++ b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsPanel.qml @@ -1,8 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2021 Devin Lin - * - * SPDX-License-Identifier: LGPL-2.0-or-later - */ +// SPDX-FileCopyrightText: 2021-2024 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later import QtQuick import QtQuick.Controls as QQC2 @@ -36,6 +33,9 @@ MobileShell.BaseItem { */ 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 topPadding: Kirigami.Units.smallSpacing * 4 leftPadding: Kirigami.Units.smallSpacing * 4 @@ -59,8 +59,8 @@ MobileShell.BaseItem { height: root.fullScreenHeight spacing: 0 - MobileShell.StatusBar { - id: statusBar + MobileShell.BaseItem { + id: statusBarProxy Layout.alignment: Qt.AlignTop Layout.fillWidth: true // 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.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 { - id: quickSettings - - quickSettingsModel: root.quickSettingsModel + MobileShell.BaseItem { + id: quickSettingsProxy width: column.width implicitHeight: quickSettings.fullHeight Layout.alignment: Qt.AlignTop 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 - - actionDrawer: root.actionDrawer - fullViewProgress: 1.0 } Item { Layout.fillHeight: true } diff --git a/components/mobileshell/qml/components/BaseItem.qml b/components/mobileshell/qml/components/BaseItem.qml index e44898d5..59ec1a72 100644 --- a/components/mobileshell/qml/components/BaseItem.qml +++ b/components/mobileshell/qml/components/BaseItem.qml @@ -31,13 +31,17 @@ Item { implicitWidth: leftPadding + rightPadding + contentItem.implicitWidth onContentItemChanged: { - contentItem.parent = contentItemLoader; - contentItem.anchors.fill = contentItemLoader; + if (contentItem !== null && contentItem !== undefined) { + contentItem.parent = contentItemLoader; + contentItem.anchors.fill = contentItemLoader; + } } onBackgroundChanged: { - background.parent = backgroundLoader; - background.anchors.fill = backgroundLoader; + if (background !== null && background !== undefined) { + background.parent = backgroundLoader; + background.anchors.fill = backgroundLoader; + } } Item { diff --git a/tests/ActionDrawerTest.qml b/tests/ActionDrawerTest.qml index 25269b37..d439d883 100644 --- a/tests/ActionDrawerTest.qml +++ b/tests/ActionDrawerTest.qml @@ -63,6 +63,7 @@ ApplicationWindow { id: drawer z: 1 anchors.fill: parent + visible: offset !== 0 notificationSettings: NotificationManager.Settings {} notificationModelType: MobileShell.NotificationsModelType.WatchedNotificationsModel