2023-10-22 03:59:27 +00:00
|
|
|
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
|
|
|
|
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
2021-12-31 00:49:08 +00:00
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
import QtQuick
|
|
|
|
|
import QtQuick.Window
|
|
|
|
|
import QtQuick.Layouts
|
|
|
|
|
import QtQuick.Effects
|
|
|
|
|
import QtQuick.Controls as QQC2
|
2021-12-31 00:49:08 +00:00
|
|
|
|
2026-03-07 03:08:07 +00:00
|
|
|
import org.kde.kirigami as Kirigami
|
2021-12-31 00:49:08 +00:00
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
import org.kde.plasma.plasmoid 2.0
|
|
|
|
|
import org.kde.plasma.components 3.0 as PC3
|
2023-11-02 11:08:17 +00:00
|
|
|
import org.kde.plasma.private.mobileshell as MobileShell
|
2026-04-09 08:14:55 +00:00
|
|
|
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
|
2026-05-01 11:03:20 +00:00
|
|
|
import QtQuick.Templates as T
|
2025-07-16 17:02:18 +00:00
|
|
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
2021-12-31 00:49:08 +00:00
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
import "./delegate"
|
|
|
|
|
import "./settings"
|
|
|
|
|
|
2021-12-31 00:49:08 +00:00
|
|
|
Item {
|
|
|
|
|
id: root
|
2024-06-21 04:42:14 +00:00
|
|
|
property Folio.HomeScreen folio
|
Folio/Halcyon: Expand Background Blur Effect using a MaskLayer
This merge request expands upon the folio and halcyon background blur effects, making the folio background blur include the backgrounds of folder icons, the favorites bar, and wallpaper selector, and for halcyon, it now includes the folder icons, app library, search, and wallpaper selector. To accomplish this, a mask layer plugin was created to easily attach to these elements. This way, we can use a `OpacityMask` to cut out from the existing blur layer, thus hopefully keeping the performance cost low. And with my limited testing, it does at least seems to run about the same on my oneplus 6t, though it is not really a low end device, so I can not fairly judge the impact for something slower (eg. PinePhone). To be on the safe side, a third option was also added to the folio settings, allowing for the ability to toggle back to the old functionality if needed.




2025-06-27 18:27:30 +00:00
|
|
|
property MobileShell.MaskManager maskManager
|
2024-06-21 04:42:14 +00:00
|
|
|
property Folio.HomeScreenState homeScreenState: folio.HomeScreenState
|
2022-12-11 02:05:13 +00:00
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
property real topMargin: 0
|
|
|
|
|
property real bottomMargin: 0
|
|
|
|
|
property real leftMargin: 0
|
|
|
|
|
property real rightMargin: 0
|
|
|
|
|
|
2021-12-31 00:49:08 +00:00
|
|
|
property bool interactive: true
|
2022-04-20 19:53:02 +00:00
|
|
|
|
2023-11-05 05:14:39 +00:00
|
|
|
// non-widget drop animation
|
|
|
|
|
readonly property bool dropAnimationRunning: delegateDragItem.dropAnimationRunning || widgetDragItem.dropAnimationRunning
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2023-11-05 05:14:39 +00:00
|
|
|
// widget that is currently being dragged (or dropped)
|
|
|
|
|
readonly property Folio.FolioWidget currentlyDraggedWidget: widgetDragItem.widget
|
|
|
|
|
|
|
|
|
|
// how much to scale out in the settings mode
|
2023-10-22 03:59:27 +00:00
|
|
|
readonly property real settingsModeHomeScreenScale: 0.8
|
|
|
|
|
|
2024-06-21 04:42:14 +00:00
|
|
|
onTopMarginChanged: folio.HomeScreenState.viewTopPadding = root.topMargin
|
|
|
|
|
onBottomMarginChanged: folio.HomeScreenState.viewBottomPadding = root.bottomMargin
|
|
|
|
|
onLeftMarginChanged: folio.HomeScreenState.viewLeftPadding = root.leftMargin
|
|
|
|
|
onRightMarginChanged: folio.HomeScreenState.viewRightPadding = root.rightMargin
|
2025-08-11 20:04:35 +00:00
|
|
|
onWidthChanged: folio.HomeScreenState.viewWidth = width
|
|
|
|
|
onHeightChanged: folio.HomeScreenState.viewHeight = height
|
2023-10-22 03:59:27 +00:00
|
|
|
|
Folio/Halcyon: Expand Background Blur Effect using a MaskLayer
This merge request expands upon the folio and halcyon background blur effects, making the folio background blur include the backgrounds of folder icons, the favorites bar, and wallpaper selector, and for halcyon, it now includes the folder icons, app library, search, and wallpaper selector. To accomplish this, a mask layer plugin was created to easily attach to these elements. This way, we can use a `OpacityMask` to cut out from the existing blur layer, thus hopefully keeping the performance cost low. And with my limited testing, it does at least seems to run about the same on my oneplus 6t, though it is not really a low end device, so I can not fairly judge the impact for something slower (eg. PinePhone). To be on the safe side, a third option was also added to the folio settings, allowing for the ability to toggle back to the old functionality if needed.




2025-06-27 18:27:30 +00:00
|
|
|
signal wallpaperSelectorTriggered()
|
|
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
// called by any delegates when starting drag
|
|
|
|
|
// returns the mapped coordinates to be used in the home screen state
|
2024-07-14 02:16:13 +00:00
|
|
|
function prepareStartDelegateDrag(delegate, item, skipSwipeThreshold) {
|
|
|
|
|
|
|
|
|
|
// If the user is prompted with a context menu, they may want to let go, and so we keep the detect swipe threshold.
|
|
|
|
|
// Otherwise, we want to skip detecting a swipe because we know we immediately go into delegate dragging.
|
|
|
|
|
if (skipSwipeThreshold) {
|
|
|
|
|
swipeArea.setSkipSwipeThreshold(true);
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2023-11-05 05:14:39 +00:00
|
|
|
if (delegate) {
|
|
|
|
|
delegateDragItem.delegate = delegate;
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
return root.mapFromItem(item, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function cancelDelegateDrag() {
|
|
|
|
|
homeScreenState.cancelDelegateDrag();
|
2021-12-31 00:49:08 +00:00
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
|
|
|
|
// sets the coordinates for the folder opening/closing animation
|
|
|
|
|
function prepareFolderOpen(item) {
|
|
|
|
|
return root.mapFromItem(item, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function openConfigure() {
|
|
|
|
|
Plasmoid.internalAction("configure").trigger();
|
2021-12-31 02:11:21 +00:00
|
|
|
}
|
2023-03-05 17:39:03 +00:00
|
|
|
|
2026-05-01 11:03:20 +00:00
|
|
|
function showDesktopContextMenu() {
|
|
|
|
|
desktopContextMenu.popup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PC3.Menu {
|
|
|
|
|
id: desktopContextMenu
|
|
|
|
|
popupType: T.Popup.Window
|
|
|
|
|
|
|
|
|
|
PC3.MenuItem {
|
|
|
|
|
text: i18n("Desktop and Wallpaper...")
|
|
|
|
|
icon.name: "preferences-desktop-wallpaper"
|
|
|
|
|
onTriggered: root.wallpaperSelectorTriggered()
|
|
|
|
|
}
|
|
|
|
|
PC3.MenuItem {
|
|
|
|
|
text: i18n("Add Widgets...")
|
|
|
|
|
icon.name: "widget-alternatives"
|
|
|
|
|
onTriggered: {
|
|
|
|
|
folio.HomeScreenState.openSettingsView();
|
|
|
|
|
settings.openWidgetsBrowser();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PC3.MenuSeparator {}
|
|
|
|
|
PC3.MenuItem {
|
|
|
|
|
text: i18n("Configure Desktop...")
|
|
|
|
|
icon.name: "settings-configure"
|
|
|
|
|
onTriggered: root.openConfigure()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 20:04:35 +00:00
|
|
|
Keys.onPressed: (event) => {
|
|
|
|
|
// The root is focused when we aren't in key navigation mode
|
|
|
|
|
// Begin key navigation when arrow keys are pressed
|
|
|
|
|
if (event.key === Qt.Key_Up || event.key === Qt.Key_Down
|
|
|
|
|
|| event.key === Qt.Key_Left || event.key === Qt.Key_Right) {
|
|
|
|
|
homeScreenPages.forceActiveFocus();
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
// determine how tall an app label is, for delegate measurements
|
|
|
|
|
DelegateLabel {
|
|
|
|
|
id: appLabelMetrics
|
|
|
|
|
text: "M\nM"
|
|
|
|
|
visible: false
|
|
|
|
|
|
2024-06-21 04:42:14 +00:00
|
|
|
onHeightChanged: folio.HomeScreenState.pageDelegateLabelHeight = appLabelMetrics.height
|
2023-10-22 03:59:27 +00:00
|
|
|
|
|
|
|
|
Component.onCompleted: {
|
2024-06-21 04:42:14 +00:00
|
|
|
folio.HomeScreenState.pageDelegateLabelWidth = Kirigami.Units.smallSpacing;
|
2023-10-22 03:59:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-05 05:14:39 +00:00
|
|
|
// a way of stopping focus
|
|
|
|
|
FocusScope {
|
|
|
|
|
id: noFocus
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 20:04:35 +00:00
|
|
|
// Listen to view changes
|
|
|
|
|
Connections {
|
|
|
|
|
target: folio.HomeScreenState
|
|
|
|
|
|
|
|
|
|
function onViewStateChanged() {
|
|
|
|
|
if (folio.HomeScreenState.viewState === Folio.HomeScreenState.PageView) {
|
|
|
|
|
// Focus root when on page view
|
|
|
|
|
root.forceActiveFocus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// Drag and drop area
|
|
|
|
|
DelegateDropArea {
|
|
|
|
|
id: dropArea
|
|
|
|
|
folio: root.folio
|
2021-12-31 00:49:08 +00:00
|
|
|
anchors.fill: parent
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// Area that can be swiped
|
|
|
|
|
MobileShell.SwipeArea {
|
|
|
|
|
id: swipeArea
|
|
|
|
|
anchors.fill: parent
|
2024-07-16 02:32:01 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
interactive: root.interactive &&
|
|
|
|
|
settings.homeScreenInteractive &&
|
|
|
|
|
!dropArea.containsDrag &&
|
|
|
|
|
(appDrawer.flickable.atYBeginning || // there are cases where contentY > 0 but atYBeginning is true
|
|
|
|
|
appDrawer.flickable.contentY <= 10 ||
|
|
|
|
|
// disable the swipe area when we are swiping in the app drawer, and not in drag-and-drop
|
|
|
|
|
folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate ||
|
|
|
|
|
folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate ||
|
|
|
|
|
folio.HomeScreenState.swipeState === Folio.HomeScreenState.SwipingAppDrawerGrid ||
|
|
|
|
|
folio.HomeScreenState.viewState !== Folio.HomeScreenState.AppDrawerView)
|
|
|
|
|
|
|
|
|
|
onSwipeStarted: (currentPos, startPos) => {
|
|
|
|
|
const deltaX = currentPos.x - startPos.x;
|
|
|
|
|
const deltaY = currentPos.y - startPos.y;
|
|
|
|
|
homeScreenState.swipeStarted(deltaX, deltaY);
|
|
|
|
|
}
|
|
|
|
|
onSwipeEnded: {
|
|
|
|
|
homeScreenState.swipeEnded();
|
|
|
|
|
}
|
|
|
|
|
onSwipeMove: (totalDeltaX, totalDeltaY, deltaX, deltaY) => {
|
|
|
|
|
// cancel swipe when settings component is opening to prevent conflicts
|
|
|
|
|
if (folio.HomeScreenState.settingsOpenProgress && folio.HomeScreenState.viewState !== Folio.HomeScreenState.SettingsView) {
|
|
|
|
|
homeScreenState.swipeCancelled();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
homeScreenState.swipeMoved(totalDeltaX, totalDeltaY, deltaX, deltaY);
|
2023-11-05 05:14:39 +00:00
|
|
|
}
|
2025-04-25 01:23:48 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
onTouchpadScrollStarted: homeScreenState.swipeStarted(0, 0);
|
|
|
|
|
onTouchpadScrollEnded: homeScreenState.swipeEnded();
|
|
|
|
|
onTouchpadScrollMove: (totalDeltaX, totalDeltaY, deltaX, deltaY) => homeScreenState.swipeMoved(totalDeltaX, totalDeltaY, deltaX, deltaY);
|
2023-11-05 05:14:39 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
onPressedChanged: {
|
|
|
|
|
if (pressed) {
|
|
|
|
|
// ensures that components like the widget settings overlay close when swiping
|
|
|
|
|
noFocus.forceActiveFocus();
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-03 19:41:43 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
SettingsComponent {
|
2025-07-03 19:41:43 +00:00
|
|
|
id: settings
|
|
|
|
|
folio: root.folio
|
2025-12-12 05:33:25 +00:00
|
|
|
homeScreen: root
|
|
|
|
|
settingsModeHomeScreenScale: root.settingsModeHomeScreenScale
|
|
|
|
|
|
|
|
|
|
// Don't anchor, since we set y
|
|
|
|
|
width: parent.width
|
|
|
|
|
height: parent.height
|
|
|
|
|
opacity: folio.HomeScreenState.settingsOpenProgress
|
|
|
|
|
visible: opacity > 0
|
|
|
|
|
|
|
|
|
|
z: 1
|
2025-07-03 19:41:43 +00:00
|
|
|
|
|
|
|
|
bottomMargin: root.bottomMargin
|
|
|
|
|
leftMargin: root.leftMargin
|
|
|
|
|
rightMargin: root.rightMargin
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
Item {
|
|
|
|
|
id: mainHomeScreen
|
|
|
|
|
anchors.fill: parent
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2026-04-09 10:29:46 +00:00
|
|
|
// we stop showing halfway through the animation (skip in convergence — desktop stays visible)
|
|
|
|
|
opacity: ShellSettings.Settings.convergenceModeEnabled
|
|
|
|
|
? 1
|
|
|
|
|
: 1 - Math.max(homeScreenState.appDrawerOpenProgress, homeScreenState.searchWidgetOpenProgress, homeScreenState.folderOpenProgress) * 2
|
2025-12-12 05:33:25 +00:00
|
|
|
visible: opacity > 0 // prevent handlers from picking up events
|
2025-08-11 20:04:35 +00:00
|
|
|
|
2023-10-22 03:59:27 +00:00
|
|
|
transform: [
|
|
|
|
|
Scale {
|
2026-04-09 10:29:46 +00:00
|
|
|
property real scaleFactor: ShellSettings.Settings.convergenceModeEnabled
|
|
|
|
|
? 0
|
|
|
|
|
: Math.max(homeScreenState.appDrawerOpenProgress, homeScreenState.searchWidgetOpenProgress)
|
2025-12-12 05:33:25 +00:00
|
|
|
origin.x: mainHomeScreen.width / 2
|
|
|
|
|
origin.y: mainHomeScreen.height / 2
|
|
|
|
|
yScale: 1 - (scaleFactor * 2) * 0.1
|
|
|
|
|
xScale: 1 - (scaleFactor * 2) * 0.1
|
2023-10-22 03:59:27 +00:00
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
HomeScreenPages {
|
|
|
|
|
id: homeScreenPages
|
|
|
|
|
folio: root.folio
|
|
|
|
|
maskManager: root.maskManager
|
|
|
|
|
homeScreen: root
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.topMargin: root.topMargin
|
|
|
|
|
anchors.leftMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? 0 : root.leftMargin
|
|
|
|
|
anchors.rightMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? 0 : root.rightMargin
|
|
|
|
|
anchors.bottomMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? 0 : root.bottomMargin
|
Folio/Halcyon: Expand Background Blur Effect using a MaskLayer
This merge request expands upon the folio and halcyon background blur effects, making the folio background blur include the backgrounds of folder icons, the favorites bar, and wallpaper selector, and for halcyon, it now includes the folder icons, app library, search, and wallpaper selector. To accomplish this, a mask layer plugin was created to easily attach to these elements. This way, we can use a `OpacityMask` to cut out from the existing blur layer, thus hopefully keeping the performance cost low. And with my limited testing, it does at least seems to run about the same on my oneplus 6t, though it is not really a low end device, so I can not fairly judge the impact for something slower (eg. PinePhone). To be on the safe side, a third option was also added to the folio settings, allowing for the ability to toggle back to the old functionality if needed.




2025-06-27 18:27:30 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// update the model with page dimensions
|
|
|
|
|
onWidthChanged: {
|
|
|
|
|
homeScreenState.pageWidth = homeScreenPages.width;
|
|
|
|
|
}
|
|
|
|
|
onHeightChanged: {
|
|
|
|
|
homeScreenState.pageHeight = homeScreenPages.height;
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// Keyboard navigation from pages
|
|
|
|
|
Keys.onPressed: (event) => {
|
|
|
|
|
switch (event.key) {
|
|
|
|
|
case Qt.Key_Up:
|
|
|
|
|
// Open search widget when going up
|
|
|
|
|
folio.HomeScreenState.openSearchWidget();
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
break;
|
|
|
|
|
case Qt.Key_Down:
|
|
|
|
|
// Focus on favorites bar or app drawer, depending on its physical location
|
|
|
|
|
if (folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom) {
|
|
|
|
|
favouritesBar.forceActiveFocus();
|
|
|
|
|
} else {
|
|
|
|
|
folio.HomeScreenState.openAppDrawer();
|
|
|
|
|
}
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
break;
|
|
|
|
|
case Qt.Key_Left:
|
|
|
|
|
if (folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left) {
|
|
|
|
|
// If favorites bar is on the left, navigate to it
|
|
|
|
|
favouritesBar.forceActiveFocus();
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise go to page on the left
|
|
|
|
|
folio.HomeScreenState.goToPage(folio.HomeScreenState.currentPage - 1, false);
|
|
|
|
|
homeScreenPages.focusCurrentPageForKeyboardNav();
|
|
|
|
|
}
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
break;
|
|
|
|
|
case Qt.Key_Right:
|
|
|
|
|
if (folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right) {
|
|
|
|
|
// If favorites bar is on the right, navigate to it
|
|
|
|
|
favouritesBar.forceActiveFocus();
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise go to page on the right
|
|
|
|
|
folio.HomeScreenState.goToPage(folio.HomeScreenState.currentPage + 1, false);
|
|
|
|
|
homeScreenPages.focusCurrentPageForKeyboardNav();
|
|
|
|
|
}
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
transform: [
|
|
|
|
|
Scale {
|
|
|
|
|
// animation when settings opens
|
|
|
|
|
property real scaleFactor: 1 - folio.HomeScreenState.settingsOpenProgress * (1 - settingsModeHomeScreenScale)
|
|
|
|
|
origin.x: root.leftMargin + (root.width - root.rightMargin - root.leftMargin) / 2
|
|
|
|
|
origin.y: root.height * settingsModeHomeScreenScale / 2
|
|
|
|
|
xScale: scaleFactor
|
|
|
|
|
yScale: scaleFactor
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
states: [
|
|
|
|
|
State {
|
|
|
|
|
name: "bottom"
|
|
|
|
|
when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
|
|
|
|
|
AnchorChanges {
|
|
|
|
|
target: homeScreenPages
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.bottom: favouritesBar.top
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
}
|
|
|
|
|
}, State {
|
|
|
|
|
name: "left"
|
|
|
|
|
when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left
|
|
|
|
|
AnchorChanges {
|
|
|
|
|
target: homeScreenPages
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.left: favouritesBar.right
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
}
|
|
|
|
|
}, State {
|
|
|
|
|
name: "right"
|
|
|
|
|
when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right
|
|
|
|
|
AnchorChanges {
|
|
|
|
|
target: homeScreenPages
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: favouritesBar.left
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
Rectangle {
|
|
|
|
|
id: favouritesBarScrim
|
|
|
|
|
color: Qt.rgba(255, 255, 255, 0.2)
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
Component.onCompleted: maskManager.assignToMask(this)
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// don't show in settings mode
|
|
|
|
|
opacity: 1 - folio.HomeScreenState.settingsOpenProgress
|
|
|
|
|
visible: folio.FolioSettings.showFavouritesBarBackground
|
2021-12-31 00:49:08 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.top: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? favouritesBar.top : parent.top
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.left: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? favouritesBar.left : parent.left
|
|
|
|
|
anchors.right: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? favouritesBar.right : parent.right
|
|
|
|
|
|
|
|
|
|
// because of the scale animation, we need to extend the panel out a bit
|
|
|
|
|
anchors.topMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom ? 0 : -Kirigami.Units.gridUnit * 5
|
|
|
|
|
anchors.bottomMargin: -Kirigami.Units.gridUnit * 5
|
|
|
|
|
anchors.leftMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right ? 0 : -Kirigami.Units.gridUnit * 5
|
|
|
|
|
anchors.rightMargin: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left ? 0 : -Kirigami.Units.gridUnit * 5
|
|
|
|
|
}
|
2021-12-31 00:49:08 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
FavouritesBar {
|
|
|
|
|
id: favouritesBar
|
|
|
|
|
folio: root.folio
|
|
|
|
|
maskManager: root.maskManager
|
|
|
|
|
homeScreen: root
|
|
|
|
|
|
|
|
|
|
// don't show in settings mode
|
|
|
|
|
opacity: 1 - folio.HomeScreenState.settingsOpenProgress
|
2026-04-11 07:42:21 +00:00
|
|
|
// Hidden in convergence mode — the dock overlay window renders it instead
|
|
|
|
|
visible: opacity > 0 && !ShellSettings.Settings.convergenceModeEnabled
|
2025-12-12 05:33:25 +00:00
|
|
|
|
|
|
|
|
// one is ignored as anchors are set
|
2026-05-04 06:43:10 +00:00
|
|
|
height: ShellSettings.Settings.convergenceModeEnabled ? MobileShell.Constants.convergenceDockHeight : Kirigami.Units.gridUnit * 6
|
|
|
|
|
width: ShellSettings.Settings.convergenceModeEnabled ? MobileShell.Constants.convergenceDockHeight : Kirigami.Units.gridUnit * 6
|
2025-12-12 05:33:25 +00:00
|
|
|
|
|
|
|
|
anchors.topMargin: root.topMargin
|
2026-04-09 09:09:25 +00:00
|
|
|
anchors.bottomMargin: ShellSettings.Settings.convergenceModeEnabled ? 0 : root.bottomMargin
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.leftMargin: root.leftMargin
|
|
|
|
|
anchors.rightMargin: root.rightMargin
|
|
|
|
|
|
|
|
|
|
// Keyboard navigation on favorites bar
|
|
|
|
|
Keys.onPressed: (event) => {
|
|
|
|
|
switch (event.key) {
|
|
|
|
|
case Qt.Key_Up:
|
|
|
|
|
// Focus on homescreen pages or search widget depending on physical position
|
|
|
|
|
if (folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom) {
|
|
|
|
|
homeScreenPages.forceActiveFocus();
|
|
|
|
|
} else {
|
|
|
|
|
folio.HomeScreenState.openSearchWidget();
|
|
|
|
|
}
|
2025-08-11 20:04:35 +00:00
|
|
|
event.accepted = true;
|
2025-12-12 05:33:25 +00:00
|
|
|
break;
|
|
|
|
|
case Qt.Key_Down:
|
|
|
|
|
// Open app drawer
|
|
|
|
|
folio.HomeScreenState.openAppDrawer();
|
2025-08-11 20:04:35 +00:00
|
|
|
event.accepted = true;
|
2025-12-12 05:33:25 +00:00
|
|
|
break;
|
|
|
|
|
case Qt.Key_Left:
|
|
|
|
|
if (folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left) {
|
|
|
|
|
// Go to left page if mounted on the left
|
|
|
|
|
folio.HomeScreenState.goToPage(folio.HomeScreenState.currentPage - 1, false);
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Qt.Key_Right:
|
|
|
|
|
if (folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right) {
|
|
|
|
|
// Go to right page if mounted on the right
|
|
|
|
|
folio.HomeScreenState.goToPage(folio.HomeScreenState.currentPage + 1, false);
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2025-08-11 20:04:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
states: [
|
|
|
|
|
State {
|
|
|
|
|
name: "bottom"
|
|
|
|
|
when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
|
|
|
|
|
AnchorChanges {
|
|
|
|
|
target: favouritesBar
|
|
|
|
|
anchors.top: undefined
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
}
|
|
|
|
|
PropertyChanges {
|
|
|
|
|
target: favouritesBar
|
2026-05-04 06:43:10 +00:00
|
|
|
height: ShellSettings.Settings.convergenceModeEnabled ? MobileShell.Constants.convergenceDockHeight : Kirigami.Units.gridUnit * 6
|
2025-12-12 05:33:25 +00:00
|
|
|
}
|
|
|
|
|
}, State {
|
|
|
|
|
name: "left"
|
|
|
|
|
when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Left
|
|
|
|
|
AnchorChanges {
|
|
|
|
|
target: favouritesBar
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: undefined
|
|
|
|
|
}
|
|
|
|
|
PropertyChanges {
|
|
|
|
|
target: favouritesBar
|
|
|
|
|
width: Kirigami.Units.gridUnit * 6
|
|
|
|
|
}
|
|
|
|
|
}, State {
|
|
|
|
|
name: "right"
|
|
|
|
|
when: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Right
|
|
|
|
|
AnchorChanges {
|
|
|
|
|
target: favouritesBar
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.left: undefined
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
}
|
|
|
|
|
PropertyChanges {
|
|
|
|
|
target: favouritesBar
|
|
|
|
|
width: Kirigami.Units.gridUnit * 6
|
|
|
|
|
}
|
2021-12-31 00:49:08 +00:00
|
|
|
}
|
2025-12-12 05:33:25 +00:00
|
|
|
]
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
Item {
|
|
|
|
|
id: pageIndicatorWrapper
|
|
|
|
|
property bool favouritesBarAtBottom: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// don't show in settings mode
|
|
|
|
|
opacity: 1 - folio.HomeScreenState.settingsOpenProgress
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
anchors.bottom: favouritesBarAtBottom ? favouritesBar.top : parent.bottom
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.topMargin: root.topMargin
|
|
|
|
|
anchors.leftMargin: root.leftMargin
|
|
|
|
|
anchors.rightMargin: root.rightMargin
|
|
|
|
|
anchors.bottomMargin: favouritesBarAtBottom ? 0 : (root.bottomMargin + Kirigami.Units.largeSpacing)
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// show page indicator if there are multiple pages
|
|
|
|
|
QQC2.PageIndicator {
|
|
|
|
|
visible: count > 1
|
|
|
|
|
Kirigami.Theme.inherit: false
|
|
|
|
|
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
|
anchors.bottom: parent.bottom
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
currentIndex: folio.HomeScreenState.currentPage
|
|
|
|
|
count: folio.PageListModel.length
|
2024-02-11 23:15:51 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
TapHandler {
|
2026-04-09 08:14:55 +00:00
|
|
|
enabled: !ShellSettings.Settings.convergenceModeEnabled
|
2025-12-12 05:33:25 +00:00
|
|
|
onTapped: folio.HomeScreenState.openAppDrawer()
|
|
|
|
|
}
|
2024-02-11 23:15:51 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-09 08:14:55 +00:00
|
|
|
// show arrow to open app drawer when there is 1 page (hidden in convergence mode)
|
2025-12-12 05:33:25 +00:00
|
|
|
Kirigami.Icon {
|
|
|
|
|
source: 'arrow-up'
|
|
|
|
|
Kirigami.Theme.inherit: false
|
|
|
|
|
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
2026-05-17 06:57:06 +00:00
|
|
|
isMask: true
|
|
|
|
|
color: Kirigami.Theme.textColor
|
2024-06-21 04:42:14 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
implicitHeight: Kirigami.Units.iconSizes.small
|
|
|
|
|
implicitWidth: Kirigami.Units.iconSizes.small
|
2024-02-11 23:15:51 +00:00
|
|
|
|
2026-04-09 08:14:55 +00:00
|
|
|
visible: folio.PageListModel.length <= 1 && !ShellSettings.Settings.convergenceModeEnabled
|
2024-06-21 04:42:14 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.bottomMargin: Kirigami.Units.smallSpacing
|
2024-02-11 23:15:51 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
TapHandler {
|
|
|
|
|
onTapped: folio.HomeScreenState.openAppDrawer()
|
|
|
|
|
}
|
2024-02-11 23:15:51 +00:00
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// folder view
|
|
|
|
|
FolderView {
|
|
|
|
|
id: folderView
|
|
|
|
|
folio: root.folio
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
anchors.topMargin: root.topMargin
|
|
|
|
|
anchors.leftMargin: root.leftMargin
|
|
|
|
|
anchors.rightMargin: root.rightMargin
|
|
|
|
|
anchors.bottomMargin: root.bottomMargin
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
homeScreen: root
|
|
|
|
|
opacity: homeScreenState.folderOpenProgress
|
|
|
|
|
transform: Translate { y: folderView.opacity > 0 ? 0 : folderView.height }
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2026-04-15 08:18:34 +00:00
|
|
|
// Click-to-dismiss overlay (mobile only; convergence uses layer-shell overlay)
|
2026-04-09 10:29:46 +00:00
|
|
|
MouseArea {
|
|
|
|
|
anchors.fill: parent
|
2026-04-15 08:18:34 +00:00
|
|
|
visible: !ShellSettings.Settings.convergenceModeEnabled
|
|
|
|
|
&& homeScreenState.appDrawerOpenProgress > 0
|
2026-04-09 10:29:46 +00:00
|
|
|
onClicked: folio.HomeScreenState.closeAppDrawer()
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:18:34 +00:00
|
|
|
// bottom app drawer (mobile only; convergence uses layer-shell overlay)
|
2025-12-12 05:33:25 +00:00
|
|
|
AppDrawer {
|
|
|
|
|
id: appDrawer
|
|
|
|
|
folio: root.folio
|
2026-04-15 08:18:34 +00:00
|
|
|
visible: !ShellSettings.Settings.convergenceModeEnabled
|
2026-04-09 10:29:46 +00:00
|
|
|
|
2026-04-15 08:18:34 +00:00
|
|
|
width: parent.width
|
|
|
|
|
height: parent.height
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
homeScreen: root
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// we only start showing it halfway through
|
|
|
|
|
opacity: homeScreenState.appDrawerOpenProgress < 0.5 ? 0 : (homeScreenState.appDrawerOpenProgress - 0.5) * 2
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// position for animation
|
|
|
|
|
property real animationY: (1 - homeScreenState.appDrawerOpenProgress) * (Kirigami.Units.gridUnit * 2)
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2026-04-09 10:29:46 +00:00
|
|
|
// Full-screen position
|
2026-04-15 08:18:34 +00:00
|
|
|
x: 0
|
|
|
|
|
y: (opacity > 0) ? animationY : parent.height
|
2025-07-10 16:54:01 +00:00
|
|
|
|
2026-04-15 08:18:34 +00:00
|
|
|
headerHeight: Math.round(Kirigami.Units.gridUnit * 4)
|
2025-12-12 05:33:25 +00:00
|
|
|
headerItem: AppDrawerHeader {
|
|
|
|
|
id: appDrawerHeader
|
|
|
|
|
folio: root.folio
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
onReleaseFocusRequested: appDrawer.forceActiveFocus()
|
2025-07-10 16:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:18:34 +00:00
|
|
|
// Account for panels
|
|
|
|
|
topPadding: root.topMargin
|
|
|
|
|
bottomPadding: root.bottomMargin
|
|
|
|
|
leftPadding: root.leftMargin
|
|
|
|
|
rightPadding: root.rightMargin
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// Forward keyboard text to the search bar
|
|
|
|
|
Keys.onPressed: (event) => {
|
|
|
|
|
if (event.text.trim().length > 0) {
|
|
|
|
|
appDrawerHeader.addSearchText(event.text);
|
|
|
|
|
appDrawerHeader.forceActiveFocus();
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
} else if (event.key === Qt.Key_Left || event.key === Qt.Key_Right || event.key === Qt.Key_Up || event.key === Qt.Key_Down) {
|
|
|
|
|
appDrawerHeader.forceActiveFocus();
|
|
|
|
|
event.accepted = true;
|
|
|
|
|
}
|
2025-07-10 16:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
Connections {
|
|
|
|
|
target: folio.HomeScreenState
|
|
|
|
|
|
|
|
|
|
function onAppDrawerOpened() {
|
|
|
|
|
appDrawer.forceActiveFocus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onAppDrawerClosed() {
|
|
|
|
|
// reset app drawer position when closed
|
|
|
|
|
appDrawer.flickable.contentY = 0;
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// search component
|
|
|
|
|
MobileShell.KRunnerScreen {
|
|
|
|
|
id: searchWidget
|
|
|
|
|
anchors.fill: parent
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
opacity: homeScreenState.searchWidgetOpenProgress
|
|
|
|
|
visible: opacity > 0
|
|
|
|
|
transform: Translate { y: (1 - homeScreenState.searchWidgetOpenProgress) * (-Kirigami.Units.gridUnit * 2) }
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
onVisibleChanged: {
|
|
|
|
|
if (!visible) {
|
|
|
|
|
// clear search bar when closed
|
|
|
|
|
searchWidget.clearField();
|
|
|
|
|
}
|
2023-11-16 07:11:03 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
// focus the search bar if it opens
|
|
|
|
|
Connections {
|
|
|
|
|
target: folio.HomeScreenState
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
function onSearchWidgetOpenProgressChanged() {
|
|
|
|
|
if (homeScreenState.searchWidgetOpenProgress === 1.0) {
|
|
|
|
|
searchWidget.requestFocus();
|
|
|
|
|
}
|
2021-12-31 00:49:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
onRequestedClose: (triggeredByKeyEvent) => {
|
|
|
|
|
homeScreenState.closeSearchWidget();
|
|
|
|
|
}
|
2023-10-22 03:59:27 +00:00
|
|
|
|
2025-12-12 05:33:25 +00:00
|
|
|
anchors.topMargin: root.topMargin
|
|
|
|
|
anchors.bottomMargin: root.bottomMargin
|
|
|
|
|
anchors.leftMargin: root.leftMargin
|
|
|
|
|
anchors.rightMargin: root.rightMargin
|
|
|
|
|
}
|
2021-12-31 00:49:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|