mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2025-12-06 06:36:15 +00:00
444 lines
14 KiB
QML
444 lines
14 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import Quickshell
|
|
import Quickshell.Wayland
|
|
import qs.Commons
|
|
import qs.Modules.MainScreen
|
|
import qs.Services.System
|
|
import qs.Services.UI
|
|
import qs.Widgets
|
|
|
|
SmartPanel {
|
|
id: root
|
|
|
|
preferredWidth: Math.round(preferredWidthRatio * 2560 * Style.uiScaleRatio)
|
|
preferredHeight: Math.round(preferredHeightRatio * 1440 * Style.uiScaleRatio)
|
|
preferredWidthRatio: 0.4
|
|
preferredHeightRatio: 0.6
|
|
|
|
panelAnchorHorizontalCenter: true
|
|
panelAnchorVerticalCenter: true
|
|
|
|
closeWithEscape: false
|
|
|
|
property int currentStep: 0
|
|
property int totalSteps: 5
|
|
property bool isCompleting: false
|
|
|
|
onOpened: function () {
|
|
selectedScaleRatio = Settings.data.general.scaleRatio;
|
|
selectedBarPosition = Settings.data.bar.position;
|
|
selectedWallpaperDirectory = Settings.data.wallpaper.directory || Settings.defaultWallpapersDirectory;
|
|
isCompleting = false;
|
|
}
|
|
|
|
Connections {
|
|
target: Settings
|
|
function onSettingsSaved() {
|
|
if (isCompleting) {
|
|
Logger.i("SetupWizard", "Settings saved, closing panel");
|
|
isCompleting = false;
|
|
root.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Setup wizard data
|
|
property string selectedWallpaperDirectory: Settings.defaultWallpapersDirectory
|
|
property string selectedWallpaper: ""
|
|
property real selectedScaleRatio: 1.0
|
|
property string selectedBarPosition: "top"
|
|
|
|
panelContent: Component {
|
|
Item {
|
|
id: container
|
|
anchors.fill: parent
|
|
|
|
ColumnLayout {
|
|
id: wizardContent
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginXL
|
|
spacing: Style.marginL
|
|
|
|
// Step content - takes most of the space
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
Layout.minimumHeight: Math.round(300 * Style.uiScaleRatio)
|
|
|
|
StackLayout {
|
|
id: stepStack
|
|
anchors.fill: parent
|
|
currentIndex: currentStep
|
|
|
|
// Step 0: Welcome - Beautiful centered design
|
|
Item {
|
|
ColumnLayout {
|
|
anchors.centerIn: parent
|
|
width: Math.round(Math.min(parent.width - Style.marginXL * 2, 420))
|
|
spacing: Style.marginXL
|
|
|
|
// Logo with subtle glow effect
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 120
|
|
Layout.alignment: Qt.AlignHCenter
|
|
|
|
Rectangle {
|
|
anchors.centerIn: parent
|
|
width: 120
|
|
height: 120
|
|
radius: width / 2
|
|
color: Color.mPrimary
|
|
opacity: 0.08
|
|
scale: 1.3
|
|
}
|
|
|
|
Image {
|
|
anchors.centerIn: parent
|
|
width: 110
|
|
height: 110
|
|
source: Qt.resolvedUrl(Quickshell.shellDir + "/Assets/noctalia.svg")
|
|
fillMode: Image.PreserveAspectFit
|
|
smooth: true
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: Color.mSurfaceVariant
|
|
radius: width / 2
|
|
border.color: Color.mOutline
|
|
border.width: Style.borderM
|
|
visible: parent.status === Image.Error
|
|
|
|
NIcon {
|
|
icon: "sparkles"
|
|
pointSize: Style.fontSizeXXL * 1.5
|
|
color: Color.mPrimary
|
|
anchors.centerIn: parent
|
|
}
|
|
}
|
|
|
|
// Subtle pulse animation
|
|
SequentialAnimation on scale {
|
|
running: true
|
|
loops: Animation.Infinite
|
|
NumberAnimation {
|
|
from: 1.0
|
|
to: 1.05
|
|
duration: 2000
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
NumberAnimation {
|
|
from: 1.05
|
|
to: 1.0
|
|
duration: 2000
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Welcome text with gradient feel
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
Layout.alignment: Qt.AlignHCenter
|
|
spacing: Style.marginM
|
|
|
|
NText {
|
|
text: "Welcome to Noctalia! ✨"
|
|
pointSize: Style.fontSizeXXL * 1.4
|
|
font.weight: Style.fontWeightBold
|
|
color: Color.mOnSurface
|
|
Layout.fillWidth: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
}
|
|
|
|
NText {
|
|
text: "Let's make your desktop uniquely yours"
|
|
pointSize: Style.fontSizeL
|
|
color: Color.mOnSurfaceVariant
|
|
Layout.fillWidth: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
|
|
// Friendly subtext
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Style.marginL
|
|
Layout.preferredHeight: childrenRect.height + Style.marginM * 2
|
|
color: Color.mSurfaceVariant
|
|
radius: Style.radiusL
|
|
opacity: 0.4
|
|
|
|
NText {
|
|
anchors.centerIn: parent
|
|
width: parent.width - Style.marginL * 2
|
|
text: I18n.tr("setup.welcome.note")
|
|
pointSize: Style.fontSizeM
|
|
color: Color.mOnSurfaceVariant
|
|
horizontalAlignment: Text.AlignHCenter
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 1: Wallpaper Setup
|
|
SetupWallpaperStep {
|
|
id: step1
|
|
selectedDirectory: root.selectedWallpaperDirectory
|
|
selectedWallpaper: root.selectedWallpaper
|
|
onDirectoryChanged: function (directory) {
|
|
root.selectedWallpaperDirectory = directory;
|
|
root.applyWallpaperSettings();
|
|
}
|
|
onWallpaperChanged: function (wallpaper) {
|
|
root.selectedWallpaper = wallpaper;
|
|
root.applyWallpaperSettings();
|
|
}
|
|
}
|
|
|
|
// Step 2: Appearance - Dark mode and color source
|
|
SetupAppearanceStep {
|
|
id: step3
|
|
}
|
|
|
|
// Step 3: UI Configuration
|
|
SetupCustomizeStep {
|
|
id: step2
|
|
selectedScaleRatio: root.selectedScaleRatio
|
|
selectedBarPosition: root.selectedBarPosition
|
|
onScaleRatioChanged: function (ratio) {
|
|
root.selectedScaleRatio = ratio;
|
|
root.applyUISettings();
|
|
}
|
|
onBarPositionChanged: function (position) {
|
|
root.selectedBarPosition = position;
|
|
root.applyUISettings();
|
|
}
|
|
}
|
|
|
|
// Step 4: Dock Setup
|
|
SetupDockStep {
|
|
id: stepDock
|
|
}
|
|
}
|
|
}
|
|
|
|
// Elegant divider
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 1
|
|
color: Color.mOutline
|
|
opacity: 0.2
|
|
}
|
|
|
|
// Modern progress indicator with labels
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 32
|
|
|
|
RowLayout {
|
|
anchors.centerIn: parent
|
|
spacing: Style.marginM
|
|
|
|
Repeater {
|
|
model: [
|
|
{
|
|
"icon": "sparkles",
|
|
"label": "Welcome"
|
|
},
|
|
{
|
|
"icon": "image",
|
|
"label": "Wallpaper"
|
|
},
|
|
{
|
|
"icon": "palette",
|
|
"label": "Appearance"
|
|
},
|
|
{
|
|
"icon": "settings",
|
|
"label": "Customize"
|
|
},
|
|
{
|
|
"icon": "device-desktop",
|
|
"label": "Dock"
|
|
}
|
|
]
|
|
delegate: RowLayout {
|
|
spacing: Style.marginS
|
|
|
|
Rectangle {
|
|
width: 24
|
|
height: 24
|
|
radius: width / 2
|
|
color: index <= currentStep ? Color.mPrimary : Color.mSurfaceVariant
|
|
border.color: index === currentStep ? Color.mPrimary : "transparent"
|
|
border.width: index === currentStep ? 2 : 0
|
|
|
|
NIcon {
|
|
icon: modelData.icon
|
|
pointSize: Style.fontSizeS
|
|
color: index <= currentStep ? Color.mOnPrimary : Color.mOnSurfaceVariant
|
|
anchors.centerIn: parent
|
|
}
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationNormal
|
|
}
|
|
}
|
|
}
|
|
|
|
NText {
|
|
text: modelData.label
|
|
pointSize: Style.fontSizeS
|
|
color: index <= currentStep ? Color.mPrimary : Color.mOnSurfaceVariant
|
|
font.weight: index === currentStep ? Style.fontWeightBold : Style.fontWeightRegular
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationNormal
|
|
}
|
|
}
|
|
}
|
|
|
|
// Connector line
|
|
Rectangle {
|
|
width: 40
|
|
height: 2
|
|
radius: 1
|
|
color: index < currentStep ? Color.mPrimary : Color.mSurfaceVariant
|
|
visible: index < totalSteps - 1
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationNormal
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Smooth navigation buttons
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 44
|
|
Layout.topMargin: Style.marginS
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
spacing: Style.marginM
|
|
|
|
NButton {
|
|
text: "Skip Setup"
|
|
outlined: true
|
|
visible: currentStep === 0
|
|
Layout.preferredHeight: 44
|
|
onClicked: {
|
|
root.completeSetup();
|
|
}
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
NButton {
|
|
text: "← Back"
|
|
outlined: true
|
|
visible: currentStep > 0
|
|
Layout.preferredHeight: 44
|
|
onClicked: {
|
|
if (currentStep > 0) {
|
|
currentStep--;
|
|
}
|
|
}
|
|
}
|
|
|
|
NButton {
|
|
text: currentStep === totalSteps - 1 ? "All Done!" : "Continue →"
|
|
Layout.preferredHeight: 44
|
|
onClicked: {
|
|
if (currentStep < totalSteps - 1) {
|
|
currentStep++;
|
|
} else {
|
|
root.completeSetup();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function completeSetup() {
|
|
if (isCompleting) {
|
|
Logger.w("SetupWizard", "completeSetup() called while already completing, ignoring");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
Logger.i("SetupWizard", "Completing setup with selected options");
|
|
isCompleting = true;
|
|
|
|
if (selectedWallpaperDirectory !== Settings.data.wallpaper.directory) {
|
|
Settings.data.wallpaper.directory = selectedWallpaperDirectory;
|
|
WallpaperService.refreshWallpapersList();
|
|
}
|
|
|
|
if (selectedWallpaper !== "") {
|
|
WallpaperService.changeWallpaper(selectedWallpaper, undefined);
|
|
}
|
|
|
|
Settings.data.general.scaleRatio = selectedScaleRatio;
|
|
Settings.data.bar.position = selectedBarPosition;
|
|
Settings.data.setupCompleted = true;
|
|
|
|
// Save settings immediately and wait for settingsSaved signal before closing
|
|
Settings.saveImmediate();
|
|
Logger.i("SetupWizard", "Setup completed successfully, waiting for settings save confirmation");
|
|
|
|
// Fallback: if settingsSaved signal doesn't fire within 2 seconds, close anyway
|
|
closeTimer.start();
|
|
} catch (error) {
|
|
Logger.e("SetupWizard", "Error completing setup:", error);
|
|
isCompleting = false;
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: closeTimer
|
|
interval: 2000
|
|
onTriggered: {
|
|
if (isCompleting) {
|
|
Logger.w("SetupWizard", "Settings save timeout, closing panel anyway");
|
|
isCompleting = false;
|
|
root.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
function applyWallpaperSettings() {
|
|
if (selectedWallpaperDirectory !== Settings.data.wallpaper.directory) {
|
|
Settings.data.wallpaper.directory = selectedWallpaperDirectory;
|
|
WallpaperService.refreshWallpapersList();
|
|
}
|
|
|
|
if (selectedWallpaper !== "") {
|
|
WallpaperService.changeWallpaper(selectedWallpaper, undefined);
|
|
}
|
|
}
|
|
|
|
function applyUISettings() {
|
|
Settings.data.general.scaleRatio = selectedScaleRatio;
|
|
Settings.data.bar.position = selectedBarPosition;
|
|
}
|
|
}
|