1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-15 10:12:07 -04:00

replace qmlformat with a better tool

still not perfect, but well - what can ya do
This commit is contained in:
bbedward
2025-08-08 15:55:37 -04:00
parent 8dc6e2805d
commit 4d408c65f2
137 changed files with 30315 additions and 29625 deletions

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick import QtQuick
import Quickshell import Quickshell
@@ -13,10 +14,7 @@ Singleton {
readonly property int slidePx: 80 readonly property int slidePx: 80
readonly property var emphasized: [ readonly property var emphasized: [0.05, 0.00, 0.133333, 0.06, 0.166667, 0.40, 0.208333, 0.82, 0.25, 1.00, 1.00, 1.00]
0.05, 0.00, 0.133333, 0.06, 0.166667, 0.40,
0.208333, 0.82, 0.25, 1.00, 1.00, 1.00
]
readonly property var emphasizedDecel: [0.05, 0.70, 0.10, 1.00, 1.00, 1.00] readonly property var emphasizedDecel: [0.05, 0.70, 0.10, 1.00, 1.00, 1.00]

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtCore import QtCore
import QtQuick import QtQuick
@@ -10,47 +11,52 @@ Singleton {
id: root id: root
property var appUsageRanking: {} property var appUsageRanking: {
}
Component.onCompleted: { Component.onCompleted: {
loadSettings(); loadSettings()
} }
function loadSettings() { function loadSettings() {
parseSettings(settingsFile.text()); parseSettings(settingsFile.text())
} }
function parseSettings(content) { function parseSettings(content) {
try { try {
if (content && content.trim()) { if (content && content.trim()) {
var settings = JSON.parse(content); var settings = JSON.parse(content)
appUsageRanking = settings.appUsageRanking || {}; appUsageRanking = settings.appUsageRanking || {}
} }
} catch (e) { } catch (e) {
} }
} }
function saveSettings() { function saveSettings() {
settingsFile.setText(JSON.stringify({ settingsFile.setText(JSON.stringify({
"appUsageRanking": appUsageRanking "appUsageRanking": appUsageRanking
}, null, 2)); }, null, 2))
} }
function addAppUsage(app) { function addAppUsage(app) {
if (!app) if (!app)
return; return
var appId = app.id || (app.execString || app.exec || ""); var appId = app.id || (app.execString || app.exec || "")
if (!appId) if (!appId)
return; return
var currentRanking = Object.assign({}, appUsageRanking); var currentRanking = Object.assign({}, appUsageRanking)
if (currentRanking[appId]) { if (currentRanking[appId]) {
currentRanking[appId].usageCount = (currentRanking[appId].usageCount || 1) + 1; currentRanking[appId].usageCount = (currentRanking[appId].usageCount
currentRanking[appId].lastUsed = Date.now(); || 1) + 1
currentRanking[appId].icon = app.icon || currentRanking[appId].icon || "application-x-executable"; currentRanking[appId].lastUsed = Date.now()
currentRanking[appId].name = app.name || currentRanking[appId].name || ""; currentRanking[appId].icon = app.icon || currentRanking[appId].icon
|| "application-x-executable"
currentRanking[appId].name = app.name || currentRanking[appId].name || ""
} else { } else {
currentRanking[appId] = { currentRanking[appId] = {
"name": app.name || "", "name": app.name || "",
@@ -59,67 +65,67 @@ Singleton {
"comment": app.comment || "", "comment": app.comment || "",
"usageCount": 1, "usageCount": 1,
"lastUsed": Date.now() "lastUsed": Date.now()
}; }
} }
appUsageRanking = currentRanking; appUsageRanking = currentRanking
saveSettings(); saveSettings()
} }
function getAppUsageRanking() { function getAppUsageRanking() {
return appUsageRanking; return appUsageRanking
} }
function getRankedApps() { function getRankedApps() {
var apps = []; var apps = []
for (var appId in appUsageRanking) { for (var appId in appUsageRanking) {
var appData = appUsageRanking[appId]; var appData = appUsageRanking[appId]
apps.push({ apps.push({
id: appId, "id": appId,
name: appData.name, "name": appData.name,
exec: appData.exec, "exec": appData.exec,
icon: appData.icon, "icon": appData.icon,
comment: appData.comment, "comment": appData.comment,
usageCount: appData.usageCount, "usageCount": appData.usageCount,
lastUsed: appData.lastUsed "lastUsed": appData.lastUsed
}); })
} }
return apps.sort(function (a, b) { return apps.sort(function (a, b) {
if (a.usageCount !== b.usageCount) if (a.usageCount !== b.usageCount)
return b.usageCount - a.usageCount; return b.usageCount - a.usageCount
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name)
}); })
} }
function cleanupAppUsageRanking(availableAppIds) { function cleanupAppUsageRanking(availableAppIds) {
var currentRanking = Object.assign({}, appUsageRanking); var currentRanking = Object.assign({}, appUsageRanking)
var hasChanges = false; var hasChanges = false
for (var appId in currentRanking) { for (var appId in currentRanking) {
if (availableAppIds.indexOf(appId) === -1) { if (availableAppIds.indexOf(appId) === -1) {
delete currentRanking[appId]; delete currentRanking[appId]
hasChanges = true; hasChanges = true
} }
} }
if (hasChanges) { if (hasChanges) {
appUsageRanking = currentRanking; appUsageRanking = currentRanking
saveSettings(); saveSettings()
} }
} }
FileView { FileView {
id: settingsFile id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/appusage.json" path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/appusage.json"
blockLoading: true blockLoading: true
blockWrites: true blockWrites: true
watchChanges: true watchChanges: true
onLoaded: { onLoaded: {
parseSettings(settingsFile.text()); parseSettings(settingsFile.text())
}
onLoadFailed: (error) => {
} }
onLoadFailed: error => {}
} }
} }

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick import QtQuick
import Quickshell import Quickshell
@@ -40,7 +41,8 @@ Singleton {
readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1] readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1]
readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1] readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1] readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1] readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1
/ 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1] readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1] readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
readonly property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1] readonly property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]

View File

@@ -7,18 +7,22 @@ Singleton {
// Clear all image cache // Clear all image cache
function clearImageCache() { function clearImageCache() {
Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)]); Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)])
Paths.mkdir(Paths.imagecache); Paths.mkdir(Paths.imagecache)
} }
// Clear cache older than specified minutes // Clear cache older than specified minutes
function clearOldCache(ageInMinutes) { function clearOldCache(ageInMinutes) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"]); Quickshell.execDetached(
["find", Paths.stringify(
Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"])
} }
// Clear cache for specific size // Clear cache for specific size
function clearCacheForSize(size) { function clearCacheForSize(size) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"]); Quickshell.execDetached(
["find", Paths.stringify(
Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"])
} }
// Get cache size in MB // Get cache size in MB
@@ -26,7 +30,8 @@ Singleton {
var process = Qt.createQmlObject(` var process = Qt.createQmlObject(`
import Quickshell.Io import Quickshell.Io
Process { Process {
command: ["du", "-sm", "${Paths.stringify(Paths.imagecache)}"] command: ["du", "-sm", "${Paths.stringify(
Paths.imagecache)}"]
running: true running: true
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
@@ -35,7 +40,6 @@ Singleton {
} }
} }
} }
`, root); `, root)
} }
} }

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import Qt.labs.platform import Qt.labs.platform
import QtQuick import QtQuick
@@ -11,11 +12,18 @@ import qs.Common
Singleton { Singleton {
id: root id: root
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation) readonly property string _homeUrl: StandardPaths.writableLocation(
readonly property string homeDir: _homeUrl.startsWith("file://") ? _homeUrl.substring(7) : _homeUrl StandardPaths.HomeLocation)
readonly property string _configUrl: StandardPaths.writableLocation(StandardPaths.ConfigLocation) readonly property string homeDir: _homeUrl.startsWith(
readonly property string configDir: _configUrl.startsWith("file://") ? _configUrl.substring(7) : _configUrl "file://") ? _homeUrl.substring(
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Common/", "") 7) : _homeUrl
readonly property string _configUrl: StandardPaths.writableLocation(
StandardPaths.ConfigLocation)
readonly property string configDir: _configUrl.startsWith(
"file://") ? _configUrl.substring(
7) : _configUrl
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace(
"file://", "").replace("/Common/", "")
readonly property string wallpaperPath: SessionData.wallpaperPath readonly property string wallpaperPath: SessionData.wallpaperPath
property bool matugenAvailable: false property bool matugenAvailable: false
property bool gtkThemingEnabled: false property bool gtkThemingEnabled: false
@@ -29,18 +37,23 @@ Singleton {
property color primary: getMatugenColor("primary", "#42a5f5") property color primary: getMatugenColor("primary", "#42a5f5")
property color secondary: getMatugenColor("secondary", "#8ab4f8") property color secondary: getMatugenColor("secondary", "#8ab4f8")
property color tertiary: getMatugenColor("tertiary", "#bb86fc") property color tertiary: getMatugenColor("tertiary", "#bb86fc")
property color tertiaryContainer: getMatugenColor("tertiary_container", "#3700b3") property color tertiaryContainer: getMatugenColor("tertiary_container",
"#3700b3")
property color error: getMatugenColor("error", "#cf6679") property color error: getMatugenColor("error", "#cf6679")
property color inversePrimary: getMatugenColor("inverse_primary", "#6200ea") property color inversePrimary: getMatugenColor("inverse_primary", "#6200ea")
property color bg: getMatugenColor("background", "#1a1c1e") property color bg: getMatugenColor("background", "#1a1c1e")
property color surface: getMatugenColor("surface", "#1a1c1e") property color surface: getMatugenColor("surface", "#1a1c1e")
property color surfaceContainer: getMatugenColor("surface_container", "#1e2023") property color surfaceContainer: getMatugenColor("surface_container",
property color surfaceContainerHigh: getMatugenColor("surface_container_high", "#292b2f") "#1e2023")
property color surfaceContainerHigh: getMatugenColor(
"surface_container_high", "#292b2f")
property color surfaceVariant: getMatugenColor("surface_variant", "#44464f") property color surfaceVariant: getMatugenColor("surface_variant", "#44464f")
property color surfaceText: getMatugenColor("on_background", "#e3e8ef") property color surfaceText: getMatugenColor("on_background", "#e3e8ef")
property color primaryText: getMatugenColor("on_primary", "#ffffff") property color primaryText: getMatugenColor("on_primary", "#ffffff")
property color surfaceVariantText: getMatugenColor("on_surface_variant", "#c4c7c5") property color surfaceVariantText: getMatugenColor("on_surface_variant",
property color primaryContainer: getMatugenColor("primary_container", "#1976d2") "#c4c7c5")
property color primaryContainer: getMatugenColor("primary_container",
"#1976d2")
property color surfaceTint: getMatugenColor("surface_tint", "#8ab4f8") property color surfaceTint: getMatugenColor("surface_tint", "#8ab4f8")
property color outline: getMatugenColor("outline", "#8e918f") property color outline: getMatugenColor("outline", "#8e918f")
property color accentHi: primary property color accentHi: primary
@@ -50,46 +63,48 @@ Singleton {
function onLightModeChanged() { function onLightModeChanged() {
if (matugenColors && Object.keys(matugenColors).length > 0) { if (matugenColors && Object.keys(matugenColors).length > 0) {
colorUpdateTrigger++; colorUpdateTrigger++
colorsUpdated(); colorsUpdated()
if (typeof Theme !== "undefined" && Theme.isDynamicTheme) { if (typeof Theme !== "undefined" && Theme.isDynamicTheme) {
generateSystemThemes(); generateSystemThemes()
} }
} }
} }
function extractColors() { function extractColors() {
extractionRequested = true; extractionRequested = true
if (matugenAvailable) if (matugenAvailable)
fileChecker.running = true; fileChecker.running = true
else else
matugenCheck.running = true; matugenCheck.running = true
} }
function getMatugenColor(path, fallback) { function getMatugenColor(path, fallback) {
colorUpdateTrigger; colorUpdateTrigger
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark"; const colorMode = (typeof SessionData !== "undefined"
let cur = matugenColors && matugenColors.colors && matugenColors.colors[colorMode]; && SessionData.isLightMode) ? "light" : "dark"
let cur = matugenColors && matugenColors.colors
&& matugenColors.colors[colorMode]
for (const part of path.split(".")) { for (const part of path.split(".")) {
if (!cur || typeof cur !== "object" || !(part in cur)) if (!cur || typeof cur !== "object" || !(part in cur))
return fallback; return fallback
cur = cur[part]; cur = cur[part]
} }
return cur || fallback; return cur || fallback
} }
function isColorDark(c) { function isColorDark(c) {
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5; return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5
} }
Component.onCompleted: { Component.onCompleted: {
matugenCheck.running = true; matugenCheck.running = true
checkGtkThemingAvailability(); checkGtkThemingAvailability()
checkQtThemingAvailability(); checkQtThemingAvailability()
if (typeof SessionData !== "undefined") if (typeof SessionData !== "undefined")
SessionData.isLightModeChanged.connect(root.onLightModeChanged); SessionData.isLightModeChanged.connect(root.onLightModeChanged)
} }
Process { Process {
@@ -97,14 +112,14 @@ Singleton {
command: ["which", "matugen"] command: ["which", "matugen"]
onExited: code => { onExited: code => {
matugenAvailable = (code === 0); matugenAvailable = (code === 0)
if (!matugenAvailable) { if (!matugenAvailable) {
ToastService.wallpaperErrorStatus = "matugen_missing"; ToastService.wallpaperErrorStatus = "matugen_missing"
ToastService.showWarning("matugen not found - dynamic theming disabled"); ToastService.showWarning("matugen not found - dynamic theming disabled")
return; return
} }
if (extractionRequested) { if (extractionRequested) {
fileChecker.running = true; fileChecker.running = true
} }
} }
} }
@@ -115,10 +130,10 @@ Singleton {
command: ["test", "-r", wallpaperPath] command: ["test", "-r", wallpaperPath]
onExited: code => { onExited: code => {
if (code === 0) { if (code === 0) {
matugenProcess.running = true; matugenProcess.running = true
} else { } else {
ToastService.wallpaperErrorStatus = "error"; ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper processing failed"); ToastService.showError("Wallpaper processing failed")
} }
} }
} }
@@ -132,21 +147,21 @@ Singleton {
id: matugenCollector id: matugenCollector
onStreamFinished: { onStreamFinished: {
const out = matugenCollector.text; const out = matugenCollector.text
if (!out.length) { if (!out.length) {
ToastService.wallpaperErrorStatus = "error"; ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed"); ToastService.showError("Wallpaper Processing Failed")
return; return
} }
try { try {
root.matugenJson = out; root.matugenJson = out
root.matugenColors = JSON.parse(out); root.matugenColors = JSON.parse(out)
root.colorsUpdated(); root.colorsUpdated()
generateAppConfigs(); generateAppConfigs()
ToastService.clearWallpaperError(); ToastService.clearWallpaperError()
} catch (e) { } catch (e) {
ToastService.wallpaperErrorStatus = "error"; ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed"); ToastService.showError("Wallpaper Processing Failed")
} }
} }
} }
@@ -158,28 +173,30 @@ Singleton {
function generateAppConfigs() { function generateAppConfigs() {
if (!matugenColors || !matugenColors.colors) { if (!matugenColors || !matugenColors.colors) {
return; return
} }
generateNiriConfig(); generateNiriConfig()
generateGhosttyConfig(); generateGhosttyConfig()
if (gtkThemingEnabled && typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) { if (gtkThemingEnabled && typeof SettingsData !== "undefined"
generateSystemThemes(); && SettingsData.gtkThemingEnabled) {
} else if (qtThemingEnabled && typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) { generateSystemThemes()
generateSystemThemes(); } else if (qtThemingEnabled && typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) {
generateSystemThemes()
} }
} }
function generateNiriConfig() { function generateNiriConfig() {
var dark = matugenColors.colors.dark; var dark = matugenColors.colors.dark
if (!dark) if (!dark)
return; return
var bg = dark.background || "#1a1c1e"; var bg = dark.background || "#1a1c1e"
var primary = dark.primary || "#42a5f5"; var primary = dark.primary || "#42a5f5"
var secondary = dark.secondary || "#8ab4f8"; var secondary = dark.secondary || "#8ab4f8"
var inverse = dark.inverse_primary || "#6200ea"; var inverse = dark.inverse_primary || "#6200ea"
var content = `layout { var content = `layout {
border { border {
@@ -190,34 +207,35 @@ Singleton {
active-color "${inverse}" active-color "${inverse}"
} }
background-color "${bg}" background-color "${bg}"
}`; }`
Quickshell.execDetached(["bash", "-c", `echo '${content}' > niri-colors.generated.kdl`]); Quickshell.execDetached(
["bash", "-c", `echo '${content}' > niri-colors.generated.kdl`])
} }
function generateGhosttyConfig() { function generateGhosttyConfig() {
var dark = matugenColors.colors.dark; var dark = matugenColors.colors.dark
var light = matugenColors.colors.light; var light = matugenColors.colors.light
if (!dark || !light) if (!dark || !light)
return; return
var bg = dark.background || "#1a1c1e"; var bg = dark.background || "#1a1c1e"
var fg = dark.on_background || "#e3e8ef"; var fg = dark.on_background || "#e3e8ef"
var primary = dark.primary || "#42a5f5"; var primary = dark.primary || "#42a5f5"
var secondary = dark.secondary || "#8ab4f8"; var secondary = dark.secondary || "#8ab4f8"
var tertiary = dark.tertiary || "#bb86fc"; var tertiary = dark.tertiary || "#bb86fc"
var tertiary_ctr = dark.tertiary_container || "#3700b3"; var tertiary_ctr = dark.tertiary_container || "#3700b3"
var error = dark.error || "#cf6679"; var error = dark.error || "#cf6679"
var inverse = dark.inverse_primary || "#6200ea"; var inverse = dark.inverse_primary || "#6200ea"
var bg_b = light.background || "#fef7ff"; var bg_b = light.background || "#fef7ff"
var fg_b = light.on_background || "#1d1b20"; var fg_b = light.on_background || "#1d1b20"
var primary_b = light.primary || "#1976d2"; var primary_b = light.primary || "#1976d2"
var secondary_b = light.secondary || "#1565c0"; var secondary_b = light.secondary || "#1565c0"
var tertiary_b = light.tertiary || "#7b1fa2"; var tertiary_b = light.tertiary || "#7b1fa2"
var tertiary_ctr_b = light.tertiary_container || "#e1bee7"; var tertiary_ctr_b = light.tertiary_container || "#e1bee7"
var error_b = light.error || "#b00020"; var error_b = light.error || "#b00020"
var inverse_b = light.inverse_primary || "#bb86fc"; var inverse_b = light.inverse_primary || "#bb86fc"
var content = `background = ${bg} var content = `background = ${bg}
foreground = ${fg} foreground = ${fg}
@@ -239,66 +257,76 @@ palette = 11=${secondary_b}
palette = 12=${primary_b} palette = 12=${primary_b}
palette = 13=${tertiary_ctr_b} palette = 13=${tertiary_ctr_b}
palette = 14=${inverse_b} palette = 14=${inverse_b}
palette = 15=${fg_b}`; palette = 15=${fg_b}`
var ghosttyConfigDir = configDir + "/ghostty"; var ghosttyConfigDir = configDir + "/ghostty"
var ghosttyConfigPath = ghosttyConfigDir + "/config-dankcolors"; var ghosttyConfigPath = ghosttyConfigDir + "/config-dankcolors"
Quickshell.execDetached(["bash", "-c", `mkdir -p '${ghosttyConfigDir}' && echo '${content}' > '${ghosttyConfigPath}'`]); Quickshell.execDetached(
["bash", "-c", `mkdir -p '${ghosttyConfigDir}' && echo '${content}' > '${ghosttyConfigPath}'`])
} }
function checkGtkThemingAvailability() { function checkGtkThemingAvailability() {
gtkAvailabilityChecker.running = true; gtkAvailabilityChecker.running = true
} }
function checkQtThemingAvailability() { function checkQtThemingAvailability() {
qtAvailabilityChecker.running = true; qtAvailabilityChecker.running = true
} }
function generateSystemThemes() { function generateSystemThemes() {
if (systemThemeGenerationInProgress) { if (systemThemeGenerationInProgress) {
return; return
} }
if (!matugenAvailable) { if (!matugenAvailable) {
return; return
} }
if (!wallpaperPath || wallpaperPath === "") { if (!wallpaperPath || wallpaperPath === "") {
return; return
} }
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false"; const isLight = (typeof SessionData !== "undefined"
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"; && SessionData.isLightMode) ? "true" : "false"
const gtkTheming = (typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) ? "true" : "false"; const iconTheme = (typeof SettingsData !== "undefined"
const qtTheming = (typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) ? "true" : "false"; && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
const gtkTheming = (typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) ? "true" : "false"
const qtTheming = (typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) ? "true" : "false"
systemThemeGenerationInProgress = true; systemThemeGenerationInProgress = true
systemThemeGenerator.command = [shellDir + "/generate-themes.sh", wallpaperPath, shellDir, configDir, "generate", isLight, iconTheme, gtkTheming, qtTheming]; systemThemeGenerator.command = [shellDir + "/generate-themes.sh", wallpaperPath, shellDir, configDir, "generate", isLight, iconTheme, gtkTheming, qtTheming]
systemThemeGenerator.running = true; systemThemeGenerator.running = true
} }
function restoreSystemThemes() { function restoreSystemThemes() {
const shellDir = root.shellDir; const shellDir = root.shellDir
if (!shellDir) { if (!shellDir) {
return; return
} }
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false"; const isLight = (typeof SessionData !== "undefined"
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"; && SessionData.isLightMode) ? "true" : "false"
const gtkTheming = (typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) ? "true" : "false"; const iconTheme = (typeof SettingsData !== "undefined"
const qtTheming = (typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) ? "true" : "false"; && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
const gtkTheming = (typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) ? "true" : "false"
const qtTheming = (typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) ? "true" : "false"
systemThemeRestoreProcess.command = [shellDir + "/generate-themes.sh", "", shellDir, configDir, "restore", isLight, iconTheme, gtkTheming, qtTheming]; systemThemeRestoreProcess.command = [shellDir + "/generate-themes.sh", "", shellDir, configDir, "restore", isLight, iconTheme, gtkTheming, qtTheming]
systemThemeRestoreProcess.running = true; systemThemeRestoreProcess.running = true
} }
Process { Process {
id: gtkAvailabilityChecker id: gtkAvailabilityChecker
command: ["bash", "-c", "command -v gsettings >/dev/null && [ -d " + configDir + "/gtk-3.0 -o -d " + configDir + "/gtk-4.0 ]"] command: ["bash", "-c", "command -v gsettings >/dev/null && [ -d "
+ configDir + "/gtk-3.0 -o -d " + configDir + "/gtk-4.0 ]"]
running: false running: false
onExited: exitCode => { onExited: exitCode => {
gtkThemingEnabled = (exitCode === 0); gtkThemingEnabled = (exitCode === 0)
} }
} }
@@ -307,7 +335,7 @@ palette = 15=${fg_b}`;
command: ["bash", "-c", "command -v qt5ct >/dev/null || command -v qt6ct >/dev/null"] command: ["bash", "-c", "command -v qt5ct >/dev/null || command -v qt6ct >/dev/null"]
running: false running: false
onExited: exitCode => { onExited: exitCode => {
qtThemingEnabled = (exitCode === 0); qtThemingEnabled = (exitCode === 0)
} }
} }
@@ -324,10 +352,11 @@ palette = 15=${fg_b}`;
} }
onExited: exitCode => { onExited: exitCode => {
systemThemeGenerationInProgress = false; systemThemeGenerationInProgress = false
if (exitCode !== 0) { if (exitCode !== 0) {
ToastService.showError("Failed to generate system themes: " + systemThemeStderr.text); ToastService.showError(
"Failed to generate system themes: " + systemThemeStderr.text)
} }
} }
} }
@@ -346,9 +375,10 @@ palette = 15=${fg_b}`;
onExited: exitCode => { onExited: exitCode => {
if (exitCode === 0) { if (exitCode === 0) {
ToastService.showInfo("System themes restored to default"); ToastService.showInfo("System themes restored to default")
} else { } else {
ToastService.showWarning("Failed to restore system themes: " + restoreThemeStderr.text); ToastService.showWarning(
"Failed to restore system themes: " + restoreThemeStderr.text)
} }
} }
} }

View File

@@ -6,37 +6,43 @@ import QtCore
Singleton { Singleton {
id: root id: root
readonly property url home: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0] readonly property url home: StandardPaths.standardLocations(
readonly property url pictures: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] StandardPaths.HomeLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(
StandardPaths.PicturesLocation)[0]
readonly property url data: `${StandardPaths.standardLocations(StandardPaths.GenericDataLocation)[0]}/DankMaterialShell` readonly property url data: `${StandardPaths.standardLocations(
readonly property url state: `${StandardPaths.standardLocations(StandardPaths.GenericStateLocation)[0]}/DankMaterialShell` StandardPaths.GenericDataLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell` readonly property url state: `${StandardPaths.standardLocations(
readonly property url config: `${StandardPaths.standardLocations(StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell` StandardPaths.GenericStateLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(
StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
readonly property url config: `${StandardPaths.standardLocations(
StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url imagecache: `${cache}/imagecache` readonly property url imagecache: `${cache}/imagecache`
function stringify(path: url): string { function stringify(path: url): string {
return path.toString().replace(/%20/g, " "); return path.toString().replace(/%20/g, " ")
} }
function expandTilde(path: string): string { function expandTilde(path: string): string {
return strip(path.replace("~", stringify(root.home))); return strip(path.replace("~", stringify(root.home)))
} }
function shortenHome(path: string): string { function shortenHome(path: string): string {
return path.replace(strip(root.home), "~"); return path.replace(strip(root.home), "~")
} }
function strip(path: url): string { function strip(path: url): string {
return stringify(path).replace("file://", ""); return stringify(path).replace("file://", "")
} }
function mkdir(path: url): void { function mkdir(path: url): void {
Quickshell.execDetached(["mkdir", "-p", strip(path)]); Quickshell.execDetached(["mkdir", "-p", strip(path)])
} }
function copy(from: url, to: url): void { function copy(from: url, to: url): void {
Quickshell.execDetached(["cp", strip(from), strip(to)]); Quickshell.execDetached(["cp", strip(from), strip(to)])
} }
} }

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtCore import QtCore
import QtQuick import QtQuick
@@ -18,25 +19,27 @@ Singleton {
property var pinnedApps: [] property var pinnedApps: []
Component.onCompleted: { Component.onCompleted: {
loadSettings(); loadSettings()
} }
function loadSettings() { function loadSettings() {
parseSettings(settingsFile.text()); parseSettings(settingsFile.text())
} }
function parseSettings(content) { function parseSettings(content) {
try { try {
if (content && content.trim()) { if (content && content.trim()) {
var settings = JSON.parse(content); var settings = JSON.parse(content)
isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false; isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false
wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : ""; wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : ""
wallpaperLastPath = settings.wallpaperLastPath !== undefined ? settings.wallpaperLastPath : ""; wallpaperLastPath = settings.wallpaperLastPath
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""; !== undefined ? settings.wallpaperLastPath : ""
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false; profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : []; doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : []
} }
} catch (e) { } catch (e) {
} }
} }
@@ -48,79 +51,82 @@ Singleton {
"profileLastPath": profileLastPath, "profileLastPath": profileLastPath,
"doNotDisturb": doNotDisturb, "doNotDisturb": doNotDisturb,
"pinnedApps": pinnedApps "pinnedApps": pinnedApps
}, null, 2)); }, null, 2))
} }
function setLightMode(lightMode) { function setLightMode(lightMode) {
isLightMode = lightMode; isLightMode = lightMode
saveSettings(); saveSettings()
} }
function setDoNotDisturb(enabled) { function setDoNotDisturb(enabled) {
doNotDisturb = enabled; doNotDisturb = enabled
saveSettings(); saveSettings()
} }
function setWallpaperPath(path) { function setWallpaperPath(path) {
wallpaperPath = path; wallpaperPath = path
saveSettings(); saveSettings()
} }
function setWallpaper(imagePath) { function setWallpaper(imagePath) {
wallpaperPath = imagePath; wallpaperPath = imagePath
saveSettings(); saveSettings()
if (typeof Colors !== "undefined" && typeof SettingsData !== "undefined" && SettingsData.wallpaperDynamicTheming) { if (typeof Colors !== "undefined" && typeof SettingsData !== "undefined"
Colors.extractColors(); && SettingsData.wallpaperDynamicTheming) {
Colors.extractColors()
} }
} }
function setWallpaperLastPath(path) { function setWallpaperLastPath(path) {
wallpaperLastPath = path; wallpaperLastPath = path
saveSettings(); saveSettings()
} }
function setProfileLastPath(path) { function setProfileLastPath(path) {
profileLastPath = path; profileLastPath = path
saveSettings(); saveSettings()
} }
function setPinnedApps(apps) { function setPinnedApps(apps) {
pinnedApps = apps; pinnedApps = apps
saveSettings(); saveSettings()
} }
function addPinnedApp(appId) { function addPinnedApp(appId) {
if (!appId) return; if (!appId)
var currentPinned = [...pinnedApps]; return
var currentPinned = [...pinnedApps]
if (currentPinned.indexOf(appId) === -1) { if (currentPinned.indexOf(appId) === -1) {
currentPinned.push(appId); currentPinned.push(appId)
setPinnedApps(currentPinned); setPinnedApps(currentPinned)
} }
} }
function removePinnedApp(appId) { function removePinnedApp(appId) {
if (!appId) return; if (!appId)
var currentPinned = pinnedApps.filter(id => id !== appId); return
setPinnedApps(currentPinned); var currentPinned = pinnedApps.filter(id => id !== appId)
setPinnedApps(currentPinned)
} }
function isPinnedApp(appId) { function isPinnedApp(appId) {
return appId && pinnedApps.indexOf(appId) !== -1; return appId && pinnedApps.indexOf(appId) !== -1
} }
FileView { FileView {
id: settingsFile id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json" path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: true blockLoading: true
blockWrites: true blockWrites: true
watchChanges: true watchChanges: true
onLoaded: { onLoaded: {
parseSettings(settingsFile.text()); parseSettings(settingsFile.text())
}
onLoadFailed: (error) => {
} }
onLoadFailed: error => {}
} }
IpcHandler { IpcHandler {
@@ -135,7 +141,9 @@ Singleton {
return "ERROR: No path provided" 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 { try {
root.setWallpaper(absolutePath) root.setWallpaper(absolutePath)

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick import QtQuick
import Quickshell import Quickshell
@@ -334,20 +335,34 @@ Singleton {
property int currentThemeIndex: 0 property int currentThemeIndex: 0
property bool isDynamicTheme: false property bool isDynamicTheme: false
property bool isLightMode: false property bool isLightMode: false
property color primary: isDynamicTheme ? Colors.accentHi : getCurrentTheme().primary property color primary: isDynamicTheme ? Colors.accentHi : getCurrentTheme(
property color primaryText: isDynamicTheme ? Colors.primaryText : getCurrentTheme().primaryText ).primary
property color primaryContainer: isDynamicTheme ? Colors.primaryContainer : getCurrentTheme().primaryContainer property color primaryText: isDynamicTheme ? Colors.primaryText : getCurrentTheme(
property color secondary: isDynamicTheme ? Colors.accentLo : getCurrentTheme().secondary ).primaryText
property color surface: isDynamicTheme ? Colors.surface : getCurrentTheme().surface property color primaryContainer: isDynamicTheme ? Colors.primaryContainer : getCurrentTheme(
property color surfaceText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme().surfaceText ).primaryContainer
property color surfaceVariant: isDynamicTheme ? Colors.surfaceVariant : getCurrentTheme().surfaceVariant property color secondary: isDynamicTheme ? Colors.accentLo : getCurrentTheme(
property color surfaceVariantText: isDynamicTheme ? Colors.surfaceVariantText : getCurrentTheme().surfaceVariantText ).secondary
property color surfaceTint: isDynamicTheme ? Colors.surfaceTint : getCurrentTheme().surfaceTint property color surface: isDynamicTheme ? Colors.surface : getCurrentTheme(
property color background: isDynamicTheme ? Colors.bg : getCurrentTheme().background ).surface
property color backgroundText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme().backgroundText property color surfaceText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme(
property color outline: isDynamicTheme ? Colors.outline : getCurrentTheme().outline ).surfaceText
property color surfaceContainer: isDynamicTheme ? Colors.surfaceContainer : getCurrentTheme().surfaceContainer property color surfaceVariant: isDynamicTheme ? Colors.surfaceVariant : getCurrentTheme(
property color surfaceContainerHigh: isDynamicTheme ? Colors.surfaceContainerHigh : getCurrentTheme().surfaceContainerHigh ).surfaceVariant
property color surfaceVariantText: isDynamicTheme ? Colors.surfaceVariantText : getCurrentTheme(
).surfaceVariantText
property color surfaceTint: isDynamicTheme ? Colors.surfaceTint : getCurrentTheme(
).surfaceTint
property color background: isDynamicTheme ? Colors.bg : getCurrentTheme(
).background
property color backgroundText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme(
).backgroundText
property color outline: isDynamicTheme ? Colors.outline : getCurrentTheme(
).outline
property color surfaceContainer: isDynamicTheme ? Colors.surfaceContainer : getCurrentTheme(
).surfaceContainer
property color surfaceContainerHigh: isDynamicTheme ? Colors.surfaceContainerHigh : getCurrentTheme(
).surfaceContainerHigh
property color archBlue: "#1793D1" property color archBlue: "#1793D1"
property color success: "#4CAF50" property color success: "#4CAF50"
property color warning: "#FF9800" property color warning: "#FF9800"
@@ -359,23 +374,37 @@ Singleton {
property color tempDanger: "#ff5555" // Balanced red for dangerous temperatures property color tempDanger: "#ff5555" // Balanced red for dangerous temperatures
property color primaryHover: Qt.rgba(primary.r, primary.g, primary.b, 0.12) property color primaryHover: Qt.rgba(primary.r, primary.g, primary.b, 0.12)
property color primaryHoverLight: Qt.rgba(primary.r, primary.g, primary.b, 0.08) property color primaryHoverLight: Qt.rgba(primary.r, primary.g,
primary.b, 0.08)
property color primaryPressed: Qt.rgba(primary.r, primary.g, primary.b, 0.16) property color primaryPressed: Qt.rgba(primary.r, primary.g, primary.b, 0.16)
property color primarySelected: Qt.rgba(primary.r, primary.g, primary.b, 0.3) property color primarySelected: Qt.rgba(primary.r, primary.g, primary.b, 0.3)
property color primaryBackground: Qt.rgba(primary.r, primary.g, primary.b, 0.04) property color primaryBackground: Qt.rgba(primary.r, primary.g,
primary.b, 0.04)
property color secondaryHover: Qt.rgba(secondary.r, secondary.g, secondary.b, 0.08) property color secondaryHover: Qt.rgba(secondary.r, secondary.g,
secondary.b, 0.08)
property color surfaceHover: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.08) property color surfaceHover: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
property color surfacePressed: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.12) surfaceVariant.b, 0.08)
property color surfaceSelected: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.15) property color surfacePressed: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
property color surfaceLight: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.1) surfaceVariant.b, 0.12)
property color surfaceVariantAlpha: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.2) property color surfaceSelected: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
property color surfaceTextHover: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.08) surfaceVariant.b, 0.15)
property color surfaceTextPressed: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.12) property color surfaceLight: Qt.rgba(surfaceVariant.r, surfaceVariant.g,
property color surfaceTextAlpha: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.3) surfaceVariant.b, 0.1)
property color surfaceTextLight: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.06) property color surfaceVariantAlpha: Qt.rgba(surfaceVariant.r,
property color surfaceTextMedium: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.7) surfaceVariant.g,
surfaceVariant.b, 0.2)
property color surfaceTextHover: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.08)
property color surfaceTextPressed: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.12)
property color surfaceTextAlpha: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.3)
property color surfaceTextLight: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.06)
property color surfaceTextMedium: Qt.rgba(surfaceText.r, surfaceText.g,
surfaceText.b, 0.7)
property color outlineLight: Qt.rgba(outline.r, outline.g, outline.b, 0.05) property color outlineLight: Qt.rgba(outline.r, outline.g, outline.b, 0.05)
property color outlineMedium: Qt.rgba(outline.r, outline.g, outline.b, 0.08) property color outlineMedium: Qt.rgba(outline.r, outline.g, outline.b, 0.08)
@@ -426,196 +455,200 @@ Singleton {
function onColorsUpdated() { function onColorsUpdated() {
if (isDynamicTheme) { if (isDynamicTheme) {
currentThemeIndex = 10; currentThemeIndex = 10
isDynamicTheme = true; isDynamicTheme = true
if (typeof SettingsData !== "undefined") if (typeof SettingsData !== "undefined")
SettingsData.setTheme(currentThemeIndex, isDynamicTheme); SettingsData.setTheme(currentThemeIndex, isDynamicTheme)
} }
} }
function switchTheme(themeIndex, isDynamic = false, savePrefs = true) { function switchTheme(themeIndex, isDynamic = false, savePrefs = true) {
if (isDynamic && themeIndex === 10) { if (isDynamic && themeIndex === 10) {
isDynamicTheme = true; isDynamicTheme = true
if (typeof Colors !== "undefined") { if (typeof Colors !== "undefined") {
Colors.extractColors(); Colors.extractColors()
} }
} else if (themeIndex >= 0 && themeIndex < themes.length) { } else if (themeIndex >= 0 && themeIndex < themes.length) {
if (isDynamicTheme && typeof Colors !== "undefined") { if (isDynamicTheme && typeof Colors !== "undefined") {
Colors.restoreSystemThemes(); Colors.restoreSystemThemes()
} }
currentThemeIndex = themeIndex; currentThemeIndex = themeIndex
isDynamicTheme = false; isDynamicTheme = false
} }
if (savePrefs && typeof SettingsData !== "undefined") if (savePrefs && typeof SettingsData !== "undefined")
SettingsData.setTheme(currentThemeIndex, isDynamicTheme); SettingsData.setTheme(currentThemeIndex, isDynamicTheme)
} }
function toggleLightMode(savePrefs = true) { function toggleLightMode(savePrefs = true) {
isLightMode = !isLightMode; isLightMode = !isLightMode
if (savePrefs && typeof SessionData !== "undefined") if (savePrefs && typeof SessionData !== "undefined")
SessionData.setLightMode(isLightMode); SessionData.setLightMode(isLightMode)
} }
function getCurrentThemeArray() { function getCurrentThemeArray() {
return isLightMode ? lightThemes : themes; return isLightMode ? lightThemes : themes
} }
function getCurrentTheme() { function getCurrentTheme() {
var themeArray = getCurrentThemeArray(); var themeArray = getCurrentThemeArray()
return currentThemeIndex < themeArray.length ? themeArray[currentThemeIndex] : themeArray[0]; return currentThemeIndex < themeArray.length ? themeArray[currentThemeIndex] : themeArray[0]
} }
function getPopupBackgroundAlpha() { function getPopupBackgroundAlpha() {
return popupTransparency; return popupTransparency
} }
function getContentBackgroundAlpha() { function getContentBackgroundAlpha() {
return popupTransparency; return popupTransparency
} }
function popupBackground() { function popupBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, popupTransparency); return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
popupTransparency)
} }
function contentBackground() { function contentBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, popupTransparency); return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
popupTransparency)
} }
function panelBackground() { function panelBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, panelTransparency); return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
panelTransparency)
} }
function widgetBackground() { function widgetBackground() {
return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b, widgetTransparency); return Qt.rgba(surfaceContainer.r, surfaceContainer.g, surfaceContainer.b,
widgetTransparency)
} }
function getBatteryIcon(level, isCharging, batteryAvailable) { function getBatteryIcon(level, isCharging, batteryAvailable) {
if (!batteryAvailable) if (!batteryAvailable)
return _getBatteryPowerProfileIcon(); return _getBatteryPowerProfileIcon()
if (isCharging) { if (isCharging) {
if (level >= 90) if (level >= 90)
return "battery_charging_full"; return "battery_charging_full"
if (level >= 80) if (level >= 80)
return "battery_charging_90"; return "battery_charging_90"
if (level >= 60) if (level >= 60)
return "battery_charging_80"; return "battery_charging_80"
if (level >= 50) if (level >= 50)
return "battery_charging_60"; return "battery_charging_60"
if (level >= 30) if (level >= 30)
return "battery_charging_50"; return "battery_charging_50"
if (level >= 20) if (level >= 20)
return "battery_charging_30"; return "battery_charging_30"
return "battery_charging_20"; return "battery_charging_20"
} else { } else {
if (level >= 95) if (level >= 95)
return "battery_full"; return "battery_full"
if (level >= 85) if (level >= 85)
return "battery_6_bar"; return "battery_6_bar"
if (level >= 70) if (level >= 70)
return "battery_5_bar"; return "battery_5_bar"
if (level >= 55) if (level >= 55)
return "battery_4_bar"; return "battery_4_bar"
if (level >= 40) if (level >= 40)
return "battery_3_bar"; return "battery_3_bar"
if (level >= 25) if (level >= 25)
return "battery_2_bar"; return "battery_2_bar"
if (level >= 10) if (level >= 10)
return "battery_1_bar"; return "battery_1_bar"
return "battery_alert"; return "battery_alert"
} }
} }
function _getBatteryPowerProfileIcon() { function _getBatteryPowerProfileIcon() {
if (typeof PowerProfiles === "undefined") if (typeof PowerProfiles === "undefined")
return "balance"; return "balance"
switch (PowerProfiles.profile) { switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver: case PowerProfile.PowerSaver:
return "energy_savings_leaf"; return "energy_savings_leaf"
case PowerProfile.Performance: case PowerProfile.Performance:
return "rocket_launch"; return "rocket_launch"
default: default:
return "balance"; return "balance"
} }
} }
function getPowerProfileIcon(profile) { function getPowerProfileIcon(profile) {
switch (profile) { switch (profile) {
case PowerProfile.PowerSaver: case PowerProfile.PowerSaver:
return "battery_saver"; return "battery_saver"
case PowerProfile.Balanced: case PowerProfile.Balanced:
return "battery_std"; return "battery_std"
case PowerProfile.Performance: case PowerProfile.Performance:
return "flash_on"; return "flash_on"
default: default:
return "settings"; return "settings"
} }
} }
function getPowerProfileLabel(profile) { function getPowerProfileLabel(profile) {
switch (profile) { switch (profile) {
case PowerProfile.PowerSaver: case PowerProfile.PowerSaver:
return "Power Saver"; return "Power Saver"
case PowerProfile.Balanced: case PowerProfile.Balanced:
return "Balanced"; return "Balanced"
case PowerProfile.Performance: case PowerProfile.Performance:
return "Performance"; return "Performance"
default: default:
return profile.charAt(0).toUpperCase() + profile.slice(1); return profile.charAt(0).toUpperCase() + profile.slice(1)
} }
} }
function getPowerProfileDescription(profile) { function getPowerProfileDescription(profile) {
switch (profile) { switch (profile) {
case PowerProfile.PowerSaver: case PowerProfile.PowerSaver:
return "Extend battery life"; return "Extend battery life"
case PowerProfile.Balanced: case PowerProfile.Balanced:
return "Balance power and performance"; return "Balance power and performance"
case PowerProfile.Performance: case PowerProfile.Performance:
return "Prioritize performance"; return "Prioritize performance"
default: default:
return "Custom power profile"; return "Custom power profile"
} }
} }
Component.onCompleted: { Component.onCompleted: {
if (typeof Colors !== "undefined") if (typeof Colors !== "undefined")
Colors.colorsUpdated.connect(root.onColorsUpdated); Colors.colorsUpdated.connect(root.onColorsUpdated)
if (typeof SettingsData !== "undefined") { if (typeof SettingsData !== "undefined") {
if (SettingsData.popupTransparency !== undefined) if (SettingsData.popupTransparency !== undefined)
root.popupTransparency = SettingsData.popupTransparency; root.popupTransparency = SettingsData.popupTransparency
if (SettingsData.topBarWidgetTransparency !== undefined) if (SettingsData.topBarWidgetTransparency !== undefined)
root.widgetTransparency = SettingsData.topBarWidgetTransparency; root.widgetTransparency = SettingsData.topBarWidgetTransparency
if (SettingsData.popupTransparencyChanged) if (SettingsData.popupTransparencyChanged)
SettingsData.popupTransparencyChanged.connect(function () { SettingsData.popupTransparencyChanged.connect(function () {
if (typeof SettingsData !== "undefined" && SettingsData.popupTransparency !== undefined) if (typeof SettingsData !== "undefined"
root.popupTransparency = SettingsData.popupTransparency; && SettingsData.popupTransparency !== undefined)
}); root.popupTransparency = SettingsData.popupTransparency
})
if (SettingsData.topBarWidgetTransparencyChanged) if (SettingsData.topBarWidgetTransparencyChanged)
SettingsData.topBarWidgetTransparencyChanged.connect(function () { SettingsData.topBarWidgetTransparencyChanged.connect(function () {
if (typeof SettingsData !== "undefined" && SettingsData.topBarWidgetTransparency !== undefined) if (typeof SettingsData !== "undefined"
root.widgetTransparency = SettingsData.topBarWidgetTransparency; && SettingsData.topBarWidgetTransparency !== undefined)
}); root.widgetTransparency = SettingsData.topBarWidgetTransparency
})
} }
} }
} }

View File

@@ -18,110 +18,109 @@ DankModal {
property string searchText: "" property string searchText: ""
function updateFilteredModel() { function updateFilteredModel() {
filteredClipboardModel.clear(); filteredClipboardModel.clear()
for (let i = 0; i < clipboardModel.count; i++) { for (var i = 0; i < clipboardModel.count; i++) {
const entry = clipboardModel.get(i).entry; const entry = clipboardModel.get(i).entry
if (searchText.trim().length === 0) { if (searchText.trim().length === 0) {
filteredClipboardModel.append({ filteredClipboardModel.append({
"entry": entry "entry": entry
}); })
} else { } else {
const content = getEntryPreview(entry).toLowerCase(); const content = getEntryPreview(entry).toLowerCase()
if (content.includes(searchText.toLowerCase())) if (content.includes(searchText.toLowerCase()))
filteredClipboardModel.append({ filteredClipboardModel.append({
"entry": entry "entry": entry
}); })
} }
} }
clipboardHistoryModal.totalCount = filteredClipboardModel.count; clipboardHistoryModal.totalCount = filteredClipboardModel.count
} }
function toggle() { function toggle() {
if (visible) if (visible)
hide(); hide()
else else
show(); show()
} }
function show() { function show() {
clipboardHistoryModal.visible = true; clipboardHistoryModal.visible = true
initializeThumbnailSystem(); initializeThumbnailSystem()
refreshClipboard(); refreshClipboard()
} }
function hide() { function hide() {
clipboardHistoryModal.visible = false; clipboardHistoryModal.visible = false
clipboardHistoryModal.searchText = ""; clipboardHistoryModal.searchText = ""
cleanupTempFiles(); cleanupTempFiles()
} }
function initializeThumbnailSystem() { function initializeThumbnailSystem() {// No initialization needed - using direct image display
// No initialization needed - using direct image display
} }
function cleanupTempFiles() { function cleanupTempFiles() {
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"]); Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"])
} }
function generateThumbnails() { function generateThumbnails() {// No thumbnail generation needed - using direct image display
// No thumbnail generation needed - using direct image display
} }
function refreshClipboard() { function refreshClipboard() {
clipboardProcess.running = true; clipboardProcess.running = true
} }
function copyEntry(entry) { function copyEntry(entry) {
const entryId = entry.split('\t')[0]; const entryId = entry.split('\t')[0]
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`]); Quickshell.execDetached(
["sh", "-c", `cliphist decode ${entryId} | wl-copy`])
ToastService.showInfo("Copied to clipboard"); ToastService.showInfo("Copied to clipboard")
clipboardHistoryModal.hide(); clipboardHistoryModal.hide()
} }
function deleteEntry(entry) { function deleteEntry(entry) {
deleteProcess.command = ["sh", "-c", `echo '${entry.replace(/'/g, "'\\''")}' | cliphist delete`]; deleteProcess.command = ["sh", "-c", `echo '${entry.replace(
deleteProcess.running = true; /'/g, "'\\''")}' | cliphist delete`]
deleteProcess.running = true
} }
function clearAll() { function clearAll() {
clearProcess.running = true; clearProcess.running = true
} }
function getEntryPreview(entry) { function getEntryPreview(entry) {
let content = entry.replace(/^\s*\d+\s+/, ""); let content = entry.replace(/^\s*\d+\s+/, "")
if (content.includes("image/") || content.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) { if (content.includes("image/") || content.includes("binary data")
const dimensionMatch = content.match(/(\d+)x(\d+)/); || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
const dimensionMatch = content.match(/(\d+)x(\d+)/)
if (dimensionMatch) if (dimensionMatch)
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`; return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i); const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i)
if (typeMatch) if (typeMatch)
return `Image (${typeMatch[1].toUpperCase()})`; return `Image (${typeMatch[1].toUpperCase()})`
return "Image"; return "Image"
} }
if (content.length > 100) if (content.length > 100)
return content.substring(0, 100) + "..."; return content.substring(0, 100) + "..."
return content; return content
} }
function getEntryType(entry) { function getEntryType(entry) {
if (entry.includes("image/") || entry.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry) || /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry)) if (entry.includes("image/") || entry.includes("binary data")
return "image"; || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry)
|| /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
return "image"
if (entry.length > 200) if (entry.length > 200)
return "long_text"; return "long_text"
return "text"; return "text"
} }
visible: false visible: false
width: 650 width: 650
height: 550 height: 550
@@ -132,7 +131,7 @@ DankModal {
borderWidth: 1 borderWidth: 1
enableShadow: true enableShadow: true
onBackgroundClicked: { onBackgroundClicked: {
hide(); hide()
} }
DankModal { DankModal {
@@ -143,7 +142,7 @@ DankModal {
height: 150 height: 150
keyboardFocus: "ondemand" keyboardFocus: "ondemand"
onBackgroundClicked: { onBackgroundClicked: {
showClearConfirmation = false; showClearConfirmation = false
} }
content: Component { content: Component {
@@ -199,7 +198,6 @@ DankModal {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: showClearConfirmation = false onClicked: showClearConfirmation = false
} }
} }
Rectangle { Rectangle {
@@ -223,22 +221,16 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
clearAll(); clearAll()
showClearConfirmation = false; showClearConfirmation = false
hide(); hide()
} }
} }
} }
} }
} }
} }
} }
} }
ListModel { ListModel {
@@ -257,72 +249,64 @@ DankModal {
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
clipboardModel.clear(); clipboardModel.clear()
const lines = text.trim().split('\n'); const lines = text.trim().split('\n')
for (const line of lines) { for (const line of lines) {
if (line.trim().length > 0) if (line.trim().length > 0)
clipboardModel.append({ clipboardModel.append({
"entry": line "entry": line
}); })
} }
updateFilteredModel(); updateFilteredModel()
} }
} }
} }
Process { Process {
id: deleteProcess id: deleteProcess
running: false running: false
onExited: (exitCode) => { onExited: exitCode => {
if (exitCode === 0) if (exitCode === 0)
refreshClipboard(); refreshClipboard()
else else
console.warn("Failed to delete clipboard entry"); console.warn("Failed to delete clipboard entry")
} }
} }
Process { Process {
id: clearProcess id: clearProcess
command: ["cliphist", "wipe"] command: ["cliphist", "wipe"]
running: false running: false
onExited: (exitCode) => { onExited: exitCode => {
if (exitCode === 0) { if (exitCode === 0) {
clipboardModel.clear(); clipboardModel.clear()
filteredClipboardModel.clear(); filteredClipboardModel.clear()
totalCount = 0; totalCount = 0
} else { } else {
} }
} }
} }
IpcHandler { IpcHandler {
function open() { function open() {
clipboardHistoryModal.show(); clipboardHistoryModal.show()
return "CLIPBOARD_OPEN_SUCCESS"; return "CLIPBOARD_OPEN_SUCCESS"
} }
function close() { function close() {
clipboardHistoryModal.hide(); clipboardHistoryModal.hide()
return "CLIPBOARD_CLOSE_SUCCESS"; return "CLIPBOARD_CLOSE_SUCCESS"
} }
function toggle() { function toggle() {
clipboardHistoryModal.toggle(); clipboardHistoryModal.toggle()
return "CLIPBOARD_TOGGLE_SUCCESS"; return "CLIPBOARD_TOGGLE_SUCCESS"
} }
target: "clipboard" target: "clipboard"
@@ -336,8 +320,8 @@ DankModal {
focus: true focus: true
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
hide(); hide()
event.accepted = true; event.accepted = true
} }
} }
@@ -364,7 +348,6 @@ DankModal {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -378,7 +361,7 @@ DankModal {
iconColor: Theme.error iconColor: Theme.error
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: { onClicked: {
showClearConfirmation = true; showClearConfirmation = true
} }
} }
@@ -389,9 +372,7 @@ DankModal {
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: hide() onClicked: hide()
} }
} }
} }
DankTextField { DankTextField {
@@ -402,22 +383,21 @@ DankModal {
leftIconName: "search" leftIconName: "search"
showClearButton: true showClearButton: true
onTextChanged: { onTextChanged: {
clipboardHistoryModal.searchText = text; clipboardHistoryModal.searchText = text
updateFilteredModel(); updateFilteredModel()
} }
Connections { Connections {
function onOpened() { function onOpened() {
searchField.forceActiveFocus(); searchField.forceActiveFocus()
} }
function onDialogClosed() { function onDialogClosed() {
searchField.clearFocus(); searchField.clearFocus()
} }
target: clipboardHistoryModal target: clipboardHistoryModal
} }
} }
Rectangle { Rectangle {
@@ -471,7 +451,8 @@ DankModal {
property alias thumbnailImageSource: thumbnailImageSource property alias thumbnailImageSource: thumbnailImageSource
width: clipboardListView.width width: clipboardListView.width
height: Math.max(entryType === "image" ? 72 : 60, contentText.contentHeight + Theme.spacingL) height: Math.max(entryType === "image" ? 72 : 60,
contentText.contentHeight + Theme.spacingL)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground color: mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground
border.color: Theme.outlineStrong border.color: Theme.outlineStrong
@@ -497,7 +478,6 @@ DankModal {
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.primary color: Theme.primary
} }
} }
Row { Row {
@@ -514,7 +494,8 @@ DankModal {
id: thumbnailImageSource id: thumbnailImageSource
anchors.fill: parent anchors.fill: parent
property string entryId: model.entry.split('\t')[0] property string entryId: model.entry.split('\t')[0]
source: entryType === "image" && imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : "" source: entryType === "image"
&& imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : ""
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
smooth: true smooth: true
cache: true cache: true
@@ -530,7 +511,7 @@ DankModal {
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
imageLoader.imageData = text.trim(); imageLoader.imageData = text.trim()
} }
} }
} }
@@ -542,7 +523,8 @@ DankModal {
source: thumbnailImageSource source: thumbnailImageSource
maskEnabled: true maskEnabled: true
maskSource: clipboardCircularMask maskSource: clipboardCircularMask
visible: entryType === "image" && thumbnailImageSource.status === Image.Ready visible: entryType === "image"
&& thumbnailImageSource.status === Image.Ready
maskThresholdMin: 0.5 maskThresholdMin: 0.5
maskSpreadAtMin: 1 maskSpreadAtMin: 1
} }
@@ -562,41 +544,41 @@ DankModal {
color: "black" color: "black"
antialiasing: true antialiasing: true
} }
} }
DankIcon { DankIcon {
visible: !(entryType === "image" && thumbnailImageSource.status === Image.Ready) visible: !(entryType === "image"
&& thumbnailImageSource.status === Image.Ready)
name: { name: {
if (entryType === "image") if (entryType === "image")
return "image"; return "image"
if (entryType === "long_text") if (entryType === "long_text")
return "subject"; return "subject"
return "content_copy"; return "content_copy"
} }
size: Theme.iconSize size: Theme.iconSize
color: Theme.primary color: Theme.primary
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
Column { Column {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: parent.width - (entryType === "image" ? 48 : Theme.iconSize) - Theme.spacingM width: parent.width - (entryType === "image" ? 48 : Theme.iconSize)
- Theme.spacingM
spacing: Theme.spacingXS spacing: Theme.spacingXS
StyledText { StyledText {
text: { text: {
switch (entryType) { switch (entryType) {
case "image": case "image":
return "Image • " + entryPreview; return "Image • " + entryPreview
case "long_text": case "long_text":
return "Long Text"; return "Long Text"
default: default:
return "Text"; return "Text"
} }
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -617,11 +599,8 @@ DankModal {
maximumLineCount: entryType === "long_text" ? 3 : 1 maximumLineCount: entryType === "long_text" ? 3 : 1
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
} }
} }
DankActionButton { DankActionButton {
@@ -634,7 +613,7 @@ DankModal {
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: { onClicked: {
deleteEntry(model.entry); deleteEntry(model.entry)
} }
} }
@@ -652,17 +631,10 @@ DankModal {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -28,20 +28,20 @@ PanelWindow {
property real cornerRadius: Theme.cornerRadiusLarge property real cornerRadius: Theme.cornerRadiusLarge
property bool enableShadow: false property bool enableShadow: false
signal opened() signal opened
signal dialogClosed() signal dialogClosed
signal backgroundClicked() signal backgroundClicked
function open() { function open() {
visible = true; visible = true
} }
function close() { function close() {
visible = false; visible = false
} }
function toggle() { function toggle() {
visible = !visible; visible = !visible
} }
color: "transparent" color: "transparent"
@@ -50,22 +50,22 @@ PanelWindow {
WlrLayershell.keyboardFocus: { WlrLayershell.keyboardFocus: {
switch (root.keyboardFocus) { switch (root.keyboardFocus) {
case "exclusive": case "exclusive":
return WlrKeyboardFocus.Exclusive; return WlrKeyboardFocus.Exclusive
case "none": case "none":
return WlrKeyboardFocus.None; return WlrKeyboardFocus.None
default: default:
return WlrKeyboardFocus.OnDemand; return WlrKeyboardFocus.OnDemand
} }
} }
onVisibleChanged: { onVisibleChanged: {
if (root.visible) { if (root.visible) {
opened(); opened()
} else { } else {
if (Qt.inputMethod) { if (Qt.inputMethod) {
Qt.inputMethod.hide(); Qt.inputMethod.hide()
Qt.inputMethod.reset(); Qt.inputMethod.reset()
} }
dialogClosed(); dialogClosed()
} }
} }
@@ -87,11 +87,12 @@ PanelWindow {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
enabled: root.closeOnBackgroundClick enabled: root.closeOnBackgroundClick
onClicked: (mouse) => { onClicked: mouse => {
var localPos = mapToItem(contentContainer, mouse.x, mouse.y); var localPos = mapToItem(contentContainer, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height) if (localPos.x < 0 || localPos.x > contentContainer.width
root.backgroundClicked(); || localPos.y < 0
|| localPos.y > contentContainer.height)
root.backgroundClicked()
} }
} }
@@ -100,9 +101,7 @@ PanelWindow {
duration: root.animationDuration duration: root.animationDuration
easing.type: root.animationEasing easing.type: root.animationEasing
} }
} }
} }
Rectangle { Rectangle {
@@ -113,17 +112,18 @@ PanelWindow {
anchors.centerIn: positioning === "center" ? parent : undefined anchors.centerIn: positioning === "center" ? parent : undefined
x: { x: {
if (positioning === "top-right") if (positioning === "top-right")
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL); return Math.max(Theme.spacingL,
root.screenWidth - width - Theme.spacingL)
else if (positioning === "custom") else if (positioning === "custom")
return root.customPosition.x; return root.customPosition.x
return 0; // Will be overridden by anchors.centerIn when positioning === "center" return 0 // Will be overridden by anchors.centerIn when positioning === "center"
} }
y: { y: {
if (positioning === "top-right") if (positioning === "top-right")
return Theme.barHeight + Theme.spacingXS; return Theme.barHeight + Theme.spacingXS
else if (positioning === "custom") else if (positioning === "custom")
return root.customPosition.y; return root.customPosition.y
return 0; // Will be overridden by anchors.centerIn when positioning === "center" return 0 // Will be overridden by anchors.centerIn when positioning === "center"
} }
color: root.backgroundColor color: root.backgroundColor
radius: root.cornerRadius radius: root.cornerRadius
@@ -133,9 +133,9 @@ PanelWindow {
opacity: root.visible ? 1 : 0 opacity: root.visible ? 1 : 0
scale: { scale: {
if (root.animationType === "scale") if (root.animationType === "scale")
return root.visible ? 1 : 0.9; return root.visible ? 1 : 0.9
return 1; return 1
} }
transform: root.animationType === "slide" ? slideTransform : null transform: root.animationType === "slide" ? slideTransform : null
@@ -159,7 +159,6 @@ PanelWindow {
duration: root.animationDuration duration: root.animationDuration
easing.type: root.animationEasing easing.type: root.animationEasing
} }
} }
Behavior on scale { Behavior on scale {
@@ -169,7 +168,6 @@ PanelWindow {
duration: root.animationDuration duration: root.animationDuration
easing.type: root.animationEasing easing.type: root.animationEasing
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
@@ -180,7 +178,6 @@ PanelWindow {
shadowColor: Theme.shadowStrong shadowColor: Theme.shadowStrong
shadowOpacity: 0.3 shadowOpacity: 0.3
} }
} }
FocusScope { FocusScope {
@@ -190,23 +187,22 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
visible: root.visible // Only active when the modal is visible visible: root.visible // Only active when the modal is visible
focus: root.visible focus: root.visible
Keys.onEscapePressed: (event) => { Keys.onEscapePressed: event => {
if (root.closeOnEscapeKey) { if (root.closeOnEscapeKey) {
root.visible = false; root.visible = false
event.accepted = true; event.accepted = true
} }
} }
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
Qt.callLater(function () { Qt.callLater(function () {
focusScope.forceActiveFocus(); focusScope.forceActiveFocus()
}); })
} }
} }
} }
// Expose the focusScope for external access // Expose the focusScope for external access
property alias modalFocusScope: focusScope property alias modalFocusScope: focusScope
} }

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
@@ -7,12 +7,14 @@ import Qt.labs.folderlistmodel
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
DankModal { DankModal {
id: fileBrowserModal id: fileBrowserModal
signal fileSelected(string path) signal fileSelected(string path)
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation) property string homeDir: StandardPaths.writableLocation(
StandardPaths.HomeLocation)
property string currentPath: "" property string currentPath: ""
property var fileExtensions: ["*.*"] property var fileExtensions: ["*.*"]
property string browserTitle: "Select File" property string browserTitle: "Select File"
@@ -31,35 +33,36 @@ DankModal {
} }
function isImageFile(fileName) { function isImageFile(fileName) {
if (!fileName) return false if (!fileName)
return false
var ext = fileName.toLowerCase().split('.').pop() var ext = fileName.toLowerCase().split('.').pop()
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext) return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
} }
function getLastPath() { function getLastPath() {
var lastPath = ""; var lastPath = ""
if (browserType === "wallpaper") { if (browserType === "wallpaper") {
lastPath = SessionData.wallpaperLastPath; lastPath = SessionData.wallpaperLastPath
} else if (browserType === "profile") { } else if (browserType === "profile") {
lastPath = SessionData.profileLastPath; lastPath = SessionData.profileLastPath
} }
if (lastPath && lastPath !== "") { if (lastPath && lastPath !== "") {
return lastPath; return lastPath
} }
return homeDir; return homeDir
} }
function saveLastPath(path) { function saveLastPath(path) {
if (browserType === "wallpaper") { if (browserType === "wallpaper") {
SessionData.setWallpaperLastPath(path); SessionData.setWallpaperLastPath(path)
} else if (browserType === "profile") { } else if (browserType === "profile") {
SessionData.setProfileLastPath(path); SessionData.setProfileLastPath(path)
} }
} }
Component.onCompleted: { Component.onCompleted: {
currentPath = getLastPath(); currentPath = getLastPath()
} }
width: 800 width: 800
@@ -72,37 +75,38 @@ DankModal {
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
var startPath = getLastPath(); var startPath = getLastPath()
currentPath = startPath; currentPath = startPath
} }
} }
onCurrentPathChanged: { onCurrentPathChanged: {
} }
function navigateUp() { function navigateUp() {
var path = currentPath; var path = currentPath
if (path === homeDir) { if (path === homeDir) {
return; return
} }
var lastSlash = path.lastIndexOf('/'); var lastSlash = path.lastIndexOf('/')
if (lastSlash > 0) { if (lastSlash > 0) {
var newPath = path.substring(0, lastSlash); var newPath = path.substring(0, lastSlash)
if (newPath.length < homeDir.length) { if (newPath.length < homeDir.length) {
currentPath = homeDir; currentPath = homeDir
saveLastPath(homeDir); saveLastPath(homeDir)
} else { } else {
currentPath = newPath; currentPath = newPath
saveLastPath(newPath); saveLastPath(newPath)
} }
} }
} }
function navigateTo(path) { function navigateTo(path) {
currentPath = path; currentPath = path
saveLastPath(path); // Save the path when navigating saveLastPath(path) // Save the path when navigating
} }
content: Component { content: Component {
@@ -155,7 +159,8 @@ DankModal {
width: 32 width: 32
height: 32 height: 32
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: mouseArea.containsMouse && currentPath !== homeDir ? Theme.surfaceVariant : "transparent" color: mouseArea.containsMouse
&& currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
opacity: currentPath !== homeDir ? 1.0 : 0.0 opacity: currentPath !== homeDir ? 1.0 : 0.0
DankIcon { DankIcon {
@@ -200,8 +205,12 @@ DankModal {
model: folderModel model: folderModel
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded } ScrollBar.vertical: ScrollBar {
ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AlwaysOff } policy: ScrollBar.AsNeeded
}
ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff
}
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now // Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
interactive: true interactive: true
@@ -240,7 +249,8 @@ DankModal {
anchors.fill: parent anchors.fill: parent
imagePath: !delegateRoot.fileIsDir ? delegateRoot.filePath : "" imagePath: !delegateRoot.fileIsDir ? delegateRoot.filePath : ""
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
visible: !delegateRoot.fileIsDir && isImageFile(delegateRoot.fileName) visible: !delegateRoot.fileIsDir && isImageFile(
delegateRoot.fileName)
maxCacheSize: 80 maxCacheSize: 80
} }
@@ -249,7 +259,8 @@ DankModal {
name: "description" name: "description"
size: Theme.iconSizeLarge size: Theme.iconSizeLarge
color: Theme.primary color: Theme.primary
visible: !delegateRoot.fileIsDir && !isImageFile(delegateRoot.fileName) visible: !delegateRoot.fileIsDir && !isImageFile(
delegateRoot.fileName)
} }
DankIcon { DankIcon {
@@ -282,9 +293,9 @@ DankModal {
onClicked: { onClicked: {
if (delegateRoot.fileIsDir) { if (delegateRoot.fileIsDir) {
navigateTo(delegateRoot.filePath); navigateTo(delegateRoot.filePath)
} else { } else {
fileSelected(delegateRoot.filePath); fileSelected(delegateRoot.filePath)
} }
} }
} }

View File

@@ -16,17 +16,17 @@ DankModal {
property string networkDetails: "" property string networkDetails: ""
function showNetworkInfo(ssid, data) { function showNetworkInfo(ssid, data) {
networkSSID = ssid; networkSSID = ssid
networkData = data; networkData = data
networkInfoModalVisible = true; networkInfoModalVisible = true
NetworkService.fetchNetworkInfo(ssid); NetworkService.fetchNetworkInfo(ssid)
} }
function hideDialog() { function hideDialog() {
networkInfoModalVisible = false; networkInfoModalVisible = false
networkSSID = ""; networkSSID = ""
networkData = null; networkData = null
networkDetails = ""; networkDetails = ""
} }
visible: networkInfoModalVisible visible: networkInfoModalVisible
@@ -34,13 +34,13 @@ DankModal {
height: 500 height: 500
enableShadow: true enableShadow: true
onBackgroundClicked: { onBackgroundClicked: {
hideDialog(); hideDialog()
} }
onVisibleChanged: { onVisibleChanged: {
if (!visible) { if (!visible) {
networkSSID = ""; networkSSID = ""
networkData = null; networkData = null
networkDetails = ""; networkDetails = ""
} }
} }
@@ -74,7 +74,6 @@ DankModal {
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
DankActionButton { DankActionButton {
@@ -83,10 +82,9 @@ DankModal {
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: { onClicked: {
root.hideDialog(); root.hideDialog()
} }
} }
} }
Flickable { Flickable {
@@ -108,10 +106,13 @@ DankModal {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling // Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler { WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => { onWheel: event => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60 let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY)) newY = Math.max(0, Math.min(
parent.contentHeight - parent.height,
newY))
parent.contentY = newY parent.contentY = newY
event.accepted = true event.accepted = true
} }
@@ -121,7 +122,8 @@ DankModal {
id: detailsRect id: detailsRect
width: parent.width width: parent.width
height: Math.max(parent.parent.height, detailsText.contentHeight + Theme.spacingM * 2) height: Math.max(parent.parent.height,
detailsText.contentHeight + Theme.spacingM * 2)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceHover color: Theme.surfaceHover
border.color: Theme.outlineStrong border.color: Theme.outlineStrong
@@ -132,13 +134,13 @@ DankModal {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingM anchors.margins: Theme.spacingM
text: NetworkService.networkInfoDetails.replace(/\\n/g, '\n') || "No information available" text: NetworkService.networkInfoDetails.replace(/\\n/g, '\n')
|| "No information available"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText color: Theme.surfaceText
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
lineHeight: 1.5 lineHeight: 1.5
} }
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@@ -148,7 +150,6 @@ DankModal {
ScrollBar.horizontal: ScrollBar { ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff policy: ScrollBar.AlwaysOff
} }
} }
Item { Item {
@@ -161,7 +162,8 @@ DankModal {
width: Math.max(70, closeText.contentWidth + Theme.spacingM * 2) width: Math.max(70, closeText.contentWidth + Theme.spacingM * 2)
height: 36 height: 36
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: closeArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary color: closeArea.containsMouse ? Qt.darker(Theme.primary,
1.1) : Theme.primary
StyledText { StyledText {
id: closeText id: closeText
@@ -180,7 +182,7 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.hideDialog(); root.hideDialog()
} }
} }
@@ -189,17 +191,10 @@ DankModal {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -17,17 +17,17 @@ DankModal {
function executePowerAction(action) { function executePowerAction(action) {
switch (action) { switch (action) {
case "logout": case "logout":
NiriService.quit(); NiriService.quit()
break; break
case "suspend": case "suspend":
Quickshell.execDetached(["systemctl", "suspend"]); Quickshell.execDetached(["systemctl", "suspend"])
break; break
case "reboot": case "reboot":
Quickshell.execDetached(["systemctl", "reboot"]); Quickshell.execDetached(["systemctl", "reboot"])
break; break
case "poweroff": case "poweroff":
Quickshell.execDetached(["systemctl", "poweroff"]); Quickshell.execDetached(["systemctl", "poweroff"])
break; break
} }
} }
@@ -37,7 +37,7 @@ DankModal {
keyboardFocus: "ondemand" keyboardFocus: "ondemand"
enableShadow: false enableShadow: false
onBackgroundClicked: { onBackgroundClicked: {
powerConfirmVisible = false; powerConfirmVisible = false
} }
content: Component { content: Component {
@@ -55,11 +55,11 @@ DankModal {
color: { color: {
switch (powerConfirmAction) { switch (powerConfirmAction) {
case "poweroff": case "poweroff":
return Theme.error; return Theme.error
case "reboot": case "reboot":
return Theme.warning; return Theme.warning
default: default:
return Theme.surfaceText; return Theme.surfaceText
} }
} }
font.weight: Font.Medium font.weight: Font.Medium
@@ -105,10 +105,9 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
powerConfirmVisible = false; powerConfirmVisible = false
} }
} }
} }
Rectangle { Rectangle {
@@ -116,19 +115,22 @@ DankModal {
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
let baseColor; let baseColor
switch (powerConfirmAction) { switch (powerConfirmAction) {
case "poweroff": case "poweroff":
baseColor = Theme.error; baseColor = Theme.error
break; break
case "reboot": case "reboot":
baseColor = Theme.warning; baseColor = Theme.warning
break; break
default: default:
baseColor = Theme.primary; baseColor = Theme.primary
break; break
} }
return confirmButton.containsMouse ? Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 0.9) : baseColor; return confirmButton.containsMouse ? Qt.rgba(baseColor.r,
baseColor.g,
baseColor.b,
0.9) : baseColor
} }
StyledText { StyledText {
@@ -146,19 +148,13 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
powerConfirmVisible = false; powerConfirmVisible = false
executePowerAction(powerConfirmAction); executePowerAction(powerConfirmAction)
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -18,22 +18,21 @@ DankModal {
property var tabNames: ["Processes", "Performance", "System"] property var tabNames: ["Processes", "Performance", "System"]
function show() { function show() {
processListModal.visible = true; processListModal.visible = true
UserInfoService.getUptime(); UserInfoService.getUptime()
} }
function hide() { function hide() {
processListModal.visible = false; processListModal.visible = false
if (processContextMenu.visible) if (processContextMenu.visible)
processContextMenu.close(); processContextMenu.close()
} }
function toggle() { function toggle() {
if (processListModal.visible) if (processListModal.visible)
hide(); hide()
else else
show(); show()
} }
width: 900 width: 900
@@ -55,23 +54,18 @@ DankModal {
ProcessesTab { ProcessesTab {
contextMenu: processContextMenu contextMenu: processContextMenu
} }
} }
Component { Component {
id: performanceTabComponent id: performanceTabComponent
PerformanceTab { PerformanceTab {}
}
} }
Component { Component {
id: systemTabComponent id: systemTabComponent
SystemTab { SystemTab {}
}
} }
ProcessContextMenu { ProcessContextMenu {
@@ -84,17 +78,17 @@ DankModal {
focus: true focus: true
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
processListModal.hide(); processListModal.hide()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_1) { } else if (event.key === Qt.Key_1) {
currentTab = 0; currentTab = 0
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_2) { } else if (event.key === Qt.Key_2) {
currentTab = 1; currentTab = 1
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_3) { } else if (event.key === Qt.Key_3) {
currentTab = 2; currentTab = 2
event.accepted = true; event.accepted = true
} }
} }
@@ -128,7 +122,6 @@ DankModal {
onClicked: processListModal.hide() onClicked: processListModal.hide()
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
Rectangle { Rectangle {
@@ -163,13 +156,13 @@ DankModal {
name: { name: {
switch (index) { switch (index) {
case 0: case 0:
return "list_alt"; return "list_alt"
case 1: case 1:
return "analytics"; return "analytics"
case 2: case 2:
return "settings"; return "settings"
default: default:
return "tab"; return "tab"
} }
} }
size: Theme.iconSize - 2 size: Theme.iconSize - 2
@@ -181,9 +174,7 @@ DankModal {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
StyledText { StyledText {
@@ -198,11 +189,8 @@ DankModal {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -212,7 +200,7 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
currentTab = index; currentTab = index
} }
} }
@@ -220,22 +208,16 @@ DankModal {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
Behavior on border.color { Behavior on border.color {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -261,9 +243,7 @@ DankModal {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
Loader { Loader {
@@ -281,9 +261,7 @@ DankModal {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
Loader { Loader {
@@ -301,17 +279,10 @@ DankModal {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior
import Quickshell.Io import Quickshell.Io
import QtQuick import QtQuick
@@ -10,21 +10,21 @@ import qs.Widgets
DankModal { DankModal {
id: settingsModal id: settingsModal
signal closingModal() signal closingModal
function show() { function show() {
settingsModal.visible = true; settingsModal.visible = true
} }
function hide() { function hide() {
settingsModal.visible = false; settingsModal.visible = false
} }
function toggle() { function toggle() {
if (settingsModal.visible) if (settingsModal.visible)
hide(); hide()
else else
show(); show()
} }
width: 750 width: 750
@@ -39,8 +39,8 @@ DankModal {
focus: true focus: true
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
settingsModal.hide(); settingsModal.hide()
event.accepted = true; event.accepted = true
} }
} }
@@ -81,7 +81,6 @@ DankModal {
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: settingsModal.hide() onClicked: settingsModal.hide()
} }
} }
Column { Column {
@@ -94,13 +93,22 @@ DankModal {
width: parent.width width: parent.width
model: [ model: [{
{ text: "Personalization", icon: "person" }, "text": "Personalization",
{ text: "Time & Weather", icon: "schedule" }, "icon": "person"
{ text: "Widgets", icon: "widgets" }, }, {
{ text: "Launcher", icon: "apps" }, "text": "Time & Weather",
{ text: "Appearance", icon: "palette" } "icon": "schedule"
] }, {
"text": "Widgets",
"icon": "widgets"
}, {
"text": "Launcher",
"icon": "apps"
}, {
"text": "Appearance",
"icon": "palette"
}]
} }
Item { Item {
@@ -166,23 +174,22 @@ DankModal {
} }
} }
} }
} }
IpcHandler { IpcHandler {
function open() { function open() {
settingsModal.show(); settingsModal.show()
return "SETTINGS_OPEN_SUCCESS"; return "SETTINGS_OPEN_SUCCESS"
} }
function close() { function close() {
settingsModal.hide(); settingsModal.hide()
return "SETTINGS_CLOSE_SUCCESS"; return "SETTINGS_CLOSE_SUCCESS"
} }
function toggle() { function toggle() {
settingsModal.toggle(); settingsModal.toggle()
return "SETTINGS_TOGGLE_SUCCESS"; return "SETTINGS_TOGGLE_SUCCESS"
} }
target: "settings" target: "settings"

View File

@@ -16,23 +16,23 @@ DankModal {
function show() { function show() {
spotlightOpen = true; spotlightOpen = true
appLauncher.searchQuery = ""; appLauncher.searchQuery = ""
} }
function hide() { function hide() {
spotlightOpen = false; spotlightOpen = false
appLauncher.searchQuery = ""; appLauncher.searchQuery = ""
appLauncher.selectedIndex = 0; appLauncher.selectedIndex = 0
appLauncher.setCategory("All"); appLauncher.setCategory("All")
} }
function toggle() { function toggle() {
if (spotlightOpen) if (spotlightOpen)
hide(); hide()
else else
show(); show()
} }
visible: spotlightOpen visible: spotlightOpen
@@ -47,11 +47,10 @@ DankModal {
onVisibleChanged: { onVisibleChanged: {
if (visible && !spotlightOpen) if (visible && !spotlightOpen)
show(); show()
} }
onBackgroundClicked: { onBackgroundClicked: {
spotlightOpen = false; spotlightOpen = false
} }
Component.onCompleted: { Component.onCompleted: {
@@ -64,27 +63,27 @@ DankModal {
gridColumns: 4 gridColumns: 4
onAppLaunched: hide() onAppLaunched: hide()
onViewModeSelected: function (mode) { onViewModeSelected: function (mode) {
SettingsData.setSpotlightModalViewMode(mode); SettingsData.setSpotlightModalViewMode(mode)
} }
} }
IpcHandler { IpcHandler {
function open() { function open() {
spotlightModal.show(); spotlightModal.show()
return "SPOTLIGHT_OPEN_SUCCESS"; return "SPOTLIGHT_OPEN_SUCCESS"
} }
function close() { function close() {
spotlightModal.hide(); spotlightModal.hide()
return "SPOTLIGHT_CLOSE_SUCCESS"; return "SPOTLIGHT_CLOSE_SUCCESS"
} }
function toggle() { function toggle() {
spotlightModal.toggle(); spotlightModal.toggle()
return "SPOTLIGHT_TOGGLE_SUCCESS"; return "SPOTLIGHT_TOGGLE_SUCCESS"
} }
target: "spotlight" target: "spotlight"
@@ -98,27 +97,31 @@ DankModal {
focus: true focus: true
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
hide(); hide()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Down) { } else if (event.key === Qt.Key_Down) {
appLauncher.selectNext(); appLauncher.selectNext()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Up) { } else if (event.key === Qt.Key_Up) {
appLauncher.selectPrevious(); appLauncher.selectPrevious()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Right && appLauncher.viewMode === "grid") { } else if (event.key === Qt.Key_Right
appLauncher.selectNextInRow(); && appLauncher.viewMode === "grid") {
event.accepted = true; appLauncher.selectNextInRow()
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") { event.accepted = true
appLauncher.selectPreviousInRow(); } else if (event.key === Qt.Key_Left
event.accepted = true; && appLauncher.viewMode === "grid") {
appLauncher.selectPreviousInRow()
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
appLauncher.launchSelected(); appLauncher.launchSelected()
event.accepted = true; event.accepted = true
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) { } else if (!searchField.activeFocus && event.text
searchField.forceActiveFocus(); && event.text.length > 0 && event.text.match(
searchField.insertText(event.text); /[a-zA-Z0-9\\s]/)) {
event.accepted = true; searchField.forceActiveFocus()
searchField.insertText(event.text)
event.accepted = true
} }
} }
@@ -134,7 +137,8 @@ DankModal {
color: Theme.surfaceVariantAlpha color: Theme.surfaceVariantAlpha
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
border.width: 1 border.width: 1
visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0 visible: appLauncher.categories.length > 1
|| appLauncher.model.count > 0
CategorySelector { CategorySelector {
id: categorySelector id: categorySelector
@@ -144,11 +148,10 @@ DankModal {
categories: appLauncher.categories categories: appLauncher.categories
selectedCategory: appLauncher.selectedCategory selectedCategory: appLauncher.selectedCategory
compact: false compact: false
onCategorySelected: (category) => { onCategorySelected: category => {
return appLauncher.setCategory(category); return appLauncher.setCategory(category)
} }
} }
} }
Row { Row {
@@ -161,7 +164,10 @@ DankModal {
width: parent.width - 80 - Theme.spacingM // Leave space for view toggle buttons width: parent.width - 80 - Theme.spacingM // Leave space for view toggle buttons
height: 56 height: 56
cornerRadius: Theme.cornerRadiusLarge cornerRadius: Theme.cornerRadiusLarge
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7) backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.7)
normalBorderColor: Theme.outlineMedium normalBorderColor: Theme.outlineMedium
focusedBorderColor: Theme.primary focusedBorderColor: Theme.primary
leftIconName: "search" leftIconName: "search"
@@ -177,20 +183,25 @@ DankModal {
keyForwardTargets: [spotlightKeyHandler] keyForwardTargets: [spotlightKeyHandler]
text: appLauncher.searchQuery text: appLauncher.searchQuery
onTextEdited: { onTextEdited: {
appLauncher.searchQuery = text; appLauncher.searchQuery = text
} }
Keys.onPressed: (event) => { Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
hide(); hide()
event.accepted = true; event.accepted = true
} else if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length > 0) { } else if ((event.key === Qt.Key_Return
if (appLauncher.keyboardNavigationActive && appLauncher.model.count > 0) || event.key === Qt.Key_Enter)
appLauncher.launchSelected(); && text.length > 0) {
if (appLauncher.keyboardNavigationActive
&& appLauncher.model.count > 0)
appLauncher.launchSelected()
else if (appLauncher.model.count > 0) else if (appLauncher.model.count > 0)
appLauncher.launchApp(appLauncher.model.get(0)); appLauncher.launchApp(appLauncher.model.get(0))
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) { } else if (event.key === Qt.Key_Down || event.key
event.accepted = false; === Qt.Key_Up || event.key === Qt.Key_Left || event.key
=== Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
event.accepted = false
} }
} }
@@ -198,14 +209,13 @@ DankModal {
function onSpotlightOpenChanged() { function onSpotlightOpenChanged() {
if (spotlightModal.spotlightOpen) { if (spotlightModal.spotlightOpen) {
Qt.callLater(function () { Qt.callLater(function () {
searchField.forceActiveFocus(); searchField.forceActiveFocus()
}); })
} }
} }
target: spotlightModal target: spotlightModal
} }
} }
Row { Row {
@@ -235,10 +245,9 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
appLauncher.setViewMode("list"); appLauncher.setViewMode("list")
} }
} }
} }
Rectangle { Rectangle {
@@ -263,14 +272,11 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
appLauncher.setViewMode("grid"); appLauncher.setViewMode("grid")
} }
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -293,21 +299,21 @@ DankModal {
property bool hoverUpdatesSelection: false property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
signal keyboardNavigationReset() signal keyboardNavigationReset
signal itemClicked(int index, var modelData) signal itemClicked(int index, var modelData)
signal itemHovered(int index) signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY) signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) { function ensureVisible(index) {
if (index < 0 || index >= count) if (index < 0 || index >= count)
return; return
var itemY = index * (itemHeight + itemSpacing); var itemY = index * (itemHeight + itemSpacing)
var itemBottom = itemY + itemHeight; var itemBottom = itemY + itemHeight
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height)
contentY = itemBottom - height; contentY = itemBottom - height
} }
anchors.fill: parent anchors.fill: parent
@@ -324,20 +330,20 @@ DankModal {
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (keyboardNavigationActive) if (keyboardNavigationActive)
ensureVisible(currentIndex); ensureVisible(currentIndex)
} }
onItemClicked: function (index, modelData) { onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData); appLauncher.launchApp(modelData)
} }
onItemHovered: function (index) { onItemHovered: function (index) {
appLauncher.selectedIndex = index; appLauncher.selectedIndex = index
} }
onItemRightClicked: function (index, modelData, mouseX, mouseY) { onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData) contextMenu.show(mouseX, mouseY, modelData)
} }
onKeyboardNavigationReset: { onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false; appLauncher.keyboardNavigationActive = false
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@@ -352,7 +358,7 @@ DankModal {
width: ListView.view.width width: ListView.view.width
height: resultsList.itemHeight height: resultsList.itemHeight
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: ListView.isCurrentItem ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
border.width: ListView.isCurrentItem ? 2 : 1 border.width: ListView.isCurrentItem ? 2 : 1
@@ -367,10 +373,12 @@ DankModal {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
IconImage { IconImage {
id: iconImg id: listIconImg
anchors.fill: parent anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : "" source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
@@ -378,7 +386,7 @@ DankModal {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
visible: !iconImg.visible visible: !listIconImg.visible
color: Theme.surfaceLight color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.width: 1 border.width: 1
@@ -386,7 +394,10 @@ DankModal {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A" text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: resultsList.iconSize * 0.4 font.pixelSize: resultsList.iconSize * 0.4
color: Theme.primary color: Theme.primary
font.weight: Font.Bold font.weight: Font.Bold
@@ -414,13 +425,14 @@ DankModal {
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
elide: Text.ElideRight elide: Text.ElideRight
visible: resultsList.showDescription && model.comment && model.comment.length > 0 visible: resultsList.showDescription && model.comment
&& model.comment.length > 0
} }
} }
} }
MouseArea { MouseArea {
id: mouseArea id: listMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
@@ -428,20 +440,23 @@ DankModal {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10 z: 10
onEntered: { onEntered: {
if (resultsList.hoverUpdatesSelection && !resultsList.keyboardNavigationActive) if (resultsList.hoverUpdatesSelection
resultsList.currentIndex = index; && !resultsList.keyboardNavigationActive)
resultsList.currentIndex = index
resultsList.itemHovered(index); resultsList.itemHovered(index)
} }
onPositionChanged: { onPositionChanged: {
resultsList.keyboardNavigationReset(); resultsList.keyboardNavigationReset()
} }
onClicked: (mouse) => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
resultsList.itemClicked(index, model); resultsList.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y); var globalPos = mapToGlobal(mouse.x, mouse.y)
resultsList.itemRightClicked(index, model, globalPos.x, globalPos.y); resultsList.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
} }
} }
} }
@@ -462,26 +477,31 @@ DankModal {
property int minIconSize: 32 property int minIconSize: 32
property bool hoverUpdatesSelection: false property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns property int baseCellWidth: adaptiveColumns ? Math.max(
minCellWidth,
Math.min(
maxCellWidth,
width / columns)) : (width - Theme.spacingS * 2) / columns
property int baseCellHeight: baseCellWidth + 20 property int baseCellHeight: baseCellWidth + 20
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns property int actualColumns: adaptiveColumns ? Math.floor(
width / cellWidth) : columns
property int remainingSpace: width - (actualColumns * cellWidth) property int remainingSpace: width - (actualColumns * cellWidth)
signal keyboardNavigationReset() signal keyboardNavigationReset
signal itemClicked(int index, var modelData) signal itemClicked(int index, var modelData)
signal itemHovered(int index) signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY) signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) { function ensureVisible(index) {
if (index < 0 || index >= count) if (index < 0 || index >= count)
return; return
var itemY = Math.floor(index / actualColumns) * cellHeight; var itemY = Math.floor(index / actualColumns) * cellHeight
var itemBottom = itemY + cellHeight; var itemBottom = itemY + cellHeight
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height)
contentY = itemBottom - height; contentY = itemBottom - height
} }
anchors.fill: parent anchors.fill: parent
@@ -500,20 +520,20 @@ DankModal {
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (keyboardNavigationActive) if (keyboardNavigationActive)
ensureVisible(currentIndex); ensureVisible(currentIndex)
} }
onItemClicked: function (index, modelData) { onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData); appLauncher.launchApp(modelData)
} }
onItemHovered: function (index) { onItemHovered: function (index) {
appLauncher.selectedIndex = index; appLauncher.selectedIndex = index
} }
onItemRightClicked: function (index, modelData, mouseX, mouseY) { onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData) contextMenu.show(mouseX, mouseY, modelData)
} }
onKeyboardNavigationReset: { onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false; appLauncher.keyboardNavigationActive = false
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@@ -528,8 +548,9 @@ DankModal {
width: resultsGrid.cellWidth - resultsGrid.cellPadding width: resultsGrid.cellWidth - resultsGrid.cellPadding
height: resultsGrid.cellHeight - resultsGrid.cellPadding height: resultsGrid.cellHeight - resultsGrid.cellPadding
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: resultsGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium border.color: resultsGrid.currentIndex
=== index ? Theme.primarySelected : Theme.outlineMedium
border.width: resultsGrid.currentIndex === index ? 2 : 1 border.width: resultsGrid.currentIndex === index ? 2 : 1
Column { Column {
@@ -537,17 +558,22 @@ DankModal {
spacing: Theme.spacingS spacing: Theme.spacingS
Item { Item {
property int iconSize: Math.min(resultsGrid.maxIconSize, Math.max(resultsGrid.minIconSize, resultsGrid.cellWidth * resultsGrid.iconSizeRatio)) property int iconSize: Math.min(
resultsGrid.maxIconSize, Math.max(
resultsGrid.minIconSize,
resultsGrid.cellWidth * resultsGrid.iconSizeRatio))
width: iconSize width: iconSize
height: iconSize height: iconSize
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
IconImage { IconImage {
id: iconImg id: gridIconImg
anchors.fill: parent anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : "" source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
@@ -555,7 +581,7 @@ DankModal {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
visible: !iconImg.visible visible: !gridIconImg.visible
color: Theme.surfaceLight color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.width: 1 border.width: 1
@@ -563,7 +589,10 @@ DankModal {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A" text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: Math.min(28, parent.width * 0.5) font.pixelSize: Math.min(28, parent.width * 0.5)
color: Theme.primary color: Theme.primary
font.weight: Font.Bold font.weight: Font.Bold
@@ -586,7 +615,7 @@ DankModal {
} }
MouseArea { MouseArea {
id: mouseArea id: gridMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
@@ -594,32 +623,31 @@ DankModal {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10 z: 10
onEntered: { onEntered: {
if (resultsGrid.hoverUpdatesSelection && !resultsGrid.keyboardNavigationActive) if (resultsGrid.hoverUpdatesSelection
resultsGrid.currentIndex = index; && !resultsGrid.keyboardNavigationActive)
resultsGrid.currentIndex = index
resultsGrid.itemHovered(index); resultsGrid.itemHovered(index)
} }
onPositionChanged: { onPositionChanged: {
resultsGrid.keyboardNavigationReset(); resultsGrid.keyboardNavigationReset()
} }
onClicked: (mouse) => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
resultsGrid.itemClicked(index, model); resultsGrid.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y); var globalPos = mapToGlobal(mouse.x, mouse.y)
resultsGrid.itemRightClicked(index, model, globalPos.x, globalPos.y); resultsGrid.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
} }
} }
} }
} }
} }
} }
} }
} }
} }
Popup { Popup {
@@ -629,24 +657,25 @@ DankModal {
function show(x, y, app) { function show(x, y, app) {
currentApp = app currentApp = app
if (!contextMenu.parent && typeof Overlay !== "undefined" && Overlay.overlay) if (!contextMenu.parent && typeof Overlay !== "undefined"
contextMenu.parent = Overlay.overlay; && Overlay.overlay)
contextMenu.parent = Overlay.overlay
const menuWidth = 180; const menuWidth = 180
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2; const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
const screenWidth = Screen.width; const screenWidth = Screen.width
const screenHeight = Screen.height; const screenHeight = Screen.height
let finalX = x; let finalX = x
let finalY = y; let finalY = y
if (x + menuWidth > screenWidth - 20) if (x + menuWidth > screenWidth - 20)
finalX = x - menuWidth; finalX = x - menuWidth
if (y + menuHeight > screenHeight - 20) if (y + menuHeight > screenHeight - 20)
finalY = y - menuHeight; finalY = y - menuHeight
contextMenu.x = Math.max(20, finalX); contextMenu.x = Math.max(20, finalX)
contextMenu.y = Math.max(20, finalY); contextMenu.y = Math.max(20, finalY)
open(); open()
} }
width: 180 width: 180
@@ -655,17 +684,17 @@ DankModal {
modal: false modal: false
closePolicy: Popup.CloseOnEscape closePolicy: Popup.CloseOnEscape
onClosed: { onClosed: {
closePolicy = Popup.CloseOnEscape; closePolicy = Popup.CloseOnEscape
} }
onOpened: { onOpened: {
outsideClickTimer.start(); outsideClickTimer.start()
} }
Timer { Timer {
id: outsideClickTimer id: outsideClickTimer
interval: 100 interval: 100
onTriggered: { onTriggered: {
contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside; contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside
} }
} }
@@ -676,7 +705,8 @@ DankModal {
contentItem: Rectangle { contentItem: Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
Column { Column {
@@ -689,7 +719,10 @@ DankModal {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -699,8 +732,11 @@ DankModal {
DankIcon { DankIcon {
name: { name: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) return "push_pin" if (!contextMenu.currentApp
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || "" || !contextMenu.currentApp.desktopEntry)
return "push_pin"
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin" return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin"
} }
size: Theme.iconSize - 2 size: Theme.iconSize - 2
@@ -711,9 +747,13 @@ DankModal {
StyledText { StyledText {
text: { text: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) return "Pin to Dock" if (!contextMenu.currentApp
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || "" || !contextMenu.currentApp.desktopEntry)
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock" return "Pin to Dock"
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(
appId) ? "Unpin from Dock" : "Pin to Dock"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
@@ -728,8 +768,11 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) return if (!contextMenu.currentApp
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || "" || !contextMenu.currentApp.desktopEntry)
return
var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
if (SessionData.isPinnedApp(appId)) { if (SessionData.isPinnedApp(appId)) {
SessionData.removePinnedApp(appId) SessionData.removePinnedApp(appId)
} else { } else {
@@ -750,7 +793,8 @@ DankModal {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width width: parent.width
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
} }
} }
@@ -758,7 +802,10 @@ DankModal {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -799,5 +846,4 @@ DankModal {
} }
} }
} }
} }

View File

@@ -17,21 +17,21 @@ DankModal {
keyboardFocus: "exclusive" keyboardFocus: "exclusive"
onVisibleChanged: { onVisibleChanged: {
if (!visible) if (!visible)
wifiPasswordInput = ""; wifiPasswordInput = ""
} }
onBackgroundClicked: { onBackgroundClicked: {
wifiPasswordModalVisible = false; wifiPasswordModalVisible = false
wifiPasswordInput = ""; wifiPasswordInput = ""
} }
Connections { Connections {
function onPasswordDialogShouldReopenChanged() { function onPasswordDialogShouldReopenChanged() {
if (NetworkService.passwordDialogShouldReopen && NetworkService.connectingSSID !== "") { if (NetworkService.passwordDialogShouldReopen
wifiPasswordSSID = NetworkService.connectingSSID; && NetworkService.connectingSSID !== "") {
wifiPasswordInput = ""; wifiPasswordSSID = NetworkService.connectingSSID
wifiPasswordModalVisible = true; wifiPasswordInput = ""
NetworkService.passwordDialogShouldReopen = false; wifiPasswordModalVisible = true
NetworkService.passwordDialogShouldReopen = false
} }
} }
@@ -69,7 +69,6 @@ DankModal {
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
DankActionButton { DankActionButton {
@@ -78,11 +77,10 @@ DankModal {
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: { onClicked: {
wifiPasswordModalVisible = false; wifiPasswordModalVisible = false
wifiPasswordInput = ""; wifiPasswordInput = ""
} }
} }
} }
Rectangle { Rectangle {
@@ -105,13 +103,14 @@ DankModal {
backgroundColor: "transparent" backgroundColor: "transparent"
focus: true focus: true
onTextEdited: { onTextEdited: {
wifiPasswordInput = text; wifiPasswordInput = text
} }
onAccepted: { onAccepted: {
NetworkService.connectToWifiWithPassword(wifiPasswordSSID, passwordInput.text); NetworkService.connectToWifiWithPassword(wifiPasswordSSID,
wifiPasswordModalVisible = false; passwordInput.text)
wifiPasswordInput = ""; wifiPasswordModalVisible = false
passwordInput.text = ""; wifiPasswordInput = ""
passwordInput.text = ""
} }
Timer { Timer {
@@ -121,25 +120,23 @@ DankModal {
} }
Component.onCompleted: { Component.onCompleted: {
focusTimer.start(); focusTimer.start()
} }
Connections { Connections {
function onOpened() { function onOpened() {
focusTimer.start(); focusTimer.start()
} }
function onVisibleChanged() { function onVisibleChanged() {
if (root.visible) { if (root.visible) {
focusTimer.start(); focusTimer.start()
} }
} }
target: root target: root
} }
} }
} }
Row { Row {
@@ -170,10 +167,9 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
showPasswordCheckbox.checked = !showPasswordCheckbox.checked; showPasswordCheckbox.checked = !showPasswordCheckbox.checked
} }
} }
} }
StyledText { StyledText {
@@ -182,7 +178,6 @@ DankModal {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Item { Item {
@@ -219,18 +214,18 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
wifiPasswordModalVisible = false; wifiPasswordModalVisible = false
wifiPasswordInput = ""; wifiPasswordInput = ""
} }
} }
} }
Rectangle { Rectangle {
width: Math.max(80, connectText.contentWidth + Theme.spacingM * 2) width: Math.max(80, connectText.contentWidth + Theme.spacingM * 2)
height: 36 height: 36
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: connectArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary color: connectArea.containsMouse ? Qt.darker(Theme.primary,
1.1) : Theme.primary
enabled: passwordInput.text.length > 0 enabled: passwordInput.text.length > 0
opacity: enabled ? 1 : 0.5 opacity: enabled ? 1 : 0.5
@@ -252,10 +247,11 @@ DankModal {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
enabled: parent.enabled enabled: parent.enabled
onClicked: { onClicked: {
NetworkService.connectToWifiWithPassword(wifiPasswordSSID, passwordInput.text); NetworkService.connectToWifiWithPassword(wifiPasswordSSID,
wifiPasswordModalVisible = false; passwordInput.text)
wifiPasswordInput = ""; wifiPasswordModalVisible = false
passwordInput.text = ""; wifiPasswordInput = ""
passwordInput.text = ""
} }
} }
@@ -264,18 +260,11 @@ DankModal {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
}
}
}
}
}
} }
} }
}
}
}
}
}
} }

View File

@@ -21,27 +21,27 @@ PanelWindow {
property var triggerScreen: null property var triggerScreen: null
function show() { function show() {
appDrawerPopout.isVisible = true; appDrawerPopout.isVisible = true
appLauncher.searchQuery = ""; appLauncher.searchQuery = ""
} }
function hide() { function hide() {
appDrawerPopout.isVisible = false; appDrawerPopout.isVisible = false
} }
function toggle() { function toggle() {
if (appDrawerPopout.isVisible) if (appDrawerPopout.isVisible)
hide(); hide()
else else
show(); show()
} }
function setTriggerPosition(x, y, width, section, screen) { function setTriggerPosition(x, y, width, section, screen) {
triggerX = x; triggerX = x
triggerY = y; triggerY = y
triggerWidth = width; triggerWidth = width
triggerSection = section; triggerSection = section
triggerScreen = screen; triggerScreen = screen
} }
WlrLayershell.layer: WlrLayershell.Overlay WlrLayershell.layer: WlrLayershell.Overlay
@@ -66,7 +66,7 @@ PanelWindow {
gridColumns: 4 gridColumns: 4
onAppLaunched: appDrawerPopout.hide() onAppLaunched: appDrawerPopout.hide()
onViewModeSelected: function (mode) { onViewModeSelected: function (mode) {
SettingsData.setAppLauncherViewMode(mode); SettingsData.setAppLauncherViewMode(mode)
} }
} }
@@ -74,10 +74,10 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
enabled: appDrawerPopout.isVisible enabled: appDrawerPopout.isVisible
onClicked: function (mouse) { onClicked: function (mouse) {
var localPos = mapToItem(launcherLoader, mouse.x, mouse.y); var localPos = mapToItem(launcherLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > launcherLoader.width || localPos.y < 0 || localPos.y > launcherLoader.height) if (localPos.x < 0 || localPos.x > launcherLoader.width || localPos.y < 0
appDrawerPopout.hide(); || localPos.y > launcherLoader.height)
appDrawerPopout.hide()
} }
} }
@@ -89,18 +89,19 @@ PanelWindow {
readonly property real screenWidth: appDrawerPopout.screen ? appDrawerPopout.screen.width : Screen.width readonly property real screenWidth: appDrawerPopout.screen ? appDrawerPopout.screen.width : Screen.width
readonly property real screenHeight: appDrawerPopout.screen ? appDrawerPopout.screen.height : Screen.height readonly property real screenHeight: appDrawerPopout.screen ? appDrawerPopout.screen.height : Screen.height
readonly property real calculatedX: { readonly property real calculatedX: {
var centerX = appDrawerPopout.triggerX + (appDrawerPopout.triggerWidth / 2) - (popupWidth / 2); var centerX = appDrawerPopout.triggerX + (appDrawerPopout.triggerWidth / 2) - (popupWidth / 2)
if (centerX >= Theme.spacingM && centerX + popupWidth <= screenWidth - Theme.spacingM) if (centerX >= Theme.spacingM
return centerX; && centerX + popupWidth <= screenWidth - Theme.spacingM)
return centerX
if (centerX < Theme.spacingM) if (centerX < Theme.spacingM)
return Theme.spacingM; return Theme.spacingM
if (centerX + popupWidth > screenWidth - Theme.spacingM) if (centerX + popupWidth > screenWidth - Theme.spacingM)
return screenWidth - popupWidth - Theme.spacingM; return screenWidth - popupWidth - Theme.spacingM
return centerX; return centerX
} }
readonly property real calculatedY: appDrawerPopout.triggerY readonly property real calculatedY: appDrawerPopout.triggerY
@@ -119,7 +120,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
Behavior on scale { Behavior on scale {
@@ -128,7 +128,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
sourceComponent: Rectangle { sourceComponent: Rectangle {
@@ -162,7 +161,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "transparent" color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.12)
border.width: 1 border.width: 1
radius: parent.radius radius: parent.radius
z: -1 z: -1
@@ -175,32 +175,36 @@ PanelWindow {
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {
if (appDrawerPopout.isVisible) if (appDrawerPopout.isVisible)
forceActiveFocus(); forceActiveFocus()
} }
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
appDrawerPopout.hide(); appDrawerPopout.hide()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Down) { } else if (event.key === Qt.Key_Down) {
appLauncher.selectNext(); appLauncher.selectNext()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Up) { } else if (event.key === Qt.Key_Up) {
appLauncher.selectPrevious(); appLauncher.selectPrevious()
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Right && appLauncher.viewMode === "grid") { } else if (event.key === Qt.Key_Right
appLauncher.selectNextInRow(); && appLauncher.viewMode === "grid") {
event.accepted = true; appLauncher.selectNextInRow()
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") { event.accepted = true
appLauncher.selectPreviousInRow(); } else if (event.key === Qt.Key_Left
event.accepted = true; && appLauncher.viewMode === "grid") {
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { appLauncher.selectPreviousInRow()
appLauncher.launchSelected(); event.accepted = true
event.accepted = true; } else if (event.key === Qt.Key_Return
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) { || event.key === Qt.Key_Enter) {
searchField.forceActiveFocus(); appLauncher.launchSelected()
searchField.insertText(event.text); event.accepted = true
event.accepted = true; } else if (!searchField.activeFocus && event.text
&& event.text.length > 0 && event.text.match(
/[a-zA-Z0-9\\s]/)) {
searchField.forceActiveFocus()
searchField.insertText(event.text)
event.accepted = true
} }
} }
@@ -234,7 +238,6 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
} }
} }
DankTextField { DankTextField {
@@ -243,8 +246,12 @@ PanelWindow {
width: parent.width width: parent.width
height: 52 height: 52
cornerRadius: Theme.cornerRadiusLarge cornerRadius: Theme.cornerRadiusLarge
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7) backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.7)
normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.3)
focusedBorderColor: Theme.primary focusedBorderColor: Theme.primary
leftIconName: "search" leftIconName: "search"
leftIconSize: Theme.iconSize leftIconSize: Theme.iconSize
@@ -257,40 +264,43 @@ PanelWindow {
ignoreLeftRightKeys: true ignoreLeftRightKeys: true
keyForwardTargets: [keyHandler] keyForwardTargets: [keyHandler]
onTextEdited: { onTextEdited: {
appLauncher.searchQuery = text; appLauncher.searchQuery = text
} }
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length > 0) { if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
if (appLauncher.keyboardNavigationActive && appLauncher.model.count > 0) { && text.length > 0) {
appLauncher.launchSelected(); if (appLauncher.keyboardNavigationActive
&& appLauncher.model.count > 0) {
appLauncher.launchSelected()
} else if (appLauncher.model.count > 0) { } else if (appLauncher.model.count > 0) {
var firstApp = appLauncher.model.get(0); var firstApp = appLauncher.model.get(0)
appLauncher.launchApp(firstApp); appLauncher.launchApp(firstApp)
} }
event.accepted = true; event.accepted = true
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) { } else if (event.key === Qt.Key_Down || event.key
event.accepted = false; === Qt.Key_Up || event.key === Qt.Key_Left || event.key
=== Qt.Key_Right || ((event.key === Qt.Key_Return || event.key
=== Qt.Key_Enter) && text.length === 0)) {
event.accepted = false
} }
} }
Component.onCompleted: { Component.onCompleted: {
if (appDrawerPopout.isVisible) if (appDrawerPopout.isVisible)
searchField.forceActiveFocus(); searchField.forceActiveFocus()
} }
Connections { Connections {
function onIsVisibleChanged() { function onIsVisibleChanged() {
if (appDrawerPopout.isVisible) if (appDrawerPopout.isVisible)
Qt.callLater(function () { Qt.callLater(function () {
searchField.forceActiveFocus(); searchField.forceActiveFocus()
}); })
else else
searchField.clearFocus(); searchField.clearFocus()
} }
target: appDrawerPopout target: appDrawerPopout
} }
} }
Row { Row {
@@ -310,10 +320,9 @@ PanelWindow {
options: appLauncher.categories options: appLauncher.categories
optionIcons: appLauncher.categoryIcons optionIcons: appLauncher.categoryIcons
onValueChanged: function (value) { onValueChanged: function (value) {
appLauncher.setCategory(value); appLauncher.setCategory(value)
} }
} }
} }
Item { Item {
@@ -331,10 +340,21 @@ PanelWindow {
iconName: "view_list" iconName: "view_list"
iconSize: 20 iconSize: 20
iconColor: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText iconColor: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText
hoverColor: appLauncher.viewMode === "list" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) hoverColor: appLauncher.viewMode
backgroundColor: appLauncher.viewMode === "list" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" === "list" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
backgroundColor: appLauncher.viewMode
=== "list" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
onClicked: { onClicked: {
appLauncher.setViewMode("list"); appLauncher.setViewMode("list")
} }
} }
@@ -344,28 +364,39 @@ PanelWindow {
iconName: "grid_view" iconName: "grid_view"
iconSize: 20 iconSize: 20
iconColor: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText iconColor: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText
hoverColor: appLauncher.viewMode === "grid" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) hoverColor: appLauncher.viewMode
backgroundColor: appLauncher.viewMode === "grid" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" === "grid" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
backgroundColor: appLauncher.viewMode
=== "grid" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
onClicked: { onClicked: {
appLauncher.setViewMode("grid"); appLauncher.setViewMode("grid")
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: { height: {
let usedHeight = 40 + Theme.spacingL; let usedHeight = 40 + Theme.spacingL
usedHeight += 52 + Theme.spacingL; usedHeight += 52 + Theme.spacingL
usedHeight += (searchField.text.length === 0 ? 40 + Theme.spacingL : 0); usedHeight += (searchField.text.length === 0 ? 40 + Theme.spacingL : 0)
return parent.height - usedHeight; return parent.height - usedHeight
} }
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1 border.width: 1
DankListView { DankListView {
@@ -378,21 +409,21 @@ PanelWindow {
property bool hoverUpdatesSelection: false property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
signal keyboardNavigationReset() signal keyboardNavigationReset
signal itemClicked(int index, var modelData) signal itemClicked(int index, var modelData)
signal itemHovered(int index) signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY) signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) { function ensureVisible(index) {
if (index < 0 || index >= count) if (index < 0 || index >= count)
return; return
var itemY = index * (itemHeight + itemSpacing); var itemY = index * (itemHeight + itemSpacing)
var itemBottom = itemY + itemHeight; var itemBottom = itemY + itemHeight
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height)
contentY = itemBottom - height; contentY = itemBottom - height
} }
anchors.fill: parent anchors.fill: parent
@@ -409,20 +440,20 @@ PanelWindow {
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (keyboardNavigationActive) if (keyboardNavigationActive)
ensureVisible(currentIndex); ensureVisible(currentIndex)
} }
onItemClicked: function (index, modelData) { onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData); appLauncher.launchApp(modelData)
} }
onItemHovered: function (index) { onItemHovered: function (index) {
appLauncher.selectedIndex = index; appLauncher.selectedIndex = index
} }
onItemRightClicked: function (index, modelData, mouseX, mouseY) { onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData); contextMenu.show(mouseX, mouseY, modelData)
} }
onKeyboardNavigationReset: { onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false; appLauncher.keyboardNavigationActive = false
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@@ -437,7 +468,7 @@ PanelWindow {
width: ListView.view.width width: ListView.view.width
height: appList.itemHeight height: appList.itemHeight
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: ListView.isCurrentItem ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
border.width: ListView.isCurrentItem ? 2 : 1 border.width: ListView.isCurrentItem ? 2 : 1
@@ -452,10 +483,12 @@ PanelWindow {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
IconImage { IconImage {
id: iconImg id: listIconImg
anchors.fill: parent anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : "" source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
@@ -463,7 +496,7 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
visible: !iconImg.visible visible: !listIconImg.visible
color: Theme.surfaceLight color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.width: 1 border.width: 1
@@ -471,7 +504,10 @@ PanelWindow {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A" text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: appList.iconSize * 0.4 font.pixelSize: appList.iconSize * 0.4
color: Theme.primary color: Theme.primary
font.weight: Font.Bold font.weight: Font.Bold
@@ -499,13 +535,14 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
elide: Text.ElideRight elide: Text.ElideRight
visible: appList.showDescription && model.comment && model.comment.length > 0 visible: appList.showDescription && model.comment
&& model.comment.length > 0
} }
} }
} }
MouseArea { MouseArea {
id: mouseArea id: listMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
@@ -513,20 +550,23 @@ PanelWindow {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10 z: 10
onEntered: { onEntered: {
if (appList.hoverUpdatesSelection && !appList.keyboardNavigationActive) if (appList.hoverUpdatesSelection
appList.currentIndex = index; && !appList.keyboardNavigationActive)
appList.currentIndex = index
appList.itemHovered(index); appList.itemHovered(index)
} }
onPositionChanged: { onPositionChanged: {
appList.keyboardNavigationReset(); appList.keyboardNavigationReset()
} }
onClicked: (mouse) => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
appList.itemClicked(index, model); appList.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y); var globalPos = mapToGlobal(mouse.x, mouse.y)
appList.itemRightClicked(index, model, globalPos.x, globalPos.y); appList.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
} }
} }
} }
@@ -547,26 +587,31 @@ PanelWindow {
property int minIconSize: 32 property int minIconSize: 32
property bool hoverUpdatesSelection: false property bool hoverUpdatesSelection: false
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns property int baseCellWidth: adaptiveColumns ? Math.max(
minCellWidth,
Math.min(
maxCellWidth,
width / columns)) : (width - Theme.spacingS * 2) / columns
property int baseCellHeight: baseCellWidth + 20 property int baseCellHeight: baseCellWidth + 20
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns property int actualColumns: adaptiveColumns ? Math.floor(
width / cellWidth) : columns
property int remainingSpace: width - (actualColumns * cellWidth) property int remainingSpace: width - (actualColumns * cellWidth)
signal keyboardNavigationReset() signal keyboardNavigationReset
signal itemClicked(int index, var modelData) signal itemClicked(int index, var modelData)
signal itemHovered(int index) signal itemHovered(int index)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY) signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
function ensureVisible(index) { function ensureVisible(index) {
if (index < 0 || index >= count) if (index < 0 || index >= count)
return; return
var itemY = Math.floor(index / actualColumns) * cellHeight; var itemY = Math.floor(index / actualColumns) * cellHeight
var itemBottom = itemY + cellHeight; var itemBottom = itemY + cellHeight
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height)
contentY = itemBottom - height; contentY = itemBottom - height
} }
anchors.fill: parent anchors.fill: parent
@@ -585,20 +630,20 @@ PanelWindow {
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (keyboardNavigationActive) if (keyboardNavigationActive)
ensureVisible(currentIndex); ensureVisible(currentIndex)
} }
onItemClicked: function (index, modelData) { onItemClicked: function (index, modelData) {
appLauncher.launchApp(modelData); appLauncher.launchApp(modelData)
} }
onItemHovered: function (index) { onItemHovered: function (index) {
appLauncher.selectedIndex = index; appLauncher.selectedIndex = index
} }
onItemRightClicked: function (index, modelData, mouseX, mouseY) { onItemRightClicked: function (index, modelData, mouseX, mouseY) {
contextMenu.show(mouseX, mouseY, modelData); contextMenu.show(mouseX, mouseY, modelData)
} }
onKeyboardNavigationReset: { onKeyboardNavigationReset: {
appLauncher.keyboardNavigationActive = false; appLauncher.keyboardNavigationActive = false
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@@ -613,8 +658,9 @@ PanelWindow {
width: appGrid.cellWidth - appGrid.cellPadding width: appGrid.cellWidth - appGrid.cellPadding
height: appGrid.cellHeight - appGrid.cellPadding height: appGrid.cellHeight - appGrid.cellPadding
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: appGrid.currentIndex === index ? Theme.primaryPressed : mouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
border.color: appGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium border.color: appGrid.currentIndex
=== index ? Theme.primarySelected : Theme.outlineMedium
border.width: appGrid.currentIndex === index ? 2 : 1 border.width: appGrid.currentIndex === index ? 2 : 1
Column { Column {
@@ -622,17 +668,22 @@ PanelWindow {
spacing: Theme.spacingS spacing: Theme.spacingS
Item { Item {
property int iconSize: Math.min(appGrid.maxIconSize, Math.max(appGrid.minIconSize, appGrid.cellWidth * appGrid.iconSizeRatio)) property int iconSize: Math.min(
appGrid.maxIconSize, Math.max(
appGrid.minIconSize,
appGrid.cellWidth * appGrid.iconSizeRatio))
width: iconSize width: iconSize
height: iconSize height: iconSize
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
IconImage { IconImage {
id: iconImg id: gridIconImg
anchors.fill: parent anchors.fill: parent
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : "" source: (model.icon) ? Quickshell.iconPath(
model.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
@@ -640,7 +691,7 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
visible: !iconImg.visible visible: !gridIconImg.visible
color: Theme.surfaceLight color: Theme.surfaceLight
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.width: 1 border.width: 1
@@ -648,7 +699,10 @@ PanelWindow {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A" text: (model.name
&& model.name.length > 0) ? model.name.charAt(
0).toUpperCase(
) : "A"
font.pixelSize: Math.min(28, parent.width * 0.5) font.pixelSize: Math.min(28, parent.width * 0.5)
color: Theme.primary color: Theme.primary
font.weight: Font.Bold font.weight: Font.Bold
@@ -671,7 +725,7 @@ PanelWindow {
} }
MouseArea { MouseArea {
id: mouseArea id: gridMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
@@ -679,34 +733,32 @@ PanelWindow {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
z: 10 z: 10
onEntered: { onEntered: {
if (appGrid.hoverUpdatesSelection && !appGrid.keyboardNavigationActive) if (appGrid.hoverUpdatesSelection
appGrid.currentIndex = index; && !appGrid.keyboardNavigationActive)
appGrid.currentIndex = index
appGrid.itemHovered(index); appGrid.itemHovered(index)
} }
onPositionChanged: { onPositionChanged: {
appGrid.keyboardNavigationReset(); appGrid.keyboardNavigationReset()
} }
onClicked: (mouse) => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
appGrid.itemClicked(index, model); appGrid.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
var globalPos = mapToGlobal(mouse.x, mouse.y); var globalPos = mapToGlobal(mouse.x, mouse.y)
appGrid.itemRightClicked(index, model, globalPos.x, globalPos.y); appGrid.itemRightClicked(index, model,
globalPos.x,
globalPos.y)
} }
} }
} }
} }
} }
} }
} }
} }
} }
} }
Popup { Popup {
@@ -715,25 +767,26 @@ PanelWindow {
property var currentApp: null property var currentApp: null
function show(x, y, app) { function show(x, y, app) {
currentApp = app; currentApp = app
if (!contextMenu.parent && typeof Overlay !== "undefined" && Overlay.overlay) if (!contextMenu.parent && typeof Overlay !== "undefined"
contextMenu.parent = Overlay.overlay; && Overlay.overlay)
contextMenu.parent = Overlay.overlay
const menuWidth = 180; const menuWidth = 180
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2; const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
const screenWidth = Screen.width; const screenWidth = Screen.width
const screenHeight = Screen.height; const screenHeight = Screen.height
let finalX = x; let finalX = x
let finalY = y; let finalY = y
if (x + menuWidth > screenWidth - 20) if (x + menuWidth > screenWidth - 20)
finalX = x - menuWidth; finalX = x - menuWidth
if (y + menuHeight > screenHeight - 20) if (y + menuHeight > screenHeight - 20)
finalY = y - menuHeight; finalY = y - menuHeight
contextMenu.x = Math.max(20, finalX); contextMenu.x = Math.max(20, finalX)
contextMenu.y = Math.max(20, finalY); contextMenu.y = Math.max(20, finalY)
open(); open()
} }
width: 180 width: 180
@@ -742,10 +795,10 @@ PanelWindow {
modal: false modal: false
closePolicy: Popup.CloseOnEscape closePolicy: Popup.CloseOnEscape
onClosed: { onClosed: {
closePolicy = Popup.CloseOnEscape; closePolicy = Popup.CloseOnEscape
} }
onOpened: { onOpened: {
outsideClickTimer.start(); outsideClickTimer.start()
} }
Timer { Timer {
@@ -753,7 +806,7 @@ PanelWindow {
interval: 100 interval: 100
onTriggered: { onTriggered: {
contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside; contextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside
} }
} }
@@ -764,7 +817,8 @@ PanelWindow {
contentItem: Rectangle { contentItem: Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
Column { Column {
@@ -778,7 +832,10 @@ PanelWindow {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -788,11 +845,13 @@ PanelWindow {
DankIcon { DankIcon {
name: { name: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) if (!contextMenu.currentApp
return "push_pin"; || !contextMenu.currentApp.desktopEntry)
return "push_pin"
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""; var appId = contextMenu.currentApp.desktopEntry.id
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin"; || contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin"
} }
size: Theme.iconSize - 2 size: Theme.iconSize - 2
color: Theme.surfaceText color: Theme.surfaceText
@@ -802,18 +861,20 @@ PanelWindow {
StyledText { StyledText {
text: { text: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) if (!contextMenu.currentApp
return "Pin to Dock"; || !contextMenu.currentApp.desktopEntry)
return "Pin to Dock"
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""; var appId = contextMenu.currentApp.desktopEntry.id
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock"; || contextMenu.currentApp.desktopEntry.execString || ""
return SessionData.isPinnedApp(
appId) ? "Unpin from Dock" : "Pin to Dock"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -823,18 +884,19 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry) if (!contextMenu.currentApp
return ; || !contextMenu.currentApp.desktopEntry)
return
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""; var appId = contextMenu.currentApp.desktopEntry.id
|| contextMenu.currentApp.desktopEntry.execString || ""
if (SessionData.isPinnedApp(appId)) if (SessionData.isPinnedApp(appId))
SessionData.removePinnedApp(appId); SessionData.removePinnedApp(appId)
else else
SessionData.addPinnedApp(appId); SessionData.addPinnedApp(appId)
contextMenu.close(); contextMenu.close()
} }
} }
} }
Rectangle { Rectangle {
@@ -847,16 +909,19 @@ PanelWindow {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width width: parent.width
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -879,7 +944,6 @@ PanelWindow {
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -890,18 +954,13 @@ PanelWindow {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (contextMenu.currentApp) if (contextMenu.currentApp)
appLauncher.launchApp(contextMenu.currentApp); appLauncher.launchApp(contextMenu.currentApp)
contextMenu.close(); contextMenu.close()
} }
} }
} }
} }
} }
} }
} }

View File

@@ -18,16 +18,18 @@ Item {
property int debounceInterval: 50 property int debounceInterval: 50
property bool keyboardNavigationActive: false property bool keyboardNavigationActive: false
property var categories: { property var categories: {
var allCategories = AppSearchService.getAllCategories().filter((cat) => { var allCategories = AppSearchService.getAllCategories().filter(cat => {
return cat !== "Education" && cat !== "Science"; return cat !== "Education"
}); && cat !== "Science"
var result = ["All"]; })
return result.concat(allCategories.filter((cat) => { var result = ["All"]
return cat !== "All"; return result.concat(allCategories.filter(cat => {
})); return cat !== "All"
}))
} }
property var categoryIcons: categories.map((category) => { property var categoryIcons: categories.map(category => {
return AppSearchService.getCategoryIcon(category); return AppSearchService.getCategoryIcon(
category)
}) })
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {} property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
property alias model: filteredModel property alias model: filteredModel
@@ -38,136 +40,140 @@ Item {
signal viewModeSelected(string mode) signal viewModeSelected(string mode)
function updateFilteredModel() { function updateFilteredModel() {
filteredModel.clear(); filteredModel.clear()
selectedIndex = 0; selectedIndex = 0
keyboardNavigationActive = false; keyboardNavigationActive = false
var apps = []; var apps = []
if (searchQuery.length === 0) { if (searchQuery.length === 0) {
if (selectedCategory === "All") { if (selectedCategory === "All") {
apps = AppSearchService.applications || []; apps = AppSearchService.applications || []
} else { } else {
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory); var categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
apps = categoryApps.slice(0, maxResults); apps = categoryApps.slice(0, maxResults)
} }
} else { } else {
if (selectedCategory === "All") { if (selectedCategory === "All") {
apps = AppSearchService.searchApplications(searchQuery); apps = AppSearchService.searchApplications(searchQuery)
} else { } else {
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory); var categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
if (categoryApps.length > 0) { if (categoryApps.length > 0) {
var allSearchResults = AppSearchService.searchApplications(searchQuery); var allSearchResults = AppSearchService.searchApplications(
var categoryNames = new Set(categoryApps.map((app) => { searchQuery)
return app.name; var categoryNames = new Set(categoryApps.map(app => {
})); return app.name
apps = allSearchResults.filter((searchApp) => { }))
return categoryNames.has(searchApp.name); apps = allSearchResults.filter(searchApp => {
}).slice(0, maxResults); return categoryNames.has(
searchApp.name)
}).slice(0, maxResults)
} else { } else {
apps = []; apps = []
} }
} }
} }
if (searchQuery.length === 0) if (searchQuery.length === 0)
apps = apps.sort(function (a, b) { apps = apps.sort(function (a, b) {
var aId = a.id || (a.execString || a.exec || ""); var aId = a.id || (a.execString || a.exec || "")
var bId = b.id || (b.execString || b.exec || ""); var bId = b.id || (b.execString || b.exec || "")
var aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0; var aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0
var bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0; var bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0
if (aUsage !== bUsage) if (aUsage !== bUsage)
return bUsage - aUsage; return bUsage - aUsage
return (a.name || "").localeCompare(b.name || ""); return (a.name || "").localeCompare(b.name || "")
}); })
apps.forEach((app) => { apps.forEach(app => {
if (app) if (app)
filteredModel.append({ filteredModel.append({
"name": app.name || "", "name": app.name || "",
"exec": app.execString || "", "exec": app.execString || "",
"icon": app.icon || "application-x-executable", "icon": app.icon
|| "application-x-executable",
"comment": app.comment || "", "comment": app.comment || "",
"categories": app.categories || [], "categories": app.categories || [],
"desktopEntry": app "desktopEntry": app
}); })
})
});
} }
function selectNext() { function selectNext() {
if (filteredModel.count > 0) { if (filteredModel.count > 0) {
keyboardNavigationActive = true; keyboardNavigationActive = true
if (viewMode === "grid") { if (viewMode === "grid") {
var newIndex = Math.min(selectedIndex + gridColumns, filteredModel.count - 1); var newIndex = Math.min(selectedIndex + gridColumns,
selectedIndex = newIndex; filteredModel.count - 1)
selectedIndex = newIndex
} else { } else {
selectedIndex = (selectedIndex + 1) % filteredModel.count; selectedIndex = (selectedIndex + 1) % filteredModel.count
} }
} }
} }
function selectPrevious() { function selectPrevious() {
if (filteredModel.count > 0) { if (filteredModel.count > 0) {
keyboardNavigationActive = true; keyboardNavigationActive = true
if (viewMode === "grid") { if (viewMode === "grid") {
var newIndex = Math.max(selectedIndex - gridColumns, 0); var newIndex = Math.max(selectedIndex - gridColumns, 0)
selectedIndex = newIndex; selectedIndex = newIndex
} else { } else {
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : filteredModel.count - 1; selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : filteredModel.count - 1
} }
} }
} }
function selectNextInRow() { function selectNextInRow() {
if (filteredModel.count > 0 && viewMode === "grid") { if (filteredModel.count > 0 && viewMode === "grid") {
keyboardNavigationActive = true; keyboardNavigationActive = true
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1); selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1)
} }
} }
function selectPreviousInRow() { function selectPreviousInRow() {
if (filteredModel.count > 0 && viewMode === "grid") { if (filteredModel.count > 0 && viewMode === "grid") {
keyboardNavigationActive = true; keyboardNavigationActive = true
selectedIndex = Math.max(selectedIndex - 1, 0); selectedIndex = Math.max(selectedIndex - 1, 0)
} }
} }
function launchSelected() { function launchSelected() {
if (filteredModel.count > 0 && selectedIndex >= 0 && selectedIndex < filteredModel.count) { if (filteredModel.count > 0 && selectedIndex >= 0
var selectedApp = filteredModel.get(selectedIndex); && selectedIndex < filteredModel.count) {
launchApp(selectedApp); var selectedApp = filteredModel.get(selectedIndex)
launchApp(selectedApp)
} }
} }
function launchApp(appData) { function launchApp(appData) {
if (!appData) if (!appData)
return ; return
appData.desktopEntry.execute(); appData.desktopEntry.execute()
appLaunched(appData); appLaunched(appData)
AppUsageHistoryData.addAppUsage(appData.desktopEntry); AppUsageHistoryData.addAppUsage(appData.desktopEntry)
} }
function setCategory(category) { function setCategory(category) {
selectedCategory = category; selectedCategory = category
categorySelected(category); categorySelected(category)
} }
function setViewMode(mode) { function setViewMode(mode) {
viewMode = mode; viewMode = mode
viewModeSelected(mode); viewModeSelected(mode)
} }
onSearchQueryChanged: { onSearchQueryChanged: {
if (debounceSearch) if (debounceSearch)
searchDebounceTimer.restart(); searchDebounceTimer.restart()
else else
updateFilteredModel(); updateFilteredModel()
} }
onSelectedCategoryChanged: updateFilteredModel() onSelectedCategoryChanged: updateFilteredModel()
onAppUsageRankingChanged: updateFilteredModel() onAppUsageRankingChanged: updateFilteredModel()
on_WatchApplicationsChanged: updateFilteredModel() on_WatchApplicationsChanged: updateFilteredModel()
Component.onCompleted: { Component.onCompleted: {
updateFilteredModel(); updateFilteredModel()
} }
ListModel { ListModel {
@@ -181,5 +187,4 @@ Item {
repeat: false repeat: false
onTriggered: updateFilteredModel() onTriggered: updateFilteredModel()
} }
} }

View File

@@ -20,14 +20,20 @@ Item {
spacing: Theme.spacingS spacing: Theme.spacingS
Repeater { Repeater {
model: categories.slice(0, Math.min(categories.length, 8)) // Limit for space model: categories.slice(0, Math.min(categories.length,
8)) // Limit for space
Rectangle { Rectangle {
height: 36 height: 36
width: (parent.width - (Math.min(categories.length, 8) - 1) * Theme.spacingS) / Math.min(categories.length, 8) width: (parent.width - (Math.min(categories.length,
8) - 1) * Theme.spacingS) / Math.min(
categories.length, 8)
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: selectedCategory === modelData ? Theme.primary : "transparent" color: selectedCategory === modelData ? Theme.primary : "transparent"
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.3)
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -43,15 +49,12 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
selectedCategory = modelData; selectedCategory = modelData
categorySelected(modelData); categorySelected(modelData)
} }
} }
} }
} }
} }
Column { Column {
@@ -66,16 +69,20 @@ Item {
spacing: Theme.spacingS spacing: Theme.spacingS
Repeater { Repeater {
model: parent.topRowCategories.filter((cat) => { model: parent.topRowCategories.filter(cat => {
return categories.includes(cat); return categories.includes(cat)
}) })
Rectangle { Rectangle {
height: 36 height: 36
width: (parent.width - (parent.topRowCategories.length - 1) * Theme.spacingS) / parent.topRowCategories.length width: (parent.width - (parent.topRowCategories.length - 1)
* Theme.spacingS) / parent.topRowCategories.length
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: selectedCategory === modelData ? Theme.primary : "transparent" color: selectedCategory === modelData ? Theme.primary : "transparent"
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.3)
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -91,15 +98,12 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
selectedCategory = modelData; selectedCategory = modelData
categorySelected(modelData); categorySelected(modelData)
} }
} }
} }
} }
} }
Row { Row {
@@ -109,16 +113,21 @@ Item {
spacing: Theme.spacingS spacing: Theme.spacingS
Repeater { Repeater {
model: parent.bottomRowCategories.filter((cat) => { model: parent.bottomRowCategories.filter(cat => {
return categories.includes(cat); return categories.includes(
cat)
}) })
Rectangle { Rectangle {
height: 36 height: 36
width: (parent.width - (parent.bottomRowCategories.length - 1) * Theme.spacingS) / parent.bottomRowCategories.length width: (parent.width - (parent.bottomRowCategories.length - 1)
* Theme.spacingS) / parent.bottomRowCategories.length
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: selectedCategory === modelData ? Theme.primary : "transparent" color: selectedCategory === modelData ? Theme.primary : "transparent"
border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) border.color: selectedCategory === modelData ? "transparent" : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.3)
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -134,17 +143,12 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
selectedCategory = modelData; selectedCategory = modelData
categorySelected(modelData); categorySelected(modelData)
} }
} }
} }
} }
} }
} }
} }

View File

@@ -20,18 +20,18 @@ PanelWindow {
interval: BrightnessService.ddcAvailable ? 500 : 50 interval: BrightnessService.ddcAvailable ? 500 : 50
repeat: false repeat: false
onTriggered: { onTriggered: {
BrightnessService.setBrightnessInternal(pendingValue); BrightnessService.setBrightnessInternal(pendingValue)
} }
} }
function show() { function show() {
root.brightnessPopupVisible = true; root.brightnessPopupVisible = true
hideTimer.restart(); hideTimer.restart()
} }
function resetHideTimer() { function resetHideTimer() {
if (root.brightnessPopupVisible) if (root.brightnessPopupVisible)
hideTimer.restart(); hideTimer.restart()
} }
screen: modelData screen: modelData
@@ -55,15 +55,15 @@ PanelWindow {
repeat: false repeat: false
onTriggered: { onTriggered: {
if (!brightnessPopup.containsMouse) if (!brightnessPopup.containsMouse)
root.brightnessPopupVisible = false; root.brightnessPopupVisible = false
else else
hideTimer.restart(); hideTimer.restart()
} }
} }
Connections { Connections {
function onBrightnessChanged() { function onBrightnessChanged() {
root.show(); root.show()
} }
target: BrightnessService target: BrightnessService
@@ -81,7 +81,8 @@ PanelWindow {
anchors.bottomMargin: Theme.spacingM anchors.bottomMargin: Theme.spacingM
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: root.brightnessPopupVisible ? 1 : 0 opacity: root.brightnessPopupVisible ? 1 : 0
scale: root.brightnessPopupVisible ? 1 : 0.9 scale: root.brightnessPopupVisible ? 1 : 0.9
@@ -110,8 +111,9 @@ PanelWindow {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: BrightnessService.brightnessLevel < 30 ? "brightness_low" : name: BrightnessService.brightnessLevel
BrightnessService.brightnessLevel < 70 ? "brightness_medium" : "brightness_high" < 30 ? "brightness_low" : BrightnessService.brightnessLevel
< 70 ? "brightness_medium" : "brightness_high"
size: Theme.iconSize size: Theme.iconSize
color: Theme.primary color: Theme.primary
} }
@@ -131,25 +133,25 @@ PanelWindow {
unit: "%" unit: "%"
Component.onCompleted: { Component.onCompleted: {
if (BrightnessService.brightnessAvailable) if (BrightnessService.brightnessAvailable)
value = BrightnessService.brightnessLevel; value = BrightnessService.brightnessLevel
} }
onSliderValueChanged: function (newValue) { onSliderValueChanged: function (newValue) {
if (BrightnessService.brightnessAvailable) { if (BrightnessService.brightnessAvailable) {
brightnessDebounceTimer.pendingValue = newValue; brightnessDebounceTimer.pendingValue = newValue
brightnessDebounceTimer.restart(); brightnessDebounceTimer.restart()
root.resetHideTimer(); root.resetHideTimer()
} }
} }
onSliderDragFinished: function (finalValue) { onSliderDragFinished: function (finalValue) {
if (BrightnessService.brightnessAvailable) { if (BrightnessService.brightnessAvailable) {
brightnessDebounceTimer.stop(); brightnessDebounceTimer.stop()
BrightnessService.setBrightnessInternal(finalValue); BrightnessService.setBrightnessInternal(finalValue)
} }
} }
Connections { Connections {
function onBrightnessChanged() { function onBrightnessChanged() {
brightnessSlider.value = BrightnessService.brightnessLevel; brightnessSlider.value = BrightnessService.brightnessLevel
} }
target: BrightnessService target: BrightnessService

View File

@@ -13,31 +13,33 @@ Column {
function loadEventsForMonth() { function loadEventsForMonth() {
if (!CalendarService || !CalendarService.khalAvailable) if (!CalendarService || !CalendarService.khalAvailable)
return ; return
let firstDay = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1); let firstDay = new Date(displayDate.getFullYear(),
let dayOfWeek = firstDay.getDay(); displayDate.getMonth(), 1)
let startDate = new Date(firstDay); let dayOfWeek = firstDay.getDay()
startDate.setDate(startDate.getDate() - dayOfWeek - 7); // Extra week padding let startDate = new Date(firstDay)
let lastDay = new Date(displayDate.getFullYear(), displayDate.getMonth() + 1, 0); startDate.setDate(startDate.getDate() - dayOfWeek - 7) // Extra week padding
let endDate = new Date(lastDay); let lastDay = new Date(displayDate.getFullYear(),
endDate.setDate(endDate.getDate() + (6 - lastDay.getDay()) + 7); // Extra week padding displayDate.getMonth() + 1, 0)
CalendarService.loadEvents(startDate, endDate); let endDate = new Date(lastDay)
endDate.setDate(endDate.getDate() + (6 - lastDay.getDay(
)) + 7) // Extra week padding
CalendarService.loadEvents(startDate, endDate)
} }
spacing: Theme.spacingM spacing: Theme.spacingM
onDisplayDateChanged: { onDisplayDateChanged: {
loadEventsForMonth(); loadEventsForMonth()
} }
Component.onCompleted: { Component.onCompleted: {
loadEventsForMonth(); loadEventsForMonth()
} }
Connections { Connections {
function onKhalAvailableChanged() { function onKhalAvailableChanged() {
if (CalendarService && CalendarService.khalAvailable) if (CalendarService && CalendarService.khalAvailable)
loadEventsForMonth(); loadEventsForMonth()
} }
target: CalendarService target: CalendarService
@@ -52,7 +54,10 @@ Column {
width: 40 width: 40
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -68,12 +73,11 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
let newDate = new Date(displayDate); let newDate = new Date(displayDate)
newDate.setMonth(newDate.getMonth() - 1); newDate.setMonth(newDate.getMonth() - 1)
displayDate = newDate; displayDate = newDate
} }
} }
} }
StyledText { StyledText {
@@ -91,7 +95,10 @@ Column {
width: 40 width: 40
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -107,14 +114,12 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
let newDate = new Date(displayDate); let newDate = new Date(displayDate)
newDate.setMonth(newDate.getMonth() + 1); newDate.setMonth(newDate.getMonth() + 1)
displayDate = newDate; displayDate = newDate
} }
} }
} }
} }
Row { Row {
@@ -133,22 +138,20 @@ Column {
anchors.centerIn: parent anchors.centerIn: parent
text: modelData text: modelData
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
font.weight: Font.Medium font.weight: Font.Medium
} }
} }
} }
} }
Grid { Grid {
property date firstDay: { property date firstDay: {
let date = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1); let date = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1)
let dayOfWeek = date.getDay(); let dayOfWeek = date.getDay()
date.setDate(date.getDate() - dayOfWeek); date.setDate(date.getDate() - dayOfWeek)
return date; return date
} }
width: parent.width width: parent.width
@@ -161,13 +164,16 @@ Column {
Rectangle { Rectangle {
property date dayDate: { property date dayDate: {
let date = new Date(parent.firstDay); let date = new Date(parent.firstDay)
date.setDate(date.getDate() + index); date.setDate(date.getDate() + index)
return date; return date
} }
property bool isCurrentMonth: dayDate.getMonth() === displayDate.getMonth() property bool isCurrentMonth: dayDate.getMonth(
property bool isToday: dayDate.toDateString() === new Date().toDateString() ) === displayDate.getMonth()
property bool isSelected: dayDate.toDateString() === selectedDate.toDateString() property bool isToday: dayDate.toDateString(
) === new Date().toDateString()
property bool isSelected: dayDate.toDateString(
) === selectedDate.toDateString()
width: parent.width / 7 width: parent.width / 7
height: parent.height / 6 height: parent.height / 6
@@ -178,7 +184,11 @@ Column {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width - 4 width: parent.width - 4
height: parent.height - 4 height: parent.height - 4
color: isSelected ? Theme.primary : isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" color: isSelected ? Theme.primary : isToday ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
clip: true clip: true
@@ -195,14 +205,15 @@ Column {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
visible: CalendarService && CalendarService.khalAvailable && CalendarService.hasEventsForDate(dayDate) visible: CalendarService && CalendarService.khalAvailable
&& CalendarService.hasEventsForDate(dayDate)
opacity: { opacity: {
if (isSelected) if (isSelected)
return 0.9; return 0.9
else if (isToday) else if (isToday)
return 0.8; return 0.8
else else
return 0.6; return 0.6
} }
gradient: Gradient { gradient: Gradient {
@@ -215,11 +226,11 @@ Column {
position: 0.9 position: 0.9
color: { color: {
if (isSelected) if (isSelected)
return Qt.lighter(Theme.primary, 1.3); return Qt.lighter(Theme.primary, 1.3)
else if (isToday) else if (isToday)
return Theme.primary; return Theme.primary
else else
return Theme.primary; return Theme.primary
} }
} }
@@ -227,14 +238,13 @@ Column {
position: 1 position: 1
color: { color: {
if (isSelected) if (isSelected)
return Qt.lighter(Theme.primary, 1.3); return Qt.lighter(Theme.primary, 1.3)
else if (isToday) else if (isToday)
return Theme.primary; return Theme.primary
else else
return Theme.primary; return Theme.primary
} }
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -242,11 +252,8 @@ Column {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -256,14 +263,10 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
selectedDate = dayDate; selectedDate = dayDate
} }
} }
} }
} }
} }
} }

View File

@@ -22,30 +22,29 @@ PanelWindow {
property var triggerScreen: null property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) { function setTriggerPosition(x, y, width, section, screen) {
triggerX = x; triggerX = x
triggerY = y; triggerY = y
triggerWidth = width; triggerWidth = width
triggerSection = section; triggerSection = section
triggerScreen = screen; triggerScreen = screen
} }
visible: internalVisible visible: internalVisible
screen: triggerScreen screen: triggerScreen
onCalendarVisibleChanged: { onCalendarVisibleChanged: {
if (calendarVisible) { if (calendarVisible) {
internalVisible = true; internalVisible = true
Qt.callLater(() => { Qt.callLater(() => {
internalVisible = true; internalVisible = true
calendarGrid.loadEventsForMonth(); calendarGrid.loadEventsForMonth()
}); })
} else { } else {
internalVisible = false; internalVisible = false
} }
} }
onVisibleChanged: { onVisibleChanged: {
if (visible && calendarGrid) if (visible && calendarGrid)
calendarGrid.loadEventsForMonth(); calendarGrid.loadEventsForMonth()
} }
implicitWidth: 480 implicitWidth: 480
implicitHeight: 600 implicitHeight: 600
@@ -64,61 +63,69 @@ PanelWindow {
Rectangle { Rectangle {
id: mainContainer id: mainContainer
readonly property real targetWidth: Math.min((root.screen ? root.screen.width : Screen.width) * 0.9, 600) readonly property real targetWidth: Math.min(
(root.screen ? root.screen.width : Screen.width) * 0.9,
600)
function calculateWidth() { function calculateWidth() {
let baseWidth = 320; let baseWidth = 320
if (leftWidgets.hasAnyWidgets) if (leftWidgets.hasAnyWidgets)
return Math.min(parent.width * 0.9, 600); return Math.min(parent.width * 0.9, 600)
return Math.min(parent.width * 0.7, 400); return Math.min(parent.width * 0.7, 400)
} }
function calculateHeight() { function calculateHeight() {
let contentHeight = Theme.spacingM * 2; // margins let contentHeight = Theme.spacingM * 2
let widgetHeight = 160; // margins
widgetHeight += 140 + Theme.spacingM; let widgetHeight = 160
let calendarHeight = 300; widgetHeight += 140 + Theme.spacingM
let mainRowHeight = Math.max(widgetHeight, calendarHeight); let calendarHeight = 300
contentHeight += mainRowHeight + Theme.spacingM; let mainRowHeight = Math.max(widgetHeight, calendarHeight)
contentHeight += mainRowHeight + Theme.spacingM
if (CalendarService && CalendarService.khalAvailable) { if (CalendarService && CalendarService.khalAvailable) {
let hasEvents = events.selectedDateEvents && events.selectedDateEvents.length > 0; let hasEvents = events.selectedDateEvents
let eventsHeight = hasEvents ? Math.min(300, 80 + events.selectedDateEvents.length * 60) : 120; && events.selectedDateEvents.length > 0
contentHeight += eventsHeight; let eventsHeight = hasEvents ? Math.min(
300,
80 + events.selectedDateEvents.length * 60) : 120
contentHeight += eventsHeight
} else { } else {
contentHeight -= Theme.spacingM; contentHeight -= Theme.spacingM
} }
return Math.min(contentHeight, parent.height * 0.9); return Math.min(contentHeight, parent.height * 0.9)
} }
readonly property real calculatedX: { readonly property real calculatedX: {
var screenWidth = root.screen ? root.screen.width : Screen.width; var screenWidth = root.screen ? root.screen.width : Screen.width
if (root.triggerSection === "center") { if (root.triggerSection === "center") {
return (screenWidth - targetWidth) / 2; return (screenWidth - targetWidth) / 2
} }
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2); var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) { if (centerX >= Theme.spacingM
return centerX; && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
} }
if (centerX < Theme.spacingM) { if (centerX < Theme.spacingM) {
return Theme.spacingM; return Theme.spacingM
} }
if (centerX + targetWidth > screenWidth - Theme.spacingM) { if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM; return screenWidth - targetWidth - Theme.spacingM
} }
return centerX; return centerX
} }
width: targetWidth width: targetWidth
height: calculateHeight() height: calculateHeight()
color: Theme.surfaceContainer color: Theme.surfaceContainer
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
layer.enabled: true layer.enabled: true
opacity: calendarVisible ? 1 : 0 opacity: calendarVisible ? 1 : 0
@@ -128,22 +135,19 @@ PanelWindow {
onOpacityChanged: { onOpacityChanged: {
if (opacity === 1) if (opacity === 1)
Qt.callLater(() => { Qt.callLater(() => {
height = calculateHeight(); height = calculateHeight()
}); })
} }
Connections { Connections {
function onEventsByDateChanged() { function onEventsByDateChanged() {
if (mainContainer.opacity === 1) if (mainContainer.opacity === 1)
mainContainer.height = mainContainer.calculateHeight(); mainContainer.height = mainContainer.calculateHeight()
} }
function onKhalAvailableChanged() { function onKhalAvailableChanged() {
if (mainContainer.opacity === 1) if (mainContainer.opacity === 1)
mainContainer.height = mainContainer.calculateHeight(); mainContainer.height = mainContainer.calculateHeight()
} }
target: CalendarService target: CalendarService
@@ -153,8 +157,7 @@ PanelWindow {
Connections { Connections {
function onSelectedDateEventsChanged() { function onSelectedDateEventsChanged() {
if (mainContainer.opacity === 1) if (mainContainer.opacity === 1)
mainContainer.height = mainContainer.calculateHeight(); mainContainer.height = mainContainer.calculateHeight()
} }
target: events target: events
@@ -163,7 +166,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04) color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
Theme.surfaceTint.b, 0.04)
radius: parent.radius radius: parent.radius
SequentialAnimation on opacity { SequentialAnimation on opacity {
@@ -181,9 +185,7 @@ PanelWindow {
duration: Theme.extraLongDuration duration: Theme.extraLongDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Column { Column {
@@ -193,21 +195,23 @@ PanelWindow {
focus: true focus: true
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
calendarVisible = false; calendarVisible = false
event.accepted = true; event.accepted = true
} else { } else {
// Don't handle other keys - let them bubble up to modals // Don't handle other keys - let them bubble up to modals
event.accepted = false; event.accepted = false
} }
} }
Row { Row {
width: parent.width width: parent.width
height: { height: {
let widgetHeight = 160; // Media widget let widgetHeight = 160
widgetHeight += 140 + Theme.spacingM; // Weather/SystemInfo widget with spacing // Media widget
let calendarHeight = 300; // Calendar widgetHeight += 140 + Theme.spacingM // Weather/SystemInfo widget with spacing
return Math.max(widgetHeight, calendarHeight); let calendarHeight = 300
// Calendar
return Math.max(widgetHeight, calendarHeight)
} }
spacing: Theme.spacingM spacing: Theme.spacingM
@@ -238,15 +242,17 @@ PanelWindow {
height: 140 height: 140
visible: !SettingsData.weatherEnabled visible: !SettingsData.weatherEnabled
} }
} }
Rectangle { Rectangle {
width: leftWidgets.hasAnyWidgets ? parent.width - leftWidgets.width - Theme.spacingM : parent.width width: leftWidgets.hasAnyWidgets ? parent.width - leftWidgets.width
- Theme.spacingM : parent.width
height: parent.height height: parent.height
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
CalendarGrid { CalendarGrid {
@@ -255,9 +261,7 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
} }
} }
} }
Events { Events {
@@ -266,7 +270,6 @@ PanelWindow {
width: parent.width width: parent.width
selectedDate: calendarGrid.selectedDate selectedDate: calendarGrid.selectedDate
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -275,7 +278,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
Behavior on scale { Behavior on scale {
@@ -284,7 +286,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
@@ -295,7 +296,6 @@ PanelWindow {
shadowColor: Qt.rgba(0, 0, 0, 0.15) shadowColor: Qt.rgba(0, 0, 0, 0.15)
shadowOpacity: 0.15 shadowOpacity: 0.15
} }
} }
MouseArea { MouseArea {
@@ -303,11 +303,10 @@ PanelWindow {
z: -1 z: -1
enabled: calendarVisible enabled: calendarVisible
onClicked: function (mouse) { onClicked: function (mouse) {
var localPos = mapToItem(mainContainer, mouse.x, mouse.y); var localPos = mapToItem(mainContainer, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0 || localPos.y > mainContainer.height) if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0
calendarVisible = false; || localPos.y > mainContainer.height)
calendarVisible = false
} }
} }
} }

View File

@@ -15,38 +15,41 @@ Rectangle {
function updateSelectedDateEvents() { function updateSelectedDateEvents() {
if (CalendarService && CalendarService.khalAvailable) { if (CalendarService && CalendarService.khalAvailable) {
let events = CalendarService.getEventsForDate(selectedDate); let events = CalendarService.getEventsForDate(selectedDate)
selectedDateEvents = events; selectedDateEvents = events
} else { } else {
selectedDateEvents = []; selectedDateEvents = []
} }
} }
onSelectedDateEventsChanged: { onSelectedDateEventsChanged: {
eventsList.model = selectedDateEvents; eventsList.model = selectedDateEvents
} }
width: parent.width width: parent.width
height: shouldShow ? (hasEvents ? Math.min(300, 80 + selectedDateEvents.length * 60) : 120) : 0 height: shouldShow ? (hasEvents ? Math.min(
300,
80 + selectedDateEvents.length * 60) : 120) : 0
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.12)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 1
visible: shouldShow visible: shouldShow
layer.enabled: true layer.enabled: true
Component.onCompleted: { Component.onCompleted: {
updateSelectedDateEvents(); updateSelectedDateEvents()
} }
onSelectedDateChanged: { onSelectedDateChanged: {
updateSelectedDateEvents(); updateSelectedDateEvents()
} }
Connections { Connections {
function onEventsByDateChanged() { function onEventsByDateChanged() {
updateSelectedDateEvents(); updateSelectedDateEvents()
} }
function onKhalAvailableChanged() { function onKhalAvailableChanged() {
updateSelectedDateEvents(); updateSelectedDateEvents()
} }
target: CalendarService target: CalendarService
@@ -70,13 +73,17 @@ Rectangle {
} }
StyledText { StyledText {
text: hasEvents ? (Qt.formatDate(selectedDate, "MMM d") + " • " + (selectedDateEvents.length === 1 ? "1 event" : selectedDateEvents.length + " events")) : Qt.formatDate(selectedDate, "MMM d") text: hasEvents ? (Qt.formatDate(
selectedDate,
"MMM d") + " • " + (selectedDateEvents.length
=== 1 ? "1 event" : selectedDateEvents.length
+ " events")) : Qt.formatDate(
selectedDate, "MMM d")
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Column { Column {
@@ -87,18 +94,19 @@ Rectangle {
DankIcon { DankIcon {
name: "event_busy" name: "event_busy"
size: Theme.iconSize + 8 size: Theme.iconSize + 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
StyledText { StyledText {
text: "No events" text: "No events"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Normal font.weight: Font.Normal
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
DankListView { DankListView {
@@ -128,7 +136,7 @@ Rectangle {
WheelHandler { WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
property real momentum: 0 property real momentum: 0
onWheel: (event) => { onWheel: event => {
if (event.pixelDelta.y !== 0) { if (event.pixelDelta.y !== 0) {
// Touchpad with pixel delta // Touchpad with pixel delta
momentum = event.pixelDelta.y * 1.8 momentum = event.pixelDelta.y * 1.8
@@ -138,7 +146,9 @@ Rectangle {
} }
let newY = parent.contentY - momentum let newY = parent.contentY - momentum
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY)) newY = Math.max(0,
Math.min(parent.contentHeight - parent.height,
newY))
parent.contentY = newY parent.contentY = newY
momentum *= 0.92 // Decay for smooth momentum momentum *= 0.92 // Decay for smooth momentum
event.accepted = true event.accepted = true
@@ -146,7 +156,8 @@ Rectangle {
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
policy: eventsList.contentHeight > eventsList.height ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff policy: eventsList.contentHeight
> eventsList.height ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff
} }
Behavior on opacity { Behavior on opacity {
@@ -154,7 +165,6 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
delegate: Rectangle { delegate: Rectangle {
@@ -163,17 +173,21 @@ Rectangle {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (modelData.url && eventMouseArea.containsMouse) if (modelData.url && eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12); return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
else if (eventMouseArea.containsMouse) else if (eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06); return Qt.rgba(Theme.primary.r, Theme.primary.g,
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.06); Theme.primary.b, 0.06)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.06)
} }
border.color: { border.color: {
if (modelData.url && eventMouseArea.containsMouse) if (modelData.url && eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3); return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
else if (eventMouseArea.containsMouse) else if (eventMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15); return Qt.rgba(Theme.primary.r, Theme.primary.g,
return "transparent"; Theme.primary.b, 0.15)
return "transparent"
} }
border.width: 1 border.width: 1
@@ -223,29 +237,33 @@ Rectangle {
DankIcon { DankIcon {
name: "schedule" name: "schedule"
size: Theme.fontSizeSmall size: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: { text: {
if (modelData.allDay) { if (modelData.allDay) {
return "All day"; return "All day"
} else { } else {
let timeFormat = SettingsData.use24HourClock ? "H:mm" : "h:mm AP"; let timeFormat = SettingsData.use24HourClock ? "H:mm" : "h:mm AP"
let startTime = Qt.formatTime(modelData.start, timeFormat); let startTime = Qt.formatTime(modelData.start, timeFormat)
if (modelData.start.toDateString() !== modelData.end.toDateString() || modelData.start.getTime() !== modelData.end.getTime()) if (modelData.start.toDateString(
return startTime + " " + Qt.formatTime(modelData.end, timeFormat); ) !== modelData.end.toDateString()
|| modelData.start.getTime() !== modelData.end.getTime())
return startTime + " " + Qt.formatTime(modelData.end,
timeFormat)
return startTime; return startTime
} }
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -259,24 +277,23 @@ Rectangle {
DankIcon { DankIcon {
name: "location_on" name: "location_on"
size: Theme.fontSizeSmall size: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: modelData.location text: modelData.location
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
elide: Text.ElideRight elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
maximumLineCount: 1 maximumLineCount: 1
width: Math.min(implicitWidth, 200) width: Math.min(implicitWidth, 200)
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -289,8 +306,7 @@ Rectangle {
onClicked: { onClicked: {
if (modelData.url && modelData.url !== "") { if (modelData.url && modelData.url !== "") {
if (Qt.openUrlExternally(modelData.url) === false) if (Qt.openUrlExternally(modelData.url) === false)
console.warn("Failed to open URL: " + modelData.url); console.warn("Failed to open URL: " + modelData.url)
} }
} }
} }
@@ -300,7 +316,6 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on border.color { Behavior on border.color {
@@ -308,11 +323,8 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
@@ -329,7 +341,5 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }

View File

@@ -18,19 +18,21 @@ Rectangle {
property real currentPosition: 0 property real currentPosition: 0
function ratio() { function ratio() {
return activePlayer && activePlayer.length > 0 ? currentPosition / activePlayer.length : 0; return activePlayer
&& activePlayer.length > 0 ? currentPosition / activePlayer.length : 0
} }
onActivePlayerChanged: { onActivePlayerChanged: {
if (!activePlayer) if (!activePlayer)
updateTimer.start(); updateTimer.start()
else else
updateTimer.stop(); updateTimer.stop()
} }
width: parent.width width: parent.width
height: parent.height height: parent.height
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 1
layer.enabled: true layer.enabled: true
@@ -40,18 +42,22 @@ Rectangle {
interval: 2000 interval: 2000
running: { running: {
return (!activePlayer) || (activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing && activePlayer.length > 0 && !progressMouseArea.isSeeking); return (!activePlayer)
|| (activePlayer
&& activePlayer.playbackState === MprisPlaybackState.Playing
&& activePlayer.length > 0 && !progressMouseArea.isSeeking)
} }
repeat: true repeat: true
onTriggered: { onTriggered: {
if (!activePlayer) { if (!activePlayer) {
lastValidTitle = ""; lastValidTitle = ""
lastValidArtist = ""; lastValidArtist = ""
lastValidAlbum = ""; lastValidAlbum = ""
lastValidArtUrl = ""; lastValidArtUrl = ""
stop(); // Stop after clearing cache stop() // Stop after clearing cache
} else if (activePlayer.playbackState === MprisPlaybackState.Playing && !progressMouseArea.isSeeking) { } else if (activePlayer.playbackState === MprisPlaybackState.Playing
currentPosition = activePlayer.position; && !progressMouseArea.isSeeking) {
currentPosition = activePlayer.position
} }
} }
} }
@@ -59,16 +65,15 @@ Rectangle {
Connections { Connections {
function onPositionChanged() { function onPositionChanged() {
if (!progressMouseArea.isSeeking) if (!progressMouseArea.isSeeking)
currentPosition = activePlayer.position; currentPosition = activePlayer.position
} }
function onPostTrackChanged() { function onPostTrackChanged() {
currentPosition = activePlayer && activePlayer.position || 0; currentPosition = activePlayer && activePlayer.position || 0
} }
function onTrackTitleChanged() { function onTrackTitleChanged() {
currentPosition = activePlayer && activePlayer.position || 0; currentPosition = activePlayer && activePlayer.position || 0
} }
target: activePlayer target: activePlayer
@@ -81,28 +86,32 @@ Rectangle {
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Theme.spacingS spacing: Theme.spacingS
visible: (!activePlayer && !lastValidTitle) || (activePlayer && activePlayer.trackTitle === "" && lastValidTitle === "") visible: (!activePlayer && !lastValidTitle)
|| (activePlayer && activePlayer.trackTitle === ""
&& lastValidTitle === "")
DankIcon { DankIcon {
name: "music_note" name: "music_note"
size: Theme.iconSize + 8 size: Theme.iconSize + 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
StyledText { StyledText {
text: "No Media Playing" text: "No Media Playing"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
Column { Column {
anchors.fill: parent anchors.fill: parent
spacing: Theme.spacingS spacing: Theme.spacingS
visible: activePlayer && activePlayer.trackTitle !== "" || lastValidTitle !== "" visible: activePlayer && activePlayer.trackTitle !== ""
|| lastValidTitle !== ""
Row { Row {
width: parent.width width: parent.width
@@ -113,7 +122,8 @@ Rectangle {
width: 60 width: 60
height: 60 height: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
Item { Item {
anchors.fill: parent anchors.fill: parent
@@ -123,11 +133,11 @@ Rectangle {
id: albumArt id: albumArt
anchors.fill: parent anchors.fill: parent
source: activePlayer && activePlayer.trackArtUrl || lastValidArtUrl || "" source: activePlayer && activePlayer.trackArtUrl
|| lastValidArtUrl || ""
onSourceChanged: { onSourceChanged: {
if (activePlayer && activePlayer.trackArtUrl) if (activePlayer && activePlayer.trackArtUrl)
lastValidArtUrl = activePlayer.trackArtUrl; lastValidArtUrl = activePlayer.trackArtUrl
} }
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
smooth: true smooth: true
@@ -145,11 +155,8 @@ Rectangle {
size: 28 size: 28
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
} }
} }
} }
} }
Column { Column {
@@ -158,11 +165,11 @@ Rectangle {
spacing: Theme.spacingXS spacing: Theme.spacingXS
StyledText { StyledText {
text: activePlayer && activePlayer.trackTitle || lastValidTitle || "Unknown Track" text: activePlayer && activePlayer.trackTitle || lastValidTitle
|| "Unknown Track"
onTextChanged: { onTextChanged: {
if (activePlayer && activePlayer.trackTitle) if (activePlayer && activePlayer.trackTitle)
lastValidTitle = activePlayer.trackTitle; lastValidTitle = activePlayer.trackTitle
} }
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Bold font.weight: Font.Bold
@@ -174,14 +181,15 @@ Rectangle {
} }
StyledText { StyledText {
text: activePlayer && activePlayer.trackArtist || lastValidArtist || "Unknown Artist" text: activePlayer && activePlayer.trackArtist || lastValidArtist
|| "Unknown Artist"
onTextChanged: { onTextChanged: {
if (activePlayer && activePlayer.trackArtist) if (activePlayer && activePlayer.trackArtist)
lastValidArtist = activePlayer.trackArtist; lastValidArtist = activePlayer.trackArtist
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
@@ -189,23 +197,22 @@ Rectangle {
} }
StyledText { StyledText {
text: activePlayer && activePlayer.trackAlbum || lastValidAlbum || "" text: activePlayer && activePlayer.trackAlbum
|| lastValidAlbum || ""
onTextChanged: { onTextChanged: {
if (activePlayer && activePlayer.trackAlbum) if (activePlayer && activePlayer.trackAlbum)
lastValidAlbum = activePlayer.trackAlbum; lastValidAlbum = activePlayer.trackAlbum
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
maximumLineCount: 1 maximumLineCount: 1
visible: text.length > 0 visible: text.length > 0
} }
} }
} }
Item { Item {
@@ -220,7 +227,8 @@ Rectangle {
width: parent.width width: parent.width
height: 6 height: 6
radius: 3 radius: 3
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
visible: activePlayer !== null visible: activePlayer !== null
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -236,9 +244,7 @@ Rectangle {
NumberAnimation { NumberAnimation {
duration: 100 duration: 100
} }
} }
} }
Rectangle { Rectangle {
@@ -250,20 +256,19 @@ Rectangle {
color: Theme.primary color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3) border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 1 border.width: 1
x: Math.max(0, Math.min(parent.width - width, progressFill.width - width / 2)) x: Math.max(0, Math.min(parent.width - width,
progressFill.width - width / 2))
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: activePlayer && activePlayer.length > 0 visible: activePlayer && activePlayer.length > 0
scale: progressMouseArea.containsMouse || progressMouseArea.pressed ? 1.2 : 1 scale: progressMouseArea.containsMouse
|| progressMouseArea.pressed ? 1.2 : 1
Behavior on scale { Behavior on scale {
NumberAnimation { NumberAnimation {
duration: 150 duration: 150
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -274,34 +279,39 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
enabled: activePlayer && activePlayer.length > 0 && activePlayer.canSeek enabled: activePlayer && activePlayer.length > 0
&& activePlayer.canSeek
preventStealing: true preventStealing: true
onPressed: function (mouse) { onPressed: function (mouse) {
isSeeking = true; isSeeking = true
if (activePlayer && activePlayer.length > 0) { if (activePlayer && activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width)); let ratio = Math.max(0, Math.min(
let seekPosition = ratio * activePlayer.length; 1, mouse.x / progressBarBackground.width))
activePlayer.position = seekPosition; let seekPosition = ratio * activePlayer.length
currentPosition = seekPosition; activePlayer.position = seekPosition
currentPosition = seekPosition
} }
} }
onReleased: { onReleased: {
isSeeking = false; isSeeking = false
} }
onPositionChanged: function (mouse) { onPositionChanged: function (mouse) {
if (pressed && isSeeking && activePlayer && activePlayer.length > 0) { if (pressed && isSeeking && activePlayer
let ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width)); && activePlayer.length > 0) {
let seekPosition = ratio * activePlayer.length; let ratio = Math.max(0, Math.min(
activePlayer.position = seekPosition; 1, mouse.x / progressBarBackground.width))
currentPosition = seekPosition; let seekPosition = ratio * activePlayer.length
activePlayer.position = seekPosition
currentPosition = seekPosition
} }
} }
onClicked: function (mouse) { onClicked: function (mouse) {
if (activePlayer && activePlayer.length > 0) { if (activePlayer && activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(1, mouse.x / progressBarBackground.width)); let ratio = Math.max(0, Math.min(
let seekPosition = ratio * activePlayer.length; 1, mouse.x / progressBarBackground.width))
activePlayer.position = seekPosition; let seekPosition = ratio * activePlayer.length
currentPosition = seekPosition; activePlayer.position = seekPosition
currentPosition = seekPosition
} }
} }
} }
@@ -317,19 +327,20 @@ Rectangle {
visible: false visible: false
preventStealing: true preventStealing: true
onPositionChanged: function (mouse) { onPositionChanged: function (mouse) {
if (progressMouseArea.isSeeking && activePlayer && activePlayer.length > 0) { if (progressMouseArea.isSeeking && activePlayer
let globalPos = mapToItem(progressBarBackground, mouse.x, mouse.y); && activePlayer.length > 0) {
let ratio = Math.max(0, Math.min(1, globalPos.x / progressBarBackground.width)); let globalPos = mapToItem(progressBarBackground, mouse.x, mouse.y)
let seekPosition = ratio * activePlayer.length; let ratio = Math.max(
activePlayer.position = seekPosition; 0, Math.min(1, globalPos.x / progressBarBackground.width))
currentPosition = seekPosition; let seekPosition = ratio * activePlayer.length
activePlayer.position = seekPosition
currentPosition = seekPosition
} }
} }
onReleased: { onReleased: {
progressMouseArea.isSeeking = false; progressMouseArea.isSeeking = false
} }
} }
} }
Item { Item {
@@ -346,7 +357,10 @@ Rectangle {
width: 28 width: 28
height: 28 height: 28
radius: 14 radius: 14
color: prevBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent" color: prevBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.12) : "transparent"
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -363,17 +377,16 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!activePlayer) if (!activePlayer)
return ; return
if (currentPosition > 8 && activePlayer.canSeek) { if (currentPosition > 8 && activePlayer.canSeek) {
activePlayer.position = 0; activePlayer.position = 0
currentPosition = 0; currentPosition = 0
} else { } else {
activePlayer.previous(); activePlayer.previous()
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -384,7 +397,8 @@ Rectangle {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow" name: activePlayer && activePlayer.playbackState
=== MprisPlaybackState.Playing ? "pause" : "play_arrow"
size: 20 size: 20
color: Theme.background color: Theme.background
} }
@@ -395,14 +409,16 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: activePlayer && activePlayer.togglePlaying() onClicked: activePlayer && activePlayer.togglePlaying()
} }
} }
Rectangle { Rectangle {
width: 28 width: 28
height: 28 height: 28
radius: 14 radius: 14
color: nextBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent" color: nextBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.12) : "transparent"
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -419,15 +435,10 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: activePlayer && activePlayer.next() onClicked: activePlayer && activePlayer.next()
} }
} }
} }
} }
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
@@ -438,5 +449,4 @@ Rectangle {
shadowColor: Qt.rgba(0, 0, 0, 0.1) shadowColor: Qt.rgba(0, 0, 0, 0.1)
shadowOpacity: 0.1 shadowOpacity: 0.1
} }
} }

View File

@@ -7,7 +7,8 @@ Rectangle {
id: root id: root
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 1
@@ -46,13 +47,12 @@ Rectangle {
StyledText { StyledText {
text: SysMonitorService.distribution + " • " + SysMonitorService.architecture text: SysMonitorService.distribution + " • " + SysMonitorService.architecture
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
} }
Rectangle { Rectangle {
@@ -82,19 +82,20 @@ Rectangle {
} }
StyledText { StyledText {
text: SysMonitorService.processCount + " proc, " + SysMonitorService.threadCount + " threads" text: SysMonitorService.processCount + " proc, "
+ SysMonitorService.threadCount + " threads"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
} }
function formatUptime(uptime) { function formatUptime(uptime) {
if (!uptime) return "0m" if (!uptime)
return "0m"
// Parse the uptime string - handle formats like "1 week, 4 days, 3:45" or "4 days, 3:45" or "3:45" // Parse the uptime string - handle formats like "1 week, 4 days, 3:45" or "4 days, 3:45" or "3:45"
var uptimeStr = uptime.toString().trim() var uptimeStr = uptime.toString().trim()
@@ -130,7 +131,5 @@ Rectangle {
// Fallback - return as is but truncated // Fallback - return as is but truncated
return uptimeStr.length > 8 ? uptimeStr.substring(0, 8) + "…" : uptimeStr return uptimeStr.length > 8 ? uptimeStr.substring(0, 8) + "…" : uptimeStr
} }
} }

View File

@@ -11,7 +11,8 @@ Rectangle {
width: parent.width width: parent.width
height: parent.height height: parent.height
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.4) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 1
layer.enabled: true layer.enabled: true
@@ -23,29 +24,32 @@ Rectangle {
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Theme.spacingS spacing: Theme.spacingS
visible: !WeatherService.weather.available || WeatherService.weather.temp === 0 visible: !WeatherService.weather.available
|| WeatherService.weather.temp === 0
DankIcon { DankIcon {
name: "cloud_off" name: "cloud_off"
size: Theme.iconSize + 8 size: Theme.iconSize + 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
StyledText { StyledText {
text: "No Weather Data" text: "No Weather Data"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
Column { Column {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingL anchors.margins: Theme.spacingL
spacing: Theme.spacingS spacing: Theme.spacingS
visible: WeatherService.weather.available && WeatherService.weather.temp !== 0 visible: WeatherService.weather.available
&& WeatherService.weather.temp !== 0
Item { Item {
width: parent.width width: parent.width
@@ -67,7 +71,8 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°" + (SettingsData.useFahrenheit ? "F" : "C") text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)
+ "°" + (SettingsData.useFahrenheit ? "F" : "C")
font.pixelSize: Theme.fontSizeXLarge font.pixelSize: Theme.fontSizeXLarge
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Light font.weight: Font.Light
@@ -78,25 +83,21 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (WeatherService.weather.available) if (WeatherService.weather.available)
SettingsData.setTemperatureUnit(!SettingsData.useFahrenheit); SettingsData.setTemperatureUnit(!SettingsData.useFahrenheit)
} }
enabled: WeatherService.weather.available enabled: WeatherService.weather.available
} }
} }
StyledText { StyledText {
text: WeatherService.weather.city || "" text: WeatherService.weather.city || ""
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text.length > 0 visible: text.length > 0
} }
} }
} }
} }
Grid { Grid {
@@ -120,7 +121,6 @@ Rectangle {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -139,7 +139,6 @@ Rectangle {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -158,7 +157,6 @@ Rectangle {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -177,11 +175,8 @@ Rectangle {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
@@ -192,5 +187,4 @@ Rectangle {
shadowColor: Qt.rgba(0, 0, 0, 0.1) shadowColor: Qt.rgba(0, 0, 0, 0.1)
shadowOpacity: 0.1 shadowOpacity: 0.1
} }
} }

View File

@@ -11,7 +11,8 @@ import qs.Widgets
Column { Column {
id: root id: root
property string currentSinkDisplayName: AudioService.sink ? AudioService.displayName(AudioService.sink) : "" property string currentSinkDisplayName: AudioService.sink ? AudioService.displayName(
AudioService.sink) : ""
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
@@ -28,7 +29,8 @@ Column {
height: 35 height: 35
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 1 border.width: 1
visible: AudioService.sink !== null visible: AudioService.sink !== null
@@ -50,34 +52,33 @@ Column {
color: Theme.primary color: Theme.primary
font.weight: Font.Medium font.weight: Font.Medium
} }
} }
} }
Repeater { Repeater {
model: { model: {
if (!Pipewire.ready || !Pipewire.nodes || !Pipewire.nodes.values) if (!Pipewire.ready || !Pipewire.nodes || !Pipewire.nodes.values)
return []; return []
let sinks = []; let sinks = []
for (let i = 0; i < Pipewire.nodes.values.length; i++) { for (var i = 0; i < Pipewire.nodes.values.length; i++) {
let node = Pipewire.nodes.values[i]; let node = Pipewire.nodes.values[i]
if (!node || node.isStream) if (!node || node.isStream)
continue; continue
if ((node.type & PwNodeType.AudioSink) === PwNodeType.AudioSink) if ((node.type & PwNodeType.AudioSink) === PwNodeType.AudioSink)
sinks.push(node); sinks.push(node)
} }
return sinks; return sinks
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: deviceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (modelData === AudioService.sink ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)) color: deviceArea.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.08) : (modelData === AudioService.sink ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData === AudioService.sink ? Theme.primary : "transparent" border.color: modelData === AudioService.sink ? Theme.primary : "transparent"
border.width: 1 border.width: 1
@@ -90,13 +91,13 @@ Column {
DankIcon { DankIcon {
name: { name: {
if (modelData.name.includes("bluez")) if (modelData.name.includes("bluez"))
return "headset"; return "headset"
else if (modelData.name.includes("hdmi")) else if (modelData.name.includes("hdmi"))
return "tv"; return "tv"
else if (modelData.name.includes("usb")) else if (modelData.name.includes("usb"))
return "headset"; return "headset"
else else
return "speaker"; return "speaker"
} }
size: Theme.iconSize size: Theme.iconSize
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
@@ -116,18 +117,19 @@ Column {
StyledText { StyledText {
text: { text: {
if (AudioService.subtitle(modelData.name) && AudioService.subtitle(modelData.name) !== "") if (AudioService.subtitle(modelData.name)
return AudioService.subtitle(modelData.name) + (modelData === AudioService.sink ? " • Selected" : ""); && AudioService.subtitle(modelData.name) !== "")
return AudioService.subtitle(
modelData.name) + (modelData === AudioService.sink ? " • Selected" : "")
else else
return modelData === AudioService.sink ? "Selected" : ""; return modelData === AudioService.sink ? "Selected" : ""
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text !== "" visible: text !== ""
} }
} }
} }
MouseArea { MouseArea {
@@ -138,13 +140,9 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (modelData) if (modelData)
Pipewire.preferredDefaultAudioSink = modelData; Pipewire.preferredDefaultAudioSink = modelData
} }
} }
} }
} }
} }

View File

@@ -11,7 +11,8 @@ import qs.Widgets
Column { Column {
id: root id: root
property string currentSourceDisplayName: AudioService.source ? AudioService.displayName(AudioService.source) : "" property string currentSourceDisplayName: AudioService.source ? AudioService.displayName(
AudioService.source) : ""
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
@@ -28,7 +29,8 @@ Column {
height: 35 height: 35
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 1 border.width: 1
visible: AudioService.source !== null visible: AudioService.source !== null
@@ -50,34 +52,34 @@ Column {
color: Theme.primary color: Theme.primary
font.weight: Font.Medium font.weight: Font.Medium
} }
} }
} }
Repeater { Repeater {
model: { model: {
if (!Pipewire.ready || !Pipewire.nodes || !Pipewire.nodes.values) if (!Pipewire.ready || !Pipewire.nodes || !Pipewire.nodes.values)
return []; return []
let sources = []; let sources = []
for (let i = 0; i < Pipewire.nodes.values.length; i++) { for (var i = 0; i < Pipewire.nodes.values.length; i++) {
let node = Pipewire.nodes.values[i]; let node = Pipewire.nodes.values[i]
if (!node || node.isStream) if (!node || node.isStream)
continue; continue
if ((node.type & PwNodeType.AudioSource) === PwNodeType.AudioSource && !node.name.includes(".monitor"))
sources.push(node);
if ((node.type & PwNodeType.AudioSource) === PwNodeType.AudioSource
&& !node.name.includes(".monitor"))
sources.push(node)
} }
return sources; return sources
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: sourceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (modelData === AudioService.source ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)) color: sourceArea.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.08) : (modelData === AudioService.source ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: modelData === AudioService.source ? Theme.primary : "transparent" border.color: modelData === AudioService.source ? Theme.primary : "transparent"
border.width: 1 border.width: 1
@@ -90,11 +92,11 @@ Column {
DankIcon { DankIcon {
name: { name: {
if (modelData.name.includes("bluez")) if (modelData.name.includes("bluez"))
return "headset_mic"; return "headset_mic"
else if (modelData.name.includes("usb")) else if (modelData.name.includes("usb"))
return "headset_mic"; return "headset_mic"
else else
return "mic"; return "mic"
} }
size: Theme.iconSize size: Theme.iconSize
color: modelData === AudioService.source ? Theme.primary : Theme.surfaceText color: modelData === AudioService.source ? Theme.primary : Theme.surfaceText
@@ -114,18 +116,19 @@ Column {
StyledText { StyledText {
text: { text: {
if (AudioService.subtitle(modelData.name) && AudioService.subtitle(modelData.name) !== "") if (AudioService.subtitle(modelData.name)
return AudioService.subtitle(modelData.name) + (modelData === AudioService.source ? " • Selected" : ""); && AudioService.subtitle(modelData.name) !== "")
return AudioService.subtitle(
modelData.name) + (modelData === AudioService.source ? " • Selected" : "")
else else
return modelData === AudioService.source ? "Selected" : ""; return modelData === AudioService.source ? "Selected" : ""
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text !== "" visible: text !== ""
} }
} }
} }
MouseArea { MouseArea {
@@ -136,13 +139,9 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (modelData) if (modelData)
Pipewire.preferredDefaultAudioSource = modelData; Pipewire.preferredDefaultAudioSource = modelData
} }
} }
} }
} }
} }

View File

@@ -10,8 +10,12 @@ import qs.Widgets
Column { Column {
id: root id: root
property real micLevel: Math.min(100, (AudioService.source && AudioService.source.audio && AudioService.source.audio.volume * 100) || 0) property real micLevel: Math.min(
property bool micMuted: (AudioService.source && AudioService.source.audio && AudioService.source.audio.muted) || false 100,
(AudioService.source && AudioService.source.audio
&& AudioService.source.audio.volume * 100) || 0)
property bool micMuted: (AudioService.source && AudioService.source.audio
&& AudioService.source.audio.muted) || false
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
@@ -39,11 +43,9 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (AudioService.source && AudioService.source.audio) if (AudioService.source && AudioService.source.audio)
AudioService.source.audio.muted = !AudioService.source.audio.muted; AudioService.source.audio.muted = !AudioService.source.audio.muted
} }
} }
} }
Item { Item {
@@ -59,7 +61,8 @@ Column {
width: parent.width width: parent.width
height: 8 height: 8
radius: 4 radius: 4
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
Rectangle { Rectangle {
@@ -76,9 +79,7 @@ Column {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel easing.bezierCurve: Anims.standardDecel
} }
} }
} }
Rectangle { Rectangle {
@@ -90,7 +91,8 @@ Column {
color: Theme.primary color: Theme.primary
border.color: Qt.lighter(Theme.primary, 1.3) border.color: Qt.lighter(Theme.primary, 1.3)
border.width: 2 border.width: 2
x: Math.max(0, Math.min(parent.width - width, micSliderFill.width - width / 2)) x: Math.max(0, Math.min(parent.width - width,
micSliderFill.width - width / 2))
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
scale: micMouseArea.containsMouse || micMouseArea.pressed ? 1.2 : 1 scale: micMouseArea.containsMouse || micMouseArea.pressed ? 1.2 : 1
@@ -106,7 +108,8 @@ Column {
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: (micMouseArea.containsMouse && !root.micMuted) || micMouseArea.isDragging visible: (micMouseArea.containsMouse && !root.micMuted)
|| micMouseArea.isDragging
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
StyledText { StyledText {
@@ -124,9 +127,7 @@ Column {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Behavior on scale { Behavior on scale {
@@ -135,11 +136,8 @@ Column {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard easing.bezierCurve: Anims.standard
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -151,34 +149,39 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
preventStealing: true preventStealing: true
onPressed: (mouse) => { onPressed: mouse => {
isDragging = true; isDragging = true
let ratio = Math.max(0, Math.min(1, mouse.x / micSliderTrack.width)); let ratio = Math.max(0, Math.min(
let newMicLevel = Math.round(ratio * 100); 1, mouse.x / micSliderTrack.width))
let newMicLevel = Math.round(ratio * 100)
if (AudioService.source && AudioService.source.audio) { if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false; AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100; AudioService.source.audio.volume = newMicLevel / 100
} }
} }
onReleased: { onReleased: {
isDragging = false; isDragging = false
} }
onPositionChanged: (mouse) => { onPositionChanged: mouse => {
if (pressed && isDragging) { if (pressed && isDragging) {
let ratio = Math.max(0, Math.min(1, mouse.x / micSliderTrack.width)); let ratio = Math.max(
let newMicLevel = Math.max(0, Math.min(100, Math.round(ratio * 100))); 0, Math.min(1, mouse.x / micSliderTrack.width))
let newMicLevel = Math.max(
0, Math.min(100, Math.round(ratio * 100)))
if (AudioService.source
&& AudioService.source.audio) {
AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100
}
}
}
onClicked: mouse => {
let ratio = Math.max(0, Math.min(
1, mouse.x / micSliderTrack.width))
let newMicLevel = Math.round(ratio * 100)
if (AudioService.source && AudioService.source.audio) { if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false; AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100; AudioService.source.audio.volume = newMicLevel / 100
}
}
}
onClicked: (mouse) => {
let ratio = Math.max(0, Math.min(1, mouse.x / micSliderTrack.width));
let newMicLevel = Math.round(ratio * 100);
if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = false;
AudioService.source.audio.volume = newMicLevel / 100;
} }
} }
} }
@@ -193,22 +196,27 @@ Column {
enabled: micMouseArea.isDragging enabled: micMouseArea.isDragging
visible: false visible: false
preventStealing: true preventStealing: true
onPositionChanged: (mouse) => { onPositionChanged: mouse => {
if (micMouseArea.isDragging) { if (micMouseArea.isDragging) {
let globalPos = mapToItem(micSliderTrack, mouse.x, mouse.y); let globalPos = mapToItem(micSliderTrack,
let ratio = Math.max(0, Math.min(1, globalPos.x / micSliderTrack.width)); mouse.x, mouse.y)
let newMicLevel = Math.max(0, Math.min(100, Math.round(ratio * 100))); let ratio = Math.max(
if (AudioService.source && AudioService.source.audio) { 0,
AudioService.source.audio.muted = false; Math.min(1,
AudioService.source.audio.volume = newMicLevel / 100; globalPos.x / micSliderTrack.width))
let newMicLevel = Math.max(
0, Math.min(100, Math.round(ratio * 100)))
if (AudioService.source
&& AudioService.source.audio) {
AudioService.source.audio.muted = false
AudioService.source.audio.volume = newMicLevel / 100
} }
} }
} }
onReleased: { onReleased: {
micMouseArea.isDragging = false; micMouseArea.isDragging = false
} }
} }
} }
DankIcon { DankIcon {
@@ -217,7 +225,5 @@ Column {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
} }

View File

@@ -6,8 +6,12 @@ import qs.Widgets
Column { Column {
id: root id: root
property real volumeLevel: Math.min(100, (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0) property real volumeLevel: Math.min(
property bool volumeMuted: (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted) || false 100,
(AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) || 0)
property bool volumeMuted: (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted) || false
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
@@ -32,31 +36,30 @@ Column {
unit: "%" unit: "%"
Connections { Connections {
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null target: AudioService.sink
&& AudioService.sink.audio ? AudioService.sink.audio : null
function onVolumeChanged() { function onVolumeChanged() {
volumeSlider.value = Math.round(AudioService.sink.audio.volume * 100); volumeSlider.value = Math.round(AudioService.sink.audio.volume * 100)
} }
} }
Component.onCompleted: { Component.onCompleted: {
if (AudioService.sink && AudioService.sink.audio) { if (AudioService.sink && AudioService.sink.audio) {
value = Math.round(AudioService.sink.audio.volume * 100); value = Math.round(AudioService.sink.audio.volume * 100)
} }
let leftIconItem = volumeSlider.children[0].children[0]; let leftIconItem = volumeSlider.children[0].children[0]
if (leftIconItem) { if (leftIconItem) {
let mouseArea = Qt.createQmlObject( let mouseArea = Qt.createQmlObject(
'import QtQuick; import qs.Services; MouseArea { anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: { if (AudioService.sink && AudioService.sink.audio) AudioService.sink.audio.muted = !AudioService.sink.audio.muted; } }', 'import QtQuick; import qs.Services; MouseArea { anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: { if (AudioService.sink && AudioService.sink.audio) AudioService.sink.audio.muted = !AudioService.sink.audio.muted; } }',
leftIconItem, leftIconItem, "dynamicMouseArea")
"dynamicMouseArea"
);
} }
} }
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
if (AudioService.sink && AudioService.sink.audio) { if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false; AudioService.sink.audio.muted = false
AudioService.sink.audio.volume = newValue / 100; AudioService.sink.audio.volume = newValue / 100
} }
} }
} }

View File

@@ -29,7 +29,7 @@ Item {
"text": "Input" "text": "Input"
}] }]
onTabClicked: function (index) { onTabClicked: function (index) {
audioTab.audioSubTab = index; audioTab.audioSubTab = index
} }
} }

View File

@@ -38,7 +38,12 @@ Column {
width: Math.max(100, scanText.contentWidth + Theme.spacingL * 2) width: Math.max(100, scanText.contentWidth + Theme.spacingL * 2)
height: 32 height: 32
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: scanArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) color: scanArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08)
border.color: Theme.primary border.color: Theme.primary
border.width: 1 border.width: 1
@@ -47,7 +52,8 @@ Column {
spacing: Theme.spacingXS spacing: Theme.spacingXS
DankIcon { DankIcon {
name: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "bluetooth_searching" name: BluetoothService.adapter
&& BluetoothService.adapter.discovering ? "stop" : "bluetooth_searching"
size: Theme.iconSize - 6 size: Theme.iconSize - 6
color: Theme.primary color: Theme.primary
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -56,13 +62,13 @@ Column {
StyledText { StyledText {
id: scanText id: scanText
text: BluetoothService.adapter && BluetoothService.adapter.discovering ? "Stop Scanning" : "Scan" text: BluetoothService.adapter
&& BluetoothService.adapter.discovering ? "Stop Scanning" : "Scan"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.primary color: Theme.primary
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -73,13 +79,10 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (BluetoothService.adapter) if (BluetoothService.adapter)
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering; BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -87,7 +90,8 @@ Column {
height: noteColumn.implicitHeight + Theme.spacingM * 2 height: noteColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08)
border.color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.2) border.color: Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -115,30 +119,33 @@ Column {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
StyledText { StyledText {
text: "Quickshell does not support pairing devices that require pin or confirmation." text: "Quickshell does not support pairing devices that require pin or confirmation."
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: parent.width width: parent.width
} }
} }
} }
Repeater { Repeater {
model: { model: {
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices) if (!BluetoothService.adapter || !BluetoothService.adapter.discovering
return []; || !Bluetooth.devices)
return []
var filtered = Bluetooth.devices.values.filter((dev) => { var filtered = Bluetooth.devices.values.filter(dev => {
return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0); return dev && !dev.paired
}); && !dev.pairing
return BluetoothService.sortDevices(filtered); && !dev.blocked
&& (dev.signalStrength === undefined
|| dev.signalStrength > 0)
})
return BluetoothService.sortDevices(filtered)
} }
Rectangle { Rectangle {
@@ -150,24 +157,28 @@ Column {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (availableDeviceArea.containsMouse && !isBusy) if (availableDeviceArea.containsMouse && !isBusy)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08); return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.08)
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting) if (modelData.pairing
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12); || modelData.state === BluetoothDeviceState.Connecting)
return Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.12)
if (modelData.blocked) if (modelData.blocked)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08); return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08); return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
} }
border.color: { border.color: {
if (modelData.pairing) if (modelData.pairing)
return Theme.warning; return Theme.warning
if (modelData.blocked) if (modelData.blocked)
return Theme.error; return Theme.error
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2); return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
border.width: 1 border.width: 1
@@ -182,12 +193,12 @@ Column {
size: Theme.iconSize size: Theme.iconSize
color: { color: {
if (modelData.pairing) if (modelData.pairing)
return Theme.warning; return Theme.warning
if (modelData.blocked) if (modelData.blocked)
return Theme.error; return Theme.error
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -201,12 +212,12 @@ Column {
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: { color: {
if (modelData.pairing) if (modelData.pairing)
return Theme.warning; return Theme.warning
if (modelData.blocked) if (modelData.blocked)
return Theme.error; return Theme.error
return Theme.surfaceText; return Theme.surfaceText
} }
font.weight: modelData.pairing ? Font.Medium : Font.Normal font.weight: modelData.pairing ? Font.Medium : Font.Normal
} }
@@ -220,45 +231,49 @@ Column {
StyledText { StyledText {
text: { text: {
if (modelData.pairing) if (modelData.pairing)
return "Pairing..."; return "Pairing..."
if (modelData.blocked) if (modelData.blocked)
return "Blocked"; return "Blocked"
return BluetoothService.getSignalStrength(modelData); return BluetoothService.getSignalStrength(modelData)
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: { color: {
if (modelData.pairing) if (modelData.pairing)
return Theme.warning; return Theme.warning
if (modelData.blocked) if (modelData.blocked)
return Theme.error; return Theme.error
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7); return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
} }
} }
DankIcon { DankIcon {
name: BluetoothService.getSignalIcon(modelData) name: BluetoothService.getSignalIcon(modelData)
size: Theme.fontSizeSmall size: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked Theme.surfaceText.b, 0.7)
visible: modelData.signalStrength !== undefined
&& modelData.signalStrength > 0 && !modelData.pairing
&& !modelData.blocked
} }
StyledText { StyledText {
text: (modelData.signalStrength !== undefined && modelData.signalStrength > 0) ? modelData.signalStrength + "%" : "" text: (modelData.signalStrength !== undefined
&& modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked Theme.surfaceText.b, 0.5)
visible: modelData.signalStrength !== undefined
&& modelData.signalStrength > 0 && !modelData.pairing
&& !modelData.blocked
} }
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -271,14 +286,19 @@ Column {
visible: modelData.state !== BluetoothDeviceState.Connecting visible: modelData.state !== BluetoothDeviceState.Connecting
color: { color: {
if (!canConnect && !isBusy) if (!canConnect && !isBusy)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3); return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
if (actionButtonArea.containsMouse && !isBusy) if (actionButtonArea.containsMouse && !isBusy)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12); return Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
return "transparent"; return "transparent"
} }
border.color: canConnect || isBusy ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: canConnect || isBusy ? Theme.primary : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
opacity: canConnect || isBusy ? 1 : 0.5 opacity: canConnect || isBusy ? 1 : 0.5
@@ -286,15 +306,18 @@ Column {
anchors.centerIn: parent anchors.centerIn: parent
text: { text: {
if (modelData.pairing) if (modelData.pairing)
return "Pairing..."; return "Pairing..."
if (modelData.blocked) if (modelData.blocked)
return "Blocked"; return "Blocked"
return "Connect"; return "Connect"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: canConnect || isBusy ? Theme.primary : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: canConnect || isBusy ? Theme.primary : Qt.rgba(
Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Medium font.weight: Font.Medium
} }
@@ -303,15 +326,14 @@ Column {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: canConnect && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor) cursorShape: canConnect
&& !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
enabled: canConnect && !isBusy enabled: canConnect && !isBusy
onClicked: { onClicked: {
if (modelData) if (modelData)
BluetoothService.connectDeviceWithTrust(modelData); BluetoothService.connectDeviceWithTrust(modelData)
} }
} }
} }
MouseArea { MouseArea {
@@ -320,30 +342,34 @@ Column {
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 90 anchors.rightMargin: 90
hoverEnabled: true hoverEnabled: true
cursorShape: canConnect && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor) cursorShape: canConnect
&& !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
enabled: canConnect && !isBusy enabled: canConnect && !isBusy
onClicked: { onClicked: {
if (modelData) if (modelData)
BluetoothService.connectDeviceWithTrust(modelData); BluetoothService.connectDeviceWithTrust(modelData)
} }
} }
} }
} }
Column { Column {
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
visible: { visible: {
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices) if (!BluetoothService.adapter || !BluetoothService.adapter.discovering
return false; || !Bluetooth.devices)
return false
var availableCount = Bluetooth.devices.values.filter((dev) => { var availableCount = Bluetooth.devices.values.filter(dev => {
return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0); return dev
}).length; && !dev.paired
return availableCount === 0; && !dev.pairing
&& !dev.blocked
&& (dev.signalStrength === undefined
|| dev.signalStrength > 0)
}).length
return availableCount === 0
} }
Row { Row {
@@ -363,7 +389,6 @@ Column {
to: 360 to: 360
duration: 2000 duration: 2000
} }
} }
StyledText { StyledText {
@@ -373,34 +398,38 @@ Column {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
StyledText { StyledText {
text: "Make sure your device is in pairing mode" text: "Make sure your device is in pairing mode"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
StyledText { StyledText {
text: "No devices found. Put your device in pairing mode and click Start Scanning." text: "No devices found. Put your device in pairing mode and click Start Scanning."
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: { visible: {
if (!BluetoothService.adapter || !Bluetooth.devices) if (!BluetoothService.adapter || !Bluetooth.devices)
return true; return true
var availableCount = Bluetooth.devices.values.filter((dev) => { var availableCount = Bluetooth.devices.values.filter(dev => {
return dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0); return dev
}).length; && !dev.paired
return availableCount === 0 && !BluetoothService.adapter.discovering; && !dev.pairing
&& !dev.blocked
&& (dev.signalStrength === undefined
|| dev.signalStrength > 0)
}).length
return availableCount === 0 && !BluetoothService.adapter.discovering
} }
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: parent.width width: parent.width
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
} }

View File

@@ -16,23 +16,23 @@ Rectangle {
property var parentItem property var parentItem
function show(x, y) { function show(x, y) {
const menuWidth = 160; const menuWidth = 160
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2; const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
let finalX = x - menuWidth / 2; let finalX = x - menuWidth / 2
let finalY = y; let finalY = y
finalX = Math.max(0, Math.min(finalX, parentItem.width - menuWidth)); finalX = Math.max(0, Math.min(finalX, parentItem.width - menuWidth))
finalY = Math.max(0, Math.min(finalY, parentItem.height - menuHeight)); finalY = Math.max(0, Math.min(finalY, parentItem.height - menuHeight))
root.x = finalX; root.x = finalX
root.y = finalY; root.y = finalY
root.visible = true; root.visible = true
root.menuVisible = true; root.menuVisible = true
} }
function hide() { function hide() {
root.menuVisible = false; root.menuVisible = false
Qt.callLater(() => { Qt.callLater(() => {
root.visible = false; root.visible = false
}); })
} }
visible: false visible: false
@@ -68,7 +68,10 @@ Rectangle {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: connectArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: connectArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -77,7 +80,8 @@ Rectangle {
spacing: Theme.spacingS spacing: Theme.spacingS
DankIcon { DankIcon {
name: root.deviceData && root.deviceData.connected ? "link_off" : "link" name: root.deviceData
&& root.deviceData.connected ? "link_off" : "link"
size: Theme.iconSize - 2 size: Theme.iconSize - 2
color: Theme.surfaceText color: Theme.surfaceText
opacity: 0.7 opacity: 0.7
@@ -85,13 +89,13 @@ Rectangle {
} }
StyledText { StyledText {
text: root.deviceData && root.deviceData.connected ? "Disconnect" : "Connect" text: root.deviceData
&& root.deviceData.connected ? "Disconnect" : "Connect"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -103,11 +107,11 @@ Rectangle {
onClicked: { onClicked: {
if (root.deviceData) { if (root.deviceData) {
if (root.deviceData.connected) if (root.deviceData.connected)
root.deviceData.disconnect(); root.deviceData.disconnect()
else else
BluetoothService.connectDeviceWithTrust(root.deviceData); BluetoothService.connectDeviceWithTrust(root.deviceData)
} }
root.hide(); root.hide()
} }
} }
@@ -116,9 +120,7 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
@@ -133,14 +135,15 @@ Rectangle {
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: forgetArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent" color: forgetArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -163,7 +166,6 @@ Rectangle {
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -174,9 +176,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (root.deviceData) if (root.deviceData)
root.deviceData.forget(); root.deviceData.forget()
root.hide(); root.hide()
} }
} }
@@ -185,11 +187,8 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -197,7 +196,6 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on scale { Behavior on scale {
@@ -205,7 +203,5 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }

View File

@@ -14,8 +14,12 @@ Rectangle {
width: parent.width width: parent.width
height: 60 height: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: bluetoothToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (BluetoothService.adapter && BluetoothService.adapter.enabled ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12)) color: bluetoothToggle.containsMouse ? Qt.rgba(
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : "transparent" Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12) : (BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12))
border.color: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Theme.primary : "transparent"
border.width: 2 border.width: 2
Row { Row {
@@ -27,7 +31,8 @@ Rectangle {
DankIcon { DankIcon {
name: "bluetooth" name: "bluetooth"
size: Theme.iconSizeLarge size: Theme.iconSizeLarge
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText color: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -38,18 +43,19 @@ Rectangle {
StyledText { StyledText {
text: "Bluetooth" text: "Bluetooth"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText color: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceText
font.weight: Font.Medium font.weight: Font.Medium
} }
StyledText { StyledText {
text: BluetoothService.adapter && BluetoothService.adapter.enabled ? "Enabled" : "Disabled" text: BluetoothService.adapter
&& BluetoothService.adapter.enabled ? "Enabled" : "Disabled"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
} }
} }
} }
MouseArea { MouseArea {
@@ -60,9 +66,7 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (BluetoothService.adapter) if (BluetoothService.adapter)
BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled; BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled
} }
} }
} }

View File

@@ -12,13 +12,13 @@ Column {
id: root id: root
function findBluetoothContextMenu() { function findBluetoothContextMenu() {
var p = parent; var p = parent
while (p) { while (p) {
if (p.bluetoothContextMenuWindow) if (p.bluetoothContextMenuWindow)
return p.bluetoothContextMenuWindow; return p.bluetoothContextMenuWindow
p = p.parent; p = p.parent
} }
return null; return null
} }
width: parent.width width: parent.width
@@ -33,15 +33,28 @@ Column {
} }
Repeater { Repeater {
model: BluetoothService.adapter && BluetoothService.adapter.devices ? BluetoothService.adapter.devices.values.filter((dev) => { model: BluetoothService.adapter
return dev && (dev.paired || dev.trusted); && BluetoothService.adapter.devices ? BluetoothService.adapter.devices.values.filter(
dev => {
return dev
&& (dev.paired
|| dev.trusted)
}) : [] }) : []
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 60 height: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: btDeviceArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (modelData.connected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)) color: btDeviceArea.containsMouse ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.08) : (modelData.connected ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
0.08))
border.color: modelData.connected ? Theme.primary : "transparent" border.color: modelData.connected ? Theme.primary : "transparent"
border.width: 1 border.width: 1
@@ -75,28 +88,30 @@ Column {
StyledText { StyledText {
text: BluetoothDeviceState.toString(modelData.state) text: BluetoothDeviceState.toString(modelData.state)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
} }
StyledText { StyledText {
text: { text: {
if (modelData.batteryAvailable && modelData.battery > 0) if (modelData.batteryAvailable && modelData.battery > 0)
return "• " + Math.round(modelData.battery * 100) + "%"; return "• " + Math.round(modelData.battery * 100) + "%"
var btBattery = BatteryService.bluetoothDevices.find((dev) => { var btBattery = BatteryService.bluetoothDevices.find(dev => {
return dev.name === (modelData.name || modelData.deviceName) || dev.name.toLowerCase().includes((modelData.name || modelData.deviceName).toLowerCase()) || (modelData.name || modelData.deviceName).toLowerCase().includes(dev.name.toLowerCase()); return dev.name === (modelData.name || modelData.deviceName) || dev.name.toLowerCase().includes((modelData.name || modelData.deviceName).toLowerCase()) || (modelData.name || modelData.deviceName).toLowerCase(
}); ).includes(
return btBattery ? "• " + btBattery.percentage + "%" : ""; dev.name.toLowerCase(
))
})
return btBattery ? "• " + btBattery.percentage + "%" : ""
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
visible: text.length > 0 visible: text.length > 0
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -105,7 +120,10 @@ Column {
width: 32 width: 32
height: 32 height: 32
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: btMenuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: btMenuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Theme.spacingM anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -125,11 +143,13 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
var contextMenu = root.findBluetoothContextMenu(); var contextMenu = root.findBluetoothContextMenu()
if (contextMenu) { if (contextMenu) {
contextMenu.deviceData = modelData; contextMenu.deviceData = modelData
let localPos = btMenuButtonArea.mapToItem(contextMenu.parentItem, btMenuButtonArea.width / 2, btMenuButtonArea.height); let localPos = btMenuButtonArea.mapToItem(
contextMenu.show(localPos.x, localPos.y); contextMenu.parentItem, btMenuButtonArea.width / 2,
btMenuButtonArea.height)
contextMenu.show(localPos.x, localPos.y)
} }
} }
} }
@@ -138,9 +158,7 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
MouseArea { MouseArea {
@@ -153,14 +171,11 @@ Column {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.BusyCursor cursorShape: enabled ? Qt.PointingHandCursor : Qt.BusyCursor
onClicked: { onClicked: {
if (modelData.connected) if (modelData.connected)
modelData.disconnect(); modelData.disconnect()
else else
BluetoothService.connectDeviceWithTrust(modelData); BluetoothService.connectDeviceWithTrust(modelData)
} }
} }
} }
} }
} }

View File

@@ -51,7 +51,7 @@ Item {
anchors.fill: parent anchors.fill: parent
visible: bluetoothContextMenuWindow.visible visible: bluetoothContextMenuWindow.visible
onClicked: { onClicked: {
bluetoothContextMenuWindow.hide(); bluetoothContextMenuWindow.hide()
} }
MouseArea { MouseArea {
@@ -60,6 +60,7 @@ Item {
width: bluetoothContextMenuWindow.width width: bluetoothContextMenuWindow.width
height: bluetoothContextMenuWindow.height height: bluetoothContextMenuWindow.height
onClicked: { onClicked: {
} }
} }
} }

View File

@@ -24,26 +24,26 @@ PanelWindow {
property string triggerSection: "right" property string triggerSection: "right"
function setTriggerPosition(x, y, width, section, screen) { function setTriggerPosition(x, y, width, section, screen) {
triggerX = x; triggerX = x
triggerY = y; triggerY = y
triggerWidth = width; triggerWidth = width
triggerSection = section; triggerSection = section
triggerScreen = screen; triggerScreen = screen
} }
signal powerActionRequested(string action, string title, string message) signal powerActionRequested(string action, string title, string message)
signal lockRequested() signal lockRequested
visible: controlCenterVisible visible: controlCenterVisible
screen: triggerScreen screen: triggerScreen
onVisibleChanged: { onVisibleChanged: {
NetworkService.autoRefreshEnabled = visible && NetworkService.wifiEnabled; NetworkService.autoRefreshEnabled = visible && NetworkService.wifiEnabled
if (!visible && BluetoothService.adapter && BluetoothService.adapter.discovering) if (!visible && BluetoothService.adapter
BluetoothService.adapter.discovering = false; && BluetoothService.adapter.discovering)
BluetoothService.adapter.discovering = false
if (visible && UserInfoService) if (visible && UserInfoService)
UserInfoService.getUptime(); UserInfoService.getUptime()
} }
implicitWidth: 600 implicitWidth: 600
implicitHeight: 500 implicitHeight: 500
@@ -64,7 +64,8 @@ PanelWindow {
readonly property real screenWidth: root.screen ? root.screen.width : Screen.width readonly property real screenWidth: root.screen ? root.screen.width : Screen.width
readonly property real screenHeight: root.screen ? root.screen.height : Screen.height readonly property real screenHeight: root.screen ? root.screen.height : Screen.height
readonly property real targetWidth: Math.min(600, screenWidth - Theme.spacingL * 2) readonly property real targetWidth: Math.min(
600, screenWidth - Theme.spacingL * 2)
asynchronous: true asynchronous: true
active: controlCenterVisible active: controlCenterVisible
@@ -72,21 +73,22 @@ PanelWindow {
height: root.powerOptionsExpanded ? 570 : 500 height: root.powerOptionsExpanded ? 570 : 500
y: Theme.barHeight + Theme.spacingXS y: Theme.barHeight + Theme.spacingXS
x: { x: {
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2); var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) { if (centerX >= Theme.spacingM
return centerX; && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
} }
if (centerX < Theme.spacingM) { if (centerX < Theme.spacingM) {
return Theme.spacingM; return Theme.spacingM
} }
if (centerX + targetWidth > screenWidth - Theme.spacingM) { if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM; return screenWidth - targetWidth - Theme.spacingM
} }
return centerX; return centerX
} }
opacity: controlCenterVisible ? 1 : 0 opacity: controlCenterVisible ? 1 : 0
scale: controlCenterVisible ? 1 : 0.9 scale: controlCenterVisible ? 1 : 0.9
@@ -97,7 +99,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
Behavior on scale { Behavior on scale {
@@ -106,27 +107,27 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
sourceComponent: Rectangle { sourceComponent: Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
antialiasing: true antialiasing: true
smooth: true smooth: true
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {
if (controlCenterVisible) if (controlCenterVisible)
forceActiveFocus(); forceActiveFocus()
} }
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
controlCenterVisible = false; controlCenterVisible = false
event.accepted = true; event.accepted = true
} else { } else {
event.accepted = false; event.accepted = false
} }
} }
@@ -134,8 +135,8 @@ PanelWindow {
function onControlCenterVisibleChanged() { function onControlCenterVisibleChanged() {
if (controlCenterVisible) if (controlCenterVisible)
Qt.callLater(function () { Qt.callLater(function () {
parent.forceActiveFocus(); parent.forceActiveFocus()
}); })
} }
target: root target: root
} }
@@ -153,8 +154,11 @@ PanelWindow {
width: parent.width width: parent.width
height: 90 height: 90
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
Row { Row {
@@ -186,12 +190,12 @@ PanelWindow {
source: { source: {
if (PortalService.profileImage === "") if (PortalService.profileImage === "")
return ""; return ""
if (PortalService.profileImage.startsWith("/")) if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage; return "file://" + PortalService.profileImage
return PortalService.profileImage; return PortalService.profileImage
} }
smooth: true smooth: true
asynchronous: true asynchronous: true
@@ -226,7 +230,6 @@ PanelWindow {
color: "black" color: "black"
antialiasing: true antialiasing: true
} }
} }
Rectangle { Rectangle {
@@ -241,7 +244,6 @@ PanelWindow {
size: Theme.iconSize + 8 size: Theme.iconSize + 8
color: Theme.primaryText color: Theme.primaryText
} }
} }
DankIcon { DankIcon {
@@ -249,9 +251,9 @@ PanelWindow {
name: "warning" name: "warning"
size: Theme.iconSize + 8 size: Theme.iconSize + 8
color: Theme.primaryText color: Theme.primaryText
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error visible: PortalService.profileImage !== ""
&& profileImageLoader.status === Image.Error
} }
} }
Column { Column {
@@ -259,7 +261,8 @@ PanelWindow {
spacing: Theme.spacingXS spacing: Theme.spacingXS
StyledText { StyledText {
text: UserInfoService.fullName || UserInfoService.username || "User" text: UserInfoService.fullName
|| UserInfoService.username || "User"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Medium font.weight: Font.Medium
@@ -271,9 +274,7 @@ PanelWindow {
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
font.weight: Font.Normal font.weight: Font.Normal
} }
} }
} }
Row { Row {
@@ -287,11 +288,14 @@ PanelWindow {
iconName: "lock" iconName: "lock"
iconSize: Theme.iconSize - 2 iconSize: Theme.iconSize - 2
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.5)
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
onClicked: { onClicked: {
controlCenterVisible = false; controlCenterVisible = false
root.lockRequested(); root.lockRequested()
} }
} }
@@ -299,7 +303,15 @@ PanelWindow {
width: 40 width: 40
height: 40 height: 40
radius: 20 radius: 20
color: powerButton.containsMouse || root.powerOptionsExpanded ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) color: powerButton.containsMouse
|| root.powerOptionsExpanded ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
@@ -315,7 +327,8 @@ PanelWindow {
anchors.centerIn: parent anchors.centerIn: parent
name: root.powerOptionsExpanded ? "expand_less" : "power_settings_new" name: root.powerOptionsExpanded ? "expand_less" : "power_settings_new"
size: Theme.iconSize - 2 size: Theme.iconSize - 2
color: powerButton.containsMouse || root.powerOptionsExpanded ? Theme.error : Theme.surfaceText color: powerButton.containsMouse
|| root.powerOptionsExpanded ? Theme.error : Theme.surfaceText
Behavior on name { Behavior on name {
SequentialAnimation { SequentialAnimation {
@@ -339,13 +352,9 @@ PanelWindow {
duration: Theme.shortDuration / 2 duration: Theme.shortDuration / 2
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -355,7 +364,7 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.powerOptionsExpanded = !root.powerOptionsExpanded; root.powerOptionsExpanded = !root.powerOptionsExpanded
} }
} }
@@ -364,9 +373,7 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
DankActionButton { DankActionButton {
@@ -374,24 +381,28 @@ PanelWindow {
iconName: "settings" iconName: "settings"
iconSize: Theme.iconSize - 2 iconSize: Theme.iconSize - 2
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) backgroundColor: Qt.rgba(Theme.surfaceVariant.r,
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.5)
hoverColor: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
onClicked: { onClicked: {
controlCenterVisible = false; controlCenterVisible = false
settingsModal.show(); settingsModal.show()
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: root.powerOptionsExpanded ? 60 : 0 height: root.powerOptionsExpanded ? 60 : 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: root.powerOptionsExpanded ? 1 : 0 border.width: root.powerOptionsExpanded ? 1 : 0
opacity: root.powerOptionsExpanded ? 1 : 0 opacity: root.powerOptionsExpanded ? 1 : 0
clip: true clip: true
@@ -405,7 +416,14 @@ PanelWindow {
width: 100 width: 100
height: 34 height: 34
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: logoutButton.containsMouse ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) color: logoutButton.containsMouse ? Qt.rgba(Theme.warning.r,
Theme.warning.g,
Theme.warning.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -425,7 +443,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -435,8 +452,10 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.powerOptionsExpanded = false; root.powerOptionsExpanded = false
root.powerActionRequested("logout", "Logout", "Are you sure you want to logout?"); root.powerActionRequested(
"logout", "Logout",
"Are you sure you want to logout?")
} }
} }
@@ -445,16 +464,21 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
width: 100 width: 100
height: 34 height: 34
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: rebootButton.containsMouse ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) color: rebootButton.containsMouse ? Qt.rgba(Theme.warning.r,
Theme.warning.g,
Theme.warning.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -474,7 +498,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -484,8 +507,10 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.powerOptionsExpanded = false; root.powerOptionsExpanded = false
root.powerActionRequested("reboot", "Restart", "Are you sure you want to restart?"); root.powerActionRequested(
"reboot", "Restart",
"Are you sure you want to restart?")
} }
} }
@@ -494,16 +519,21 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
width: 100 width: 100
height: 34 height: 34
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: suspendButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) color: suspendButton.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -523,7 +553,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -533,8 +562,10 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.powerOptionsExpanded = false; root.powerOptionsExpanded = false
root.powerActionRequested("suspend", "Suspend", "Are you sure you want to suspend?"); root.powerActionRequested(
"suspend", "Suspend",
"Are you sure you want to suspend?")
} }
} }
@@ -543,16 +574,21 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
width: 100 width: 100
height: 34 height: 34
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: shutdownButton.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) color: shutdownButton.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.5)
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -572,7 +608,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -582,8 +617,10 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.powerOptionsExpanded = false; root.powerOptionsExpanded = false
root.powerActionRequested("poweroff", "Shutdown", "Are you sure you want to shutdown?"); root.powerActionRequested(
"poweroff", "Shutdown",
"Are you sure you want to shutdown?")
} }
} }
@@ -592,11 +629,8 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
Behavior on height { Behavior on height {
@@ -604,7 +638,6 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -612,17 +645,17 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: tabBar.height + Theme.spacingM * 2 height: tabBar.height + Theme.spacingM * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.15) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) Theme.surfaceVariant.b, 0.15)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1 border.width: 1
DankTabBar { DankTabBar {
@@ -632,58 +665,58 @@ PanelWindow {
width: parent.width - Theme.spacingM * 2 width: parent.width - Theme.spacingM * 2
tabHeight: 40 tabHeight: 40
currentIndex: { currentIndex: {
let tabs = ["network", "audio"]; let tabs = ["network", "audio"]
if (BluetoothService.available) if (BluetoothService.available)
tabs.push("bluetooth"); tabs.push("bluetooth")
tabs.push("display"); tabs.push("display")
return tabs.indexOf(root.currentTab); return tabs.indexOf(root.currentTab)
} }
model: { model: {
let tabs = [{ let tabs = [{
"text": "Network", "text": "Network",
"icon": "wifi", "icon": "wifi",
"id": "network" "id": "network"
}]; }]
tabs.push({ tabs.push({
"text": "Audio", "text": "Audio",
"icon": "volume_up", "icon": "volume_up",
"id": "audio" "id": "audio"
}); })
if (BluetoothService.available) if (BluetoothService.available)
tabs.push({ tabs.push({
"text": "Bluetooth", "text": "Bluetooth",
"icon": "bluetooth", "icon": "bluetooth",
"id": "bluetooth" "id": "bluetooth"
}); })
tabs.push({ tabs.push({
"text": "Display", "text": "Display",
"icon": "brightness_6", "icon": "brightness_6",
"id": "display" "id": "display"
}); })
return tabs; return tabs
} }
onTabClicked: function (index) { onTabClicked: function (index) {
let tabs = ["network", "audio"]; let tabs = ["network", "audio"]
if (BluetoothService.available) if (BluetoothService.available)
tabs.push("bluetooth"); tabs.push("bluetooth")
tabs.push("display"); tabs.push("display")
root.currentTab = tabs[index]; root.currentTab = tabs[index]
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1 border.width: 1
NetworkTab { NetworkTab {
@@ -701,7 +734,8 @@ PanelWindow {
BluetoothTab { BluetoothTab {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
visible: BluetoothService.available && root.currentTab === "bluetooth" visible: BluetoothService.available
&& root.currentTab === "bluetooth"
} }
Column { Column {
@@ -713,7 +747,7 @@ PanelWindow {
interval: BrightnessService.ddcAvailable ? 500 : 50 interval: BrightnessService.ddcAvailable ? 500 : 50
repeat: false repeat: false
onTriggered: { onTriggered: {
BrightnessService.setBrightnessInternal(pendingValue); BrightnessService.setBrightnessInternal(pendingValue)
} }
} }
@@ -742,12 +776,12 @@ PanelWindow {
enabled: BrightnessService.brightnessAvailable enabled: BrightnessService.brightnessAvailable
showValue: true showValue: true
onSliderValueChanged: function (newValue) { onSliderValueChanged: function (newValue) {
parent.parent.brightnessDebounceTimer.pendingValue = newValue; parent.parent.brightnessDebounceTimer.pendingValue = newValue
parent.parent.brightnessDebounceTimer.restart(); parent.parent.brightnessDebounceTimer.restart()
} }
onSliderDragFinished: function (finalValue) { onSliderDragFinished: function (finalValue) {
parent.parent.brightnessDebounceTimer.stop(); parent.parent.brightnessDebounceTimer.stop()
BrightnessService.setBrightnessInternal(finalValue); BrightnessService.setBrightnessInternal(finalValue)
} }
} }
@@ -755,10 +789,10 @@ PanelWindow {
text: "ddc changes can be slow to respond" text: "ddc changes can be slow to respond"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
visible: BrightnessService.ddcAvailable && !BrightnessService.laptopBacklightAvailable visible: BrightnessService.ddcAvailable
&& !BrightnessService.laptopBacklightAvailable
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
DankToggle { DankToggle {
@@ -766,8 +800,8 @@ PanelWindow {
text: "Night Mode" text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain" description: "Apply warm color temperature to reduce eye strain"
checked: SettingsData.nightModeEnabled checked: SettingsData.nightModeEnabled
onToggled: (checked) => { onToggled: checked => {
SettingsData.setNightModeEnabled(checked); SettingsData.setNightModeEnabled(checked)
} }
} }
@@ -776,13 +810,12 @@ PanelWindow {
text: "Light Mode" text: "Light Mode"
description: "Use light theme instead of dark theme" description: "Use light theme instead of dark theme"
checked: SessionData.isLightMode checked: SessionData.isLightMode
onToggled: (checked) => { onToggled: checked => {
SessionData.setLightMode(checked); SessionData.setLightMode(checked)
Theme.isLightMode = checked; Theme.isLightMode = checked
PortalService.setLightMode(checked); PortalService.setLightMode(checked)
} }
} }
} }
Behavior on height { Behavior on height {
@@ -790,11 +823,8 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
Behavior on height { Behavior on height {
@@ -802,22 +832,18 @@ PanelWindow {
duration: Theme.shortDuration // Faster for height changes duration: Theme.shortDuration // Faster for height changes
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
z: -1 z: -1
onClicked: function (mouse) { onClicked: function (mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y); var localPos = mapToItem(contentLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height) if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0
controlCenterVisible = false; || localPos.y > contentLoader.height)
controlCenterVisible = false
} }
} }
} }

View File

@@ -19,7 +19,7 @@ Item {
interval: BrightnessService.ddcAvailable ? 500 : 50 interval: BrightnessService.ddcAvailable ? 500 : 50
repeat: false repeat: false
onTriggered: { onTriggered: {
BrightnessService.setBrightnessInternal(pendingValue); BrightnessService.setBrightnessInternal(pendingValue)
} }
} }
@@ -50,9 +50,9 @@ Item {
id: nightModeEnableProcess id: nightModeEnableProcess
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"] command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
running: false running: false
onExited: (exitCode) => { onExited: exitCode => {
if (exitCode !== 0) { if (exitCode !== 0) {
SettingsData.setNightModeEnabled(false); SettingsData.setNightModeEnabled(false)
} }
} }
} }
@@ -61,7 +61,7 @@ Item {
id: nightModeDisableProcess id: nightModeDisableProcess
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"] command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
running: false running: false
onExited: (exitCode) => { onExited: exitCode => {
if (exitCode !== 0) { if (exitCode !== 0) {
} }
@@ -89,12 +89,12 @@ Item {
rightIcon: "brightness_high" rightIcon: "brightness_high"
enabled: BrightnessService.brightnessAvailable enabled: BrightnessService.brightnessAvailable
onSliderValueChanged: function (newValue) { onSliderValueChanged: function (newValue) {
brightnessDebounceTimer.pendingValue = newValue; brightnessDebounceTimer.pendingValue = newValue
brightnessDebounceTimer.restart(); brightnessDebounceTimer.restart()
} }
onSliderDragFinished: function (finalValue) { onSliderDragFinished: function (finalValue) {
brightnessDebounceTimer.stop(); brightnessDebounceTimer.stop()
BrightnessService.setBrightnessInternal(finalValue); BrightnessService.setBrightnessInternal(finalValue)
} }
} }
@@ -102,7 +102,8 @@ Item {
text: "using ddc - changes may take a moment to apply" text: "using ddc - changes may take a moment to apply"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
visible: BrightnessService.ddcAvailable && !BrightnessService.laptopBacklightAvailable visible: BrightnessService.ddcAvailable
&& !BrightnessService.laptopBacklightAvailable
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
@@ -129,7 +130,11 @@ Item {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: SettingsData.nightModeEnabled ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (nightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)) color: SettingsData.nightModeEnabled ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : (nightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: SettingsData.nightModeEnabled ? Theme.primary : "transparent" border.color: SettingsData.nightModeEnabled ? Theme.primary : "transparent"
border.width: SettingsData.nightModeEnabled ? 1 : 0 border.width: SettingsData.nightModeEnabled ? 1 : 0
@@ -160,11 +165,11 @@ Item {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (SettingsData.nightModeEnabled) { if (SettingsData.nightModeEnabled) {
nightModeDisableProcess.running = true; nightModeDisableProcess.running = true
SettingsData.setNightModeEnabled(false); SettingsData.setNightModeEnabled(false)
} else { } else {
nightModeEnableProcess.running = true; nightModeEnableProcess.running = true
SettingsData.setNightModeEnabled(true); SettingsData.setNightModeEnabled(true)
} }
} }
} }
@@ -174,7 +179,10 @@ Item {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.isLightMode ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : (lightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)) color: Theme.isLightMode ? Qt.rgba(
Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.12) : (lightModeToggle.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
border.color: Theme.isLightMode ? Theme.primary : "transparent" border.color: Theme.isLightMode ? Theme.primary : "transparent"
border.width: Theme.isLightMode ? 1 : 0 border.width: Theme.isLightMode ? 1 : 0
@@ -204,7 +212,7 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
Theme.toggleLightMode(); Theme.toggleLightMode()
} }
} }

View File

@@ -14,12 +14,20 @@ Rectangle {
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (ethernetPreferenceArea.containsMouse && NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet") if (ethernetPreferenceArea.containsMouse && NetworkService.ethernetConnected
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.8); && NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "ethernet")
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.8)
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5); return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.5)
} }
border.color: NetworkService.networkStatus === "ethernet" ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: NetworkService.networkStatus === "ethernet" ? Theme.primary : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b,
0.12)
border.width: NetworkService.networkStatus === "ethernet" ? 2 : 1 border.width: NetworkService.networkStatus === "ethernet" ? 2 : 1
Column { Column {
@@ -48,17 +56,17 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
StyledText { StyledText {
text: NetworkService.ethernetConnected ? (NetworkService.ethernetIP || "Connected") : "Disconnected" text: NetworkService.ethernetConnected ? (NetworkService.ethernetIP
|| "Connected") : "Disconnected"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
leftPadding: Theme.iconSize + Theme.spacingM leftPadding: Theme.iconSize + Theme.spacingM
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
DankIcon { DankIcon {
@@ -70,7 +78,8 @@ Rectangle {
anchors.right: ethernetToggle.left anchors.right: ethernetToggle.left
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: NetworkService.changingPreference && NetworkService.targetPreference === "ethernet" visible: NetworkService.changingPreference
&& NetworkService.targetPreference === "ethernet"
z: 10 z: 10
RotationAnimation { RotationAnimation {
@@ -82,7 +91,6 @@ Rectangle {
duration: 1000 duration: 1000
loops: Animation.Infinite loops: Animation.Infinite
} }
} }
DankToggle { DankToggle {
@@ -94,7 +102,7 @@ Rectangle {
anchors.rightMargin: Theme.spacingM anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
onClicked: { onClicked: {
NetworkService.toggleNetworkConnection("ethernet"); NetworkService.toggleNetworkConnection("ethernet")
} }
} }
@@ -104,15 +112,19 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 60 // Exclude toggle area anchors.rightMargin: 60 // Exclude toggle area
hoverEnabled: true hoverEnabled: true
cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet") ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "ethernet" && !NetworkService.changingNetworkPreference && NetworkService.networkStatus
!== "ethernet") ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "ethernet"
&& !NetworkService.changingNetworkPreference
onClicked: { onClicked: {
if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) { if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) {
if (NetworkService.networkStatus !== "ethernet") if (NetworkService.networkStatus !== "ethernet")
NetworkService.setNetworkPreference("ethernet"); NetworkService.setNetworkPreference("ethernet")
else else
NetworkService.setNetworkPreference("auto"); NetworkService.setNetworkPreference("auto")
} }
} }
} }
@@ -122,7 +134,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -15,15 +15,15 @@ Rectangle {
function getWiFiSignalIcon(signalStrength) { function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) { switch (signalStrength) {
case "excellent": case "excellent":
return "wifi"; return "wifi"
case "good": case "good":
return "wifi_2_bar"; return "wifi_2_bar"
case "fair": case "fair":
return "wifi_1_bar"; return "wifi_1_bar"
case "poor": case "poor":
return "signal_wifi_0_bar"; return "signal_wifi_0_bar"
default: default:
return "wifi"; return "wifi"
} }
} }
@@ -31,12 +31,20 @@ Rectangle {
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (wifiPreferenceArea.containsMouse && NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi") if (wifiPreferenceArea.containsMouse && NetworkService.ethernetConnected
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.8); && NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "wifi")
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.8)
return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5); return Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.5)
} }
border.color: NetworkService.networkStatus === "wifi" ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: NetworkService.networkStatus === "wifi" ? Theme.primary : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b,
0.12)
border.width: NetworkService.networkStatus === "wifi" ? 2 : 1 border.width: NetworkService.networkStatus === "wifi" ? 2 : 1
visible: NetworkService.wifiAvailable visible: NetworkService.wifiAvailable
@@ -54,11 +62,11 @@ Rectangle {
DankIcon { DankIcon {
name: { name: {
if (!NetworkService.wifiEnabled) if (!NetworkService.wifiEnabled)
return "wifi_off"; return "wifi_off"
else if (NetworkService.currentWifiSSID !== "") else if (NetworkService.currentWifiSSID !== "")
return getWiFiSignalIcon(NetworkService.wifiSignalStrength); return getWiFiSignalIcon(NetworkService.wifiSignalStrength)
else else
return "wifi"; return "wifi"
} }
size: Theme.iconSize size: Theme.iconSize
color: NetworkService.networkStatus === "wifi" ? Theme.primary : Theme.surfaceText color: NetworkService.networkStatus === "wifi" ? Theme.primary : Theme.surfaceText
@@ -68,11 +76,11 @@ Rectangle {
StyledText { StyledText {
text: { text: {
if (!NetworkService.wifiEnabled) if (!NetworkService.wifiEnabled)
return "WiFi is off"; return "WiFi is off"
else if (NetworkService.wifiEnabled && NetworkService.currentWifiSSID) else if (NetworkService.wifiEnabled && NetworkService.currentWifiSSID)
return NetworkService.currentWifiSSID || "Connected"; return NetworkService.currentWifiSSID || "Connected"
else else
return "Not Connected"; return "Not Connected"
} }
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: NetworkService.networkStatus === "wifi" ? Theme.primary : Theme.surfaceText color: NetworkService.networkStatus === "wifi" ? Theme.primary : Theme.surfaceText
@@ -80,24 +88,23 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
StyledText { StyledText {
text: { text: {
if (!NetworkService.wifiEnabled) if (!NetworkService.wifiEnabled)
return "Turn on WiFi to see networks"; return "Turn on WiFi to see networks"
else if (NetworkService.wifiEnabled && NetworkService.currentWifiSSID) else if (NetworkService.wifiEnabled && NetworkService.currentWifiSSID)
return NetworkService.wifiIP || "Connected"; return NetworkService.wifiIP || "Connected"
else else
return "Select a network below"; return "Select a network below"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
leftPadding: Theme.iconSize + Theme.spacingM leftPadding: Theme.iconSize + Theme.spacingM
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
DankIcon { DankIcon {
@@ -109,7 +116,8 @@ Rectangle {
anchors.right: wifiToggle.left anchors.right: wifiToggle.left
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: NetworkService.changingPreference && NetworkService.targetPreference === "wifi" visible: NetworkService.changingPreference
&& NetworkService.targetPreference === "wifi"
z: 10 z: 10
RotationAnimation { RotationAnimation {
@@ -121,7 +129,6 @@ Rectangle {
duration: 1000 duration: 1000
loops: Animation.Infinite loops: Animation.Infinite
} }
} }
DankToggle { DankToggle {
@@ -135,19 +142,18 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
onClicked: { onClicked: {
if (NetworkService.wifiEnabled) { if (NetworkService.wifiEnabled) {
NetworkService.currentWifiSSID = ""; NetworkService.currentWifiSSID = ""
NetworkService.wifiSignalStrength = "excellent"; NetworkService.wifiSignalStrength = "excellent"
NetworkService.wifiNetworks = []; NetworkService.wifiNetworks = []
NetworkService.savedWifiNetworks = []; NetworkService.savedWifiNetworks = []
NetworkService.connectionStatus = ""; NetworkService.connectionStatus = ""
NetworkService.connectingSSID = ""; NetworkService.connectingSSID = ""
NetworkService.isScanning = false; NetworkService.isScanning = false
NetworkService.refreshNetworkStatus(); NetworkService.refreshNetworkStatus()
} }
NetworkService.toggleWifiRadio(); NetworkService.toggleWifiRadio()
if (refreshTimer) if (refreshTimer)
refreshTimer.triggered = true; refreshTimer.triggered = true
} }
} }
@@ -157,15 +163,19 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 60 // Exclude toggle area anchors.rightMargin: 60 // Exclude toggle area
hoverEnabled: true hoverEnabled: true
cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi") ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: (NetworkService.ethernetConnected && NetworkService.wifiEnabled
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled && NetworkService.networkStatus !== "wifi" && !NetworkService.changingNetworkPreference && NetworkService.networkStatus
!== "wifi") ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: NetworkService.ethernetConnected && NetworkService.wifiEnabled
&& NetworkService.networkStatus !== "wifi"
&& !NetworkService.changingNetworkPreference
onClicked: { onClicked: {
if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) { if (NetworkService.ethernetConnected && NetworkService.wifiEnabled) {
if (NetworkService.networkStatus !== "wifi") if (NetworkService.networkStatus !== "wifi")
NetworkService.setNetworkPreference("wifi"); NetworkService.setNetworkPreference("wifi")
else else
NetworkService.setNetworkPreference("auto"); NetworkService.setNetworkPreference("auto")
} }
} }
} }
@@ -175,7 +185,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -17,29 +17,35 @@ Rectangle {
property var networkInfoModalRef property var networkInfoModalRef
function show(x, y) { function show(x, y) {
const menuWidth = 160; const menuWidth = 160
wifiContextMenuWindow.visible = true; wifiContextMenuWindow.visible = true
Qt.callLater(() => { Qt.callLater(() => {
const menuHeight = wifiMenuColumn.implicitHeight + Theme.spacingS * 2; const menuHeight = wifiMenuColumn.implicitHeight + Theme.spacingS * 2
let finalX = x - menuWidth / 2; let finalX = x - menuWidth / 2
let finalY = y + 4; let finalY = y + 4
finalX = Math.max(Theme.spacingS, Math.min(finalX, parentItem.width - menuWidth - Theme.spacingS)); finalX = Math.max(
finalY = Math.max(Theme.spacingS, Math.min(finalY, parentItem.height - menuHeight - Theme.spacingS)); Theme.spacingS,
Math.min(finalX,
parentItem.width - menuWidth - Theme.spacingS))
finalY = Math.max(
Theme.spacingS,
Math.min(finalY,
parentItem.height - menuHeight - Theme.spacingS))
if (finalY + menuHeight > parentItem.height - Theme.spacingS) { if (finalY + menuHeight > parentItem.height - Theme.spacingS) {
finalY = y - menuHeight - 4; finalY = y - menuHeight - 4
finalY = Math.max(Theme.spacingS, finalY); finalY = Math.max(Theme.spacingS, finalY)
} }
wifiContextMenuWindow.x = finalX; wifiContextMenuWindow.x = finalX
wifiContextMenuWindow.y = finalY; wifiContextMenuWindow.y = finalY
wifiContextMenuWindow.menuVisible = true; wifiContextMenuWindow.menuVisible = true
}); })
} }
function hide() { function hide() {
wifiContextMenuWindow.menuVisible = false; wifiContextMenuWindow.menuVisible = false
Qt.callLater(() => { Qt.callLater(() => {
wifiContextMenuWindow.visible = false; wifiContextMenuWindow.visible = false
}); })
} }
visible: false visible: false
@@ -53,8 +59,8 @@ Rectangle {
opacity: menuVisible ? 1 : 0 opacity: menuVisible ? 1 : 0
scale: menuVisible ? 1 : 0.85 scale: menuVisible ? 1 : 0.85
Component.onCompleted: { Component.onCompleted: {
menuVisible = false; menuVisible = false
visible = false; visible = false
} }
Rectangle { Rectangle {
@@ -79,7 +85,10 @@ Rectangle {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: connectWifiArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: connectWifiArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -88,7 +97,8 @@ Rectangle {
spacing: Theme.spacingS spacing: Theme.spacingS
DankIcon { DankIcon {
name: wifiContextMenuWindow.networkData && wifiContextMenuWindow.networkData.connected ? "wifi_off" : "wifi" name: wifiContextMenuWindow.networkData
&& wifiContextMenuWindow.networkData.connected ? "wifi_off" : "wifi"
size: Theme.iconSize - 2 size: Theme.iconSize - 2
color: Theme.surfaceText color: Theme.surfaceText
opacity: 0.7 opacity: 0.7
@@ -96,13 +106,13 @@ Rectangle {
} }
StyledText { StyledText {
text: wifiContextMenuWindow.networkData && wifiContextMenuWindow.networkData.connected ? "Disconnect" : "Connect" text: wifiContextMenuWindow.networkData
&& wifiContextMenuWindow.networkData.connected ? "Disconnect" : "Connect"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -114,22 +124,24 @@ Rectangle {
onClicked: { onClicked: {
if (wifiContextMenuWindow.networkData) { if (wifiContextMenuWindow.networkData) {
if (wifiContextMenuWindow.networkData.connected) { if (wifiContextMenuWindow.networkData.connected) {
NetworkService.disconnectWifi(); NetworkService.disconnectWifi()
} else { } else {
if (wifiContextMenuWindow.networkData.saved) { if (wifiContextMenuWindow.networkData.saved) {
NetworkService.connectToWifi(wifiContextMenuWindow.networkData.ssid); NetworkService.connectToWifi(
wifiContextMenuWindow.networkData.ssid)
} else if (wifiContextMenuWindow.networkData.secured) { } else if (wifiContextMenuWindow.networkData.secured) {
if (wifiPasswordModalRef) { if (wifiPasswordModalRef) {
wifiPasswordModalRef.wifiPasswordSSID = wifiContextMenuWindow.networkData.ssid; wifiPasswordModalRef.wifiPasswordSSID = wifiContextMenuWindow.networkData.ssid
wifiPasswordModalRef.wifiPasswordInput = ""; wifiPasswordModalRef.wifiPasswordInput = ""
wifiPasswordModalRef.wifiPasswordModalVisible = true; wifiPasswordModalRef.wifiPasswordModalVisible = true
} }
} else { } else {
NetworkService.connectToWifi(wifiContextMenuWindow.networkData.ssid); NetworkService.connectToWifi(
wifiContextMenuWindow.networkData.ssid)
} }
} }
} }
wifiContextMenuWindow.hide(); wifiContextMenuWindow.hide()
} }
} }
@@ -138,9 +150,7 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
@@ -155,15 +165,19 @@ Rectangle {
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: forgetWifiArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent" color: forgetWifiArea.containsMouse ? Qt.rgba(Theme.error.r,
visible: wifiContextMenuWindow.networkData && (wifiContextMenuWindow.networkData.saved || wifiContextMenuWindow.networkData.connected) Theme.error.g,
Theme.error.b,
0.12) : "transparent"
visible: wifiContextMenuWindow.networkData
&& (wifiContextMenuWindow.networkData.saved
|| wifiContextMenuWindow.networkData.connected)
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -186,7 +200,6 @@ Rectangle {
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -197,9 +210,10 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (wifiContextMenuWindow.networkData) if (wifiContextMenuWindow.networkData)
NetworkService.forgetWifiNetwork(wifiContextMenuWindow.networkData.ssid); NetworkService.forgetWifiNetwork(
wifiContextMenuWindow.networkData.ssid)
wifiContextMenuWindow.hide(); wifiContextMenuWindow.hide()
} }
} }
@@ -208,16 +222,17 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: infoWifiArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: infoWifiArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -240,7 +255,6 @@ Rectangle {
font.weight: Font.Normal font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -251,9 +265,11 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (wifiContextMenuWindow.networkData && networkInfoModalRef) if (wifiContextMenuWindow.networkData && networkInfoModalRef)
networkInfoModalRef.showNetworkInfo(wifiContextMenuWindow.networkData.ssid, wifiContextMenuWindow.networkData); networkInfoModalRef.showNetworkInfo(
wifiContextMenuWindow.networkData.ssid,
wifiContextMenuWindow.networkData)
wifiContextMenuWindow.hide(); wifiContextMenuWindow.hide()
} }
} }
@@ -262,11 +278,8 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -274,7 +287,6 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on scale { Behavior on scale {
@@ -282,7 +294,5 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }

View File

@@ -17,15 +17,15 @@ Column {
function getWiFiSignalIcon(signalStrength) { function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) { switch (signalStrength) {
case "excellent": case "excellent":
return "wifi"; return "wifi"
case "good": case "good":
return "wifi_2_bar"; return "wifi_2_bar"
case "fair": case "fair":
return "wifi_1_bar"; return "wifi_1_bar"
case "poor": case "poor":
return "signal_wifi_0_bar"; return "signal_wifi_0_bar"
default: default:
return "wifi"; return "wifi"
} }
} }
@@ -58,7 +58,11 @@ Column {
width: 28 width: 28
height: 28 height: 28
radius: 14 radius: 14
color: refreshAreaSpan.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : NetworkService.isScanning ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) : "transparent" color: refreshAreaSpan.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : NetworkService.isScanning ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) : "transparent"
DankIcon { DankIcon {
id: refreshIconSpan id: refreshIconSpan
@@ -84,9 +88,7 @@ Column {
duration: 200 duration: 200
easing.type: Easing.OutQuad easing.type: Easing.OutQuad
} }
} }
} }
MouseArea { MouseArea {
@@ -97,14 +99,12 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!NetworkService.isScanning) { if (!NetworkService.isScanning) {
refreshIconSpan.rotation += 30; refreshIconSpan.rotation += 30
NetworkService.scanWifi(); NetworkService.scanWifi()
} }
} }
} }
} }
} }
Flickable { Flickable {
@@ -121,10 +121,13 @@ Column {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling // Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler { WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => { onWheel: event => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60 let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY)) newY = Math.max(0,
Math.min(parent.contentHeight - parent.height,
newY))
parent.contentY = newY parent.contentY = newY
event.accepted = true event.accepted = true
} }
@@ -137,13 +140,18 @@ Column {
spacing: Theme.spacingXS spacing: Theme.spacingXS
Repeater { Repeater {
model: NetworkService.wifiAvailable && NetworkService.wifiEnabled ? sortedWifiNetworks : [] model: NetworkService.wifiAvailable
&& NetworkService.wifiEnabled ? sortedWifiNetworks : []
Rectangle { Rectangle {
width: spanningNetworksColumn.width width: spanningNetworksColumn.width
height: 38 height: 38
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: networkArea2.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : modelData.connected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: networkArea2.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : modelData.connected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
border.color: modelData.connected ? Theme.primary : "transparent" border.color: modelData.connected ? Theme.primary : "transparent"
border.width: modelData.connected ? 1 : 0 border.width: modelData.connected ? 1 : 0
@@ -183,32 +191,36 @@ Column {
width: parent.width width: parent.width
text: { text: {
if (modelData.connected) if (modelData.connected)
return "Connected"; return "Connected"
if (NetworkService.connectionStatus === "connecting" && NetworkService.connectingSSID === modelData.ssid) if (NetworkService.connectionStatus === "connecting"
return "Connecting..."; && NetworkService.connectingSSID === modelData.ssid)
return "Connecting..."
if (NetworkService.connectionStatus === "invalid_password" && NetworkService.connectingSSID === modelData.ssid) if (NetworkService.connectionStatus === "invalid_password"
return "Invalid password"; && NetworkService.connectingSSID === modelData.ssid)
return "Invalid password"
if (modelData.saved) if (modelData.saved)
return "Saved" + (modelData.secured ? " • Secured" : " • Open"); return "Saved" + (modelData.secured ? " • Secured" : " • Open")
return modelData.secured ? "Secured" : "Open"; return modelData.secured ? "Secured" : "Open"
} }
font.pixelSize: Theme.fontSizeSmall - 1 font.pixelSize: Theme.fontSizeSmall - 1
color: { color: {
if (NetworkService.connectionStatus === "connecting" && NetworkService.connectingSSID === modelData.ssid) if (NetworkService.connectionStatus === "connecting"
return Theme.primary; && NetworkService.connectingSSID === modelData.ssid)
return Theme.primary
if (NetworkService.connectionStatus === "invalid_password" && NetworkService.connectingSSID === modelData.ssid) if (NetworkService.connectionStatus === "invalid_password"
return Theme.error; && NetworkService.connectingSSID === modelData.ssid)
return Theme.error
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7); return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
} }
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
Row { Row {
@@ -221,7 +233,8 @@ Column {
DankIcon { DankIcon {
name: "lock" name: "lock"
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
visible: modelData.secured visible: modelData.secured
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -232,7 +245,11 @@ Column {
width: 24 width: 24
height: 24 height: 24
radius: 12 radius: 12
color: wifiMenuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: wifiMenuButtonArea.containsMouse ? Qt.rgba(
Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
DankIcon { DankIcon {
name: "more_vert" name: "more_vert"
@@ -249,13 +266,16 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
wifiContextMenuWindow.networkData = modelData; wifiContextMenuWindow.networkData = modelData
let buttonCenter = wifiMenuButtonArea.width / 2; let buttonCenter = wifiMenuButtonArea.width / 2
let buttonBottom = wifiMenuButtonArea.height; let buttonBottom = wifiMenuButtonArea.height
let globalPos = wifiMenuButtonArea.mapToItem(wifiContextMenuWindow.parentItem, buttonCenter, buttonBottom); let globalPos = wifiMenuButtonArea.mapToItem(
wifiContextMenuWindow.parentItem, buttonCenter,
buttonBottom)
Qt.callLater(() => { Qt.callLater(() => {
wifiContextMenuWindow.show(globalPos.x, globalPos.y); wifiContextMenuWindow.show(globalPos.x,
}); globalPos.y)
})
} }
} }
@@ -263,13 +283,9 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -281,32 +297,27 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (modelData.connected) if (modelData.connected)
return ; return
if (modelData.saved) { if (modelData.saved) {
NetworkService.connectToWifi(modelData.ssid); NetworkService.connectToWifi(modelData.ssid)
} else if (modelData.secured) { } else if (modelData.secured) {
if (wifiPasswordModalRef) { if (wifiPasswordModalRef) {
wifiPasswordModalRef.wifiPasswordSSID = modelData.ssid; wifiPasswordModalRef.wifiPasswordSSID = modelData.ssid
wifiPasswordModalRef.wifiPasswordInput = ""; wifiPasswordModalRef.wifiPasswordInput = ""
wifiPasswordModalRef.wifiPasswordModalVisible = true; wifiPasswordModalRef.wifiPasswordModalVisible = true
} }
} else { } else {
NetworkService.connectToWifi(modelData.ssid); NetworkService.connectToWifi(modelData.ssid)
} }
} }
} }
} }
} }
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded policy: ScrollBar.AsNeeded
} }
} }
} }

View File

@@ -16,34 +16,37 @@ Item {
property var sortedWifiNetworks: { property var sortedWifiNetworks: {
if (!NetworkService.wifiAvailable || !NetworkService.wifiEnabled) { if (!NetworkService.wifiAvailable || !NetworkService.wifiEnabled) {
return []; return []
} }
var allNetworks = NetworkService.wifiNetworks; var allNetworks = NetworkService.wifiNetworks
var savedNetworks = NetworkService.savedWifiNetworks; var savedNetworks = NetworkService.savedWifiNetworks
var currentSSID = NetworkService.currentWifiSSID; var currentSSID = NetworkService.currentWifiSSID
var signalStrength = NetworkService.wifiSignalStrength; var signalStrength = NetworkService.wifiSignalStrength
var refreshTrigger = forceRefresh; // Force recalculation var refreshTrigger = forceRefresh
var networks = [...allNetworks]; // Force recalculation
var networks = [...allNetworks]
networks.forEach(function (network) { networks.forEach(function (network) {
network.connected = (network.ssid === currentSSID); network.connected = (network.ssid === currentSSID)
network.saved = savedNetworks.some(function (saved) { network.saved = savedNetworks.some(function (saved) {
return saved.ssid === network.ssid; return saved.ssid === network.ssid
}); })
if (network.connected && signalStrength) { if (network.connected && signalStrength) {
network.signalStrength = signalStrength; network.signalStrength = signalStrength
} }
}); })
networks.sort(function (a, b) { networks.sort(function (a, b) {
if (a.connected && !b.connected) return -1; if (a.connected && !b.connected)
if (!a.connected && b.connected) return 1; return -1
return b.signal - a.signal; if (!a.connected && b.connected)
}); return 1
return b.signal - a.signal
})
return networks; return networks
} }
property int forceRefresh: 0 property int forceRefresh: 0
@@ -51,21 +54,21 @@ Item {
Connections { Connections {
target: NetworkService target: NetworkService
function onNetworksUpdated() { function onNetworksUpdated() {
forceRefresh++; forceRefresh++
} }
} }
Component.onCompleted: { Component.onCompleted: {
NetworkService.addRef(); NetworkService.addRef()
NetworkService.autoRefreshEnabled = true; NetworkService.autoRefreshEnabled = true
if (NetworkService.wifiEnabled) if (NetworkService.wifiEnabled)
NetworkService.scanWifi(); NetworkService.scanWifi()
wifiMonitorTimer.start(); wifiMonitorTimer.start()
} }
Component.onDestruction: { Component.onDestruction: {
NetworkService.removeRef(); NetworkService.removeRef()
NetworkService.autoRefreshEnabled = false; NetworkService.autoRefreshEnabled = false
} }
Row { Row {
@@ -91,10 +94,12 @@ Item {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling // Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler { WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => { onWheel: event => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60 let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY)) newY = Math.max(
0, Math.min(parent.contentHeight - parent.height, newY))
parent.contentY = newY parent.contentY = newY
event.accepted = true event.accepted = true
} }
@@ -135,10 +140,12 @@ Item {
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling // Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
WheelHandler { WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => { onWheel: event => {
let delta = event.pixelDelta.y !== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60 let delta = event.pixelDelta.y
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
let newY = parent.contentY - delta let newY = parent.contentY - delta
newY = Math.max(0, Math.min(parent.contentHeight - parent.height, newY)) newY = Math.max(
0, Math.min(parent.contentHeight - parent.height, newY))
parent.contentY = newY parent.contentY = newY
event.accepted = true event.accepted = true
} }
@@ -149,8 +156,7 @@ Item {
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
EthernetCard { EthernetCard {}
}
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@@ -177,14 +183,16 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
name: "wifi_off" name: "wifi_off"
size: 48 size: 48
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
} }
StyledText { StyledText {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: "WiFi is turned off" text: "WiFi is turned off"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
font.weight: Font.Medium font.weight: Font.Medium
} }
@@ -192,7 +200,8 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: "Turn on WiFi to see networks" text: "Turn on WiFi to see networks"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.4)
} }
} }
} }
@@ -209,11 +218,11 @@ Item {
running: visible && refreshTimer.triggered running: visible && refreshTimer.triggered
property bool triggered: false property bool triggered: false
onTriggered: { onTriggered: {
NetworkService.refreshNetworkStatus(); NetworkService.refreshNetworkStatus()
if (NetworkService.wifiEnabled && !NetworkService.isScanning) { if (NetworkService.wifiEnabled && !NetworkService.isScanning) {
NetworkService.scanWifi(); NetworkService.scanWifi()
} }
triggered = false; triggered = false
} }
} }
@@ -221,18 +230,18 @@ Item {
target: NetworkService target: NetworkService
function onWifiEnabledChanged() { function onWifiEnabledChanged() {
if (NetworkService.wifiEnabled && visible) { if (NetworkService.wifiEnabled && visible) {
wifiScanDelayTimer.start(); wifiScanDelayTimer.start()
wifiMonitorTimer.start(); wifiMonitorTimer.start()
} else { } else {
NetworkService.currentWifiSSID = ""; NetworkService.currentWifiSSID = ""
NetworkService.wifiSignalStrength = "excellent"; NetworkService.wifiSignalStrength = "excellent"
NetworkService.wifiNetworks = []; NetworkService.wifiNetworks = []
NetworkService.savedWifiNetworks = []; NetworkService.savedWifiNetworks = []
NetworkService.connectionStatus = ""; NetworkService.connectionStatus = ""
NetworkService.connectingSSID = ""; NetworkService.connectingSSID = ""
NetworkService.isScanning = false; NetworkService.isScanning = false
NetworkService.refreshNetworkStatus(); NetworkService.refreshNetworkStatus()
wifiMonitorTimer.stop(); wifiMonitorTimer.stop()
} }
} }
} }
@@ -245,9 +254,9 @@ Item {
onTriggered: { onTriggered: {
if (NetworkService.wifiEnabled && visible) { if (NetworkService.wifiEnabled && visible) {
if (!NetworkService.isScanning) { if (!NetworkService.isScanning) {
NetworkService.scanWifi(); NetworkService.scanWifi()
} else { } else {
wifiRetryTimer.start(); wifiRetryTimer.start()
} }
} }
} }
@@ -259,9 +268,10 @@ Item {
running: false running: false
repeat: false repeat: false
onTriggered: { onTriggered: {
if (NetworkService.wifiEnabled && visible && NetworkService.wifiNetworks.length === 0) { if (NetworkService.wifiEnabled && visible
&& NetworkService.wifiNetworks.length === 0) {
if (!NetworkService.isScanning) { if (!NetworkService.isScanning) {
NetworkService.scanWifi(); NetworkService.scanWifi()
} }
} }
} }
@@ -274,33 +284,32 @@ Item {
repeat: true repeat: true
onTriggered: { onTriggered: {
if (!visible || !NetworkService.wifiEnabled) { if (!visible || !NetworkService.wifiEnabled) {
running = false; running = false
return; return
} }
var shouldScan = false; var shouldScan = false
var reason = ""; var reason = ""
if (NetworkService.networkStatus !== "wifi") { if (NetworkService.networkStatus !== "wifi") {
shouldScan = true; shouldScan = true
reason = "not connected to WiFi"; reason = "not connected to WiFi"
} } else if (NetworkService.wifiNetworks.length === 0) {
else if (NetworkService.wifiNetworks.length === 0) { shouldScan = true
shouldScan = true; reason = "no networks cached"
reason = "no networks cached";
} }
if (shouldScan && !NetworkService.isScanning) { if (shouldScan && !NetworkService.isScanning) {
NetworkService.scanWifi(); NetworkService.scanWifi()
} }
} }
} }
onVisibleChanged: { onVisibleChanged: {
if (visible && NetworkService.wifiEnabled) { if (visible && NetworkService.wifiEnabled) {
wifiMonitorTimer.start(); wifiMonitorTimer.start()
} else { } else {
wifiMonitorTimer.stop(); wifiMonitorTimer.stop()
} }
} }
@@ -315,7 +324,7 @@ Item {
anchors.fill: parent anchors.fill: parent
visible: wifiContextMenuWindow.visible visible: wifiContextMenuWindow.visible
onClicked: { onClicked: {
wifiContextMenuWindow.hide(); wifiContextMenuWindow.hide()
} }
MouseArea { MouseArea {
@@ -324,6 +333,7 @@ Item {
width: wifiContextMenuWindow.width width: wifiContextMenuWindow.width
height: wifiContextMenuWindow.height height: wifiContextMenuWindow.height
onClicked: { onClicked: {
} }
} }
} }

View File

@@ -34,7 +34,7 @@ PanelWindow {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
powerMenuVisible = false; powerMenuVisible = false
} }
} }
@@ -45,7 +45,8 @@ PanelWindow {
y: Theme.barHeight + Theme.spacingXS y: Theme.barHeight + Theme.spacingXS
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: powerMenuVisible ? 1 : 0 opacity: powerMenuVisible ? 1 : 0
scale: powerMenuVisible ? 1 : 0.85 scale: powerMenuVisible ? 1 : 0.85
@@ -54,6 +55,7 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
} }
} }
@@ -84,10 +86,9 @@ PanelWindow {
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
onClicked: { onClicked: {
powerMenuVisible = false; powerMenuVisible = false
} }
} }
} }
Column { Column {
@@ -98,7 +99,13 @@ PanelWindow {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: logoutArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) color: logoutArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -120,7 +127,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -130,21 +136,26 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
powerMenuVisible = false; powerMenuVisible = false
root.powerConfirmAction = "logout"; root.powerConfirmAction = "logout"
root.powerConfirmTitle = "Log Out"; root.powerConfirmTitle = "Log Out"
root.powerConfirmMessage = "Are you sure you want to log out?"; root.powerConfirmMessage = "Are you sure you want to log out?"
root.powerConfirmVisible = true; root.powerConfirmVisible = true
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: suspendArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) color: suspendArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -166,7 +177,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -176,21 +186,26 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
powerMenuVisible = false; powerMenuVisible = false
root.powerConfirmAction = "suspend"; root.powerConfirmAction = "suspend"
root.powerConfirmTitle = "Suspend"; root.powerConfirmTitle = "Suspend"
root.powerConfirmMessage = "Are you sure you want to suspend the system?"; root.powerConfirmMessage = "Are you sure you want to suspend the system?"
root.powerConfirmVisible = true; root.powerConfirmVisible = true
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: rebootArea.containsMouse ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) color: rebootArea.containsMouse ? Qt.rgba(Theme.warning.r,
Theme.warning.g,
Theme.warning.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -212,7 +227,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -222,21 +236,26 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
powerMenuVisible = false; powerMenuVisible = false
root.powerConfirmAction = "reboot"; root.powerConfirmAction = "reboot"
root.powerConfirmTitle = "Reboot"; root.powerConfirmTitle = "Reboot"
root.powerConfirmMessage = "Are you sure you want to reboot the system?"; root.powerConfirmMessage = "Are you sure you want to reboot the system?"
root.powerConfirmVisible = true; root.powerConfirmVisible = true
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: powerOffArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) color: powerOffArea.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.08) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.08)
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -258,7 +277,6 @@ PanelWindow {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -268,18 +286,15 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
powerMenuVisible = false; powerMenuVisible = false
root.powerConfirmAction = "poweroff"; root.powerConfirmAction = "poweroff"
root.powerConfirmTitle = "Power Off"; root.powerConfirmTitle = "Power Off"
root.powerConfirmMessage = "Are you sure you want to power off the system?"; root.powerConfirmMessage = "Are you sure you want to power off the system?"
root.powerConfirmVisible = true; root.powerConfirmVisible = true
} }
} }
} }
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -287,7 +302,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on scale { Behavior on scale {
@@ -295,9 +309,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
} }

View File

@@ -20,21 +20,30 @@ PanelWindow {
property bool autoHide: SettingsData.dockAutoHide property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency property real backgroundTransparency: SettingsData.dockTransparency
property bool contextMenuOpen: (contextMenu && contextMenu.visible
property bool contextMenuOpen: (contextMenu && contextMenu.visible && contextMenu.screen === modelData) || (windowsMenu && windowsMenu.visible && windowsMenu.screen === modelData) && contextMenu.screen === modelData)
|| (windowsMenu && windowsMenu.visible
&& windowsMenu.screen === modelData)
property bool windowIsFullscreen: { property bool windowIsFullscreen: {
if (!NiriService.focusedWindowId || !NiriService.niriAvailable) return false if (!NiriService.focusedWindowId || !NiriService.niriAvailable)
var focusedWindow = NiriService.windows.find(w => w.id === NiriService.focusedWindowId) return false
if (!focusedWindow) return false var focusedWindow = NiriService.windows.find(
w => w.id === NiriService.focusedWindowId)
if (!focusedWindow)
return false
var fullscreenApps = ["vlc", "mpv", "kodi", "steam", "lutris", "wine", "dosbox"] var fullscreenApps = ["vlc", "mpv", "kodi", "steam", "lutris", "wine", "dosbox"]
return fullscreenApps.some(app => focusedWindow.app_id && focusedWindow.app_id.toLowerCase().includes(app)) return fullscreenApps.some(app => focusedWindow.app_id
&& focusedWindow.app_id.toLowerCase(
).includes(app))
} }
property bool reveal: (!autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen) && !windowIsFullscreen property bool reveal: (!autoHide || dockMouseArea.containsMouse
|| dockApps.requestDockShow || contextMenuOpen)
&& !windowIsFullscreen
Connections { Connections {
target: SettingsData target: SettingsData
function onDockTransparencyChanged() { function onDockTransparencyChanged() {
dock.backgroundTransparency = SettingsData.dockTransparency; dock.backgroundTransparency = SettingsData.dockTransparency
} }
} }
@@ -77,7 +86,6 @@ PanelWindow {
} }
} }
Item { Item {
id: dockContainer id: dockContainer
anchors.fill: parent anchors.fill: parent
@@ -109,7 +117,8 @@ PanelWindow {
anchors.topMargin: 4 anchors.topMargin: 4
anchors.bottomMargin: 1 anchors.bottomMargin: 1
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, backgroundTransparency)
radius: Theme.cornerRadiusXLarge radius: Theme.cornerRadiusXLarge
border.width: 1 border.width: 1
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
@@ -117,7 +126,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04) color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
Theme.surfaceTint.b, 0.04)
radius: parent.radius radius: parent.radius
} }
@@ -133,24 +143,26 @@ PanelWindow {
contextMenu: dock.contextMenu contextMenu: dock.contextMenu
windowsMenu: dock.windowsMenu windowsMenu: dock.windowsMenu
} }
} }
Rectangle { Rectangle {
id: appTooltip id: appTooltip
property var hoveredButton: { property var hoveredButton: {
if (!dockApps.children[0]) return null if (!dockApps.children[0])
return null
var row = dockApps.children[0] var row = dockApps.children[0]
var repeater = null var repeater = null
for (var i = 0; i < row.children.length; i++) { for (var i = 0; i < row.children.length; i++) {
var child = row.children[i] var child = row.children[i]
if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") { if (child && typeof child.count !== "undefined"
&& typeof child.itemAt === "function") {
repeater = child repeater = child
break break
} }
} }
if (!repeater || !repeater.itemAt) return null if (!repeater || !repeater.itemAt)
return null
for (var i = 0; i < repeater.count; i++) { for (var i = 0; i < repeater.count; i++) {
var item = repeater.itemAt(i) var item = repeater.itemAt(i)
if (item && item.dockButton && item.dockButton.showTooltip) { if (item && item.dockButton && item.dockButton.showTooltip) {
@@ -172,7 +184,9 @@ PanelWindow {
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
y: -height - 8 y: -height - 8
x: hoveredButton ? hoveredButton.mapToItem(dockContainer, hoveredButton.width/2, 0).x - width/2 : 0 x: hoveredButton ? hoveredButton.mapToItem(dockContainer,
hoveredButton.width / 2,
0).x - width / 2 : 0
StyledText { StyledText {
id: tooltipLabel id: tooltipLabel
@@ -181,7 +195,6 @@ PanelWindow {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
} }
} }

View File

@@ -106,18 +106,19 @@ Item {
cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onPressed: mouse => {
onPressed: (mouse) => { if (mouse.button === Qt.LeftButton && appData
if (mouse.button === Qt.LeftButton && appData && appData.isPinned) { && appData.isPinned) {
dragStartPos = Qt.point(mouse.x, mouse.y) dragStartPos = Qt.point(mouse.x, mouse.y)
longPressTimer.start() longPressTimer.start()
} }
} }
onReleased: (mouse) => { onReleased: mouse => {
longPressTimer.stop() longPressTimer.stop()
if (longPressing) { if (longPressing) {
if (dragging && targetIndex >= 0 && targetIndex !== originalIndex && dockApps) { if (dragging && targetIndex >= 0
&& targetIndex !== originalIndex && dockApps) {
dockApps.movePinnedApp(originalIndex, targetIndex) dockApps.movePinnedApp(originalIndex, targetIndex)
} }
@@ -129,9 +130,12 @@ Item {
} }
} }
onPositionChanged: (mouse) => { onPositionChanged: mouse => {
if (longPressing && !dragging) { if (longPressing && !dragging) {
var distance = Math.sqrt(Math.pow(mouse.x - dragStartPos.x, 2) + Math.pow(mouse.y - dragStartPos.y, 2)) var distance = Math.sqrt(
Math.pow(mouse.x - dragStartPos.x,
2) + Math.pow(mouse.y - dragStartPos.y,
2))
if (distance > 5) { if (distance > 5) {
dragging = true dragging = true
targetIndex = index targetIndex = index
@@ -140,15 +144,18 @@ Item {
} }
if (dragging) { if (dragging) {
dragOffset = Qt.point(mouse.x - dragStartPos.x, mouse.y - dragStartPos.y) dragOffset = Qt.point(mouse.x - dragStartPos.x,
mouse.y - dragStartPos.y)
if (dockApps) { if (dockApps) {
var threshold = 40 var threshold = 40
var newTargetIndex = targetIndex var newTargetIndex = targetIndex
if (dragOffset.x > threshold && targetIndex < dockApps.pinnedAppCount - 1) { if (dragOffset.x > threshold
&& targetIndex < dockApps.pinnedAppCount - 1) {
newTargetIndex = targetIndex + 1 newTargetIndex = targetIndex + 1
} else if (dragOffset.x < -threshold && targetIndex > 0) { } else if (dragOffset.x < -threshold
&& targetIndex > 0) {
newTargetIndex = targetIndex - 1 newTargetIndex = targetIndex - 1
} }
@@ -160,8 +167,9 @@ Item {
} }
} }
onClicked: (mouse) => { onClicked: mouse => {
if (!appData || longPressing) return if (!appData || longPressing)
return
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
var windowCount = appData.windows ? appData.windows.count : 0 var windowCount = appData.windows ? appData.windows.count : 0
@@ -171,11 +179,15 @@ Item {
var desktopEntry = DesktopEntries.byId(appData.appId) var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry) { if (desktopEntry) {
AppUsageHistoryData.addAppUsage({ AppUsageHistoryData.addAppUsage({
id: appData.appId, "id": appData.appId,
name: desktopEntry.name || appData.appId, "name": desktopEntry.name
icon: desktopEntry.icon || "", || appData.appId,
exec: desktopEntry.exec || "", "icon": desktopEntry.icon
comment: desktopEntry.comment || "" || "",
"exec": desktopEntry.exec
|| "",
"comment": desktopEntry.comment
|| ""
}) })
} }
Quickshell.execDetached(["gtk-launch", appData.appId]) Quickshell.execDetached(["gtk-launch", appData.appId])
@@ -191,11 +203,15 @@ Item {
var desktopEntry = DesktopEntries.byId(appData.appId) var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry) { if (desktopEntry) {
AppUsageHistoryData.addAppUsage({ AppUsageHistoryData.addAppUsage({
id: appData.appId, "id": appData.appId,
name: desktopEntry.name || appData.appId, "name": desktopEntry.name
icon: desktopEntry.icon || "", || appData.appId,
exec: desktopEntry.exec || "", "icon": desktopEntry.icon
comment: desktopEntry.comment || "" || "",
"exec": desktopEntry.exec
|| "",
"comment": desktopEntry.comment
|| ""
}) })
} }
Quickshell.execDetached(["gtk-launch", appData.appId]) Quickshell.execDetached(["gtk-launch", appData.appId])
@@ -210,22 +226,25 @@ Item {
property bool showTooltip: mouseArea.containsMouse && !dragging property bool showTooltip: mouseArea.containsMouse && !dragging
property string tooltipText: { property string tooltipText: {
if (!appData || !appData.appId) return "" if (!appData || !appData.appId)
return ""
var desktopEntry = DesktopEntries.byId(appData.appId) var desktopEntry = DesktopEntries.byId(appData.appId)
return desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId return desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId
} }
IconImage { IconImage {
id: iconImg id: iconImg
width: 40 width: 40
height: 40 height: 40
anchors.centerIn: parent anchors.centerIn: parent
source: { source: {
if (!appData || !appData.appId) return "" if (!appData || !appData.appId)
return ""
var desktopEntry = DesktopEntries.byId(appData.appId) var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry && desktopEntry.icon) { if (desktopEntry && desktopEntry.icon) {
var iconPath = Quickshell.iconPath(desktopEntry.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) var iconPath = Quickshell.iconPath(
desktopEntry.icon,
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme)
return iconPath return iconPath
} }
return "" return ""
@@ -250,7 +269,8 @@ Item {
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
text: { text: {
if (!appData || !appData.appId) return "?" if (!appData || !appData.appId)
return "?"
var desktopEntry = DesktopEntries.byId(appData.appId) var desktopEntry = DesktopEntries.byId(appData.appId)
if (desktopEntry && desktopEntry.name) { if (desktopEntry && desktopEntry.name) {
return desktopEntry.name.charAt(0).toUpperCase() return desktopEntry.name.charAt(0).toUpperCase()
@@ -263,7 +283,6 @@ Item {
} }
} }
Row { Row {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@@ -278,10 +297,15 @@ Item {
height: 2 height: 2
radius: 1 radius: 1
color: { color: {
if (!appData || !appData.windows || appData.windows.count === 0) return "transparent" if (!appData || !appData.windows || appData.windows.count === 0)
return "transparent"
var window = appData.windows.get(index) var window = appData.windows.get(index)
return window && window.id == NiriService.focusedWindowId ? Theme.primary : return window
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) && window.id == NiriService.focusedWindowId ? Theme.primary : Qt.rgba(
Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.6)
} }
} }
} }

View File

@@ -17,10 +17,13 @@ Item {
implicitHeight: row.height implicitHeight: row.height
function movePinnedApp(fromIndex, toIndex) { function movePinnedApp(fromIndex, toIndex) {
if (fromIndex === toIndex) return if (fromIndex === toIndex)
return
var currentPinned = [...(SessionData.pinnedApps || [])] var currentPinned = [...(SessionData.pinnedApps || [])]
if (fromIndex < 0 || fromIndex >= currentPinned.length || toIndex < 0 || toIndex >= currentPinned.length) return if (fromIndex < 0 || fromIndex >= currentPinned.length || toIndex < 0
|| toIndex >= currentPinned.length)
return
var movedApp = currentPinned.splice(fromIndex, 1)[0] var movedApp = currentPinned.splice(fromIndex, 1)[0]
currentPinned.splice(toIndex, 0, movedApp) currentPinned.splice(toIndex, 0, movedApp)
@@ -49,16 +52,16 @@ Item {
var pinnedApps = [...(SessionData.pinnedApps || [])] var pinnedApps = [...(SessionData.pinnedApps || [])]
var addedApps = new Set() var addedApps = new Set()
pinnedApps.forEach(appId => { pinnedApps.forEach(appId => {
var lowerAppId = appId.toLowerCase() var lowerAppId = appId.toLowerCase()
if (!addedApps.has(lowerAppId)) { if (!addedApps.has(lowerAppId)) {
var windows = NiriService.getWindowsByAppId(appId) var windows = NiriService.getWindowsByAppId(
appId)
items.push({ items.push({
appId: appId, "appId": appId,
windows: windows, "windows": windows,
isPinned: true, "isPinned": true,
isRunning: windows.length > 0 "isRunning": windows.length > 0
}) })
addedApps.add(lowerAppId) addedApps.add(lowerAppId)
} }
@@ -85,10 +88,12 @@ Item {
var recentApps = [] var recentApps = []
for (var appId in appUsageRanking) { for (var appId in appUsageRanking) {
var lowerAppId = appId.toLowerCase() var lowerAppId = appId.toLowerCase()
if (!addedApps.has(lowerAppId) && !unpinnedAppsSet.has(lowerAppId)) { if (!addedApps.has(lowerAppId) && !unpinnedAppsSet.has(
lowerAppId)) {
recentApps.push({ recentApps.push({
appId: appId, "appId": appId,
lastUsed: appUsageRanking[appId].lastUsed || 0 "lastUsed": appUsageRanking[appId].lastUsed
|| 0
}) })
} }
} }
@@ -101,19 +106,20 @@ Item {
} }
if (pinnedApps.length > 0 && unpinnedApps.length > 0) { if (pinnedApps.length > 0 && unpinnedApps.length > 0) {
items.push({ items.push({
appId: "__SEPARATOR__", "appId": "__SEPARATOR__",
windows: [], "windows": [],
isPinned: false, "isPinned": false,
isRunning: false "isRunning": false
}) })
} }
unpinnedApps.forEach(appId => { unpinnedApps.forEach(appId => {
var windows = NiriService.getWindowsByAppId(appId) var windows = NiriService.getWindowsByAppId(
appId)
items.push({ items.push({
appId: appId, "appId": appId,
windows: windows, "windows": windows,
isPinned: false, "isPinned": false,
isRunning: windows.length > 0 "isRunning": windows.length > 0
}) })
}) })
items.forEach(item => { items.forEach(item => {
@@ -158,12 +164,18 @@ Item {
Connections { Connections {
target: NiriService target: NiriService
function onWindowsChanged() { dockModel.updateModel() } function onWindowsChanged() {
function onWindowOpenedOrChanged() { dockModel.updateModel() } dockModel.updateModel()
}
function onWindowOpenedOrChanged() {
dockModel.updateModel()
}
} }
Connections { Connections {
target: SessionData target: SessionData
function onPinnedAppsChanged() { dockModel.updateModel() } function onPinnedAppsChanged() {
dockModel.updateModel()
}
} }
} }

View File

@@ -34,7 +34,9 @@ PanelWindow {
showContextMenu = true showContextMenu = true
} }
function close() { showContextMenu = false } function close() {
showContextMenu = false
}
screen: Quickshell.screens[0] screen: Quickshell.screens[0]
@@ -43,12 +45,18 @@ PanelWindow {
WlrLayershell.exclusiveZone: -1 WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent" color: "transparent"
anchors { top: true; left: true; right: true; bottom: true } anchors {
top: true
left: true
right: true
bottom: true
}
property point anchorPos: Qt.point(screen.width / 2, screen.height - 100) property point anchorPos: Qt.point(screen.width / 2, screen.height - 100)
onAnchorItemChanged: updatePosition() onAnchorItemChanged: updatePosition()
onVisibleChanged: if (visible) updatePosition() onVisibleChanged: if (visible)
updatePosition()
function updatePosition() { function updatePosition() {
if (!anchorItem) { if (!anchorItem) {
@@ -72,7 +80,8 @@ PanelWindow {
} }
for (var i = 0; i < item.children.length; i++) { for (var i = 0; i < item.children.length; i++) {
var found = findDockBackground(item.children[i]) var found = findDockBackground(item.children[i])
if (found) return found if (found)
return found
} }
return null return null
} }
@@ -96,7 +105,9 @@ PanelWindow {
Rectangle { Rectangle {
id: menuContainer id: menuContainer
width: Math.min(400, Math.max(200, menuColumn.implicitWidth + Theme.spacingS * 2)) width: Math.min(400,
Math.max(200,
menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2) height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
x: { x: {
@@ -108,7 +119,8 @@ PanelWindow {
y: Math.max(10, root.anchorPos.y - height + 30) y: Math.max(10, root.anchorPos.y - height + 30)
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: showContextMenu ? 1 : 0 opacity: showContextMenu ? 1 : 0
scale: showContextMenu ? 1 : 0.85 scale: showContextMenu ? 1 : 0.85
@@ -136,7 +148,10 @@ PanelWindow {
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText { StyledText {
anchors.left: parent.left anchors.left: parent.left
@@ -144,7 +159,8 @@ PanelWindow {
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: root.appData && root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock" text: root.appData
&& root.appData.isPinned ? "Unpin from Dock" : "Pin to Dock"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Normal font.weight: Font.Normal
@@ -158,7 +174,8 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!root.appData) return if (!root.appData)
return
if (root.appData.isPinned) { if (root.appData.isPinned) {
SessionData.removePinnedApp(root.appData.appId) SessionData.removePinnedApp(root.appData.appId)
} else { } else {
@@ -170,21 +187,26 @@ PanelWindow {
} }
Rectangle { Rectangle {
visible: root.appData && root.appData.windows && root.appData.windows.count > 0 visible: root.appData && root.appData.windows
&& root.appData.windows.count > 0
width: parent.width width: parent.width
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
Repeater { Repeater {
model: root.appData && root.appData.windows ? root.appData.windows : null model: root.appData
&& root.appData.windows ? root.appData.windows : null
Rectangle { Rectangle {
required property var model required property var model
width: menuColumn.width width: menuColumn.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText { StyledText {
anchors.left: parent.left anchors.left: parent.left
@@ -214,18 +236,23 @@ PanelWindow {
} }
Rectangle { Rectangle {
visible: root.appData && root.appData.windows && root.appData.windows.count > 1 visible: root.appData && root.appData.windows
&& root.appData.windows.count > 1
width: parent.width width: parent.width
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
Rectangle { Rectangle {
visible: root.appData && root.appData.windows && root.appData.windows.count > 1 visible: root.appData && root.appData.windows
&& root.appData.windows.count > 1
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: closeAllArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent" color: closeAllArea.containsMouse ? Qt.rgba(Theme.error.r,
Theme.error.g,
Theme.error.b,
0.12) : "transparent"
StyledText { StyledText {
anchors.left: parent.left anchors.left: parent.left
@@ -247,7 +274,8 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (!root.appData || !root.appData.windows) return if (!root.appData || !root.appData.windows)
return
for (var i = 0; i < root.appData.windows.count; i++) { for (var i = 0; i < root.appData.windows.count; i++) {
var window = root.appData.windows.get(i) var window = root.appData.windows.get(i)
NiriService.closeWindow(window.id) NiriService.closeWindow(window.id)

View File

@@ -35,7 +35,9 @@ PanelWindow {
showWindowsMenu = true showWindowsMenu = true
} }
function close() { showWindowsMenu = false } function close() {
showWindowsMenu = false
}
screen: Quickshell.screens[0] screen: Quickshell.screens[0]
@@ -44,12 +46,18 @@ PanelWindow {
WlrLayershell.exclusiveZone: -1 WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent" color: "transparent"
anchors { top: true; left: true; right: true; bottom: true } anchors {
top: true
left: true
right: true
bottom: true
}
property point anchorPos: Qt.point(screen.width / 2, screen.height - 100) property point anchorPos: Qt.point(screen.width / 2, screen.height - 100)
onAnchorItemChanged: updatePosition() onAnchorItemChanged: updatePosition()
onVisibleChanged: if (visible) updatePosition() onVisibleChanged: if (visible)
updatePosition()
function updatePosition() { function updatePosition() {
if (!anchorItem) { if (!anchorItem) {
@@ -73,7 +81,8 @@ PanelWindow {
} }
for (var i = 0; i < item.children.length; i++) { for (var i = 0; i < item.children.length; i++) {
var found = findDockBackground(item.children[i]) var found = findDockBackground(item.children[i])
if (found) return found if (found)
return found
} }
return null return null
} }
@@ -97,7 +106,9 @@ PanelWindow {
Rectangle { Rectangle {
id: menuContainer id: menuContainer
width: Math.min(600, Math.max(250, windowColumn.implicitWidth + Theme.spacingS * 2)) width: Math.min(600,
Math.max(250,
windowColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, windowColumn.implicitHeight + Theme.spacingS * 2) height: Math.max(60, windowColumn.implicitHeight + Theme.spacingS * 2)
x: { x: {
@@ -109,12 +120,12 @@ PanelWindow {
y: Math.max(10, root.anchorPos.y - height + 30) y: Math.max(10, root.anchorPos.y - height + 30)
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: showWindowsMenu ? 1 : 0 opacity: showWindowsMenu ? 1 : 0
scale: showWindowsMenu ? 1 : 0.85 scale: showWindowsMenu ? 1 : 0.85
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 4 anchors.topMargin: 4
@@ -126,7 +137,6 @@ PanelWindow {
z: parent.z - 1 z: parent.z - 1
} }
Column { Column {
id: windowColumn id: windowColumn
width: parent.width - Theme.spacingS * 2 width: parent.width - Theme.spacingS * 2
@@ -136,14 +146,18 @@ PanelWindow {
spacing: 1 spacing: 1
Repeater { Repeater {
model: root.appData && root.appData.windows ? root.appData.windows : null model: root.appData
&& root.appData.windows ? root.appData.windows : null
Rectangle { Rectangle {
required property var model required property var model
width: windowColumn.width width: windowColumn.width
height: 32 height: 32
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText { StyledText {
anchors.left: parent.left anchors.left: parent.left

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior
import QtQuick import QtQuick
import Quickshell import Quickshell
@@ -32,7 +32,7 @@ Item {
LockSurface { LockSurface {
lock: lock lock: lock
sharedPasswordBuffer: lock.sharedPasswordBuffer sharedPasswordBuffer: lock.sharedPasswordBuffer
onPasswordChanged: (newPassword) => { onPasswordChanged: newPassword => {
lock.sharedPasswordBuffer = newPassword lock.sharedPasswordBuffer = newPassword
} }
} }

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
@@ -21,32 +21,11 @@ Item {
property var powerModal: null property var powerModal: null
property string confirmAction: "" property string confirmAction: ""
property var facts: [ property var facts: ["Light takes 100,000 years to escape the Sun's core, then just 8 minutes to reach us.", "A teaspoon of neutron star matter would weigh a billion tons here on Earth.", "Right now, 100 trillion solar neutrinos are passing through your body every second.", "The Sun burns 4 million tons of itself into pure energy every second.", "The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.", "There's a nebula out there that's actually colder than empty space itself.", "We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.", "Some cosmic radio bursts release more energy in milliseconds than our Sun does in days.", "Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.", "Distant galaxies can move away from us faster than light because space itself is stretching.", "The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.", "The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.", "A day on Venus lasts longer than its entire year around the Sun.", "On Mercury, the time between sunrises is 176 Earth days long.", "In about 4.5 billion years, our galaxy will smash into Andromeda.", "Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.", "A black hole the mass of our Sun would take longer to evaporate than the current age of the universe... times a trillion trillion trillion trillion trillion.", "The fastest spinning star we know rotates 716 times per second.", "Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.", "Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky."]
"Light takes 100,000 years to escape the Sun's core, then just 8 minutes to reach us.",
"A teaspoon of neutron star matter would weigh a billion tons here on Earth.",
"Right now, 100 trillion solar neutrinos are passing through your body every second.",
"The Sun burns 4 million tons of itself into pure energy every second.",
"The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.",
"There's a nebula out there that's actually colder than empty space itself.",
"We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.",
"Some cosmic radio bursts release more energy in milliseconds than our Sun does in days.",
"Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.",
"Distant galaxies can move away from us faster than light because space itself is stretching.",
"The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.",
"The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.",
"A day on Venus lasts longer than its entire year around the Sun.",
"On Mercury, the time between sunrises is 176 Earth days long.",
"In about 4.5 billion years, our galaxy will smash into Andromeda.",
"Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.",
"A black hole the mass of our Sun would take longer to evaporate than the current age of the universe... times a trillion trillion trillion trillion trillion.",
"The fastest spinning star we know rotates 716 times per second.",
"Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.",
"Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky."
]
property string randomFact: "" property string randomFact: ""
signal unlockRequested() signal unlockRequested
Component.onCompleted: { Component.onCompleted: {
pickRandomFact() pickRandomFact()
@@ -115,7 +94,10 @@ Item {
id: clockText id: clockText
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top anchors.top: parent.top
text: SettingsData.use24HourClock ? Qt.formatTime(new Date(), "H:mm") : Qt.formatTime(new Date(), "h:mm AP") text: SettingsData.use24HourClock ? Qt.formatTime(
new Date(),
"H:mm") : Qt.formatTime(
new Date(), "h:mm AP")
font.pixelSize: 120 font.pixelSize: 120
font.weight: Font.Light font.weight: Font.Light
color: "white" color: "white"
@@ -125,7 +107,11 @@ Item {
interval: 1000 interval: 1000
running: true running: true
repeat: true repeat: true
onTriggered: parent.text = SettingsData.use24HourClock ? Qt.formatTime(new Date(), "H:mm") : Qt.formatTime(new Date(), "h:mm AP") onTriggered: parent.text = SettingsData.use24HourClock ? Qt.formatTime(
new Date(),
"H:mm") : Qt.formatTime(
new Date(),
"h:mm AP")
} }
} }
@@ -227,7 +213,8 @@ Item {
name: "warning" name: "warning"
size: Theme.iconSize + 4 size: Theme.iconSize + 4
color: Theme.primaryText color: Theme.primaryText
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error visible: PortalService.profileImage !== ""
&& profileImageLoader.status === Image.Error
} }
} }
@@ -235,8 +222,10 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 60 Layout.preferredHeight: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(1, 1, 1, 0.3) Theme.surfaceContainer.b, 0.9)
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(
1, 1, 1, 0.3)
border.width: passwordField.activeFocus ? 2 : 1 border.width: passwordField.activeFocus ? 2 : 1
property bool showPassword: false property bool showPassword: false
@@ -262,7 +251,10 @@ Item {
id: passwordField id: passwordField
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: lockIcon.width + Theme.spacingM * 2 anchors.leftMargin: lockIcon.width + Theme.spacingM * 2
anchors.rightMargin: (revealButton.visible ? revealButton.width + Theme.spacingM : 0) + (enterButton.visible ? enterButton.width + Theme.spacingM : 0) + (loadingSpinner.visible ? loadingSpinner.width + Theme.spacingM : Theme.spacingM) anchors.rightMargin: (revealButton.visible ? revealButton.width + Theme.spacingM : 0)
+ (enterButton.visible ? enterButton.width + Theme.spacingM : 0)
+ (loadingSpinner.visible ? loadingSpinner.width
+ Theme.spacingM : Theme.spacingM)
opacity: 0 opacity: 0
focus: !demoMode focus: !demoMode
enabled: !demoMode enabled: !demoMode
@@ -289,7 +281,8 @@ Item {
} }
Keys.onPressed: event => { Keys.onPressed: event => {
if (demoMode) return if (demoMode)
return
if (pam.active) { if (pam.active) {
console.log("PAM is active, ignoring input") console.log("PAM is active, ignoring input")
@@ -310,9 +303,12 @@ Item {
property string pamState: "" property string pamState: ""
text: { text: {
if (demoMode) return "" if (demoMode)
if (root.unlocking) return "Unlocking..." return ""
if (pam.active) return "Authenticating..." if (root.unlocking)
return "Unlocking..."
if (pam.active)
return "Authenticating..."
return "hunter2" return "hunter2"
} }
@@ -372,7 +368,8 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
iconName: parent.showPassword ? "visibility_off" : "visibility" iconName: parent.showPassword ? "visibility_off" : "visibility"
buttonSize: 32 buttonSize: 32
visible: !demoMode && root.passwordBuffer.length > 0 && !pam.active && !root.unlocking visible: !demoMode && root.passwordBuffer.length > 0 && !pam.active
&& !root.unlocking
enabled: visible enabled: visible
onClicked: parent.showPassword = !parent.showPassword onClicked: parent.showPassword = !parent.showPassword
} }
@@ -397,8 +394,20 @@ Item {
SequentialAnimation on scale { SequentialAnimation on scale {
running: root.unlocking running: root.unlocking
NumberAnimation { from: 0; to: 1.2; duration: Anims.durShort; easing.type: Easing.BezierSpline; easing.bezierCurve: Anims.emphasizedDecel } NumberAnimation {
NumberAnimation { from: 1.2; to: 1; duration: Anims.durShort; easing.type: Easing.BezierSpline; easing.bezierCurve: Anims.emphasizedAccel } from: 0
to: 1.2
duration: Anims.durShort
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedDecel
}
NumberAnimation {
from: 1.2
to: 1
duration: Anims.durShort
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedAccel
}
} }
} }
@@ -412,7 +421,8 @@ Item {
radius: 10 radius: 10
anchors.centerIn: parent anchors.centerIn: parent
color: "transparent" color: "transparent"
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 2 border.width: 2
} }
@@ -430,7 +440,9 @@ Item {
height: parent.height / 2 height: parent.height / 2
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9) color: Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.9)
} }
RotationAnimation on rotation { RotationAnimation on rotation {
@@ -451,7 +463,8 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
iconName: "keyboard_return" iconName: "keyboard_return"
buttonSize: 36 buttonSize: 36
visible: (demoMode || (root.passwordBuffer.length > 0 && !pam.active && !root.unlocking)) visible: (demoMode || (root.passwordBuffer.length > 0 && !pam.active
&& !root.unlocking))
enabled: !demoMode enabled: !demoMode
onClicked: { onClicked: {
if (!demoMode) { if (!demoMode) {
@@ -468,16 +481,18 @@ Item {
} }
} }
} }
} }
StyledText { StyledText {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: placeholder.pamState ? 20 : 0 Layout.preferredHeight: placeholder.pamState ? 20 : 0
text: { text: {
if (placeholder.pamState === "error") return "Authentication error - try again" if (placeholder.pamState === "error")
if (placeholder.pamState === "max") return "Too many attempts - locked out" return "Authentication error - try again"
if (placeholder.pamState === "fail") return "Incorrect password - try again" if (placeholder.pamState === "max")
return "Too many attempts - locked out"
if (placeholder.pamState === "fail")
return "Incorrect password - try again"
return "" return ""
} }
color: Theme.error color: Theme.error
@@ -517,9 +532,8 @@ Item {
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
anchors.margins: Theme.spacingXL anchors.margins: Theme.spacingXL
text: WeatherService.weather.available && WeatherService.weather.city && WeatherService.weather.city !== "Unknown" ? text: WeatherService.weather.available && WeatherService.weather.city
`${WeatherService.weather.city} ${(SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)}°${(SettingsData.useFahrenheit ? "F" : "C")}` : && WeatherService.weather.city !== "Unknown" ? `${WeatherService.weather.city} ${(SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp)}°${(SettingsData.useFahrenheit ? "F" : "C")}` : ""
""
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: "white" color: "white"
horizontalAlignment: Text.AlignRight horizontalAlignment: Text.AlignRight
@@ -606,15 +620,19 @@ Item {
config: pamConfigWatcher.loaded ? "dankshell" : "login" config: pamConfigWatcher.loaded ? "dankshell" : "login"
onResponseRequiredChanged: { onResponseRequiredChanged: {
if (demoMode) return if (demoMode)
return
console.log("PAM response required:", responseRequired) console.log("PAM response required:", responseRequired)
if (!responseRequired) return if (!responseRequired)
console.log("Responding to PAM with password buffer length:", root.passwordBuffer.length) return
console.log("Responding to PAM with password buffer length:",
root.passwordBuffer.length)
respond(root.passwordBuffer) respond(root.passwordBuffer)
} }
onCompleted: res => { onCompleted: res => {
if (demoMode) return if (demoMode)
return
console.log("PAM authentication completed with result:", res) console.log("PAM authentication completed with result:", res)
if (res === PamResult.Success) { if (res === PamResult.Success) {
console.log("Authentication successful, unlocking") console.log("Authentication successful, unlocking")
@@ -656,8 +674,12 @@ Item {
visible: false visible: false
z: 1000 z: 1000
function open() { visible = true } function open() {
function close() { visible = false } visible = true
}
function close() {
visible = false
}
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
@@ -695,8 +717,11 @@ Item {
width: 100 width: 100
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: cancelMouse1.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) : color: cancelMouse1.pressed ? Qt.rgba(
cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -718,8 +743,14 @@ Item {
width: 100 width: 100
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: powerMouse.pressed ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8) : color: powerMouse.pressed ? Qt.rgba(
powerMouse.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 1.0) : Theme.error Theme.error.r, Theme.error.g,
Theme.error.b,
0.8) : powerMouse.containsMouse ? Qt.rgba(
Theme.error.r,
Theme.error.g,
Theme.error.b,
1.0) : Theme.error
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -752,8 +783,12 @@ Item {
visible: false visible: false
z: 1000 z: 1000
function open() { visible = true } function open() {
function close() { visible = false } visible = true
}
function close() {
visible = false
}
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
@@ -791,8 +826,11 @@ Item {
width: 100 width: 100
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: cancelMouse2.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) : color: cancelMouse2.pressed ? Qt.rgba(
cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -814,8 +852,14 @@ Item {
width: 100 width: 100
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: rebootMouse.pressed ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) : color: rebootMouse.pressed ? Qt.rgba(
rebootMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1.0) : Theme.primary Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.8) : rebootMouse.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
1.0) : Theme.primary
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -848,8 +892,12 @@ Item {
visible: false visible: false
z: 1000 z: 1000
function open() { visible = true } function open() {
function close() { visible = false } visible = true
}
function close() {
visible = false
}
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
@@ -887,8 +935,11 @@ Item {
width: 100 width: 100
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: cancelMouse3.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) : color: cancelMouse3.pressed ? Qt.rgba(
cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -910,8 +961,14 @@ Item {
width: 100 width: 100
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: logoutMouse.pressed ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) : color: logoutMouse.pressed ? Qt.rgba(
logoutMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1.0) : Theme.primary Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.8) : logoutMouse.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
1.0) : Theme.primary
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -936,5 +993,4 @@ Item {
} }
} }
} }
} }

View File

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

View File

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

View File

@@ -14,8 +14,8 @@ PanelWindow {
property bool micPopupVisible: false property bool micPopupVisible: false
function show() { function show() {
root.micPopupVisible = true; root.micPopupVisible = true
hideTimer.restart(); hideTimer.restart()
} }
screen: modelData screen: modelData
@@ -38,13 +38,13 @@ PanelWindow {
interval: 2000 interval: 2000
repeat: false repeat: false
onTriggered: { onTriggered: {
root.micPopupVisible = false; root.micPopupVisible = false
} }
} }
Connections { Connections {
function onMicMuteChanged() { function onMicMuteChanged() {
root.show(); root.show()
} }
target: AudioService target: AudioService
@@ -60,7 +60,8 @@ PanelWindow {
anchors.bottomMargin: Theme.spacingM anchors.bottomMargin: Theme.spacingM
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: root.micPopupVisible ? 1 : 0 opacity: root.micPopupVisible ? 1 : 0
scale: root.micPopupVisible ? 1 : 0.9 scale: root.micPopupVisible ? 1 : 0.9
@@ -70,9 +71,11 @@ PanelWindow {
id: micContent id: micContent
anchors.centerIn: parent anchors.centerIn: parent
name: AudioService.source && AudioService.source.audio && AudioService.source.audio.muted ? "mic_off" : "mic" name: AudioService.source && AudioService.source.audio
&& AudioService.source.audio.muted ? "mic_off" : "mic"
size: Theme.iconSize size: Theme.iconSize
color: AudioService.source && AudioService.source.audio && AudioService.source.audio.muted ? Theme.error : Theme.primary color: AudioService.source && AudioService.source.audio
&& AudioService.source.audio.muted ? Theme.error : Theme.primary
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {

View File

@@ -11,25 +11,36 @@ Rectangle {
id: root id: root
property var notificationGroup property var notificationGroup
property bool expanded: NotificationService.expandedGroups[notificationGroup?.key] || false property bool expanded: NotificationService.expandedGroups[notificationGroup?.key]
property bool descriptionExpanded: NotificationService.expandedMessages[notificationGroup?.latestNotification?.notification?.id + "_desc"] || false || false
property bool descriptionExpanded: NotificationService.expandedMessages[notificationGroup?.latestNotification?.notification?.id + "_desc"]
|| false
property bool userInitiatedExpansion: false property bool userInitiatedExpansion: false
width: parent ? parent.width : 400 width: parent ? parent.width : 400
height: { height: {
if (expanded) { if (expanded) {
return expandedContent.height + 28; return expandedContent.height + 28
} }
const baseHeight = 116; const baseHeight = 116
if (descriptionExpanded) { if (descriptionExpanded) {
return baseHeight + descriptionText.contentHeight - (descriptionText.font.pixelSize * 1.2 * 2); return baseHeight + descriptionText.contentHeight - (descriptionText.font.pixelSize * 1.2 * 2)
} }
return baseHeight; return baseHeight
} }
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) Theme.surfaceVariant.b, 0.1)
border.width: notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical ? 2 : 1 border.color: notificationGroup?.latestNotification?.urgency
=== NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.3) : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.05)
border.width: notificationGroup?.latestNotification?.urgency
=== NotificationUrgency.Critical ? 2 : 1
clip: true clip: true
Rectangle { Rectangle {
@@ -67,7 +78,9 @@ Rectangle {
Rectangle { Rectangle {
id: iconContainer id: iconContainer
readonly property bool hasNotificationImage: notificationGroup?.latestNotification?.image && notificationGroup.latestNotification.image !== "" readonly property bool hasNotificationImage: notificationGroup?.latestNotification?.image
&& notificationGroup.latestNotification.image
!== ""
width: 55 width: 55
height: 55 height: 55
@@ -84,24 +97,27 @@ Rectangle {
anchors.margins: 2 anchors.margins: 2
source: { source: {
if (parent.hasNotificationImage) if (parent.hasNotificationImage)
return notificationGroup.latestNotification.cleanImage; return notificationGroup.latestNotification.cleanImage
if (notificationGroup?.latestNotification?.appIcon) { if (notificationGroup?.latestNotification?.appIcon) {
const appIcon = notificationGroup.latestNotification.appIcon; const appIcon = notificationGroup.latestNotification.appIcon
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://")) if (appIcon.startsWith("file://") || appIcon.startsWith("http://")
return appIcon; || appIcon.startsWith("https://"))
return Quickshell.iconPath(appIcon, ""); return appIcon
return Quickshell.iconPath(appIcon, "")
} }
return ""; return ""
} }
visible: status === Image.Ready visible: status === Image.Ready
} }
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
visible: !parent.hasNotificationImage && (!notificationGroup?.latestNotification?.appIcon || notificationGroup.latestNotification.appIcon === "") visible: !parent.hasNotificationImage
&& (!notificationGroup?.latestNotification?.appIcon
|| notificationGroup.latestNotification.appIcon === "")
text: { text: {
const appName = notificationGroup?.appName || "?"; const appName = notificationGroup?.appName || "?"
return appName.charAt(0).toUpperCase(); return appName.charAt(0).toUpperCase()
} }
font.pixelSize: 20 font.pixelSize: 20
font.weight: Font.Bold font.weight: Font.Bold
@@ -121,7 +137,8 @@ Rectangle {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString() text: (notificationGroup?.count
|| 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString()
color: Theme.primaryText color: Theme.primaryText
font.pixelSize: 9 font.pixelSize: 9
font.weight: Font.Bold font.weight: Font.Bold
@@ -154,11 +171,12 @@ Rectangle {
StyledText { StyledText {
width: parent.width width: parent.width
text: { text: {
const timeStr = notificationGroup?.latestNotification?.timeStr || ""; const timeStr = notificationGroup?.latestNotification?.timeStr
|| ""
if (timeStr.length > 0) if (timeStr.length > 0)
return (notificationGroup?.appName || "") + " • " + timeStr; return (notificationGroup?.appName || "") + " • " + timeStr
else else
return notificationGroup?.appName || ""; return notificationGroup?.appName || ""
} }
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -180,7 +198,8 @@ Rectangle {
StyledText { StyledText {
id: descriptionText id: descriptionText
property string fullText: notificationGroup?.latestNotification?.htmlBody || "" property string fullText: notificationGroup?.latestNotification?.htmlBody
|| ""
property bool hasMoreText: truncated property bool hasMoreText: truncated
text: fullText text: fullText
@@ -192,30 +211,31 @@ Rectangle {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
visible: text.length > 0 visible: text.length > 0
linkColor: Theme.primary linkColor: Theme.primary
onLinkActivated: (link) => Qt.openUrlExternally(link) onLinkActivated: link => Qt.openUrlExternally(link)
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (parent.hasMoreText
(parent.hasMoreText || descriptionExpanded) ? Qt.PointingHandCursor : || descriptionExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
Qt.ArrowCursor
onClicked: mouse => { onClicked: mouse => {
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) { if (!parent.hoveredLink
const messageId = notificationGroup?.latestNotification?.notification?.id + "_desc"; && (parent.hasMoreText || descriptionExpanded)) {
NotificationService.toggleMessageExpansion(messageId); const messageId = notificationGroup?.latestNotification?.notification?.id + "_desc"
NotificationService.toggleMessageExpansion(
messageId)
} }
} }
propagateComposedEvents: true propagateComposedEvents: true
onPressed: mouse => { onPressed: mouse => {
if (parent.hoveredLink) { if (parent.hoveredLink) {
mouse.accepted = false; mouse.accepted = false
} }
} }
onReleased: mouse => { onReleased: mouse => {
if (parent.hoveredLink) { if (parent.hoveredLink) {
mouse.accepted = false; mouse.accepted = false
} }
} }
} }
@@ -268,14 +288,15 @@ Rectangle {
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: (notificationGroup?.count || 0) > 99 ? "99+" : (notificationGroup?.count || 0).toString() text: (notificationGroup?.count
|| 0) > 99 ? "99+" : (notificationGroup?.count
|| 0).toString()
color: Theme.primaryText color: Theme.primaryText
font.pixelSize: 9 font.pixelSize: 9
font.weight: Font.Bold font.weight: Font.Bold
} }
} }
} }
} }
Column { Column {
@@ -287,23 +308,25 @@ Rectangle {
delegate: Rectangle { delegate: Rectangle {
required property var modelData required property var modelData
readonly property bool messageExpanded: NotificationService.expandedMessages[modelData?.notification?.id] || false readonly property bool messageExpanded: NotificationService.expandedMessages[modelData?.notification?.id]
|| false
width: parent.width width: parent.width
height: { height: {
const baseHeight = 120; const baseHeight = 120
if (messageExpanded) { if (messageExpanded) {
const twoLineHeight = bodyText.font.pixelSize * 1.2 * 2; const twoLineHeight = bodyText.font.pixelSize * 1.2 * 2
if (bodyText.implicitHeight > twoLineHeight + 2) { if (bodyText.implicitHeight > twoLineHeight + 2) {
const extraHeight = bodyText.implicitHeight - twoLineHeight; const extraHeight = bodyText.implicitHeight - twoLineHeight
return baseHeight + extraHeight; return baseHeight + extraHeight
} }
} }
return baseHeight; return baseHeight
} }
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: "transparent" color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1 border.width: 1
Behavior on height { Behavior on height {
@@ -318,7 +341,8 @@ Rectangle {
Rectangle { Rectangle {
id: messageIcon id: messageIcon
readonly property bool hasNotificationImage: modelData?.image && modelData.image !== "" readonly property bool hasNotificationImage: modelData?.image
&& modelData.image !== ""
width: 32 width: 32
height: 32 height: 32
@@ -326,8 +350,10 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 32 anchors.topMargin: 32
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) color: Qt.rgba(Theme.primary.r, Theme.primary.g,
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) Theme.primary.b, 0.1)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.2)
border.width: 1 border.width: 1
IconImage { IconImage {
@@ -335,26 +361,28 @@ Rectangle {
anchors.margins: 1 anchors.margins: 1
source: { source: {
if (parent.hasNotificationImage) if (parent.hasNotificationImage)
return modelData.cleanImage; return modelData.cleanImage
if (modelData?.appIcon) { if (modelData?.appIcon) {
const appIcon = modelData.appIcon; const appIcon = modelData.appIcon
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://")) if (appIcon.startsWith("file://") || appIcon.startsWith(
return appIcon; "http://") || appIcon.startsWith("https://"))
return appIcon
return Quickshell.iconPath(appIcon, ""); return Quickshell.iconPath(appIcon, "")
} }
return ""; return ""
} }
visible: status === Image.Ready visible: status === Image.Ready
} }
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
visible: !parent.hasNotificationImage && (!modelData?.appIcon || modelData.appIcon === "") visible: !parent.hasNotificationImage
&& (!modelData?.appIcon || modelData.appIcon === "")
text: { text: {
const appName = modelData?.appName || "?"; const appName = modelData?.appName || "?"
return appName.charAt(0).toUpperCase(); return appName.charAt(0).toUpperCase()
} }
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold font.weight: Font.Bold
@@ -413,28 +441,29 @@ Rectangle {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
visible: text.length > 0 visible: text.length > 0
linkColor: Theme.primary linkColor: Theme.primary
onLinkActivated: (link) => Qt.openUrlExternally(link) onLinkActivated: link => Qt.openUrlExternally(link)
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : (bodyText.hasMoreText || messageExpanded) ? Qt.PointingHandCursor : Qt.ArrowCursor
(bodyText.hasMoreText || messageExpanded) ? Qt.PointingHandCursor :
Qt.ArrowCursor
onClicked: mouse => { onClicked: mouse => {
if (!parent.hoveredLink && (bodyText.hasMoreText || messageExpanded)) { if (!parent.hoveredLink
NotificationService.toggleMessageExpansion(modelData?.notification?.id || ""); && (bodyText.hasMoreText
|| messageExpanded)) {
NotificationService.toggleMessageExpansion(
modelData?.notification?.id || "")
} }
} }
propagateComposedEvents: true propagateComposedEvents: true
onPressed: mouse => { onPressed: mouse => {
if (parent.hoveredLink) { if (parent.hoveredLink) {
mouse.accepted = false; mouse.accepted = false
} }
} }
onReleased: mouse => { onReleased: mouse => {
if (parent.hoveredLink) { if (parent.hoveredLink) {
mouse.accepted = false; mouse.accepted = false
} }
} }
} }
@@ -462,7 +491,10 @@ Rectangle {
width: Math.max(actionText.implicitWidth + 12, 50) width: Math.max(actionText.implicitWidth + 12, 50)
height: 24 height: 24
radius: 4 radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent" color: isHovered ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.1) : "transparent"
StyledText { StyledText {
id: actionText id: actionText
@@ -482,7 +514,7 @@ Rectangle {
onExited: parent.isHovered = false onExited: parent.isHovered = false
onClicked: { onClicked: {
if (modelData && modelData.invoke) { if (modelData && modelData.invoke) {
modelData.invoke(); modelData.invoke()
} }
} }
} }
@@ -495,7 +527,10 @@ Rectangle {
width: Math.max(clearText.implicitWidth + 12, 50) width: Math.max(clearText.implicitWidth + 12, 50)
height: 24 height: 24
radius: 4 radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent" color: isHovered ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.1) : "transparent"
StyledText { StyledText {
id: clearText id: clearText
@@ -512,7 +547,8 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onEntered: parent.isHovered = true onEntered: parent.isHovered = true
onExited: parent.isHovered = false onExited: parent.isHovered = false
onClicked: NotificationService.dismissNotification(modelData) onClicked: NotificationService.dismissNotification(
modelData)
} }
} }
} }
@@ -541,7 +577,8 @@ Rectangle {
width: Math.max(actionText.implicitWidth + 12, 50) width: Math.max(actionText.implicitWidth + 12, 50)
height: 24 height: 24
radius: 4 radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent" color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
StyledText { StyledText {
id: actionText id: actionText
@@ -561,7 +598,7 @@ Rectangle {
onExited: parent.isHovered = false onExited: parent.isHovered = false
onClicked: { onClicked: {
if (modelData && modelData.invoke) { if (modelData && modelData.invoke) {
modelData.invoke(); modelData.invoke()
} }
} }
} }
@@ -582,7 +619,8 @@ Rectangle {
width: clearText.width + 16 width: clearText.width + 16
height: clearText.height + 8 height: clearText.height + 8
radius: 6 radius: 6
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent" color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
StyledText { StyledText {
id: clearText id: clearText
@@ -605,7 +643,8 @@ Rectangle {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
visible: !expanded && (notificationGroup?.count || 0) > 1 && !descriptionExpanded visible: !expanded && (notificationGroup?.count || 0) > 1
&& !descriptionExpanded
onClicked: { onClicked: {
root.userInitiatedExpansion = true root.userInitiatedExpansion = true
NotificationService.toggleGroupExpansion(notificationGroup?.key || "") NotificationService.toggleGroupExpansion(notificationGroup?.key || "")

View File

@@ -18,15 +18,15 @@ PanelWindow {
property string triggerSection: "right" property string triggerSection: "right"
function setTriggerPosition(x, y, width, section) { function setTriggerPosition(x, y, width, section) {
triggerX = x; triggerX = x
triggerY = y; triggerY = y
triggerWidth = width; triggerWidth = width
triggerSection = section; triggerSection = section
} }
visible: notificationHistoryVisible visible: notificationHistoryVisible
onNotificationHistoryVisibleChanged: { onNotificationHistoryVisibleChanged: {
NotificationService.disablePopups(notificationHistoryVisible); NotificationService.disablePopups(notificationHistoryVisible)
} }
implicitWidth: 400 implicitWidth: 400
implicitHeight: Math.min(Screen.height * 0.8, 400) implicitHeight: Math.min(Screen.height * 0.8, 400)
@@ -45,7 +45,7 @@ PanelWindow {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
notificationHistoryVisible = false; notificationHistoryVisible = false
} }
} }
@@ -53,34 +53,35 @@ PanelWindow {
id: mainRect id: mainRect
function calculateHeight() { function calculateHeight() {
let baseHeight = Theme.spacingL * 2; let baseHeight = Theme.spacingL * 2
baseHeight += notificationHeader.height; baseHeight += notificationHeader.height
baseHeight += Theme.spacingM; baseHeight += Theme.spacingM
let listHeight = notificationList.listContentHeight; let listHeight = notificationList.listContentHeight
if (NotificationService.groupedNotifications.length === 0) if (NotificationService.groupedNotifications.length === 0)
listHeight = 200; listHeight = 200
baseHeight += Math.min(listHeight, 600); baseHeight += Math.min(listHeight, 600)
return Math.max(300, baseHeight); return Math.max(300, baseHeight)
} }
readonly property real popupWidth: 400 readonly property real popupWidth: 400
readonly property real calculatedX: { readonly property real calculatedX: {
var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2); var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2)
if (centerX >= Theme.spacingM && centerX + popupWidth <= Screen.width - Theme.spacingM) { if (centerX >= Theme.spacingM
return centerX; && centerX + popupWidth <= Screen.width - Theme.spacingM) {
return centerX
} }
if (centerX < Theme.spacingM) { if (centerX < Theme.spacingM) {
return Theme.spacingM; return Theme.spacingM
} }
if (centerX + popupWidth > Screen.width - Theme.spacingM) { if (centerX + popupWidth > Screen.width - Theme.spacingM) {
return Screen.width - popupWidth - Theme.spacingM; return Screen.width - popupWidth - Theme.spacingM
} }
return centerX; return centerX
} }
width: popupWidth width: popupWidth
@@ -89,7 +90,8 @@ PanelWindow {
y: root.triggerY y: root.triggerY
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: notificationHistoryVisible ? 1 : 0 opacity: notificationHistoryVisible ? 1 : 0
scale: notificationHistoryVisible ? 1 : 0.9 scale: notificationHistoryVisible ? 1 : 0.9
@@ -97,6 +99,7 @@ PanelWindow {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
} }
} }
@@ -109,12 +112,12 @@ PanelWindow {
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {
if (notificationHistoryVisible) if (notificationHistoryVisible)
forceActiveFocus(); forceActiveFocus()
} }
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
notificationHistoryVisible = false; notificationHistoryVisible = false
event.accepted = true; event.accepted = true
} }
} }
@@ -122,10 +125,10 @@ PanelWindow {
function onNotificationHistoryVisibleChanged() { function onNotificationHistoryVisibleChanged() {
if (notificationHistoryVisible) if (notificationHistoryVisible)
Qt.callLater(function () { Qt.callLater(function () {
contentColumn.forceActiveFocus(); contentColumn.forceActiveFocus()
}); })
else else
contentColumn.focus = false; contentColumn.focus = false
} }
target: root target: root
} }
@@ -140,24 +143,23 @@ PanelWindow {
width: parent.width width: parent.width
height: parent.height - notificationHeader.height - contentColumn.spacing height: parent.height - notificationHeader.height - contentColumn.spacing
} }
} }
Connections { Connections {
function onNotificationsChanged() { function onNotificationsChanged() {
mainRect.height = mainRect.calculateHeight(); mainRect.height = mainRect.calculateHeight()
} }
function onGroupedNotificationsChanged() { function onGroupedNotificationsChanged() {
mainRect.height = mainRect.calculateHeight(); mainRect.height = mainRect.calculateHeight()
} }
function onExpandedGroupsChanged() { function onExpandedGroupsChanged() {
mainRect.height = mainRect.calculateHeight(); mainRect.height = mainRect.calculateHeight()
} }
function onExpandedMessagesChanged() { function onExpandedMessagesChanged() {
mainRect.height = mainRect.calculateHeight(); mainRect.height = mainRect.calculateHeight()
} }
target: NotificationService target: NotificationService
@@ -168,7 +170,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -177,7 +178,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
Behavior on scale { Behavior on scale {
@@ -186,9 +186,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
} }
} }

View File

@@ -19,18 +19,18 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
name: "notifications_none" name: "notifications_none"
size: Theme.iconSizeLarge + 16 size: Theme.iconSizeLarge + 16
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
} }
StyledText { StyledText {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: "Nothing to see here" text: "Nothing to see here"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
font.weight: Font.Medium font.weight: Font.Medium
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
} }
} }

View File

@@ -63,13 +63,9 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -81,8 +77,14 @@ Item {
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: NotificationService.notifications.length > 0 visible: NotificationService.notifications.length > 0
color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) Theme.primary.b, 0.12) : Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(
Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
Row { Row {
@@ -103,7 +105,6 @@ Item {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -120,7 +121,6 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on border.color { Behavior on border.color {
@@ -128,9 +128,6 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }

View File

@@ -21,7 +21,6 @@ DankListView {
anchors.centerIn: parent anchors.centerIn: parent
} }
delegate: NotificationCard { delegate: NotificationCard {
notificationGroup: modelData notificationGroup: modelData
} }

View File

@@ -13,52 +13,53 @@ PanelWindow {
required property var notificationData required property var notificationData
required property string notificationId required property string notificationId
readonly property bool hasValidData: notificationData && notificationData.notification readonly property bool hasValidData: notificationData
&& notificationData.notification
property int screenY: 0 property int screenY: 0
property bool exiting: false property bool exiting: false
property bool _isDestroying: false property bool _isDestroying: false
property bool _finalized: false property bool _finalized: false
signal entered() signal entered
signal exitFinished() signal exitFinished
function startExit() { function startExit() {
if (exiting || _isDestroying) if (exiting || _isDestroying)
return ; return
exiting = true; exiting = true
exitAnim.restart(); exitAnim.restart()
exitWatchdog.restart(); exitWatchdog.restart()
if (NotificationService.removeFromVisibleNotifications) if (NotificationService.removeFromVisibleNotifications)
NotificationService.removeFromVisibleNotifications(win.notificationData); NotificationService.removeFromVisibleNotifications(win.notificationData)
} }
function forceExit() { function forceExit() {
if (_isDestroying) if (_isDestroying)
return ; return
_isDestroying = true; _isDestroying = true
exiting = true; exiting = true
visible = false; visible = false
exitWatchdog.stop(); exitWatchdog.stop()
finalizeExit("forced"); finalizeExit("forced")
} }
function finalizeExit(reason) { function finalizeExit(reason) {
if (_finalized) if (_finalized)
return ; return
_finalized = true; _finalized = true
_isDestroying = true; _isDestroying = true
exitWatchdog.stop(); exitWatchdog.stop()
wrapperConn.enabled = false; wrapperConn.enabled = false
wrapperConn.target = null; wrapperConn.target = null
win.exitFinished(); win.exitFinished()
} }
visible: hasValidData visible: hasValidData
WlrLayershell.layer: notificationData && notificationData.urgency === NotificationUrgency.Critical ? WlrLayershell.Overlay : WlrLayershell.Top WlrLayershell.layer: notificationData && notificationData.urgency
=== NotificationUrgency.Critical ? WlrLayershell.Overlay : WlrLayershell.Top
WlrLayershell.exclusiveZone: -1 WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent" color: "transparent"
@@ -68,36 +69,37 @@ PanelWindow {
onHasValidDataChanged: { onHasValidDataChanged: {
if (!hasValidData && !exiting && !_isDestroying) { if (!hasValidData && !exiting && !_isDestroying) {
forceExit(); forceExit()
} }
} }
Component.onCompleted: { Component.onCompleted: {
if (hasValidData) { if (hasValidData) {
Qt.callLater(() => { Qt.callLater(() => {
return enterX.restart(); return enterX.restart()
}); })
} else { } else {
forceExit(); forceExit()
} }
} }
onNotificationDataChanged: { onNotificationDataChanged: {
if (!_isDestroying) { if (!_isDestroying) {
wrapperConn.target = win.notificationData || null; wrapperConn.target = win.notificationData || null
notificationConn.target = (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null; notificationConn.target = (win.notificationData
&& win.notificationData.notification
&& win.notificationData.notification.Retainable)
|| null
} }
} }
onEntered: { onEntered: {
if (!_isDestroying) if (!_isDestroying)
enterDelay.start(); enterDelay.start()
} }
Component.onDestruction: { Component.onDestruction: {
_isDestroying = true; _isDestroying = true
exitWatchdog.stop(); exitWatchdog.stop()
if (notificationData && notificationData.timer) if (notificationData && notificationData.timer)
notificationData.timer.stop(); notificationData.timer.stop()
} }
anchors { anchors {
@@ -125,8 +127,16 @@ PanelWindow {
anchors.margins: 4 anchors.margins: 4
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Theme.popupBackground() color: Theme.popupBackground()
border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: notificationData && notificationData.urgency
border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 1 === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.3) : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.08)
border.width: notificationData
&& notificationData.urgency === NotificationUrgency.Critical ? 2 : 1
clip: true clip: true
Rectangle { Rectangle {
@@ -158,7 +168,8 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
color: "transparent" color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.12)
border.width: 1 border.width: 1
radius: parent.radius radius: parent.radius
z: -1 z: -1
@@ -167,7 +178,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: parent.radius radius: parent.radius
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical visible: notificationData
&& notificationData.urgency === NotificationUrgency.Critical
opacity: 1 opacity: 1
gradient: Gradient { gradient: Gradient {
@@ -187,9 +199,7 @@ PanelWindow {
position: 0.021 position: 0.021
color: "transparent" color: "transparent"
} }
} }
} }
Item { Item {
@@ -206,7 +216,9 @@ PanelWindow {
Rectangle { Rectangle {
id: iconContainer id: iconContainer
readonly property bool hasNotificationImage: notificationData && notificationData.image && notificationData.image !== "" readonly property bool hasNotificationImage: notificationData
&& notificationData.image
&& notificationData.image !== ""
width: 55 width: 55
height: 55 height: 55
@@ -225,35 +237,38 @@ PanelWindow {
asynchronous: true asynchronous: true
source: { source: {
if (!notificationData) if (!notificationData)
return ""; return ""
if (parent.hasNotificationImage) if (parent.hasNotificationImage)
return notificationData.cleanImage || ""; return notificationData.cleanImage || ""
if (notificationData.appIcon) { if (notificationData.appIcon) {
const appIcon = notificationData.appIcon; const appIcon = notificationData.appIcon
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://")) if (appIcon.startsWith("file://") || appIcon.startsWith(
return appIcon; "http://") || appIcon.startsWith("https://"))
return appIcon
return Quickshell.iconPath(appIcon, ""); return Quickshell.iconPath(appIcon, "")
} }
return ""; return ""
} }
visible: status === Image.Ready visible: status === Image.Ready
} }
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
visible: !parent.hasNotificationImage && (!notificationData || !notificationData.appIcon || notificationData.appIcon === "") visible: !parent.hasNotificationImage
&& (!notificationData || !notificationData.appIcon
|| notificationData.appIcon === "")
text: { text: {
const appName = notificationData && notificationData.appName ? notificationData.appName : "?"; const appName = notificationData
return appName.charAt(0).toUpperCase(); && notificationData.appName ? notificationData.appName : "?"
return appName.charAt(0).toUpperCase()
} }
font.pixelSize: 20 font.pixelSize: 20
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.primaryText color: Theme.primaryText
} }
} }
Rectangle { Rectangle {
@@ -282,14 +297,14 @@ PanelWindow {
width: parent.width width: parent.width
text: { text: {
if (!notificationData) if (!notificationData)
return ""; return ""
const appName = notificationData.appName || ""; const appName = notificationData.appName || ""
const timeStr = notificationData.timeStr || ""; const timeStr = notificationData.timeStr || ""
if (timeStr.length > 0) if (timeStr.length > 0)
return appName + " • " + timeStr; return appName + " • " + timeStr
else else
return appName; return appName
} }
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -319,8 +334,8 @@ PanelWindow {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
visible: text.length > 0 visible: text.length > 0
linkColor: Theme.primary linkColor: Theme.primary
onLinkActivated: (link) => { onLinkActivated: link => {
return Qt.openUrlExternally(link); return Qt.openUrlExternally(link)
} }
MouseArea { MouseArea {
@@ -328,15 +343,10 @@ PanelWindow {
acceptedButtons: Qt.NoButton acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
} }
} }
} }
} }
} }
} }
DankActionButton { DankActionButton {
@@ -352,8 +362,7 @@ PanelWindow {
z: 15 z: 15
onClicked: { onClicked: {
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
notificationData.popup = false; notificationData.popup = false
} }
} }
@@ -374,7 +383,8 @@ PanelWindow {
width: Math.max(actionText.implicitWidth + 12, 50) width: Math.max(actionText.implicitWidth + 12, 50)
height: 24 height: 24
radius: 4 radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent" color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
StyledText { StyledText {
id: actionText id: actionText
@@ -396,18 +406,14 @@ PanelWindow {
onExited: parent.isHovered = false onExited: parent.isHovered = false
onClicked: { onClicked: {
if (modelData && modelData.invoke) if (modelData && modelData.invoke)
modelData.invoke(); modelData.invoke()
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
notificationData.popup = false; notificationData.popup = false
} }
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -422,7 +428,8 @@ PanelWindow {
width: Math.max(clearText.implicitWidth + 12, 50) width: Math.max(clearText.implicitWidth + 12, 50)
height: 24 height: 24
radius: 4 radius: 4
color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : "transparent" color: isHovered ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.1) : "transparent"
z: 20 z: 20
StyledText { StyledText {
@@ -444,11 +451,9 @@ PanelWindow {
onExited: clearButton.isHovered = false onExited: clearButton.isHovered = false
onClicked: { onClicked: {
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
NotificationService.dismissNotification(notificationData); NotificationService.dismissNotification(notificationData)
} }
} }
} }
MouseArea { MouseArea {
@@ -461,21 +466,18 @@ PanelWindow {
z: -1 z: -1
onEntered: { onEntered: {
if (notificationData && notificationData.timer) if (notificationData && notificationData.timer)
notificationData.timer.stop(); notificationData.timer.stop()
} }
onExited: { onExited: {
if (notificationData && notificationData.popup && notificationData.timer) if (notificationData && notificationData.popup
notificationData.timer.restart(); && notificationData.timer)
notificationData.timer.restart()
} }
onClicked: { onClicked: {
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
notificationData.popup = false; notificationData.popup = false
} }
} }
} }
transform: Translate { transform: Translate {
@@ -483,7 +485,6 @@ PanelWindow {
x: Anims.slidePx x: Anims.slidePx
} }
} }
NumberAnimation { NumberAnimation {
@@ -498,7 +499,7 @@ PanelWindow {
easing.bezierCurve: Anims.emphasizedDecel easing.bezierCurve: Anims.emphasizedDecel
onStopped: { onStopped: {
if (!win.exiting && !win._isDestroying && Math.abs(tx.x) < 0.5) { if (!win.exiting && !win._isDestroying && Math.abs(tx.x) < 0.5) {
win.entered(); win.entered()
} }
} }
} }
@@ -537,7 +538,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedAccel easing.bezierCurve: Anims.emphasizedAccel
} }
} }
Connections { Connections {
@@ -545,11 +545,10 @@ PanelWindow {
function onPopupChanged() { function onPopupChanged() {
if (!win.notificationData || win._isDestroying) if (!win.notificationData || win._isDestroying)
return ; return
if (!win.notificationData.popup && !win.exiting) if (!win.notificationData.popup && !win.exiting)
startExit(); startExit()
} }
target: win.notificationData || null target: win.notificationData || null
@@ -562,11 +561,11 @@ PanelWindow {
function onDropped() { function onDropped() {
if (!win._isDestroying && !win.exiting) if (!win._isDestroying && !win.exiting)
forceExit(); forceExit()
} }
target: (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null target: (win.notificationData && win.notificationData.notification
&& win.notificationData.notification.Retainable) || null
ignoreUnknownSignals: true ignoreUnknownSignals: true
enabled: !win._isDestroying enabled: !win._isDestroying
} }
@@ -577,9 +576,9 @@ PanelWindow {
interval: 160 interval: 160
repeat: false repeat: false
onTriggered: { onTriggered: {
if (notificationData && notificationData.timer && !exiting && !_isDestroying) if (notificationData && notificationData.timer && !exiting
notificationData.timer.start(); && !_isDestroying)
notificationData.timer.start()
} }
} }
@@ -601,7 +600,5 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel easing.bezierCurve: Anims.standardDecel
} }
} }
} }

View File

@@ -19,14 +19,13 @@ QtObject {
onEntered: manager._onPopupEntered(this) onEntered: manager._onPopupEntered(this)
onExitFinished: manager._onPopupExitFinished(this) onExitFinished: manager._onPopupExitFinished(this)
} }
} }
property Connections notificationConnections property Connections notificationConnections
notificationConnections: Connections { notificationConnections: Connections {
function onVisibleNotificationsChanged() { function onVisibleNotificationsChanged() {
manager._sync(NotificationService.visibleNotifications); manager._sync(NotificationService.visibleNotifications)
} }
target: NotificationService target: NotificationService
@@ -39,21 +38,24 @@ QtObject {
running: false // Not running by default running: false // Not running by default
repeat: true repeat: true
onTriggered: { onTriggered: {
let toRemove = []; let toRemove = []
for (let p of popupWindows) { for (let p of popupWindows) {
if (!p) { if (!p) {
toRemove.push(p); toRemove.push(p)
continue; continue
} }
const isZombie = p.status === Component.Null || (!p.visible && !p.exiting) || (!p.notificationData && !p._isDestroying) || (!p.hasValidData && !p._isDestroying); const isZombie = p.status === Component.Null || (!p.visible
&& !p.exiting)
|| (!p.notificationData && !p._isDestroying)
|| (!p.hasValidData && !p._isDestroying)
if (isZombie) { if (isZombie) {
toRemove.push(p); toRemove.push(p)
if (p.forceExit) { if (p.forceExit) {
p.forceExit(); p.forceExit()
} else if (p.destroy) { } else if (p.destroy) {
try { try {
p.destroy(); p.destroy()
} catch (e) { } catch (e) {
} }
@@ -62,48 +64,49 @@ QtObject {
} }
if (toRemove.length > 0) { if (toRemove.length > 0) {
for (let zombie of toRemove) { for (let zombie of toRemove) {
const i = popupWindows.indexOf(zombie); const i = popupWindows.indexOf(zombie)
if (i !== -1) if (i !== -1)
popupWindows.splice(i, 1); popupWindows.splice(i, 1)
} }
popupWindows = popupWindows.slice(); popupWindows = popupWindows.slice()
const survivors = _active().sort((a, b) => { const survivors = _active().sort((a, b) => {
return a.screenY - b.screenY; return a.screenY - b.screenY
}); })
for (let k = 0; k < survivors.length; ++k) { for (var k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight; survivors[k].screenY = topMargin + k * baseNotificationHeight
} }
} }
if (popupWindows.length === 0) if (popupWindows.length === 0)
sweeper.stop(); sweeper.stop()
} }
} }
function _hasWindowFor(w) { function _hasWindowFor(w) {
return popupWindows.some((p) => { return popupWindows.some(p => {
return p && p.notificationData === w && !p._isDestroying && p.status !== Component.Null; return p && p.notificationData === w
}); && !p._isDestroying
&& p.status !== Component.Null
})
} }
function _isValidWindow(p) { function _isValidWindow(p) {
return p && p.status !== Component.Null && !p._isDestroying && p.hasValidData; return p && p.status !== Component.Null && !p._isDestroying
&& p.hasValidData
} }
function _sync(newWrappers) { function _sync(newWrappers) {
for (let w of newWrappers) { for (let w of newWrappers) {
if (w && !_hasWindowFor(w)) if (w && !_hasWindowFor(w))
insertNewestAtTop(w); insertNewestAtTop(w)
} }
for (let p of popupWindows.slice()) { for (let p of popupWindows.slice()) {
if (!_isValidWindow(p)) if (!_isValidWindow(p))
continue; continue
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1 && !p.exiting) { if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1
p.notificationData.removedByLimit = true; && !p.exiting) {
p.notificationData.popup = false; p.notificationData.removedByLimit = true
p.notificationData.popup = false
} }
} }
} }
@@ -111,135 +114,136 @@ QtObject {
function insertNewestAtTop(wrapper) { function insertNewestAtTop(wrapper) {
if (!wrapper) { if (!wrapper) {
return ; return
} }
for (let p of popupWindows) { for (let p of popupWindows) {
if (!_isValidWindow(p)) if (!_isValidWindow(p))
continue; continue
if (p.exiting) if (p.exiting)
continue; continue
p.screenY = p.screenY + baseNotificationHeight; p.screenY = p.screenY + baseNotificationHeight
} }
const notificationId = wrapper && wrapper.notification ? wrapper.notification.id : ""; const notificationId = wrapper
&& wrapper.notification ? wrapper.notification.id : ""
const win = popupComponent.createObject(null, { const win = popupComponent.createObject(null, {
"notificationData": wrapper, "notificationData": wrapper,
"notificationId": notificationId, "notificationId": notificationId,
"screenY": topMargin, "screenY": topMargin,
"screen": manager.modelData "screen": manager.modelData
}); })
if (!win) { if (!win) {
return ; return
} }
if (!win.hasValidData) { if (!win.hasValidData) {
win.destroy(); win.destroy()
return ; return
} }
popupWindows.push(win); popupWindows.push(win)
if (!sweeper.running) if (!sweeper.running)
sweeper.start(); sweeper.start()
_maybeStartOverflow(); _maybeStartOverflow()
} }
function _active() { function _active() {
return popupWindows.filter((p) => { return popupWindows.filter(p => {
return _isValidWindow(p) && p.notificationData && p.notificationData.popup && !p.exiting; return _isValidWindow(p) && p.notificationData
}); && p.notificationData.popup && !p.exiting
})
} }
function _bottom() { function _bottom() {
let b = null, maxY = -1; let b = null, maxY = -1
for (let p of _active()) { for (let p of _active()) {
if (p.screenY > maxY) { if (p.screenY > maxY) {
maxY = p.screenY; maxY = p.screenY
b = p; b = p
} }
} }
return b; return b
} }
function _maybeStartOverflow() { function _maybeStartOverflow() {
const activeWindows = _active(); const activeWindows = _active()
if (activeWindows.length <= maxTargetNotifications + 1) if (activeWindows.length <= maxTargetNotifications + 1)
return ; return
const b = _bottom(); const b = _bottom()
if (b && !b.exiting) { if (b && !b.exiting) {
b.notificationData.removedByLimit = true; b.notificationData.removedByLimit = true
b.notificationData.popup = false; b.notificationData.popup = false
} }
} }
function _onPopupEntered(p) { function _onPopupEntered(p) {
if (_isValidWindow(p)) if (_isValidWindow(p))
_maybeStartOverflow(); _maybeStartOverflow()
} }
function _onPopupExitFinished(p) { function _onPopupExitFinished(p) {
if (!p) if (!p)
return ; return
const windowId = p.toString(); const windowId = p.toString()
if (destroyingWindows.has(windowId)) if (destroyingWindows.has(windowId))
return ; return
destroyingWindows.add(windowId); destroyingWindows.add(windowId)
const i = popupWindows.indexOf(p); const i = popupWindows.indexOf(p)
if (i !== -1) { if (i !== -1) {
popupWindows.splice(i, 1); popupWindows.splice(i, 1)
popupWindows = popupWindows.slice(); popupWindows = popupWindows.slice()
} }
if (NotificationService.releaseWrapper && p.notificationData) if (NotificationService.releaseWrapper && p.notificationData)
NotificationService.releaseWrapper(p.notificationData); NotificationService.releaseWrapper(p.notificationData)
Qt.callLater(() => { Qt.callLater(() => {
if (p && p.destroy) { if (p && p.destroy) {
try { try {
p.destroy(); p.destroy()
} catch (e) { } catch (e) {
} }
} }
Qt.callLater(() => { Qt.callLater(() => {
destroyingWindows.delete(windowId); destroyingWindows.delete(windowId)
}); })
}); })
const survivors = _active().sort((a, b) => { const survivors = _active().sort((a, b) => {
return a.screenY - b.screenY; return a.screenY - b.screenY
}); })
for (let k = 0; k < survivors.length; ++k) { for (var k = 0; k < survivors.length; ++k) {
survivors[k].screenY = topMargin + k * baseNotificationHeight; survivors[k].screenY = topMargin + k * baseNotificationHeight
} }
_maybeStartOverflow(); _maybeStartOverflow()
} }
function cleanupAllWindows() { function cleanupAllWindows() {
sweeper.stop(); sweeper.stop()
for (let p of popupWindows.slice()) { for (let p of popupWindows.slice()) {
if (p) { if (p) {
try { try {
if (p.forceExit) if (p.forceExit)
p.forceExit(); p.forceExit()
else if (p.destroy) else if (p.destroy)
p.destroy(); p.destroy()
} catch (e) { } catch (e) {
} }
} }
} }
popupWindows = []; popupWindows = []
destroyingWindows.clear(); destroyingWindows.clear()
} }
onPopupWindowsChanged: { onPopupWindowsChanged: {
if (popupWindows.length > 0 && !sweeper.running) if (popupWindows.length > 0 && !sweeper.running)
sweeper.start(); sweeper.start()
else if (popupWindows.length === 0 && sweeper.running) else if (popupWindows.length === 0 && sweeper.running)
sweeper.stop(); sweeper.stop()
} }
} }

View File

@@ -7,39 +7,41 @@ import qs.Widgets
Column { Column {
function formatNetworkSpeed(bytesPerSec) { function formatNetworkSpeed(bytesPerSec) {
if (bytesPerSec < 1024) if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s"; return bytesPerSec.toFixed(0) + " B/s"
else if (bytesPerSec < 1024 * 1024) else if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s"; return (bytesPerSec / 1024).toFixed(1) + " KB/s"
else if (bytesPerSec < 1024 * 1024 * 1024) else if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"; return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
else else
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"; return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
} }
function formatDiskSpeed(bytesPerSec) { function formatDiskSpeed(bytesPerSec) {
if (bytesPerSec < 1024 * 1024) if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s"; return (bytesPerSec / 1024).toFixed(1) + " KB/s"
else if (bytesPerSec < 1024 * 1024 * 1024) else if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"; return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
else else
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"; return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
} }
anchors.fill: parent anchors.fill: parent
spacing: Theme.spacingM spacing: Theme.spacingM
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 200 height: 200
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1 border.width: 1
Column { Column {
@@ -64,7 +66,8 @@ Column {
width: 80 width: 80
height: 24 height: 24
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) color: Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b, 0.12)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
@@ -74,7 +77,6 @@ Column {
color: Theme.primary color: Theme.primary
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
Item { Item {
@@ -88,7 +90,6 @@ Column {
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
ScrollView { ScrollView {
@@ -122,7 +123,8 @@ Column {
width: parent.width - 80 width: parent.width - 80
height: 6 height: 6
radius: 3 radius: 3
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
Rectangle { Rectangle {
@@ -130,25 +132,22 @@ Column {
height: parent.height height: parent.height
radius: parent.radius radius: parent.radius
color: { color: {
const usage = modelData; const usage = modelData
if (usage > 80) if (usage > 80)
return Theme.error; return Theme.error
if (usage > 60) if (usage > 60)
return Theme.warning; return Theme.warning
return Theme.primary; return Theme.primary
} }
Behavior on width { Behavior on width {
NumberAnimation { NumberAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
StyledText { StyledText {
@@ -160,25 +159,21 @@ Column {
horizontalAlignment: Text.AlignRight horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
} }
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 80 height: 80
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1 border.width: 1
Row { Row {
@@ -198,11 +193,12 @@ Column {
} }
StyledText { StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB) + " / " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB) text: SysMonitorService.formatSystemMemory(
SysMonitorService.usedMemoryKB) + " / " + SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
} }
} }
Item { Item {
@@ -222,38 +218,41 @@ Column {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle { Rectangle {
width: SysMonitorService.totalMemoryKB > 0 ? parent.width * (SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) : 0 width: SysMonitorService.totalMemoryKB
> 0 ? parent.width * (SysMonitorService.usedMemoryKB
/ SysMonitorService.totalMemoryKB) : 0
height: parent.height height: parent.height
radius: parent.radius radius: parent.radius
color: { color: {
const usage = SysMonitorService.totalMemoryKB > 0 ? (SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) : 0; const usage = SysMonitorService.totalMemoryKB
> 0 ? (SysMonitorService.usedMemoryKB
/ SysMonitorService.totalMemoryKB) : 0
if (usage > 0.9) if (usage > 0.9)
return Theme.error; return Theme.error
if (usage > 0.7) if (usage > 0.7)
return Theme.warning; return Theme.warning
return Theme.secondary; return Theme.secondary
} }
Behavior on width { Behavior on width {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.mediumDuration
} }
} }
} }
} }
StyledText { StyledText {
text: SysMonitorService.totalMemoryKB > 0 ? ((SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) * 100).toFixed(1) + "% used" : "No data" text: SysMonitorService.totalMemoryKB
> 0 ? ((SysMonitorService.usedMemoryKB
/ SysMonitorService.totalMemoryKB) * 100).toFixed(
1) + "% used" : "No data"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
Item { Item {
@@ -273,11 +272,14 @@ Column {
} }
StyledText { StyledText {
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) + " / " + SysMonitorService.formatSystemMemory(SysMonitorService.totalSwapKB) : "No swap configured" text: SysMonitorService.totalSwapKB
> 0 ? SysMonitorService.formatSystemMemory(
SysMonitorService.usedSwapKB) + " / "
+ SysMonitorService.formatSystemMemory(
SysMonitorService.totalSwapKB) : "No swap configured"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
} }
} }
Item { Item {
@@ -297,45 +299,45 @@ Column {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle { Rectangle {
width: SysMonitorService.totalSwapKB > 0 ? parent.width * (SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB) : 0 width: SysMonitorService.totalSwapKB
> 0 ? parent.width * (SysMonitorService.usedSwapKB
/ SysMonitorService.totalSwapKB) : 0
height: parent.height height: parent.height
radius: parent.radius radius: parent.radius
color: { color: {
if (!SysMonitorService.totalSwapKB) if (!SysMonitorService.totalSwapKB)
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3); return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
const usage = SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB; const usage = SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB
if (usage > 0.9) if (usage > 0.9)
return Theme.error; return Theme.error
if (usage > 0.7) if (usage > 0.7)
return Theme.warning; return Theme.warning
return Theme.info; return Theme.info
} }
Behavior on width { Behavior on width {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.mediumDuration
} }
} }
} }
} }
StyledText { StyledText {
text: SysMonitorService.totalSwapKB > 0 ? ((SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB) * 100).toFixed(1) + "% used" : "Not available" text: SysMonitorService.totalSwapKB
> 0 ? ((SysMonitorService.usedSwapKB
/ SysMonitorService.totalSwapKB) * 100).toFixed(
1) + "% used" : "Not available"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
} }
} }
Row { Row {
@@ -347,8 +349,10 @@ Column {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 80 height: 80
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1 border.width: 1
Column { Column {
@@ -377,12 +381,13 @@ Column {
} }
StyledText { StyledText {
text: SysMonitorService.networkRxRate > 0 ? formatNetworkSpeed(SysMonitorService.networkRxRate) : "0 B/s" text: SysMonitorService.networkRxRate
> 0 ? formatNetworkSpeed(
SysMonitorService.networkRxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
Row { Row {
@@ -395,26 +400,26 @@ Column {
} }
StyledText { StyledText {
text: SysMonitorService.networkTxRate > 0 ? formatNetworkSpeed(SysMonitorService.networkTxRate) : "0 B/s" text: SysMonitorService.networkTxRate
> 0 ? formatNetworkSpeed(
SysMonitorService.networkTxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
} }
} }
} }
Rectangle { Rectangle {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 80 height: 80
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) Theme.surfaceVariant.b, 0.04)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.06)
border.width: 1 border.width: 1
Column { Column {
@@ -448,7 +453,6 @@ Column {
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
Row { Row {
@@ -466,15 +470,9 @@ Column {
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
} }
} }
} }
} }
} }

View File

@@ -12,24 +12,25 @@ Popup {
property var processData: null property var processData: null
function show(x, y) { function show(x, y) {
if (!processContextMenu.parent && typeof Overlay !== "undefined" && Overlay.overlay) if (!processContextMenu.parent && typeof Overlay !== "undefined"
processContextMenu.parent = Overlay.overlay; && Overlay.overlay)
processContextMenu.parent = Overlay.overlay
const menuWidth = 180; const menuWidth = 180
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2; const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
const screenWidth = Screen.width; const screenWidth = Screen.width
const screenHeight = Screen.height; const screenHeight = Screen.height
let finalX = x; let finalX = x
let finalY = y; let finalY = y
if (x + menuWidth > screenWidth - 20) if (x + menuWidth > screenWidth - 20)
finalX = x - menuWidth; finalX = x - menuWidth
if (y + menuHeight > screenHeight - 20) if (y + menuHeight > screenHeight - 20)
finalY = y - menuHeight; finalY = y - menuHeight
processContextMenu.x = Math.max(20, finalX); processContextMenu.x = Math.max(20, finalX)
processContextMenu.y = Math.max(20, finalY); processContextMenu.y = Math.max(20, finalY)
open(); open()
} }
width: 180 width: 180
@@ -38,10 +39,10 @@ Popup {
modal: false modal: false
closePolicy: Popup.CloseOnEscape closePolicy: Popup.CloseOnEscape
onClosed: { onClosed: {
closePolicy = Popup.CloseOnEscape; closePolicy = Popup.CloseOnEscape
} }
onOpened: { onOpened: {
outsideClickTimer.start(); outsideClickTimer.start()
} }
Timer { Timer {
@@ -49,7 +50,7 @@ Popup {
interval: 100 interval: 100
onTriggered: { onTriggered: {
processContextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside; processContextMenu.closePolicy = Popup.CloseOnEscape | Popup.CloseOnPressOutside
} }
} }
@@ -62,7 +63,8 @@ Popup {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
Column { Column {
@@ -76,7 +78,10 @@ Popup {
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: copyPidArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: copyPidArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText { StyledText {
anchors.left: parent.left anchors.left: parent.left
@@ -96,19 +101,22 @@ Popup {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (processContextMenu.processData) if (processContextMenu.processData)
Quickshell.execDetached(["wl-copy", processContextMenu.processData.pid.toString()]); Quickshell.execDetached(
["wl-copy", processContextMenu.processData.pid.toString()])
processContextMenu.close(); processContextMenu.close()
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: copyNameArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: copyNameArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
StyledText { StyledText {
anchors.left: parent.left anchors.left: parent.left
@@ -128,13 +136,13 @@ Popup {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (processContextMenu.processData) { if (processContextMenu.processData) {
let processName = processContextMenu.processData.displayName || processContextMenu.processData.command; let processName = processContextMenu.processData.displayName
Quickshell.execDetached(["wl-copy", processName]); || processContextMenu.processData.command
Quickshell.execDetached(["wl-copy", processName])
} }
processContextMenu.close(); processContextMenu.close()
} }
} }
} }
Rectangle { Rectangle {
@@ -149,14 +157,15 @@ Popup {
height: 1 height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: killArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent" color: killArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b,
0.12) : "transparent"
enabled: processContextMenu.processData enabled: processContextMenu.processData
opacity: enabled ? 1 : 0.5 opacity: enabled ? 1 : 0.5
@@ -166,7 +175,9 @@ Popup {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "Kill Process" text: "Kill Process"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: parent.enabled ? (killArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: parent.enabled ? (killArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(
Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Normal font.weight: Font.Normal
} }
@@ -179,20 +190,24 @@ Popup {
enabled: parent.enabled enabled: parent.enabled
onClicked: { onClicked: {
if (processContextMenu.processData) if (processContextMenu.processData)
Quickshell.execDetached(["kill", processContextMenu.processData.pid.toString()]); Quickshell.execDetached(
["kill", processContextMenu.processData.pid.toString()])
processContextMenu.close(); processContextMenu.close()
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: forceKillArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent" color: forceKillArea.containsMouse ? Qt.rgba(Theme.error.r,
enabled: processContextMenu.processData && processContextMenu.processData.pid > 1000 Theme.error.g,
Theme.error.b,
0.12) : "transparent"
enabled: processContextMenu.processData
&& processContextMenu.processData.pid > 1000
opacity: enabled ? 1 : 0.5 opacity: enabled ? 1 : 0.5
StyledText { StyledText {
@@ -201,7 +216,9 @@ Popup {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "Force Kill Process" text: "Force Kill Process"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: parent.enabled ? (forceKillArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: parent.enabled ? (forceKillArea.containsMouse ? Theme.error : Theme.surfaceText) : Qt.rgba(
Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.5)
font.weight: Font.Normal font.weight: Font.Normal
} }
@@ -214,16 +231,14 @@ Popup {
enabled: parent.enabled enabled: parent.enabled
onClicked: { onClicked: {
if (processContextMenu.processData) if (processContextMenu.processData)
Quickshell.execDetached(["kill", "-9", processContextMenu.processData.pid.toString()]); Quickshell.execDetached(
["kill", "-9", processContextMenu.processData.pid.toString(
)])
processContextMenu.close(); processContextMenu.close()
} }
} }
} }
} }
} }
} }

View File

@@ -12,8 +12,14 @@ Rectangle {
width: parent ? parent.width : 0 width: parent ? parent.width : 0
height: 40 height: 40
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
border.color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" Theme.primary.g,
Theme.primary.b,
0.08) : "transparent"
border.color: processMouseArea.containsMouse ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.12) : "transparent"
border.width: 1 border.width: 1
MouseArea { MouseArea {
@@ -23,21 +29,25 @@ Rectangle {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => { onClicked: mouse => {
if (mouse.button === Qt.RightButton) { if (mouse.button === Qt.RightButton) {
if (process && process.pid > 0 && contextMenu) { if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process; contextMenu.processData = process
let globalPos = processMouseArea.mapToGlobal(mouse.x, mouse.y); let globalPos = processMouseArea.mapToGlobal(mouse.x,
let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(globalPos.x, globalPos.y) : globalPos; mouse.y)
contextMenu.show(localPos.x, localPos.y); let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(
globalPos.x,
globalPos.y) : globalPos
contextMenu.show(localPos.x, localPos.y)
} }
} }
} }
onPressAndHold: { onPressAndHold: {
if (process && process.pid > 0 && contextMenu) { if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process; contextMenu.processData = process
let globalPos = processMouseArea.mapToGlobal(processMouseArea.width / 2, processMouseArea.height / 2); let globalPos = processMouseArea.mapToGlobal(
contextMenu.show(globalPos.x, globalPos.y); processMouseArea.width / 2, processMouseArea.height / 2)
contextMenu.show(globalPos.x, globalPos.y)
} }
} }
} }
@@ -53,12 +63,12 @@ Rectangle {
size: Theme.iconSize - 4 size: Theme.iconSize - 4
color: { color: {
if (process && process.cpu > 80) if (process && process.cpu > 80)
return Theme.error; return Theme.error
if (process && process.cpu > 50) if (process && process.cpu > 50)
return Theme.warning; return Theme.warning
return Theme.surfaceText; return Theme.surfaceText
} }
opacity: 0.8 opacity: 0.8
anchors.left: parent.left anchors.left: parent.left
@@ -86,12 +96,14 @@ Rectangle {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (process && process.cpu > 80) if (process && process.cpu > 80)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12); return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
if (process && process.cpu > 50) if (process && process.cpu > 50)
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12); return Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.12)
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08); return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.08)
} }
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 194 anchors.rightMargin: 194
@@ -104,16 +116,15 @@ Rectangle {
font.weight: Font.Bold font.weight: Font.Bold
color: { color: {
if (process && process.cpu > 80) if (process && process.cpu > 80)
return Theme.error; return Theme.error
if (process && process.cpu > 50) if (process && process.cpu > 50)
return Theme.warning; return Theme.warning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
Rectangle { Rectangle {
@@ -124,34 +135,36 @@ Rectangle {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (process && process.memoryKB > 1024 * 1024) if (process && process.memoryKB > 1024 * 1024)
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12); return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
if (process && process.memoryKB > 512 * 1024) if (process && process.memoryKB > 512 * 1024)
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12); return Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.12)
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08); return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.08)
} }
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 102 anchors.rightMargin: 102
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
text: SysMonitorService.formatMemoryUsage(process ? process.memoryKB : 0) text: SysMonitorService.formatMemoryUsage(
process ? process.memoryKB : 0)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
color: { color: {
if (process && process.memoryKB > 1024 * 1024) if (process && process.memoryKB > 1024 * 1024)
return Theme.error; return Theme.error
if (process && process.memoryKB > 512 * 1024) if (process && process.memoryKB > 512 * 1024)
return Theme.warning; return Theme.warning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
StyledText { StyledText {
@@ -173,7 +186,10 @@ Rectangle {
width: 28 width: 28
height: 28 height: 28
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: menuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: menuButtonArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -193,10 +209,13 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (process && process.pid > 0 && contextMenu) { if (process && process.pid > 0 && contextMenu) {
contextMenu.processData = process; contextMenu.processData = process
let globalPos = menuButtonArea.mapToGlobal(menuButtonArea.width / 2, menuButtonArea.height); let globalPos = menuButtonArea.mapToGlobal(
let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(globalPos.x, globalPos.y) : globalPos; menuButtonArea.width / 2, menuButtonArea.height)
contextMenu.show(localPos.x, localPos.y); let localPos = contextMenu.parent ? contextMenu.parent.mapFromGlobal(
globalPos.x,
globalPos.y) : globalPos
contextMenu.show(localPos.x, localPos.y)
} }
} }
} }
@@ -205,11 +224,7 @@ Rectangle {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
} }

View File

@@ -23,29 +23,28 @@ PanelWindow {
property var triggerScreen: null property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) { function setTriggerPosition(x, y, width, section, screen) {
triggerX = x; triggerX = x
triggerY = y; triggerY = y
triggerWidth = width; triggerWidth = width
triggerSection = section; triggerSection = section
triggerScreen = screen; triggerScreen = screen
} }
function hide() { function hide() {
isVisible = false; isVisible = false
if (processContextMenu.visible) if (processContextMenu.visible)
processContextMenu.close(); processContextMenu.close()
} }
function show() { function show() {
isVisible = true; isVisible = true
} }
function toggle() { function toggle() {
if (isVisible) if (isVisible)
hide(); hide()
else else
show(); show()
} }
visible: isVisible visible: isVisible
@@ -71,10 +70,10 @@ PanelWindow {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: function (mouse) { onClicked: function (mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y); var localPos = mapToItem(contentLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height) if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0
processListPopout.hide(); || localPos.y > contentLoader.height)
processListPopout.hide()
} }
} }
@@ -83,24 +82,29 @@ PanelWindow {
readonly property real screenWidth: processListPopout.screen ? processListPopout.screen.width : Screen.width readonly property real screenWidth: processListPopout.screen ? processListPopout.screen.width : Screen.width
readonly property real screenHeight: processListPopout.screen ? processListPopout.screen.height : Screen.height readonly property real screenHeight: processListPopout.screen ? processListPopout.screen.height : Screen.height
readonly property real targetWidth: Math.min(600, screenWidth - Theme.spacingL * 2) readonly property real targetWidth: Math.min(
readonly property real targetHeight: Math.min(600, screenHeight - Theme.barHeight - Theme.spacingS * 2) 600, screenWidth - Theme.spacingL * 2)
readonly property real targetHeight: Math.min(
600,
screenHeight - Theme.barHeight - Theme.spacingS * 2)
readonly property real calculatedX: { readonly property real calculatedX: {
var centerX = processListPopout.triggerX + (processListPopout.triggerWidth / 2) - (targetWidth / 2); var centerX = processListPopout.triggerX + (processListPopout.triggerWidth
/ 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) { if (centerX >= Theme.spacingM
return centerX; && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
} }
if (centerX < Theme.spacingM) { if (centerX < Theme.spacingM) {
return Theme.spacingM; return Theme.spacingM
} }
if (centerX + targetWidth > screenWidth - Theme.spacingM) { if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM; return screenWidth - targetWidth - Theme.spacingM
} }
return centerX; return centerX
} }
asynchronous: true asynchronous: true
@@ -118,7 +122,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
Behavior on scale { Behavior on scale {
@@ -127,7 +130,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
sourceComponent: Rectangle { sourceComponent: Rectangle {
@@ -135,7 +137,8 @@ PanelWindow {
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Theme.popupBackground() color: Theme.popupBackground()
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
clip: true clip: true
antialiasing: true antialiasing: true
@@ -143,12 +146,12 @@ PanelWindow {
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {
if (processListPopout.isVisible) if (processListPopout.isVisible)
forceActiveFocus(); forceActiveFocus()
} }
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
processListPopout.hide(); processListPopout.hide()
event.accepted = true; event.accepted = true
} }
} }
@@ -156,8 +159,8 @@ PanelWindow {
function onIsVisibleChanged() { function onIsVisibleChanged() {
if (processListPopout.isVisible) if (processListPopout.isVisible)
Qt.callLater(function () { Qt.callLater(function () {
dropdownContent.forceActiveFocus(); dropdownContent.forceActiveFocus()
}); })
} }
target: processListPopout target: processListPopout
} }
@@ -171,8 +174,10 @@ PanelWindow {
Layout.fillWidth: true Layout.fillWidth: true
height: systemOverview.height + Theme.spacingM * 2 height: systemOverview.height + Theme.spacingM * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
SystemOverview { SystemOverview {
@@ -181,15 +186,16 @@ PanelWindow {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width - Theme.spacingM * 2 width: parent.width - Theme.spacingM * 2
} }
} }
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.05)
border.width: 1 border.width: 1
ProcessListView { ProcessListView {
@@ -197,17 +203,12 @@ PanelWindow {
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
contextMenu: processContextMenu contextMenu: processContextMenu
} }
} }
} }
} }
} }
ProcessContextMenu { ProcessContextMenu {
id: processContextMenu id: processContextMenu
} }
} }

View File

@@ -10,10 +10,10 @@ Column {
property var contextMenu: null property var contextMenu: null
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
Item { Item {
@@ -26,7 +26,10 @@ Column {
Rectangle { Rectangle {
width: 60 width: 60
height: 20 height: 20
color: processHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: processHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 0 anchors.leftMargin: 0
@@ -49,7 +52,7 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
SysMonitorService.setSortBy("name"); SysMonitorService.setSortBy("name")
} }
} }
@@ -57,15 +60,16 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
Rectangle { Rectangle {
width: 80 width: 80
height: 20 height: 20
color: cpuHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: cpuHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 200 anchors.rightMargin: 200
@@ -88,7 +92,7 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
SysMonitorService.setSortBy("cpu"); SysMonitorService.setSortBy("cpu")
} }
} }
@@ -96,15 +100,16 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
Rectangle { Rectangle {
width: 80 width: 80
height: 20 height: 20
color: memoryHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: memoryHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 112 anchors.rightMargin: 112
@@ -127,7 +132,7 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
SysMonitorService.setSortBy("memory"); SysMonitorService.setSortBy("memory")
} }
} }
@@ -135,15 +140,16 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
Rectangle { Rectangle {
width: 50 width: 50
height: 20 height: 20
color: pidHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: pidHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 53 anchors.rightMargin: 53
@@ -167,7 +173,7 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
SysMonitorService.setSortBy("pid"); SysMonitorService.setSortBy("pid")
} }
} }
@@ -175,16 +181,17 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
Rectangle { Rectangle {
width: 28 width: 28
height: 28 height: 28
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: sortOrderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent" color: sortOrderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.08) : "transparent"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 8 anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -203,7 +210,7 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
SysMonitorService.toggleSortOrder(); SysMonitorService.toggleSortOrder()
} }
} }
@@ -211,11 +218,8 @@ Column {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
} }
DankListView { DankListView {
@@ -234,5 +238,4 @@ Column {
contextMenu: root.contextMenu contextMenu: root.contextMenu
} }
} }
} }

View File

@@ -25,5 +25,4 @@ ColumnLayout {
ProcessContextMenu { ProcessContextMenu {
id: localContextMenu id: localContextMenu
} }
} }

View File

@@ -7,10 +7,10 @@ Row {
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
Rectangle { Rectangle {
@@ -19,13 +19,19 @@ Row {
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: { color: {
if (SysMonitorService.sortBy === "cpu") if (SysMonitorService.sortBy === "cpu")
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16); return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16)
else if (cpuCardMouseArea.containsMouse) else if (cpuCardMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12); return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
else else
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08); return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
} }
border.color: SysMonitorService.sortBy === "cpu" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) border.color: SysMonitorService.sortBy === "cpu" ? Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.4) : Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b, 0.2)
border.width: SysMonitorService.sortBy === "cpu" ? 2 : 1 border.width: SysMonitorService.sortBy === "cpu" ? 2 : 1
MouseArea { MouseArea {
@@ -66,26 +72,29 @@ Row {
Rectangle { Rectangle {
width: 1 width: 1
height: 20 height: 20
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: { text: {
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) { if (SysMonitorService.cpuTemperature === undefined
return "--°"; || SysMonitorService.cpuTemperature === null
|| SysMonitorService.cpuTemperature < 0) {
return "--°"
} }
return Math.round(SysMonitorService.cpuTemperature) + "°"; return Math.round(SysMonitorService.cpuTemperature) + "°"
} }
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Medium font.weight: Font.Medium
color: { color: {
if (SysMonitorService.cpuTemperature > 80) if (SysMonitorService.cpuTemperature > 80)
return Theme.error; return Theme.error
if (SysMonitorService.cpuTemperature > 60) if (SysMonitorService.cpuTemperature > 60)
return Theme.warning; return Theme.warning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -98,23 +107,19 @@ Row {
color: Theme.surfaceText color: Theme.surfaceText
opacity: 0.7 opacity: 0.7
} }
} }
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
Behavior on border.color { Behavior on border.color {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
Rectangle { Rectangle {
@@ -123,13 +128,23 @@ Row {
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: { color: {
if (SysMonitorService.sortBy === "memory") if (SysMonitorService.sortBy === "memory")
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16); return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16)
else if (memoryCardMouseArea.containsMouse) else if (memoryCardMouseArea.containsMouse)
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.12); return Qt.rgba(Theme.secondary.r, Theme.secondary.g,
Theme.secondary.b, 0.12)
else else
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08); return Qt.rgba(Theme.secondary.r, Theme.secondary.g,
Theme.secondary.b, 0.08)
} }
border.color: SysMonitorService.sortBy === "memory" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.2) border.color: SysMonitorService.sortBy === "memory" ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.4) : Qt.rgba(
Theme.secondary.r,
Theme.secondary.g,
Theme.secondary.b,
0.2)
border.width: SysMonitorService.sortBy === "memory" ? 2 : 1 border.width: SysMonitorService.sortBy === "memory" ? 2 : 1
MouseArea { MouseArea {
@@ -159,7 +174,8 @@ Row {
spacing: Theme.spacingS spacing: Theme.spacingS
StyledText { StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB) text: SysMonitorService.formatSystemMemory(
SysMonitorService.usedMemoryKB)
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
@@ -170,13 +186,15 @@ Row {
Rectangle { Rectangle {
width: 1 width: 1
height: 20 height: 20
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.3)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: SysMonitorService.totalSwapKB > 0 visible: SysMonitorService.totalSwapKB > 0
} }
StyledText { StyledText {
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) : "" text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(
SysMonitorService.usedSwapKB) : ""
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Medium font.weight: Font.Medium
@@ -189,40 +207,40 @@ Row {
StyledText { StyledText {
text: { text: {
if (SysMonitorService.totalSwapKB > 0) { if (SysMonitorService.totalSwapKB > 0) {
return "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB) + " + swap"; return "of " + SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB) + " + swap"
} }
return "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB); return "of " + SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB)
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Theme.surfaceText color: Theme.surfaceText
opacity: 0.7 opacity: 0.7
} }
} }
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
Behavior on border.color { Behavior on border.color {
ColorAnimation { ColorAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
} }
} }
} }
Rectangle { Rectangle {
width: (parent.width - Theme.spacingM * 2) / 3 width: (parent.width - Theme.spacingM * 2) / 3
height: 80 height: 80
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) Theme.surfaceVariant.b, 0.08)
border.color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -241,73 +259,79 @@ Row {
StyledText { StyledText {
text: { text: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) { if (!SysMonitorService.availableGpus
return "None"; || SysMonitorService.availableGpus.length === 0) {
return "None"
} }
if (SysMonitorService.availableGpus.length === 1) { if (SysMonitorService.availableGpus.length === 1) {
var gpu = SysMonitorService.availableGpus[0]; var gpu = SysMonitorService.availableGpus[0]
var temp = gpu.temperature; var temp = gpu.temperature
var tempText = (temp === undefined || temp === null || temp === 0) ? "--°" : Math.round(temp) + "°"; var tempText = (temp === undefined || temp === null
return tempText; || temp === 0) ? "--°" : Math.round(temp) + "°"
return tempText
} }
// Multiple GPUs - show average temp // Multiple GPUs - show average temp
var totalTemp = 0; var totalTemp = 0
var validTemps = 0; var validTemps = 0
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) { for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
var temp = SysMonitorService.availableGpus[i].temperature; var temp = SysMonitorService.availableGpus[i].temperature
if (temp !== undefined && temp !== null && temp > 0) { if (temp !== undefined && temp !== null && temp > 0) {
totalTemp += temp; totalTemp += temp
validTemps++; validTemps++
} }
} }
if (validTemps > 0) { if (validTemps > 0) {
return Math.round(totalTemp / validTemps) + "°"; return Math.round(totalTemp / validTemps) + "°"
} }
return "--°"; return "--°"
} }
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Bold font.weight: Font.Bold
color: { color: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) { if (!SysMonitorService.availableGpus
return Theme.surfaceText; || SysMonitorService.availableGpus.length === 0) {
return Theme.surfaceText
} }
if (SysMonitorService.availableGpus.length === 1) { if (SysMonitorService.availableGpus.length === 1) {
var temp = SysMonitorService.availableGpus[0].temperature || 0; var temp = SysMonitorService.availableGpus[0].temperature || 0
if (temp > 80) return Theme.tempDanger; if (temp > 80)
if (temp > 60) return Theme.tempWarning; return Theme.tempDanger
return Theme.surfaceText; if (temp > 60)
return Theme.tempWarning
return Theme.surfaceText
} }
// Multiple GPUs - get max temp for coloring // Multiple GPUs - get max temp for coloring
var maxTemp = 0; var maxTemp = 0
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) { for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
var temp = SysMonitorService.availableGpus[i].temperature || 0; var temp = SysMonitorService.availableGpus[i].temperature || 0
if (temp > maxTemp) maxTemp = temp; if (temp > maxTemp)
maxTemp = temp
} }
if (maxTemp > 80) return Theme.tempDanger; if (maxTemp > 80)
if (maxTemp > 60) return Theme.tempWarning; return Theme.tempDanger
return Theme.surfaceText; if (maxTemp > 60)
return Theme.tempWarning
return Theme.surfaceText
} }
} }
StyledText { StyledText {
text: { text: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) { if (!SysMonitorService.availableGpus
return "No GPUs detected"; || SysMonitorService.availableGpus.length === 0) {
return "No GPUs detected"
} }
if (SysMonitorService.availableGpus.length === 1) { if (SysMonitorService.availableGpus.length === 1) {
return SysMonitorService.availableGpus[0].driver.toUpperCase(); return SysMonitorService.availableGpus[0].driver.toUpperCase()
} }
return SysMonitorService.availableGpus.length + " GPUs detected"; return SysMonitorService.availableGpus.length + " GPUs detected"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Theme.surfaceText color: Theme.surfaceText
opacity: 0.7 opacity: 0.7
} }
} }
} }
} }

View File

@@ -10,10 +10,10 @@ ScrollView {
ScrollBar.vertical.policy: ScrollBar.AsNeeded ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
Column { Column {
@@ -24,7 +24,8 @@ ScrollView {
width: parent.width width: parent.width
height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.6)
border.width: 0 border.width: 0
Column { Column {
@@ -60,10 +61,12 @@ ScrollView {
} }
StyledText { StyledText {
text: SysMonitorService.distribution + " • " + SysMonitorService.architecture + " • " + SysMonitorService.kernelVersion text: SysMonitorService.distribution + " • " + SysMonitorService.architecture
+ " • " + SysMonitorService.kernelVersion
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
@@ -71,20 +74,22 @@ ScrollView {
text: "Up " + UserInfoService.uptime + " • Boot: " + SysMonitorService.bootTime text: "Up " + UserInfoService.uptime + " • Boot: " + SysMonitorService.bootTime
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
StyledText { StyledText {
text: "Load: " + SysMonitorService.loadAverage + " • " + SysMonitorService.processCount + " processes, " + SysMonitorService.threadCount + " threads" text: "Load: " + SysMonitorService.loadAverage + " • "
+ SysMonitorService.processCount + " processes, "
+ SysMonitorService.threadCount + " threads"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
} }
} }
Rectangle { Rectangle {
@@ -99,11 +104,15 @@ ScrollView {
Rectangle { Rectangle {
width: (parent.width - Theme.spacingXL) / 2 width: (parent.width - Theme.spacingXL) / 2
height: Math.max(hardwareColumn.implicitHeight, memoryColumn.implicitHeight) + Theme.spacingM height: Math.max(hardwareColumn.implicitHeight,
memoryColumn.implicitHeight) + Theme.spacingM
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, 0.4) color: Qt.rgba(Theme.surfaceContainerHigh.r,
Theme.surfaceContainerHigh.g,
Theme.surfaceContainerHigh.b, 0.4)
border.width: 1 border.width: 1
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
Column { Column {
id: hardwareColumn id: hardwareColumn
@@ -133,7 +142,6 @@ ScrollView {
color: Theme.primary color: Theme.primary
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
StyledText { StyledText {
@@ -153,7 +161,8 @@ ScrollView {
text: SysMonitorService.motherboard text: SysMonitorService.motherboard
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.8)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
@@ -165,23 +174,26 @@ ScrollView {
text: "BIOS " + SysMonitorService.biosVersion text: "BIOS " + SysMonitorService.biosVersion
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
} }
} }
Rectangle { Rectangle {
width: (parent.width - Theme.spacingXL) / 2 width: (parent.width - Theme.spacingXL) / 2
height: Math.max(hardwareColumn.implicitHeight, memoryColumn.implicitHeight) + Theme.spacingM height: Math.max(hardwareColumn.implicitHeight,
memoryColumn.implicitHeight) + Theme.spacingM
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, 0.4) color: Qt.rgba(Theme.surfaceContainerHigh.r,
Theme.surfaceContainerHigh.g,
Theme.surfaceContainerHigh.b, 0.4)
border.width: 1 border.width: 1
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
Column { Column {
id: memoryColumn id: memoryColumn
@@ -211,11 +223,11 @@ ScrollView {
color: Theme.secondary color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
StyledText { StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB) + " Total" text: SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB) + " Total"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
font.weight: Font.Medium font.weight: Font.Medium
@@ -226,10 +238,15 @@ ScrollView {
} }
StyledText { StyledText {
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB) + " Used • " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB - SysMonitorService.usedMemoryKB) + " Available" text: SysMonitorService.formatSystemMemory(
SysMonitorService.usedMemoryKB) + " Used • "
+ SysMonitorService.formatSystemMemory(
SysMonitorService.totalMemoryKB
- SysMonitorService.usedMemoryKB) + " Available"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g,
Theme.surfaceText.b, 0.7)
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@@ -239,22 +256,18 @@ ScrollView {
width: parent.width width: parent.width
height: Theme.fontSizeSmall + Theme.spacingXS height: Theme.fontSizeSmall + Theme.spacingXS
} }
} }
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: storageColumn.implicitHeight + 2 * Theme.spacingL height: storageColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.6)
border.width: 0 border.width: 0
Column { Column {
@@ -285,7 +298,6 @@ ScrollView {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Column { Column {
@@ -362,7 +374,6 @@ ScrollView {
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
} }
Repeater { Repeater {
@@ -374,7 +385,10 @@ ScrollView {
width: parent.width width: parent.width
height: 24 height: 24
radius: Theme.cornerRadiusSmall radius: Theme.cornerRadiusSmall
color: diskMouseArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04) : "transparent" color: diskMouseArea.containsMouse ? Qt.rgba(Theme.surfaceText.r,
Theme.surfaceText.g,
Theme.surfaceText.b,
0.04) : "transparent"
MouseArea { MouseArea {
id: diskMouseArea id: diskMouseArea
@@ -447,33 +461,25 @@ ScrollView {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily font.family: SettingsData.monoFontFamily
color: { color: {
const percent = parseInt(modelData.percent); const percent = parseInt(modelData.percent)
if (percent > 90) if (percent > 90)
return Theme.error; return Theme.error
if (percent > 75) if (percent > 75)
return Theme.warning; return Theme.warning
return Theme.surfaceText; return Theme.surfaceText
} }
width: parent.width * 0.1 width: parent.width * 0.1
elide: Text.ElideRight elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -51,8 +51,10 @@ Item {
width: parent.width width: parent.width
height: displaySection.implicitHeight + Theme.spacingL * 2 height: displaySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -80,7 +82,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
DankToggle { DankToggle {
@@ -88,12 +89,12 @@ Item {
text: "Night Mode" text: "Night Mode"
description: "Apply warm color temperature to reduce eye strain" description: "Apply warm color temperature to reduce eye strain"
checked: SettingsData.nightModeEnabled checked: SettingsData.nightModeEnabled
onToggled: (checked) => { onToggled: checked => {
SettingsData.setNightModeEnabled(checked); SettingsData.setNightModeEnabled(checked)
if (checked) if (checked)
nightModeEnableProcess.running = true; nightModeEnableProcess.running = true
else else
nightModeDisableProcess.running = true; nightModeDisableProcess.running = true
} }
} }
@@ -102,10 +103,10 @@ Item {
text: "Light Mode" text: "Light Mode"
description: "Use light theme instead of dark theme" description: "Use light theme instead of dark theme"
checked: SessionData.isLightMode checked: SessionData.isLightMode
onToggled: (checked) => { onToggled: checked => {
SessionData.setLightMode(checked); SessionData.setLightMode(checked)
Theme.isLightMode = checked; Theme.isLightMode = checked
PortalService.setLightMode(checked); PortalService.setLightMode(checked)
} }
} }
@@ -118,14 +119,16 @@ Item {
popupWidthOffset: 100 popupWidthOffset: 100
maxPopupHeight: 400 maxPopupHeight: 400
options: { options: {
SettingsData.detectAvailableIconThemes(); SettingsData.detectAvailableIconThemes()
return SettingsData.availableIconThemes; return SettingsData.availableIconThemes
} }
onValueChanged: (value) => { onValueChanged: value => {
SettingsData.setIconTheme(value); SettingsData.setIconTheme(value)
if (value !== "System Default" && !SettingsData.qt5ctAvailable && !SettingsData.qt6ctAvailable) if (value !== "System Default"
ToastService.showWarning("qt5ct or qt6ct not found - Qt app themes may not update without these tools"); && !SettingsData.qt5ctAvailable
&& !SettingsData.qt6ctAvailable)
ToastService.showWarning(
"qt5ct or qt6ct not found - Qt app themes may not update without these tools")
} }
} }
@@ -135,41 +138,48 @@ Item {
description: "Select system font family" description: "Select system font family"
currentValue: { currentValue: {
if (SettingsData.fontFamily === SettingsData.defaultFontFamily) if (SettingsData.fontFamily === SettingsData.defaultFontFamily)
return "Default (" + SettingsData.defaultFontFamily + ")"; return "Default (" + SettingsData.defaultFontFamily + ")"
else else
return SettingsData.fontFamily || "Default (" + SettingsData.defaultFontFamily + ")"; return SettingsData.fontFamily
|| "Default (" + SettingsData.defaultFontFamily + ")"
} }
enableFuzzySearch: true enableFuzzySearch: true
popupWidthOffset: 100 popupWidthOffset: 100
maxPopupHeight: 400 maxPopupHeight: 400
options: { options: {
var fonts = ["Default (" + SettingsData.defaultFontFamily + ")"]; var fonts = ["Default (" + SettingsData.defaultFontFamily + ")"]
var availableFonts = Qt.fontFamilies(); var availableFonts = Qt.fontFamilies()
var rootFamilies = []; var rootFamilies = []
var seenFamilies = new Set(); var seenFamilies = new Set()
for (var i = 0; i < availableFonts.length; i++) { for (var i = 0; i < availableFonts.length; i++) {
var fontName = availableFonts[i]; var fontName = availableFonts[i]
if (fontName.startsWith(".")) if (fontName.startsWith("."))
continue; continue
if (fontName === SettingsData.defaultFontFamily) 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) { var rootName = fontName.replace(
return match; / (Thin|Extra Light|Light|Regular|Medium|Semi Bold|Demi Bold|Bold|Extra Bold|Black|Heavy)$/i,
}).trim(); "").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 !== "") { if (!seenFamilies.has(rootName) && rootName !== "") {
seenFamilies.add(rootName); seenFamilies.add(rootName)
rootFamilies.push(rootName); rootFamilies.push(rootName)
} }
} }
return fonts.concat(rootFamilies.sort()); return fonts.concat(rootFamilies.sort())
} }
onValueChanged: (value) => { onValueChanged: value => {
if (value.startsWith("Default (")) if (value.startsWith("Default ("))
SettingsData.setFontFamily(SettingsData.defaultFontFamily); SettingsData.setFontFamily(
SettingsData.defaultFontFamily)
else else
SettingsData.setFontFamily(value); SettingsData.setFontFamily(value)
} }
} }
@@ -180,63 +190,63 @@ Item {
currentValue: { currentValue: {
switch (SettingsData.fontWeight) { switch (SettingsData.fontWeight) {
case Font.Thin: case Font.Thin:
return "Thin"; return "Thin"
case Font.ExtraLight: case Font.ExtraLight:
return "Extra Light"; return "Extra Light"
case Font.Light: case Font.Light:
return "Light"; return "Light"
case Font.Normal: case Font.Normal:
return "Regular"; return "Regular"
case Font.Medium: case Font.Medium:
return "Medium"; return "Medium"
case Font.DemiBold: case Font.DemiBold:
return "Demi Bold"; return "Demi Bold"
case Font.Bold: case Font.Bold:
return "Bold"; return "Bold"
case Font.ExtraBold: case Font.ExtraBold:
return "Extra Bold"; return "Extra Bold"
case Font.Black: case Font.Black:
return "Black"; return "Black"
default: default:
return "Regular"; return "Regular"
} }
} }
options: ["Thin", "Extra Light", "Light", "Regular", "Medium", "Demi Bold", "Bold", "Extra Bold", "Black"] options: ["Thin", "Extra Light", "Light", "Regular", "Medium", "Demi Bold", "Bold", "Extra Bold", "Black"]
onValueChanged: (value) => { onValueChanged: value => {
var weight; var weight
switch (value) { switch (value) {
case "Thin": case "Thin":
weight = Font.Thin; weight = Font.Thin
break; break
case "Extra Light": case "Extra Light":
weight = Font.ExtraLight; weight = Font.ExtraLight
break; break
case "Light": case "Light":
weight = Font.Light; weight = Font.Light
break; break
case "Regular": case "Regular":
weight = Font.Normal; weight = Font.Normal
break; break
case "Medium": case "Medium":
weight = Font.Medium; weight = Font.Medium
break; break
case "Demi Bold": case "Demi Bold":
weight = Font.DemiBold; weight = Font.DemiBold
break; break
case "Bold": case "Bold":
weight = Font.Bold; weight = Font.Bold
break; break
case "Extra Bold": case "Extra Bold":
weight = Font.ExtraBold; weight = Font.ExtraBold
break; break
case "Black": case "Black":
weight = Font.Black; weight = Font.Black
break; break
default: default:
weight = Font.Normal; weight = Font.Normal
break; break
} }
SettingsData.setFontWeight(weight); SettingsData.setFontWeight(weight)
} }
} }
@@ -246,45 +256,58 @@ Item {
description: "Select monospace font for process list and technical displays" description: "Select monospace font for process list and technical displays"
currentValue: { currentValue: {
if (SettingsData.monoFontFamily === SettingsData.defaultMonoFontFamily) if (SettingsData.monoFontFamily === SettingsData.defaultMonoFontFamily)
return "Default"; return "Default"
return SettingsData.monoFontFamily || "Default"; return SettingsData.monoFontFamily || "Default"
} }
enableFuzzySearch: true enableFuzzySearch: true
popupWidthOffset: 100 popupWidthOffset: 100
maxPopupHeight: 400 maxPopupHeight: 400
options: { options: {
var fonts = ["Default"]; var fonts = ["Default"]
var availableFonts = Qt.fontFamilies(); var availableFonts = Qt.fontFamilies()
var monoFamilies = []; var monoFamilies = []
var seenFamilies = new Set(); var seenFamilies = new Set()
for (var i = 0; i < availableFonts.length; i++) { for (var i = 0; i < availableFonts.length; i++) {
var fontName = availableFonts[i]; var fontName = availableFonts[i]
if (fontName.startsWith(".")) if (fontName.startsWith("."))
continue; continue
if (fontName === SettingsData.defaultMonoFontFamily) if (fontName === SettingsData.defaultMonoFontFamily)
continue; continue
var lowerName = fontName.toLowerCase(); var lowerName = fontName.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")) { if (lowerName.includes("mono") || lowerName.includes(
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, "").trim(); "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 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,
"").trim()
if (!seenFamilies.has(rootName) && rootName !== "") { if (!seenFamilies.has(rootName) && rootName !== "") {
seenFamilies.add(rootName); seenFamilies.add(rootName)
monoFamilies.push(rootName); monoFamilies.push(rootName)
} }
} }
} }
return fonts.concat(monoFamilies.sort()); return fonts.concat(monoFamilies.sort())
} }
onValueChanged: (value) => { onValueChanged: value => {
if (value === "Default") if (value === "Default")
SettingsData.setMonoFontFamily(SettingsData.defaultMonoFontFamily); SettingsData.setMonoFontFamily(
SettingsData.defaultMonoFontFamily)
else else
SettingsData.setMonoFontFamily(value); SettingsData.setMonoFontFamily(value)
} }
} }
} }
} }
} }
@@ -297,8 +320,10 @@ Item {
width: parent.width width: parent.width
height: transparencySection.implicitHeight + Theme.spacingL * 2 height: transparencySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -326,7 +351,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Column { Column {
@@ -348,11 +372,11 @@ Item {
maximum: 100 maximum: 100
unit: "" unit: ""
showValue: true showValue: true
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
SettingsData.setTopBarTransparency(newValue / 100); SettingsData.setTopBarTransparency(
newValue / 100)
} }
} }
} }
Column { Column {
@@ -374,11 +398,11 @@ Item {
maximum: 100 maximum: 100
unit: "" unit: ""
showValue: true showValue: true
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
SettingsData.setTopBarWidgetTransparency(newValue / 100); SettingsData.setTopBarWidgetTransparency(
newValue / 100)
} }
} }
} }
Column { Column {
@@ -400,13 +424,12 @@ Item {
maximum: 100 maximum: 100
unit: "" unit: ""
showValue: true showValue: true
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
SettingsData.setPopupTransparency(newValue / 100); SettingsData.setPopupTransparency(
newValue / 100)
} }
} }
} }
} }
} }
} }
@@ -419,8 +442,10 @@ Item {
width: parent.width width: parent.width
height: themeSection.implicitHeight + Theme.spacingL * 2 height: themeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -448,7 +473,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Column { Column {
@@ -466,10 +490,10 @@ Item {
StyledText { StyledText {
text: { text: {
if (Theme.isDynamicTheme) if (Theme.isDynamicTheme)
return "Wallpaper-based dynamic colors"; return "Wallpaper-based dynamic colors"
var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"]; var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"]
return descriptions[Theme.currentThemeIndex] || "Select a theme"; return descriptions[Theme.currentThemeIndex] || "Select a theme"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
@@ -478,7 +502,6 @@ Item {
width: Math.min(parent.width, 400) width: Math.min(parent.width, 400)
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
} }
Column { Column {
@@ -498,8 +521,10 @@ Item {
radius: 16 radius: 16
color: Theme.themes[index].primary color: Theme.themes[index].primary
border.color: Theme.outline border.color: Theme.outline
border.width: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 2 : 1 border.width: (Theme.currentThemeIndex === index
scale: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 1.1 : 1 && !Theme.isDynamicTheme) ? 2 : 1
scale: (Theme.currentThemeIndex === index
&& !Theme.isDynamicTheme) ? 1.1 : 1
Rectangle { Rectangle {
width: nameText.contentWidth + Theme.spacingS * 2 width: nameText.contentWidth + Theme.spacingS * 2
@@ -521,7 +546,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
MouseArea { MouseArea {
@@ -531,7 +555,7 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
Theme.switchTheme(index, false); Theme.switchTheme(index, false)
} }
} }
@@ -540,7 +564,6 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on border.width { Behavior on border.width {
@@ -548,13 +571,9 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
} }
} }
Row { Row {
@@ -570,7 +589,8 @@ Item {
width: 32 width: 32
height: 32 height: 32
radius: 16 radius: 16
color: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].primary : "transparent" color: themeIndex
< Theme.themes.length ? Theme.themes[themeIndex].primary : "transparent"
border.color: Theme.outline border.color: Theme.outline
border.width: Theme.currentThemeIndex === themeIndex ? 2 : 1 border.width: Theme.currentThemeIndex === themeIndex ? 2 : 1
visible: themeIndex < Theme.themes.length visible: themeIndex < Theme.themes.length
@@ -586,7 +606,8 @@ Item {
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS anchors.bottomMargin: Theme.spacingXS
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: mouseArea2.containsMouse && themeIndex < Theme.themes.length visible: mouseArea2.containsMouse
&& themeIndex < Theme.themes.length
StyledText { StyledText {
id: nameText2 id: nameText2
@@ -596,7 +617,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
MouseArea { MouseArea {
@@ -607,8 +627,7 @@ Item {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (themeIndex < Theme.themes.length) if (themeIndex < Theme.themes.length)
Theme.switchTheme(themeIndex); Theme.switchTheme(themeIndex)
} }
} }
@@ -617,7 +636,6 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on border.width { Behavior on border.width {
@@ -625,13 +643,9 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
} }
} }
Item { Item {
@@ -645,18 +659,22 @@ Item {
radius: 20 radius: 20
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
color: { color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "error"
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12); || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.12)
else else
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3); return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
} }
border.color: { border.color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "error"
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.5); || ToastService.wallpaperErrorStatus === "matugen_missing")
return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.5)
else if (Theme.isDynamicTheme) else if (Theme.isDynamicTheme)
return Theme.primary; return Theme.primary
else else
return Theme.outline; return Theme.outline
} }
border.width: Theme.isDynamicTheme ? 2 : 1 border.width: Theme.isDynamicTheme ? 2 : 1
scale: Theme.isDynamicTheme ? 1.1 : (autoMouseArea.containsMouse ? 1.02 : 1) scale: Theme.isDynamicTheme ? 1.1 : (autoMouseArea.containsMouse ? 1.02 : 1)
@@ -667,17 +685,19 @@ Item {
DankIcon { DankIcon {
name: { name: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "error"
return "error"; || ToastService.wallpaperErrorStatus === "matugen_missing")
return "error"
else else
return "palette"; return "palette"
} }
size: 16 size: 16
color: { color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "error"
return Theme.error; || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error
else else
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -685,23 +705,23 @@ Item {
StyledText { StyledText {
text: { text: {
if (ToastService.wallpaperErrorStatus === "error") if (ToastService.wallpaperErrorStatus === "error")
return "Error"; return "Error"
else if (ToastService.wallpaperErrorStatus === "matugen_missing") else if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "No matugen"; return "No matugen"
else else
return "Auto"; return "Auto"
} }
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: { color: {
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "error"
return Theme.error; || ToastService.wallpaperErrorStatus === "matugen_missing")
return Theme.error
else else
return Theme.surfaceText; return Theme.surfaceText
} }
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -712,11 +732,13 @@ Item {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "matugen_missing")
ToastService.showError("matugen not found - install matugen package for dynamic theming"); ToastService.showError(
"matugen not found - install matugen package for dynamic theming")
else if (ToastService.wallpaperErrorStatus === "error") else if (ToastService.wallpaperErrorStatus === "error")
ToastService.showError("Wallpaper processing failed - check wallpaper path"); ToastService.showError(
"Wallpaper processing failed - check wallpaper path")
else else
Theme.switchTheme(10, true); Theme.switchTheme(10, true)
} }
} }
@@ -730,25 +752,29 @@ Item {
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: autoMouseArea.containsMouse && (!Theme.isDynamicTheme || ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") visible: autoMouseArea.containsMouse
&& (!Theme.isDynamicTheme
|| ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus === "matugen_missing")
StyledText { StyledText {
id: autoTooltipText id: autoTooltipText
text: { text: {
if (ToastService.wallpaperErrorStatus === "matugen_missing") if (ToastService.wallpaperErrorStatus === "matugen_missing")
return "Install matugen package for dynamic themes"; return "Install matugen package for dynamic themes"
else else
return "Dynamic wallpaper-based colors"; return "Dynamic wallpaper-based colors"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing") ? Theme.error : Theme.surfaceText color: (ToastService.wallpaperErrorStatus === "error"
|| ToastService.wallpaperErrorStatus
=== "matugen_missing") ? Theme.error : Theme.surfaceText
anchors.centerIn: parent anchors.centerIn: parent
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: Math.min(implicitWidth, 250) width: Math.min(implicitWidth, 250)
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
} }
Behavior on scale { Behavior on scale {
@@ -756,7 +782,6 @@ Item {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on color { Behavior on color {
@@ -764,7 +789,6 @@ Item {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on border.color { Behavior on border.color {
@@ -772,13 +796,9 @@ Item {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
} }
} }
} }
@@ -791,8 +811,10 @@ Item {
width: parent.width width: parent.width
height: systemThemingSection.implicitHeight + Theme.spacingL * 2 height: systemThemingSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
visible: Theme.isDynamicTheme && Colors.matugenAvailable visible: Theme.isDynamicTheme && Colors.matugenAvailable
@@ -821,7 +843,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
DankToggle { DankToggle {
@@ -831,10 +852,9 @@ Item {
enabled: Colors.gtkThemingEnabled enabled: Colors.gtkThemingEnabled
checked: Colors.gtkThemingEnabled && SettingsData.gtkThemingEnabled checked: Colors.gtkThemingEnabled && SettingsData.gtkThemingEnabled
onToggled: function (checked) { onToggled: function (checked) {
SettingsData.setGtkThemingEnabled(checked); SettingsData.setGtkThemingEnabled(checked)
if (checked && Theme.isDynamicTheme) if (checked && Theme.isDynamicTheme)
Colors.generateGtkThemes(); Colors.generateGtkThemes()
} }
} }
@@ -845,13 +865,11 @@ Item {
enabled: Colors.qtThemingEnabled enabled: Colors.qtThemingEnabled
checked: Colors.qtThemingEnabled && SettingsData.qtThemingEnabled checked: Colors.qtThemingEnabled && SettingsData.qtThemingEnabled
onToggled: function (checked) { onToggled: function (checked) {
SettingsData.setQtThemingEnabled(checked); SettingsData.setQtThemingEnabled(checked)
if (checked && Theme.isDynamicTheme) if (checked && Theme.isDynamicTheme)
Colors.generateQtThemes(); Colors.generateQtThemes()
} }
} }
} }
} }
} }
@@ -861,10 +879,9 @@ Item {
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"] command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
running: false running: false
onExited: (exitCode) => { onExited: exitCode => {
if (exitCode !== 0) if (exitCode !== 0)
SettingsData.setNightModeEnabled(true); SettingsData.setNightModeEnabled(true)
} }
} }
@@ -873,11 +890,9 @@ Item {
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"] command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
running: false running: false
onExited: (exitCode) => { onExited: exitCode => {
if (exitCode !== 0) if (exitCode !== 0)
SettingsData.setNightModeEnabled(false); SettingsData.setNightModeEnabled(false)
} }
} }
} }

View File

@@ -45,8 +45,10 @@ Item {
width: parent.width width: parent.width
height: appLauncherSection.implicitHeight + Theme.spacingL * 2 height: appLauncherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -61,8 +63,8 @@ Item {
text: "Use OS Logo" text: "Use OS Logo"
description: "Display operating system logo instead of apps icon" description: "Display operating system logo instead of apps icon"
checked: SettingsData.useOSLogo checked: SettingsData.useOSLogo
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setUseOSLogo(checked); return SettingsData.setUseOSLogo(checked)
} }
} }
@@ -95,14 +97,13 @@ Item {
topPadding: Theme.spacingXS topPadding: Theme.spacingXS
bottomPadding: Theme.spacingXS bottomPadding: Theme.spacingXS
onEditingFinished: { onEditingFinished: {
var color = text.trim(); var color = text.trim()
if (color === "" || /^#[0-9A-Fa-f]{6}$/.test(color)) if (color === "" || /^#[0-9A-Fa-f]{6}$/.test(color))
SettingsData.setOSLogoColorOverride(color); SettingsData.setOSLogoColorOverride(color)
else else
text = SettingsData.osLogoColorOverride; text = SettingsData.osLogoColorOverride
} }
} }
} }
Column { Column {
@@ -124,11 +125,11 @@ Item {
value: Math.round(SettingsData.osLogoBrightness * 100) value: Math.round(SettingsData.osLogoBrightness * 100)
unit: "%" unit: "%"
showValue: true showValue: true
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
SettingsData.setOSLogoBrightness(newValue / 100); SettingsData.setOSLogoBrightness(
newValue / 100)
} }
} }
} }
Column { Column {
@@ -150,11 +151,11 @@ Item {
value: Math.round(SettingsData.osLogoContrast * 100) value: Math.round(SettingsData.osLogoContrast * 100)
unit: "%" unit: "%"
showValue: true showValue: true
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
SettingsData.setOSLogoContrast(newValue / 100); SettingsData.setOSLogoContrast(
newValue / 100)
} }
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -162,11 +163,8 @@ Item {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
} }
} }
} }
@@ -179,8 +177,10 @@ Item {
width: parent.width width: parent.width
height: dockSection.implicitHeight + Theme.spacingL * 2 height: dockSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -215,7 +215,7 @@ Item {
text: "Show Dock" text: "Show Dock"
description: "Display a dock at the bottom of the screen with pinned and running applications" description: "Display a dock at the bottom of the screen with pinned and running applications"
checked: SettingsData.showDock checked: SettingsData.showDock
onToggled: (checked) => { onToggled: checked => {
SettingsData.setShowDock(checked) SettingsData.setShowDock(checked)
} }
} }
@@ -227,7 +227,7 @@ Item {
checked: SettingsData.dockAutoHide checked: SettingsData.dockAutoHide
visible: SettingsData.showDock visible: SettingsData.showDock
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
onToggled: (checked) => { onToggled: checked => {
SettingsData.setDockAutoHide(checked) SettingsData.setDockAutoHide(checked)
} }
@@ -260,8 +260,9 @@ Item {
maximum: 100 maximum: 100
unit: "" unit: ""
showValue: true showValue: true
onSliderValueChanged: (newValue) => { onSliderValueChanged: newValue => {
SettingsData.setDockTransparency(newValue / 100); SettingsData.setDockTransparency(
newValue / 100)
} }
} }
@@ -272,7 +273,6 @@ Item {
} }
} }
} }
} }
} }
} }
@@ -285,17 +285,19 @@ Item {
width: parent.width width: parent.width
height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2 height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
id: recentlyUsedSection id: recentlyUsedSection
property var rankedAppsModel: { property var rankedAppsModel: {
var apps = []; var apps = []
for (var appId in (AppUsageHistoryData.appUsageRanking || {})) { for (var appId in (AppUsageHistoryData.appUsageRanking || {})) {
var appData = (AppUsageHistoryData.appUsageRanking || {})[appId]; var appData = (AppUsageHistoryData.appUsageRanking || {})[appId]
apps.push({ apps.push({
"id": appId, "id": appId,
"name": appData.name, "name": appData.name,
@@ -304,15 +306,15 @@ Item {
"comment": appData.comment, "comment": appData.comment,
"usageCount": appData.usageCount, "usageCount": appData.usageCount,
"lastUsed": appData.lastUsed "lastUsed": appData.lastUsed
}); })
} }
apps.sort(function (a, b) { apps.sort(function (a, b) {
if (a.usageCount !== b.usageCount) if (a.usageCount !== b.usageCount)
return b.usageCount - a.usageCount; return b.usageCount - a.usageCount
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name)
}); })
return apps.slice(0, 20); return apps.slice(0, 20)
} }
anchors.fill: parent anchors.fill: parent
@@ -339,7 +341,8 @@ Item {
} }
Item { Item {
width: parent.width - parent.children[0].width - parent.children[1].width - clearAllButton.width - Theme.spacingM * 3 width: parent.width - parent.children[0].width - parent.children[1].width
- clearAllButton.width - Theme.spacingM * 3
height: 1 height: 1
} }
@@ -349,14 +352,14 @@ Item {
iconName: "delete_sweep" iconName: "delete_sweep"
iconSize: Theme.iconSize - 2 iconSize: Theme.iconSize - 2
iconColor: Theme.error iconColor: Theme.error
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) hoverColor: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.12)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
onClicked: { onClicked: {
AppUsageHistoryData.appUsageRanking = {}; AppUsageHistoryData.appUsageRanking = {}
SettingsData.saveSettings(); SettingsData.saveSettings()
} }
} }
} }
StyledText { StyledText {
@@ -380,8 +383,11 @@ Item {
width: rankedAppsList.width width: rankedAppsList.width
height: 48 height: 48
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.3) color: Qt.rgba(Theme.surfaceContainer.r,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1) Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
border.width: 1 border.width: 1
Row { Row {
@@ -409,8 +415,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
onStatusChanged: { onStatusChanged: {
if (status === Image.Error) if (status === Image.Error)
source = "image://icon/application-x-executable"; source = "image://icon/application-x-executable"
} }
} }
@@ -428,34 +433,35 @@ Item {
StyledText { StyledText {
text: { text: {
if (!modelData.lastUsed) if (!modelData.lastUsed)
return "Never used"; return "Never used"
var date = new Date(modelData.lastUsed); var date = new Date(modelData.lastUsed)
var now = new Date(); var now = new Date()
var diffMs = now - date; var diffMs = now - date
var diffMins = Math.floor(diffMs / (1000 * 60)); var diffMins = Math.floor(diffMs / (1000 * 60))
var diffHours = Math.floor(diffMs / (1000 * 60 * 60)); var diffHours = Math.floor(diffMs / (1000 * 60 * 60))
var diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); var diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))
if (diffMins < 1) if (diffMins < 1)
return "Last launched just now"; return "Last launched just now"
if (diffMins < 60) if (diffMins < 60)
return "Last launched " + diffMins + " minute" + (diffMins === 1 ? "" : "s") + " ago"; return "Last launched " + diffMins + " minute"
+ (diffMins === 1 ? "" : "s") + " ago"
if (diffHours < 24) if (diffHours < 24)
return "Last launched " + diffHours + " hour" + (diffHours === 1 ? "" : "s") + " ago"; return "Last launched " + diffHours + " hour"
+ (diffHours === 1 ? "" : "s") + " ago"
if (diffDays < 7) if (diffDays < 7)
return "Last launched " + diffDays + " day" + (diffDays === 1 ? "" : "s") + " ago"; return "Last launched " + diffDays + " day"
+ (diffDays === 1 ? "" : "s") + " ago"
return "Last launched " + date.toLocaleDateString(); return "Last launched " + date.toLocaleDateString()
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
} }
} }
} }
DankActionButton { DankActionButton {
@@ -466,31 +472,29 @@ Item {
iconName: "close" iconName: "close"
iconSize: 16 iconSize: 16
iconColor: Theme.error iconColor: Theme.error
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) hoverColor: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.12)
onClicked: { onClicked: {
var currentRanking = Object.assign({ var currentRanking = Object.assign(
}, AppUsageHistoryData.appUsageRanking || {}); {}, AppUsageHistoryData.appUsageRanking || {})
delete currentRanking[modelData.id]; delete currentRanking[modelData.id]
AppUsageHistoryData.appUsageRanking = currentRanking; AppUsageHistoryData.appUsageRanking = currentRanking
SettingsData.saveSettings(); SettingsData.saveSettings()
} }
} }
} }
} }
StyledText { StyledText {
width: parent.width width: parent.width
text: recentlyUsedSection.rankedAppsModel.length === 0 ? "No apps have been launched yet." : "" text: recentlyUsedSection.rankedAppsModel.length
=== 0 ? "No apps have been launched yet." : ""
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
visible: recentlyUsedSection.rankedAppsModel.length === 0 visible: recentlyUsedSection.rankedAppsModel.length === 0
} }
}
}
} }
} }
} }

View File

@@ -51,8 +51,10 @@ Item {
width: parent.width width: parent.width
height: profileSection.implicitHeight + Theme.spacingL * 2 height: profileSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -80,7 +82,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -109,12 +110,12 @@ Item {
source: { source: {
if (PortalService.profileImage === "") if (PortalService.profileImage === "")
return ""; return ""
if (PortalService.profileImage.startsWith("/")) if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage; return "file://" + PortalService.profileImage
return PortalService.profileImage; return PortalService.profileImage
} }
smooth: true smooth: true
asynchronous: true asynchronous: true
@@ -149,7 +150,6 @@ Item {
color: "black" color: "black"
antialiasing: true antialiasing: true
} }
} }
Rectangle { Rectangle {
@@ -164,7 +164,6 @@ Item {
size: Theme.iconSizeLarge + 8 size: Theme.iconSizeLarge + 8
color: Theme.primaryText color: Theme.primaryText
} }
} }
DankIcon { DankIcon {
@@ -172,9 +171,9 @@ Item {
name: "warning" name: "warning"
size: Theme.iconSizeLarge size: Theme.iconSizeLarge
color: Theme.error color: Theme.error
visible: PortalService.profileImage !== "" && avatarImageSource.status === Image.Error visible: PortalService.profileImage !== ""
&& avatarImageSource.status === Image.Error
} }
} }
Column { Column {
@@ -183,7 +182,9 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
text: PortalService.profileImage ? PortalService.profileImage.split('/').pop() : "No profile image selected" text: PortalService.profileImage ? PortalService.profileImage.split(
'/').pop(
) : "No profile image selected"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText color: Theme.surfaceText
elide: Text.ElideMiddle elide: Text.ElideMiddle
@@ -216,7 +217,6 @@ Item {
color: Theme.error color: Theme.error
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -245,21 +245,18 @@ Item {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
profileBrowserLoader.active = true; profileBrowserLoader.active = true
profileBrowser.visible = true; profileBrowser.visible = true
} }
} }
} }
StyledRect { StyledRect {
width: 80 width: 80
height: 32 height: 32
@@ -284,7 +281,6 @@ Item {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -292,18 +288,13 @@ Item {
enabled: PortalService.profileImage !== "" enabled: PortalService.profileImage !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: { onClicked: {
PortalService.setProfileImage(""); PortalService.setProfileImage("")
} }
} }
} }
} }
} }
} }
} }
} }
} }
@@ -316,8 +307,10 @@ Item {
width: parent.width width: parent.width
height: wallpaperSection.implicitHeight + Theme.spacingL * 2 height: wallpaperSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -345,7 +338,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -375,7 +367,6 @@ Item {
maskThresholdMin: 0.5 maskThresholdMin: 0.5
maskSpreadAtMin: 1 maskSpreadAtMin: 1
} }
} }
Rectangle { Rectangle {
@@ -396,7 +387,6 @@ Item {
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
visible: SessionData.wallpaperPath === "" visible: SessionData.wallpaperPath === ""
} }
} }
Column { Column {
@@ -405,7 +395,9 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
text: SessionData.wallpaperPath ? SessionData.wallpaperPath.split('/').pop() : "No wallpaper selected" text: SessionData.wallpaperPath ? SessionData.wallpaperPath.split(
'/').pop(
) : "No wallpaper selected"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText color: Theme.surfaceText
elide: Text.ElideMiddle elide: Text.ElideMiddle
@@ -447,18 +439,16 @@ Item {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
wallpaperBrowserLoader.active = true; wallpaperBrowserLoader.active = true
wallpaperBrowser.visible = true; wallpaperBrowser.visible = true
} }
} }
} }
StyledRect { StyledRect {
@@ -485,7 +475,6 @@ Item {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -493,18 +482,13 @@ Item {
enabled: SessionData.wallpaperPath !== "" enabled: SessionData.wallpaperPath !== ""
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: { onClicked: {
SessionData.setWallpaper(""); SessionData.setWallpaper("")
} }
} }
} }
} }
} }
} }
} }
} }
} }
@@ -517,8 +501,10 @@ Item {
width: parent.width width: parent.width
height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2 height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -558,7 +544,6 @@ Item {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: parent.width width: parent.width
} }
} }
DankToggle { DankToggle {
@@ -567,14 +552,13 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
checked: Theme.isDynamicTheme checked: Theme.isDynamicTheme
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing" enabled: ToastService.wallpaperErrorStatus !== "matugen_missing"
onToggled: (toggled) => { onToggled: toggled => {
if (toggled) if (toggled)
Theme.switchTheme(10, true); Theme.switchTheme(10, true)
else else
Theme.switchTheme(0); Theme.switchTheme(0)
} }
} }
} }
StyledText { StyledText {
@@ -585,7 +569,6 @@ Item {
width: parent.width width: parent.width
leftPadding: Theme.iconSize + Theme.spacingM leftPadding: Theme.iconSize + Theme.spacingM
} }
} }
} }
} }
@@ -602,14 +585,15 @@ Item {
browserIcon: "person" browserIcon: "person"
browserType: "profile" browserType: "profile"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"] fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => { onFileSelected: path => {
PortalService.setProfileImage(path); PortalService.setProfileImage(path)
visible = false; visible = false
}
onDialogClosed: {}
} }
onDialogClosed: {
} }
}
}
LazyLoader { LazyLoader {
id: wallpaperBrowserLoader id: wallpaperBrowserLoader
@@ -623,13 +607,13 @@ Item {
browserIcon: "wallpaper" browserIcon: "wallpaper"
browserType: "wallpaper" browserType: "wallpaper"
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"] fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: (path) => { onFileSelected: path => {
SessionData.setWallpaper(path); SessionData.setWallpaper(path)
visible = false; visible = false
}
onDialogClosed: {}
} }
onDialogClosed: {
} }
}
}
} }

View File

@@ -1,4 +1,4 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior
import QtQuick import QtQuick
import qs.Common import qs.Common
@@ -18,8 +18,7 @@ Column {
spacing: expanded ? Theme.spacingM : 0 spacing: expanded ? Theme.spacingM : 0
Component.onCompleted: { Component.onCompleted: {
if (!collapsible) if (!collapsible)
expanded = true; expanded = true
} }
MouseArea { MouseArea {
@@ -29,13 +28,14 @@ Column {
hoverEnabled: collapsible hoverEnabled: collapsible
onClicked: { onClicked: {
if (collapsible) if (collapsible)
expanded = !expanded; expanded = !expanded
} }
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: parent.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" color: parent.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g,
Theme.primary.b,
0.08) : "transparent"
radius: Theme.radiusS radius: Theme.radiusS
} }
@@ -59,9 +59,7 @@ Column {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard easing.bezierCurve: Appearance.anim.curves.standard
} }
} }
} }
DankIcon { DankIcon {
@@ -79,9 +77,7 @@ Column {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
} }
Rectangle { Rectangle {
@@ -106,9 +102,6 @@ Column {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard easing.bezierCurve: Appearance.anim.curves.standard
} }
} }
} }
} }

View File

@@ -39,8 +39,10 @@ Item {
width: parent.width width: parent.width
height: timeSection.implicitHeight + Theme.spacingL * 2 height: timeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -68,7 +70,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
DankToggle { DankToggle {
@@ -76,11 +77,10 @@ Item {
text: "24-Hour Format" text: "24-Hour Format"
description: "Use 24-hour time format instead of 12-hour AM/PM" description: "Use 24-hour time format instead of 12-hour AM/PM"
checked: SettingsData.use24HourClock checked: SettingsData.use24HourClock
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setClockFormat(checked); return SettingsData.setClockFormat(checked)
} }
} }
} }
} }
} }
@@ -93,8 +93,10 @@ Item {
width: parent.width width: parent.width
height: weatherSection.implicitHeight + Theme.spacingL * 2 height: weatherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -122,7 +124,6 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
DankToggle { DankToggle {
@@ -130,8 +131,8 @@ Item {
text: "Enable Weather" text: "Enable Weather"
description: "Show weather information in top bar and centcom center" description: "Show weather information in top bar and centcom center"
checked: SettingsData.weatherEnabled checked: SettingsData.weatherEnabled
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setWeatherEnabled(checked); return SettingsData.setWeatherEnabled(checked)
} }
} }
@@ -141,8 +142,8 @@ Item {
description: "Use Fahrenheit instead of Celsius for temperature" description: "Use Fahrenheit instead of Celsius for temperature"
checked: SettingsData.useFahrenheit checked: SettingsData.useFahrenheit
enabled: SettingsData.weatherEnabled enabled: SettingsData.weatherEnabled
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setTemperatureUnit(checked); return SettingsData.setTemperatureUnit(checked)
} }
} }
@@ -152,8 +153,8 @@ Item {
description: "Allow wttr.in to determine location based on IP address" description: "Allow wttr.in to determine location based on IP address"
checked: SettingsData.useAutoLocation checked: SettingsData.useAutoLocation
enabled: SettingsData.weatherEnabled enabled: SettingsData.weatherEnabled
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setAutoLocation(checked); return SettingsData.setAutoLocation(checked)
} }
} }
@@ -174,12 +175,11 @@ Item {
currentLocation: SettingsData.weatherLocation currentLocation: SettingsData.weatherLocation
placeholderText: "New York, NY" placeholderText: "New York, NY"
onLocationSelected: (displayName, coordinates) => { onLocationSelected: (displayName, coordinates) => {
SettingsData.setWeatherLocation(displayName, coordinates); SettingsData.setWeatherLocation(displayName,
} coordinates)
} }
}
} }
} }
} }
} }

View File

@@ -165,62 +165,62 @@ Item {
var widgetObj = { var widgetObj = {
"id": widgetId, "id": widgetId,
"enabled": true "enabled": true
}; }
if (widgetId === "spacer") if (widgetId === "spacer")
widgetObj.size = 20; widgetObj.size = 20
if (widgetId === "gpuTemp") if (widgetId === "gpuTemp")
widgetObj.selectedGpuIndex = 0; widgetObj.selectedGpuIndex = 0
var widgets = []; var widgets = []
if (targetSection === "left") { if (targetSection === "left") {
widgets = SettingsData.topBarLeftWidgets.slice(); widgets = SettingsData.topBarLeftWidgets.slice()
widgets.push(widgetObj); widgets.push(widgetObj)
SettingsData.setTopBarLeftWidgets(widgets); SettingsData.setTopBarLeftWidgets(widgets)
} else if (targetSection === "center") { } else if (targetSection === "center") {
widgets = SettingsData.topBarCenterWidgets.slice(); widgets = SettingsData.topBarCenterWidgets.slice()
widgets.push(widgetObj); widgets.push(widgetObj)
SettingsData.setTopBarCenterWidgets(widgets); SettingsData.setTopBarCenterWidgets(widgets)
} else if (targetSection === "right") { } else if (targetSection === "right") {
widgets = SettingsData.topBarRightWidgets.slice(); widgets = SettingsData.topBarRightWidgets.slice()
widgets.push(widgetObj); widgets.push(widgetObj)
SettingsData.setTopBarRightWidgets(widgets); SettingsData.setTopBarRightWidgets(widgets)
} }
} }
function removeWidgetFromSection(sectionId, widgetIndex) { function removeWidgetFromSection(sectionId, widgetIndex) {
var widgets = []; var widgets = []
if (sectionId === "left") { if (sectionId === "left") {
widgets = SettingsData.topBarLeftWidgets.slice(); widgets = SettingsData.topBarLeftWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) { if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets.splice(widgetIndex, 1); widgets.splice(widgetIndex, 1)
} }
SettingsData.setTopBarLeftWidgets(widgets); SettingsData.setTopBarLeftWidgets(widgets)
} else if (sectionId === "center") { } else if (sectionId === "center") {
widgets = SettingsData.topBarCenterWidgets.slice(); widgets = SettingsData.topBarCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) { if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets.splice(widgetIndex, 1); widgets.splice(widgetIndex, 1)
} }
SettingsData.setTopBarCenterWidgets(widgets); SettingsData.setTopBarCenterWidgets(widgets)
} else if (sectionId === "right") { } else if (sectionId === "right") {
widgets = SettingsData.topBarRightWidgets.slice(); widgets = SettingsData.topBarRightWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) { if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets.splice(widgetIndex, 1); widgets.splice(widgetIndex, 1)
} }
SettingsData.setTopBarRightWidgets(widgets); SettingsData.setTopBarRightWidgets(widgets)
} }
} }
function handleItemEnabledChanged(sectionId, itemId, enabled) { function handleItemEnabledChanged(sectionId, itemId, enabled) {
var widgets = []; var widgets = []
if (sectionId === "left") if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice(); widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center") else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice(); widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right") else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice(); widgets = SettingsData.topBarRightWidgets.slice()
for (var i = 0; i < widgets.length; i++) { for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i]; var widget = widgets[i]
var widgetId = typeof widget === "string" ? widget : widget.id; var widgetId = typeof widget === "string" ? widget : widget.id
if (widgetId === itemId) { if (widgetId === itemId) {
widgets[i] = typeof widget === "string" ? { widgets[i] = typeof widget === "string" ? {
"id": widget, "id": widget,
@@ -230,38 +230,38 @@ Item {
"enabled": enabled, "enabled": enabled,
"size": widget.size, "size": widget.size,
"selectedGpuIndex": widget.selectedGpuIndex "selectedGpuIndex": widget.selectedGpuIndex
}; }
break; break
} }
} }
if (sectionId === "left") if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets); SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center") else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets); SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right") else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets); SettingsData.setTopBarRightWidgets(widgets)
} }
function handleItemOrderChanged(sectionId, newOrder) { function handleItemOrderChanged(sectionId, newOrder) {
if (sectionId === "left") if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(newOrder); SettingsData.setTopBarLeftWidgets(newOrder)
else if (sectionId === "center") else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(newOrder); SettingsData.setTopBarCenterWidgets(newOrder)
else if (sectionId === "right") else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(newOrder); SettingsData.setTopBarRightWidgets(newOrder)
} }
function handleSpacerSizeChanged(sectionId, itemId, newSize) { function handleSpacerSizeChanged(sectionId, itemId, newSize) {
var widgets = []; var widgets = []
if (sectionId === "left") if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice(); widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center") else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice(); widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right") else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice(); widgets = SettingsData.topBarRightWidgets.slice()
for (var i = 0; i < widgets.length; i++) { for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i]; var widget = widgets[i]
var widgetId = typeof widget === "string" ? widget : widget.id; var widgetId = typeof widget === "string" ? widget : widget.id
if (widgetId === itemId && widgetId === "spacer") { if (widgetId === itemId && widgetId === "spacer") {
widgets[i] = typeof widget === "string" ? { widgets[i] = typeof widget === "string" ? {
"id": widget, "id": widget,
@@ -272,29 +272,29 @@ Item {
"enabled": widget.enabled, "enabled": widget.enabled,
"size": newSize, "size": newSize,
"selectedGpuIndex": widget.selectedGpuIndex "selectedGpuIndex": widget.selectedGpuIndex
}; }
break; break
} }
} }
if (sectionId === "left") if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets); SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center") else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets); SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right") else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets); SettingsData.setTopBarRightWidgets(widgets)
} }
function handleGpuSelectionChanged(sectionId, widgetIndex, selectedGpuIndex) { function handleGpuSelectionChanged(sectionId, widgetIndex, selectedGpuIndex) {
var widgets = []; var widgets = []
if (sectionId === "left") if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice(); widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center") else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice(); widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right") else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice(); widgets = SettingsData.topBarRightWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) { if (widgetIndex >= 0 && widgetIndex < widgets.length) {
var widget = widgets[widgetIndex]; var widget = widgets[widgetIndex]
widgets[widgetIndex] = typeof widget === "string" ? { widgets[widgetIndex] = typeof widget === "string" ? {
"id": widget, "id": widget,
"enabled": true, "enabled": true,
@@ -304,87 +304,97 @@ Item {
"enabled": widget.enabled, "enabled": widget.enabled,
"size": widget.size, "size": widget.size,
"selectedGpuIndex": selectedGpuIndex "selectedGpuIndex": selectedGpuIndex
}; }
} }
if (sectionId === "left") if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets); SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center") else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets); SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right") else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets); SettingsData.setTopBarRightWidgets(widgets)
} }
function getItemsForSection(sectionId) { function getItemsForSection(sectionId) {
var widgets = []; var widgets = []
var widgetData = []; var widgetData = []
if (sectionId === "left") if (sectionId === "left")
widgetData = SettingsData.topBarLeftWidgets || []; widgetData = SettingsData.topBarLeftWidgets || []
else if (sectionId === "center") else if (sectionId === "center")
widgetData = SettingsData.topBarCenterWidgets || []; widgetData = SettingsData.topBarCenterWidgets || []
else if (sectionId === "right") else if (sectionId === "right")
widgetData = SettingsData.topBarRightWidgets || []; widgetData = SettingsData.topBarRightWidgets || []
widgetData.forEach((widget) => { widgetData.forEach(widget => {
var widgetId = typeof widget === "string" ? widget : widget.id; var widgetId = typeof widget === "string" ? widget : widget.id
var widgetEnabled = typeof widget === "string" ? true : widget.enabled; var widgetEnabled = typeof widget === "string" ? true : widget.enabled
var widgetSize = typeof widget === "string" ? undefined : widget.size; var widgetSize = typeof widget === "string" ? undefined : widget.size
var widgetSelectedGpuIndex = typeof widget === "string" ? undefined : widget.selectedGpuIndex; var widgetSelectedGpuIndex = typeof widget
var widgetDef = baseWidgetDefinitions.find((w) => { === "string" ? undefined : widget.selectedGpuIndex
return w.id === widgetId; var widgetDef = baseWidgetDefinitions.find(w => {
}); return w.id === widgetId
})
if (widgetDef) { if (widgetDef) {
var item = Object.assign({ var item = Object.assign({}, widgetDef)
}, widgetDef); item.enabled = widgetEnabled
item.enabled = widgetEnabled;
if (widgetSize !== undefined) if (widgetSize !== undefined)
item.size = widgetSize; item.size = widgetSize
if (widgetSelectedGpuIndex !== undefined) if (widgetSelectedGpuIndex !== undefined)
item.selectedGpuIndex = widgetSelectedGpuIndex; item.selectedGpuIndex = widgetSelectedGpuIndex
widgets.push(item); widgets.push(item)
} }
}); })
return widgets; return widgets
} }
Component.onCompleted: { Component.onCompleted: {
if (!SettingsData.topBarLeftWidgets || SettingsData.topBarLeftWidgets.length === 0) if (!SettingsData.topBarLeftWidgets
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets); || SettingsData.topBarLeftWidgets.length === 0)
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets)
if (!SettingsData.topBarCenterWidgets || SettingsData.topBarCenterWidgets.length === 0) if (!SettingsData.topBarCenterWidgets
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets); || SettingsData.topBarCenterWidgets.length === 0)
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets)
if (!SettingsData.topBarRightWidgets || SettingsData.topBarRightWidgets.length === 0) if (!SettingsData.topBarRightWidgets
SettingsData.setTopBarRightWidgets(defaultRightWidgets); || SettingsData.topBarRightWidgets.length === 0)
SettingsData.setTopBarRightWidgets(
["left", "center", "right"].forEach((sectionId) => { defaultRightWidgets)["left", "center", "right"].forEach(sectionId => {
var widgets = []; var widgets = []
if (sectionId === "left") if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice(); widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center") else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice(); widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right") else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice(); widgets = SettingsData.topBarRightWidgets.slice()
var updated = false; var updated = false
for (var i = 0; i < widgets.length; i++) { for (var i = 0; i
var widget = widgets[i]; < widgets.length; i++) {
if (typeof widget === "object" && widget.id === "spacer" && !widget.size) { var widget = widgets[i]
widgets[i] = Object.assign({ if (typeof widget === "object"
}, widget, { && widget.id === "spacer"
&& !widget.size) {
widgets[i] = Object.assign(
{},
widget,
{
"size": 20 "size": 20
}); })
updated = true; updated = true
} }
} }
if (updated) { if (updated) {
if (sectionId === "left") if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets); SettingsData.setTopBarLeftWidgets(
widgets)
else if (sectionId === "center") else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets); SettingsData.setTopBarCenterWidgets(
widgets)
else if (sectionId === "right") else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets); SettingsData.setTopBarRightWidgets(
widgets)
} }
}); })
} }
DankFlickable { DankFlickable {
@@ -457,7 +467,10 @@ Item {
color: resetArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariant color: resetArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariant
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
border.width: 1 border.width: 1
border.color: resetArea.containsMouse ? Theme.outline : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.5) border.color: resetArea.containsMouse ? Theme.outline : Qt.rgba(
Theme.outline.r,
Theme.outline.g,
Theme.outline.b, 0.5)
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -486,9 +499,9 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
SettingsData.setTopBarLeftWidgets(defaultLeftWidgets); SettingsData.setTopBarLeftWidgets(defaultLeftWidgets)
SettingsData.setTopBarCenterWidgets(defaultCenterWidgets); SettingsData.setTopBarCenterWidgets(defaultCenterWidgets)
SettingsData.setTopBarRightWidgets(defaultRightWidgets); SettingsData.setTopBarRightWidgets(defaultRightWidgets)
} }
} }
@@ -517,8 +530,10 @@ Item {
width: parent.width width: parent.width
height: messageText.contentHeight + Theme.spacingM * 2 height: messageText.contentHeight + Theme.spacingM * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
StyledText { StyledText {
@@ -550,31 +565,38 @@ Item {
allWidgets: widgetsTab.baseWidgetDefinitions allWidgets: widgetsTab.baseWidgetDefinitions
items: widgetsTab.getItemsForSection("left") items: widgetsTab.getItemsForSection("left")
onItemEnabledChanged: (sectionId, itemId, enabled) => { onItemEnabledChanged: (sectionId, itemId, enabled) => {
widgetsTab.handleItemEnabledChanged(sectionId, itemId, enabled); widgetsTab.handleItemEnabledChanged(sectionId,
itemId,
enabled)
} }
onItemOrderChanged: (newOrder) => { onItemOrderChanged: newOrder => {
widgetsTab.handleItemOrderChanged("left", newOrder); widgetsTab.handleItemOrderChanged("left",
newOrder)
} }
onAddWidget: (sectionId) => { onAddWidget: sectionId => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions; widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions
widgetSelectionPopup.targetSection = sectionId; widgetSelectionPopup.targetSection = sectionId
widgetSelectionPopup.safeOpen(); widgetSelectionPopup.safeOpen()
} }
onRemoveWidget: (sectionId, widgetIndex) => { onRemoveWidget: (sectionId, widgetIndex) => {
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex); widgetsTab.removeWidgetFromSection(sectionId,
widgetIndex)
} }
onSpacerSizeChanged: (sectionId, itemId, newSize) => { onSpacerSizeChanged: (sectionId, itemId, newSize) => {
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize); widgetsTab.handleSpacerSizeChanged(sectionId,
itemId,
newSize)
} }
onCompactModeChanged: (widgetId, enabled) => { onCompactModeChanged: (widgetId, enabled) => {
if (widgetId === "clock") { if (widgetId === "clock") {
SettingsData.setClockCompactMode(enabled); SettingsData.setClockCompactMode(enabled)
} else if (widgetId === "music") { } else if (widgetId === "music") {
SettingsData.setMediaCompactMode(enabled); SettingsData.setMediaCompactMode(enabled)
} }
} }
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => { onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex); widgetsTab.handleGpuSelectionChanged(
sectionId, widgetIndex, selectedIndex)
} }
} }
@@ -586,31 +608,38 @@ Item {
allWidgets: widgetsTab.baseWidgetDefinitions allWidgets: widgetsTab.baseWidgetDefinitions
items: widgetsTab.getItemsForSection("center") items: widgetsTab.getItemsForSection("center")
onItemEnabledChanged: (sectionId, itemId, enabled) => { onItemEnabledChanged: (sectionId, itemId, enabled) => {
widgetsTab.handleItemEnabledChanged(sectionId, itemId, enabled); widgetsTab.handleItemEnabledChanged(sectionId,
itemId,
enabled)
} }
onItemOrderChanged: (newOrder) => { onItemOrderChanged: newOrder => {
widgetsTab.handleItemOrderChanged("center", newOrder); widgetsTab.handleItemOrderChanged("center",
newOrder)
} }
onAddWidget: (sectionId) => { onAddWidget: sectionId => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions; widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions
widgetSelectionPopup.targetSection = sectionId; widgetSelectionPopup.targetSection = sectionId
widgetSelectionPopup.safeOpen(); widgetSelectionPopup.safeOpen()
} }
onRemoveWidget: (sectionId, widgetIndex) => { onRemoveWidget: (sectionId, widgetIndex) => {
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex); widgetsTab.removeWidgetFromSection(sectionId,
widgetIndex)
} }
onSpacerSizeChanged: (sectionId, itemId, newSize) => { onSpacerSizeChanged: (sectionId, itemId, newSize) => {
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize); widgetsTab.handleSpacerSizeChanged(sectionId,
itemId,
newSize)
} }
onCompactModeChanged: (widgetId, enabled) => { onCompactModeChanged: (widgetId, enabled) => {
if (widgetId === "clock") { if (widgetId === "clock") {
SettingsData.setClockCompactMode(enabled); SettingsData.setClockCompactMode(enabled)
} else if (widgetId === "music") { } else if (widgetId === "music") {
SettingsData.setMediaCompactMode(enabled); SettingsData.setMediaCompactMode(enabled)
} }
} }
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => { onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex); widgetsTab.handleGpuSelectionChanged(
sectionId, widgetIndex, selectedIndex)
} }
} }
@@ -622,31 +651,38 @@ Item {
allWidgets: widgetsTab.baseWidgetDefinitions allWidgets: widgetsTab.baseWidgetDefinitions
items: widgetsTab.getItemsForSection("right") items: widgetsTab.getItemsForSection("right")
onItemEnabledChanged: (sectionId, itemId, enabled) => { onItemEnabledChanged: (sectionId, itemId, enabled) => {
widgetsTab.handleItemEnabledChanged(sectionId, itemId, enabled); widgetsTab.handleItemEnabledChanged(sectionId,
itemId,
enabled)
} }
onItemOrderChanged: (newOrder) => { onItemOrderChanged: newOrder => {
widgetsTab.handleItemOrderChanged("right", newOrder); widgetsTab.handleItemOrderChanged("right",
newOrder)
} }
onAddWidget: (sectionId) => { onAddWidget: sectionId => {
widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions; widgetSelectionPopup.allWidgets = widgetsTab.baseWidgetDefinitions
widgetSelectionPopup.targetSection = sectionId; widgetSelectionPopup.targetSection = sectionId
widgetSelectionPopup.safeOpen(); widgetSelectionPopup.safeOpen()
} }
onRemoveWidget: (sectionId, widgetIndex) => { onRemoveWidget: (sectionId, widgetIndex) => {
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex); widgetsTab.removeWidgetFromSection(sectionId,
widgetIndex)
} }
onSpacerSizeChanged: (sectionId, itemId, newSize) => { onSpacerSizeChanged: (sectionId, itemId, newSize) => {
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize); widgetsTab.handleSpacerSizeChanged(sectionId,
itemId,
newSize)
} }
onCompactModeChanged: (widgetId, enabled) => { onCompactModeChanged: (widgetId, enabled) => {
if (widgetId === "clock") { if (widgetId === "clock") {
SettingsData.setClockCompactMode(enabled); SettingsData.setClockCompactMode(enabled)
} else if (widgetId === "music") { } else if (widgetId === "music") {
SettingsData.setMediaCompactMode(enabled); SettingsData.setMediaCompactMode(enabled)
} }
} }
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => { onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex); widgetsTab.handleGpuSelectionChanged(
sectionId, widgetIndex, selectedIndex)
} }
} }
} }
@@ -660,8 +696,10 @@ Item {
width: parent.width width: parent.width
height: workspaceSection.implicitHeight + Theme.spacingL * 2 height: workspaceSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
Column { Column {
@@ -696,8 +734,8 @@ Item {
text: "Workspace Index Numbers" text: "Workspace Index Numbers"
description: "Show workspace index numbers in the top bar workspace switcher" description: "Show workspace index numbers in the top bar workspace switcher"
checked: SettingsData.showWorkspaceIndex checked: SettingsData.showWorkspaceIndex
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setShowWorkspaceIndex(checked); return SettingsData.setShowWorkspaceIndex(checked)
} }
} }
@@ -706,22 +744,20 @@ Item {
text: "Workspace Padding" text: "Workspace Padding"
description: "Always show a minimum of 3 workspaces, even if fewer are available" description: "Always show a minimum of 3 workspaces, even if fewer are available"
checked: SettingsData.showWorkspacePadding checked: SettingsData.showWorkspacePadding
onToggled: (checked) => { onToggled: checked => {
return SettingsData.setShowWorkspacePadding(checked); return SettingsData.setShowWorkspacePadding(checked)
} }
} }
} }
} }
} }
DankWidgetSelectionPopup { DankWidgetSelectionPopup {
id: widgetSelectionPopup id: widgetSelectionPopup
anchors.centerIn: parent anchors.centerIn: parent
onWidgetSelected: (widgetId, targetSection) => { onWidgetSelected: (widgetId, targetSection) => {
widgetsTab.addWidgetToSection(widgetId, targetSection); widgetsTab.addWidgetToSection(widgetId, targetSection)
} }
} }
} }

View File

@@ -48,7 +48,6 @@ Column {
width: parent.width - 60 width: parent.width - 60
height: 1 height: 1
} }
} }
Column { Column {
@@ -76,8 +75,10 @@ Column {
anchors.fill: parent anchors.fill: parent
anchors.margins: 2 anchors.margins: 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.8) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceContainer.b, 0.8)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
DankIcon { DankIcon {
@@ -119,12 +120,13 @@ Column {
StyledText { StyledText {
text: modelData.description text: modelData.description
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: modelData.enabled ? Theme.outline : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6) color: modelData.enabled ? Theme.outline : Qt.rgba(
Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.6)
elide: Text.ElideRight elide: Text.ElideRight
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
} }
} }
Row { Row {
@@ -144,27 +146,40 @@ Column {
id: gpuDropdown id: gpuDropdown
anchors.fill: parent anchors.fill: parent
currentValue: { currentValue: {
var selectedIndex = modelData.selectedGpuIndex !== undefined ? modelData.selectedGpuIndex : 0; var selectedIndex = modelData.selectedGpuIndex
if (SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > selectedIndex && selectedIndex >= 0) { !== undefined ? modelData.selectedGpuIndex : 0
var gpu = SysMonitorService.availableGpus[selectedIndex]; if (SysMonitorService.availableGpus
return gpu.driver.toUpperCase() + " (" + Math.round(gpu.temperature || 0) + "°C)"; && SysMonitorService.availableGpus.length > selectedIndex
&& selectedIndex >= 0) {
var gpu = SysMonitorService.availableGpus[selectedIndex]
return gpu.driver.toUpperCase() + " (" + Math.round(
gpu.temperature || 0) + "°C)"
} }
return SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > 0 ? SysMonitorService.availableGpus[0].driver.toUpperCase() + " (" + Math.round(SysMonitorService.availableGpus[0].temperature || 0) + "°C)" : ""; return SysMonitorService.availableGpus
&& SysMonitorService.availableGpus.length
> 0 ? SysMonitorService.availableGpus[0].driver.toUpperCase(
) + " (" + Math.round(
SysMonitorService.availableGpus[0].temperature
|| 0) + "°C)" : ""
} }
options: { options: {
var gpuOptions = []; var gpuOptions = []
if (SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > 0) { if (SysMonitorService.availableGpus
&& SysMonitorService.availableGpus.length > 0) {
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) { for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
var gpu = SysMonitorService.availableGpus[i]; var gpu = SysMonitorService.availableGpus[i]
gpuOptions.push(gpu.driver.toUpperCase() + " (" + Math.round(gpu.temperature || 0) + "°C)"); gpuOptions.push(gpu.driver.toUpperCase(
) + " (" + Math.round(gpu.temperature
|| 0) + "°C)")
} }
} }
return gpuOptions; return gpuOptions
} }
onValueChanged: (value) => { onValueChanged: value => {
var gpuIndex = options.indexOf(value); var gpuIndex = options.indexOf(value)
if (gpuIndex >= 0) { if (gpuIndex >= 0) {
root.gpuSelectionChanged(root.sectionId, index, gpuIndex); root.gpuSelectionChanged(root.sectionId,
index, gpuIndex)
} }
} }
} }
@@ -179,14 +194,22 @@ Column {
id: compactModeButton id: compactModeButton
anchors.fill: parent anchors.fill: parent
buttonSize: 32 buttonSize: 32
iconName: (modelData.id === "clock" && SettingsData.clockCompactMode) || (modelData.id === "music" && SettingsData.mediaCompactMode) ? "zoom_out" : "zoom_in" iconName: (modelData.id === "clock"
&& SettingsData.clockCompactMode)
|| (modelData.id === "music"
&& SettingsData.mediaCompactMode) ? "zoom_out" : "zoom_in"
iconSize: 18 iconSize: 18
iconColor: ((modelData.id === "clock" && SettingsData.clockCompactMode) || (modelData.id === "music" && SettingsData.mediaCompactMode)) ? Theme.primary : Theme.outline iconColor: ((modelData.id === "clock"
&& SettingsData.clockCompactMode)
|| (modelData.id === "music"
&& SettingsData.mediaCompactMode)) ? Theme.primary : Theme.outline
onClicked: { onClicked: {
if (modelData.id === "clock") { if (modelData.id === "clock") {
root.compactModeChanged("clock", !SettingsData.clockCompactMode); root.compactModeChanged("clock",
!SettingsData.clockCompactMode)
} else if (modelData.id === "music") { } else if (modelData.id === "music") {
root.compactModeChanged("music", !SettingsData.mediaCompactMode); root.compactModeChanged("music",
!SettingsData.mediaCompactMode)
} }
} }
} }
@@ -199,7 +222,8 @@ Column {
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 1
visible: compactModeButton.children[1] && compactModeButton.children[1].containsMouse visible: compactModeButton.children[1]
&& compactModeButton.children[1].containsMouse
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
x: -width - Theme.spacingS x: -width - Theme.spacingS
y: (parent.height - height) / 2 y: (parent.height - height) / 2
@@ -229,7 +253,8 @@ Column {
iconSize: 18 iconSize: 18
iconColor: modelData.enabled ? Theme.primary : Theme.outline iconColor: modelData.enabled ? Theme.primary : Theme.outline
onClicked: { onClicked: {
root.itemEnabledChanged(root.sectionId, modelData.id, !modelData.enabled); root.itemEnabledChanged(root.sectionId, modelData.id,
!modelData.enabled)
} }
} }
@@ -244,9 +269,9 @@ Column {
iconSize: 14 iconSize: 14
iconColor: Theme.outline iconColor: Theme.outline
onClicked: { onClicked: {
var currentSize = modelData.size || 20; var currentSize = modelData.size || 20
var newSize = Math.max(5, currentSize - 5); var newSize = Math.max(5, currentSize - 5)
root.spacerSizeChanged(root.sectionId, modelData.id, newSize); root.spacerSizeChanged(root.sectionId, modelData.id, newSize)
} }
} }
@@ -263,12 +288,11 @@ Column {
iconSize: 14 iconSize: 14
iconColor: Theme.outline iconColor: Theme.outline
onClicked: { onClicked: {
var currentSize = modelData.size || 20; var currentSize = modelData.size || 20
var newSize = Math.min(5000, currentSize + 5); var newSize = Math.min(5000, currentSize + 5)
root.spacerSizeChanged(root.sectionId, modelData.id, newSize); root.spacerSizeChanged(root.sectionId, modelData.id, newSize)
} }
} }
} }
DankActionButton { DankActionButton {
@@ -277,10 +301,9 @@ Column {
iconSize: 18 iconSize: 18
iconColor: Theme.error iconColor: Theme.error
onClicked: { onClicked: {
root.removeWidget(root.sectionId, index); root.removeWidget(root.sectionId, index)
} }
} }
} }
MouseArea { MouseArea {
@@ -298,29 +321,31 @@ Column {
drag.maximumY: itemsList.height drag.maximumY: itemsList.height
preventStealing: true preventStealing: true
onPressed: { onPressed: {
delegateItem.z = 2; delegateItem.z = 2
delegateItem.originalY = delegateItem.y; delegateItem.originalY = delegateItem.y
} }
onReleased: { onReleased: {
delegateItem.z = 1; delegateItem.z = 1
if (drag.active) { if (drag.active) {
var newIndex = Math.round(delegateItem.y / (delegateItem.height + itemsList.spacing)); var newIndex = Math.round(
newIndex = Math.max(0, Math.min(newIndex, root.items.length - 1)); delegateItem.y / (delegateItem.height + itemsList.spacing))
newIndex = Math.max(0, Math.min(newIndex,
root.items.length - 1))
if (newIndex !== index) { if (newIndex !== index) {
var newItems = root.items.slice(); var newItems = root.items.slice()
var draggedItem = newItems.splice(index, 1)[0]; var draggedItem = newItems.splice(index, 1)[0]
newItems.splice(newIndex, 0, draggedItem); newItems.splice(newIndex, 0, draggedItem)
root.itemOrderChanged(newItems.map((item) => { root.itemOrderChanged(newItems.map(item => {
return ({ return ({
"id": item.id, "id": item.id,
"enabled": item.enabled, "enabled": item.enabled,
"size": item.size "size": item.size
}); })
})); }))
} }
} }
delegateItem.x = 0; delegateItem.x = 0
delegateItem.y = delegateItem.originalY; delegateItem.y = delegateItem.originalY
} }
} }
@@ -331,23 +356,22 @@ Column {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
} }
} }
Rectangle { Rectangle {
width: 200 width: 200
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: addButtonArea.containsMouse ? Theme.primaryContainer : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: addButtonArea.containsMouse ? Theme.primaryContainer : Qt.rgba(
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 1 border.width: 1
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@@ -367,7 +391,7 @@ Column {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.addWidget(root.sectionId); root.addWidget(root.sectionId)
} }
} }
@@ -376,9 +400,6 @@ Column {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }

View File

@@ -36,13 +36,13 @@ PanelWindow {
color: { color: {
switch (ToastService.currentLevel) { switch (ToastService.currentLevel) {
case ToastService.levelError: case ToastService.levelError:
return Theme.error; return Theme.error
case ToastService.levelWarn: case ToastService.levelWarn:
return Theme.warning; return Theme.warning
case ToastService.levelInfo: case ToastService.levelInfo:
return Theme.primary; return Theme.primary
default: default:
return Theme.primary; return Theme.primary
} }
} }
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
@@ -60,13 +60,13 @@ PanelWindow {
name: { name: {
switch (ToastService.currentLevel) { switch (ToastService.currentLevel) {
case ToastService.levelError: case ToastService.levelError:
return "error"; return "error"
case ToastService.levelWarn: case ToastService.levelWarn:
return "warning"; return "warning"
case ToastService.levelInfo: case ToastService.levelInfo:
return "info"; return "info"
default: default:
return "info"; return "info"
} }
} }
size: Theme.iconSize size: Theme.iconSize
@@ -83,7 +83,6 @@ PanelWindow {
width: 300 width: 300
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
} }
} }
MouseArea { MouseArea {
@@ -109,7 +108,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on scale { Behavior on scale {
@@ -117,7 +115,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on color { Behavior on color {
@@ -125,13 +122,10 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
mask: Region { mask: Region {
item: toast item: toast
} }
} }

View File

@@ -8,7 +8,8 @@ Item {
readonly property MprisPlayer activePlayer: MprisController.activePlayer readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool hasActiveMedia: activePlayer !== null readonly property bool hasActiveMedia: activePlayer !== null
readonly property bool isPlaying: hasActiveMedia && activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing readonly property bool isPlaying: hasActiveMedia && activePlayer
&& activePlayer.playbackState === MprisPlaybackState.Playing
width: 20 width: 20
height: Theme.iconSize height: Theme.iconSize
@@ -24,7 +25,10 @@ Item {
interval: 256 interval: 256
repeat: true repeat: true
onTriggered: { onTriggered: {
CavaService.values = [Math.random() * 40 + 10, Math.random() * 60 + 20, Math.random() * 50 + 15, Math.random() * 35 + 20, Math.random() * 45 + 15, Math.random() * 55 + 25]; CavaService.values = [Math.random() * 40 + 10, Math.random(
) * 60 + 20, Math.random() * 50 + 15, Math.random(
) * 35 + 20, Math.random() * 45 + 15, Math.random(
) * 55 + 25]
} }
} }
@@ -39,13 +43,14 @@ Item {
width: 2 width: 2
height: { height: {
if (root.isPlaying && CavaService.values.length > index) { if (root.isPlaying && CavaService.values.length > index) {
const rawLevel = CavaService.values[index] || 0; const rawLevel = CavaService.values[index] || 0
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0), 100) / 100) * 100; const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0),
const maxHeight = Theme.iconSize - 2; 100) / 100) * 100
const minHeight = 3; const maxHeight = Theme.iconSize - 2
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight); const minHeight = 3
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight)
} }
return 3; return 3
} }
radius: 1.5 radius: 1.5
color: Theme.primary color: Theme.primary
@@ -57,13 +62,8 @@ Item {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel easing.bezierCurve: Anims.standardDecel
} }
} }
} }
} }
} }
} }

View File

@@ -12,14 +12,16 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
signal toggleBatteryPopup() signal toggleBatteryPopup
width: BatteryService.batteryAvailable ? 70 : 40 width: BatteryService.batteryAvailable ? 70 : 40
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = batteryArea.containsMouse || batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = batteryArea.containsMouse
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); || batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
visible: true visible: true
@@ -28,19 +30,21 @@ Rectangle {
spacing: 4 spacing: 4
DankIcon { DankIcon {
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable) name: Theme.getBatteryIcon(BatteryService.batteryLevel,
BatteryService.isCharging,
BatteryService.batteryAvailable)
size: Theme.iconSize - 6 size: Theme.iconSize - 6
color: { color: {
if (!BatteryService.batteryAvailable) if (!BatteryService.batteryAvailable)
return Theme.surfaceText; return Theme.surfaceText
if (BatteryService.isLowBattery && !BatteryService.isCharging) if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error; return Theme.error
if (BatteryService.isCharging) if (BatteryService.isCharging)
return Theme.primary; return Theme.primary
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -61,9 +65,7 @@ Rectangle {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard easing.bezierCurve: Anims.standard
} }
} }
} }
StyledText { StyledText {
@@ -72,20 +74,19 @@ Rectangle {
font.weight: Font.Medium font.weight: Font.Medium
color: { color: {
if (!BatteryService.batteryAvailable) if (!BatteryService.batteryAvailable)
return Theme.surfaceText; return Theme.surfaceText
if (BatteryService.isLowBattery && !BatteryService.isCharging) if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error; return Theme.error
if (BatteryService.isCharging) if (BatteryService.isCharging)
return Theme.primary; return Theme.primary
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable visible: BatteryService.batteryAvailable
} }
} }
MouseArea { MouseArea {
@@ -96,13 +97,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
toggleBatteryPopup(); toggleBatteryPopup()
} }
} }
@@ -131,30 +134,29 @@ Rectangle {
text: { text: {
if (!BatteryService.batteryAvailable) { if (!BatteryService.batteryAvailable) {
if (typeof PowerProfiles === "undefined") if (typeof PowerProfiles === "undefined")
return "Power Management"; return "Power Management"
switch (PowerProfiles.profile) { switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver: case PowerProfile.PowerSaver:
return "Power Profile: Power Saver"; return "Power Profile: Power Saver"
case PowerProfile.Performance: case PowerProfile.Performance:
return "Power Profile: Performance"; return "Power Profile: Performance"
default: default:
return "Power Profile: Balanced"; return "Power Profile: Balanced"
} }
} }
let status = BatteryService.batteryStatus; let status = BatteryService.batteryStatus
let level = BatteryService.batteryLevel + "%"; let level = BatteryService.batteryLevel + "%"
let time = BatteryService.formatTimeRemaining(); let time = BatteryService.formatTimeRemaining()
if (time !== "Unknown") if (time !== "Unknown")
return status + " • " + level + " • " + time; return status + " • " + level + " • " + time
else else
return status + " • " + level; return status + " • " + level
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -162,9 +164,7 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Behavior on color { Behavior on color {
@@ -172,7 +172,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -19,29 +19,28 @@ PanelWindow {
property var triggerScreen: null property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) { function setTriggerPosition(x, y, width, section, screen) {
triggerX = x; triggerX = x
triggerY = y; triggerY = y
triggerWidth = width; triggerWidth = width
triggerSection = section; triggerSection = section
triggerScreen = screen; triggerScreen = screen
} }
function isActiveProfile(profile) { function isActiveProfile(profile) {
if (typeof PowerProfiles === "undefined") if (typeof PowerProfiles === "undefined")
return false; return false
return PowerProfiles.profile === profile; return PowerProfiles.profile === profile
} }
function setProfile(profile) { function setProfile(profile) {
if (typeof PowerProfiles === "undefined") { if (typeof PowerProfiles === "undefined") {
ToastService.showError("power-profiles-daemon not available"); ToastService.showError("power-profiles-daemon not available")
return ; return
} }
PowerProfiles.profile = profile; PowerProfiles.profile = profile
if (PowerProfiles.profile !== profile) if (PowerProfiles.profile !== profile)
ToastService.showError("Failed to set power profile"); ToastService.showError("Failed to set power profile")
} }
visible: batteryPopupVisible visible: batteryPopupVisible
@@ -63,10 +62,10 @@ PanelWindow {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: function (mouse) { onClicked: function (mouse) {
var localPos = mapToItem(contentLoader, mouse.x, mouse.y); var localPos = mapToItem(contentLoader, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height) if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0
batteryPopupVisible = false; || localPos.y > contentLoader.height)
batteryPopupVisible = false
} }
} }
@@ -75,24 +74,28 @@ PanelWindow {
readonly property real screenWidth: root.screen ? root.screen.width : Screen.width readonly property real screenWidth: root.screen ? root.screen.width : Screen.width
readonly property real screenHeight: root.screen ? root.screen.height : Screen.height readonly property real screenHeight: root.screen ? root.screen.height : Screen.height
readonly property real targetWidth: Math.min(380, screenWidth - Theme.spacingL * 2) readonly property real targetWidth: Math.min(
readonly property real targetHeight: Math.min(450, screenHeight - Theme.barHeight - Theme.spacingS * 2) 380, screenWidth - Theme.spacingL * 2)
readonly property real targetHeight: Math.min(
450,
screenHeight - Theme.barHeight - Theme.spacingS * 2)
readonly property real calculatedX: { readonly property real calculatedX: {
var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2); var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2)
if (centerX >= Theme.spacingM && centerX + targetWidth <= screenWidth - Theme.spacingM) { if (centerX >= Theme.spacingM
return centerX; && centerX + targetWidth <= screenWidth - Theme.spacingM) {
return centerX
} }
if (centerX < Theme.spacingM) { if (centerX < Theme.spacingM) {
return Theme.spacingM; return Theme.spacingM
} }
if (centerX + targetWidth > screenWidth - Theme.spacingM) { if (centerX + targetWidth > screenWidth - Theme.spacingM) {
return screenWidth - targetWidth - Theme.spacingM; return screenWidth - targetWidth - Theme.spacingM
} }
return centerX; return centerX
} }
asynchronous: true asynchronous: true
@@ -110,7 +113,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
Behavior on scale { Behavior on scale {
@@ -119,7 +121,6 @@ PanelWindow {
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasized easing.bezierCurve: Anims.emphasized
} }
} }
sourceComponent: Rectangle { sourceComponent: Rectangle {
@@ -132,12 +133,12 @@ PanelWindow {
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {
if (batteryPopupVisible) if (batteryPopupVisible)
forceActiveFocus(); forceActiveFocus()
} }
Keys.onPressed: function (event) { Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
batteryPopupVisible = false; batteryPopupVisible = false
event.accepted = true; event.accepted = true
} }
} }
@@ -145,8 +146,8 @@ PanelWindow {
function onBatteryPopupVisibleChanged() { function onBatteryPopupVisibleChanged() {
if (batteryPopupVisible) if (batteryPopupVisible)
Qt.callLater(function () { Qt.callLater(function () {
parent.forceActiveFocus(); parent.forceActiveFocus()
}); })
} }
target: root target: root
} }
@@ -225,21 +226,22 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
batteryPopupVisible = false; batteryPopupVisible = false
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 80 height: 80
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Theme.outlineMedium) border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Theme.outlineMedium)
border.width: BatteryService.isCharging || BatteryService.isLowBattery ? 2 : 1 border.width: BatteryService.isCharging
|| BatteryService.isLowBattery ? 2 : 1
visible: BatteryService.batteryAvailable visible: BatteryService.batteryAvailable
Row { Row {
@@ -249,16 +251,18 @@ PanelWindow {
spacing: Theme.spacingL spacing: Theme.spacingL
DankIcon { DankIcon {
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable) name: Theme.getBatteryIcon(BatteryService.batteryLevel,
BatteryService.isCharging,
BatteryService.batteryAvailable)
size: Theme.iconSizeLarge size: Theme.iconSizeLarge
color: { color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging) if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error; return Theme.error
if (BatteryService.isCharging) if (BatteryService.isCharging)
return Theme.primary; return Theme.primary
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -274,13 +278,14 @@ PanelWindow {
text: BatteryService.batteryLevel + "%" text: BatteryService.batteryLevel + "%"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: { color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging) if (BatteryService.isLowBattery
return Theme.error; && !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging) if (BatteryService.isCharging)
return Theme.primary; return Theme.primary
return Theme.surfaceText; return Theme.surfaceText
} }
font.weight: Font.Bold font.weight: Font.Bold
} }
@@ -289,44 +294,44 @@ PanelWindow {
text: BatteryService.batteryStatus text: BatteryService.batteryStatus
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: { color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging) if (BatteryService.isLowBattery
return Theme.error; && !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging) if (BatteryService.isCharging)
return Theme.primary; return Theme.primary
return Theme.surfaceText; return Theme.surfaceText
} }
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
StyledText { StyledText {
text: { text: {
let time = BatteryService.formatTimeRemaining(); let time = BatteryService.formatTimeRemaining()
if (time !== "Unknown") if (time !== "Unknown")
return BatteryService.isCharging ? "Time until full: " + time : "Time remaining: " + time; return BatteryService.isCharging ? "Time until full: "
+ time : "Time remaining: " + time
return ""; return ""
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium color: Theme.surfaceTextMedium
visible: text.length > 0 visible: text.length > 0
} }
} }
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 80 height: 80
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
border.width: 1 border.width: 1
visible: !BatteryService.batteryAvailable visible: !BatteryService.batteryAvailable
@@ -358,11 +363,8 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium color: Theme.surfaceTextMedium
} }
} }
} }
} }
Column { Column {
@@ -397,13 +399,12 @@ PanelWindow {
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: { color: {
if (BatteryService.batteryHealth === "N/A") if (BatteryService.batteryHealth === "N/A")
return Theme.surfaceText; return Theme.surfaceText
var healthNum = parseInt(BatteryService.batteryHealth); var healthNum = parseInt(BatteryService.batteryHealth)
return healthNum < 80 ? Theme.error : Theme.surfaceText; return healthNum < 80 ? Theme.error : Theme.surfaceText
} }
} }
} }
Column { Column {
@@ -418,15 +419,13 @@ PanelWindow {
} }
StyledText { StyledText {
text: BatteryService.batteryCapacity > 0 ? BatteryService.batteryCapacity.toFixed(1) + " Wh" : "Unknown" text: BatteryService.batteryCapacity > 0 ? BatteryService.batteryCapacity.toFixed(
1) + " Wh" : "Unknown"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText color: Theme.surfaceText
} }
} }
} }
} }
Column { Column {
@@ -446,14 +445,17 @@ PanelWindow {
spacing: Theme.spacingS spacing: Theme.spacingS
Repeater { Repeater {
model: (typeof PowerProfiles !== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance] model: (typeof PowerProfiles
!== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(
PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: profileArea.containsMouse ? Theme.primaryHoverLight : (root.isActiveProfile(modelData) ? Theme.primaryPressed : Theme.surfaceLight) color: profileArea.containsMouse ? Theme.primaryHoverLight : (root.isActiveProfile(modelData) ? Theme.primaryPressed : Theme.surfaceLight)
border.color: root.isActiveProfile(modelData) ? Theme.primary : Theme.outlineLight border.color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.outlineLight
border.width: root.isActiveProfile(modelData) ? 2 : 1 border.width: root.isActiveProfile(modelData) ? 2 : 1
Row { Row {
@@ -465,7 +467,8 @@ PanelWindow {
DankIcon { DankIcon {
name: Theme.getPowerProfileIcon(modelData) name: Theme.getPowerProfileIcon(modelData)
size: Theme.iconSize size: Theme.iconSize
color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -476,8 +479,10 @@ PanelWindow {
StyledText { StyledText {
text: Theme.getPowerProfileLabel(modelData) text: Theme.getPowerProfileLabel(modelData)
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText color: root.isActiveProfile(
font.weight: root.isActiveProfile(modelData) ? Font.Medium : Font.Normal modelData) ? Theme.primary : Theme.surfaceText
font.weight: root.isActiveProfile(
modelData) ? Font.Medium : Font.Normal
} }
StyledText { StyledText {
@@ -485,9 +490,7 @@ PanelWindow {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium color: Theme.surfaceTextMedium
} }
} }
} }
MouseArea { MouseArea {
@@ -497,16 +500,12 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.setProfile(modelData); root.setProfile(modelData)
} }
} }
} }
} }
} }
} }
Rectangle { Rectangle {
@@ -516,7 +515,8 @@ PanelWindow {
color: Theme.errorHover color: Theme.errorHover
border.color: Theme.primarySelected border.color: Theme.primarySelected
border.width: 1 border.width: 1
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None visible: (typeof PowerProfiles !== "undefined")
&& PowerProfiles.degradationReason !== PerformanceDegradationReason.None
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -543,23 +543,18 @@ PanelWindow {
} }
StyledText { StyledText {
text: (typeof PowerProfiles !== "undefined") ? PerformanceDegradationReason.toString(PowerProfiles.degradationReason) : "" text: (typeof PowerProfiles
!== "undefined") ? PerformanceDegradationReason.toString(
PowerProfiles.degradationReason) : ""
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8) color: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.8)
} }
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -12,17 +12,18 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
signal clockClicked() signal clockClicked
width: clockRow.implicitWidth + Theme.spacingS * 2 width: clockRow.implicitWidth + Theme.spacingS * 2
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover; const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Component.onCompleted: { Component.onCompleted: {
root.currentDate = systemClock.date; root.currentDate = systemClock.date
} }
Row { Row {
@@ -32,7 +33,9 @@ Rectangle {
spacing: Theme.spacingS spacing: Theme.spacingS
StyledText { StyledText {
text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate, "H:mm") : Qt.formatTime(root.currentDate, "h:mm AP") text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate,
"H:mm") : Qt.formatTime(
root.currentDate, "h:mm AP")
font.pixelSize: Theme.fontSizeMedium - 1 font.pixelSize: Theme.fontSizeMedium - 1
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -53,7 +56,6 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode visible: !SettingsData.clockCompactMode
} }
} }
SystemClock { SystemClock {
@@ -71,13 +73,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
root.clockClicked(); root.clockClicked()
} }
} }
@@ -86,7 +90,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -11,20 +11,20 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
signal clicked() signal clicked
function getWiFiSignalIcon(signalStrength) { function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) { switch (signalStrength) {
case "excellent": case "excellent":
return "wifi"; return "wifi"
case "good": case "good":
return "wifi_2_bar"; return "wifi_2_bar"
case "fair": case "fair":
return "wifi_1_bar"; return "wifi_1_bar"
case "poor": case "poor":
return "signal_wifi_0_bar"; return "signal_wifi_0_bar"
default: default:
return "wifi"; return "wifi"
} }
} }
@@ -32,8 +32,10 @@ Rectangle {
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = controlCenterArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = controlCenterArea.containsMouse
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); || root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Row { Row {
@@ -45,11 +47,11 @@ Rectangle {
DankIcon { DankIcon {
name: { name: {
if (NetworkService.networkStatus === "ethernet") if (NetworkService.networkStatus === "ethernet")
return "lan"; return "lan"
else if (NetworkService.networkStatus === "wifi") else if (NetworkService.networkStatus === "wifi")
return getWiFiSignalIcon(NetworkService.wifiSignalStrength); return getWiFiSignalIcon(NetworkService.wifiSignalStrength)
else else
return "wifi_off"; return "wifi_off"
} }
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton color: NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
@@ -74,9 +76,13 @@ Rectangle {
DankIcon { DankIcon {
id: audioIcon id: audioIcon
name: (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted) ? "volume_off" : (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) < 33 ? "volume_down" : "volume_up" name: (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted) ? "volume_off" : (AudioService.sink
&& AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) < 33 ? "volume_down" : "volume_up"
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: audioWheelArea.containsMouse || controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText color: audioWheelArea.containsMouse || controlCenterArea.containsMouse
|| root.isActive ? Theme.primary : Theme.surfaceText
anchors.centerIn: parent anchors.centerIn: parent
} }
@@ -87,21 +93,21 @@ Rectangle {
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.NoButton acceptedButtons: Qt.NoButton
onWheel: function (wheelEvent) { onWheel: function (wheelEvent) {
let delta = wheelEvent.angleDelta.y; let delta = wheelEvent.angleDelta.y
let currentVolume = (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0; let currentVolume = (AudioService.sink && AudioService.sink.audio
let newVolume; && AudioService.sink.audio.volume * 100) || 0
let newVolume
if (delta > 0) if (delta > 0)
newVolume = Math.min(100, currentVolume + 5); newVolume = Math.min(100, currentVolume + 5)
else else
newVolume = Math.max(0, currentVolume - 5); newVolume = Math.max(0, currentVolume - 5)
if (AudioService.sink && AudioService.sink.audio) { if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false; AudioService.sink.audio.muted = false
AudioService.sink.audio.volume = newVolume / 100; AudioService.sink.audio.volume = newVolume / 100
} }
wheelEvent.accepted = true; wheelEvent.accepted = true
} }
} }
} }
DankIcon { DankIcon {
@@ -111,7 +117,6 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: false // TODO: Add mic detection visible: false // TODO: Add mic detection
} }
} }
MouseArea { MouseArea {
@@ -122,13 +127,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
root.clicked(); root.clicked()
} }
} }
@@ -137,7 +144,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -18,14 +18,15 @@ Rectangle {
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
MouseArea { MouseArea {
@@ -36,15 +37,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
SysMonitorService.setSortBy("cpu"); SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList) if (root.toggleProcessList)
root.toggleProcessList(); root.toggleProcessList()
} }
} }
@@ -57,29 +60,29 @@ Rectangle {
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: { color: {
if (SysMonitorService.cpuUsage > 80) if (SysMonitorService.cpuUsage > 80)
return Theme.tempDanger; return Theme.tempDanger
if (SysMonitorService.cpuUsage > 60) if (SysMonitorService.cpuUsage > 60)
return Theme.tempWarning; return Theme.tempWarning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: { text: {
if (SysMonitorService.cpuUsage === undefined || SysMonitorService.cpuUsage === null || SysMonitorService.cpuUsage === 0) { if (SysMonitorService.cpuUsage === undefined
return "--%"; || SysMonitorService.cpuUsage === null
|| SysMonitorService.cpuUsage === 0) {
return "--%"
} }
return SysMonitorService.cpuUsage.toFixed(0) + "%"; return SysMonitorService.cpuUsage.toFixed(0) + "%"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
} }

View File

@@ -18,14 +18,15 @@ Rectangle {
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
MouseArea { MouseArea {
@@ -36,15 +37,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
SysMonitorService.setSortBy("cpu"); SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList) if (root.toggleProcessList)
root.toggleProcessList(); root.toggleProcessList()
} }
} }
@@ -57,29 +60,30 @@ Rectangle {
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: { color: {
if (SysMonitorService.cpuTemperature > 85) if (SysMonitorService.cpuTemperature > 85)
return Theme.tempDanger; return Theme.tempDanger
if (SysMonitorService.cpuTemperature > 69) if (SysMonitorService.cpuTemperature > 69)
return Theme.tempWarning; return Theme.tempWarning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: { text: {
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) { if (SysMonitorService.cpuTemperature === undefined
return "--°"; || SysMonitorService.cpuTemperature === null
|| SysMonitorService.cpuTemperature < 0) {
return "--°"
} }
return Math.round(SysMonitorService.cpuTemperature) + "°"; return Math.round(SysMonitorService.cpuTemperature) + "°"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Behavior on color { Behavior on color {

View File

@@ -12,18 +12,24 @@ Rectangle {
readonly property int maxNormalWidth: 456 readonly property int maxNormalWidth: 456
readonly property int maxCompactWidth: 288 readonly property int maxCompactWidth: 288
width: compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth) width: compactMode ? Math.min(baseWidth,
maxCompactWidth) : Math.min(baseWidth,
maxNormalWidth)
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (!FocusedWindowService.focusedAppName && !FocusedWindowService.focusedWindowTitle) if (!FocusedWindowService.focusedAppName
return "transparent"; && !FocusedWindowService.focusedWindowTitle)
return "transparent"
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover; const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
clip: true clip: true
visible: FocusedWindowService.niriAvailable && (FocusedWindowService.focusedAppName || FocusedWindowService.focusedWindowTitle) visible: FocusedWindowService.niriAvailable
&& (FocusedWindowService.focusedAppName
|| FocusedWindowService.focusedWindowTitle)
Row { Row {
id: contentRow id: contentRow
@@ -65,7 +71,6 @@ Rectangle {
width: Math.min(implicitWidth, compactMode ? 180 : 250) width: Math.min(implicitWidth, compactMode ? 180 : 250)
visible: text.length > 0 visible: text.length > 0
} }
} }
MouseArea { MouseArea {
@@ -80,7 +85,6 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on width { Behavior on width {
@@ -88,7 +92,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -14,15 +14,17 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
property var widgetData: null property var widgetData: null
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0 property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex
!== undefined) ? widgetData.selectedGpuIndex : 0
Connections { Connections {
target: SettingsData target: SettingsData
function onWidgetDataChanged() { function onWidgetDataChanged() {
// Force property re-evaluation by triggering change detection // Force property re-evaluation by triggering change detection
root.selectedGpuIndex = Qt.binding(() => { root.selectedGpuIndex = Qt.binding(() => {
return (root.widgetData && root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0; return (root.widgetData
}); && root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0
})
} }
} }
@@ -30,22 +32,26 @@ Rectangle {
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
property real displayTemp: { property real displayTemp: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) return 0; if (!SysMonitorService.availableGpus
if (selectedGpuIndex >= 0 && selectedGpuIndex < SysMonitorService.availableGpus.length) { || SysMonitorService.availableGpus.length === 0)
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0; return 0
if (selectedGpuIndex >= 0
&& selectedGpuIndex < SysMonitorService.availableGpus.length) {
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0
} }
return 0; return 0
} }
MouseArea { MouseArea {
@@ -56,15 +62,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
SysMonitorService.setSortBy("cpu"); SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList) if (root.toggleProcessList)
root.toggleProcessList(); root.toggleProcessList()
} }
} }
@@ -77,29 +85,29 @@ Rectangle {
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: { color: {
if (root.displayTemp > 80) if (root.displayTemp > 80)
return Theme.tempDanger; return Theme.tempDanger
if (root.displayTemp > 65) if (root.displayTemp > 65)
return Theme.tempWarning; return Theme.tempWarning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: { text: {
if (root.displayTemp === undefined || root.displayTemp === null || root.displayTemp === 0) { if (root.displayTemp === undefined || root.displayTemp === null
return "--°"; || root.displayTemp === 0) {
return "--°"
} }
return Math.round(root.displayTemp) + "°"; return Math.round(root.displayTemp) + "°"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Behavior on color { Behavior on color {

View File

@@ -11,14 +11,16 @@ Rectangle {
property var popupTarget: null // Reference to the popup to position property var popupTarget: null // Reference to the popup to position
property var parentScreen: null // The screen this button is on property var parentScreen: null // The screen this button is on
signal clicked() signal clicked
width: 40 width: 40
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = launcherArea.containsMouse || isActive ? Theme.surfaceTextPressed : Theme.surfaceTextHover; const baseColor = launcherArea.containsMouse
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); || isActive ? Theme.surfaceTextPressed : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
SystemLogo { SystemLogo {
@@ -47,13 +49,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
root.clicked(); root.clicked()
} }
} }
@@ -62,7 +66,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -17,13 +17,14 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
signal clicked() signal clicked
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = Theme.surfaceTextHover; const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
states: [ states: [
State { State {
@@ -35,7 +36,6 @@ Rectangle {
opacity: 1 opacity: 1
width: SettingsData.mediaCompactMode ? compactContentWidth : normalContentWidth width: SettingsData.mediaCompactMode ? compactContentWidth : normalContentWidth
} }
}, },
State { State {
name: "hidden" name: "hidden"
@@ -46,7 +46,6 @@ Rectangle {
opacity: 0 opacity: 0
width: 0 width: 0
} }
} }
] ]
transitions: [ transitions: [
@@ -64,9 +63,7 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
}, },
Transition { Transition {
from: "hidden" from: "hidden"
@@ -77,7 +74,6 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
] ]
@@ -104,20 +100,24 @@ Rectangle {
visible: !SettingsData.mediaCompactMode visible: !SettingsData.mediaCompactMode
text: { text: {
if (!activePlayer || !activePlayer.trackTitle) if (!activePlayer || !activePlayer.trackTitle)
return ""; return ""
let identity = activePlayer.identity || ""; let identity = activePlayer.identity || ""
let isWebMedia = identity.toLowerCase().includes("firefox") || identity.toLowerCase().includes("chrome") || identity.toLowerCase().includes("chromium") || identity.toLowerCase().includes("edge") || identity.toLowerCase().includes("safari"); let isWebMedia = identity.toLowerCase().includes("firefox")
let title = ""; || identity.toLowerCase().includes(
let subtitle = ""; "chrome") || identity.toLowerCase().includes("chromium")
|| identity.toLowerCase().includes(
"edge") || identity.toLowerCase().includes("safari")
let title = ""
let subtitle = ""
if (isWebMedia && activePlayer.trackTitle) { if (isWebMedia && activePlayer.trackTitle) {
title = activePlayer.trackTitle; title = activePlayer.trackTitle
subtitle = activePlayer.trackArtist || identity; subtitle = activePlayer.trackArtist || identity
} else { } else {
title = activePlayer.trackTitle || "Unknown Track"; title = activePlayer.trackTitle || "Unknown Track"
subtitle = activePlayer.trackArtist || ""; subtitle = activePlayer.trackArtist || ""
} }
return subtitle.length > 0 ? title + " • " + subtitle : title; return subtitle.length > 0 ? title + " • " + subtitle : title
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
@@ -132,18 +132,18 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (root.popupTarget && root.popupTarget.setTriggerPosition) { if (root.popupTarget && root.popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = root.parentScreen || Screen; var currentScreen = root.parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
root.popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, root.width, root.section, currentScreen); root.popupTarget.setTriggerPosition(
relativeX, Theme.barHeight + Theme.spacingXS, root.width,
root.section, currentScreen)
} }
root.clicked(); root.clicked()
} }
} }
} }
} }
Row { Row {
@@ -174,11 +174,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (activePlayer) if (activePlayer)
activePlayer.previous(); activePlayer.previous()
} }
} }
} }
Rectangle { Rectangle {
@@ -186,15 +184,18 @@ Rectangle {
height: 24 height: 24
radius: 12 radius: 12
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: activePlayer && activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
visible: root.playerAvailable visible: root.playerAvailable
opacity: activePlayer ? 1 : 0.3 opacity: activePlayer ? 1 : 0.3
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: activePlayer && activePlayer.playbackState === 1 ? "pause" : "play_arrow" name: activePlayer
&& activePlayer.playbackState === 1 ? "pause" : "play_arrow"
size: 14 size: 14
color: activePlayer && activePlayer.playbackState === 1 ? Theme.background : Theme.primary color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.background : Theme.primary
} }
MouseArea { MouseArea {
@@ -203,11 +204,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (activePlayer) if (activePlayer)
activePlayer.togglePlaying(); activePlayer.togglePlaying()
} }
} }
} }
Rectangle { Rectangle {
@@ -234,15 +233,11 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (activePlayer) if (activePlayer)
activePlayer.next(); activePlayer.next()
} }
} }
} }
} }
} }
Behavior on color { Behavior on color {
@@ -250,7 +245,6 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on width { Behavior on width {
@@ -258,7 +252,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -11,21 +11,24 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
signal clicked() signal clicked
width: 40 width: 40
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = notificationArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = notificationArea.containsMouse
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); || root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: SessionData.doNotDisturb ? "notifications_off" : "notifications" name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
size: Theme.iconSize - 6 size: Theme.iconSize - 6
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText) color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse
|| root.isActive ? Theme.primary : Theme.surfaceText)
} }
Rectangle { Rectangle {
@@ -48,13 +51,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
root.clicked(); root.clicked()
} }
} }
@@ -63,7 +68,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -12,7 +12,8 @@ Rectangle {
property var parentScreen: null property var parentScreen: null
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
readonly property int activeCount: (PrivacyService.microphoneActive ? 1 : 0) + (PrivacyService.cameraActive ? 1 : 0) + (PrivacyService.screensharingActive ? 1 : 0) readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive
+ PrivacyService.screensharingActive
width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0 width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0
height: hasActivePrivacy ? 30 : 0 height: hasActivePrivacy ? 30 : 0
@@ -20,10 +21,12 @@ Rectangle {
visible: hasActivePrivacy visible: hasActivePrivacy
opacity: hasActivePrivacy ? 1 : 0 opacity: hasActivePrivacy ? 1 : 0
color: { color: Qt.rgba(
const baseColor = privacyArea.containsMouse ? Theme.errorPressed : Theme.errorHover; privacyArea.containsMouse ? Theme.errorPressed.r : Theme.errorHover.r,
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); privacyArea.containsMouse ? Theme.errorPressed.g : Theme.errorHover.g,
} privacyArea.containsMouse ? Theme.errorPressed.b : Theme.errorHover.b,
(privacyArea.containsMouse ? Theme.errorPressed.a : Theme.errorHover.a)
* Theme.widgetTransparency)
MouseArea { MouseArea {
id: privacyArea id: privacyArea
@@ -32,6 +35,7 @@ Rectangle {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
} }
} }
@@ -53,7 +57,6 @@ Rectangle {
filled: true filled: true
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
Item { Item {
@@ -81,7 +84,7 @@ Rectangle {
anchors.topMargin: -1 anchors.topMargin: -1
SequentialAnimation on opacity { SequentialAnimation on opacity {
running: parent.visible running: parent.visible && hasActivePrivacy
loops: Animation.Infinite loops: Animation.Infinite
NumberAnimation { NumberAnimation {
@@ -113,20 +116,13 @@ Rectangle {
} }
Behavior on width { Behavior on width {
enabled: hasActivePrivacy
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on opacity {
enabled: !hasActivePrivacy
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
Rectangle { Rectangle {
id: tooltip id: tooltip
@@ -136,8 +132,8 @@ Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
border.width: 1 border.width: 1
visible: privacyArea.containsMouse && hasActivePrivacy visible: false
opacity: visible ? 1 : 0 opacity: privacyArea.containsMouse && hasActivePrivacy ? 1 : 0
z: 100 z: 100
x: (parent.width - width) / 2 x: (parent.width - width) / 2
@@ -152,6 +148,7 @@ Rectangle {
} }
Behavior on opacity { Behavior on opacity {
enabled: hasActivePrivacy
NumberAnimation { NumberAnimation {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing

View File

@@ -18,14 +18,15 @@ Rectangle {
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover; const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Component.onCompleted: { Component.onCompleted: {
SysMonitorService.addRef(); SysMonitorService.addRef()
} }
Component.onDestruction: { Component.onDestruction: {
SysMonitorService.removeRef(); SysMonitorService.removeRef()
} }
MouseArea { MouseArea {
@@ -36,15 +37,17 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
SysMonitorService.setSortBy("memory"); SysMonitorService.setSortBy("memory")
if (root.toggleProcessList) if (root.toggleProcessList)
root.toggleProcessList(); root.toggleProcessList()
} }
} }
@@ -57,29 +60,29 @@ Rectangle {
size: Theme.iconSize - 8 size: Theme.iconSize - 8
color: { color: {
if (SysMonitorService.memoryUsage > 90) if (SysMonitorService.memoryUsage > 90)
return Theme.tempDanger; return Theme.tempDanger
if (SysMonitorService.memoryUsage > 75) if (SysMonitorService.memoryUsage > 75)
return Theme.tempWarning; return Theme.tempWarning
return Theme.surfaceText; return Theme.surfaceText
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: { text: {
if (SysMonitorService.memoryUsage === undefined || SysMonitorService.memoryUsage === null || SysMonitorService.memoryUsage === 0) { if (SysMonitorService.memoryUsage === undefined
return "--%"; || SysMonitorService.memoryUsage === null
|| SysMonitorService.memoryUsage === 0) {
return "--%"
} }
return SysMonitorService.memoryUsage.toFixed(0) + "%"; return SysMonitorService.memoryUsage.toFixed(0) + "%"
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
} }

View File

@@ -9,18 +9,21 @@ Rectangle {
property var parentWindow: null property var parentWindow: null
property var parentScreen: null property var parentScreen: null
readonly property int calculatedWidth: SystemTray.items.values.length > 0 ? SystemTray.items.values.length * 24 + (SystemTray.items.values.length - 1) * Theme.spacingXS + Theme.spacingS * 2 : 0 readonly property int calculatedWidth: SystemTray.items.values.length
> 0 ? SystemTray.items.values.length * 24
+ (SystemTray.items.values.length - 1)
* Theme.spacingXS + Theme.spacingS * 2 : 0
width: calculatedWidth width: calculatedWidth
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (SystemTray.items.values.length === 0) if (SystemTray.items.values.length === 0)
return "transparent"; return "transparent"
const baseColor = Theme.secondaryHover; const baseColor = Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
visible: SystemTray.items.values.length > 0 visible: SystemTray.items.values.length > 0
@@ -36,16 +39,20 @@ Rectangle {
delegate: Item { delegate: Item {
property var trayItem: modelData property var trayItem: modelData
property string iconSource: { property string iconSource: {
let icon = trayItem && trayItem.icon; let icon = trayItem && trayItem.icon
if (typeof icon === 'string' || icon instanceof String) { if (typeof icon === 'string' || icon instanceof String) {
if (icon.includes("?path=")) { if (icon.includes("?path=")) {
const [name, path] = icon.split("?path="); const split = icon.split("?path=")
const fileName = name.substring(name.lastIndexOf("/") + 1); if (split.length !== 2)
return `file://${path}/${fileName}`; return icon
const name = split[0]
const path = split[1]
const fileName = name.substring(name.lastIndexOf("/") + 1)
return `file://${path}/${fileName}`
} }
return icon; return icon
} }
return ""; return ""
} }
width: 24 width: 24
@@ -63,9 +70,7 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
Image { Image {
@@ -85,7 +90,7 @@ Rectangle {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => { onClicked: mouse => {
if (!trayItem) if (!trayItem)
return return
@@ -96,22 +101,20 @@ Rectangle {
var relativeX = globalPos.x - screenX var relativeX = globalPos.x - screenX
menuAnchor.menu = trayItem.menu menuAnchor.menu = trayItem.menu
menuAnchor.anchor.window = parentWindow menuAnchor.anchor.window = parentWindow
menuAnchor.anchor.rect = Qt.rect(relativeX, Theme.barHeight + Theme.spacingS, parent.width, 1) menuAnchor.anchor.rect = Qt.rect(
relativeX, Theme.barHeight + Theme.spacingS,
parent.width, 1)
menuAnchor.open() menuAnchor.open()
} else if (mouse.button === Qt.LeftButton) { } else if (mouse.button === Qt.LeftButton) {
trayItem.activate() trayItem.activate()
} }
} }
} }
} }
} }
} }
QsMenuAnchor { QsMenuAnchor {
id: menuAnchor id: menuAnchor
} }
} }

View File

@@ -25,27 +25,28 @@ PanelWindow {
implicitHeight: Theme.barHeight - 4 implicitHeight: Theme.barHeight - 4
color: "transparent" color: "transparent"
Component.onCompleted: { Component.onCompleted: {
let fonts = Qt.fontFamilies(); let fonts = Qt.fontFamilies()
if (fonts.indexOf("Material Symbols Rounded") === -1) if (fonts.indexOf("Material Symbols Rounded") === -1)
ToastService.showError("Please install Material Symbols Rounded and Restart your Shell. See README.md for instructions"); ToastService.showError(
"Please install Material Symbols Rounded and Restart your Shell. See README.md for instructions")
SettingsData.forceTopBarLayoutRefresh.connect(function () { SettingsData.forceTopBarLayoutRefresh.connect(function () {
Qt.callLater(() => { Qt.callLater(() => {
leftSection.visible = false; leftSection.visible = false
centerSection.visible = false; centerSection.visible = false
rightSection.visible = false; rightSection.visible = false
Qt.callLater(() => { Qt.callLater(() => {
leftSection.visible = true; leftSection.visible = true
centerSection.visible = true; centerSection.visible = true
rightSection.visible = true; rightSection.visible = true
}); })
}); })
}); })
} }
Connections { Connections {
function onTopBarTransparencyChanged() { function onTopBarTransparencyChanged() {
root.backgroundTransparency = SettingsData.topBarTransparency; root.backgroundTransparency = SettingsData.topBarTransparency
} }
target: SettingsData target: SettingsData
@@ -56,7 +57,7 @@ PanelWindow {
function onGeometryChanged() { function onGeometryChanged() {
// Re-layout center widgets when screen geometry changes // Re-layout center widgets when screen geometry changes
if (centerSection && centerSection.width > 0) { if (centerSection && centerSection.width > 0) {
Qt.callLater(centerSection.updateLayout); Qt.callLater(centerSection.updateLayout)
} }
} }
} }
@@ -84,7 +85,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: Theme.cornerRadiusXLarge radius: Theme.cornerRadiusXLarge
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, root.backgroundTransparency) color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, root.backgroundTransparency)
layer.enabled: true layer.enabled: true
Rectangle { Rectangle {
@@ -97,7 +99,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04) color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
Theme.surfaceTint.b, 0.04)
radius: parent.radius radius: parent.radius
SequentialAnimation on opacity { SequentialAnimation on opacity {
@@ -115,9 +118,7 @@ PanelWindow {
duration: Theme.extraLongDuration duration: Theme.extraLongDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
@@ -128,7 +129,6 @@ PanelWindow {
shadowColor: Qt.rgba(0, 0, 0, 0.15) shadowColor: Qt.rgba(0, 0, 0, 0.15)
shadowOpacity: 0.15 shadowOpacity: 0.15
} }
} }
Item { Item {
@@ -138,111 +138,125 @@ PanelWindow {
readonly property int launcherButtonWidth: 40 readonly property int launcherButtonWidth: 40
readonly property int workspaceSwitcherWidth: 120 // Approximate readonly property int workspaceSwitcherWidth: 120 // Approximate
readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2) readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth
+ focusedAppMaxWidth + (Theme.spacingXS * 2)
readonly property int rightSectionWidth: rightSection.width readonly property int rightSectionWidth: rightSection.width
readonly property int clockWidth: 120 // Approximate clock width readonly property int clockWidth: 120 // Approximate clock width
readonly property int mediaMaxWidth: 280 // Normal max width readonly property int mediaMaxWidth: 280 // Normal max width
readonly property int weatherWidth: 80 // Approximate weather width readonly property int weatherWidth: 80 // Approximate weather width
readonly property bool validLayout: availableWidth > 100 && estimatedLeftSectionWidth > 0 && rightSectionWidth > 0 readonly property bool validLayout: availableWidth > 100
&& estimatedLeftSectionWidth > 0
&& rightSectionWidth > 0
readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2 readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2
readonly property int clockRightEdge: clockLeftEdge + clockWidth readonly property int clockRightEdge: clockLeftEdge + clockWidth
readonly property int leftSectionRightEdge: estimatedLeftSectionWidth readonly property int leftSectionRightEdge: estimatedLeftSectionWidth
readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth - Theme.spacingS readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth - Theme.spacingS
readonly property int rightSectionLeftEdge: availableWidth - rightSectionWidth readonly property int rightSectionLeftEdge: availableWidth - rightSectionWidth
readonly property int leftToClockGap: Math.max(0, clockLeftEdge - leftSectionRightEdge) readonly property int leftToClockGap: Math.max(
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap 0,
clockLeftEdge - leftSectionRightEdge)
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(
0,
mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0 readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0
readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000 readonly property int clockToRightGap: validLayout ? Math.max(
readonly property bool spacingTight: validLayout && (leftToMediaGap < 150 || clockToRightGap < 100) 0,
readonly property bool overlapping: validLayout && (leftToMediaGap < 100 || clockToRightGap < 50) rightSectionLeftEdge
- clockRightEdge) : 1000
readonly property bool spacingTight: validLayout
&& (leftToMediaGap < 150
|| clockToRightGap < 100)
readonly property bool overlapping: validLayout
&& (leftToMediaGap < 100
|| clockToRightGap < 50)
function getWidgetEnabled(enabled) { function getWidgetEnabled(enabled) {
return enabled !== undefined ? enabled : true; return enabled !== undefined ? enabled : true
} }
function getWidgetVisible(widgetId) { function getWidgetVisible(widgetId) {
switch (widgetId) { switch (widgetId) {
case "launcherButton": case "launcherButton":
return true; return true
case "workspaceSwitcher": case "workspaceSwitcher":
return true; return true
case "focusedWindow": case "focusedWindow":
return true; return true
case "clock": case "clock":
return true; return true
case "music": case "music":
return true; return true
case "weather": case "weather":
return true; return true
case "systemTray": case "systemTray":
return true; return true
case "privacyIndicator": case "privacyIndicator":
return true; return true
case "clipboard": case "clipboard":
return true; return true
case "cpuUsage": case "cpuUsage":
return true; return true
case "memUsage": case "memUsage":
return true; return true
case "cpuTemp": case "cpuTemp":
return true; return true
case "gpuTemp": case "gpuTemp":
return true; return true
case "notificationButton": case "notificationButton":
return true; return true
case "battery": case "battery":
return true; return true
case "controlCenterButton": case "controlCenterButton":
return true; return true
case "spacer": case "spacer":
return true; return true
case "separator": case "separator":
return true; return true
default: default:
return false; return false
} }
} }
function getWidgetComponent(widgetId) { function getWidgetComponent(widgetId) {
switch (widgetId) { switch (widgetId) {
case "launcherButton": case "launcherButton":
return launcherButtonComponent; return launcherButtonComponent
case "workspaceSwitcher": case "workspaceSwitcher":
return workspaceSwitcherComponent; return workspaceSwitcherComponent
case "focusedWindow": case "focusedWindow":
return focusedWindowComponent; return focusedWindowComponent
case "clock": case "clock":
return clockComponent; return clockComponent
case "music": case "music":
return mediaComponent; return mediaComponent
case "weather": case "weather":
return weatherComponent; return weatherComponent
case "systemTray": case "systemTray":
return systemTrayComponent; return systemTrayComponent
case "privacyIndicator": case "privacyIndicator":
return privacyIndicatorComponent; return privacyIndicatorComponent
case "clipboard": case "clipboard":
return clipboardComponent; return clipboardComponent
case "cpuUsage": case "cpuUsage":
return cpuUsageComponent; return cpuUsageComponent
case "memUsage": case "memUsage":
return memUsageComponent; return memUsageComponent
case "cpuTemp": case "cpuTemp":
return cpuTempComponent; return cpuTempComponent
case "gpuTemp": case "gpuTemp":
return gpuTempComponent; return gpuTempComponent
case "notificationButton": case "notificationButton":
return notificationButtonComponent; return notificationButtonComponent
case "battery": case "battery":
return batteryComponent; return batteryComponent
case "controlCenterButton": case "controlCenterButton":
return controlCenterButtonComponent; return controlCenterButtonComponent
case "spacer": case "spacer":
return spacerComponent; return spacerComponent
case "separator": case "separator":
return separatorComponent; return separatorComponent
default: default:
return null; return null
} }
} }
@@ -274,9 +288,7 @@ PanelWindow {
sourceComponent: topBarContent.getWidgetComponent(model.widgetId) sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0 opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
} }
} }
} }
Item { Item {
@@ -290,71 +302,72 @@ PanelWindow {
function updateLayout() { function updateLayout() {
// Defer layout if dimensions are invalid // Defer layout if dimensions are invalid
if (width <= 0 || height <= 0 || !visible) { if (width <= 0 || height <= 0 || !visible) {
Qt.callLater(updateLayout); Qt.callLater(updateLayout)
return; return
} }
centerWidgets = []; centerWidgets = []
totalWidgets = 0; totalWidgets = 0
totalWidth = 0; totalWidth = 0
for (let i = 0; i < centerRepeater.count; i++) { for (var i = 0; i < centerRepeater.count; i++) {
let item = centerRepeater.itemAt(i); let item = centerRepeater.itemAt(i)
if (item && item.active && item.item) { if (item && item.active && item.item) {
centerWidgets.push(item.item); centerWidgets.push(item.item)
totalWidgets++; totalWidgets++
totalWidth += item.item.width; totalWidth += item.item.width
} }
} }
if (totalWidgets > 1) if (totalWidgets > 1)
totalWidth += spacing * (totalWidgets - 1); totalWidth += spacing * (totalWidgets - 1)
positionWidgets(); positionWidgets()
} }
function positionWidgets() { function positionWidgets() {
if (totalWidgets === 0 || width <= 0) if (totalWidgets === 0 || width <= 0)
return ; return
let parentCenterX = width / 2; let parentCenterX = width / 2
if (totalWidgets % 2 === 1) { if (totalWidgets % 2 === 1) {
let middleIndex = Math.floor(totalWidgets / 2); let middleIndex = Math.floor(totalWidgets / 2)
let currentX = parentCenterX - (centerWidgets[middleIndex].width / 2); let currentX = parentCenterX - (centerWidgets[middleIndex].width / 2)
centerWidgets[middleIndex].x = currentX; centerWidgets[middleIndex].x = currentX
centerWidgets[middleIndex].anchors.horizontalCenter = undefined; centerWidgets[middleIndex].anchors.horizontalCenter = undefined
currentX = centerWidgets[middleIndex].x; currentX = centerWidgets[middleIndex].x
for (let i = middleIndex - 1; i >= 0; i--) { for (var i = middleIndex - 1; i >= 0; i--) {
currentX -= (spacing + centerWidgets[i].width); currentX -= (spacing + centerWidgets[i].width)
centerWidgets[i].x = currentX; centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined; centerWidgets[i].anchors.horizontalCenter = undefined
} }
currentX = centerWidgets[middleIndex].x + centerWidgets[middleIndex].width; currentX = centerWidgets[middleIndex].x + centerWidgets[middleIndex].width
for (let i = middleIndex + 1; i < totalWidgets; i++) { for (var i = middleIndex + 1; i < totalWidgets; i++) {
currentX += spacing; currentX += spacing
centerWidgets[i].x = currentX; centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined; centerWidgets[i].anchors.horizontalCenter = undefined
currentX += centerWidgets[i].width; currentX += centerWidgets[i].width
} }
} else { } else {
let leftMiddleIndex = (totalWidgets / 2) - 1; let leftMiddleIndex = (totalWidgets / 2) - 1
let rightMiddleIndex = totalWidgets / 2; let rightMiddleIndex = totalWidgets / 2
let gapCenter = parentCenterX; let gapCenter = parentCenterX
let halfSpacing = spacing / 2; let halfSpacing = spacing / 2
centerWidgets[leftMiddleIndex].x = gapCenter - halfSpacing - centerWidgets[leftMiddleIndex].width; centerWidgets[leftMiddleIndex].x = gapCenter - halfSpacing
centerWidgets[leftMiddleIndex].anchors.horizontalCenter = undefined; - centerWidgets[leftMiddleIndex].width
centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing; centerWidgets[leftMiddleIndex].anchors.horizontalCenter = undefined
centerWidgets[rightMiddleIndex].anchors.horizontalCenter = undefined; centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing
let currentX = centerWidgets[leftMiddleIndex].x; centerWidgets[rightMiddleIndex].anchors.horizontalCenter = undefined
for (let i = leftMiddleIndex - 1; i >= 0; i--) { let currentX = centerWidgets[leftMiddleIndex].x
currentX -= (spacing + centerWidgets[i].width); for (var i = leftMiddleIndex - 1; i >= 0; i--) {
centerWidgets[i].x = currentX; currentX -= (spacing + centerWidgets[i].width)
centerWidgets[i].anchors.horizontalCenter = undefined; centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined
} }
currentX = centerWidgets[rightMiddleIndex].x + centerWidgets[rightMiddleIndex].width; currentX = centerWidgets[rightMiddleIndex].x + centerWidgets[rightMiddleIndex].width
for (let i = rightMiddleIndex + 1; i < totalWidgets; i++) { for (var i = rightMiddleIndex + 1; i < totalWidgets; i++) {
currentX += spacing; currentX += spacing
centerWidgets[i].x = currentX; centerWidgets[i].x = currentX
centerWidgets[i].anchors.horizontalCenter = undefined; centerWidgets[i].anchors.horizontalCenter = undefined
currentX += centerWidgets[i].width; currentX += centerWidgets[i].width
} }
} }
} }
@@ -364,19 +377,19 @@ PanelWindow {
anchors.centerIn: parent anchors.centerIn: parent
Component.onCompleted: { Component.onCompleted: {
Qt.callLater(() => { Qt.callLater(() => {
Qt.callLater(updateLayout); Qt.callLater(updateLayout)
}); })
} }
onWidthChanged: { onWidthChanged: {
if (width > 0) { if (width > 0) {
Qt.callLater(updateLayout); Qt.callLater(updateLayout)
} }
} }
onVisibleChanged: { onVisibleChanged: {
if (visible && width > 0) { if (visible && width > 0) {
Qt.callLater(updateLayout); Qt.callLater(updateLayout)
} }
} }
@@ -396,30 +409,28 @@ PanelWindow {
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0 opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
onLoaded: { onLoaded: {
if (item) { if (item) {
item.onWidthChanged.connect(centerSection.updateLayout); item.onWidthChanged.connect(centerSection.updateLayout)
if (model.widgetId === "spacer") if (model.widgetId === "spacer")
item.spacerSize = Qt.binding(() => { item.spacerSize = Qt.binding(() => {
return model.size || 20; return model.size || 20
}); })
Qt.callLater(centerSection.updateLayout); Qt.callLater(centerSection.updateLayout)
} }
} }
onActiveChanged: { onActiveChanged: {
Qt.callLater(centerSection.updateLayout); Qt.callLater(centerSection.updateLayout)
} }
} }
} }
Connections { Connections {
function onCountChanged() { function onCountChanged() {
Qt.callLater(centerSection.updateLayout); Qt.callLater(centerSection.updateLayout)
} }
target: SettingsData.topBarCenterWidgetsModel target: SettingsData.topBarCenterWidgetsModel
} }
} }
Row { Row {
@@ -443,9 +454,7 @@ PanelWindow {
sourceComponent: topBarContent.getWidgetComponent(model.widgetId) sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0 opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
} }
} }
} }
Component { Component {
@@ -456,20 +465,22 @@ PanelWindow {
section: { section: {
// Determine which section this loader is in by checking parent // Determine which section this loader is in by checking parent
if (parent && parent.parent) { if (parent && parent.parent) {
if (parent.parent === leftSection) return "left"; if (parent.parent === leftSection)
if (parent.parent === rightSection) return "right"; return "left"
if (parent.parent === centerSection) return "center"; if (parent.parent === rightSection)
return "right"
if (parent.parent === centerSection)
return "center"
} }
return "left"; // default fallback return "left" // default fallback
} }
popupTarget: appDrawerPopout popupTarget: appDrawerPopout
parentScreen: root.screen parentScreen: root.screen
onClicked: { onClicked: {
if (appDrawerPopout) if (appDrawerPopout)
appDrawerPopout.toggle(); appDrawerPopout.toggle()
} }
} }
} }
Component { Component {
@@ -478,7 +489,6 @@ PanelWindow {
WorkspaceSwitcher { WorkspaceSwitcher {
screenName: root.screenName screenName: root.screenName
} }
} }
Component { Component {
@@ -488,7 +498,6 @@ PanelWindow {
compactMode: topBarContent.spacingTight compactMode: topBarContent.spacingTight
availableWidth: topBarContent.leftToMediaGap availableWidth: topBarContent.leftToMediaGap
} }
} }
Component { Component {
@@ -497,18 +506,20 @@ PanelWindow {
Clock { Clock {
compactMode: topBarContent.overlapping compactMode: topBarContent.overlapping
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "center"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "center"
} }
popupTarget: centcomPopout popupTarget: centcomPopout
parentScreen: root.screen parentScreen: root.screen
onClockClicked: { onClockClicked: {
centcomPopout.calendarVisible = !centcomPopout.calendarVisible; centcomPopout.calendarVisible = !centcomPopout.calendarVisible
} }
} }
} }
Component { Component {
@@ -517,18 +528,20 @@ PanelWindow {
Media { Media {
compactMode: topBarContent.spacingTight || topBarContent.overlapping compactMode: topBarContent.spacingTight || topBarContent.overlapping
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "center"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "center"
} }
popupTarget: centcomPopout popupTarget: centcomPopout
parentScreen: root.screen parentScreen: root.screen
onClicked: { onClicked: {
centcomPopout.calendarVisible = !centcomPopout.calendarVisible; centcomPopout.calendarVisible = !centcomPopout.calendarVisible
} }
} }
} }
Component { Component {
@@ -536,18 +549,20 @@ PanelWindow {
Weather { Weather {
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "center"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "center"
} }
popupTarget: centcomPopout popupTarget: centcomPopout
parentScreen: root.screen parentScreen: root.screen
onClicked: { onClicked: {
centcomPopout.calendarVisible = !centcomPopout.calendarVisible; centcomPopout.calendarVisible = !centcomPopout.calendarVisible
} }
} }
} }
Component { Component {
@@ -557,7 +572,6 @@ PanelWindow {
parentWindow: root parentWindow: root
parentScreen: root.screen parentScreen: root.screen
} }
} }
Component { Component {
@@ -565,14 +579,16 @@ PanelWindow {
PrivacyIndicator { PrivacyIndicator {
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
parentScreen: root.screen parentScreen: root.screen
} }
} }
Component { Component {
@@ -583,8 +599,9 @@ PanelWindow {
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover; const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
DankIcon { DankIcon {
@@ -601,7 +618,7 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
clipboardHistoryModalPopup.toggle(); clipboardHistoryModalPopup.toggle()
} }
} }
@@ -610,11 +627,8 @@ PanelWindow {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }
} }
Component { Component {
@@ -622,18 +636,20 @@ PanelWindow {
CpuMonitor { CpuMonitor {
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: processListPopout popupTarget: processListPopout
parentScreen: root.screen parentScreen: root.screen
toggleProcessList: () => { toggleProcessList: () => {
return processListPopout.toggle(); return processListPopout.toggle()
} }
} }
} }
Component { Component {
@@ -641,18 +657,20 @@ PanelWindow {
RamMonitor { RamMonitor {
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: processListPopout popupTarget: processListPopout
parentScreen: root.screen parentScreen: root.screen
toggleProcessList: () => { toggleProcessList: () => {
return processListPopout.toggle(); return processListPopout.toggle()
} }
} }
} }
Component { Component {
@@ -660,18 +678,20 @@ PanelWindow {
CpuTemperature { CpuTemperature {
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: processListPopout popupTarget: processListPopout
parentScreen: root.screen parentScreen: root.screen
toggleProcessList: () => { toggleProcessList: () => {
return processListPopout.toggle(); return processListPopout.toggle()
} }
} }
} }
Component { Component {
@@ -679,19 +699,21 @@ PanelWindow {
GpuTemperature { GpuTemperature {
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: processListPopout popupTarget: processListPopout
parentScreen: root.screen parentScreen: root.screen
widgetData: parent.widgetData widgetData: parent.widgetData
toggleProcessList: () => { toggleProcessList: () => {
return processListPopout.toggle(); return processListPopout.toggle()
} }
} }
} }
Component { Component {
@@ -701,18 +723,21 @@ PanelWindow {
hasUnread: root.notificationCount > 0 hasUnread: root.notificationCount > 0
isActive: notificationCenter.notificationHistoryVisible isActive: notificationCenter.notificationHistoryVisible
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: notificationCenter popupTarget: notificationCenter
parentScreen: root.screen parentScreen: root.screen
onClicked: { onClicked: {
notificationCenter.notificationHistoryVisible = !notificationCenter.notificationHistoryVisible; notificationCenter.notificationHistoryVisible
= !notificationCenter.notificationHistoryVisible
} }
} }
} }
Component { Component {
@@ -721,18 +746,20 @@ PanelWindow {
Battery { Battery {
batteryPopupVisible: batteryPopout.batteryPopupVisible batteryPopupVisible: batteryPopout.batteryPopupVisible
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: batteryPopout popupTarget: batteryPopout
parentScreen: root.screen parentScreen: root.screen
onToggleBatteryPopup: { onToggleBatteryPopup: {
batteryPopout.batteryPopupVisible = !batteryPopout.batteryPopupVisible; batteryPopout.batteryPopupVisible = !batteryPopout.batteryPopupVisible
} }
} }
} }
Component { Component {
@@ -741,24 +768,25 @@ PanelWindow {
ControlCenterButton { ControlCenterButton {
isActive: controlCenterPopout.controlCenterVisible isActive: controlCenterPopout.controlCenterVisible
section: { section: {
if (parent && parent.parent === leftSection) return "left"; if (parent && parent.parent === leftSection)
if (parent && parent.parent === rightSection) return "right"; return "left"
if (parent && parent.parent === centerSection) return "center"; if (parent && parent.parent === rightSection)
return "right"; return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
} }
popupTarget: controlCenterPopout popupTarget: controlCenterPopout
parentScreen: root.screen parentScreen: root.screen
onClicked: { onClicked: {
controlCenterPopout.triggerScreen = root.screen; controlCenterPopout.triggerScreen = root.screen
controlCenterPopout.controlCenterVisible = !controlCenterPopout.controlCenterVisible; controlCenterPopout.controlCenterVisible = !controlCenterPopout.controlCenterVisible
if (controlCenterPopout.controlCenterVisible) { if (controlCenterPopout.controlCenterVisible) {
if (NetworkService.wifiEnabled) if (NetworkService.wifiEnabled)
NetworkService.scanWifi(); NetworkService.scanWifi()
} }
} }
} }
} }
Component { Component {
@@ -771,7 +799,8 @@ PanelWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "transparent" color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1)
border.width: 1 border.width: 1
radius: 2 radius: 2
visible: false visible: false
@@ -782,11 +811,8 @@ PanelWindow {
onEntered: parent.visible = true onEntered: parent.visible = true
onExited: parent.visible = false onExited: parent.visible = false
} }
} }
} }
} }
Component { Component {
@@ -798,11 +824,7 @@ PanelWindow {
color: Theme.outline color: Theme.outline
opacity: 0.3 opacity: 0.3
} }
} }
} }
} }
} }

View File

@@ -10,15 +10,17 @@ Rectangle {
property var popupTarget: null property var popupTarget: null
property var parentScreen: null property var parentScreen: null
signal clicked() signal clicked
visible: SettingsData.weatherEnabled visible: SettingsData.weatherEnabled
width: visible ? Math.min(100, weatherRow.implicitWidth + Theme.spacingS * 2) : 0 width: visible ? Math.min(100,
weatherRow.implicitWidth + Theme.spacingS * 2) : 0
height: 30 height: 30
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover; const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
Ref { Ref {
@@ -40,17 +42,16 @@ Rectangle {
StyledText { StyledText {
text: { text: {
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp; var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp
if (temp === undefined || temp === null || temp === 0) { if (temp === undefined || temp === null || temp === 0) {
return "--°" + (SettingsData.useFahrenheit ? "F" : "C"); return "--°" + (SettingsData.useFahrenheit ? "F" : "C")
} }
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C"); return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C")
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
MouseArea { MouseArea {
@@ -61,13 +62,15 @@ Rectangle {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) { if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0); var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen; var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0; var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX; var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
} }
root.clicked(); root.clicked()
} }
} }
@@ -76,7 +79,6 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
Behavior on width { Behavior on width {
@@ -84,7 +86,5 @@ Rectangle {
duration: Theme.shortDuration duration: Theme.shortDuration
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -11,72 +11,83 @@ Rectangle {
property string screenName: "" property string screenName: ""
property int currentWorkspace: getDisplayActiveWorkspace() property int currentWorkspace: getDisplayActiveWorkspace()
property var workspaceList: { property var workspaceList: {
var baseList = getDisplayWorkspaces(); var baseList = getDisplayWorkspaces()
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList; return SettingsData.showWorkspacePadding ? padWorkspaces(
baseList) : baseList
} }
function padWorkspaces(list) { function padWorkspaces(list) {
var padded = list.slice(); var padded = list.slice()
while (padded.length < 3)padded.push(-1) // Use -1 as a placeholder while (padded.length < 3)
return padded; padded.push(-1) // Use -1 as a placeholder
return padded
} }
function getDisplayWorkspaces() { function getDisplayWorkspaces() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0) if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return [1, 2]; return [1, 2]
if (!root.screenName) if (!root.screenName)
return NiriService.getCurrentOutputWorkspaceNumbers(); return NiriService.getCurrentOutputWorkspaceNumbers()
var displayWorkspaces = []; var displayWorkspaces = []
for (var i = 0; i < NiriService.allWorkspaces.length; i++) { for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i]; var ws = NiriService.allWorkspaces[i]
if (ws.output === root.screenName) if (ws.output === root.screenName)
displayWorkspaces.push(ws.idx + 1); displayWorkspaces.push(ws.idx + 1)
} }
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]; return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]
} }
function getDisplayActiveWorkspace() { function getDisplayActiveWorkspace() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0) if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return 1; return 1
if (!root.screenName) if (!root.screenName)
return NiriService.getCurrentWorkspaceNumber(); return NiriService.getCurrentWorkspaceNumber()
for (var i = 0; i < NiriService.allWorkspaces.length; i++) { for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i]; var ws = NiriService.allWorkspaces[i]
if (ws.output === root.screenName && ws.is_active) if (ws.output === root.screenName && ws.is_active)
return ws.idx + 1; return ws.idx + 1
} }
return 1; return 1
} }
width: SettingsData.showWorkspacePadding ? Math.max(120, workspaceRow.implicitWidth + Theme.spacingL * 2) : workspaceRow.implicitWidth + Theme.spacingL * 2 width: SettingsData.showWorkspacePadding ? Math.max(
120,
workspaceRow.implicitWidth + Theme.spacingL
* 2) : workspaceRow.implicitWidth
+ Theme.spacingL * 2
height: 30 height: 30
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
color: { color: {
const baseColor = Theme.surfaceTextHover; const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency); return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
} }
visible: NiriService.niriAvailable visible: NiriService.niriAvailable
Connections { Connections {
function onAllWorkspacesChanged() { function onAllWorkspacesChanged() {
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces(); root.workspaceList
root.currentWorkspace = root.getDisplayActiveWorkspace(); = SettingsData.showWorkspacePadding ? root.padWorkspaces(
root.getDisplayWorkspaces(
)) : root.getDisplayWorkspaces()
root.currentWorkspace = root.getDisplayActiveWorkspace()
} }
function onFocusedWorkspaceIndexChanged() { function onFocusedWorkspaceIndexChanged() {
root.currentWorkspace = root.getDisplayActiveWorkspace(); root.currentWorkspace = root.getDisplayActiveWorkspace()
} }
function onNiriAvailableChanged() { function onNiriAvailableChanged() {
if (NiriService.niriAvailable) { if (NiriService.niriAvailable) {
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces(); root.workspaceList
root.currentWorkspace = root.getDisplayActiveWorkspace(); = SettingsData.showWorkspacePadding ? root.padWorkspaces(
root.getDisplayWorkspaces(
)) : root.getDisplayWorkspaces()
root.currentWorkspace = root.getDisplayActiveWorkspace()
} }
} }
@@ -85,8 +96,9 @@ Rectangle {
Connections { Connections {
function onShowWorkspacePaddingChanged() { function onShowWorkspacePaddingChanged() {
var baseList = root.getDisplayWorkspaces(); var baseList = root.getDisplayWorkspaces()
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(baseList) : baseList; root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(
baseList) : baseList
} }
target: SettingsData target: SettingsData
@@ -121,8 +133,7 @@ Rectangle {
enabled: !isPlaceholder enabled: !isPlaceholder
onClicked: { onClicked: {
if (!isPlaceholder) if (!isPlaceholder)
NiriService.switchToWorkspace(modelData - 1); NiriService.switchToWorkspace(modelData - 1)
} }
} }
@@ -130,7 +141,11 @@ Rectangle {
visible: SettingsData.showWorkspaceIndex visible: SettingsData.showWorkspaceIndex
anchors.centerIn: parent anchors.centerIn: parent
text: isPlaceholder ? sequentialNumber : sequentialNumber text: isPlaceholder ? sequentialNumber : sequentialNumber
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium color: isActive ? Qt.rgba(
Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal
} }
@@ -140,7 +155,6 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on color { Behavior on color {
@@ -148,13 +162,8 @@ Rectangle {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
} }
} }
} }

View File

@@ -14,14 +14,13 @@ PanelWindow {
property bool volumePopupVisible: false property bool volumePopupVisible: false
function show() { function show() {
root.volumePopupVisible = true; root.volumePopupVisible = true
hideTimer.restart(); hideTimer.restart()
} }
function resetHideTimer() { function resetHideTimer() {
if (root.volumePopupVisible) if (root.volumePopupVisible)
hideTimer.restart(); hideTimer.restart()
} }
screen: modelData screen: modelData
@@ -45,21 +44,20 @@ PanelWindow {
repeat: false repeat: false
onTriggered: { onTriggered: {
if (!volumePopup.containsMouse) if (!volumePopup.containsMouse)
root.volumePopupVisible = false; root.volumePopupVisible = false
else else
hideTimer.restart(); hideTimer.restart()
} }
} }
Connections { Connections {
function onVolumeChanged() { function onVolumeChanged() {
root.show(); root.show()
} }
function onSinkChanged() { function onSinkChanged() {
if (root.volumePopupVisible) if (root.volumePopupVisible)
root.show(); root.show()
} }
target: AudioService target: AudioService
@@ -77,7 +75,8 @@ PanelWindow {
anchors.bottomMargin: Theme.spacingM anchors.bottomMargin: Theme.spacingM
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: root.volumePopupVisible ? 1 : 0 opacity: root.volumePopupVisible ? 1 : 0
scale: root.volumePopupVisible ? 1 : 0.9 scale: root.volumePopupVisible ? 1 : 0.9
@@ -106,7 +105,8 @@ PanelWindow {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted ? "volume_off" : "volume_up" name: AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted ? "volume_off" : "volume_up"
size: Theme.iconSize size: Theme.iconSize
color: muteButton.containsMouse ? Theme.primary : Theme.surfaceText color: muteButton.containsMouse ? Theme.primary : Theme.surfaceText
} }
@@ -118,11 +118,10 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
AudioService.toggleMute(); AudioService.toggleMute()
root.resetHideTimer(); root.resetHideTimer()
} }
} }
} }
DankSlider { DankSlider {
@@ -139,28 +138,26 @@ PanelWindow {
unit: "%" unit: "%"
Component.onCompleted: { Component.onCompleted: {
if (AudioService.sink && AudioService.sink.audio) if (AudioService.sink && AudioService.sink.audio)
value = Math.round(AudioService.sink.audio.volume * 100); value = Math.round(AudioService.sink.audio.volume * 100)
} }
onSliderValueChanged: function (newValue) { onSliderValueChanged: function (newValue) {
if (AudioService.sink && AudioService.sink.audio) { if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.volume = newValue / 100; AudioService.sink.audio.volume = newValue / 100
root.resetHideTimer(); root.resetHideTimer()
} }
} }
Connections { Connections {
function onVolumeChanged() { function onVolumeChanged() {
volumeSlider.value = Math.round(AudioService.sink.audio.volume * 100); volumeSlider.value = Math.round(
AudioService.sink.audio.volume * 100)
} }
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null target: AudioService.sink
&& AudioService.sink.audio ? AudioService.sink.audio : null
} }
} }
} }
} }
MouseArea { MouseArea {
@@ -191,7 +188,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on scale { Behavior on scale {
@@ -199,7 +195,6 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
Behavior on transform { Behavior on transform {
@@ -207,13 +202,10 @@ PanelWindow {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
} }
mask: Region { mask: Region {
item: volumePopup item: volumePopup
} }
} }

View File

@@ -37,11 +37,11 @@ LazyLoader {
onSourceChanged: { onSourceChanged: {
if (!source) if (!source)
current = null; current = null
else if (current === one) else if (current === one)
two.update(); two.update()
else else
one.update(); one.update()
} }
Loader { Loader {
@@ -96,8 +96,8 @@ LazyLoader {
id: img id: img
function update(): void { function update(): void {
source = ""; source = ""
source = root.source; source = root.source
} }
anchors.fill: parent anchors.fill: parent
@@ -110,7 +110,7 @@ LazyLoader {
onStatusChanged: { onStatusChanged: {
if (status === Image.Ready) if (status === Image.Ready)
root.current = this; root.current = this
} }
states: State { states: State {

View File

@@ -1,5 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick import QtQuick
import Quickshell import Quickshell
@@ -13,9 +14,13 @@ Singleton {
property var applications: DesktopEntries.applications.values property var applications: DesktopEntries.applications.values
property var preppedApps: applications.map(app => ({ property var preppedApps: applications.map(app => ({
name: Fuzzy.prepare(app.name || ""), "name": Fuzzy.prepare(
comment: Fuzzy.prepare(app.comment || ""), app.name
entry: app || ""),
"comment": Fuzzy.prepare(
app.comment
|| ""),
"entry": app
})) }))
function searchApplications(query) { function searchApplications(query) {
@@ -28,9 +33,9 @@ Singleton {
} }
var results = Fuzzy.go(query, preppedApps, { var results = Fuzzy.go(query, preppedApps, {
all: false, "all": false,
keys: ["name", "comment"], "keys": ["name", "comment"],
scoreFn: r => { "scoreFn": r => {
var nameScore = r[0] ? r[0].score : 0 var nameScore = r[0] ? r[0].score : 0
var commentScore = r[1] ? r[1].score : 0 var commentScore = r[1] ? r[1].score : 0
var appName = r.obj.entry.name || "" var appName = r.obj.entry.name || ""
@@ -42,17 +47,17 @@ Singleton {
if (nameLower === queryLower) { if (nameLower === queryLower) {
finalScore = nameScore * 100 finalScore = nameScore * 100
} } else if (nameLower.startsWith(queryLower)) {
else if (nameLower.startsWith(queryLower)) {
finalScore = nameScore * 50 finalScore = nameScore * 50
} } else if (nameLower.includes(" " + queryLower)
else if (nameLower.includes(" " + queryLower) || nameLower.includes(queryLower + " ") || nameLower.endsWith(" " + queryLower)) { || nameLower.includes(
queryLower + " ")
|| nameLower.endsWith(
" " + queryLower)) {
finalScore = nameScore * 25 finalScore = nameScore * 25
} } else if (nameLower.includes(queryLower)) {
else if (nameLower.includes(queryLower)) {
finalScore = nameScore * 10 finalScore = nameScore * 10
} } else {
else {
finalScore = nameScore * 2 + commentScore * 0.1 finalScore = nameScore * 2 + commentScore * 0.1
} }
} else { } else {
@@ -61,16 +66,15 @@ Singleton {
return finalScore return finalScore
}, },
limit: 50 "limit": 50
}) })
return results.map(r => r.obj.entry) return results.map(r => r.obj.entry)
} }
function getCategoriesForApp(app) { function getCategoriesForApp(app) {
if (!app || !app.categories) return [] if (!app || !app.categories)
return []
var categoryMap = { var categoryMap = {
"AudioVideo": "Media", "AudioVideo": "Media",
@@ -150,5 +154,4 @@ Singleton {
return appCategories.includes(category) return appCategories.includes(category)
}) })
} }
} }

Some files were not shown because too many files have changed in this diff Show More