feat: add nexus sub pages
This commit is contained in:
parent
550eb0bf1a
commit
4a77746393
5 changed files with 194 additions and 24 deletions
|
|
@ -5,7 +5,22 @@ QtObject {
|
|||
property ShellScreen screen
|
||||
property bool isWindow
|
||||
property int currentPageIdx
|
||||
property list<int> subPageIdxStack
|
||||
property bool searchOpen
|
||||
|
||||
signal close
|
||||
signal subPageOpened(idx: int)
|
||||
signal subPageClosed
|
||||
|
||||
function openSubPage(idx: int): void {
|
||||
subPageIdxStack.push(idx);
|
||||
subPageOpened(idx);
|
||||
}
|
||||
|
||||
function closeSubPage(): void {
|
||||
subPageClosed();
|
||||
subPageIdxStack.pop();
|
||||
}
|
||||
|
||||
onCurrentPageIdxChanged: subPageIdxStack.length = 0
|
||||
}
|
||||
|
|
|
|||
20
modules/nexus/PageCompRegistry.qml
Normal file
20
modules/nexus/PageCompRegistry.qml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import qs.modules.nexus.common
|
||||
import qs.modules.nexus.pages
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
readonly property list<Component> pageComps: [
|
||||
// Appearance
|
||||
Component {
|
||||
StackPage {
|
||||
Component {
|
||||
WallpaperAndStyle {}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import "pages"
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Caelestia.Config
|
||||
|
|
@ -13,23 +12,39 @@ Item {
|
|||
|
||||
required property NexusState nState
|
||||
|
||||
readonly property list<Component> pageComps: [
|
||||
Component {
|
||||
WallpaperAndStyle {
|
||||
nState: root.nState
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
property int lastPageIdx
|
||||
property int animOff
|
||||
property Item currentItem
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
function loadPage(idx: int): void {
|
||||
if (currentItem)
|
||||
currentItem.destroy();
|
||||
|
||||
const comp = PageCompRegistry.pageComps[idx] ?? placeholderComp;
|
||||
const incubator = comp.incubateObject(container, {
|
||||
nState
|
||||
});
|
||||
|
||||
const attach = () => {
|
||||
incubator.object.anchors.fill = container;
|
||||
currentItem = incubator.object;
|
||||
};
|
||||
|
||||
if (incubator.status === Component.Ready)
|
||||
attach();
|
||||
else
|
||||
incubator.onStatusChanged = status => {
|
||||
if (status === Component.Ready)
|
||||
attach();
|
||||
};
|
||||
}
|
||||
|
||||
Item {
|
||||
id: container
|
||||
|
||||
anchors.fill: parent
|
||||
layer.enabled: opacity < 1
|
||||
Component.onCompleted: sourceComponent = root.pageComps[root.nState.currentPageIdx] ?? placeholderComp
|
||||
Component.onCompleted: root.loadPage(root.nState.currentPageIdx)
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
|
@ -47,36 +62,34 @@ Item {
|
|||
id: switchAnim
|
||||
|
||||
Anim {
|
||||
target: loader
|
||||
target: container
|
||||
property: "opacity"
|
||||
to: 0
|
||||
type: Anim.DefaultEffects
|
||||
}
|
||||
PropertyAction {
|
||||
target: loader
|
||||
property: "sourceComponent"
|
||||
value: root.pageComps[root.nState.currentPageIdx] ?? placeholderComp
|
||||
ScriptAction {
|
||||
script: root.loadPage(root.nState.currentPageIdx)
|
||||
}
|
||||
PropertyAction {
|
||||
target: loader.anchors
|
||||
target: container.anchors
|
||||
property: "topMargin"
|
||||
value: root.animOff
|
||||
}
|
||||
PropertyAction {
|
||||
target: loader.anchors
|
||||
target: container.anchors
|
||||
property: "bottomMargin"
|
||||
value: -root.animOff
|
||||
}
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
target: loader
|
||||
target: container
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
type: Anim.SlowEffects
|
||||
}
|
||||
Anim {
|
||||
target: loader.anchors
|
||||
target: container.anchors
|
||||
properties: "topMargin,bottomMargin"
|
||||
to: 0
|
||||
type: Anim.SlowEffects
|
||||
|
|
@ -88,6 +101,8 @@ Item {
|
|||
id: placeholderComp
|
||||
|
||||
Item {
|
||||
property NexusState nState // To avoid the warning from non-existent property
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: Tokens.padding.extraSmall
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ ColumnLayout {
|
|||
|
||||
default property Item contentChild
|
||||
|
||||
signal close
|
||||
|
||||
spacing: Tokens.spacing.extraExtraLarge
|
||||
|
||||
RowLayout {
|
||||
|
|
@ -37,7 +35,7 @@ ColumnLayout {
|
|||
isRound: true
|
||||
inactiveColour: Colours.tPalette.m3surfaceContainerHigh
|
||||
inactiveOnColour: Colours.palette.m3onSurface
|
||||
onClicked: root.close()
|
||||
onClicked: root.nState.closeSubPage()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
122
modules/nexus/common/StackPage.qml
Normal file
122
modules/nexus/common/StackPage.qml
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Caelestia.Config
|
||||
import qs.components
|
||||
import qs.modules.nexus
|
||||
|
||||
StackView {
|
||||
id: root
|
||||
|
||||
required property NexusState nState
|
||||
default property list<Component> pages
|
||||
readonly property int animMovement: Tokens.padding.extraExtraLarge * 2
|
||||
|
||||
function openSubPage(idx: int, immediate: bool): void {
|
||||
const page = pages[idx];
|
||||
if (page) {
|
||||
push(page, {
|
||||
nState
|
||||
}, immediate ? StackView.Immediate : StackView.PushTransition);
|
||||
} else {
|
||||
console.warn(logCat, "Attempted to open invalid sub-page index", idx);
|
||||
nState.closeSubPage();
|
||||
}
|
||||
}
|
||||
|
||||
clip: busy
|
||||
|
||||
Component.onCompleted: {
|
||||
openSubPage(0, true);
|
||||
for (const page of nState.subPageIdxStack)
|
||||
openSubPage(page, true);
|
||||
}
|
||||
|
||||
pushEnter: Transition {
|
||||
SequentialAnimation {
|
||||
PropertyAction {
|
||||
property: "opacity"
|
||||
value: 0
|
||||
}
|
||||
PauseAnimation {
|
||||
duration: Tokens.anim.durations.expressiveDefaultEffects
|
||||
}
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
type: Anim.SlowEffects
|
||||
}
|
||||
Anim {
|
||||
property: "x"
|
||||
from: root.animMovement
|
||||
to: 0
|
||||
type: Anim.SlowEffects
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pushExit: Transition {
|
||||
Anim {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
type: Anim.DefaultEffects
|
||||
}
|
||||
}
|
||||
|
||||
popEnter: Transition {
|
||||
SequentialAnimation {
|
||||
PropertyAction {
|
||||
property: "opacity"
|
||||
value: 0
|
||||
}
|
||||
PauseAnimation {
|
||||
duration: Tokens.anim.durations.expressiveDefaultEffects
|
||||
}
|
||||
ParallelAnimation {
|
||||
Anim {
|
||||
property: "opacity"
|
||||
to: 1
|
||||
type: Anim.SlowEffects
|
||||
}
|
||||
Anim {
|
||||
property: "x"
|
||||
from: -root.animMovement
|
||||
to: 0
|
||||
type: Anim.SlowEffects
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
popExit: Transition {
|
||||
Anim {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
type: Anim.DefaultEffects
|
||||
}
|
||||
}
|
||||
|
||||
LoggingCategory {
|
||||
id: logCat
|
||||
|
||||
name: "caelestia.nexus"
|
||||
defaultLogLevel: LoggingCategory.Info
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onSubPageOpened(idx: int): void {
|
||||
root.openSubPage(idx, false);
|
||||
}
|
||||
|
||||
function onSubPageClosed(): void {
|
||||
if (root.depth < root.nState.subPageIdxStack.length) {
|
||||
console.log(logCat, "Attempted to close page while depth < stack depth. Ignoring.");
|
||||
return;
|
||||
}
|
||||
root.pop();
|
||||
}
|
||||
|
||||
target: root.nState
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue