From ebd0bdd37090827f1046e3b928771d29b8ec7f1a Mon Sep 17 00:00:00 2001 From: Corey Woodworth Date: Wed, 15 Oct 2025 11:24:26 -0400 Subject: [PATCH 01/15] feat: Add option to load control center panel in the center of the screen --- Modules/ControlCenter/ControlCenterPanel.qml | 4 ++-- Modules/Settings/Tabs/ControlCenterTab.qml | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 599dddb6..45cf6a9c 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -46,8 +46,8 @@ NPanel { // Positioning readonly property string controlCenterPosition: Settings.data.controlCenter.position - panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_center") - panelAnchorVerticalCenter: false + panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && (controlCenterPosition.endsWith("_center") || controlCenterPosition === "center") + panelAnchorVerticalCenter: controlCenterPosition === "center" panelAnchorLeft: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_left") panelAnchorRight: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_right") panelAnchorBottom: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.startsWith("bottom_") diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml index 4bf62cfb..5fbbbf9e 100644 --- a/Modules/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -143,6 +143,9 @@ ColumnLayout { }, { "key": "top_center", "name": I18n.tr("options.control-center.position.top_center") + }, { + "key": "center", + "name": I18n.tr("options.control-center.position.center") }] currentKey: Settings.data.controlCenter.position onSelected: function (key) { From 4cf79d9ed7f9633b8369235f3c268c9ab1831246 Mon Sep 17 00:00:00 2001 From: Corey Woodworth Date: Wed, 15 Oct 2025 11:27:56 -0400 Subject: [PATCH 02/15] Include english string --- Assets/Translations/en.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 7f6cf5c7..9052de86 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1305,7 +1305,8 @@ "bottom_left": "Bottom left", "bottom_right": "Bottom right", "bottom_center": "Bottom center", - "top_center": "Top center" + "top_center": "Top center", + "center": "Center" }, "quickSettingsStyle": { "modern": "Modern", @@ -1623,4 +1624,4 @@ "disabled": "Battery manager disabled" } } -} \ No newline at end of file +} From 1d1c5ec01648e219a7614ac8fc6a638f676e3561 Mon Sep 17 00:00:00 2001 From: Corey Woodworth Date: Wed, 15 Oct 2025 11:48:13 -0400 Subject: [PATCH 03/15] Include additional translation strings --- Assets/Translations/de.json | 5 +++-- Assets/Translations/es.json | 5 +++-- Assets/Translations/fr.json | 5 +++-- Assets/Translations/pt.json | 5 +++-- Assets/Translations/zh-CN.json | 5 +++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 6a5bb0bd..b75e0079 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1322,7 +1322,8 @@ "bottom_left": "Unten links", "bottom_right": "Unten rechts", "bottom_center": "Unten mittig", - "top_center": "Oben mittig" + "top_center": "Oben mittig", + "center": "Mitte" }, "quickSettingsStyle": { "modern": "Modern", @@ -1623,4 +1624,4 @@ "description": "Das Control-Center-Widget wurde aus der Leiste entfernt. Um es erneut über die Leiste zu öffnen, fügen Sie das Widget wieder hinzu. Sie können es auch durch Rechtsklick auf die Leiste öffnen." } } -} \ No newline at end of file +} diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 9ced10d2..fe0fd6fa 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -1305,7 +1305,8 @@ "bottom_left": "Inferior izquierda", "bottom_right": "Inferior derecha", "bottom_center": "Inferior central", - "top_center": "Superior central" + "top_center": "Superior central", + "center": "Centro" }, "quickSettingsStyle": { "modern": "Moderno", @@ -1623,4 +1624,4 @@ "disabled": "Administrador de batería deshabilitado" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 1d2d9568..e8ab41bc 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1305,7 +1305,8 @@ "bottom_left": "En bas à gauche", "bottom_right": "En bas à droite", "bottom_center": "En bas au centre", - "top_center": "En haut au centre" + "top_center": "En haut au centre", + "center": "Centre" }, "quickSettingsStyle": { "modern": "Moderne", @@ -1623,4 +1624,4 @@ "disabled": "Gestionnaire de batterie désactivé" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 118939a8..ac27a3b5 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -1303,7 +1303,8 @@ "bottom_left": "Inferior esquerdo", "bottom_right": "Inferior direito", "bottom_center": "Centro inferior", - "top_center": "Centro superior" + "top_center": "Centro superior", + "center": "Centro" }, "quickSettingsStyle": { "modern": "Moderno", @@ -1629,4 +1630,4 @@ "uninstall-failed": "Falha na desinstalação" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index d64db2ff..fd255395 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -1305,7 +1305,8 @@ "bottom_left": "左下角", "bottom_right": "右下角", "bottom_center": "底部居中", - "top_center": "顶部居中" + "top_center": "顶部居中", + "center": "居中" }, "quickSettingsStyle": { "modern": "现代", @@ -1623,4 +1624,4 @@ "disabled": "电池管理器已禁用" } } -} \ No newline at end of file +} From 514fdaa4ccb3421f501e0dc869ccabcfc25172e1 Mon Sep 17 00:00:00 2001 From: lysec Date: Wed, 15 Oct 2025 18:01:08 +0200 Subject: [PATCH 04/15] SetupWizard: initial commit --- Assets/Translations/de.json | 30 ++ Assets/Translations/en.json | 29 + Assets/Translations/es.json | 30 ++ Assets/Translations/fr.json | 31 ++ Assets/Translations/pt.json | 31 ++ Assets/Translations/zh-CN.json | 31 ++ Assets/settings-default.json | 3 +- Commons/Settings.qml | 1 + Modules/SetupWizard/SetupAppearanceStep.qml | 555 ++++++++++++++++++++ Modules/SetupWizard/SetupCustomizeStep.qml | 522 ++++++++++++++++++ Modules/SetupWizard/SetupWallpaperStep.qml | 507 ++++++++++++++++++ Modules/SetupWizard/SetupWizard.qml | 414 +++++++++++++++ Services/AppThemeService.qml | 2 +- Widgets/NImageCached.qml | 20 +- shell.qml | 26 + 15 files changed, 2228 insertions(+), 4 deletions(-) create mode 100644 Modules/SetupWizard/SetupAppearanceStep.qml create mode 100644 Modules/SetupWizard/SetupCustomizeStep.qml create mode 100644 Modules/SetupWizard/SetupWallpaperStep.qml create mode 100644 Modules/SetupWizard/SetupWizard.qml diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 6a5bb0bd..3bfd4dd6 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1621,6 +1621,36 @@ "missing-control-center": { "label": "Letztes Control-Center-Widget entfernt", "description": "Das Control-Center-Widget wurde aus der Leiste entfernt. Um es erneut über die Leiste zu öffnen, fügen Sie das Widget wieder hinzu. Sie können es auch durch Rechtsklick auf die Leiste öffnen." + }, + "setup": { + "customize": { + "header": "Erlebnis anpassen", + "subheader": "Leistenposition, Dichte, Skalierung und mehr einstellen." + }, + "appearance": { + "header": "Erscheinungsbild", + "subheader": "Dunkelmodus und Farbquellen wählen (Matugen oder vordefiniert)." + }, + "wallpaper": { + "header": "Wähle dein Hintergrundbild", + "subheader": "Bestimme die Stimmung mit einem schönen Hintergrund.", + "select-prompt": "Wähle unten ein Hintergrundbild", + "preview-error": "Bild konnte nicht geladen werden", + "none-in-dir": "Keine Hintergrundbilder im Verzeichnis gefunden", + "no-dir": "Kein Hintergrundbild-Verzeichnis ausgewählt", + "no-valid": "Keine gültigen Bilddateien gefunden in: {dir}", + "choose-dir": "Wähle ein Verzeichnis mit deinen Hintergrundbildern", + "dir": { + "label": "Hintergrundbild-Verzeichnis", + "description": "Wähle den Ordner mit deinen Hintergrundbildern", + "browse": "Ordner auswählen", + "select-title": "Hintergrundbild-Ordner wählen" + } } + , + "welcome": { + "note": "Nur ein paar Grundeinstellungen – alle Optionen findest du in den Einstellungen" } + } +} } \ No newline at end of file diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 7f6cf5c7..bd8545e4 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1622,5 +1622,34 @@ "lifespan": "Extended lifespan ({percent}%)", "disabled": "Battery manager disabled" } + }, + "setup": { + "customize": { + "header": "Customize your experience", + "subheader": "Adjust bar position, density, scaling and more." + }, + "appearance": { + "header": "Appearance", + "subheader": "Choose dark mode and color sources (Matugen or predefined)." + }, + "wallpaper": { + "header": "Choose your wallpaper", + "subheader": "Set the mood with a beautiful background.", + "select-prompt": "Select a wallpaper below", + "preview-error": "Failed to load image", + "none-in-dir": "No wallpapers found in directory", + "no-dir": "No wallpaper directory selected", + "no-valid": "No valid image files found in: {dir}", + "choose-dir": "Choose a directory containing your wallpaper images", + "dir": { + "label": "Wallpaper directory", + "description": "Choose the folder containing your wallpapers", + "browse": "Browse for wallpaper folder", + "select-title": "Select wallpaper folder" + } + }, + "welcome": { + "note": "Just a few basics to get you started - full options are in Settings" + } } } \ No newline at end of file diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 9ced10d2..e33bbb3b 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -1622,5 +1622,35 @@ "lifespan": "Vida útil prolongada ({percent}%)", "disabled": "Administrador de batería deshabilitado" } + }, + "setup": { + "customize": { + "header": "Personaliza tu experiencia", + "subheader": "Ajusta la posición de la barra, densidad, escala y más." + }, + "appearance": { + "header": "Apariencia", + "subheader": "Elige modo oscuro y fuentes de color (Matugen o predefinido)." + }, + "wallpaper": { + "header": "Elige tu fondo", + "subheader": "Define el ambiente con un bonito fondo.", + "select-prompt": "Selecciona un fondo abajo", + "preview-error": "No se pudo cargar la imagen", + "none-in-dir": "No se encontraron fondos en el directorio", + "no-dir": "No se seleccionó un directorio de fondos", + "no-valid": "No se encontraron imágenes válidas en: {dir}", + "choose-dir": "Elige un directorio que contenga tus fondos", + "dir": { + "label": "Directorio de fondos", + "description": "Elige la carpeta que contiene tus fondos", + "browse": "Seleccionar carpeta", + "select-title": "Seleccionar carpeta de fondos" + } + , + "welcome": { + "note": "Solo algunos ajustes básicos para empezar - el resto está en Configuración" } + } +} } \ No newline at end of file diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 1d2d9568..c613046d 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1623,4 +1623,35 @@ "disabled": "Gestionnaire de batterie désactivé" } } + , + "setup": { + "customize": { + "header": "Personnaliser votre expérience", + "subheader": "Ajustez la position de la barre, la densité, l'échelle et plus encore." + }, + "appearance": { + "header": "Apparence", + "subheader": "Choisissez le mode sombre et la source des couleurs (Matugen ou prédéfinie)." + }, + "wallpaper": { + "header": "Choisissez votre fond d'écran", + "subheader": "Définissez l'ambiance avec un joli fond.", + "select-prompt": "Sélectionnez un fond ci-dessous", + "preview-error": "Échec du chargement de l'image", + "none-in-dir": "Aucun fond d'écran trouvé dans le répertoire", + "no-dir": "Aucun répertoire de fonds d'écran sélectionné", + "no-valid": "Aucun fichier image valide trouvé dans : {dir}", + "choose-dir": "Choisissez un répertoire contenant vos fonds d'écran", + "dir": { + "label": "Répertoire des fonds d'écran", + "description": "Choisissez le dossier contenant vos fonds d'écran", + "browse": "Parcourir le dossier", + "select-title": "Sélectionner le dossier des fonds d'écran" + } + } + , + "welcome": { + "note": "Quelques réglages de base pour démarrer — toutes les options sont dans Paramètres" + } + } } \ No newline at end of file diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 118939a8..e825b83e 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -1629,4 +1629,35 @@ "uninstall-failed": "Falha na desinstalação" } } + , + "setup": { + "customize": { + "header": "Personalizar a sua experiência", + "subheader": "Ajuste a posição da barra, densidade, escala e mais." + }, + "appearance": { + "header": "Aparência", + "subheader": "Escolha o modo escuro e as fontes de cores (Matugen ou predefinidas)." + }, + "wallpaper": { + "header": "Escolha o seu papel de parede", + "subheader": "Defina o ambiente com um belo fundo.", + "select-prompt": "Selecione um papel de parede abaixo", + "preview-error": "Falha ao carregar a imagem", + "none-in-dir": "Nenhum papel de parede encontrado no diretório", + "no-dir": "Nenhum diretório de papéis de parede selecionado", + "no-valid": "Nenhuma imagem válida encontrada em: {dir}", + "choose-dir": "Escolha um diretório contendo seus papéis de parede", + "dir": { + "label": "Diretório de papéis de parede", + "description": "Escolha a pasta que contém seus papéis de parede", + "browse": "Procurar pasta", + "select-title": "Selecionar pasta de papéis de parede" + } + } + , + "welcome": { + "note": "Apenas alguns ajustes básicos para começar - o restante está em Configurações" + } + } } \ No newline at end of file diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index d64db2ff..9aa29719 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -1623,4 +1623,35 @@ "disabled": "电池管理器已禁用" } } + , + "setup": { + "customize": { + "header": "自定义体验", + "subheader": "调整状态栏位置、密度、缩放等。" + }, + "appearance": { + "header": "外观", + "subheader": "选择深色模式与配色来源(Matugen 或预设)。" + }, + "wallpaper": { + "header": "选择你的壁纸", + "subheader": "用精美壁纸营造氛围。", + "select-prompt": "在下方选择一张壁纸", + "preview-error": "图片加载失败", + "none-in-dir": "目录中未找到壁纸", + "no-dir": "未选择壁纸目录", + "no-valid": "在 {dir} 中未找到有效图片文件", + "choose-dir": "选择包含壁纸图片的目录", + "dir": { + "label": "壁纸目录", + "description": "选择存放壁纸的文件夹", + "browse": "浏览文件夹", + "select-title": "选择壁纸文件夹" + } + } + , + "welcome": { + "note": "先进行一些基础设置——更多选项可在“设置”中找到" + } + } } \ No newline at end of file diff --git a/Assets/settings-default.json b/Assets/settings-default.json index b8a82259..99ef9c6d 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -64,7 +64,8 @@ "screenRadiusRatio": 1, "animationSpeed": 1, "animationDisabled": false, - "compactLockScreen": false + "compactLockScreen": false, + "setupCompleted": false }, "location": { "name": "Tokyo", diff --git a/Commons/Settings.qml b/Commons/Settings.qml index d0308487..2349a292 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -185,6 +185,7 @@ Singleton { property real animationSpeed: 1.0 property bool animationDisabled: false property bool compactLockScreen: false + property bool setupCompleted: false } // location diff --git a/Modules/SetupWizard/SetupAppearanceStep.qml b/Modules/SetupWizard/SetupAppearanceStep.qml new file mode 100644 index 00000000..15c8c1ee --- /dev/null +++ b/Modules/SetupWizard/SetupAppearanceStep.qml @@ -0,0 +1,555 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Quickshell.Io +import qs.Commons +import qs.Services +import qs.Widgets + +ColumnLayout { + id: root + spacing: Style.marginM + + function extractSchemeName(path) { + var basename = path.split('/').pop() + return basename.replace('.json', '') + } + + // Cache for scheme colors (mirrors ColorSchemeTab approach) + property var schemeColorsCache: ({}) + property int cacheVersion: 0 + + function getSchemeColor(schemeName, key) { + try { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var data = schemeColorsCache[schemeName] + if (data && data[mode] && data[mode][key]) + return data[mode][key] + } catch (e) { + + } + return Color.mSurfaceVariant + } + + // Match ColorSchemeTab helpers + function schemeLoaded(schemeName, jsonData) { + var value = jsonData || {} + schemeColorsCache[schemeName] = value + cacheVersion++ + Logger.log("SetupAppearanceStep", `Loaded scheme ${schemeName}`) + } + + Connections { + target: ColorSchemeService + function onSchemesChanged() { + Logger.log("SetupAppearanceStep", `Color schemes changed: ${ColorSchemeService.schemes.length}`) + schemeColorsCache = {} + cacheVersion++ + } + } + + // Beautiful header with icon + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "palette" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginXS + + NText { + text: I18n.tr("setup.appearance.header") + pointSize: Style.fontSizeXL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("setup.appearance.subheader") + pointSize: Style.fontSizeM + color: Color.mOnSurfaceVariant + } + } + } + + ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + clip: true + contentWidth: availableWidth + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + ColumnLayout { + width: parent.width + spacing: Style.marginM + + // Dark Mode Toggle + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "moon" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + NText { + text: I18n.tr("settings.color-scheme.color-source.dark-mode.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("settings.color-scheme.color-source.dark-mode.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + + NToggle { + checked: Settings.data.colorSchemes.darkMode + onToggled: checked => Settings.data.colorSchemes.darkMode = checked + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + } + + // Wallpaper Colors Toggle + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "color-picker" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + NText { + text: I18n.tr("settings.color-scheme.color-source.use-wallpaper-colors.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("settings.color-scheme.color-source.use-wallpaper-colors.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + + NToggle { + enabled: ProgramCheckerService.matugenAvailable + opacity: ProgramCheckerService.matugenAvailable ? 1.0 : 0.6 + checked: Settings.data.colorSchemes.useWallpaperColors && ProgramCheckerService.matugenAvailable + onToggled: checked => { + if (!ProgramCheckerService.matugenAvailable) + return + if (checked) { + Settings.data.colorSchemes.useWallpaperColors = true + AppThemeService.generate() + } else { + Settings.data.colorSchemes.useWallpaperColors = false + if (Settings.data.colorSchemes.predefinedScheme) { + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + } + } + } + } + } + + // Matugen not available notice + RowLayout { + Layout.fillWidth: true + spacing: Style.marginS + visible: !ProgramCheckerService.matugenAvailable + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + NIcon { + icon: "alert-triangle" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + NText { + text: I18n.tr("settings.color-scheme.color-source.use-wallpaper-colors.description") + // Reuse description; availability is visually indicated + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + + // Matugen scheme type (visible when wallpaper colors enabled and matugen available) + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + visible: Settings.data.colorSchemes.useWallpaperColors && ProgramCheckerService.matugenAvailable + + RowLayout { + Layout.fillWidth: true + spacing: Style.marginS + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "wand" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + NText { + text: I18n.tr("settings.color-scheme.color-source.matugen-scheme-type.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("settings.color-scheme.color-source.matugen-scheme-type.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } + } + } + + // Matugen scheme options styled like bar position buttons + GridLayout { + Layout.fillWidth: true + columns: 2 + rowSpacing: Style.marginS + columnSpacing: Style.marginS + + Repeater { + model: [{ + "key": "scheme-content", + "name": "Content" + }, { + "key": "scheme-expressive", + "name": "Expressive" + }, { + "key": "scheme-fidelity", + "name": "Fidelity" + }, { + "key": "scheme-fruit-salad", + "name": "Fruit Salad" + }, { + "key": "scheme-monochrome", + "name": "Monochrome" + }, { + "key": "scheme-neutral", + "name": "Neutral" + }, { + "key": "scheme-rainbow", + "name": "Rainbow" + }, { + "key": "scheme-tonal-spot", + "name": "Tonal Spot" + }] + delegate: Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 48 + radius: Style.radiusM + border.width: 1 + + property bool isActive: Settings.data.colorSchemes.matugenSchemeType === modelData.key + + color: (hoverHandler.hovered || isActive) ? Color.mPrimary : Color.mSurfaceVariant + border.color: (hoverHandler.hovered || isActive) ? Color.mPrimary : Color.mOutline + opacity: (hoverHandler.hovered || isActive) ? 1.0 : 0.8 + + NText { + text: modelData.name + pointSize: Style.fontSizeM + font.weight: (hoverHandler.hovered || parent.isActive) ? Style.fontWeightBold : Style.fontWeightMedium + color: (hoverHandler.hovered || parent.isActive) ? Color.mOnPrimary : Color.mOnSurface + anchors.centerIn: parent + } + + HoverHandler { + id: hoverHandler + } + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + Settings.data.colorSchemes.matugenSchemeType = modelData.key + AppThemeService.generate() + } + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + Behavior on border.color { + ColorAnimation { + duration: Style.animationFast + } + } + Behavior on opacity { + NumberAnimation { + duration: Style.animationFast + } + } + } + } + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + visible: !Settings.data.colorSchemes.useWallpaperColors + } + + // Predefined schemes section (visible when wallpaper colors disabled) + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + visible: !Settings.data.colorSchemes.useWallpaperColors + + RowLayout { + Layout.fillWidth: true + spacing: Style.marginS + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "palette" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + NText { + text: I18n.tr("settings.color-scheme.predefined.section.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("settings.color-scheme.predefined.section.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } + } + } + + // Predefined schemes Grid (matches ColorSchemeTab) + GridLayout { + id: schemesGrid + columns: Math.max(2, Math.floor((parent.width - Style.marginM * 2) / 180)) + rowSpacing: Style.marginM + columnSpacing: Style.marginM + Layout.fillWidth: true + + Repeater { + model: ColorSchemeService.schemes + + delegate: Rectangle { + id: schemeItem + + property string schemePath: modelData + property string schemeName: root.extractSchemeName(modelData) + + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + height: 50 + radius: Style.radiusS + color: (root.cacheVersionroot.getSchemeColor(schemeName, "mSurface")) + border.width: Math.max(1, Style.borderL) + border.color: itemMouseArea.containsMouse ? Color.mTertiary : (Settings.data.colorSchemes.predefinedScheme === schemeName ? Color.mSecondary : Color.mOutline) + + RowLayout { + anchors.fill: parent + anchors.margins: Style.marginL + spacing: Style.marginXS + + NText { + text: schemeItem.schemeName + pointSize: Style.fontSizeS + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + Layout.fillWidth: true + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + maximumLineCount: 1 + } + + Rectangle { + width: 14 + height: 14 + radius: width * 0.5 + color: (root.cacheVersionfunction () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mPrimary) || root.getSchemeColor(schemeItem.schemeName, "mPrimary") + })() + } + Rectangle { + width: 14 + height: 14 + radius: width * 0.5 + color: (root.cacheVersionfunction () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mSecondary) || root.getSchemeColor(schemeItem.schemeName, "mSecondary") + })() + } + Rectangle { + width: 14 + height: 14 + radius: width * 0.5 + color: (root.cacheVersionfunction () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mTertiary) || root.getSchemeColor(schemeItem.schemeName, "mTertiary") + })() + } + Rectangle { + width: 14 + height: 14 + radius: width * 0.5 + color: (root.cacheVersionfunction () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mError) || root.getSchemeColor(schemeItem.schemeName, "mError") + })() + } + } + + MouseArea { + id: itemMouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + Settings.data.colorSchemes.useWallpaperColors = false + Settings.data.colorSchemes.predefinedScheme = schemeItem.schemeName + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + } + } + } + } + } + } + + // Bottom spacer + Item { + Layout.fillWidth: true + Layout.preferredHeight: Style.marginL + } + } + } + + // Hidden loader to populate schemeColorsCache from files + Item { + visible: false + Repeater { + model: ColorSchemeService.schemes + delegate: Item { + FileView { + path: modelData + blockLoading: false + onLoaded: { + var schemeName = root.extractSchemeName(path) + try { + var jsonData = JSON.parse(text()) + root.schemeLoaded(schemeName, jsonData) + } catch (e) { + root.schemeLoaded(schemeName, null) + } + } + } + } + } + } +} diff --git a/Modules/SetupWizard/SetupCustomizeStep.qml b/Modules/SetupWizard/SetupCustomizeStep.qml new file mode 100644 index 00000000..a1854f5f --- /dev/null +++ b/Modules/SetupWizard/SetupCustomizeStep.qml @@ -0,0 +1,522 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +ColumnLayout { + id: root + + property real selectedScaleRatio: 1.0 + property string selectedBarPosition: "top" + property bool selectedDimDesktop: true + + signal scaleRatioChanged(real ratio) + signal barPositionChanged(string position) + signal dimDesktopChanged(bool dim) + + spacing: Style.marginM + + // Beautiful header with icon + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "palette" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginXS + + NText { + text: I18n.tr("setup.customize.header") + pointSize: Style.fontSizeXL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("setup.customize.subheader") + pointSize: Style.fontSizeM + color: Color.mOnSurfaceVariant + } + } + } + + ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + clip: true + contentWidth: availableWidth + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + ColumnLayout { + width: parent.width + spacing: Style.marginM + + // Bar Position section + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + + RowLayout { + Layout.fillWidth: true + spacing: Style.marginS + + Rectangle { + width: 28 + height: 28 + radius: Style.radiusM + color: Color.mSurface + + NIcon { + icon: "layout-2" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + NText { + text: I18n.tr("settings.bar.appearance.position.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("settings.bar.appearance.position.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } + } + } + + GridLayout { + Layout.fillWidth: true + columns: 2 + rowSpacing: Style.marginS + columnSpacing: Style.marginS + + Repeater { + model: [{ + "key": "top", + "name": I18n.tr("options.bar.position.top"), + "icon": "arrow-up" + }, { + "key": "bottom", + "name": I18n.tr("options.bar.position.bottom"), + "icon": "arrow-down" + }, { + "key": "left", + "name": I18n.tr("options.bar.position.left"), + "icon": "arrow-left" + }, { + "key": "right", + "name": I18n.tr("options.bar.position.right"), + "icon": "arrow-right" + }] + delegate: Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 48 + radius: Style.radiusM + border.width: 1 + + property bool isActive: selectedBarPosition === modelData.key + + color: (hoverHandler.hovered || isActive) ? Color.mPrimary : Color.mSurfaceVariant + border.color: (hoverHandler.hovered || isActive) ? Color.mPrimary : Color.mOutline + opacity: (hoverHandler.hovered || isActive) ? 1.0 : 0.8 + + NText { + text: modelData.name + pointSize: Style.fontSizeM + font.weight: (hoverHandler.hovered || parent.isActive) ? Style.fontWeightBold : Style.fontWeightMedium + color: (hoverHandler.hovered || parent.isActive) ? Color.mOnPrimary : Color.mOnSurface + anchors.centerIn: parent + } + + HoverHandler { + id: hoverHandler + } + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + selectedBarPosition = modelData.key + barPositionChanged(modelData.key) + } + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + Behavior on border.color { + ColorAnimation { + duration: Style.animationFast + } + } + Behavior on opacity { + NumberAnimation { + duration: Style.animationFast + } + } + } + } + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + } + + // Dim Desktop section + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + Rectangle { + width: 32 + height: 32 + radius: Style.radiusM + color: Color.mSurface + NIcon { + icon: "moon" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + NText { + text: I18n.tr("settings.user-interface.dim-desktop.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + NText { + text: I18n.tr("settings.user-interface.dim-desktop.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + + NToggle { + checked: selectedDimDesktop + onToggled: function (checked) { + selectedDimDesktop = checked + dimDesktopChanged(checked) + } + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + } + + // Bar Density section + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + Rectangle { + width: 32 + height: 32 + radius: Style.radiusM + color: Color.mSurface + NIcon { + icon: "minimize" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + NText { + text: I18n.tr("settings.bar.appearance.density.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + NText { + text: I18n.tr("settings.bar.appearance.density.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + + RowLayout { + spacing: Style.marginS + Repeater { + model: [{ + "key": "mini", + "name": I18n.tr("options.bar.density.mini") + }, { + "key": "compact", + "name": I18n.tr("options.bar.density.compact") + }, { + "key": "default", + "name": I18n.tr("options.bar.density.default") + }, { + "key": "comfortable", + "name": I18n.tr("options.bar.density.comfortable") + }] + delegate: Rectangle { + radius: 16 + border.width: 1 + Layout.preferredHeight: 32 + Layout.preferredWidth: Math.max(72, densityText.implicitWidth + Style.marginM) + + property bool isActive: Settings.data.bar.density === modelData.key + + color: (hoverHandler.hovered || isActive) ? Color.mPrimary : Color.mSurfaceVariant + border.color: (hoverHandler.hovered || isActive) ? Color.mPrimary : Color.mOutline + opacity: (hoverHandler.hovered || isActive) ? 1.0 : 0.8 + + NText { + id: densityText + text: modelData.name + pointSize: Style.fontSizeS + font.weight: (hoverHandler.hovered || parent.isActive) ? Style.fontWeightBold : Style.fontWeightMedium + color: (hoverHandler.hovered || parent.isActive) ? Color.mOnPrimary : Color.mOnSurface + anchors.centerIn: parent + } + + HoverHandler { + id: hoverHandler + } + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + Settings.data.bar.density = modelData.key + } + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + Behavior on border.color { + ColorAnimation { + duration: Style.animationFast + } + } + Behavior on opacity { + NumberAnimation { + duration: Style.animationFast + } + } + } + } + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + } + + // UI Scale section + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + + RowLayout { + Layout.fillWidth: true + spacing: Style.marginS + Rectangle { + width: 32 + height: 32 + radius: Style.radiusM + color: Color.mSurface + NIcon { + icon: "maximize" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + NText { + text: I18n.tr("settings.user-interface.scaling.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + NText { + text: I18n.tr("settings.user-interface.scaling.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } + } + } + + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + NText { + text: "80%" + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } + NValueSlider { + Layout.fillWidth: true + from: 0.8 + to: 1.2 + stepSize: 0.05 + value: selectedScaleRatio + onMoved: function (value) { + selectedScaleRatio = value + scaleRatioChanged(value) + } + text: Math.floor(selectedScaleRatio * 100) + "%" + } + NText { + text: "120%" + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + } + + // Bar Floating toggle + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + Rectangle { + width: 32 + height: 32 + radius: Style.radiusM + color: Color.mSurface + NIcon { + icon: "layout-2" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + NText { + text: I18n.tr("settings.bar.appearance.floating.label") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + NText { + text: I18n.tr("settings.bar.appearance.floating.description") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + NToggle { + checked: Settings.data.bar.floating + onToggled: function (checked) { + Settings.data.bar.floating = checked + } + } + } + + // Divider + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Color.mOutline + opacity: 0.2 + Layout.topMargin: Style.marginS + Layout.bottomMargin: Style.marginS + } + + // Bar Background Opacity + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + NLabel { + label: I18n.tr("settings.bar.appearance.background-opacity.label") + description: I18n.tr("settings.bar.appearance.background-opacity.description") + } + NValueSlider { + Layout.fillWidth: true + from: 0 + to: 1 + stepSize: 0.01 + value: Settings.data.bar.backgroundOpacity + onMoved: function (value) { + Settings.data.bar.backgroundOpacity = value + } + text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%" + } + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: Style.marginL + } + } + } +} diff --git a/Modules/SetupWizard/SetupWallpaperStep.qml b/Modules/SetupWizard/SetupWallpaperStep.qml new file mode 100644 index 00000000..fa1225c2 --- /dev/null +++ b/Modules/SetupWizard/SetupWallpaperStep.qml @@ -0,0 +1,507 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Effects +import Quickshell +import Quickshell.Io +import qs.Commons +import qs.Services +import qs.Widgets +import "../../Helpers/FuzzySort.js" as FuzzySort + +ColumnLayout { + id: root + + property string selectedDirectory: "" + property string selectedWallpaper: "" + + signal directoryChanged(string directory) + signal wallpaperChanged(string wallpaper) + + spacing: Style.marginL + + // Beautiful header with icon + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + + RowLayout { + spacing: Style.marginM + + Rectangle { + width: 40 + height: 40 + radius: Style.radiusL + color: Color.mSurfaceVariant + opacity: 0.6 + + NIcon { + icon: "image" + pointSize: Style.fontSizeL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + ColumnLayout { + spacing: Style.marginXS + + NText { + text: I18n.tr("setup.wallpaper.header") + pointSize: Style.fontSizeXL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NText { + text: I18n.tr("setup.wallpaper.subheader") + pointSize: Style.fontSizeM + color: Color.mOnSurfaceVariant + } + } + } + } + + // Large preview with rounded corners and shadow effect + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumHeight: 180 + color: Color.mSurfaceVariant + radius: Style.radiusL + border.color: selectedWallpaper !== "" ? Color.mPrimary : Color.mOutline + border.width: selectedWallpaper !== "" ? 2 : 1 + clip: true + + // Mirror WallpaperPanel approach with rounded shader mask + NImageCached { + id: previewCached + anchors.fill: parent + anchors.margins: 4 + maxCacheDimension: 512 + cacheFolder: Settings.cacheDirImagesWallpapers + imagePath: selectedWallpaper !== "" ? "file://" + selectedWallpaper : "" + visible: false // used as texture source for the shader + } + + ShaderEffect { + anchors.fill: parent + anchors.margins: 4 + property var source: ShaderEffectSource { + sourceItem: previewCached + hideSource: true + live: true + recursive: false + format: ShaderEffectSource.RGBA + } + property real itemWidth: width + property real itemHeight: height + property real cornerRadius: Style.radiusL + property real imageOpacity: 1.0 + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/rounded_image.frag.qsb") + supportsAtlasTextures: false + blending: true + } + + // Loading placeholder + Rectangle { + anchors.fill: parent + color: Color.mSurfaceVariant + radius: Style.radiusL + visible: (previewCached.status === Image.Loading || previewCached.status === Image.Null) && selectedWallpaper !== "" + + NIcon { + icon: "image" + pointSize: Style.fontSizeXXL + color: Color.mOnSurfaceVariant + anchors.centerIn: parent + } + } + + // Error placeholder + Rectangle { + anchors.fill: parent + color: Color.mError + opacity: 0.1 + radius: Style.radiusL + visible: previewCached.status === Image.Error && selectedWallpaper !== "" + + ColumnLayout { + anchors.centerIn: parent + spacing: Style.marginS + + NIcon { + icon: "alert-circle" + pointSize: Style.fontSizeXXL + color: Color.mError + Layout.alignment: Qt.AlignHCenter + } + + NText { + text: I18n.tr("setup.wallpaper.preview-error") + pointSize: Style.fontSizeS + color: Color.mError + Layout.alignment: Qt.AlignHCenter + } + } + } + + NBusyIndicator { + anchors.centerIn: parent + visible: (previewCached.status === Image.Loading || previewCached.status === Image.Null) && selectedWallpaper !== "" + running: visible + size: 28 + } + + ColumnLayout { + anchors.centerIn: parent + spacing: Style.marginL + visible: selectedWallpaper === "" + opacity: 0.6 + + Rectangle { + Layout.alignment: Qt.AlignHCenter + width: 64 + height: 64 + radius: width / 2 + color: Color.mPrimary + opacity: 0.15 + + NIcon { + icon: "sparkles" + pointSize: Style.fontSizeXXL + color: Color.mPrimary + anchors.centerIn: parent + } + } + + NText { + text: I18n.tr("setup.wallpaper.select-prompt") + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignHCenter + font.weight: Style.fontWeightMedium + } + } + + Behavior on border.color { + ColorAnimation { + duration: Style.animationFast + } + } + } + + // Wallpaper gallery strip + Item { + Layout.fillWidth: true + Layout.preferredHeight: 90 + visible: filteredWallpapers.length > 0 + + ScrollView { + anchors.fill: parent + clip: true + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AlwaysOff + + RowLayout { + spacing: Style.marginM + height: parent.height + + Repeater { + model: filteredWallpapers + delegate: Rectangle { + Layout.preferredWidth: 120 + Layout.preferredHeight: 80 + color: Color.mSurface + radius: Style.radiusM + border.color: selectedWallpaper === modelData ? Color.mPrimary : Color.mOutline + border.width: selectedWallpaper === modelData ? 2 : 1 + clip: true + + // Cached thumbnail (used as shader source) + NImageCached { + id: thumbCached + anchors.fill: parent + anchors.margins: 3 + maxCacheDimension: 256 + cacheFolder: Settings.cacheDirImagesWallpapers + imagePath: "file://" + modelData + visible: false + } + + ShaderEffect { + anchors.fill: parent + anchors.margins: 3 + property var source: ShaderEffectSource { + sourceItem: thumbCached + hideSource: true + live: true + recursive: false + format: ShaderEffectSource.RGBA + } + property real itemWidth: width + property real itemHeight: height + property real cornerRadius: Style.radiusM - 3 + property real imageOpacity: 1.0 + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/rounded_image.frag.qsb") + supportsAtlasTextures: false + blending: true + } + + // Loading state + Rectangle { + anchors.fill: parent + color: Color.mSurfaceVariant + radius: Style.radiusM + visible: thumbCached.status === Image.Loading + + NIcon { + icon: "image" + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + anchors.centerIn: parent + } + } + + // Error state + Rectangle { + anchors.fill: parent + color: Color.mSurfaceVariant + radius: Style.radiusM + visible: thumbCached.status === Image.Error + + NIcon { + icon: "image" + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + anchors.centerIn: parent + } + } + + NBusyIndicator { + anchors.centerIn: parent + visible: thumbCached.status === Image.Loading || thumbCached.status === Image.Null + running: visible + size: 18 + } + + Rectangle { + anchors.fill: parent + color: Color.mPrimary + opacity: hoverHandler.hovered ? 0.1 : 0 + radius: Style.radiusM + Behavior on opacity { + NumberAnimation { + duration: Style.animationFast + } + } + } + + Rectangle { + visible: selectedWallpaper === modelData + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 6 + width: 24 + height: 24 + radius: width / 2 + color: Color.mPrimary + + NIcon { + icon: "check" + pointSize: Style.fontSizeS + color: Color.mOnPrimary + anchors.centerIn: parent + } + } + + HoverHandler { + id: hoverHandler + } + + TapHandler { + onTapped: { + selectedWallpaper = modelData + wallpaperChanged(modelData) + } + } + } + } + } + } + } + + // Helpful info card + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 80 + color: Color.mSurfaceVariant + radius: Style.radiusM + opacity: 0.4 + visible: filteredWallpapers.length === 0 + + RowLayout { + anchors.fill: parent + anchors.margins: Style.marginL + spacing: Style.marginM + + NIcon { + icon: "folder-open" + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + } + + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginXS + NText { + text: filteredWallpapers.length === 0 && selectedDirectory !== "" ? I18n.tr("setup.wallpaper.none-in-dir") : I18n.tr("setup.wallpaper.no-dir") + pointSize: Style.fontSizeM + font.weight: Style.fontWeightBold + color: Color.mOnSurfaceVariant + } + NText { + text: selectedDirectory !== "" ? I18n.tr("setup.wallpaper.no-valid", { + "dir": selectedDirectory + }) : I18n.tr("setup.wallpaper.choose-dir") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + opacity: 0.8 + } + } + } + } + + // Directory selection + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginM + + NTextInputButton { + id: wallpaperPathInput + label: I18n.tr("setup.wallpaper.dir.label") + description: I18n.tr("setup.wallpaper.dir.description") + text: selectedDirectory + buttonIcon: "folder-open" + buttonTooltip: I18n.tr("setup.wallpaper.dir.browse") + Layout.fillWidth: true + onInputEditingFinished: { + selectedDirectory = text + directoryChanged(text) + } + onButtonClicked: directoryPicker.open() + } + } + + // Internal properties and functions + property list wallpapersList: [] + property list filteredWallpapers: [] + + function updateFilteredWallpapers() { + filteredWallpapers = wallpapersList + } + + function refreshWallpapers() { + if (!selectedDirectory || selectedDirectory === "") { + wallpapersList = [] + filteredWallpapers = [] + return + } + if (typeof WallpaperService !== "undefined" && WallpaperService.getWallpapersList) { + var wallpapers = WallpaperService.getWallpapersList(Screen.name) + wallpapersList = wallpapers + updateFilteredWallpapers() + if (wallpapersList.length > 0 && selectedWallpaper === "") { + selectedWallpaper = wallpapersList[0] + } + } else { + readDirectoryImages(selectedDirectory) + } + } + + function readDirectoryImages(directoryPath) { + directoryScanner.command = ["find", directoryPath, "-type", "f", "\\(-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.bmp", "-o", "-iname", "*.webp", "-o", "-iname", "*.svg", "\\)"] + directoryScanner.running = true + return [] + } + + onSelectedDirectoryChanged: { + if (typeof Settings !== "undefined" && Settings.data && Settings.data.wallpaper) { + Settings.data.wallpaper.directory = selectedDirectory + } + if (typeof WallpaperService !== "undefined" && WallpaperService.refreshWallpapersList) { + WallpaperService.refreshWallpapersList() + } + Qt.callLater(refreshWallpapers) + } + + Connections { + target: WallpaperService + enabled: typeof WallpaperService !== "undefined" + function onWallpaperListChanged(screenName, count) { + if (screenName === Screen.name) { + Qt.callLater(refreshWallpapers) + } + } + } + + Timer { + id: initialRefreshTimer + interval: 1000 + running: false + repeat: false + onTriggered: refreshWallpapers() + } + + Component.onCompleted: { + if (typeof Settings !== "undefined" && Settings.data && Settings.data.wallpaper && Settings.data.wallpaper.directory) { + selectedDirectory = Settings.data.wallpaper.directory + } else { + selectedDirectory = Quickshell.env("HOME") + "/Pictures/Wallpapers" + } + if (typeof WallpaperService !== "undefined" && WallpaperService.currentWallpaper) { + selectedWallpaper = WallpaperService.currentWallpaper + } + initialRefreshTimer.start() + } + + NFilePicker { + id: directoryPicker + selectionMode: "folders" + title: I18n.tr("setup.wallpaper.dir.select-title") + initialPath: selectedDirectory || Quickshell.env("HOME") + "/Pictures" + onAccepted: paths => { + if (paths.length > 0) { + selectedDirectory = paths[0] + directoryChanged(paths[0]) + } + } + } + + Process { + id: directoryScanner + command: ["find", "", "-type", "f", "\\(-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.bmp", "-o", "-iname", "*.webp", "-o", "-iname", "*.svg", "\\)"] + running: false + stdout: StdioCollector {} + stderr: StdioCollector {} + onExited: function (exitCode) { + if (exitCode === 0) { + var lines = stdout.text.split('\n') + var images = [] + for (var i = 0; i < lines.length; i++) { + var line = lines[i].trim() + if (line !== '') { + images.push(line) + } + } + wallpapersList = images + updateFilteredWallpapers() + if (wallpapersList.length > 0 && selectedWallpaper === "") { + selectedWallpaper = wallpapersList[0] + } + } + } + } +} diff --git a/Modules/SetupWizard/SetupWizard.qml b/Modules/SetupWizard/SetupWizard.qml new file mode 100644 index 00000000..d34d6013 --- /dev/null +++ b/Modules/SetupWizard/SetupWizard.qml @@ -0,0 +1,414 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Quickshell +import Quickshell.Wayland +import qs.Commons +import qs.Services +import qs.Widgets + +NPanel { + id: root + + preferredWidth: 520 + preferredHeight: 600 + preferredWidthRatio: 0.4 + preferredHeightRatio: 0.6 + panelAnchorHorizontalCenter: true + panelAnchorVerticalCenter: true + panelKeyboardFocus: true + + // Prevent closing during setup + backgroundClickEnabled: false + draggable: false + + property int currentStep: 0 + property int totalSteps: 4 + + // Setup wizard data + property string selectedWallpaperDirectory: Settings.defaultWallpapersDirectory + property string selectedWallpaper: "" + property real selectedScaleRatio: 1.0 + property string selectedBarPosition: "top" + property bool selectedDimDesktop: true + + panelContent: Component { + Item { + id: container + anchors.fill: parent + + ColumnLayout { + id: wizardContent + anchors.fill: parent + anchors.margins: Style.marginXL + spacing: Style.marginL + + // Override ESC key to prevent closing during setup + Shortcut { + sequences: ["Escape"] + enabled: root.active + onActivated: { + + // Do nothing - prevent ESC from closing the setup wizard + } + context: Qt.WindowShortcut + } + + // Step content - takes most of the space + Item { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumHeight: 300 + + StackLayout { + id: stepStack + anchors.fill: parent + currentIndex: currentStep + + // Step 0: Welcome - Beautiful centered design + Item { + ColumnLayout { + anchors.centerIn: parent + width: 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: "https://assets.noctalia.dev/noctalia-logo.svg" + fillMode: Image.PreserveAspectFit + smooth: true + + Rectangle { + anchors.fill: parent + color: Color.mSurfaceVariant + radius: width / 2 + border.color: Color.mOutline + border.width: 2 + 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: UI Configuration + SetupCustomizeStep { + id: step2 + selectedScaleRatio: root.selectedScaleRatio + selectedBarPosition: root.selectedBarPosition + selectedDimDesktop: root.selectedDimDesktop + onScaleRatioChanged: function (ratio) { + root.selectedScaleRatio = ratio + root.applyUISettings() + } + onBarPositionChanged: function (position) { + root.selectedBarPosition = position + root.applyUISettings() + } + onDimDesktopChanged: function (dim) { + root.selectedDimDesktop = dim + root.applyUISettings() + } + } + + // Step 3: Appearance - Dark mode and color source + SetupAppearanceStep { + id: step3 + } + } + } + + // 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": "settings", + "label": "Customize" + }, { + "icon": "palette", + "label": "Appearance" + }] + 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() { + Logger.log("SetupWizard", "Completing setup with selected options") + + 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.general.dimDesktop = selectedDimDesktop + Settings.data.general.setupCompleted = true + + Settings.saveImmediate() + Logger.log("SetupWizard", "Setup completed successfully") + 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 + Settings.data.general.dimDesktop = selectedDimDesktop + } + + Component.onCompleted: { + Logger.log("SetupWizard", "Setup wizard opened") + // Initialize selections from existing settings to avoid overwriting user config + if (Settings && Settings.data) { + selectedScaleRatio = Settings.data.general.scaleRatio + selectedBarPosition = Settings.data.bar.position + selectedDimDesktop = Settings.data.general.dimDesktop + selectedWallpaperDirectory = Settings.data.wallpaper.directory || Settings.defaultWallpapersDirectory + } + } +} diff --git a/Services/AppThemeService.qml b/Services/AppThemeService.qml index 53f7fe75..d8fa9589 100644 --- a/Services/AppThemeService.qml +++ b/Services/AppThemeService.qml @@ -105,8 +105,8 @@ Singleton { // Wallpaper Colors Generation // -------------------------------------------------------------------------------- function generateFromWallpaper() { - Logger.log("AppThemeService", "Generating from wallpaper on screen:", Screen.name) + // Logger.log("AppThemeService", "Generating from wallpaper on screen:", Screen.name) const wp = WallpaperService.getWallpaper(Screen.name).replace(/'/g, "'\\''") if (!wp) { Logger.error("AppThemeService", "No wallpaper found") diff --git a/Widgets/NImageCached.qml b/Widgets/NImageCached.qml index 1343828b..edeb4baf 100644 --- a/Widgets/NImageCached.qml +++ b/Widgets/NImageCached.qml @@ -31,8 +31,9 @@ Image { } onCachePathChanged: { if (imageHash && cachePath) { - // Try to load the cached version, failure will be detected below in onStatusChanged - source = cachePath + // Check if cache file exists before trying to load it + cacheChecker.command = ["test", "-f", cachePath] + cacheChecker.running = true } } onStatusChanged: { @@ -48,4 +49,19 @@ Image { }) } } + + // Check if cache file exists to avoid warnings + Process { + id: cacheChecker + running: false + onExited: function (exitCode) { + if (exitCode === 0 && root.cachePath) { + // Cache file exists, load it + root.source = root.cachePath + } else if (root.imagePath) { + // Cache doesn't exist, load original directly + root.source = root.imagePath + } + } + } } diff --git a/shell.qml b/shell.qml index 39b76224..46edcf47 100644 --- a/shell.qml +++ b/shell.qml @@ -40,6 +40,7 @@ import qs.Modules.OSD import qs.Modules.Settings import qs.Modules.Toast import qs.Modules.Wallpaper +import qs.Modules.SetupWizard ShellRoot { id: shellRoot @@ -89,6 +90,10 @@ ShellRoot { HooksService.init() BluetoothService.init() BatteryService.init() + + if (Settings && Settings.data && Settings.data.general && !Settings.data.general.setupCompleted) { + setupWizardLoader.active = true + } } Background {} @@ -166,6 +171,27 @@ ShellRoot { id: batteryPanel objectName: "batteryPanel" } + + // Lazy-load Setup Wizard to save memory + Component { + id: setupWizardComponent + SetupWizard { + id: setupWizardPanel + objectName: "setupWizardPanel" + } + } + + Loader { + id: setupWizardLoader + active: false + asynchronous: true + sourceComponent: setupWizardComponent + onLoaded: { + if (setupWizardLoader.item && setupWizardLoader.item.open) { + setupWizardLoader.item.open() + } + } + } } } } From ff057355dafbebea23562ab8ddf831b2a373d127 Mon Sep 17 00:00:00 2001 From: lysec Date: Wed, 15 Oct 2025 18:10:39 +0200 Subject: [PATCH 05/15] SetupWizard: small fixes --- Modules/SetupWizard/SetupAppearanceStep.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/SetupWizard/SetupAppearanceStep.qml b/Modules/SetupWizard/SetupAppearanceStep.qml index 15c8c1ee..a85f2d59 100644 --- a/Modules/SetupWizard/SetupAppearanceStep.qml +++ b/Modules/SetupWizard/SetupAppearanceStep.qml @@ -443,7 +443,7 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter height: 50 radius: Style.radiusS - color: (root.cacheVersionroot.getSchemeColor(schemeName, "mSurface")) + color: (root.cacheVersion, root.getSchemeColor(schemeName, "mSurface")) border.width: Math.max(1, Style.borderL) border.color: itemMouseArea.containsMouse ? Color.mTertiary : (Settings.data.colorSchemes.predefinedScheme === schemeName ? Color.mSecondary : Color.mOutline) @@ -468,7 +468,7 @@ ColumnLayout { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersionfunction () { + color: (root.cacheVersion, function () { var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" var cached = root.schemeColorsCache[schemeItem.schemeName] return (cached && cached[mode] && cached[mode].mPrimary) || root.getSchemeColor(schemeItem.schemeName, "mPrimary") @@ -478,7 +478,7 @@ ColumnLayout { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersionfunction () { + color: (root.cacheVersion, function () { var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" var cached = root.schemeColorsCache[schemeItem.schemeName] return (cached && cached[mode] && cached[mode].mSecondary) || root.getSchemeColor(schemeItem.schemeName, "mSecondary") @@ -488,7 +488,7 @@ ColumnLayout { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersionfunction () { + color: (root.cacheVersion, function () { var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" var cached = root.schemeColorsCache[schemeItem.schemeName] return (cached && cached[mode] && cached[mode].mTertiary) || root.getSchemeColor(schemeItem.schemeName, "mTertiary") @@ -498,7 +498,7 @@ ColumnLayout { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersionfunction () { + color: (root.cacheVersion, function () { var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" var cached = root.schemeColorsCache[schemeItem.schemeName] return (cached && cached[mode] && cached[mode].mError) || root.getSchemeColor(schemeItem.schemeName, "mError") From f67551688d264187ba9b29d15a8216886d983ad4 Mon Sep 17 00:00:00 2001 From: Damian D'Souza Date: Wed, 15 Oct 2025 18:12:42 +0200 Subject: [PATCH 06/15] MediaService: add a check if blacklisted before adding to specific or generic players --- Services/MediaService.qml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Services/MediaService.qml b/Services/MediaService.qml index 006285c9..b0a4eb16 100644 --- a/Services/MediaService.qml +++ b/Services/MediaService.qml @@ -38,12 +38,19 @@ Singleton { let allPlayers = Mpris.players.values let finalPlayers = [] const genericBrowsers = ["firefox", "chromium", "chrome"] + const blacklist = (Settings.data.audio && Settings.data.audio.mprisBlacklist) ? Settings.data.audio.mprisBlacklist : [] // Separate players into specific and generic lists let specificPlayers = [] let genericPlayers = [] for (var i = 0; i < allPlayers.length; i++) { const identity = String(allPlayers[i].identity || "").toLowerCase() + const match = blacklist.find(b => { + const s = String(b || "").toLowerCase() + return s && (identity.includes(s)) + }) + if (match) + continue if (genericBrowsers.some(b => identity.includes(b))) { genericPlayers.push(allPlayers[i]) } else { From f20cd85e7977711a9bd052d982293b5937b44194 Mon Sep 17 00:00:00 2001 From: lysec Date: Wed, 15 Oct 2025 18:24:10 +0200 Subject: [PATCH 07/15] SetupWizard: layout changes Autoformat --- Modules/SetupWizard/SetupAppearanceStep.qml | 54 +++++++++++---------- Modules/SetupWizard/SetupCustomizeStep.qml | 54 ++++++++------------- Modules/SetupWizard/SetupWallpaperStep.qml | 3 +- Modules/SetupWizard/SetupWizard.qml | 2 +- 4 files changed, 51 insertions(+), 62 deletions(-) diff --git a/Modules/SetupWizard/SetupAppearanceStep.qml b/Modules/SetupWizard/SetupAppearanceStep.qml index a85f2d59..32903902 100644 --- a/Modules/SetupWizard/SetupAppearanceStep.qml +++ b/Modules/SetupWizard/SetupAppearanceStep.qml @@ -51,13 +51,15 @@ ColumnLayout { // Beautiful header with icon RowLayout { Layout.fillWidth: true + Layout.bottomMargin: Style.marginL spacing: Style.marginM Rectangle { - width: 28 - height: 28 - radius: Style.radiusM - color: Color.mSurface + width: 40 + height: 40 + radius: Style.radiusL + color: Color.mSurfaceVariant + opacity: 0.6 NIcon { icon: "palette" @@ -75,7 +77,7 @@ ColumnLayout { text: I18n.tr("setup.appearance.header") pointSize: Style.fontSizeXL font.weight: Style.fontWeightBold - color: Color.mOnSurface + color: Color.mPrimary } NText { @@ -443,7 +445,7 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter height: 50 radius: Style.radiusS - color: (root.cacheVersion, root.getSchemeColor(schemeName, "mSurface")) + color: root.cacheVersion >= 0 ? root.getSchemeColor(schemeName, "mSurface") : root.getSchemeColor(schemeName, "mSurface") border.width: Math.max(1, Style.borderL) border.color: itemMouseArea.containsMouse ? Color.mTertiary : (Settings.data.colorSchemes.predefinedScheme === schemeName ? Color.mSecondary : Color.mOutline) @@ -468,41 +470,41 @@ ColumnLayout { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersion, function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mPrimary) || root.getSchemeColor(schemeItem.schemeName, "mPrimary") - })() + color: root.cacheVersion >= 0 ? (function () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mPrimary) || root.getSchemeColor(schemeItem.schemeName, "mPrimary") + })() : Color.mPrimary } Rectangle { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersion, function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mSecondary) || root.getSchemeColor(schemeItem.schemeName, "mSecondary") - })() + color: root.cacheVersion >= 0 ? (function () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mSecondary) || root.getSchemeColor(schemeItem.schemeName, "mSecondary") + })() : Color.mSecondary } Rectangle { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersion, function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mTertiary) || root.getSchemeColor(schemeItem.schemeName, "mTertiary") - })() + color: root.cacheVersion >= 0 ? (function () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mTertiary) || root.getSchemeColor(schemeItem.schemeName, "mTertiary") + })() : Color.mTertiary } Rectangle { width: 14 height: 14 radius: width * 0.5 - color: (root.cacheVersion, function () { - var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" - var cached = root.schemeColorsCache[schemeItem.schemeName] - return (cached && cached[mode] && cached[mode].mError) || root.getSchemeColor(schemeItem.schemeName, "mError") - })() + color: root.cacheVersion >= 0 ? (function () { + var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light" + var cached = root.schemeColorsCache[schemeItem.schemeName] + return (cached && cached[mode] && cached[mode].mError) || root.getSchemeColor(schemeItem.schemeName, "mError") + })() : Color.mError } } diff --git a/Modules/SetupWizard/SetupCustomizeStep.qml b/Modules/SetupWizard/SetupCustomizeStep.qml index a1854f5f..e5e0dcc1 100644 --- a/Modules/SetupWizard/SetupCustomizeStep.qml +++ b/Modules/SetupWizard/SetupCustomizeStep.qml @@ -22,13 +22,15 @@ ColumnLayout { // Beautiful header with icon RowLayout { Layout.fillWidth: true + Layout.bottomMargin: Style.marginL spacing: Style.marginM Rectangle { - width: 28 - height: 28 - radius: Style.radiusM - color: Color.mSurface + width: 40 + height: 40 + radius: Style.radiusL + color: Color.mSurfaceVariant + opacity: 0.6 NIcon { icon: "palette" @@ -46,7 +48,7 @@ ColumnLayout { text: I18n.tr("setup.customize.header") pointSize: Style.fontSizeXL font.weight: Style.fontWeightBold - color: Color.mOnSurface + color: Color.mPrimary } NText { @@ -111,11 +113,9 @@ ColumnLayout { } } - GridLayout { + RowLayout { Layout.fillWidth: true - columns: 2 - rowSpacing: Style.marginS - columnSpacing: Style.marginS + spacing: Style.marginS Repeater { model: [{ @@ -137,7 +137,7 @@ ColumnLayout { }] delegate: Rectangle { Layout.fillWidth: true - Layout.preferredHeight: 48 + Layout.preferredHeight: 40 radius: Style.radiusM border.width: 1 @@ -308,7 +308,7 @@ ColumnLayout { radius: 16 border.width: 1 Layout.preferredHeight: 32 - Layout.preferredWidth: Math.max(72, densityText.implicitWidth + Style.marginM) + Layout.preferredWidth: Math.max(90, densityText.implicitWidth + Style.marginXL * 2) property bool isActive: Settings.data.bar.density === modelData.key @@ -403,31 +403,17 @@ ColumnLayout { } } - RowLayout { + NValueSlider { Layout.fillWidth: true - spacing: Style.marginM - NText { - text: "80%" - pointSize: Style.fontSizeS - color: Color.mOnSurfaceVariant - } - NValueSlider { - Layout.fillWidth: true - from: 0.8 - to: 1.2 - stepSize: 0.05 - value: selectedScaleRatio - onMoved: function (value) { - selectedScaleRatio = value - scaleRatioChanged(value) - } - text: Math.floor(selectedScaleRatio * 100) + "%" - } - NText { - text: "120%" - pointSize: Style.fontSizeS - color: Color.mOnSurfaceVariant + from: 0.8 + to: 1.2 + stepSize: 0.05 + value: selectedScaleRatio + onMoved: function (value) { + selectedScaleRatio = value + scaleRatioChanged(value) } + text: Math.floor(selectedScaleRatio * 100) + "%" } } diff --git a/Modules/SetupWizard/SetupWallpaperStep.qml b/Modules/SetupWizard/SetupWallpaperStep.qml index fa1225c2..aa915f72 100644 --- a/Modules/SetupWizard/SetupWallpaperStep.qml +++ b/Modules/SetupWizard/SetupWallpaperStep.qml @@ -23,6 +23,7 @@ ColumnLayout { // Beautiful header with icon ColumnLayout { Layout.fillWidth: true + Layout.bottomMargin: Style.marginL spacing: Style.marginM RowLayout { @@ -50,7 +51,7 @@ ColumnLayout { text: I18n.tr("setup.wallpaper.header") pointSize: Style.fontSizeXL font.weight: Style.fontWeightBold - color: Color.mOnSurface + color: Color.mPrimary } NText { diff --git a/Modules/SetupWizard/SetupWizard.qml b/Modules/SetupWizard/SetupWizard.qml index d34d6013..63cc052f 100644 --- a/Modules/SetupWizard/SetupWizard.qml +++ b/Modules/SetupWizard/SetupWizard.qml @@ -346,7 +346,7 @@ NPanel { } NButton { - text: currentStep === totalSteps - 1 ? "🎉 All Done!" : "Continue →" + text: currentStep === totalSteps - 1 ? "All Done!" : "Continue →" Layout.preferredHeight: 44 onClicked: { if (currentStep < totalSteps - 1) { From 7d0f14a3b446e99ccb80fb01fbf6cb517e79e19b Mon Sep 17 00:00:00 2001 From: Damian D'Souza Date: Wed, 15 Oct 2025 18:29:23 +0200 Subject: [PATCH 08/15] BatteryService: set chargingMode to disabled after success --- Services/BatteryService.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/BatteryService.qml b/Services/BatteryService.qml index cf64b853..0e2bea2a 100644 --- a/Services/BatteryService.qml +++ b/Services/BatteryService.qml @@ -60,7 +60,6 @@ Singleton { if (enabled) { setChargingMode(BatteryService.ChargingMode.Full) } else { - BatteryService.chargingMode = BatteryService.ChargingMode.Disabled BatteryService.initialSetter = true ToastService.showNotice(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.uninstall-setup")) PanelService.getPanel("batteryPanel")?.toggle(this) @@ -194,6 +193,7 @@ Singleton { Logger.log("BatteryService", "Battery Manager uninstalled successfully") ToastService.showNotice(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.uninstall-success")) Settings.data.battery.chargingMode = BatteryService.chargingMode + BatteryService.chargingMode = BatteryService.ChargingMode.Disabled cleanupProcess.running = true } else { ToastService.showError(I18n.tr("toast.battery-manager.title"), I18n.tr("toast.battery-manager.uninstall-failed")) From 15eee455cf872d9d0acb666e7476de32080ef443 Mon Sep 17 00:00:00 2001 From: lysec Date: Wed, 15 Oct 2025 19:11:18 +0200 Subject: [PATCH 09/15] SetupWizard: replace remote logo with local --- Assets/noctalia.svg | 65 +++++++++++++++++++++++++++++ Modules/SetupWizard/SetupWizard.qml | 2 +- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 Assets/noctalia.svg diff --git a/Assets/noctalia.svg b/Assets/noctalia.svg new file mode 100644 index 00000000..10646225 --- /dev/null +++ b/Assets/noctalia.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Modules/SetupWizard/SetupWizard.qml b/Modules/SetupWizard/SetupWizard.qml index 63cc052f..494f462f 100644 --- a/Modules/SetupWizard/SetupWizard.qml +++ b/Modules/SetupWizard/SetupWizard.qml @@ -92,7 +92,7 @@ NPanel { anchors.centerIn: parent width: 110 height: 110 - source: "https://assets.noctalia.dev/noctalia-logo.svg" + source: Qt.resolvedUrl(Quickshell.shellDir + "/Assets/noctalia.svg") fillMode: Image.PreserveAspectFit smooth: true From 8045771133e53c3e63e2debcaa7b82acf3db2a4e Mon Sep 17 00:00:00 2001 From: jacobrreed Date: Wed, 15 Oct 2025 13:58:19 -0400 Subject: [PATCH 10/15] style(colorscheme): Added Eldritch color scheme https://github.com/eldritch-theme/eldritch --- Assets/ColorScheme/Eldritch/Eldritch.json | 34 ++++++++++ .../Eldritch/terminal/foot/Eldritch-dark | 23 +++++++ .../Eldritch/terminal/foot/Eldritch-light | 22 +++++++ .../Eldritch/terminal/ghostty/Eldritch-dark | 21 +++++++ .../Eldritch/terminal/ghostty/Eldritch-light | 22 +++++++ .../terminal/kitty/Eldritch-dark.conf | 63 +++++++++++++++++++ .../terminal/kitty/Eldritch-light.conf | 63 +++++++++++++++++++ 7 files changed, 248 insertions(+) create mode 100644 Assets/ColorScheme/Eldritch/Eldritch.json create mode 100644 Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-dark create mode 100644 Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-light create mode 100644 Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-dark create mode 100644 Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-light create mode 100644 Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf create mode 100644 Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf diff --git a/Assets/ColorScheme/Eldritch/Eldritch.json b/Assets/ColorScheme/Eldritch/Eldritch.json new file mode 100644 index 00000000..3fedfeef --- /dev/null +++ b/Assets/ColorScheme/Eldritch/Eldritch.json @@ -0,0 +1,34 @@ +{ + "dark": { + "mPrimary": "#37f499", + "mOnPrimary": "#171928", + "mSecondary": "#04d1f9", + "mOnSecondary": "#171928", + "mTertiary": "#a48cf2", + "mOnTertiary": "#171928", + "mError": "#f16c75", + "mOnError": "#171928", + "mSurface": "#212337", + "mOnSurface": "#ebfafa", + "mSurfaceVariant": "#292e42", + "mOnSurfaceVariant": "#ABB4DA", + "mOutline": "#3b4261", + "mShadow": "#414868" + }, + "light": { + "mPrimary": "#37f499", + "mOnPrimary": "#171928", + "mSecondary": "#04d1f9", + "mOnSecondary": "#171928", + "mTertiary": "#a48cf2", + "mOnTertiary": "#171928", + "mError": "#f16c75", + "mOnError": "#171928", + "mSurface": "#ffffff", + "mOnSurface": "#171928", + "mSurfaceVariant": "#f2f4f8", + "mOnSurfaceVariant": "#3b4261", + "mOutline": "#b0b6c3", + "mShadow": "#e0e3e8" + } +} diff --git a/Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-dark b/Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-dark new file mode 100644 index 00000000..dc0c5b58 --- /dev/null +++ b/Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-dark @@ -0,0 +1,23 @@ +[colors] +foreground=ebfafa +background=212337 +regular0=21222c +regular1=f9515d +regular2=37f499 +regular3=e9f941 +regular4=9071f4 +regular5=f265b5 +regular6=04d1f9 +regular7=ebfafa +bright0=7081d0 +bright1=f16c75 +bright2=69F8B3 +bright3=f1fc79 +bright4=a48cf2 +bright5=FD92CE +bright6=66e4fd +bright7=ffffff +selection-foreground=ebfafa +selection-background=bf4f8e +cursor=37f499 f8f8f2 + diff --git a/Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-light b/Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-light new file mode 100644 index 00000000..90602968 --- /dev/null +++ b/Assets/ColorScheme/Eldritch/terminal/foot/Eldritch-light @@ -0,0 +1,22 @@ +[colors] +foreground=212337 +background=ebfafa +regular0=ebfafa # black → white +regular1=ba1a1a # red (darker) +regular2=1a7f4c # green (darker) +regular3=9e8c13 # yellow (darker) +regular4=3a3e8c # blue (darker) +regular5=8c2a6c # magenta (darker) +regular6=1a6c8c # cyan (darker) +regular7=212337 # white → black +bright0=7081d0 # keep as accent +bright1=d23b3b # lighter red +bright2=37f499 # original green +bright3=e9f941 # original yellow +bright4=9071f4 # original blue +bright5=f265b5 # original magenta +bright6=04d1f9 # original cyan +bright7=212337 # black +selection-foreground=212337 +selection-background=bf4f8e +cursor=1a7f4c 212337 diff --git a/Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-dark b/Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-dark new file mode 100644 index 00000000..e6b33937 --- /dev/null +++ b/Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-dark @@ -0,0 +1,21 @@ +palette = 0=#21222c +palette = 1=#f9515d +palette = 2=#37f499 +palette = 3=#e9f941 +palette = 4=#9071f4 +palette = 5=#f265b5 +palette = 6=#04d1f9 +palette = 7=#ebfafa +palette = 8=#7081d0 +palette = 9=#f16c75 +palette = 10=#69F8B3 +palette = 11=#f1fc79 +palette = 12=#a48cf2 +palette = 13=#FD92CE +palette = 14=#66e4fd +palette = 15=#ffffff +background = 212337 +foreground = ebfafa +cursor-color = 37f499 +selection-background = bf4f8e +selection-foreground = ebfafa diff --git a/Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-light b/Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-light new file mode 100644 index 00000000..24b6cba5 --- /dev/null +++ b/Assets/ColorScheme/Eldritch/terminal/ghostty/Eldritch-light @@ -0,0 +1,22 @@ +palette = 0=#f8f8fa # base background (was dark, now light) +palette = 1=#d7263d # red (less saturated) +palette = 2=#1eb980 # green (cooler, lighter) +palette = 3=#f7c948 # yellow (warmer) +palette = 4=#5e60ce # blue (lighter) +palette = 5=#c77dff # magenta (lighter) +palette = 6=#38a1db # cyan (lighter) +palette = 7=#21222c # base foreground (was background, now dark) +palette = 8=#bfc9e3 # bright black (light gray) +palette = 9=#f9515d # bright red +palette = 10=#37f499 # bright green +palette = 11=#e9f941 # bright yellow +palette = 12=#9071f4 # bright blue +palette = 13=#f265b5 # bright magenta +palette = 14=#04d1f9 # bright cyan +palette = 15=#21222c # bright white (dark for contrast) +background = f8f8fa +foreground = 21222c +cursor-color = 5e60ce +selection-background = d7e3fa +selection-foreground = 21222c + diff --git a/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf new file mode 100644 index 00000000..85a274b6 --- /dev/null +++ b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf @@ -0,0 +1,63 @@ +# vim:ft=kitty +## name: Eldritch +## author: jacobrreed +## license: MIT +## upstream: https://github.com/eldritch-theme/kitty +## blurb: A theme for the Ancient Ones! +foreground #ebfafa +background #212337 +selection_foreground #ebfafa +selection_background #bf4f8e + +url_color #04d1f9 + +# black +color0 #21222c +color8 #7081d0 + +# red +color1 #f9515d +color9 #f16c75 + +# green +color2 #37f499 +color10 #69F8B3 + +# yellow +color3 #e9f941 +color11 #f1fc79 + +# blue +color4 #9071f4 +color12 #a48cf2 + +# magenta +color5 #f265b5 +color13 #FD92CE + +# cyan +color6 #04d1f9 +color14 #66e4fd + +# white +color7 #ebfafa +color15 #ffffff + +# Cursor colors +cursor #37f499 +cursor_text_color #f8f8f2 + +# Tab bar colors +active_tab_foreground #212337 +active_tab_background #04d1f9 +inactive_tab_foreground #37f499 +inactive_tab_background #323449 + +# Marks +mark1_foreground #212337 +mark1_background #f9515d + +# Splits/Windows +active_border_color #a48cf2 +inactive_border_color #212337 + diff --git a/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf new file mode 100644 index 00000000..c98a3c1a --- /dev/null +++ b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf @@ -0,0 +1,63 @@ +# vim:ft=kitty +## name: Eldritch Light +## author: jacobrreed (light variant by CodeCompanion) +## license: MIT +## upstream: https://github.com/eldritch-theme/kitty +## blurb: A light variant of the Eldritch theme! + +foreground #212337 # dark text +background #ebfafa # light background +selection_foreground #ebfafa # light text on selection +selection_background #bf4f8e # magenta selection + +url_color #04d1f9 + +# black +color0 #ebfafa # background-like +color8 #7081d0 + +# red +color1 #f9515d +color9 #f16c75 + +# green +color2 #37f499 +color10 #69F8B3 + +# yellow +color3 #e9f941 +color11 #f1fc79 + +# blue +color4 #9071f4 +color12 #a48cf2 + +# magenta +color5 #f265b5 +color13 #FD92CE + +# cyan +color6 #04d1f9 +color14 #66e4fd + +# white +color7 #212337 # foreground-like +color15 #323449 + +# Cursor colors +cursor #212337 # dark cursor +cursor_text_color #ebfafa + +# Tab bar colors +active_tab_foreground #ebfafa +active_tab_background #04d1f9 +inactive_tab_foreground #37f499 +inactive_tab_background #dbe6e6 + +# Marks +mark1_foreground #ebfafa +mark1_background #f9515d + +# Splits/Windows +active_border_color #a48cf2 +inactive_border_color #ebfafa From 09b02b1a693a7afe9ee6c7382a67d3bbd218ef8f Mon Sep 17 00:00:00 2001 From: lysec Date: Wed, 15 Oct 2025 20:10:32 +0200 Subject: [PATCH 11/15] eldritch: fix kitty template --- .../terminal/kitty/Eldritch-dark.conf | 71 ++++-------------- .../terminal/kitty/Eldritch-light.conf | 73 ++++--------------- 2 files changed, 31 insertions(+), 113 deletions(-) diff --git a/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf index 85a274b6..8decd1c9 100644 --- a/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf +++ b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-dark.conf @@ -1,63 +1,22 @@ -# vim:ft=kitty -## name: Eldritch -## author: jacobrreed -## license: MIT -## upstream: https://github.com/eldritch-theme/kitty -## blurb: A theme for the Ancient Ones! -foreground #ebfafa -background #212337 -selection_foreground #ebfafa -selection_background #bf4f8e - -url_color #04d1f9 - -# black -color0 #21222c -color8 #7081d0 - -# red -color1 #f9515d -color9 #f16c75 - -# green -color2 #37f499 +color0 #21222c +color1 #f9515d +color2 #37f499 +color3 #e9f941 +color4 #9071f4 +color5 #f265b5 +color6 #04d1f9 +color7 #ebfafa +color8 #7081d0 +color9 #f16c75 color10 #69F8B3 - -# yellow -color3 #e9f941 color11 #f1fc79 - -# blue -color4 #9071f4 -color12 #a48cf2 - -# magenta -color5 #f265b5 +color12 #a48cf2 color13 #FD92CE - -# cyan -color6 #04d1f9 color14 #66e4fd - -# white -color7 #ebfafa color15 #ffffff - -# Cursor colors +background #212337 +selection_foreground #ebfafa cursor #37f499 cursor_text_color #f8f8f2 - -# Tab bar colors -active_tab_foreground #212337 -active_tab_background #04d1f9 -inactive_tab_foreground #37f499 -inactive_tab_background #323449 - -# Marks -mark1_foreground #212337 -mark1_background #f9515d - -# Splits/Windows -active_border_color #a48cf2 -inactive_border_color #212337 - +foreground #ebfafa +selection_background #bf4f8e diff --git a/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf index c98a3c1a..eb75e925 100644 --- a/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf +++ b/Assets/ColorScheme/Eldritch/terminal/kitty/Eldritch-light.conf @@ -1,63 +1,22 @@ -# vim:ft=kitty -## name: Eldritch Light -## author: jacobrreed (light variant by CodeCompanion) -## license: MIT -## upstream: https://github.com/eldritch-theme/kitty -## blurb: A light variant of the Eldritch theme! - -foreground #212337 # dark text -background #ebfafa # light background -selection_foreground #ebfafa # light text on selection -selection_background #bf4f8e # magenta selection - -url_color #04d1f9 - -# black -color0 #ebfafa # background-like -color8 #7081d0 - -# red -color1 #f9515d -color9 #f16c75 - -# green -color2 #37f499 +color0 #ebfafa +color1 #f9515d +color2 #37f499 +color3 #e9f941 +color4 #9071f4 +color5 #f265b5 +color6 #04d1f9 +color7 #212337 +color8 #7081d0 +color9 #f16c75 color10 #69F8B3 - -# yellow -color3 #e9f941 color11 #f1fc79 - -# blue -color4 #9071f4 -color12 #a48cf2 - -# magenta -color5 #f265b5 +color12 #a48cf2 color13 #FD92CE - -# cyan -color6 #04d1f9 color14 #66e4fd - -# white -color7 #212337 # foreground-like color15 #323449 - -# Cursor colors -cursor #212337 # dark cursor +background #ebfafa +selection_foreground #ebfafa +cursor #212337 cursor_text_color #ebfafa - -# Tab bar colors -active_tab_foreground #ebfafa -active_tab_background #04d1f9 -inactive_tab_foreground #37f499 -inactive_tab_background #dbe6e6 - -# Marks -mark1_foreground #ebfafa -mark1_background #f9515d - -# Splits/Windows -active_border_color #a48cf2 -inactive_border_color #ebfafa +foreground #212337 +selection_background #bf4f8e From fd33761901ca683f236b44c78f85c48059b1982b Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 15 Oct 2025 16:02:46 -0400 Subject: [PATCH 12/15] BT: fixed signal icons --- Commons/TablerIcons.qml | 6 ++++++ Modules/Bar/Bluetooth/BluetoothDevicesList.qml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Commons/TablerIcons.qml b/Commons/TablerIcons.qml index 3522e30d..a840d72f 100644 --- a/Commons/TablerIcons.qml +++ b/Commons/TablerIcons.qml @@ -128,6 +128,12 @@ Singleton { "bt-device-watch": "device-watch", "bt-device-speaker": "device-speaker", "bt-device-tv": "device-tv", + "antenna-bars-1": "antenna-bars-1", + "antenna-bars-2": "antenna-bars-2", + "antenna-bars-3": "antenna-bars-3", + "antenna-bars-4": "antenna-bars-4", + "antenna-bars-5": "antenna-bars-5", + "antenna-bars-off": "antenna-bars-off", "noctalia": "noctalia", "hyprland": "hyprland", "filepicker-folder": "folder", diff --git a/Modules/Bar/Bluetooth/BluetoothDevicesList.qml b/Modules/Bar/Bluetooth/BluetoothDevicesList.qml index 8e144c31..311bfeb4 100644 --- a/Modules/Bar/Bluetooth/BluetoothDevicesList.qml +++ b/Modules/Bar/Bluetooth/BluetoothDevicesList.qml @@ -109,7 +109,7 @@ ColumnLayout { NIcon { visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked - text: BluetoothService.getSignalIcon(modelData) + icon: BluetoothService.getSignalIcon(modelData) pointSize: Style.fontSizeXS color: getContentColor(Color.mOnSurface) } From 6fd41cd5915ee98a7c20fe04e7227ecf66efc3b1 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 15 Oct 2025 16:03:29 -0400 Subject: [PATCH 13/15] Removed invalid properties from NIcon callers --- Modules/Settings/Tabs/ColorSchemeTab.qml | 1 - Modules/Wallpaper/WallpaperPanel.qml | 1 - Services/BluetoothService.qml | 12 ++++++------ Widgets/NCheckbox.qml | 1 - Widgets/NFilePicker.qml | 1 - Widgets/NReorderCheckboxes.qml | 1 - 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index b38d521e..969c8769 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -336,7 +336,6 @@ ColumnLayout { NIcon { icon: "check" pointSize: Style.fontSizeXS - font.weight: Style.fontWeightBold color: Color.mOnSecondary anchors.centerIn: parent } diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index be3a526b..2dcfe18e 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -423,7 +423,6 @@ NPanel { NIcon { icon: "check" pointSize: Style.fontSizeM - font.weight: Style.fontWeightBold color: Color.mOnSecondary anchors.centerIn: parent } diff --git a/Services/BluetoothService.qml b/Services/BluetoothService.qml index c5e17d62..2911ee34 100644 --- a/Services/BluetoothService.qml +++ b/Services/BluetoothService.qml @@ -171,22 +171,22 @@ Singleton { function getSignalIcon(device) { if (!device || device.signalStrength === undefined || device.signalStrength <= 0) { - return "signal_cellular_null" + return "antenna-bars-off" } var signal = device.signalStrength if (signal >= 80) { - return "signal_cellular_4_bar" + return "antenna-bars-5" } if (signal >= 60) { - return "signal_cellular_3_bar" + return "antenna-bars-4" } if (signal >= 40) { - return "signal_cellular_2_bar" + return "antenna-bars-3" } if (signal >= 20) { - return "signal_cellular_1_bar" + return "antenna-bars-2" } - return "signal_cellular_0_bar" + return "antenna-bars-1" } function isDeviceBusy(device) { diff --git a/Widgets/NCheckbox.qml b/Widgets/NCheckbox.qml index f27694e6..9fe63be9 100644 --- a/Widgets/NCheckbox.qml +++ b/Widgets/NCheckbox.qml @@ -61,7 +61,6 @@ RowLayout { icon: "check" color: root.activeOnColor pointSize: Math.max(Style.fontSizeXS, root.baseSize * 0.5) - font.weight: Style.fontWeightBold } MouseArea { diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index 4fd7875e..cc318f02 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -624,7 +624,6 @@ Popup { NIcon { icon: "filepicker-check" pointSize: Style.fontSizeS - font.weight: Style.fontWeightBold color: Color.mOnSecondary anchors.centerIn: parent } diff --git a/Widgets/NReorderCheckboxes.qml b/Widgets/NReorderCheckboxes.qml index 9a8c1abc..a7d95927 100644 --- a/Widgets/NReorderCheckboxes.qml +++ b/Widgets/NReorderCheckboxes.qml @@ -217,7 +217,6 @@ Item { icon: "check" color: root.activeOnColor pointSize: Math.max(Style.fontSizeXS, root.baseSize * 0.5) - font.weight: Style.fontWeightBold } MouseArea { From 4910497487a0ae58239851a0d9bab1c727d97dd3 Mon Sep 17 00:00:00 2001 From: Matan Bendix Shenhav Date: Wed, 15 Oct 2025 23:57:23 +0200 Subject: [PATCH 14/15] fix(flake): allow overriding NixOS systemd package --- flake.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 54381f04..d2046bb1 100644 --- a/flake.nix +++ b/flake.nix @@ -49,9 +49,13 @@ nixpkgs.legacyPackages.${pkgs.system}.app2unit; }; - nixosModules.default = {pkgs, ...}: { + nixosModules.default = { + pkgs, + lib, + ... + }: { imports = [./nix/nixos-module.nix]; - services.noctalia-shell.package = self.packages.${pkgs.system}.default; + services.noctalia-shell.package = lib.mkDefault self.packages.${pkgs.system}.default; }; }; } From 2ce0992b19dca6c3d9934259936526b0c36ef0c3 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 15 Oct 2025 19:30:15 -0400 Subject: [PATCH 15/15] comment --- Commons/Settings.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 11767999..22a1c2ff 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -102,7 +102,7 @@ Singleton { // Emit the signal root.settingsLoaded() - // Last, update our local settings version + // Finally, update our local settings version adapter.settingsVersion = settingsVersion } }