mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-08-03 10:14:45 +00:00
homescreen: Extract out state management to HomeScreenState and use single flickable
This commit is contained in:
parent
46c1aa8fc8
commit
57a4a28fe3
22 changed files with 922 additions and 605 deletions
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import QtQuick 2.4
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Controls 2.3 as Controls
|
|
||||||
import QtGraphicalEffects 1.6
|
|
||||||
|
|
||||||
import org.kde.plasma.plasmoid 2.0
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
|
||||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
|
||||||
import org.kde.kquickcontrolsaddons 2.0
|
|
||||||
|
|
||||||
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
|
||||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: delegate
|
|
||||||
width: GridView.view.cellWidth
|
|
||||||
height: GridView.view.cellHeight
|
|
||||||
|
|
||||||
property int reservedSpaceForLabel
|
|
||||||
property alias iconItem: icon
|
|
||||||
|
|
||||||
signal launch(int x, int y, var source, string title, string storageId)
|
|
||||||
signal dragStarted(string imageSource, int x, int y, string mimeData)
|
|
||||||
|
|
||||||
onPressAndHold: {
|
|
||||||
delegate.grabToImage(function(result) {
|
|
||||||
delegate.Drag.imageSource = result.url
|
|
||||||
dragStarted(result.url, width/2, height/2, model.applicationStorageId)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
propagateComposedEvents: true
|
|
||||||
onClicked: {
|
|
||||||
mouse.accepted = true
|
|
||||||
if (model.applicationRunning) {
|
|
||||||
delegate.launch(0, 0, "", model.applicationName, model.applicationStorageId);
|
|
||||||
} else {
|
|
||||||
delegate.launch(delegate.x + (PlasmaCore.Units.smallSpacing * 2), delegate.y + (PlasmaCore.Units.smallSpacing * 2), icon.source, model.applicationName, model.applicationStorageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//preventStealing: true
|
|
||||||
ColumnLayout {
|
|
||||||
anchors {
|
|
||||||
fill: parent
|
|
||||||
leftMargin: PlasmaCore.Units.smallSpacing * 2
|
|
||||||
topMargin: PlasmaCore.Units.smallSpacing * 2
|
|
||||||
rightMargin: PlasmaCore.Units.smallSpacing * 2
|
|
||||||
bottomMargin: PlasmaCore.Units.smallSpacing * 2
|
|
||||||
}
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
PlasmaCore.IconItem {
|
|
||||||
id: icon
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.minimumHeight: parent.height - delegate.reservedSpaceForLabel
|
|
||||||
Layout.preferredHeight: Layout.minimumHeight
|
|
||||||
|
|
||||||
usesPlasmaTheme: false
|
|
||||||
source: model.applicationIcon
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors {
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
visible: model.applicationRunning
|
|
||||||
radius: width
|
|
||||||
width: PlasmaCore.Units.smallSpacing
|
|
||||||
height: width
|
|
||||||
color: PlasmaCore.Theme.highlightColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PlasmaComponents.Label {
|
|
||||||
id: label
|
|
||||||
visible: text.length > 0
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: delegate.reservedSpaceForLabel
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.leftMargin: -parent.anchors.leftMargin + PlasmaCore.Units.smallSpacing
|
|
||||||
Layout.rightMargin: -parent.anchors.rightMargin + PlasmaCore.Units.smallSpacing
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignTop
|
|
||||||
maximumLineCount: 2
|
|
||||||
elide: Text.ElideRight
|
|
||||||
|
|
||||||
text: model.applicationName
|
|
||||||
|
|
||||||
//FIXME: export smallestReadableFont
|
|
||||||
font.pointSize: PlasmaCore.Theme.defaultFont.pointSize * 0.9
|
|
||||||
color: "white"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
107
components/mobilehomescreencomponents/qml/FlickContainer.qml
Normal file
107
components/mobilehomescreencomponents/qml/FlickContainer.qml
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import org.kde.taskmanager 0.1 as TaskManager
|
||||||
|
import org.kde.plasma.core 2.1 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
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var homeScreenState
|
||||||
|
|
||||||
|
// we use flickable solely for capturing flicks, not positioning elements
|
||||||
|
contentWidth: width + 99999
|
||||||
|
contentHeight: height + 99999
|
||||||
|
contentX: startContentX
|
||||||
|
contentY: startContentY
|
||||||
|
|
||||||
|
readonly property real startContentX: contentWidth / 2
|
||||||
|
readonly property real startContentY: contentHeight / 2
|
||||||
|
|
||||||
|
property bool positionChangedDueToFlickable: false
|
||||||
|
|
||||||
|
// ensure that flickable is not moving when other sources are changing position
|
||||||
|
Connections {
|
||||||
|
target: root.homeScreenState
|
||||||
|
|
||||||
|
onXPositionChanged: {
|
||||||
|
if (!root.positionChangedDueToFlickable) {
|
||||||
|
root.cancelMovement();
|
||||||
|
}
|
||||||
|
root.positionChangedDueToFlickable = true;
|
||||||
|
}
|
||||||
|
onYPositionChanged: {
|
||||||
|
if (!root.positionChangedDueToFlickable) {
|
||||||
|
root.cancelMovement();
|
||||||
|
}
|
||||||
|
root.positionChangedDueToFlickable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update position from flickable movement
|
||||||
|
property real oldContentX
|
||||||
|
property real oldContentY
|
||||||
|
onContentXChanged: {
|
||||||
|
positionChangedDueToFlickable = true;
|
||||||
|
homeScreenState.updatePositionWithOffset(contentX - oldContentX, 0);
|
||||||
|
oldContentX = contentX;
|
||||||
|
}
|
||||||
|
onContentYChanged: {
|
||||||
|
positionChangedDueToFlickable = true;
|
||||||
|
homeScreenState.updatePositionWithOffset(0, -(contentY - oldContentY));
|
||||||
|
oldContentY = contentY;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMovementStarted: homeScreenState.cancelAnimations();
|
||||||
|
onMovementEnded: {
|
||||||
|
if (!homeScreenState.animationsRunning) {
|
||||||
|
homeScreenState.updateState();
|
||||||
|
}
|
||||||
|
resetPosition();
|
||||||
|
}
|
||||||
|
onFlickEnded: {
|
||||||
|
homeScreenState.cancelEditModeForItemsRequested()
|
||||||
|
resetPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragStarted: homeScreenState.cancelEditModeForItemsRequested()
|
||||||
|
onDragEnded: homeScreenState.cancelEditModeForItemsRequested()
|
||||||
|
onFlickStarted: homeScreenState.cancelEditModeForItemsRequested()
|
||||||
|
|
||||||
|
onDraggingChanged: {
|
||||||
|
if (!dragging) {
|
||||||
|
cancelMovement();
|
||||||
|
resetPosition();
|
||||||
|
if (!homeScreenState.animationsRunning) {
|
||||||
|
homeScreenState.updateState();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
homeScreenState.cancelAnimations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelMovement() {
|
||||||
|
root.cancelFlick();
|
||||||
|
|
||||||
|
// HACK: cancelFlick() doesn't seem to cancel flicks...
|
||||||
|
root.flick(-horizontalVelocity, -verticalVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetPosition() {
|
||||||
|
positionChangedDueToFlickable = true;
|
||||||
|
oldContentX = startContentX;
|
||||||
|
contentX = startContentX;
|
||||||
|
oldContentY = startContentY;
|
||||||
|
contentY = startContentY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -23,6 +23,8 @@ import "private" as Private
|
||||||
ContainmentLayoutManager.ItemContainer {
|
ContainmentLayoutManager.ItemContainer {
|
||||||
id: delegate
|
id: delegate
|
||||||
|
|
||||||
|
property var homeScreenState
|
||||||
|
|
||||||
z: dragActive ? 1 : 0
|
z: dragActive ? 1 : 0
|
||||||
|
|
||||||
property var modelData: typeof model !== "undefined" ? model : null
|
property var modelData: typeof model !== "undefined" ? model : null
|
||||||
|
|
@ -64,11 +66,11 @@ ContainmentLayoutManager.ItemContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: mainFlickable
|
target: homeScreenState
|
||||||
function onCancelEditModeForItemsRequested() {
|
function onCancelEditModeForItemsRequested() {
|
||||||
cancelEdit()
|
cancelEdit()
|
||||||
}
|
}
|
||||||
function onContentYChanged() {
|
function onXPositionChanged() {
|
||||||
syncDelegateGeometry()
|
syncDelegateGeometry()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
135
components/mobilehomescreencomponents/qml/HomeScreen.qml
Normal file
135
components/mobilehomescreencomponents/qml/HomeScreen.qml
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||||
|
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Window 2.12
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
|
import org.kde.plasma.plasmoid 2.0
|
||||||
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
|
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||||
|
import org.kde.draganddrop 2.0 as DragDrop
|
||||||
|
|
||||||
|
import "private" as Private
|
||||||
|
import "appdrawer"
|
||||||
|
|
||||||
|
import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager
|
||||||
|
|
||||||
|
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
|
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool interactive: true
|
||||||
|
|
||||||
|
property var homeScreenState: HomeScreenState {
|
||||||
|
totalPagesWidth: pages.contentWidth
|
||||||
|
|
||||||
|
appDrawerFlickable: appDrawer.flickable
|
||||||
|
|
||||||
|
availableScreenHeight: height - (MobileShell.TaskPanelControls.isPortrait ? MobileShell.TaskPanelControls.panelHeight : 0)
|
||||||
|
availableScreenWidth: width - (MobileShell.TaskPanelControls.isPortrait ? 0 : MobileShell.TaskPanelControls.panelWidth)
|
||||||
|
|
||||||
|
appDrawerBottomOffset: favoriteStrip.height
|
||||||
|
}
|
||||||
|
|
||||||
|
property alias appDrawer: appDrawerLoader.item
|
||||||
|
property alias homeScreenContents: contents
|
||||||
|
|
||||||
|
Component.onCompleted: homeScreenState.goToPageIndex(0)
|
||||||
|
|
||||||
|
// the parent of the homescreen is a flickable that captures all flicks
|
||||||
|
FlickContainer {
|
||||||
|
id: flickContainer
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
homeScreenState: root.homeScreenState
|
||||||
|
|
||||||
|
// disable flick tracking when necessary
|
||||||
|
interactive: root.interactive && homeScreenState.currentView !== HomeScreenState.AppDrawerView &&
|
||||||
|
root.parent.focus && !contents.appletsLayout.editMode && !plasmoid.editMode && !contents.launcherDragManager.active
|
||||||
|
|
||||||
|
// item is effectively anchored to root, while allowing flickContainer
|
||||||
|
// to keep track of flicks
|
||||||
|
Item {
|
||||||
|
x: flickContainer.contentX
|
||||||
|
y: flickContainer.contentY
|
||||||
|
width: flickContainer.width
|
||||||
|
height: flickContainer.height
|
||||||
|
|
||||||
|
// horizontal pages
|
||||||
|
HomeScreenPages {
|
||||||
|
id: pages
|
||||||
|
homeScreenState: root.homeScreenState
|
||||||
|
|
||||||
|
// account for panels
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.topMargin: MobileShell.TopPanelControls.panelHeight
|
||||||
|
anchors.rightMargin: MobileShell.TaskPanelControls.isPortrait ? 0 : MobileShell.TaskPanelControls.panelWidth
|
||||||
|
anchors.bottomMargin: MobileShell.TaskPanelControls.isPortrait ? MobileShell.TaskPanelControls.panelHeight : 0
|
||||||
|
|
||||||
|
// animation when app drawer is being shown
|
||||||
|
opacity: root.appDrawer ? 1 - root.appDrawer.openFactor : 1
|
||||||
|
transform: Translate {
|
||||||
|
y: root.appDrawer ? (-pages.height / 20) * root.appDrawer.openFactor : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
contentWidth: Math.max(width, width * Math.ceil(contents.itemsBoundingRect.width/width)) + (contents.launcherDragManager.active ? width : 0)
|
||||||
|
showAddPageIndicator: contents.launcherDragManager.active
|
||||||
|
|
||||||
|
HomeScreenContents {
|
||||||
|
id: contents
|
||||||
|
homeScreenState: root.homeScreenState
|
||||||
|
|
||||||
|
height: pages.height
|
||||||
|
width: pages.width * 100
|
||||||
|
|
||||||
|
favoriteStrip: favoriteStrip
|
||||||
|
homeScreenPages: pages
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: FavoriteStrip {
|
||||||
|
id: favoriteStrip
|
||||||
|
|
||||||
|
appletsLayout: contents.appletsLayout
|
||||||
|
visible: favoriteStrip.flow.children.length > 0 || contents.launcherDragManager.active || contents.containsDrag
|
||||||
|
opacity: contents.launcherDragManager.active && HomeScreenComponents.ApplicationListModel.favoriteCount >= HomeScreenComponents.ApplicationListModel.maxFavoriteCount ? 0.3 : 1
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
target: favoriteStrip
|
||||||
|
onTapped: {
|
||||||
|
//Hides icons close button
|
||||||
|
contents.appletsLayout.appletsLayoutInteracted();
|
||||||
|
contents.appletsLayout.editMode = false;
|
||||||
|
}
|
||||||
|
onLongPressed: {
|
||||||
|
if (homeScreenState.currentSwipeState === HomeScreenState.DeterminingType) {
|
||||||
|
// only go into edit mode when not in a swipe
|
||||||
|
contents.appletsLayout.editMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onPressedChanged: root.parent.focus = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// app drawer
|
||||||
|
AppDrawerLoader {
|
||||||
|
id: appDrawerLoader
|
||||||
|
anchors.fill: parent
|
||||||
|
homeScreenState: root.homeScreenState
|
||||||
|
|
||||||
|
// account for panels
|
||||||
|
topPadding: MobileShell.TopPanelControls.panelHeight
|
||||||
|
rightPadding: MobileShell.TaskPanelControls.isPortrait ? 0 : MobileShell.TaskPanelControls.panelWidth
|
||||||
|
bottomPadding: MobileShell.TaskPanelControls.isPortrait ? MobileShell.TaskPanelControls.panelHeight : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,10 +24,9 @@ import "private" as Private
|
||||||
|
|
||||||
DragDrop.DropArea {
|
DragDrop.DropArea {
|
||||||
id: dropArea
|
id: dropArea
|
||||||
width: mainFlickable.width * 100
|
|
||||||
//width: Math.max(mainFlickable.width, mainFlickable.width * Math.ceil(appletsLayout.childrenRect.width/mainFlickable.width))
|
required property var homeScreenState
|
||||||
height: mainFlickable.height
|
|
||||||
|
|
||||||
property alias launcherDelegate: launcherRepeater.delegate
|
property alias launcherDelegate: launcherRepeater.delegate
|
||||||
property alias launcherModel: launcherRepeater.model
|
property alias launcherModel: launcherRepeater.model
|
||||||
property alias launcherRepeater: launcherRepeater
|
property alias launcherRepeater: launcherRepeater
|
||||||
|
|
@ -36,6 +35,7 @@ DragDrop.DropArea {
|
||||||
property alias appletsLayout: appletsLayout
|
property alias appletsLayout: appletsLayout
|
||||||
|
|
||||||
property FavoriteStrip favoriteStrip
|
property FavoriteStrip favoriteStrip
|
||||||
|
property HomeScreenPages homeScreenPages
|
||||||
|
|
||||||
property LauncherDragManager launcherDragManager: LauncherDragManager {
|
property LauncherDragManager launcherDragManager: LauncherDragManager {
|
||||||
id: launcherDragManager
|
id: launcherDragManager
|
||||||
|
|
@ -48,7 +48,7 @@ DragDrop.DropArea {
|
||||||
}
|
}
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
z: 999999
|
z: 999999
|
||||||
appletsLayout: homeScreenContents.appletsLayout
|
appletsLayout: dropArea.appletsLayout
|
||||||
favoriteStrip: dropArea.favoriteStrip
|
favoriteStrip: dropArea.favoriteStrip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,6 +63,7 @@ DragDrop.DropArea {
|
||||||
event.accept(event.proposedAction);
|
event.accept(event.proposedAction);
|
||||||
launcherDragManager.active = true;
|
launcherDragManager.active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onDragMove: {
|
onDragMove: {
|
||||||
let posInFavorites = favoriteStrip.mapFromItem(this, event.x, event.y);
|
let posInFavorites = favoriteStrip.mapFromItem(this, event.x, event.y);
|
||||||
if (posInFavorites.y > 0) {
|
if (posInFavorites.y > 0) {
|
||||||
|
|
@ -84,13 +85,13 @@ DragDrop.DropArea {
|
||||||
let scenePos = mapToItem(null, event.x, event.y);
|
let scenePos = mapToItem(null, event.x, event.y);
|
||||||
//SCROLL LEFT
|
//SCROLL LEFT
|
||||||
if (scenePos.x < PlasmaCore.Units.gridUnit) {
|
if (scenePos.x < PlasmaCore.Units.gridUnit) {
|
||||||
mainFlickable.scrollLeft();
|
homeScreenPages.scrollLeft();
|
||||||
//SCROLL RIGHT
|
//SCROLL RIGHT
|
||||||
} else if (scenePos.x > mainFlickable.width - PlasmaCore.Units.gridUnit) {
|
} else if (scenePos.x > homeScreenPages.width - PlasmaCore.Units.gridUnit) {
|
||||||
mainFlickable.scrollRight();
|
homeScreenPages.scrollRight();
|
||||||
//DON't SCROLL
|
//DON't SCROLL
|
||||||
} else {
|
} else {
|
||||||
mainFlickable.stopScroll();
|
homeScreenPages.stopScroll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,15 +160,20 @@ DragDrop.DropArea {
|
||||||
signal appletsLayoutInteracted
|
signal appletsLayoutInteracted
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
target: mainFlickable
|
target: homeScreenPages
|
||||||
enabled: appDrawer.status !== AbstractAppDrawer.Status.Open
|
enabled: homeScreenState.currentView === HomeScreenState.PageView
|
||||||
onTapped: {
|
onTapped: {
|
||||||
//Hides icons close button
|
//Hides icons close button
|
||||||
appletsLayout.appletsLayoutInteracted();
|
appletsLayout.appletsLayoutInteracted();
|
||||||
appletsLayout.editMode = false;
|
appletsLayout.editMode = false;
|
||||||
appletsLayout.forceActiveFocus();
|
appletsLayout.forceActiveFocus();
|
||||||
}
|
}
|
||||||
onLongPressed: appletsLayout.editMode = true;
|
onLongPressed: {
|
||||||
|
if (homeScreenState.currentSwipeState === HomeScreenState.DeterminingType) {
|
||||||
|
// only go into edit mode when not in a swipe
|
||||||
|
appletsLayout.editMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
onPressedChanged: appletsLayout.focus = true;
|
onPressedChanged: appletsLayout.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,20 +206,21 @@ DragDrop.DropArea {
|
||||||
placeHolder: ContainmentLayoutManager.PlaceHolder {}
|
placeHolder: ContainmentLayoutManager.PlaceHolder {}
|
||||||
//FIXME: move
|
//FIXME: move
|
||||||
PlasmaComponents.Label {
|
PlasmaComponents.Label {
|
||||||
id: metrics
|
id: metrics
|
||||||
text: "M\nM"
|
text: "M\nM"
|
||||||
visible: false
|
visible: false
|
||||||
font.pointSize: PlasmaCore.Theme.defaultFont.pointSize * 0.9
|
font.pointSize: PlasmaCore.Theme.defaultFont.pointSize * 0.9
|
||||||
}
|
}
|
||||||
LauncherRepeater {
|
LauncherRepeater {
|
||||||
id: launcherRepeater
|
id: launcherRepeater
|
||||||
|
homeScreenState: dropArea.homeScreenState
|
||||||
cellWidth: appletsLayout.cellWidth
|
cellWidth: appletsLayout.cellWidth
|
||||||
cellHeight: appletsLayout.cellHeight
|
cellHeight: appletsLayout.cellHeight
|
||||||
appletsLayout: appletsLayout
|
appletsLayout: appletsLayout
|
||||||
favoriteStrip: dropArea.favoriteStrip
|
favoriteStrip: dropArea.favoriteStrip
|
||||||
onScrollLeftRequested: mainFlickable.scrollLeft()
|
onScrollLeftRequested: homeScreenPages.scrollLeft()
|
||||||
onScrollRightRequested: mainFlickable.scrollRight()
|
onScrollRightRequested: homeScreenPages.scrollRight()
|
||||||
onStopScrollRequested: mainFlickable.stopScroll()
|
onStopScrollRequested: homeScreenPages.stopScroll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@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
|
||||||
*/
|
*/
|
||||||
|
|
@ -23,23 +24,15 @@ import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenCompon
|
||||||
|
|
||||||
Flickable {
|
Flickable {
|
||||||
id: mainFlickable
|
id: mainFlickable
|
||||||
|
|
||||||
property AbstractAppDrawer appDrawer
|
required property var homeScreenState
|
||||||
|
|
||||||
readonly property int totalPages: Math.ceil(contentWidth / width)
|
|
||||||
property int currentIndex: 0
|
|
||||||
|
|
||||||
property ContainmentLayoutManager.AppletsLayout appletsLayout: null
|
|
||||||
property Item footer
|
property Item footer
|
||||||
|
|
||||||
property alias dragGestureEnabled: gestureHandler.enabled
|
|
||||||
opacity: appDrawer ? 1 - appDrawer.openFactor : 1
|
|
||||||
transform: Translate {
|
|
||||||
y: appDrawer ? (-mainFlickable.height / 20) * appDrawer.openFactor : 0
|
|
||||||
}
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
property bool showAddPageIndicator: false
|
property bool showAddPageIndicator: false
|
||||||
|
|
||||||
|
contentX: homeScreenState.xPosition
|
||||||
|
|
||||||
contentHeight: height
|
contentHeight: height
|
||||||
interactive: false
|
interactive: false
|
||||||
|
|
||||||
|
|
@ -49,9 +42,6 @@ Flickable {
|
||||||
onFlickStarted: cancelEditModeForItemsRequested()
|
onFlickStarted: cancelEditModeForItemsRequested()
|
||||||
onFlickEnded: cancelEditModeForItemsRequested()
|
onFlickEnded: cancelEditModeForItemsRequested()
|
||||||
|
|
||||||
//onCurrentIndexChanged: contentX = width * currentIndex;
|
|
||||||
onContentXChanged: mainFlickable.currentIndex = Math.floor(contentX / width)
|
|
||||||
|
|
||||||
onFooterChanged: {
|
onFooterChanged: {
|
||||||
if (footer) {
|
if (footer) {
|
||||||
footer.parent = mainFlickable;
|
footer.parent = mainFlickable;
|
||||||
|
|
@ -61,7 +51,7 @@ Flickable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Autoscroll related functions
|
// autoscroll between pages (when holding a delegate to go to a new page)
|
||||||
function scrollLeft() {
|
function scrollLeft() {
|
||||||
if (mainFlickable.atXBeginning) {
|
if (mainFlickable.atXBeginning) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -88,63 +78,16 @@ Flickable {
|
||||||
scrollRightIndicator.opacity = 0;
|
scrollRightIndicator.opacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function snapPage() {
|
|
||||||
scrollAnim.running = false;
|
|
||||||
scrollAnim.to = mainFlickable.width * Math.round(mainFlickable.contentX / mainFlickable.width)
|
|
||||||
scrollAnim.running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function snapNextPage() {
|
|
||||||
scrollAnim.running = false;
|
|
||||||
scrollAnim.to = mainFlickable.width * Math.ceil(mainFlickable.contentX / mainFlickable.width)
|
|
||||||
scrollAnim.running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function snapPrevPage() {
|
|
||||||
scrollAnim.running = false;
|
|
||||||
scrollAnim.to = mainFlickable.width * Math.floor(mainFlickable.contentX / mainFlickable.width)
|
|
||||||
scrollAnim.running = true;
|
|
||||||
}
|
|
||||||
function scrollToPage(index) {
|
|
||||||
scrollAnim.running = false;
|
|
||||||
scrollAnim.to = mainFlickable.width * Math.max(0, Math.min(index, mainFlickable.contentWidth - mainFlickable.width))
|
|
||||||
scrollAnim.running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: autoScrollTimer
|
id: autoScrollTimer
|
||||||
property bool scrollRight: true
|
property bool scrollRight: true
|
||||||
repeat: true
|
repeat: true
|
||||||
interval: 1500
|
interval: 1500
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
scrollAnim.to = scrollRight ?
|
homeScreenState.animateGoToPageIndex(Math.max(0, homeScreenState.currentPageIndex + (scrollRight ? 1 : -1)), PlasmaCore.Units.longDuration * 2);
|
||||||
//Scroll Right
|
|
||||||
Math.min(mainFlickable.contentItem.width - mainFlickable.width, mainFlickable.contentX + mainFlickable.width) :
|
|
||||||
//Scroll Left
|
|
||||||
Math.max(0, mainFlickable.contentX - mainFlickable.width);
|
|
||||||
|
|
||||||
scrollAnim.running = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Private.DragGestureHandler {
|
|
||||||
id: gestureHandler
|
|
||||||
target: appletsLayout
|
|
||||||
appDrawer: mainFlickable.appDrawer
|
|
||||||
mainFlickable: mainFlickable
|
|
||||||
onSnapPage: mainFlickable.snapPage();
|
|
||||||
onSnapNextPage: mainFlickable.snapNextPage();
|
|
||||||
onSnapPrevPage: mainFlickable.snapPrevPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberAnimation {
|
|
||||||
id: scrollAnim
|
|
||||||
target: mainFlickable
|
|
||||||
properties: "contentX"
|
|
||||||
duration: PlasmaCore.Units.longDuration
|
|
||||||
easing.type: Easing.InOutQuad
|
|
||||||
}
|
|
||||||
|
|
||||||
PlasmaComponents.PageIndicator {
|
PlasmaComponents.PageIndicator {
|
||||||
id: pageIndicator
|
id: pageIndicator
|
||||||
anchors {
|
anchors {
|
||||||
|
|
@ -152,12 +95,16 @@ Flickable {
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
bottomMargin: mainFlickable.footer ? mainFlickable.footer.height : 0
|
bottomMargin: mainFlickable.footer ? mainFlickable.footer.height : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
PlasmaCore.ColorScope.inherit: false
|
PlasmaCore.ColorScope.inherit: false
|
||||||
PlasmaCore.ColorScope.colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
PlasmaCore.ColorScope.colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
||||||
|
|
||||||
parent: mainFlickable
|
parent: mainFlickable
|
||||||
count: mainFlickable.totalPages
|
|
||||||
visible: count > 1
|
visible: count > 1
|
||||||
currentIndex: Math.round(mainFlickable.contentX / mainFlickable.width)
|
|
||||||
|
count: homeScreenState.pagesCount
|
||||||
|
currentIndex: homeScreenState.currentPageIndex
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
property bool isAddPageIndicator: index === pageIndicator.count-1 && mainFlickable.showAddPageIndicator
|
property bool isAddPageIndicator: index === pageIndicator.count-1 && mainFlickable.showAddPageIndicator
|
||||||
implicitWidth: PlasmaCore.Units.gridUnit/2
|
implicitWidth: PlasmaCore.Units.gridUnit/2
|
||||||
|
|
@ -166,14 +113,13 @@ Flickable {
|
||||||
radius: width
|
radius: width
|
||||||
color: isAddPageIndicator ? "transparent" : PlasmaCore.ColorScope.textColor
|
color: isAddPageIndicator ? "transparent" : PlasmaCore.ColorScope.textColor
|
||||||
|
|
||||||
|
|
||||||
PlasmaComponents.Label {
|
PlasmaComponents.Label {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: parent.isAddPageIndicator
|
visible: parent.isAddPageIndicator
|
||||||
text: "⊕"
|
text: "⊕"
|
||||||
}
|
}
|
||||||
|
|
||||||
opacity: index === currentIndex ? 0.9 : pressed ? 0.7 : 0.5
|
opacity: index === pageIndicator.currentIndex ? 0.9 : pressed ? 0.7 : 0.5
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
OpacityAnimator {
|
OpacityAnimator {
|
||||||
duration: PlasmaCore.Units.longDuration
|
duration: PlasmaCore.Units.longDuration
|
||||||
413
components/mobilehomescreencomponents/qml/HomeScreenState.qml
Normal file
413
components/mobilehomescreencomponents/qml/HomeScreenState.qml
Normal file
|
|
@ -0,0 +1,413 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
import org.kde.plasma.core 2.1 as PlasmaCore
|
||||||
|
|
||||||
|
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State object for the homescreen.
|
||||||
|
*/
|
||||||
|
QtObject {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property real totalPagesWidth
|
||||||
|
|
||||||
|
required property var appDrawerFlickable
|
||||||
|
|
||||||
|
// dimensions of the homescreen area (not including top panel and task panel)
|
||||||
|
required property real availableScreenHeight
|
||||||
|
required property real availableScreenWidth
|
||||||
|
|
||||||
|
// offset from the bottom of the screen that the app drawer starts from,
|
||||||
|
// would be the height favourites strip
|
||||||
|
required property real appDrawerBottomOffset
|
||||||
|
|
||||||
|
// ~~ positioning ~~
|
||||||
|
|
||||||
|
// xPosition:
|
||||||
|
// We start at 0, which is the beginning x position of the row of pages (left-most side).
|
||||||
|
// Increasing x moves *right* toward the next page.
|
||||||
|
//
|
||||||
|
// yPosition:
|
||||||
|
// Increasing y results in moving *up* in the view.
|
||||||
|
// appDrawerOpenYPosition - The app drawer is opened (app drawer flickable is active iff it's not at the beginning).
|
||||||
|
// pagesYPosition - The app drawer is closed. Homescreen pages are visible, can swipe left/right between pages.
|
||||||
|
property real xPosition: 0
|
||||||
|
property real yPosition: pagesYPosition
|
||||||
|
|
||||||
|
// direction of the movement
|
||||||
|
property bool movingRight: false
|
||||||
|
property bool movingUp: false
|
||||||
|
|
||||||
|
// used for calculating movement direction
|
||||||
|
property real oldXPosition: 0
|
||||||
|
property real oldYPosition: 0
|
||||||
|
onXPositionChanged: {
|
||||||
|
movingRight = xPosition > oldXPosition;
|
||||||
|
oldXPosition = xPosition;
|
||||||
|
}
|
||||||
|
onYPositionChanged: {
|
||||||
|
movingUp = yPosition > oldYPosition;
|
||||||
|
oldYPosition = yPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// yPosition when the homescreen pages are visible
|
||||||
|
readonly property real pagesYPosition: availableScreenHeight - appDrawerBottomOffset
|
||||||
|
|
||||||
|
// yPosition when drawer is open
|
||||||
|
readonly property real appDrawerOpenYPosition: 0
|
||||||
|
|
||||||
|
// ~~ active state ~~
|
||||||
|
|
||||||
|
enum View {
|
||||||
|
PageView, // we are viewing the horizontal row of pages
|
||||||
|
AppDrawerBeginningView, // we are at the top of the app drawer (could either close it or scroll down)
|
||||||
|
AppDrawerView // we are in the app drawer, and not at the top of it
|
||||||
|
}
|
||||||
|
|
||||||
|
// the current view of the homescreen
|
||||||
|
property var currentView: HomeScreenState.PageView
|
||||||
|
|
||||||
|
// number of homescreen pages
|
||||||
|
readonly property int pagesCount: Math.floor(totalPagesWidth / pageWidth)
|
||||||
|
|
||||||
|
// current homescreen page index
|
||||||
|
readonly property int currentPageIndex: {
|
||||||
|
let candidateIndex = Math.round(xPosition / (pageSpacing + pageWidth));
|
||||||
|
return Math.max(0, Math.min(pagesCount - 1, candidateIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PageViewSwipeState {
|
||||||
|
SwipingPages, // horizontal movement between pages
|
||||||
|
SwipingAppDrawerVisibility, // opening/closing app drawer
|
||||||
|
SwipingAppDrawerList, // scrolling app drawer
|
||||||
|
SwipingActionPanel, // pulling down action panel
|
||||||
|
DeterminingType
|
||||||
|
}
|
||||||
|
|
||||||
|
// when we are at the PageView view, we need to distinguish horizontal swipes (changing pages)
|
||||||
|
// and vertical swipes (opening drawer)
|
||||||
|
property var currentSwipeState: HomeScreenState.DeterminingType
|
||||||
|
|
||||||
|
// threshold of movement in a direction before we count that as the defining SwipeState
|
||||||
|
readonly property real swipeStateDetermineThreshold: PlasmaCore.Units.smallSpacing
|
||||||
|
|
||||||
|
// we put the offset position here when determining the swipe type, before we
|
||||||
|
// transfer movement over to xPosition and yPosition
|
||||||
|
property real xDetermineSwipePosition: 0
|
||||||
|
property real yDetermineSwipePosition: 0
|
||||||
|
|
||||||
|
// whether animations are currently running
|
||||||
|
property bool animationsRunning: openDrawerAnim.running || closeDrawerAnim.running || xAnim.running
|
||||||
|
|
||||||
|
// whether the app drawer flickable should be interactive
|
||||||
|
property bool appDrawerInteractive: currentView === HomeScreenState.AppDrawerView
|
||||||
|
|
||||||
|
// ~~ measurement constants ~~
|
||||||
|
|
||||||
|
// dimensions of a page
|
||||||
|
readonly property real pageHeight: availableScreenHeight
|
||||||
|
readonly property real pageWidth: availableScreenWidth
|
||||||
|
|
||||||
|
// spacing between each homescreen page
|
||||||
|
readonly property real pageSpacing: 0
|
||||||
|
|
||||||
|
// ~~ signals and functions ~~
|
||||||
|
|
||||||
|
// cancel edit mode
|
||||||
|
signal cancelEditModeForItemsRequested
|
||||||
|
|
||||||
|
// cancel all animated moving, as another flick source is taking over
|
||||||
|
signal cancelAnimations()
|
||||||
|
onCancelAnimations: {
|
||||||
|
openDrawerAnim.stop();
|
||||||
|
closeDrawerAnim.stop();
|
||||||
|
xAnim.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// be very careful when resetting the swipe state
|
||||||
|
// ensure that we aren't in the middle of a gesture
|
||||||
|
function resetSwipeState() {
|
||||||
|
currentSwipeState = HomeScreenState.DeterminingType;
|
||||||
|
xDetermineSwipePosition = 0;
|
||||||
|
yDetermineSwipePosition = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAppDrawer() {
|
||||||
|
openDrawerAnim.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAppDrawerInstantly() {
|
||||||
|
yPosition = appDrawerOpenYPosition;
|
||||||
|
currentView = HomeScreenState.AppDrawerBeginningView;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAppDrawer() {
|
||||||
|
closeDrawerAnim.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAppDrawerInstantly() {
|
||||||
|
yPosition = pagesYPosition;
|
||||||
|
currentView = HomeScreenState.PageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the xPosition where the page will be centered on the screen
|
||||||
|
function xPositionFromPageIndex(index) {
|
||||||
|
return index * (pageWidth + pageSpacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// instantly go to the page index
|
||||||
|
function goToPageIndex(index) {
|
||||||
|
xPosition = xPositionFromPageIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// go to the page index, animated
|
||||||
|
function animateGoToPageIndex(index, duration) {
|
||||||
|
xAnim.duration = duration;
|
||||||
|
xAnim.to = xPositionFromPageIndex(index);
|
||||||
|
xAnim.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the position using an offset
|
||||||
|
// called by swipe provider flickable
|
||||||
|
function updatePositionWithOffset(x, y) {
|
||||||
|
switch (currentView) {
|
||||||
|
case HomeScreenState.PageView: {
|
||||||
|
switch (currentSwipeState) {
|
||||||
|
case HomeScreenState.DeterminingType:
|
||||||
|
xDetermineSwipePosition += x;
|
||||||
|
yDetermineSwipePosition += y;
|
||||||
|
|
||||||
|
// check if a swipetype can be determined and started
|
||||||
|
if (Math.abs(xDetermineSwipePosition) >= swipeStateDetermineThreshold) {
|
||||||
|
currentSwipeState = HomeScreenState.SwipingPages;
|
||||||
|
xDetermineSwipePosition = 0;
|
||||||
|
yDetermineSwipePosition = 0;
|
||||||
|
} else if (yDetermineSwipePosition >= swipeStateDetermineThreshold) {
|
||||||
|
currentSwipeState = HomeScreenState.SwipingActionPanel;
|
||||||
|
MobileShell.TopPanelControls.startSwipe();
|
||||||
|
xDetermineSwipePosition = 0;
|
||||||
|
yDetermineSwipePosition = 0;
|
||||||
|
} else if (-yDetermineSwipePosition >= swipeStateDetermineThreshold) {
|
||||||
|
currentSwipeState = HomeScreenState.SwipingAppDrawerVisibility;
|
||||||
|
xDetermineSwipePosition = 0;
|
||||||
|
yDetermineSwipePosition = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingPages:
|
||||||
|
xPosition += x;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingActionPanel:
|
||||||
|
yPosition = pagesYPosition;
|
||||||
|
if (y !== 0) {
|
||||||
|
MobileShell.TopPanelControls.requestRelativeScroll(y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingAppDrawerVisibility:
|
||||||
|
yPosition = Math.max(appDrawerOpenYPosition, Math.min(pagesYPosition, yPosition + y));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HomeScreenState.AppDrawerBeginningView: {
|
||||||
|
switch (currentSwipeState) {
|
||||||
|
case HomeScreenState.DeterminingType:
|
||||||
|
xDetermineSwipePosition += x;
|
||||||
|
yDetermineSwipePosition += y;
|
||||||
|
|
||||||
|
// check if a swipetype can be determined and started
|
||||||
|
if (yDetermineSwipePosition >= swipeStateDetermineThreshold) {
|
||||||
|
currentSwipeState = HomeScreenState.SwipingAppDrawerVisibility;
|
||||||
|
xDetermineSwipePosition = 0;
|
||||||
|
yDetermineSwipePosition = 0;
|
||||||
|
} else if (-yDetermineSwipePosition >= swipeStateDetermineThreshold) {
|
||||||
|
currentSwipeState = HomeScreenState.SwipingAppDrawerList;
|
||||||
|
yVelocityCalculator.startMeasure(appDrawerFlickable.contentY);
|
||||||
|
xDetermineSwipePosition = 0;
|
||||||
|
yDetermineSwipePosition = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HomeScreenState.SwipingAppDrawerVisibility:
|
||||||
|
yPosition = Math.max(appDrawerOpenYPosition, Math.min(pagesYPosition, yPosition + y));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingAppDrawerList:
|
||||||
|
// app drawer scrolling
|
||||||
|
let candidateNewPos = appDrawerFlickable.contentY - y;
|
||||||
|
appDrawerFlickable.contentY = candidateNewPos;
|
||||||
|
// update velocity
|
||||||
|
yVelocityCalculator.changePosition(appDrawerFlickable.contentY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HomeScreenState.AppDrawerView: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// called after a user finishes an interaction (ex. lets go of the screen)
|
||||||
|
// called by swipe provider flickable
|
||||||
|
function updateState() {
|
||||||
|
cancelAnimations();
|
||||||
|
|
||||||
|
// we need to always call resetSwipeState() after each interaction.
|
||||||
|
// if we have an animation to run, we rely on the animation to call the function.
|
||||||
|
// otherwise, we do it directly here.
|
||||||
|
|
||||||
|
switch (currentView) {
|
||||||
|
case HomeScreenState.PageView: {
|
||||||
|
|
||||||
|
// update vertical position
|
||||||
|
switch (currentSwipeState) {
|
||||||
|
case HomeScreenState.DeterminingType: {
|
||||||
|
movingUp ? closeAppDrawer() : openAppDrawer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingActionPanel: {
|
||||||
|
MobileShell.TopPanelControls.endSwipe();
|
||||||
|
root.resetSwipeState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingAppDrawerVisibility: {
|
||||||
|
movingUp ? closeAppDrawer() : openAppDrawer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HomeScreenState.SwipingPages: {
|
||||||
|
// update pages position
|
||||||
|
let currentPageIndexPosition = xPositionFromPageIndex(currentPageIndex);
|
||||||
|
let duration = PlasmaCore.Units.longDuration * 2;
|
||||||
|
|
||||||
|
if (xPosition < currentPageIndexPosition) {
|
||||||
|
if (movingRight) {
|
||||||
|
animateGoToPageIndex(currentPageIndex, duration);
|
||||||
|
} else {
|
||||||
|
animateGoToPageIndex(Math.max(0, currentPageIndex - 1), duration);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (movingRight) {
|
||||||
|
animateGoToPageIndex(Math.min(pagesCount - 1, currentPageIndex + 1), duration);
|
||||||
|
} else {
|
||||||
|
animateGoToPageIndex(currentPageIndex, duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// this shouldn't occur, but keeps consistent state if it does
|
||||||
|
root.resetSwipeState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HomeScreenState.AppDrawerBeginningView: {
|
||||||
|
|
||||||
|
switch (currentSwipeState) {
|
||||||
|
case HomeScreenState.DeterminingType:
|
||||||
|
case HomeScreenState.SwipingAppDrawerVisibility: {
|
||||||
|
movingUp ? closeAppDrawer() : openAppDrawer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HomeScreenState.SwipingAppDrawerList: {
|
||||||
|
currentView = HomeScreenState.AppDrawerView;
|
||||||
|
appDrawerFlickable.flick(0, -yVelocityCalculator.velocity);
|
||||||
|
root.resetSwipeState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// this shouldn't occur, but keeps consistent state if it does
|
||||||
|
root.resetSwipeState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HomeScreenState.AppDrawerView: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// measure velocity of our swipe in the app drawer, so that we can flick
|
||||||
|
property var yVelocityCalculator: MobileShell.VelocityCalculator {}
|
||||||
|
|
||||||
|
// listen to the app drawer's flickable for if it goes to the top of the list
|
||||||
|
// we then update our view state
|
||||||
|
property var appDrawerFlickableListener: Connections {
|
||||||
|
target: appDrawerFlickable
|
||||||
|
|
||||||
|
function onMovementEnded() {
|
||||||
|
if (root.currentView === HomeScreenState.AppDrawerView) {
|
||||||
|
if (appDrawerFlickable.contentY <= 0) {
|
||||||
|
root.currentView = HomeScreenState.AppDrawerBeginningView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDraggingChanged() {
|
||||||
|
if (!appDrawerFlickable.dragging) {
|
||||||
|
if (root.currentView === HomeScreenState.AppDrawerView) {
|
||||||
|
if (appDrawerFlickable.contentY <= 0) {
|
||||||
|
root.currentView = HomeScreenState.AppDrawerBeginningView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~ property animators ~~
|
||||||
|
|
||||||
|
property var xAnim: NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "xPosition"
|
||||||
|
easing.type: Easing.OutBack
|
||||||
|
onFinished: {
|
||||||
|
root.resetSwipeState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property var openDrawerAnim: NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "yPosition"
|
||||||
|
to: appDrawerOpenYPosition
|
||||||
|
duration: PlasmaCore.Units.longDuration * 2
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
|
||||||
|
onFinished: {
|
||||||
|
root.currentView = HomeScreenState.AppDrawerBeginningView;
|
||||||
|
root.resetSwipeState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property var closeDrawerAnim: NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "yPosition"
|
||||||
|
to: pagesYPosition
|
||||||
|
duration: PlasmaCore.Units.longDuration * 2
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
|
||||||
|
onFinished: {
|
||||||
|
root.currentView = HomeScreenState.PageView;
|
||||||
|
root.resetSwipeState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import QtQuick 2.4
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Controls 2.3 as Controls
|
|
||||||
|
|
||||||
import org.kde.plasma.plasmoid 2.0
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
|
||||||
import org.kde.kquickcontrolsaddons 2.0
|
|
||||||
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
|
|
||||||
|
|
||||||
LauncherContainer {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
readonly property int columns: Math.floor(root.flow.width / cellWidth)
|
|
||||||
readonly property int cellWidth: root.flow.width / Math.floor(root.flow.width / ((availableCellHeight - reservedSpaceForLabel) + PlasmaCore.Units.smallSpacing*4))
|
|
||||||
readonly property int cellHeight: availableCellHeight
|
|
||||||
|
|
||||||
signal launched
|
|
||||||
|
|
||||||
frame.width: width
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
parent: root.flow
|
|
||||||
model: HomeScreenComponents.ApplicationListModel
|
|
||||||
delegate: HomeDelegate {
|
|
||||||
id: delegate
|
|
||||||
width: root.cellWidth
|
|
||||||
height: root.cellHeight
|
|
||||||
|
|
||||||
parent: parentFromLocation
|
|
||||||
property Item parentFromLocation: {
|
|
||||||
switch (model.applicationLocation) {
|
|
||||||
case HomeScreenComponents.ApplicationListModel.Desktop:
|
|
||||||
return appletsLayout;
|
|
||||||
case HomeScreenComponents.ApplicationListModel.Favorites:
|
|
||||||
return favoriteStrip.flow;
|
|
||||||
default:
|
|
||||||
return root.flow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (model.applicationLocation === HomeScreenComponents.ApplicationListModel.Desktop) {
|
|
||||||
appletsLayout.restoreItem(delegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onLaunch: (x, y, icon, title) => {
|
|
||||||
if (icon !== "") {
|
|
||||||
MobileShell.HomeScreenControls.openAppAnimation(
|
|
||||||
icon,
|
|
||||||
title,
|
|
||||||
delegate.iconItem.Kirigami.ScenePosition.x + delegate.iconItem.width/2,
|
|
||||||
delegate.iconItem.Kirigami.ScenePosition.y + delegate.iconItem.height/2,
|
|
||||||
Math.min(delegate.iconItem.width, delegate.iconItem.height));
|
|
||||||
}
|
|
||||||
root.launched();
|
|
||||||
}
|
|
||||||
onParentFromLocationChanged: {
|
|
||||||
if (!launcherDragManager.active && parent != parentFromLocation) {
|
|
||||||
parent = parentFromLocation;
|
|
||||||
if (model.applicationLocation === HomeScreenComponents.ApplicationListModel.Favorites) {
|
|
||||||
plasmoid.nativeInterface.stackBefore(delegate, parentFromLocation.children[index]);
|
|
||||||
|
|
||||||
} else if (model.applicationLocation === HomeScreenComponents.ApplicationListModel.Grid) {
|
|
||||||
plasmoid.nativeInterface.stackBefore(delegate, parentFromLocation.children[Math.max(0, index - HomeScreenComponents.ApplicationListModel.favoriteCount)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -22,6 +22,9 @@ import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenCompon
|
||||||
Repeater {
|
Repeater {
|
||||||
id: launcherRepeater
|
id: launcherRepeater
|
||||||
model: HomeScreenComponents.FavoritesModel
|
model: HomeScreenComponents.FavoritesModel
|
||||||
|
|
||||||
|
required property var homeScreenState
|
||||||
|
|
||||||
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
||||||
property FavoriteStrip favoriteStrip
|
property FavoriteStrip favoriteStrip
|
||||||
property int cellWidth
|
property int cellWidth
|
||||||
|
|
@ -33,6 +36,8 @@ Repeater {
|
||||||
|
|
||||||
delegate: HomeDelegate {
|
delegate: HomeDelegate {
|
||||||
id: delegate
|
id: delegate
|
||||||
|
homeScreenState: launcherRepeater.homeScreenState
|
||||||
|
|
||||||
width: launcherRepeater.cellWidth
|
width: launcherRepeater.cellWidth
|
||||||
height: Math.min(parent.height, launcherRepeater.cellHeight)
|
height: Math.min(parent.height, launcherRepeater.cellHeight)
|
||||||
appletsLayout: launcherRepeater.appletsLayout
|
appletsLayout: launcherRepeater.appletsLayout
|
||||||
|
|
@ -74,7 +79,7 @@ Repeater {
|
||||||
if (pos.x < PlasmaCore.Units.gridUnit) {
|
if (pos.x < PlasmaCore.Units.gridUnit) {
|
||||||
launcherRepeater.scrollLeftRequested();
|
launcherRepeater.scrollLeftRequested();
|
||||||
//SCROLL RIGHT
|
//SCROLL RIGHT
|
||||||
} else if (pos.x > mainFlickable.width - PlasmaCore.Units.gridUnit) {
|
} else if (pos.x > homeScreenState.pageWidth - PlasmaCore.Units.gridUnit) {
|
||||||
launcherRepeater.scrollRightRequested();
|
launcherRepeater.scrollRightRequested();
|
||||||
//DON't SCROLL
|
//DON't SCROLL
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -20,44 +20,21 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
||||||
|
|
||||||
import "private"
|
import "../private"
|
||||||
|
import "../"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
required property var homeScreenState
|
||||||
enum Status {
|
|
||||||
Closed,
|
|
||||||
Peeking,
|
|
||||||
Open
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MovementDirection {
|
|
||||||
None = 0,
|
|
||||||
Up,
|
|
||||||
Down
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property int status: {
|
|
||||||
if (flickable.contentY >= topMargin.height) {
|
|
||||||
return AbstractAppDrawer.Status.Open;
|
|
||||||
} else if (flickable.contentY > 0) {
|
|
||||||
return AbstractAppDrawer.Status.Peeking;
|
|
||||||
} else {
|
|
||||||
return AbstractAppDrawer.Status.Closed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property real offset: 0
|
|
||||||
property real closedPositionOffset: 0
|
|
||||||
|
|
||||||
property real leftPadding: 0
|
property real leftPadding: 0
|
||||||
property real topPadding: 0
|
property real topPadding: 0
|
||||||
property real bottomPadding: 100
|
property real bottomPadding: 100
|
||||||
property real rightPadding: 0
|
property real rightPadding: 0
|
||||||
|
|
||||||
property alias flickable: view
|
property alias flickable: flickableBody.contentItem
|
||||||
|
|
||||||
property var contentItem
|
property Flickable contentItem
|
||||||
property real contentWidth: holdingColumn.width
|
property real contentWidth: holdingColumn.width
|
||||||
|
|
||||||
required property int headerHeight
|
required property int headerHeight
|
||||||
|
|
@ -69,54 +46,14 @@ Item {
|
||||||
readonly property int reservedSpaceForLabel: metrics.height
|
readonly property int reservedSpaceForLabel: metrics.height
|
||||||
property int availableCellHeight: PlasmaCore.Units.iconSizes.huge + reservedSpaceForLabel
|
property int availableCellHeight: PlasmaCore.Units.iconSizes.huge + reservedSpaceForLabel
|
||||||
|
|
||||||
readonly property real openFactor: factorNormalize(flickable.contentY / (units.gridUnit * 10))
|
readonly property real openFactor: factorNormalize(view.contentY / (PlasmaCore.Units.gridUnit * 10))
|
||||||
|
|
||||||
// height from top of screen that the drawer starts
|
// height from top of screen that the drawer starts
|
||||||
readonly property real drawerTopMargin: height - topPadding - bottomPadding - closedPositionOffset
|
readonly property real drawerTopMargin: height - topPadding - bottomPadding - closedPositionOffset
|
||||||
|
readonly property real closedPositionOffset: homeScreenState.appDrawerBottomOffset
|
||||||
|
|
||||||
//BEGIN functions
|
//BEGIN functions
|
||||||
|
|
||||||
function goToBeginning() {
|
|
||||||
scrollAnim.to = drawerTopMargin;
|
|
||||||
scrollAnim.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
function open() {
|
|
||||||
if (root.status === AbstractAppDrawer.Status.Open) {
|
|
||||||
flickable.flick(0,1);
|
|
||||||
} else {
|
|
||||||
goToBeginning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
if (root.status !== AbstractAppDrawer.Status.Closed) {
|
|
||||||
scrollAnim.to = 0;
|
|
||||||
scrollAnim.restart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// snap the drawer to an open or close position
|
|
||||||
function snapDrawerStatus() {
|
|
||||||
if (flickable.contentY > topMargin.height) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flickable.movementDirection === AbstractAppDrawer.MovementDirection.Up) {
|
|
||||||
if (flickable.contentY > topMargin.height / 8) { // over one eighth of the screen
|
|
||||||
open();
|
|
||||||
} else {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (flickable.contentY < 7 * topMargin.height / 8) { // over one eighth of the screen
|
|
||||||
close();
|
|
||||||
} else {
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function factorNormalize(num) {
|
function factorNormalize(num) {
|
||||||
return Math.min(1, Math.max(0, num));
|
return Math.min(1, Math.max(0, num));
|
||||||
}
|
}
|
||||||
|
|
@ -125,15 +62,6 @@ Item {
|
||||||
|
|
||||||
Drag.dragType: Drag.Automatic
|
Drag.dragType: Drag.Automatic
|
||||||
|
|
||||||
NumberAnimation {
|
|
||||||
id: scrollAnim
|
|
||||||
target: flickable
|
|
||||||
properties: "contentY"
|
|
||||||
duration: PlasmaCore.Units.longDuration * 2
|
|
||||||
easing.type: Easing.OutQuad
|
|
||||||
easing.amplitude: 2.0
|
|
||||||
}
|
|
||||||
|
|
||||||
PC3.Label {
|
PC3.Label {
|
||||||
id: metrics
|
id: metrics
|
||||||
text: "M\nM"
|
text: "M\nM"
|
||||||
|
|
@ -143,7 +71,7 @@ Item {
|
||||||
|
|
||||||
// bottom divider
|
// bottom divider
|
||||||
GradientBar {
|
GradientBar {
|
||||||
opacity: root.status !== AbstractAppDrawer.Status.Closed ? 0.6 : 0
|
opacity: (homeScreenState.currentView !== HomeScreenState.PageView || homeScreenState.currentSwipeState === HomeScreenState.SwipingAppDrawerVisibility) ? 0.6 : 0
|
||||||
visible: root.bottomPadding > 0
|
visible: root.bottomPadding > 0
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
@ -156,25 +84,14 @@ Item {
|
||||||
id: view
|
id: view
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
// We have a situation where this vertical flickable conflicts with the horizontal flickable used for homescreen pages.
|
// scroll events are handled by our flick container, we are only using this for positioning
|
||||||
// This flickable is on top of the other, so we disable it when it isn't open.
|
interactive: false
|
||||||
// We do the initial open gesture in private/DragGestureHandler.qml
|
contentY: Math.max(0, Math.min(root.drawerTopMargin, root.drawerTopMargin - homeScreenState.yPosition))
|
||||||
interactive: contentY > PlasmaCore.Units.gridUnit
|
|
||||||
|
|
||||||
contentHeight: column.implicitHeight
|
contentHeight: column.implicitHeight
|
||||||
contentWidth: -1
|
contentWidth: -1
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
|
||||||
// snap
|
|
||||||
onMovementEnded: root.snapDrawerStatus()
|
|
||||||
|
|
||||||
property int movementDirection: AbstractAppDrawer.MovementDirection.None
|
|
||||||
property real oldContentY
|
|
||||||
onContentYChanged: { // update state
|
|
||||||
movementDirection = oldContentY > contentY ? AbstractAppDrawer.MovementDirection.Down : AbstractAppDrawer.MovementDirection.Up;
|
|
||||||
oldContentY = contentY;
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: column
|
id: column
|
||||||
width: view.width
|
width: view.width
|
||||||
|
|
@ -196,8 +113,8 @@ Item {
|
||||||
}
|
}
|
||||||
factor: root.openFactor
|
factor: root.openFactor
|
||||||
flickable: view
|
flickable: view
|
||||||
onOpenRequested: root.open();
|
onOpenRequested: homeScreenState.openAppDrawer();
|
||||||
onCloseRequested: root.close();
|
onCloseRequested: homeScreenState.closeAppDrawer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,8 +123,6 @@ Item {
|
||||||
id: drawerFlickable
|
id: drawerFlickable
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: root.height
|
Layout.preferredHeight: root.height
|
||||||
|
|
||||||
visible: view.interactive // this is so that the favourites strip can be interacted with
|
|
||||||
leftPadding: root.leftPadding; topPadding: root.topPadding
|
leftPadding: root.leftPadding; topPadding: root.topPadding
|
||||||
rightPadding: root.rightPadding; bottomPadding: root.bottomPadding
|
rightPadding: root.rightPadding; bottomPadding: root.bottomPadding
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||||
|
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Window 2.12
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
|
import org.kde.plasma.plasmoid 2.0
|
||||||
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
|
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||||
|
|
||||||
|
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
||||||
|
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var homeScreenState
|
||||||
|
|
||||||
|
property real topPadding: 0
|
||||||
|
property real bottomPadding: 0
|
||||||
|
property real leftPadding: 0
|
||||||
|
property real rightPadding: 0
|
||||||
|
|
||||||
|
property string appDrawerType: "gridview" // gridview/listview
|
||||||
|
|
||||||
|
readonly property real headerHeight: Math.round(PlasmaCore.Units.gridUnit * 3)
|
||||||
|
|
||||||
|
sourceComponent: appDrawerType === "gridview" ? gridViewDrawer : listViewDrawer
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: headerComponent
|
||||||
|
|
||||||
|
AppDrawerHeader {
|
||||||
|
onSwitchToListRequested: {
|
||||||
|
if (root.appDrawerType !== "listview") {
|
||||||
|
root.appDrawerType = "listview";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSwitchToGridRequested: {
|
||||||
|
if (root.appDrawerType !== "gridview") {
|
||||||
|
root.appDrawerType = "gridview";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: listViewDrawer
|
||||||
|
ListViewAppDrawer {
|
||||||
|
anchors.fill: parent
|
||||||
|
topPadding: root.topPadding
|
||||||
|
bottomPadding: root.bottomPadding
|
||||||
|
leftPadding: root.leftPadding
|
||||||
|
rightPadding: root.rightPadding
|
||||||
|
|
||||||
|
homeScreenState: root.homeScreenState
|
||||||
|
headerItem: Loader { sourceComponent: headerComponent }
|
||||||
|
headerHeight: root.headerHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: gridViewDrawer
|
||||||
|
GridViewAppDrawer {
|
||||||
|
anchors.fill: parent
|
||||||
|
topPadding: root.topPadding
|
||||||
|
bottomPadding: root.bottomPadding
|
||||||
|
leftPadding: root.leftPadding
|
||||||
|
rightPadding: root.rightPadding
|
||||||
|
|
||||||
|
homeScreenState: root.homeScreenState
|
||||||
|
headerItem: Loader { sourceComponent: headerComponent }
|
||||||
|
headerHeight: root.headerHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
||||||
|
|
||||||
import "private"
|
import "../private"
|
||||||
|
|
||||||
AbstractAppDrawer {
|
AbstractAppDrawer {
|
||||||
id: root
|
id: root
|
||||||
|
|
@ -28,32 +28,7 @@ AbstractAppDrawer {
|
||||||
contentItem: GridView {
|
contentItem: GridView {
|
||||||
id: gridView
|
id: gridView
|
||||||
clip: true
|
clip: true
|
||||||
|
interactive: root.homeScreenState.appDrawerInteractive
|
||||||
// start location of dragging
|
|
||||||
property real startDragContentY
|
|
||||||
onMovementStarted: {
|
|
||||||
oldContentY = contentY;
|
|
||||||
startDragContentY = contentY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move drawer down when at the top of the app list
|
|
||||||
property real oldContentY
|
|
||||||
property bool movingDrawerDown: false
|
|
||||||
onContentYChanged: {
|
|
||||||
let candidateContentY = root.flickable.contentY - (oldContentY - contentY);
|
|
||||||
if (dragging && startDragContentY <= 0 && oldContentY <= 0 && candidateContentY <= root.drawerTopMargin) {
|
|
||||||
root.flickable.contentY = candidateContentY;
|
|
||||||
contentY = 0;
|
|
||||||
movingDrawerDown = true;
|
|
||||||
}
|
|
||||||
oldContentY = contentY;
|
|
||||||
}
|
|
||||||
onMovementEnded: {
|
|
||||||
if (movingDrawerDown) {
|
|
||||||
root.snapDrawerStatus();
|
|
||||||
movingDrawerDown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cellWidth: root.contentWidth / Math.floor(root.contentWidth / ((root.availableCellHeight - root.reservedSpaceForLabel) + PlasmaCore.Units.smallSpacing*4))
|
cellWidth: root.contentWidth / Math.floor(root.contentWidth / ((root.availableCellHeight - root.reservedSpaceForLabel) + PlasmaCore.Units.smallSpacing*4))
|
||||||
cellHeight: root.availableCellHeight
|
cellHeight: root.availableCellHeight
|
||||||
|
|
@ -78,7 +53,7 @@ AbstractAppDrawer {
|
||||||
root.Drag.hotSpot.y = y;
|
root.Drag.hotSpot.y = y;
|
||||||
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
||||||
|
|
||||||
root.close()
|
root.homeScreenState.closeAppDrawer()
|
||||||
|
|
||||||
root.dragStarted()
|
root.dragStarted()
|
||||||
root.Drag.active = true;
|
root.Drag.active = true;
|
||||||
|
|
@ -20,7 +20,7 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
||||||
|
|
||||||
import "private"
|
import "../private"
|
||||||
|
|
||||||
AbstractAppDrawer {
|
AbstractAppDrawer {
|
||||||
id: root
|
id: root
|
||||||
|
|
@ -31,31 +31,7 @@ AbstractAppDrawer {
|
||||||
reuseItems: true
|
reuseItems: true
|
||||||
cacheBuffer: model.count * delegateHeight // delegate height
|
cacheBuffer: model.count * delegateHeight // delegate height
|
||||||
|
|
||||||
// start location of dragging
|
interactive: root.homeScreenState.appDrawerInteractive
|
||||||
property real startDragContentY
|
|
||||||
onMovementStarted: {
|
|
||||||
oldContentY = contentY;
|
|
||||||
startDragContentY = contentY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move drawer down when at the top of the app list
|
|
||||||
property real oldContentY
|
|
||||||
property bool movingDrawerDown: false
|
|
||||||
onContentYChanged: {
|
|
||||||
let candidateContentY = root.flickable.contentY - (oldContentY - contentY);
|
|
||||||
if (dragging && startDragContentY <= 0 && oldContentY <= 0 && candidateContentY <= root.drawerTopMargin) {
|
|
||||||
root.flickable.contentY = candidateContentY;
|
|
||||||
contentY = 0;
|
|
||||||
movingDrawerDown = true;
|
|
||||||
}
|
|
||||||
oldContentY = contentY;
|
|
||||||
}
|
|
||||||
onMovementEnded: {
|
|
||||||
if (movingDrawerDown) {
|
|
||||||
root.snapDrawerStatus();
|
|
||||||
movingDrawerDown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property int delegateHeight: PlasmaCore.Units.gridUnit * 3
|
property int delegateHeight: PlasmaCore.Units.gridUnit * 3
|
||||||
|
|
||||||
|
|
@ -74,7 +50,7 @@ AbstractAppDrawer {
|
||||||
root.Drag.hotSpot.y = y;
|
root.Drag.hotSpot.y = y;
|
||||||
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
||||||
|
|
||||||
root.close()
|
root.homeScreenState.closeAppDrawer()
|
||||||
|
|
||||||
root.dragStarted()
|
root.dragStarted()
|
||||||
root.Drag.active = true;
|
root.Drag.active = true;
|
||||||
|
|
@ -22,6 +22,7 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: arrowUpIcon
|
id: arrowUpIcon
|
||||||
z: 9
|
z: 9
|
||||||
|
|
||||||
property Flickable flickable
|
property Flickable flickable
|
||||||
property real factor: 0
|
property real factor: 0
|
||||||
|
|
||||||
|
|
@ -32,7 +33,6 @@ MouseArea {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
openRequested();
|
openRequested();
|
||||||
scrollAnim.restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,23 @@ module org.kde.plasma.private.mobilehomescreencomponents
|
||||||
|
|
||||||
plugin mobilehomescreencomponentsplugin
|
plugin mobilehomescreencomponentsplugin
|
||||||
|
|
||||||
AbstractAppDrawer 0.1 AbstractAppDrawer.qml
|
AbstractAppDrawer 0.1 appdrawer/AbstractAppDrawer.qml
|
||||||
GridViewAppDrawer 0.1 GridViewAppDrawer.qml
|
AppDrawerHeader 0.1 appdrawer/AppDrawerHeader.qml
|
||||||
ListViewAppDrawer 0.1 ListViewAppDrawer.qml
|
AppDrawerLoader 0.1 appdrawer/AppDrawerLoader.qml
|
||||||
DrawerListDelegate 0.1 DrawerListDelegate.qml
|
DrawerGridDelegate 0.1 appdrawer/DrawerGridDelegate.qml
|
||||||
DrawerGridDelegate 0.1 DrawerGridDelegate.qml
|
DrawerListDelegate 0.1 appdrawer/DrawerListDelegate.qml
|
||||||
|
GridViewAppDrawer 0.1 appdrawer/GridViewAppDrawer.qml
|
||||||
|
ListViewAppDrawer 0.1 appdrawer/ListViewAppDrawer.qml
|
||||||
|
|
||||||
FavoriteStrip 0.1 FavoriteStrip.qml
|
FavoriteStrip 0.1 FavoriteStrip.qml
|
||||||
FlickablePages 0.1 FlickablePages.qml
|
FlickContainer 0.1 FlickContainer.qml
|
||||||
HomeDelegate 0.1 HomeDelegate.qml
|
HomeDelegate 0.1 HomeDelegate.qml
|
||||||
|
HomeScreen 0.1 HomeScreen.qml
|
||||||
HomeScreenContents 0.1 HomeScreenContents.qml
|
HomeScreenContents 0.1 HomeScreenContents.qml
|
||||||
|
HomeScreenPages 0.1 HomeScreenPages.qml
|
||||||
|
HomeScreenState 0.1 HomeScreenState.qml
|
||||||
LauncherContainer 0.1 LauncherContainer.qml
|
LauncherContainer 0.1 LauncherContainer.qml
|
||||||
LauncherDragManager 0.1 LauncherDragManager.qml
|
LauncherDragManager 0.1 LauncherDragManager.qml
|
||||||
LauncherGrid 0.1 LauncherGrid.qml
|
LauncherGrid 0.1 LauncherGrid.qml
|
||||||
LauncherRepeater 0.1 LauncherRepeater.qml
|
LauncherRepeater 0.1 LauncherRepeater.qml
|
||||||
MobileAppletContainer 0.1 MobileAppletContainer.qml
|
MobileAppletContainer 0.1 MobileAppletContainer.qml
|
||||||
|
|
||||||
|
|
|
||||||
72
components/mobileshell/qml/components/VelocityCalculator.qml
Normal file
72
components/mobileshell/qml/components/VelocityCalculator.qml
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2013 Canonical Ltd. <legal@canonical.com>
|
||||||
|
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool zeroVelocityCounts: false
|
||||||
|
|
||||||
|
property real velocity: 0
|
||||||
|
|
||||||
|
function changePosition(position) {
|
||||||
|
__pushDragEvent(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startMeasure(position) {
|
||||||
|
__dragEvents = [];
|
||||||
|
__pushDragEvent(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
//BEGIN internal
|
||||||
|
|
||||||
|
property var __dragEvents: []
|
||||||
|
property var __dateTime: new function() {
|
||||||
|
this.getCurrentTimeMs = function() {return new Date().getTime()}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __updateSpeed() {
|
||||||
|
var totalSpeed = 0;
|
||||||
|
for (var i = 0; i < __dragEvents.length; i++) {
|
||||||
|
totalSpeed += __dragEvents[i][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zeroVelocityCounts || Math.abs(totalSpeed) > 0.001) {
|
||||||
|
velocity = totalSpeed / __dragEvents.length * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __cullOldDragEvents(currentTime) {
|
||||||
|
// cull events older than 50 ms but always keep the latest 2 events
|
||||||
|
for (var numberOfCulledEvents = 0; numberOfCulledEvents < __dragEvents.length-2; numberOfCulledEvents++) {
|
||||||
|
// __dragEvents[numberOfCulledEvents][0] is the dragTime
|
||||||
|
if (currentTime - __dragEvents[numberOfCulledEvents][0] <= 50) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
__dragEvents.splice(0, numberOfCulledEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
function __getEventSpeed(currentTime, position) {
|
||||||
|
if (__dragEvents.length != 0) {
|
||||||
|
var lastDrag = __dragEvents[__dragEvents.length-1];
|
||||||
|
var duration = Math.max(1, currentTime - lastDrag[0]);
|
||||||
|
return (position - lastDrag[1]) / duration;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __pushDragEvent(position) {
|
||||||
|
let currentTime = __dateTime.getCurrentTimeMs();
|
||||||
|
__dragEvents.push([currentTime, position, __getEventSpeed(currentTime, position)]);
|
||||||
|
__cullOldDragEvents(currentTime);
|
||||||
|
__updateSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
//END internal
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ ActionDrawerOpenSurface 1.0 actiondrawer/ActionDrawerOpenSurface.qml
|
||||||
BaseItem 1.0 components/BaseItem.qml
|
BaseItem 1.0 components/BaseItem.qml
|
||||||
Direction 1.0 components/Direction.qml
|
Direction 1.0 components/Direction.qml
|
||||||
StartupFeedback 1.0 components/StartupFeedback.qml
|
StartupFeedback 1.0 components/StartupFeedback.qml
|
||||||
|
VelocityCalculator 1.0 components/VelocityCalculator.qml
|
||||||
|
|
||||||
# /dataproviders
|
# /dataproviders
|
||||||
singleton BatteryProvider 1.0 dataproviders/BatteryProvider.qml
|
singleton BatteryProvider 1.0 dataproviders/BatteryProvider.qml
|
||||||
|
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
|
||||||
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import QtQuick 2.12
|
|
||||||
import QtQuick.Window 2.12
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
|
|
||||||
import org.kde.plasma.plasmoid 2.0
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
|
||||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
|
||||||
|
|
||||||
import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenComponents
|
|
||||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property alias flickablePages: mainFlickable
|
|
||||||
property alias homeScreenContents: contents
|
|
||||||
|
|
||||||
// listview/gridview header
|
|
||||||
property string appDrawerType: "gridview" // gridview/listview
|
|
||||||
property alias appDrawer: appDrawerLoader.item
|
|
||||||
|
|
||||||
readonly property real headerHeight: Math.round(PlasmaCore.Units.gridUnit * 3)
|
|
||||||
|
|
||||||
//BEGIN functions
|
|
||||||
|
|
||||||
function activate() {
|
|
||||||
// there's a couple of steps:
|
|
||||||
// - minimize windows
|
|
||||||
// - open app drawer
|
|
||||||
// - restore windows
|
|
||||||
if (!plasmoid.nativeInterface.showingDesktop) {
|
|
||||||
plasmoid.nativeInterface.showingDesktop = true
|
|
||||||
} else if (appDrawer.status !== HomeScreenComponents.AbstractAppDrawer.Status.Open) {
|
|
||||||
mainFlickable.currentIndex = 0
|
|
||||||
root.appDrawer.open()
|
|
||||||
} else {
|
|
||||||
plasmoid.nativeInterface.showingDesktop = false
|
|
||||||
root.appDrawer.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//END functions
|
|
||||||
|
|
||||||
HomeScreenComponents.FlickablePages {
|
|
||||||
id: mainFlickable
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
fill: parent
|
|
||||||
topMargin: plasmoid.availableScreenRect.y
|
|
||||||
bottomMargin: plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y
|
|
||||||
}
|
|
||||||
|
|
||||||
appletsLayout: homeScreenContents.appletsLayout
|
|
||||||
|
|
||||||
appDrawer: root.appDrawer
|
|
||||||
contentWidth: Math.max(width, width * Math.ceil(homeScreenContents.itemsBoundingRect.width/width)) + (homeScreenContents.launcherDragManager.active ? width : 0)
|
|
||||||
showAddPageIndicator: homeScreenContents.launcherDragManager.active
|
|
||||||
|
|
||||||
dragGestureEnabled: root.parent.focus && (!root.appDrawer || root.appDrawer.status !== HomeScreenComponents.AbstractAppDrawer.Status.Open) && !appletsLayout.editMode && !plasmoid.editMode && !homeScreenContents.launcherDragManager.active
|
|
||||||
|
|
||||||
HomeScreenComponents.HomeScreenContents {
|
|
||||||
id: contents
|
|
||||||
width: mainFlickable.width * 100
|
|
||||||
favoriteStrip: favoriteStrip
|
|
||||||
}
|
|
||||||
|
|
||||||
footer: HomeScreenComponents.FavoriteStrip {
|
|
||||||
id: favoriteStrip
|
|
||||||
|
|
||||||
appletsLayout: homeScreenContents.appletsLayout
|
|
||||||
visible: favoriteStrip.flow.children.length > 0 || homeScreenContents.launcherDragManager.active || homeScreenContents.containsDrag
|
|
||||||
opacity: homeScreenContents.launcherDragManager.active && HomeScreenComponents.ApplicationListModel.favoriteCount >= HomeScreenComponents.ApplicationListModel.maxFavoriteCount ? 0.3 : 1
|
|
||||||
|
|
||||||
TapHandler {
|
|
||||||
target: favoriteStrip
|
|
||||||
onTapped: {
|
|
||||||
//Hides icons close button
|
|
||||||
homeScreenContents.appletsLayout.appletsLayoutInteracted();
|
|
||||||
homeScreenContents.appletsLayout.editMode = false;
|
|
||||||
}
|
|
||||||
onLongPressed: homeScreenContents.appletsLayout.editMode = true;
|
|
||||||
onPressedChanged: root.parent.focus = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: headerComponent
|
|
||||||
|
|
||||||
AppDrawerHeader {
|
|
||||||
onSwitchToListRequested: {
|
|
||||||
if (root.appDrawerType !== "listview") {
|
|
||||||
root.appDrawerType = "listview";
|
|
||||||
appDrawer.flickable.goToBeginning(); // jump to top
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSwitchToGridRequested: {
|
|
||||||
if (root.appDrawerType !== "gridview") {
|
|
||||||
root.appDrawerType = "gridview";
|
|
||||||
appDrawer.flickable.goToBeginning(); // jump to top
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: listViewDrawer
|
|
||||||
HomeScreenComponents.ListViewAppDrawer {
|
|
||||||
anchors.fill: parent
|
|
||||||
topPadding: plasmoid.availableScreenRect.y
|
|
||||||
|
|
||||||
// pad for navbar
|
|
||||||
rightPadding: MobileShell.TaskPanelControls.isPortrait ? 0 : MobileShell.TaskPanelControls.panelWidth
|
|
||||||
bottomPadding: plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y
|
|
||||||
|
|
||||||
closedPositionOffset: favoriteStrip.height
|
|
||||||
|
|
||||||
headerItem: Loader { sourceComponent: headerComponent }
|
|
||||||
headerHeight: root.headerHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: gridViewDrawer
|
|
||||||
HomeScreenComponents.GridViewAppDrawer {
|
|
||||||
anchors.fill: parent
|
|
||||||
topPadding: plasmoid.availableScreenRect.y
|
|
||||||
|
|
||||||
// pad for navbar
|
|
||||||
rightPadding: MobileShell.TaskPanelControls.isPortrait ? 0 : MobileShell.TaskPanelControls.panelWidth
|
|
||||||
bottomPadding: plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y
|
|
||||||
|
|
||||||
closedPositionOffset: favoriteStrip.height
|
|
||||||
|
|
||||||
headerItem: Loader { sourceComponent: headerComponent }
|
|
||||||
headerHeight: root.headerHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
|
||||||
id: appDrawerLoader
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: appDrawerType === "gridview" ? gridViewDrawer : listViewDrawer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -28,7 +28,7 @@ FocusScope {
|
||||||
if (!componentComplete) {
|
if (!componentComplete) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HomeScreenComponents.ApplicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / homescreen.homeScreenContents.appletsLayout.cellWidth));
|
HomeScreenComponents.ApplicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / homescreen.homeScreenContents.favoriteStrip.cellWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
function triggerHomeScreen() {
|
function triggerHomeScreen() {
|
||||||
|
|
@ -50,21 +50,22 @@ FocusScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onResetHomeScreenPosition() {
|
function onResetHomeScreenPosition() {
|
||||||
homescreen.flickablePages.scrollToPage(0);
|
homescreen.homeScreenState.goToPageIndex(0);
|
||||||
homescreen.appDrawer.close();
|
homescreen.homeScreenState.closeAppDrawer();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSnapHomeScreenPosition() {
|
function onSnapHomeScreenPosition() {
|
||||||
if (lastRequestedPosition < 0) {
|
if (lastRequestedPosition < 0) {
|
||||||
homescreen.appDrawer.open();
|
homescreen.homeScreenState.openAppDrawer();
|
||||||
} else {
|
} else {
|
||||||
homescreen.appDrawer.close();
|
homescreen.homeScreenState.closeAppDrawer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRequestRelativeScroll(pos) {
|
function onRequestRelativeScroll(pos) {
|
||||||
homescreen.appDrawer.offset -= pos.y;
|
// TODO
|
||||||
lastRequestedPosition = pos.y;
|
//homescreen.appDrawer.offset -= pos.y;
|
||||||
|
//lastRequestedPosition = pos.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOpenAppAnimation(splashIcon, title, x, y, sourceIconSize) {
|
function onOpenAppAnimation(splashIcon, title, x, y, sourceIconSize) {
|
||||||
|
|
@ -110,14 +111,29 @@ FocusScope {
|
||||||
|
|
||||||
Plasmoid.onActivated: {
|
Plasmoid.onActivated: {
|
||||||
console.log("Triggered!", plasmoid.nativeInterface.showingDesktop)
|
console.log("Triggered!", plasmoid.nativeInterface.showingDesktop)
|
||||||
homescreen.activate();
|
|
||||||
|
// there's a couple of steps:
|
||||||
|
// - minimize windows
|
||||||
|
// - open app drawer
|
||||||
|
// - restore windows
|
||||||
|
if (!plasmoid.nativeInterface.showingDesktop) {
|
||||||
|
plasmoid.nativeInterface.showingDesktop = true;
|
||||||
|
} else if (homescreen.homeScreenState.currentView === MobileShell.HomeScreenState.PageView) {
|
||||||
|
homescreen.homeScreenState.openAppDrawer()
|
||||||
|
} else {
|
||||||
|
plasmoid.nativeInterface.showingDesktop = false
|
||||||
|
homescreen.homeScreenState.closeAppDrawer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// homescreen component
|
// homescreen component
|
||||||
HomeScreen {
|
HomeScreenComponents.HomeScreen {
|
||||||
id: homescreen
|
id: homescreen
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// make the homescreen not interactable when task switcher or startup feedback is on
|
||||||
|
interactive: !taskSwitcher.visible && !startupFeedback.visible
|
||||||
|
|
||||||
opacity: 1
|
opacity: 1
|
||||||
NumberAnimation on opacity {
|
NumberAnimation on opacity {
|
||||||
id: opacityAnimation
|
id: opacityAnimation
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue