mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +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 {
|
||||
id: delegate
|
||||
|
||||
property var homeScreenState
|
||||
|
||||
z: dragActive ? 1 : 0
|
||||
|
||||
property var modelData: typeof model !== "undefined" ? model : null
|
||||
|
|
@ -64,11 +66,11 @@ ContainmentLayoutManager.ItemContainer {
|
|||
}
|
||||
}
|
||||
Connections {
|
||||
target: mainFlickable
|
||||
target: homeScreenState
|
||||
function onCancelEditModeForItemsRequested() {
|
||||
cancelEdit()
|
||||
}
|
||||
function onContentYChanged() {
|
||||
function onXPositionChanged() {
|
||||
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 {
|
||||
id: dropArea
|
||||
width: mainFlickable.width * 100
|
||||
//width: Math.max(mainFlickable.width, mainFlickable.width * Math.ceil(appletsLayout.childrenRect.width/mainFlickable.width))
|
||||
height: mainFlickable.height
|
||||
|
||||
|
||||
required property var homeScreenState
|
||||
|
||||
property alias launcherDelegate: launcherRepeater.delegate
|
||||
property alias launcherModel: launcherRepeater.model
|
||||
property alias launcherRepeater: launcherRepeater
|
||||
|
|
@ -36,6 +35,7 @@ DragDrop.DropArea {
|
|||
property alias appletsLayout: appletsLayout
|
||||
|
||||
property FavoriteStrip favoriteStrip
|
||||
property HomeScreenPages homeScreenPages
|
||||
|
||||
property LauncherDragManager launcherDragManager: LauncherDragManager {
|
||||
id: launcherDragManager
|
||||
|
|
@ -48,7 +48,7 @@ DragDrop.DropArea {
|
|||
}
|
||||
anchors.fill: parent
|
||||
z: 999999
|
||||
appletsLayout: homeScreenContents.appletsLayout
|
||||
appletsLayout: dropArea.appletsLayout
|
||||
favoriteStrip: dropArea.favoriteStrip
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +63,7 @@ DragDrop.DropArea {
|
|||
event.accept(event.proposedAction);
|
||||
launcherDragManager.active = true;
|
||||
}
|
||||
|
||||
onDragMove: {
|
||||
let posInFavorites = favoriteStrip.mapFromItem(this, event.x, event.y);
|
||||
if (posInFavorites.y > 0) {
|
||||
|
|
@ -84,13 +85,13 @@ DragDrop.DropArea {
|
|||
let scenePos = mapToItem(null, event.x, event.y);
|
||||
//SCROLL LEFT
|
||||
if (scenePos.x < PlasmaCore.Units.gridUnit) {
|
||||
mainFlickable.scrollLeft();
|
||||
homeScreenPages.scrollLeft();
|
||||
//SCROLL RIGHT
|
||||
} else if (scenePos.x > mainFlickable.width - PlasmaCore.Units.gridUnit) {
|
||||
mainFlickable.scrollRight();
|
||||
} else if (scenePos.x > homeScreenPages.width - PlasmaCore.Units.gridUnit) {
|
||||
homeScreenPages.scrollRight();
|
||||
//DON't SCROLL
|
||||
} else {
|
||||
mainFlickable.stopScroll();
|
||||
homeScreenPages.stopScroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -159,15 +160,20 @@ DragDrop.DropArea {
|
|||
signal appletsLayoutInteracted
|
||||
|
||||
TapHandler {
|
||||
target: mainFlickable
|
||||
enabled: appDrawer.status !== AbstractAppDrawer.Status.Open
|
||||
target: homeScreenPages
|
||||
enabled: homeScreenState.currentView === HomeScreenState.PageView
|
||||
onTapped: {
|
||||
//Hides icons close button
|
||||
appletsLayout.appletsLayoutInteracted();
|
||||
appletsLayout.editMode = false;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -200,20 +206,21 @@ DragDrop.DropArea {
|
|||
placeHolder: ContainmentLayoutManager.PlaceHolder {}
|
||||
//FIXME: move
|
||||
PlasmaComponents.Label {
|
||||
id: metrics
|
||||
text: "M\nM"
|
||||
visible: false
|
||||
font.pointSize: PlasmaCore.Theme.defaultFont.pointSize * 0.9
|
||||
}
|
||||
id: metrics
|
||||
text: "M\nM"
|
||||
visible: false
|
||||
font.pointSize: PlasmaCore.Theme.defaultFont.pointSize * 0.9
|
||||
}
|
||||
LauncherRepeater {
|
||||
id: launcherRepeater
|
||||
homeScreenState: dropArea.homeScreenState
|
||||
cellWidth: appletsLayout.cellWidth
|
||||
cellHeight: appletsLayout.cellHeight
|
||||
appletsLayout: appletsLayout
|
||||
favoriteStrip: dropArea.favoriteStrip
|
||||
onScrollLeftRequested: mainFlickable.scrollLeft()
|
||||
onScrollRightRequested: mainFlickable.scrollRight()
|
||||
onStopScrollRequested: mainFlickable.stopScroll()
|
||||
onScrollLeftRequested: homeScreenPages.scrollLeft()
|
||||
onScrollRightRequested: homeScreenPages.scrollRight()
|
||||
onStopScrollRequested: homeScreenPages.stopScroll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
|
@ -23,23 +24,15 @@ import org.kde.plasma.private.mobilehomescreencomponents 0.1 as HomeScreenCompon
|
|||
|
||||
Flickable {
|
||||
id: mainFlickable
|
||||
|
||||
property AbstractAppDrawer appDrawer
|
||||
|
||||
readonly property int totalPages: Math.ceil(contentWidth / width)
|
||||
property int currentIndex: 0
|
||||
|
||||
property ContainmentLayoutManager.AppletsLayout appletsLayout: null
|
||||
|
||||
required property var homeScreenState
|
||||
|
||||
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
|
||||
|
||||
contentX: homeScreenState.xPosition
|
||||
|
||||
contentHeight: height
|
||||
interactive: false
|
||||
|
||||
|
|
@ -49,9 +42,6 @@ Flickable {
|
|||
onFlickStarted: cancelEditModeForItemsRequested()
|
||||
onFlickEnded: cancelEditModeForItemsRequested()
|
||||
|
||||
//onCurrentIndexChanged: contentX = width * currentIndex;
|
||||
onContentXChanged: mainFlickable.currentIndex = Math.floor(contentX / width)
|
||||
|
||||
onFooterChanged: {
|
||||
if (footer) {
|
||||
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() {
|
||||
if (mainFlickable.atXBeginning) {
|
||||
return;
|
||||
|
|
@ -88,63 +78,16 @@ Flickable {
|
|||
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 {
|
||||
id: autoScrollTimer
|
||||
property bool scrollRight: true
|
||||
repeat: true
|
||||
interval: 1500
|
||||
onTriggered: {
|
||||
scrollAnim.to = scrollRight ?
|
||||
//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;
|
||||
homeScreenState.animateGoToPageIndex(Math.max(0, homeScreenState.currentPageIndex + (scrollRight ? 1 : -1)), PlasmaCore.Units.longDuration * 2);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
id: pageIndicator
|
||||
anchors {
|
||||
|
|
@ -152,12 +95,16 @@ Flickable {
|
|||
horizontalCenter: parent.horizontalCenter
|
||||
bottomMargin: mainFlickable.footer ? mainFlickable.footer.height : 0
|
||||
}
|
||||
|
||||
PlasmaCore.ColorScope.inherit: false
|
||||
PlasmaCore.ColorScope.colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
|
||||
|
||||
parent: mainFlickable
|
||||
count: mainFlickable.totalPages
|
||||
visible: count > 1
|
||||
currentIndex: Math.round(mainFlickable.contentX / mainFlickable.width)
|
||||
|
||||
count: homeScreenState.pagesCount
|
||||
currentIndex: homeScreenState.currentPageIndex
|
||||
|
||||
delegate: Rectangle {
|
||||
property bool isAddPageIndicator: index === pageIndicator.count-1 && mainFlickable.showAddPageIndicator
|
||||
implicitWidth: PlasmaCore.Units.gridUnit/2
|
||||
|
|
@ -166,14 +113,13 @@ Flickable {
|
|||
radius: width
|
||||
color: isAddPageIndicator ? "transparent" : PlasmaCore.ColorScope.textColor
|
||||
|
||||
|
||||
PlasmaComponents.Label {
|
||||
anchors.centerIn: parent
|
||||
visible: parent.isAddPageIndicator
|
||||
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 {
|
||||
OpacityAnimator {
|
||||
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 {
|
||||
id: launcherRepeater
|
||||
model: HomeScreenComponents.FavoritesModel
|
||||
|
||||
required property var homeScreenState
|
||||
|
||||
property ContainmentLayoutManager.AppletsLayout appletsLayout
|
||||
property FavoriteStrip favoriteStrip
|
||||
property int cellWidth
|
||||
|
|
@ -33,6 +36,8 @@ Repeater {
|
|||
|
||||
delegate: HomeDelegate {
|
||||
id: delegate
|
||||
homeScreenState: launcherRepeater.homeScreenState
|
||||
|
||||
width: launcherRepeater.cellWidth
|
||||
height: Math.min(parent.height, launcherRepeater.cellHeight)
|
||||
appletsLayout: launcherRepeater.appletsLayout
|
||||
|
|
@ -74,7 +79,7 @@ Repeater {
|
|||
if (pos.x < PlasmaCore.Units.gridUnit) {
|
||||
launcherRepeater.scrollLeftRequested();
|
||||
//SCROLL RIGHT
|
||||
} else if (pos.x > mainFlickable.width - PlasmaCore.Units.gridUnit) {
|
||||
} else if (pos.x > homeScreenState.pageWidth - PlasmaCore.Units.gridUnit) {
|
||||
launcherRepeater.scrollRightRequested();
|
||||
//DON't SCROLL
|
||||
} 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 "private"
|
||||
import "../private"
|
||||
import "../"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
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
|
||||
required property var homeScreenState
|
||||
|
||||
property real leftPadding: 0
|
||||
property real topPadding: 0
|
||||
property real bottomPadding: 100
|
||||
property real rightPadding: 0
|
||||
|
||||
property alias flickable: view
|
||||
property alias flickable: flickableBody.contentItem
|
||||
|
||||
property var contentItem
|
||||
property Flickable contentItem
|
||||
property real contentWidth: holdingColumn.width
|
||||
|
||||
required property int headerHeight
|
||||
|
|
@ -69,54 +46,14 @@ Item {
|
|||
readonly property int reservedSpaceForLabel: metrics.height
|
||||
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
|
||||
readonly property real drawerTopMargin: height - topPadding - bottomPadding - closedPositionOffset
|
||||
readonly property real closedPositionOffset: homeScreenState.appDrawerBottomOffset
|
||||
|
||||
//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) {
|
||||
return Math.min(1, Math.max(0, num));
|
||||
}
|
||||
|
|
@ -125,15 +62,6 @@ Item {
|
|||
|
||||
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 {
|
||||
id: metrics
|
||||
text: "M\nM"
|
||||
|
|
@ -143,7 +71,7 @@ Item {
|
|||
|
||||
// bottom divider
|
||||
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
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
|
@ -156,25 +84,14 @@ Item {
|
|||
id: view
|
||||
anchors.fill: parent
|
||||
|
||||
// We have a situation where this vertical flickable conflicts with the horizontal flickable used for homescreen pages.
|
||||
// This flickable is on top of the other, so we disable it when it isn't open.
|
||||
// We do the initial open gesture in private/DragGestureHandler.qml
|
||||
interactive: contentY > PlasmaCore.Units.gridUnit
|
||||
// scroll events are handled by our flick container, we are only using this for positioning
|
||||
interactive: false
|
||||
contentY: Math.max(0, Math.min(root.drawerTopMargin, root.drawerTopMargin - homeScreenState.yPosition))
|
||||
|
||||
contentHeight: column.implicitHeight
|
||||
contentWidth: -1
|
||||
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 {
|
||||
id: column
|
||||
width: view.width
|
||||
|
|
@ -196,8 +113,8 @@ Item {
|
|||
}
|
||||
factor: root.openFactor
|
||||
flickable: view
|
||||
onOpenRequested: root.open();
|
||||
onCloseRequested: root.close();
|
||||
onOpenRequested: homeScreenState.openAppDrawer();
|
||||
onCloseRequested: homeScreenState.closeAppDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -206,8 +123,6 @@ Item {
|
|||
id: drawerFlickable
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.height
|
||||
|
||||
visible: view.interactive // this is so that the favourites strip can be interacted with
|
||||
leftPadding: root.leftPadding; topPadding: root.topPadding
|
||||
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 "private"
|
||||
import "../private"
|
||||
|
||||
AbstractAppDrawer {
|
||||
id: root
|
||||
|
|
@ -28,32 +28,7 @@ AbstractAppDrawer {
|
|||
contentItem: GridView {
|
||||
id: gridView
|
||||
clip: true
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
interactive: root.homeScreenState.appDrawerInteractive
|
||||
|
||||
cellWidth: root.contentWidth / Math.floor(root.contentWidth / ((root.availableCellHeight - root.reservedSpaceForLabel) + PlasmaCore.Units.smallSpacing*4))
|
||||
cellHeight: root.availableCellHeight
|
||||
|
|
@ -78,7 +53,7 @@ AbstractAppDrawer {
|
|||
root.Drag.hotSpot.y = y;
|
||||
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
||||
|
||||
root.close()
|
||||
root.homeScreenState.closeAppDrawer()
|
||||
|
||||
root.dragStarted()
|
||||
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 "private"
|
||||
import "../private"
|
||||
|
||||
AbstractAppDrawer {
|
||||
id: root
|
||||
|
|
@ -31,31 +31,7 @@ AbstractAppDrawer {
|
|||
reuseItems: true
|
||||
cacheBuffer: model.count * delegateHeight // delegate height
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
interactive: root.homeScreenState.appDrawerInteractive
|
||||
|
||||
property int delegateHeight: PlasmaCore.Units.gridUnit * 3
|
||||
|
||||
|
|
@ -74,7 +50,7 @@ AbstractAppDrawer {
|
|||
root.Drag.hotSpot.y = y;
|
||||
root.Drag.mimeData = { "text/x-plasma-phone-homescreen-launcher": mimeData };
|
||||
|
||||
root.close()
|
||||
root.homeScreenState.closeAppDrawer()
|
||||
|
||||
root.dragStarted()
|
||||
root.Drag.active = true;
|
||||
|
|
@ -22,6 +22,7 @@ import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
|||
MouseArea {
|
||||
id: arrowUpIcon
|
||||
z: 9
|
||||
|
||||
property Flickable flickable
|
||||
property real factor: 0
|
||||
|
||||
|
|
@ -32,7 +33,6 @@ MouseArea {
|
|||
|
||||
onClicked: {
|
||||
openRequested();
|
||||
scrollAnim.restart();
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
|
|||
|
|
@ -6,18 +6,23 @@ module org.kde.plasma.private.mobilehomescreencomponents
|
|||
|
||||
plugin mobilehomescreencomponentsplugin
|
||||
|
||||
AbstractAppDrawer 0.1 AbstractAppDrawer.qml
|
||||
GridViewAppDrawer 0.1 GridViewAppDrawer.qml
|
||||
ListViewAppDrawer 0.1 ListViewAppDrawer.qml
|
||||
DrawerListDelegate 0.1 DrawerListDelegate.qml
|
||||
DrawerGridDelegate 0.1 DrawerGridDelegate.qml
|
||||
AbstractAppDrawer 0.1 appdrawer/AbstractAppDrawer.qml
|
||||
AppDrawerHeader 0.1 appdrawer/AppDrawerHeader.qml
|
||||
AppDrawerLoader 0.1 appdrawer/AppDrawerLoader.qml
|
||||
DrawerGridDelegate 0.1 appdrawer/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
|
||||
FlickablePages 0.1 FlickablePages.qml
|
||||
FlickContainer 0.1 FlickContainer.qml
|
||||
HomeDelegate 0.1 HomeDelegate.qml
|
||||
HomeScreen 0.1 HomeScreen.qml
|
||||
HomeScreenContents 0.1 HomeScreenContents.qml
|
||||
HomeScreenPages 0.1 HomeScreenPages.qml
|
||||
HomeScreenState 0.1 HomeScreenState.qml
|
||||
LauncherContainer 0.1 LauncherContainer.qml
|
||||
LauncherDragManager 0.1 LauncherDragManager.qml
|
||||
LauncherGrid 0.1 LauncherGrid.qml
|
||||
LauncherRepeater 0.1 LauncherRepeater.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
|
||||
Direction 1.0 components/Direction.qml
|
||||
StartupFeedback 1.0 components/StartupFeedback.qml
|
||||
VelocityCalculator 1.0 components/VelocityCalculator.qml
|
||||
|
||||
# /dataproviders
|
||||
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) {
|
||||
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() {
|
||||
|
|
@ -50,21 +50,22 @@ FocusScope {
|
|||
}
|
||||
|
||||
function onResetHomeScreenPosition() {
|
||||
homescreen.flickablePages.scrollToPage(0);
|
||||
homescreen.appDrawer.close();
|
||||
homescreen.homeScreenState.goToPageIndex(0);
|
||||
homescreen.homeScreenState.closeAppDrawer();
|
||||
}
|
||||
|
||||
function onSnapHomeScreenPosition() {
|
||||
if (lastRequestedPosition < 0) {
|
||||
homescreen.appDrawer.open();
|
||||
homescreen.homeScreenState.openAppDrawer();
|
||||
} else {
|
||||
homescreen.appDrawer.close();
|
||||
homescreen.homeScreenState.closeAppDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
function onRequestRelativeScroll(pos) {
|
||||
homescreen.appDrawer.offset -= pos.y;
|
||||
lastRequestedPosition = pos.y;
|
||||
// TODO
|
||||
//homescreen.appDrawer.offset -= pos.y;
|
||||
//lastRequestedPosition = pos.y;
|
||||
}
|
||||
|
||||
function onOpenAppAnimation(splashIcon, title, x, y, sourceIconSize) {
|
||||
|
|
@ -110,14 +111,29 @@ FocusScope {
|
|||
|
||||
Plasmoid.onActivated: {
|
||||
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 {
|
||||
HomeScreenComponents.HomeScreen {
|
||||
id: homescreen
|
||||
anchors.fill: parent
|
||||
|
||||
|
||||
// make the homescreen not interactable when task switcher or startup feedback is on
|
||||
interactive: !taskSwitcher.visible && !startupFeedback.visible
|
||||
|
||||
opacity: 1
|
||||
NumberAnimation on opacity {
|
||||
id: opacityAnimation
|
||||
|
|
|
|||
Loading…
Reference in a new issue