1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

Allow solid colored wallpaper, fix fzf search

This commit is contained in:
bbedward
2025-09-03 16:29:47 -04:00
parent 3856ce14cd
commit b4e607e2b4
27 changed files with 639 additions and 427 deletions

View File

@@ -1,4 +1,5 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtCore
@@ -53,19 +54,13 @@ Singleton {
var settings = JSON.parse(content)
isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false
wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : ""
wallpaperLastPath = settings.wallpaperLastPath
!== undefined ? settings.wallpaperLastPath : ""
profileLastPath = settings.profileLastPath
!== undefined ? settings.profileLastPath : ""
wallpaperLastPath = settings.wallpaperLastPath !== undefined ? settings.wallpaperLastPath : ""
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
nightModeEnabled = settings.nightModeEnabled
!== undefined ? settings.nightModeEnabled : false
nightModeTemperature = settings.nightModeTemperature
!== undefined ? settings.nightModeTemperature : 4500
nightModeAutoEnabled = settings.nightModeAutoEnabled
!== undefined ? settings.nightModeAutoEnabled : false
nightModeAutoMode = settings.nightModeAutoMode
!== undefined ? settings.nightModeAutoMode : "time"
nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false
nightModeTemperature = settings.nightModeTemperature !== undefined ? settings.nightModeTemperature : 4500
nightModeAutoEnabled = settings.nightModeAutoEnabled !== undefined ? settings.nightModeAutoEnabled : false
nightModeAutoMode = settings.nightModeAutoMode !== undefined ? settings.nightModeAutoMode : "time"
// Handle legacy time format
if (settings.nightModeStartTime !== undefined) {
const parts = settings.nightModeStartTime.split(":")
@@ -87,24 +82,15 @@ Singleton {
longitude = settings.longitude !== undefined ? settings.longitude : 0.0
nightModeLocationProvider = settings.nightModeLocationProvider !== undefined ? settings.nightModeLocationProvider : ""
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : []
selectedGpuIndex = settings.selectedGpuIndex
!== undefined ? settings.selectedGpuIndex : 0
nvidiaGpuTempEnabled = settings.nvidiaGpuTempEnabled
!== undefined ? settings.nvidiaGpuTempEnabled : false
nonNvidiaGpuTempEnabled = settings.nonNvidiaGpuTempEnabled
!== undefined ? settings.nonNvidiaGpuTempEnabled : false
enabledGpuPciIds = settings.enabledGpuPciIds
!== undefined ? settings.enabledGpuPciIds : []
wallpaperCyclingEnabled = settings.wallpaperCyclingEnabled
!== undefined ? settings.wallpaperCyclingEnabled : false
wallpaperCyclingMode = settings.wallpaperCyclingMode
!== undefined ? settings.wallpaperCyclingMode : "interval"
wallpaperCyclingInterval = settings.wallpaperCyclingInterval
!== undefined ? settings.wallpaperCyclingInterval : 300
wallpaperCyclingTime = settings.wallpaperCyclingTime
!== undefined ? settings.wallpaperCyclingTime : "06:00"
lastBrightnessDevice = settings.lastBrightnessDevice
!== undefined ? settings.lastBrightnessDevice : ""
selectedGpuIndex = settings.selectedGpuIndex !== undefined ? settings.selectedGpuIndex : 0
nvidiaGpuTempEnabled = settings.nvidiaGpuTempEnabled !== undefined ? settings.nvidiaGpuTempEnabled : false
nonNvidiaGpuTempEnabled = settings.nonNvidiaGpuTempEnabled !== undefined ? settings.nonNvidiaGpuTempEnabled : false
enabledGpuPciIds = settings.enabledGpuPciIds !== undefined ? settings.enabledGpuPciIds : []
wallpaperCyclingEnabled = settings.wallpaperCyclingEnabled !== undefined ? settings.wallpaperCyclingEnabled : false
wallpaperCyclingMode = settings.wallpaperCyclingMode !== undefined ? settings.wallpaperCyclingMode : "interval"
wallpaperCyclingInterval = settings.wallpaperCyclingInterval !== undefined ? settings.wallpaperCyclingInterval : 300
wallpaperCyclingTime = settings.wallpaperCyclingTime !== undefined ? settings.wallpaperCyclingTime : "06:00"
lastBrightnessDevice = settings.lastBrightnessDevice !== undefined ? settings.lastBrightnessDevice : ""
notepadContent = settings.notepadContent !== undefined ? settings.notepadContent : ""
}
} catch (e) {
@@ -218,22 +204,41 @@ Singleton {
}
function setWallpaper(imagePath) {
console.log("SessionData.setWallpaper called with:", imagePath)
wallpaperPath = imagePath
saveSettings()
if (typeof Theme !== "undefined") {
console.log("Theme is available, current theme:", Theme.currentTheme)
// Always extract colors for shell UI if dynamic theming is enabled
if (typeof SettingsData !== "undefined" && SettingsData.wallpaperDynamicTheming) {
console.log("Dynamic theming enabled, extracting colors")
Theme.switchTheme("dynamic")
Theme.extractColors()
}
// Always generate system themes (matugen templates) when wallpaper changes
console.log("Calling generateSystemThemesFromCurrentTheme")
Theme.generateSystemThemesFromCurrentTheme()
} else {
console.log("Theme is undefined!")
}
}
function setWallpaperColor(color) {
wallpaperPath = color
saveSettings()
if (typeof Theme !== "undefined") {
if (typeof SettingsData !== "undefined" && SettingsData.wallpaperDynamicTheming) {
Theme.switchTheme("dynamic")
Theme.extractColors()
}
Theme.generateSystemThemesFromCurrentTheme()
}
}
function clearWallpaper() {
wallpaperPath = ""
saveSettings()
if (typeof Theme !== "undefined") {
if (typeof SettingsData !== "undefined" && SettingsData.theme) {
Theme.switchTheme(SettingsData.theme)
} else {
Theme.switchTheme("blue")
}
}
}
@@ -321,8 +326,7 @@ Singleton {
FileView {
id: settingsFile
path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: true
blockWrites: true
watchChanges: true
@@ -344,9 +348,7 @@ Singleton {
return "ERROR: No path provided"
}
var absolutePath = path.startsWith(
"/") ? path : StandardPaths.writableLocation(
StandardPaths.HomeLocation) + "/" + path
var absolutePath = path.startsWith("/") ? path : StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/" + path
try {
root.setWallpaper(absolutePath)

View File

@@ -1,4 +1,5 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtCore
@@ -14,7 +15,7 @@ Singleton {
property string currentTheme: "blue"
property bool isLightMode: false
readonly property string dynamic: "dynamic"
readonly property string homeDir: {
@@ -27,7 +28,7 @@ Singleton {
}
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Common/", "")
readonly property string wallpaperPath: typeof SessionData !== "undefined" ? SessionData.wallpaperPath : ""
property bool matugenAvailable: false
property bool gtkThemingEnabled: typeof SettingsData !== "undefined" ? SettingsData.gtkAvailable : false
property bool qtThemingEnabled: typeof SettingsData !== "undefined" ? (SettingsData.qt5ctAvailable || SettingsData.qt6ctAvailable) : false
@@ -36,7 +37,7 @@ Singleton {
property bool extractionRequested: false
property int colorUpdateTrigger: 0
property var customThemeData: null
readonly property string stateDir: {
const cacheHome = StandardPaths.writableLocation(StandardPaths.CacheLocation).toString()
const path = cacheHome.startsWith("file://") ? cacheHome.substring(7) : cacheHome
@@ -60,24 +61,24 @@ Singleton {
return customThemeData || StockThemes.getThemeByName("blue", isLightMode)
} else if (currentTheme === dynamic) {
return {
primary: getMatugenColor("primary", "#42a5f5"),
primaryText: getMatugenColor("on_primary", "#ffffff"),
primaryContainer: getMatugenColor("primary_container", "#1976d2"),
secondary: getMatugenColor("secondary", "#8ab4f8"),
surface: getMatugenColor("surface", "#1a1c1e"),
surfaceText: getMatugenColor("on_background", "#e3e8ef"),
surfaceVariant: getMatugenColor("surface_variant", "#44464f"),
surfaceVariantText: getMatugenColor("on_surface_variant", "#c4c7c5"),
surfaceTint: getMatugenColor("surface_tint", "#8ab4f8"),
background: getMatugenColor("background", "#1a1c1e"),
backgroundText: getMatugenColor("on_background", "#e3e8ef"),
outline: getMatugenColor("outline", "#8e918f"),
surfaceContainer: getMatugenColor("surface_container", "#1e2023"),
surfaceContainerHigh: getMatugenColor("surface_container_high", "#292b2f"),
error: "#F2B8B5",
warning: "#FF9800",
info: "#2196F3",
success: "#4CAF50"
"primary": getMatugenColor("primary", "#42a5f5"),
"primaryText": getMatugenColor("on_primary", "#ffffff"),
"primaryContainer": getMatugenColor("primary_container", "#1976d2"),
"secondary": getMatugenColor("secondary", "#8ab4f8"),
"surface": getMatugenColor("surface", "#1a1c1e"),
"surfaceText": getMatugenColor("on_background", "#e3e8ef"),
"surfaceVariant": getMatugenColor("surface_variant", "#44464f"),
"surfaceVariantText": getMatugenColor("on_surface_variant", "#c4c7c5"),
"surfaceTint": getMatugenColor("surface_tint", "#8ab4f8"),
"background": getMatugenColor("background", "#1a1c1e"),
"backgroundText": getMatugenColor("on_background", "#e3e8ef"),
"outline": getMatugenColor("outline", "#8e918f"),
"surfaceContainer": getMatugenColor("surface_container", "#1e2023"),
"surfaceContainerHigh": getMatugenColor("surface_container_high", "#292b2f"),
"error": "#F2B8B5",
"warning": "#FF9800",
"info": "#2196F3",
"success": "#4CAF50"
}
} else {
return StockThemes.getThemeByName(currentTheme, isLightMode)
@@ -175,7 +176,7 @@ Singleton {
}
if (savePrefs && typeof SettingsData !== "undefined")
SettingsData.setTheme(currentTheme)
generateSystemThemesFromCurrentTheme()
}
@@ -183,14 +184,14 @@ Singleton {
isLightMode = light
if (savePrefs && typeof SessionData !== "undefined")
SessionData.setLightMode(isLightMode)
PortalService.setLightMode(isLightMode)
PortalService.setLightMode(isLightMode)
generateSystemThemesFromCurrentTheme()
}
function toggleLightMode(savePrefs = true) {
setLightMode(!isLightMode, savePrefs)
}
function forceGenerateSystemThemes() {
if (!matugenAvailable) {
if (typeof ToastService !== "undefined") {
@@ -225,7 +226,7 @@ Singleton {
} else {
customThemeData = themeData
}
generateSystemThemesFromCurrentTheme()
}
@@ -237,7 +238,6 @@ Singleton {
readonly property var _availableThemeNames: StockThemes.getAllThemeNames()
property string currentThemeName: currentTheme
function popupBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, popupTransparency)
}
@@ -271,21 +271,34 @@ Singleton {
return _getBatteryPowerProfileIcon()
if (isCharging) {
if (level >= 90) return "battery_charging_full"
if (level >= 80) return "battery_charging_90"
if (level >= 60) return "battery_charging_80"
if (level >= 50) return "battery_charging_60"
if (level >= 30) return "battery_charging_50"
if (level >= 20) return "battery_charging_30"
if (level >= 90)
return "battery_charging_full"
if (level >= 80)
return "battery_charging_90"
if (level >= 60)
return "battery_charging_80"
if (level >= 50)
return "battery_charging_60"
if (level >= 30)
return "battery_charging_50"
if (level >= 20)
return "battery_charging_30"
return "battery_charging_20"
} else {
if (level >= 95) return "battery_full"
if (level >= 85) return "battery_6_bar"
if (level >= 70) return "battery_5_bar"
if (level >= 55) return "battery_4_bar"
if (level >= 40) return "battery_3_bar"
if (level >= 25) return "battery_2_bar"
if (level >= 10) return "battery_1_bar"
if (level >= 95)
return "battery_full"
if (level >= 85)
return "battery_6_bar"
if (level >= 70)
return "battery_5_bar"
if (level >= 55)
return "battery_4_bar"
if (level >= 40)
return "battery_3_bar"
if (level >= 25)
return "battery_2_bar"
if (level >= 10)
return "battery_1_bar"
return "battery_alert"
}
}
@@ -355,11 +368,11 @@ Singleton {
if (matugenColors && Object.keys(matugenColors).length > 0) {
colorUpdateTrigger++
}
if (currentTheme === "custom" && customThemeFileView.path) {
customThemeFileView.reload()
}
generateSystemThemesFromCurrentTheme()
}
@@ -368,38 +381,39 @@ Singleton {
console.warn("matugen not available - cannot set system theme")
return
}
const desired = {
"kind": kind,
"value": value,
"mode": isLight ? "light" : "dark",
"iconTheme": iconTheme || "System Default"
}
const json = JSON.stringify(desired)
const desiredPath = stateDir + "/matugen.desired.json"
Quickshell.execDetached([
"sh", "-c",
`mkdir -p '${stateDir}' && cat > '${desiredPath}' << 'EOF'\n${json}\nEOF`
])
Quickshell.execDetached(["sh", "-c", `mkdir -p '${stateDir}' && cat > '${desiredPath}' << 'EOF'\n${json}\nEOF`])
workerRunning = true
systemThemeGenerator.command = [shellDir + "/scripts/matugen-worker.sh", stateDir, shellDir, "--run"]
systemThemeGenerator.running = true
}
function generateSystemThemesFromCurrentTheme() {
if (!matugenAvailable)
return
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
if (currentTheme === dynamic) {
if (!wallpaperPath) {
return
}
setDesiredTheme("image", wallpaperPath, isLight, iconTheme)
if (wallpaperPath.startsWith("#")) {
setDesiredTheme("hex", wallpaperPath, isLight, iconTheme)
} else {
setDesiredTheme("image", wallpaperPath, isLight, iconTheme)
}
} else {
let primaryColor
if (currentTheme === "custom") {
@@ -411,7 +425,7 @@ Singleton {
} else {
primaryColor = currentThemeData.primary
}
if (!primaryColor) {
console.warn("No primary color available for theme:", currentTheme)
return
@@ -445,17 +459,22 @@ Singleton {
qtApplier.running = true
}
function extractJsonFromText(text) {
if (!text) return null
if (!text)
return null
const start = text.search(/[{\[]/)
if (start === -1) return null
if (start === -1)
return null
const open = text[start]
const pairs = { "{": '}', "[": ']' }
const pairs = {
"{": '}',
"[": ']'
}
const close = pairs[open]
if (!close) return null
if (!close)
return null
let inString = false
let escape = false
@@ -511,17 +530,18 @@ Singleton {
if (extractionRequested) {
fileChecker.running = true
}
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
if (currentTheme === dynamic) {
if (wallpaperPath) {
// Clear cache on startup to force regeneration
Quickshell.execDetached(["rm", "-f", stateDir + "/matugen.key"])
setDesiredTheme("image", wallpaperPath, isLight, iconTheme)
} else {
if (wallpaperPath.startsWith("#")) {
setDesiredTheme("hex", wallpaperPath, isLight, iconTheme)
} else {
setDesiredTheme("image", wallpaperPath, isLight, iconTheme)
}
}
} else {
let primaryColor
@@ -532,12 +552,10 @@ Singleton {
} else {
primaryColor = currentThemeData.primary
}
if (primaryColor) {
// Clear cache on startup to force regeneration
Quickshell.execDetached(["rm", "-f", stateDir + "/matugen.key"])
setDesiredTheme("hex", primaryColor, isLight, iconTheme)
} else {
}
}
}
@@ -549,6 +567,8 @@ Singleton {
onExited: code => {
if (code === 0) {
matugenProcess.running = true
} else if (wallpaperPath.startsWith("#")) {
colorMatugenProcess.running = true
}
}
}
@@ -601,18 +621,65 @@ Singleton {
}
}
Process {
id: colorMatugenProcess
command: ["matugen", "color", "hex", wallpaperPath, "--json", "hex"]
stdout: StdioCollector {
id: colorMatugenCollector
onStreamFinished: {
if (!colorMatugenCollector.text) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Color Processing Failed: Empty JSON extracted from matugen output.")
}
return
}
const extractedJson = extractJsonFromText(colorMatugenCollector.text)
if (!extractedJson) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Color Processing Failed: Invalid JSON extracted from matugen output.")
}
console.log("Raw matugen output:", colorMatugenCollector.text)
return
}
try {
root.matugenColors = JSON.parse(extractedJson)
root.colorUpdateTrigger++
if (typeof ToastService !== "undefined") {
ToastService.clearWallpaperError()
}
} catch (e) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Color processing failed (JSON parse error after extraction)")
}
}
}
}
onExited: code => {
if (code !== 0) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Matugen color command failed with exit code " + code)
}
}
}
}
Process {
id: ensureStateDir
}
Process {
id: systemThemeGenerator
running: false
onExited: exitCode => {
workerRunning = false
if (exitCode === 2) {
// Exit code 2 means wallpaper/color not found - this is expected on first run
console.log("Theme worker: wallpaper/color not found, skipping theme generation")
@@ -675,14 +742,10 @@ Singleton {
}
}
Component.onCompleted: {
matugenCheck.running = true
if (typeof SessionData !== "undefined")
SessionData.isLightModeChanged.connect(root.onLightModeChanged)
SessionData.isLightModeChanged.connect(root.onLightModeChanged)
}
FileView {
@@ -697,7 +760,7 @@ Singleton {
ToastService.showError("Invalid JSON format: " + e.message)
}
}
onLoaded: {
parseAndLoadTheme()
}
@@ -706,7 +769,7 @@ Singleton {
customThemeFileView.reload()
}
onLoadFailed: function(error) {
onLoadFailed: function (error) {
if (typeof ToastService !== "undefined") {
ToastService.showError("Failed to read theme file: " + error)
}
@@ -735,4 +798,4 @@ Singleton {
return root.isLightMode ? "light" : "dark"
}
}
}
}

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls

View File

@@ -23,7 +23,7 @@ Item {
property string powerDialogMessage: ""
property string powerDialogConfirmText: ""
property color powerDialogConfirmColor: Theme.primary
property var powerDialogOnConfirm: function() {}
property var powerDialogOnConfirm: function () {}
function showPowerDialog(title, message, confirmText, confirmColor, onConfirm) {
powerDialogTitle = title
@@ -57,7 +57,7 @@ Item {
Loader {
anchors.fill: parent
active: !SessionData.wallpaperPath
active: !SessionData.wallpaperPath || (SessionData.wallpaperPath && SessionData.wallpaperPath.startsWith("#"))
asynchronous: true
sourceComponent: DankBackdrop {}
@@ -67,7 +67,7 @@ Item {
id: wallpaperBackground
anchors.fill: parent
source: SessionData.wallpaperPath || ""
source: (SessionData.wallpaperPath && !SessionData.wallpaperPath.startsWith("#")) ? SessionData.wallpaperPath : ""
fillMode: Image.PreserveAspectCrop
smooth: true
asynchronous: false
@@ -802,7 +802,7 @@ Item {
if (demoMode) {
console.log("Demo: Power")
} else {
showPowerDialog("Power Off", "Power off this computer?", "Power Off", Theme.error, function() {
showPowerDialog("Power Off", "Power off this computer?", "Power Off", Theme.error, function () {
SessionService.poweroff()
})
}
@@ -816,7 +816,7 @@ Item {
if (demoMode) {
console.log("Demo: Reboot")
} else {
showPowerDialog("Restart", "Restart this computer?", "Restart", Theme.primary, function() {
showPowerDialog("Restart", "Restart this computer?", "Restart", Theme.primary, function () {
SessionService.reboot()
})
}
@@ -830,7 +830,7 @@ Item {
if (demoMode) {
console.log("Demo: Logout")
} else {
showPowerDialog("Log Out", "End this session?", "Log Out", Theme.primary, function() {
showPowerDialog("Log Out", "End this session?", "Log Out", Theme.primary, function () {
SessionService.logout()
})
}

View File

@@ -18,56 +18,58 @@ Item {
property bool fontsEnumerated: false
function enumerateFonts() {
var fonts = ["Default"];
var availableFonts = Qt.fontFamilies();
var rootFamilies = [];
var seenFamilies = new Set();
var fonts = ["Default"]
var availableFonts = Qt.fontFamilies()
var rootFamilies = []
var seenFamilies = new Set()
for (var i = 0; i < availableFonts.length; i++) {
var fontName = availableFonts[i];
var fontName = availableFonts[i]
if (fontName.startsWith("."))
continue;
continue
if (fontName === SettingsData.defaultFontFamily)
continue;
continue
var rootName = fontName.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").replace(/ (UI|Display|Text|Mono|Sans|Serif)$/i, function(match, suffix) {
return match;
}).trim();
var rootName = fontName.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i,
"").replace(/ (UI|Display|Text|Mono|Sans|Serif)$/i, function (match, suffix) {
return match
}).trim()
if (!seenFamilies.has(rootName) && rootName !== "") {
seenFamilies.add(rootName);
rootFamilies.push(rootName);
seenFamilies.add(rootName)
rootFamilies.push(rootName)
}
}
cachedFontFamilies = fonts.concat(rootFamilies.sort());
var monoFonts = ["Default"];
var monoFamilies = [];
var seenMonoFamilies = new Set();
cachedFontFamilies = fonts.concat(rootFamilies.sort())
var monoFonts = ["Default"]
var monoFamilies = []
var seenMonoFamilies = new Set()
for (var j = 0; j < availableFonts.length; j++) {
var fontName2 = availableFonts[j];
var fontName2 = availableFonts[j]
if (fontName2.startsWith("."))
continue;
continue
if (fontName2 === SettingsData.defaultMonoFontFamily)
continue;
continue
var lowerName = fontName2.toLowerCase();
if (lowerName.includes("mono") || lowerName.includes("code") || lowerName.includes("console") || lowerName.includes("terminal") || lowerName.includes("courier") || lowerName.includes("dejavu sans mono") || lowerName.includes("jetbrains") || lowerName.includes("fira") || lowerName.includes("hack") || lowerName.includes("source code") || lowerName.includes("ubuntu mono") || lowerName.includes("cascadia")) {
var rootName2 = fontName2.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").trim();
var lowerName = fontName2.toLowerCase()
if (lowerName.includes("mono") || lowerName.includes("code") || lowerName.includes("console") || lowerName.includes("terminal") || lowerName.includes("courier") || lowerName.includes("dejavu sans mono") || lowerName.includes(
"jetbrains") || lowerName.includes("fira") || lowerName.includes("hack") || lowerName.includes("source code") || lowerName.includes("ubuntu mono") || lowerName.includes("cascadia")) {
var rootName2 = fontName2.replace(/ (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i, "").replace(/ (Italic|Oblique|Condensed|Extended|Narrow|Wide)$/i, "").trim()
if (!seenMonoFamilies.has(rootName2) && rootName2 !== "") {
seenMonoFamilies.add(rootName2);
monoFamilies.push(rootName2);
seenMonoFamilies.add(rootName2)
monoFamilies.push(rootName2)
}
}
}
cachedMonoFamilies = monoFonts.concat(monoFamilies.sort());
cachedMonoFamilies = monoFonts.concat(monoFamilies.sort())
}
Component.onCompleted: {
// Access WallpaperCyclingService to ensure it's initialized
WallpaperCyclingService.cyclingActive;
WallpaperCyclingService.cyclingActive
if (!fontsEnumerated) {
enumerateFonts();
fontsEnumerated = true;
enumerateFonts()
fontsEnumerated = true
}
}
@@ -118,7 +120,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -136,9 +137,9 @@ Item {
CachingImage {
anchors.fill: parent
anchors.margins: 1
source: SessionData.wallpaperPath !== "" ? "file://" + SessionData.wallpaperPath : ""
source: (SessionData.wallpaperPath !== "" && !SessionData.wallpaperPath.startsWith("#")) ? "file://" + SessionData.wallpaperPath : ""
fillMode: Image.PreserveAspectCrop
visible: SessionData.wallpaperPath !== ""
visible: SessionData.wallpaperPath !== "" && !SessionData.wallpaperPath.startsWith("#")
maxCacheSize: 160
layer.enabled: true
@@ -148,7 +149,14 @@ Item {
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
}
Rectangle {
anchors.fill: parent
anchors.margins: 1
radius: Theme.cornerRadius - 1
color: SessionData.wallpaperPath.startsWith("#") ? SessionData.wallpaperPath : "transparent"
visible: SessionData.wallpaperPath !== "" && SessionData.wallpaperPath.startsWith("#")
}
Rectangle {
@@ -199,13 +207,34 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (parentModal) {
parentModal.allowFocusOverride = true;
parentModal.shouldHaveFocus = false;
parentModal.allowFocusOverride = true
parentModal.shouldHaveFocus = false
}
wallpaperBrowser.open();
wallpaperBrowser.open()
}
}
}
Rectangle {
width: 32
height: 32
radius: 16
color: Qt.rgba(255, 255, 255, 0.9)
DankIcon {
anchors.centerIn: parent
name: "palette"
size: 18
color: "black"
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
colorPicker.open()
}
}
}
Rectangle {
@@ -227,16 +256,13 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (Theme.currentTheme === Theme.dynamic)
Theme.switchTheme("blue");
Theme.switchTheme("blue")
SessionData.setWallpaper("");
SessionData.clearWallpaper()
}
}
}
}
}
MouseArea {
@@ -248,7 +274,6 @@ Item {
propagateComposedEvents: true
acceptedButtons: Qt.NoButton
}
}
Column {
@@ -283,12 +308,12 @@ Item {
buttonSize: 32
iconName: "skip_previous"
iconSize: Theme.iconSizeSmall
enabled: SessionData.wallpaperPath
opacity: SessionData.wallpaperPath ? 1 : 0.5
enabled: SessionData.wallpaperPath && !SessionData.wallpaperPath.startsWith("#")
opacity: (SessionData.wallpaperPath && !SessionData.wallpaperPath.startsWith("#")) ? 1 : 0.5
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
iconColor: Theme.surfaceText
onClicked: {
WallpaperCyclingService.cyclePrevManually();
WallpaperCyclingService.cyclePrevManually()
}
}
@@ -296,19 +321,16 @@ Item {
buttonSize: 32
iconName: "skip_next"
iconSize: Theme.iconSizeSmall
enabled: SessionData.wallpaperPath
opacity: SessionData.wallpaperPath ? 1 : 0.5
enabled: SessionData.wallpaperPath && !SessionData.wallpaperPath.startsWith("#")
opacity: (SessionData.wallpaperPath && !SessionData.wallpaperPath.startsWith("#")) ? 1 : 0.5
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
iconColor: Theme.surfaceText
onClicked: {
WallpaperCyclingService.cycleNextManually();
WallpaperCyclingService.cycleNextManually()
}
}
}
}
}
// Wallpaper Cycling Section - Full Width
@@ -354,7 +376,6 @@ Item {
color: Theme.surfaceVariantText
width: parent.width
}
}
DankToggle {
@@ -362,11 +383,10 @@ Item {
anchors.verticalCenter: parent.verticalCenter
checked: SessionData.wallpaperCyclingEnabled
onToggled: (toggled) => {
return SessionData.setWallpaperCyclingEnabled(toggled);
}
onToggled: toggled => {
return SessionData.setWallpaperCyclingEnabled(toggled)
}
}
}
// Cycling mode and settings
@@ -393,18 +413,17 @@ Item {
width: 200
height: 32
model: [{
"text": "Interval",
"icon": "schedule"
}, {
"text": "Time",
"icon": "access_time"
}]
"text": "Interval",
"icon": "schedule"
}, {
"text": "Time",
"icon": "access_time"
}]
currentIndex: SessionData.wallpaperCyclingMode === "time" ? 1 : 0
onTabClicked: (index) => {
SessionData.setWallpaperCyclingMode(index === 1 ? "time" : "interval");
}
onTabClicked: index => {
SessionData.setWallpaperCyclingMode(index === 1 ? "time" : "interval")
}
}
}
// Interval settings
@@ -418,16 +437,15 @@ Item {
description: "How often to change wallpaper"
options: intervalOptions
currentValue: {
const currentSeconds = SessionData.wallpaperCyclingInterval;
const index = intervalValues.indexOf(currentSeconds);
return index >= 0 ? intervalOptions[index] : "5 minutes";
}
onValueChanged: (value) => {
const index = intervalOptions.indexOf(value);
if (index >= 0)
SessionData.setWallpaperCyclingInterval(intervalValues[index]);
const currentSeconds = SessionData.wallpaperCyclingInterval
const index = intervalValues.indexOf(currentSeconds)
return index >= 0 ? intervalOptions[index] : "5 minutes"
}
onValueChanged: value => {
const index = intervalOptions.indexOf(value)
if (index >= 0)
SessionData.setWallpaperCyclingInterval(intervalValues[index])
}
}
// Time settings
@@ -452,25 +470,24 @@ Item {
topPadding: Theme.spacingS
bottomPadding: Theme.spacingS
onAccepted: {
var isValid = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/.test(text);
var isValid = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/.test(text)
if (isValid)
SessionData.setWallpaperCyclingTime(text);
SessionData.setWallpaperCyclingTime(text)
else
text = SessionData.wallpaperCyclingTime;
text = SessionData.wallpaperCyclingTime
}
onEditingFinished: {
var isValid = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/.test(text);
var isValid = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/.test(text)
if (isValid)
SessionData.setWallpaperCyclingTime(text);
SessionData.setWallpaperCyclingTime(text)
else
text = SessionData.wallpaperCyclingTime;
text = SessionData.wallpaperCyclingTime
}
anchors.verticalCenter: parent.verticalCenter
validator: RegularExpressionValidator {
regularExpression: /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/
}
}
StyledText {
@@ -479,15 +496,10 @@ Item {
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
// Dynamic Theme Section
@@ -536,7 +548,6 @@ Item {
wrapMode: Text.WordWrap
width: parent.width
}
}
DankToggle {
@@ -545,14 +556,13 @@ Item {
anchors.verticalCenter: parent.verticalCenter
checked: Theme.wallpaperPath !== "" && Theme.currentTheme === Theme.dynamic
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing" && Theme.wallpaperPath !== ""
onToggled: (toggled) => {
if (toggled)
Theme.switchTheme(Theme.dynamic);
else
Theme.switchTheme("blue");
}
onToggled: toggled => {
if (toggled)
Theme.switchTheme(Theme.dynamic)
else
Theme.switchTheme("blue")
}
}
}
StyledText {
@@ -563,9 +573,7 @@ Item {
width: parent.width
leftPadding: Theme.iconSize + Theme.spacingM
}
}
}
// Display Settings
@@ -602,7 +610,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
@@ -610,9 +617,9 @@ Item {
text: "Light Mode"
description: "Use light theme instead of dark theme"
checked: SessionData.isLightMode
onToggled: (checked) => {
Theme.setLightMode(checked);
}
onToggled: checked => {
Theme.setLightMode(checked)
}
}
Rectangle {
@@ -629,13 +636,13 @@ Item {
text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain. Use automation settings below to control when it activates."
checked: DisplayService.nightModeEnabled
onToggled: (checked) => {
DisplayService.toggleNightMode();
}
onToggled: checked => {
DisplayService.toggleNightMode()
}
Connections {
function onNightModeEnabledChanged() {
nightModeToggle.checked = DisplayService.nightModeEnabled;
nightModeToggle.checked = DisplayService.nightModeEnabled
}
target: DisplayService
@@ -648,16 +655,16 @@ Item {
description: "Color temperature for night mode"
currentValue: SessionData.nightModeTemperature + "K"
options: {
var temps = [];
var temps = []
for (var i = 2500; i <= 6000; i += 500) {
temps.push(i + "K");
temps.push(i + "K")
}
return temps;
}
onValueChanged: (value) => {
var temp = parseInt(value.replace("K", ""));
SessionData.setNightModeTemperature(temp);
return temps
}
onValueChanged: value => {
var temp = parseInt(value.replace("K", ""))
SessionData.setNightModeTemperature(temp)
}
}
DankToggle {
@@ -666,19 +673,19 @@ Item {
text: "Automatic Control"
description: "Only adjust gamma based on time or location rules."
checked: SessionData.nightModeAutoEnabled
onToggled: (checked) => {
if (checked && !DisplayService.nightModeEnabled) {
DisplayService.toggleNightMode();
} else if (!checked && DisplayService.nightModeEnabled) {
DisplayService.toggleNightMode();
}
SessionData.setNightModeAutoEnabled(checked);
}
onToggled: checked => {
if (checked && !DisplayService.nightModeEnabled) {
DisplayService.toggleNightMode()
} else if (!checked && DisplayService.nightModeEnabled) {
DisplayService.toggleNightMode()
}
SessionData.setNightModeAutoEnabled(checked)
}
Connections {
target: SessionData
function onNightModeAutoEnabledChanged() {
automaticToggle.checked = SessionData.nightModeAutoEnabled;
automaticToggle.checked = SessionData.nightModeAutoEnabled
}
}
}
@@ -693,7 +700,7 @@ Item {
Connections {
target: SessionData
function onNightModeAutoEnabledChanged() {
automaticSettings.visible = SessionData.nightModeAutoEnabled;
automaticSettings.visible = SessionData.nightModeAutoEnabled
}
}
@@ -702,22 +709,22 @@ Item {
width: 200
height: 32
model: [{
"text": "Time",
"icon": "access_time"
}, {
"text": "Location",
"icon": "place"
}]
"text": "Time",
"icon": "access_time"
}, {
"text": "Location",
"icon": "place"
}]
Component.onCompleted: {
currentIndex = SessionData.nightModeAutoMode === "location" ? 1 : 0;
}
onTabClicked: (index) => {
console.log("Tab clicked:", index, "Setting mode to:", index === 1 ? "location" : "time");
DisplayService.setNightModeAutomationMode(index === 1 ? "location" : "time");
currentIndex = index;
currentIndex = SessionData.nightModeAutoMode === "location" ? 1 : 0
}
onTabClicked: index => {
console.log("Tab clicked:", index, "Setting mode to:", index === 1 ? "location" : "time")
DisplayService.setNightModeAutomationMode(index === 1 ? "location" : "time")
currentIndex = index
}
}
Column {
@@ -770,15 +777,15 @@ Item {
text: ""
currentValue: SessionData.nightModeStartHour.toString()
options: {
var hours = [];
var hours = []
for (var i = 0; i < 24; i++) {
hours.push(i.toString());
hours.push(i.toString())
}
return hours;
}
onValueChanged: (value) => {
SessionData.setNightModeStartHour(parseInt(value));
return hours
}
onValueChanged: value => {
SessionData.setNightModeStartHour(parseInt(value))
}
}
DankDropdown {
@@ -787,15 +794,15 @@ Item {
text: ""
currentValue: SessionData.nightModeStartMinute.toString().padStart(2, '0')
options: {
var minutes = [];
var minutes = []
for (var i = 0; i < 60; i += 5) {
minutes.push(i.toString().padStart(2, '0'));
minutes.push(i.toString().padStart(2, '0'))
}
return minutes;
}
onValueChanged: (value) => {
SessionData.setNightModeStartMinute(parseInt(value));
return minutes
}
onValueChanged: value => {
SessionData.setNightModeStartMinute(parseInt(value))
}
}
}
@@ -818,15 +825,15 @@ Item {
text: ""
currentValue: SessionData.nightModeEndHour.toString()
options: {
var hours = [];
var hours = []
for (var i = 0; i < 24; i++) {
hours.push(i.toString());
hours.push(i.toString())
}
return hours;
}
onValueChanged: (value) => {
SessionData.setNightModeEndHour(parseInt(value));
return hours
}
onValueChanged: value => {
SessionData.setNightModeEndHour(parseInt(value))
}
}
DankDropdown {
@@ -835,15 +842,15 @@ Item {
text: ""
currentValue: SessionData.nightModeEndMinute.toString().padStart(2, '0')
options: {
var minutes = [];
var minutes = []
for (var i = 0; i < 60; i += 5) {
minutes.push(i.toString().padStart(2, '0'));
minutes.push(i.toString().padStart(2, '0'))
}
return minutes;
}
onValueChanged: (value) => {
SessionData.setNightModeEndMinute(parseInt(value));
return minutes
}
onValueChanged: value => {
SessionData.setNightModeEndMinute(parseInt(value))
}
}
}
}
@@ -860,15 +867,15 @@ Item {
description: DisplayService.geoclueAvailable ? "Use automatic location detection (geoclue2)" : "Geoclue service not running - cannot auto-detect location"
checked: SessionData.nightModeLocationProvider === "geoclue2"
enabled: DisplayService.geoclueAvailable
onToggled: (checked) => {
if (checked && DisplayService.geoclueAvailable) {
SessionData.setNightModeLocationProvider("geoclue2")
SessionData.setLatitude(0.0)
SessionData.setLongitude(0.0)
} else {
SessionData.setNightModeLocationProvider("")
}
}
onToggled: checked => {
if (checked && DisplayService.geoclueAvailable) {
SessionData.setNightModeLocationProvider("geoclue2")
SessionData.setLatitude(0.0)
SessionData.setLongitude(0.0)
} else {
SessionData.setNightModeLocationProvider("")
}
}
}
StyledText {
@@ -937,13 +944,8 @@ Item {
wrapMode: Text.WordWrap
}
}
}
}
}
// Font Settings
@@ -980,7 +982,6 @@ Item {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankDropdown {
@@ -989,20 +990,20 @@ Item {
description: "Select system font family"
currentValue: {
if (SettingsData.fontFamily === SettingsData.defaultFontFamily)
return "Default";
return "Default"
else
return SettingsData.fontFamily || "Default";
return SettingsData.fontFamily || "Default"
}
enableFuzzySearch: true
popupWidthOffset: 100
maxPopupHeight: 400
options: cachedFontFamilies
onValueChanged: (value) => {
if (value.startsWith("Default"))
SettingsData.setFontFamily(SettingsData.defaultFontFamily);
else
SettingsData.setFontFamily(value);
}
onValueChanged: value => {
if (value.startsWith("Default"))
SettingsData.setFontFamily(SettingsData.defaultFontFamily)
else
SettingsData.setFontFamily(value)
}
}
DankDropdown {
@@ -1012,64 +1013,64 @@ Item {
currentValue: {
switch (SettingsData.fontWeight) {
case Font.Thin:
return "Thin";
return "Thin"
case Font.ExtraLight:
return "Extra Light";
return "Extra Light"
case Font.Light:
return "Light";
return "Light"
case Font.Normal:
return "Regular";
return "Regular"
case Font.Medium:
return "Medium";
return "Medium"
case Font.DemiBold:
return "Demi Bold";
return "Demi Bold"
case Font.Bold:
return "Bold";
return "Bold"
case Font.ExtraBold:
return "Extra Bold";
return "Extra Bold"
case Font.Black:
return "Black";
return "Black"
default:
return "Regular";
return "Regular"
}
}
options: ["Thin", "Extra Light", "Light", "Regular", "Medium", "Demi Bold", "Bold", "Extra Bold", "Black"]
onValueChanged: (value) => {
var weight;
switch (value) {
case "Thin":
weight = Font.Thin;
break;
case "Extra Light":
weight = Font.ExtraLight;
break;
case "Light":
weight = Font.Light;
break;
case "Regular":
weight = Font.Normal;
break;
case "Medium":
weight = Font.Medium;
break;
case "Demi Bold":
weight = Font.DemiBold;
break;
case "Bold":
weight = Font.Bold;
break;
case "Extra Bold":
weight = Font.ExtraBold;
break;
case "Black":
weight = Font.Black;
break;
default:
weight = Font.Normal;
break;
}
SettingsData.setFontWeight(weight);
}
onValueChanged: value => {
var weight
switch (value) {
case "Thin":
weight = Font.Thin
break
case "Extra Light":
weight = Font.ExtraLight
break
case "Light":
weight = Font.Light
break
case "Regular":
weight = Font.Normal
break
case "Medium":
weight = Font.Medium
break
case "Demi Bold":
weight = Font.DemiBold
break
case "Bold":
weight = Font.Bold
break
case "Extra Bold":
weight = Font.ExtraBold
break
case "Black":
weight = Font.Black
break
default:
weight = Font.Normal
break
}
SettingsData.setFontWeight(weight)
}
}
DankDropdown {
@@ -1078,28 +1079,24 @@ Item {
description: "Select monospace font for process list and technical displays"
currentValue: {
if (SettingsData.monoFontFamily === SettingsData.defaultMonoFontFamily)
return "Default";
return "Default"
return SettingsData.monoFontFamily || "Default";
return SettingsData.monoFontFamily || "Default"
}
enableFuzzySearch: true
popupWidthOffset: 100
maxPopupHeight: 400
options: cachedMonoFamilies
onValueChanged: (value) => {
if (value === "Default")
SettingsData.setMonoFontFamily(SettingsData.defaultMonoFontFamily);
else
SettingsData.setMonoFontFamily(value);
}
onValueChanged: value => {
if (value === "Default")
SettingsData.setMonoFontFamily(SettingsData.defaultMonoFontFamily)
else
SettingsData.setMonoFontFamily(value)
}
}
}
}
}
}
FileBrowserModal {
@@ -1109,18 +1106,26 @@ Item {
browserIcon: "wallpaper"
browserType: "wallpaper"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => {
SessionData.setWallpaper(path);
close();
}
onFileSelected: path => {
SessionData.setWallpaper(path)
close()
}
onDialogClosed: {
if (parentModal) {
parentModal.allowFocusOverride = false;
parentModal.allowFocusOverride = false
parentModal.shouldHaveFocus = Qt.binding(() => {
return parentModal.shouldBeVisible;
});
return parentModal.shouldBeVisible
})
}
}
}
DankColorPicker {
id: colorPicker
pickerTitle: "Choose Wallpaper Color"
onColorSelected: selectedColor => {
SessionData.setWallpaperColor(selectedColor)
}
}
}

View File

@@ -33,20 +33,42 @@ LazyLoader {
anchors.fill: parent
property string source: SessionData.wallpaperPath || ""
property bool isColorSource: source.startsWith("#")
property Image current: one
onSourceChanged: {
if (!source)
if (!source) {
current = null
else if (current === one)
two.update()
else
one.update()
one.source = ""
two.source = ""
} else if (isColorSource) {
current = null
one.source = ""
two.source = ""
} else {
if (current === one)
two.update()
else
one.update()
}
}
onIsColorSourceChanged: {
if (isColorSource) {
current = null
one.source = ""
two.source = ""
} else if (source) {
if (current === one)
two.update()
else
one.update()
}
}
Loader {
anchors.fill: parent
active: !root.source
active: !root.source || root.isColorSource
asynchronous: true
sourceComponent: DankBackdrop {}

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
@@ -29,56 +29,56 @@ Singleton {
let score = 0
let matched = false
// Exact name match - highest priority
const nameWords = name.trim().split(/\s+/).filter(w => w.length > 0)
const containsAsWord = nameWords.includes(queryLower)
const startsWithAsWord = nameWords.some(word => word.startsWith(queryLower))
if (name === queryLower) {
score = 1000
score = 10000
matched = true
}
else if (containsAsWord) {
score = 9500 + (100 - Math.min(name.length, 100))
matched = true
}
// Name starts with query
else if (name.startsWith(queryLower)) {
score = 900 - name.length
score = 9000 + (100 - Math.min(name.length, 100))
matched = true
}
// Name contains query as a word
else if (name.includes(" " + queryLower) || name.includes(queryLower + " ")) {
score = 800 - name.length
else if (startsWithAsWord) {
score = 8500 + (100 - Math.min(name.length, 100))
matched = true
}
// Name contains query substring
else if (name.includes(queryLower)) {
score = 700 - name.length
score = 8000 + (100 - Math.min(name.length, 100))
matched = true
}
// Check individual keywords
else if (keywords.length > 0) {
for (const keyword of keywords) {
if (keyword === queryLower) {
score = 650 // Exact keyword match
score = 6000
matched = true
break
} else if (keyword.startsWith(queryLower)) {
score = 620 // Keyword starts with query
score = 5500
matched = true
break
} else if (keyword.includes(queryLower)) {
score = 600 // Keyword contains query
score = 5000
matched = true
break
}
}
}
// Generic name matches
if (!matched && genericName.includes(queryLower)) {
score = 500
score = 4000
matched = true
}
// Comment contains query
else if (!matched && comment.includes(queryLower)) {
score = 400
score = 3000
matched = true
}
// Fuzzy match on name only (not on all fields)
else {
else if (!matched) {
const nameFinder = new Fzf.Finder([app], {
"selector": a => a.name || "",
"casing": "case-insensitive",
@@ -86,7 +86,7 @@ Singleton {
})
const fuzzyResults = nameFinder.find(query)
if (fuzzyResults.length > 0 && fuzzyResults[0].score > 0) {
score = fuzzyResults[0].score
score = Math.min(fuzzyResults[0].score, 2000)
matched = true
}
}
@@ -96,10 +96,7 @@ Singleton {
}
}
// Sort by score descending
scoredApps.sort((a, b) => b.score - a.score)
// Return top results
return scoredApps.slice(0, 50).map(item => item.app)
}

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell

View File

@@ -6,9 +6,11 @@ Item {
anchors.fill: parent
property bool isColorWallpaper: SessionData.wallpaperPath && SessionData.wallpaperPath.startsWith("#")
Rectangle {
anchors.fill: parent
color: Theme.background
color: isColorWallpaper ? SessionData.wallpaperPath : Theme.background
}
Rectangle {
@@ -18,6 +20,7 @@ Item {
height: parent.height * 1.5
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15)
rotation: 35
visible: !isColorWallpaper
}
Rectangle {
@@ -27,6 +30,7 @@ Item {
height: parent.height * 1.2
color: Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.12)
rotation: 35
visible: !isColorWallpaper
}
Item {
@@ -35,16 +39,18 @@ Item {
anchors.leftMargin: Theme.spacingXL * 2
anchors.bottomMargin: Theme.spacingXL * 2
opacity: 0.25
visible: !isColorWallpaper
StyledText {
anchors.left: parent.left
anchors.bottom: parent.bottom
// ! TODO qmlfmt will brick this
text: `
`
`
isMonospace: true
font.pixelSize: Theme.fontSizeLarge * 1.2
color: Theme.primary

117
Widgets/DankColorPicker.qml Normal file
View File

@@ -0,0 +1,117 @@
import QtQuick
import qs.Common
import qs.Widgets
Rectangle {
id: root
property string pickerTitle: "Choose Color"
property color selectedColor: Theme.primary
property bool isOpen: false
signal colorSelected(color selectedColor)
function open() {
customColorField.text = ""
isOpen = true
Qt.callLater(() => root.forceActiveFocus())
}
function close() {
isOpen = false
}
anchors.centerIn: parent
width: 320
height: 340
radius: Theme.cornerRadius
color: Theme.surfaceContainer
border.color: Theme.outlineMedium
border.width: 1
z: 1000
visible: isOpen
focus: isOpen
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
close()
event.accepted = true
}
}
DankActionButton {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Theme.spacingS
buttonSize: 28
iconName: "close"
iconSize: 16
iconColor: Theme.surfaceText
onClicked: root.close()
}
Column {
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
StyledText {
text: pickerTitle
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
Grid {
columns: 8
spacing: 4
anchors.horizontalCenter: parent.horizontalCenter
property var colors: ["#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#03a9f4", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#795548", "#9e9e9e", "#607d8b", "#000000", "#ffffff", "#ff1744", "#f50057", "#d500f9", "#651fff", "#3d5afe", "#2979ff", "#00b0ff", "#00e5ff", "#1de9b6", "#00e676", "#76ff03", "#c6ff00", "#ffff00", "#ffc400", "#ff9100", "#ff3d00", "#bf360c", "#424242", "#37474f"]
Repeater {
model: parent.colors
Rectangle {
width: 24
height: 24
color: modelData
radius: 4
border.color: Theme.outline
border.width: root.selectedColor == modelData ? 2 : 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.selectedColor = modelData
root.colorSelected(modelData)
root.close()
}
}
}
}
}
StyledText {
text: "Custom Color:"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
}
DankTextField {
id: customColorField
width: parent.width
height: 40
placeholderText: "#ff0000"
text: ""
onAccepted: {
var hexColor = text.startsWith("#") ? text : "#" + text
if (/^#[0-9A-Fa-f]{6}$/.test(hexColor)) {
root.selectedColor = hexColor
root.colorSelected(hexColor)
root.close()
}
}
}
}
}