summaryrefslogtreecommitdiff
path: root/modules/controlcenter/Panes.qml
diff options
context:
space:
mode:
Diffstat (limited to 'modules/controlcenter/Panes.qml')
-rw-r--r--modules/controlcenter/Panes.qml178
1 files changed, 154 insertions, 24 deletions
diff --git a/modules/controlcenter/Panes.qml b/modules/controlcenter/Panes.qml
index 2548c3d..756d73a 100644
--- a/modules/controlcenter/Panes.qml
+++ b/modules/controlcenter/Panes.qml
@@ -1,6 +1,11 @@
pragma ComponentBehavior: Bound
import "bluetooth"
+import "network"
+import "audio"
+import "appearance"
+import "taskbar"
+import "launcher"
import qs.components
import qs.services
import qs.config
@@ -13,24 +18,68 @@ ClippingRectangle {
required property Session session
+ // Expose initialOpeningComplete so parent can check if opening animation is done
+ readonly property bool initialOpeningComplete: layout.initialOpeningComplete
+
color: "transparent"
+ clip: true
+ focus: false
+ activeFocusOnTab: false
+
+ // Clear focus when clicking anywhere in the panes area
+ MouseArea {
+ anchors.fill: parent
+ z: -1
+ onPressed: function(mouse) {
+ root.focus = true;
+ mouse.accepted = false;
+ }
+ }
+
+ // Clear focus when switching panes
+ Connections {
+ target: root.session
+
+ function onActiveIndexChanged(): void {
+ root.focus = true;
+ }
+ }
ColumnLayout {
id: layout
spacing: 0
y: -root.session.activeIndex * root.height
+ clip: true
+
+ property bool animationComplete: true
+ // Track if initial opening animation has completed
+ // During initial opening, only the active pane loads to avoid hiccups
+ property bool initialOpeningComplete: false
+
+ Timer {
+ id: animationDelayTimer
+ interval: Appearance.anim.durations.normal
+ onTriggered: {
+ layout.animationComplete = true;
+ }
+ }
+
+ // Timer to detect when initial opening animation completes
+ // Uses large duration to cover both normal and detached opening cases
+ Timer {
+ id: initialOpeningTimer
+ interval: Appearance.anim.durations.large
+ running: true
+ onTriggered: {
+ layout.initialOpeningComplete = true;
+ }
+ }
Pane {
index: 0
- sourceComponent: Item {
- StyledText {
- anchors.centerIn: parent
- text: qsTr("Work in progress")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
+ sourceComponent: NetworkingPane {
+ session: root.session
}
}
@@ -43,20 +92,44 @@ ClippingRectangle {
Pane {
index: 2
- sourceComponent: Item {
- StyledText {
- anchors.centerIn: parent
- text: qsTr("Work in progress")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
+ sourceComponent: AudioPane {
+ session: root.session
+ }
+ }
+
+ Pane {
+ index: 3
+ sourceComponent: AppearancePane {
+ session: root.session
+ }
+ }
+
+ Pane {
+ index: 4
+ sourceComponent: TaskbarPane {
+ session: root.session
+ }
+ }
+
+ Pane {
+ index: 5
+ sourceComponent: LauncherPane {
+ session: root.session
}
}
Behavior on y {
Anim {}
}
+
+ Connections {
+ target: root.session
+ function onActiveIndexChanged(): void {
+ // Mark animation as incomplete and start delay timer
+ layout.animationComplete = false;
+ animationDelayTimer.restart();
+ }
+ }
}
component Pane: Item {
@@ -68,19 +141,76 @@ ClippingRectangle {
implicitWidth: root.width
implicitHeight: root.height
+ // Track if this pane has ever been loaded to enable caching
+ property bool hasBeenLoaded: false
+
+ // Function to compute if this pane should be active
+ function updateActive(): void {
+ const diff = Math.abs(root.session.activeIndex - pane.index);
+ const isActivePane = diff === 0;
+ let shouldBeActive = false;
+
+ // During initial opening animation, only load the active pane
+ // This prevents hiccups from multiple panes loading simultaneously
+ if (!layout.initialOpeningComplete) {
+ shouldBeActive = isActivePane;
+ } else {
+ // After initial opening, allow current and adjacent panes for smooth transitions
+ if (diff <= 1) {
+ shouldBeActive = true;
+ } else if (pane.hasBeenLoaded) {
+ // For distant panes that have been loaded before, keep them active to preserve cached data
+ shouldBeActive = true;
+ } else {
+ // For new distant panes, wait until animation completes to avoid heavy loading during transition
+ shouldBeActive = layout.animationComplete;
+ }
+ }
+
+ loader.active = shouldBeActive;
+ }
+
Loader {
id: loader
anchors.fill: parent
- clip: true
+ clip: false
asynchronous: true
- active: {
- if (root.session.activeIndex === pane.index)
- return true;
-
- const ly = -layout.y;
- const ty = pane.index * root.height;
- return ly + root.height > ty && ly < ty + root.height;
+ active: false
+
+ Component.onCompleted: {
+ pane.updateActive();
+ }
+
+ onActiveChanged: {
+ // Mark pane as loaded when it becomes active
+ if (active && !pane.hasBeenLoaded) {
+ pane.hasBeenLoaded = true;
+ }
+ }
+
+ onItemChanged: {
+ // Mark pane as loaded when item is created
+ if (item) {
+ pane.hasBeenLoaded = true;
+ }
+ }
+ }
+
+ Connections {
+ target: root.session
+ function onActiveIndexChanged(): void {
+ pane.updateActive();
+ }
+ }
+
+ Connections {
+ target: layout
+ function onInitialOpeningCompleteChanged(): void {
+ pane.updateActive();
+ }
+ function onAnimationCompleteChanged(): void {
+ pane.updateActive();
}
}
}