diff --git a/components/mobilehomescreencomponents/qml/GridViewAppDrawer.qml b/components/mobilehomescreencomponents/qml/GridViewAppDrawer.qml index cdd550de..808b739f 100644 --- a/components/mobilehomescreencomponents/qml/GridViewAppDrawer.qml +++ b/components/mobilehomescreencomponents/qml/GridViewAppDrawer.qml @@ -85,7 +85,7 @@ AbstractAppDrawer { } onLaunch: (x, y, icon, title, storageId) => { if (icon !== "") { - NanoShell.StartupFeedback.open( + MobileShell.HomeScreenControls.openAppAnimation( icon, title, delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, diff --git a/components/mobilehomescreencomponents/qml/LauncherGrid.qml b/components/mobilehomescreencomponents/qml/LauncherGrid.qml index f70f78c4..379a124b 100644 --- a/components/mobilehomescreencomponents/qml/LauncherGrid.qml +++ b/components/mobilehomescreencomponents/qml/LauncherGrid.qml @@ -15,6 +15,7 @@ import org.kde.kirigami 2.10 as Kirigami import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager import org.kde.plasma.private.nanoshell 2.0 as NanoShell +import org.kde.plasma.private.mobileshell 1.0 as MobileShell import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents @@ -55,7 +56,7 @@ LauncherContainer { } onLaunch: (x, y, icon, title) => { if (icon !== "") { - NanoShell.StartupFeedback.open( + MobileShell.HomeScreenControls.openAppAnimation( icon, title, delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, diff --git a/components/mobilehomescreencomponents/qml/LauncherRepeater.qml b/components/mobilehomescreencomponents/qml/LauncherRepeater.qml index 7284e718..d0eea792 100644 --- a/components/mobilehomescreencomponents/qml/LauncherRepeater.qml +++ b/components/mobilehomescreencomponents/qml/LauncherRepeater.qml @@ -101,7 +101,7 @@ Repeater { onLaunch: (x, y, icon, title) => { if (icon !== "") { print(delegate.iconItem) - NanoShell.StartupFeedback.open( + MobileShell.HomeScreenControls.openAppAnimation( icon, title, delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, diff --git a/components/mobilehomescreencomponents/qml/ListViewAppDrawer.qml b/components/mobilehomescreencomponents/qml/ListViewAppDrawer.qml index a9302a41..3ecc59ae 100644 --- a/components/mobilehomescreencomponents/qml/ListViewAppDrawer.qml +++ b/components/mobilehomescreencomponents/qml/ListViewAppDrawer.qml @@ -81,7 +81,7 @@ AbstractAppDrawer { } onLaunch: (x, y, icon, title, storageId) => { if (icon !== "") { - NanoShell.StartupFeedback.open( + MobileShell.HomeScreenControls.openAppAnimation( icon, title, delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2, diff --git a/components/mobileshell/qml/HomeScreenControls.qml b/components/mobileshell/qml/HomeScreenControls.qml index 2bde6a5d..93770c8a 100644 --- a/components/mobileshell/qml/HomeScreenControls.qml +++ b/components/mobileshell/qml/HomeScreenControls.qml @@ -10,6 +10,9 @@ import QtQuick.Window 2.2 pragma Singleton +/** + * Provides access to the homescreen plasmoid containment within the shell. + */ QtObject { id: delegate @@ -18,6 +21,8 @@ QtObject { signal snapHomeScreenPosition() signal requestRelativeScroll(point pos) + signal openAppAnimation(string splashIcon, string title, real x, real y, real sourceIconSize) + property var taskSwitcher property QtObject homeScreenWindow property bool homeScreenVisible: true diff --git a/components/mobileshell/qml/TaskPanelControls.qml b/components/mobileshell/qml/TaskPanelControls.qml index e5869207..e2503c85 100644 --- a/components/mobileshell/qml/TaskPanelControls.qml +++ b/components/mobileshell/qml/TaskPanelControls.qml @@ -10,7 +10,7 @@ import org.kde.plasma.core 2.0 as PlasmaCore pragma Singleton /** - * Properties exposed by the taskpanel containment. + * Provides access to the taskpanel plasmoid containment within the shell. */ QtObject { id: root diff --git a/components/mobileshell/qml/TopPanelControls.qml b/components/mobileshell/qml/TopPanelControls.qml index 1712cf67..70644e34 100644 --- a/components/mobileshell/qml/TopPanelControls.qml +++ b/components/mobileshell/qml/TopPanelControls.qml @@ -9,6 +9,9 @@ import org.kde.plasma.core 2.0 as PlasmaCore pragma Singleton +/** + * Provides access to the panel plasmoid containment within the shell. + */ QtObject { id: root diff --git a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml index 5665f2fe..bdf56c78 100644 --- a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml +++ b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettings.qml @@ -76,6 +76,10 @@ Item { enabled: modelData.enabled settingsCommand: modelData.settingsCommand toggleFunction: modelData.toggle + + onCloseRequested: { + actionDrawer.close(); + } } } } @@ -122,6 +126,10 @@ Item { enabled: modelData.enabled settingsCommand: modelData.settingsCommand toggleFunction: modelData.toggle + + onCloseRequested: { + actionDrawer.close(); + } } } } diff --git a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDelegate.qml b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDelegate.qml index ef5cf6ca..2d2a4a69 100644 --- a/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDelegate.qml +++ b/components/mobileshell/qml/actiondrawer/quicksettings/QuickSettingsDelegate.qml @@ -28,6 +28,8 @@ Components.BaseItem { required property string settingsCommand required property var toggleFunction + signal closeRequested() + // set by children property var iconItem @@ -44,7 +46,8 @@ Components.BaseItem { } else if (root.toggleFunction) { root.toggleFunction(); } else if (root.settingsCommand) { - NanoShell.StartupFeedback.open( + closeRequested(); + MobileShell.HomeScreenControls.openAppAnimation( root.icon, root.text, iconItem.Kirigami.ScenePosition.x + iconItem.width/2, @@ -56,13 +59,13 @@ Components.BaseItem { function delegatePressAndHold() { if (root.settingsCommand) { - NanoShell.StartupFeedback.open( + closeRequested(); + MobileShell.HomeScreenControls.openAppAnimation( root.icon, root.text, iconItem.Kirigami.ScenePosition.x + iconItem.width/2, iconItem.Kirigami.ScenePosition.y + iconItem.height/2, Math.min(iconItem.width, iconItem.height)) - closeRequested(); MobileShell.ShellUtil.executeCommand(root.settingsCommand); } else if (root.toggleFunction) { root.toggleFunction(); diff --git a/components/mobileshell/qml/components/StartupFeedback.qml b/components/mobileshell/qml/components/StartupFeedback.qml new file mode 100644 index 00000000..6383179f --- /dev/null +++ b/components/mobileshell/qml/components/StartupFeedback.qml @@ -0,0 +1,183 @@ +/* + * SPDX-FileCopyrightText: 2015 Marco Martin + * SPDX-FileCopyrightText: 2021 Devin Lin + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick 2.12 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.2 +import org.kde.plasma.core 2.0 as PlasmaCore +import QtGraphicalEffects 1.12 + +import org.kde.kirigami 2.13 as Kirigami + +import org.kde.plasma.private.nanoshell 2.0 as NanoShell +import org.kde.plasma.private.mobileshell 1.0 as MobileShell + +/** + * Component that animates an app opening from a location. + */ +Item { + id: root + visible: false + + property alias backgroundColor: background.color + Kirigami.ImageColors { + id: colorGenerator + source: icon.source + } + + function open(splashIcon, title, x, y, sourceIconSize, color) { + iconParent.scale = sourceIconSize/iconParent.width; + background.scale = 0; + backgroundParent.x = -root.width/2 + x + backgroundParent.y = -root.height/2 + y + icon.source = splashIcon; + + if (color !== undefined) { + // Break binding to use custom color + background.color = color + } else { + // Recreate binding + background.color = Qt.binding(function() { return colorGenerator.dominant}) + } + + background.state = "open"; + + MobileShell.HomeScreenControls.taskSwitcher.minimizeAll(); + } + + // close when an app opens + property bool windowActive: Window.active + onWindowActiveChanged: { + background.state = "closed"; + } + + // close when homescreen requested + Connections { + target: MobileShell.HomeScreenControls + function onOpenHomeScreen() { + background.state = "closed"; + } + } + + Connections { + target: NanoShell.StartupNotifier + enabled: NanoShell.StartupNotifier.isValid + + function onActivationStarted(appId, iconName) { + icon.source = iconName + background.state = "open"; + } + } + + property alias state: background.state + property alias icon: icon.source + + onVisibleChanged: { + if (!visible) { + background.state = "closed"; + } + } + + Item { + id: backgroundParent + width: root.width + height: root.height + + Item { + id: iconParent + z: 2 + anchors.centerIn: background + width: PlasmaCore.Units.iconSizes.enormous + height: width + PlasmaCore.IconItem { + id: icon + anchors.fill: parent + colorGroup: PlasmaCore.Theme.ComplementaryColorGroup + } + DropShadow { + anchors.fill: icon + horizontalOffset: 0 + verticalOffset: 0 + radius: 8.0 + samples: 17 + color: "#80000000" + source: icon + } + } + + Rectangle { + id: background + anchors.fill: parent + + color: colorGenerator.dominant + + state: "closed" + + states: [ + State { + name: "closed" + PropertyChanges { + target: root + visible: false + } + }, + State { + name: "open" + + PropertyChanges { + target: root + visible: true + } + } + ] + + transitions: [ + Transition { + from: "closed" + SequentialAnimation { + ScriptAction { + script: { + root.visible = true; + } + } + ParallelAnimation { + ScaleAnimator { + target: background + from: background.scale + to: 1 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + ScaleAnimator { + target: iconParent + from: iconParent.scale + to: 1 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + XAnimator { + target: backgroundParent + from: backgroundParent.x + to: 0 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutCubic + } + YAnimator { + target: backgroundParent + from: backgroundParent.y + to: 0 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutCubic + } + } + } + } + ] + } + } +} + diff --git a/components/mobileshell/qml/dataproviders/VolumeProvider.qml b/components/mobileshell/qml/dataproviders/VolumeProvider.qml index 3edf1775..6dc021fd 100644 --- a/components/mobileshell/qml/dataproviders/VolumeProvider.qml +++ b/components/mobileshell/qml/dataproviders/VolumeProvider.qml @@ -152,7 +152,7 @@ QtObject { property SinkModel paSinkModel: SinkModel {} - property VolumeOSD osd: VolumeOSD { + property var osd: VolumeOSD { volume: volumeValue } diff --git a/components/mobileshell/qml/osd/volume/VolumeOSD.qml b/components/mobileshell/qml/osd/volume/VolumeOSD.qml index 41ef0366..2d78c6e1 100644 --- a/components/mobileshell/qml/osd/volume/VolumeOSD.qml +++ b/components/mobileshell/qml/osd/volume/VolumeOSD.qml @@ -17,6 +17,7 @@ import org.kde.plasma.extras 2.0 as PlasmaExtra import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtra import org.kde.plasma.private.nanoshell 2.0 as NanoShell +import org.kde.plasma.private.mobileshell 1.0 as MobileShell import org.kde.kirigami 2.12 as Kirigami @@ -170,7 +171,7 @@ NanoShell.FullScreenOverlay { onClicked: { let coords = mapToItem(flickable, 0, 0); - NanoShell.StartupFeedback.open("audio-volume-high", i18n("Audio Settings"), coords.x, coords.y, PlasmaCore.Units.iconSizes.medium); + MobileShell.HomeScreenControls.openAppAnimation("audio-volume-high", i18n("Audio Settings"), coords.x, coords.y, PlasmaCore.Units.iconSizes.medium); plasmoid.nativeInterface.executeCommand("plasma-open-settings kcm_pulseaudio"); } } diff --git a/components/mobileshell/qml/qmldir b/components/mobileshell/qml/qmldir index 4a5dfd35..567dabad 100644 --- a/components/mobileshell/qml/qmldir +++ b/components/mobileshell/qml/qmldir @@ -12,6 +12,7 @@ ActionDrawerOpenSurface 1.0 actiondrawer/ActionDrawerOpenSurface.qml # /components BaseItem 1.0 components/BaseItem.qml Direction 1.0 components/Direction.qml +StartupFeedback 1.0 components/StartupFeedback.qml # /dataproviders singleton BatteryProvider 1.0 dataproviders/BatteryProvider.qml diff --git a/containments/homescreen/package/contents/ui/main.qml b/containments/homescreen/package/contents/ui/main.qml index ebfbc458..c14d3ca3 100644 --- a/containments/homescreen/package/contents/ui/main.qml +++ b/containments/homescreen/package/contents/ui/main.qml @@ -66,6 +66,10 @@ FocusScope { homescreen.appDrawer.offset -= pos.y; lastRequestedPosition = pos.y; } + + function onOpenAppAnimation(splashIcon, title, x, y, sourceIconSize) { + startupFeedback.open(splashIcon, title, x, y, sourceIconSize); + } } Plasmoid.onScreenChanged: { @@ -150,6 +154,8 @@ FocusScope { // hide homescreen elements to make use of wallpaper onVisibleChanged: { if (visible) { + startupFeedback.visible = false; + // only animate if going from homescreen if (taskSwitcher.wasInActiveTask) { opacityAnimation.to = 0; @@ -164,5 +170,11 @@ FocusScope { } } } + + // start app animation + MobileShell.StartupFeedback { + id: startupFeedback + anchors.fill: parent + } } diff --git a/containments/panel/package/contents/ui/main.qml b/containments/panel/package/contents/ui/main.qml index 2eb94a47..f7a0288d 100644 --- a/containments/panel/package/contents/ui/main.qml +++ b/containments/panel/package/contents/ui/main.qml @@ -22,9 +22,7 @@ Item { id: root readonly property bool showingApp: !MobileShell.HomeScreenControls.homeScreenVisible - readonly property color backgroundColor: NanoShell.StartupFeedback.visible - ? NanoShell.StartupFeedback.backgroundColor - : topPanel.colorScopeColor + readonly property color backgroundColor: topPanel.colorScopeColor Plasmoid.backgroundHints: showingApp ? PlasmaCore.Types.StandardBackground : PlasmaCore.Types.NoBackground diff --git a/containments/taskpanel/package/contents/ui/main.qml b/containments/taskpanel/package/contents/ui/main.qml index 3d18a7df..ffad66ef 100644 --- a/containments/taskpanel/package/contents/ui/main.qml +++ b/containments/taskpanel/package/contents/ui/main.qml @@ -25,7 +25,7 @@ PlasmaCore.ColorScope { Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground - readonly property color backgroundColor: NanoShell.StartupFeedback.visible ? NanoShell.StartupFeedback.backgroundColor : PlasmaCore.ColorScope.backgroundColor + readonly property color backgroundColor: PlasmaCore.ColorScope.backgroundColor readonly property bool showingApp: !plasmoid.nativeInterface.allMinimized readonly property bool hasTasks: tasksModel.count > 0