mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-29 16:02:51 -05:00
Compare commits
33 Commits
623eec3689
...
stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7cdb39b0b | ||
|
|
0ceba92a23 | ||
|
|
4daa7a4c88 | ||
|
|
cc4a6a5899 | ||
|
|
994947477c | ||
|
|
311817ee97 | ||
|
|
b80c73f9b9 | ||
|
|
a85101c099 | ||
|
|
3513d57e06 | ||
|
|
1234847abb | ||
|
|
0ed595b43d | ||
|
|
060cbefc79 | ||
|
|
e022c04519 | ||
|
|
f534384e5e | ||
|
|
a25cdb43d5 | ||
|
|
4e9b4ca400 | ||
|
|
5bab1c98b1 | ||
|
|
2284bb002f | ||
|
|
b0611d6104 | ||
|
|
27965862d6 | ||
|
|
e74a901e05 | ||
|
|
77794deb2c | ||
|
|
1c10746e50 | ||
|
|
8ecb7282b9 | ||
|
|
9b3fa804ab | ||
|
|
b2ad31a27e | ||
|
|
db17e4cb14 | ||
|
|
1b7dcf56a8 | ||
|
|
502bb88e92 | ||
|
|
b76d0ce97d | ||
|
|
fa66d330cf | ||
|
|
157eab2d07 | ||
|
|
f50ad2dc22 |
78
.github/workflows/run-obs.yml
vendored
78
.github/workflows/run-obs.yml
vendored
@@ -4,14 +4,13 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
package:
|
package:
|
||||||
description: "Package to update"
|
description: "Package to update (dms, dms-git, or all)"
|
||||||
required: true
|
required: false
|
||||||
type: choice
|
default: "all"
|
||||||
options:
|
tag_version:
|
||||||
- dms
|
description: "Specific tag version for dms stable (e.g., v1.0.2). Leave empty to auto-detect latest release."
|
||||||
- dms-git
|
required: false
|
||||||
- all
|
default: ""
|
||||||
default: "dms"
|
|
||||||
rebuild_release:
|
rebuild_release:
|
||||||
description: "Release number for rebuilds (e.g., 2, 3, 4 to increment spec Release)"
|
description: "Release number for rebuilds (e.g., 2, 3, 4 to increment spec Release)"
|
||||||
required: false
|
required: false
|
||||||
@@ -57,9 +56,8 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Helper function to check dms stable tag
|
# Helper function to check dms stable tag
|
||||||
# Sets LATEST_TAG variable in parent scope if update needed
|
|
||||||
check_dms_stable() {
|
check_dms_stable() {
|
||||||
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "")
|
local LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "v\?\([^"]*\)".*/\1/' || echo "")
|
||||||
local OBS_SPEC=$(curl -s -u "$OBS_USERNAME:$OBS_PASSWORD" "https://api.opensuse.org/source/home:AvengeMedia:dms/dms/dms.spec" 2>/dev/null || echo "")
|
local OBS_SPEC=$(curl -s -u "$OBS_USERNAME:$OBS_PASSWORD" "https://api.opensuse.org/source/home:AvengeMedia:dms/dms/dms.spec" 2>/dev/null || echo "")
|
||||||
local OBS_VERSION=$(echo "$OBS_SPEC" | grep "^Version:" | awk '{print $2}' | xargs || echo "")
|
local OBS_VERSION=$(echo "$OBS_SPEC" | grep "^Version:" | awk '{print $2}' | xargs || echo "")
|
||||||
|
|
||||||
@@ -75,8 +73,8 @@ jobs:
|
|||||||
# Main logic
|
# Main logic
|
||||||
REBUILD="${{ github.event.inputs.rebuild_release }}"
|
REBUILD="${{ github.event.inputs.rebuild_release }}"
|
||||||
|
|
||||||
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
||||||
# Tag selected or pushed - always update stable package
|
# Tag push - always update stable package
|
||||||
echo "packages=dms" >> $GITHUB_OUTPUT
|
echo "packages=dms" >> $GITHUB_OUTPUT
|
||||||
VERSION="${GITHUB_REF#refs/tags/}"
|
VERSION="${GITHUB_REF#refs/tags/}"
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
@@ -106,12 +104,7 @@ jobs:
|
|||||||
# Check each package and build list of those needing updates
|
# Check each package and build list of those needing updates
|
||||||
PACKAGES_TO_UPDATE=()
|
PACKAGES_TO_UPDATE=()
|
||||||
check_dms_git && PACKAGES_TO_UPDATE+=("dms-git")
|
check_dms_git && PACKAGES_TO_UPDATE+=("dms-git")
|
||||||
if check_dms_stable; then
|
check_dms_stable && PACKAGES_TO_UPDATE+=("dms")
|
||||||
PACKAGES_TO_UPDATE+=("dms")
|
|
||||||
if [[ -n "$LATEST_TAG" ]]; then
|
|
||||||
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${#PACKAGES_TO_UPDATE[@]} -gt 0 ]]; then
|
if [[ ${#PACKAGES_TO_UPDATE[@]} -gt 0 ]]; then
|
||||||
echo "packages=${PACKAGES_TO_UPDATE[*]}" >> $GITHUB_OUTPUT
|
echo "packages=${PACKAGES_TO_UPDATE[*]}" >> $GITHUB_OUTPUT
|
||||||
@@ -136,9 +129,6 @@ jobs:
|
|||||||
if check_dms_stable; then
|
if check_dms_stable; then
|
||||||
echo "packages=$PKG" >> $GITHUB_OUTPUT
|
echo "packages=$PKG" >> $GITHUB_OUTPUT
|
||||||
echo "has_updates=true" >> $GITHUB_OUTPUT
|
echo "has_updates=true" >> $GITHUB_OUTPUT
|
||||||
if [[ -n "$LATEST_TAG" ]]; then
|
|
||||||
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
echo "packages=" >> $GITHUB_OUTPUT
|
echo "packages=" >> $GITHUB_OUTPUT
|
||||||
echo "has_updates=false" >> $GITHUB_OUTPUT
|
echo "has_updates=false" >> $GITHUB_OUTPUT
|
||||||
@@ -171,19 +161,12 @@ jobs:
|
|||||||
- name: Determine packages to update
|
- name: Determine packages to update
|
||||||
id: packages
|
id: packages
|
||||||
run: |
|
run: |
|
||||||
# Check if GITHUB_REF points to a tag (works for both push events and workflow_dispatch with tag selected)
|
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
||||||
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
# Tag push event - use the pushed tag
|
||||||
# Tag selected or pushed - use the tag from GITHUB_REF
|
|
||||||
echo "packages=dms" >> $GITHUB_OUTPUT
|
echo "packages=dms" >> $GITHUB_OUTPUT
|
||||||
VERSION="${GITHUB_REF#refs/tags/}"
|
VERSION="${GITHUB_REF#refs/tags/}"
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
echo "Using tag from GITHUB_REF: $VERSION"
|
echo "Triggered by tag: $VERSION"
|
||||||
# Check if check-updates already determined a version (from auto-detection)
|
|
||||||
elif [[ -n "${{ needs.check-updates.outputs.version }}" ]]; then
|
|
||||||
# Use version from check-updates job
|
|
||||||
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
|
||||||
echo "version=${{ needs.check-updates.outputs.version }}" >> $GITHUB_OUTPUT
|
|
||||||
echo "Using version from check-updates: ${{ needs.check-updates.outputs.version }}"
|
|
||||||
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
|
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
|
||||||
# Scheduled run - dms-git only
|
# Scheduled run - dms-git only
|
||||||
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
||||||
@@ -193,28 +176,22 @@ jobs:
|
|||||||
|
|
||||||
# Determine version for dms stable
|
# Determine version for dms stable
|
||||||
if [[ "${{ github.event.inputs.package }}" == "dms" ]]; then
|
if [[ "${{ github.event.inputs.package }}" == "dms" ]]; then
|
||||||
# Use github.ref if tag selected, otherwise auto-detect latest
|
# For explicit dms selection, require tag_version
|
||||||
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
if [[ -n "${{ github.event.inputs.tag_version }}" ]]; then
|
||||||
VERSION="${GITHUB_REF#refs/tags/}"
|
VERSION="${{ github.event.inputs.tag_version }}"
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
echo "Using tag from GITHUB_REF: $VERSION"
|
echo "Using specified tag: $VERSION"
|
||||||
else
|
else
|
||||||
# Auto-detect latest release for dms
|
echo "ERROR: tag_version is required when package=dms"
|
||||||
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "")
|
echo "Please specify a tag version (e.g., v1.0.2) or use package=all for auto-detection"
|
||||||
if [[ -n "$LATEST_TAG" ]]; then
|
exit 1
|
||||||
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
|
|
||||||
echo "Auto-detected latest release: $LATEST_TAG"
|
|
||||||
else
|
|
||||||
echo "ERROR: Could not auto-detect latest release"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
elif [[ "${{ github.event.inputs.package }}" == "all" ]]; then
|
elif [[ "${{ github.event.inputs.package }}" == "all" ]]; then
|
||||||
# Use github.ref if tag selected, otherwise auto-detect latest
|
# For "all", auto-detect if tag_version not specified
|
||||||
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
if [[ -n "${{ github.event.inputs.tag_version }}" ]]; then
|
||||||
VERSION="${GITHUB_REF#refs/tags/}"
|
VERSION="${{ github.event.inputs.tag_version }}"
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
echo "Using tag from GITHUB_REF: $VERSION"
|
echo "Using specified tag: $VERSION"
|
||||||
else
|
else
|
||||||
# Auto-detect latest release for "all"
|
# Auto-detect latest release for "all"
|
||||||
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "")
|
LATEST_TAG=$(curl -s https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/' || echo "")
|
||||||
@@ -229,7 +206,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Use filtered packages from check-updates when package="all" and no rebuild/tag specified
|
# Use filtered packages from check-updates when package="all" and no rebuild/tag specified
|
||||||
if [[ "${{ github.event.inputs.package }}" == "all" ]] && [[ -z "${{ github.event.inputs.rebuild_release }}" ]] && [[ ! "${{ github.ref }}" =~ ^refs/tags/ ]]; then
|
if [[ "${{ github.event.inputs.package }}" == "all" ]] && [[ -z "${{ github.event.inputs.rebuild_release }}" ]] && [[ -z "${{ github.event.inputs.tag_version }}" ]]; then
|
||||||
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
||||||
echo "Manual trigger: all (filtered to: ${{ needs.check-updates.outputs.packages }})"
|
echo "Manual trigger: all (filtered to: ${{ needs.check-updates.outputs.packages }})"
|
||||||
else
|
else
|
||||||
@@ -238,9 +215,6 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
||||||
if [[ -n "${{ needs.check-updates.outputs.version }}" ]]; then
|
|
||||||
echo "version=${{ needs.check-updates.outputs.version }}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Update dms-git spec version
|
- name: Update dms-git spec version
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ var (
|
|||||||
swayVersionRegex = regexp.MustCompile(`sway version (\d+\.\d+)`)
|
swayVersionRegex = regexp.MustCompile(`sway version (\d+\.\d+)`)
|
||||||
riverVersionRegex = regexp.MustCompile(`river (\d+\.\d+)`)
|
riverVersionRegex = regexp.MustCompile(`river (\d+\.\d+)`)
|
||||||
wayfireVersionRegex = regexp.MustCompile(`wayfire (\d+\.\d+)`)
|
wayfireVersionRegex = regexp.MustCompile(`wayfire (\d+\.\d+)`)
|
||||||
|
labwcVersionRegex = regexp.MustCompile(`labwc (\d+\.\d+\.\d+)`)
|
||||||
|
mangowcVersionRegex = regexp.MustCompile(`mango (\d+\.\d+\.\d+)`)
|
||||||
)
|
)
|
||||||
|
|
||||||
var doctorCmd = &cobra.Command{
|
var doctorCmd = &cobra.Command{
|
||||||
@@ -448,11 +450,13 @@ func checkWindowManagers() []checkResult {
|
|||||||
versionRegex *regexp.Regexp
|
versionRegex *regexp.Regexp
|
||||||
commands []string
|
commands []string
|
||||||
}{
|
}{
|
||||||
{"Hyprland", "hyprctl", "version", hyprlandVersionRegex, []string{"hyprland", "Hyprland"}},
|
{"Hyprland", "Hyprland", "--version", hyprlandVersionRegex, []string{"hyprland", "Hyprland"}},
|
||||||
{"niri", "niri", "--version", niriVersionRegex, []string{"niri"}},
|
{"niri", "niri", "--version", niriVersionRegex, []string{"niri"}},
|
||||||
{"Sway", "sway", "--version", swayVersionRegex, []string{"sway"}},
|
{"Sway", "sway", "--version", swayVersionRegex, []string{"sway"}},
|
||||||
{"River", "river", "-version", riverVersionRegex, []string{"river"}},
|
{"River", "river", "-version", riverVersionRegex, []string{"river"}},
|
||||||
{"Wayfire", "wayfire", "--version", wayfireVersionRegex, []string{"wayfire"}},
|
{"Wayfire", "wayfire", "--version", wayfireVersionRegex, []string{"wayfire"}},
|
||||||
|
{"labwc", "labwc", "--version", labwcVersionRegex, []string{"labwc"}},
|
||||||
|
{"mangowc", "mango", "-v", mangowcVersionRegex, []string{"mango"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
var results []checkResult
|
var results []checkResult
|
||||||
@@ -477,7 +481,7 @@ func checkWindowManagers() []checkResult {
|
|||||||
results = append(results, checkResult{
|
results = append(results, checkResult{
|
||||||
catCompositor, c.name, statusOK,
|
catCompositor, c.name, statusOK,
|
||||||
getVersionFromCommand(c.versionCmd, c.versionArg, c.versionRegex), details,
|
getVersionFromCommand(c.versionCmd, c.versionArg, c.versionRegex), details,
|
||||||
doctorDocsURL + "#compositor",
|
doctorDocsURL + "#compositor-checks",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,7 +490,7 @@ func checkWindowManagers() []checkResult {
|
|||||||
catCompositor, "Compositor", statusError,
|
catCompositor, "Compositor", statusError,
|
||||||
"No supported Wayland compositor found",
|
"No supported Wayland compositor found",
|
||||||
"Install Hyprland, niri, Sway, River, or Wayfire",
|
"Install Hyprland, niri, Sway, River, or Wayfire",
|
||||||
doctorDocsURL + "#compositor",
|
doctorDocsURL + "#compositor-checks",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,8 +502,8 @@ func checkWindowManagers() []checkResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getVersionFromCommand(cmd, arg string, regex *regexp.Regexp) string {
|
func getVersionFromCommand(cmd, arg string, regex *regexp.Regexp) string {
|
||||||
output, err := exec.Command(cmd, arg).Output()
|
output, err := exec.Command(cmd, arg).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil && len(output) == 0 {
|
||||||
return "installed"
|
return "installed"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,19 +638,14 @@ func checkI2CAvailability() checkResult {
|
|||||||
return checkResult{catOptionalFeatures, "I2C/DDC", statusOK, fmt.Sprintf("%d monitor(s) detected", len(devices)), "External monitor brightness control", doctorDocsURL + "#optional-features"}
|
return checkResult{catOptionalFeatures, "I2C/DDC", statusOK, fmt.Sprintf("%d monitor(s) detected", len(devices)), "External monitor brightness control", doctorDocsURL + "#optional-features"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func detectNetworkBackend() string {
|
func detectNetworkBackend(stackResult *network.DetectResult) string {
|
||||||
result, err := network.DetectNetworkStack()
|
switch stackResult.Backend {
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
switch result.Backend {
|
|
||||||
case network.BackendNetworkManager:
|
case network.BackendNetworkManager:
|
||||||
return "NetworkManager"
|
return "NetworkManager"
|
||||||
case network.BackendIwd:
|
case network.BackendIwd:
|
||||||
return "iwd"
|
return "iwd"
|
||||||
case network.BackendNetworkd:
|
case network.BackendNetworkd:
|
||||||
if result.HasIwd {
|
if stackResult.HasIwd {
|
||||||
return "iwd + systemd-networkd"
|
return "iwd + systemd-networkd"
|
||||||
}
|
}
|
||||||
return "systemd-networkd"
|
return "systemd-networkd"
|
||||||
@@ -657,75 +656,73 @@ func detectNetworkBackend() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getOptionalDBusStatus(busName string) (status, string) {
|
||||||
|
if utils.IsDBusServiceAvailable(busName) {
|
||||||
|
return statusOK, "Available"
|
||||||
|
} else {
|
||||||
|
return statusWarn, "Not available"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func checkOptionalDependencies() []checkResult {
|
func checkOptionalDependencies() []checkResult {
|
||||||
var results []checkResult
|
var results []checkResult
|
||||||
|
|
||||||
if utils.IsServiceActive("accounts-daemon", false) {
|
optionalFeaturesURL := doctorDocsURL + "#optional-features"
|
||||||
results = append(results, checkResult{catOptionalFeatures, "accountsservice", statusOK, "Running", "User accounts", doctorDocsURL + "#optional-features"})
|
|
||||||
} else {
|
|
||||||
results = append(results, checkResult{catOptionalFeatures, "accountsservice", statusWarn, "Not running", "User accounts", doctorDocsURL + "#optional-features"})
|
|
||||||
}
|
|
||||||
|
|
||||||
if utils.IsServiceActive("power-profiles-daemon", false) {
|
accountsStatus, accountsMsg := getOptionalDBusStatus("org.freedesktop.Accounts")
|
||||||
results = append(results, checkResult{catOptionalFeatures, "power-profiles-daemon", statusOK, "Running", "Power profile management", doctorDocsURL + "#optional-features"})
|
results = append(results, checkResult{catOptionalFeatures, "accountsservice", accountsStatus, accountsMsg, "User accounts", optionalFeaturesURL})
|
||||||
} else {
|
|
||||||
results = append(results, checkResult{catOptionalFeatures, "power-profiles-daemon", statusInfo, "Not running", "Power profile management", doctorDocsURL + "#optional-features"})
|
ppdStatus, ppdMsg := getOptionalDBusStatus("org.freedesktop.UPower.PowerProfiles")
|
||||||
}
|
results = append(results, checkResult{catOptionalFeatures, "power-profiles-daemon", ppdStatus, ppdMsg, "Power profile management", optionalFeaturesURL})
|
||||||
|
|
||||||
|
logindStatus, logindMsg := getOptionalDBusStatus("org.freedesktop.login1")
|
||||||
|
results = append(results, checkResult{catOptionalFeatures, "logind", logindStatus, logindMsg, "Session management", optionalFeaturesURL})
|
||||||
|
|
||||||
results = append(results, checkI2CAvailability())
|
results = append(results, checkI2CAvailability())
|
||||||
|
|
||||||
terminals := []string{"ghostty", "kitty", "alacritty", "foot", "wezterm"}
|
terminals := []string{"ghostty", "kitty", "alacritty", "foot", "wezterm"}
|
||||||
if idx := slices.IndexFunc(terminals, utils.CommandExists); idx >= 0 {
|
if idx := slices.IndexFunc(terminals, utils.CommandExists); idx >= 0 {
|
||||||
results = append(results, checkResult{catOptionalFeatures, "Terminal", statusOK, terminals[idx], "", doctorDocsURL + "#optional-features"})
|
results = append(results, checkResult{catOptionalFeatures, "Terminal", statusOK, terminals[idx], "", optionalFeaturesURL})
|
||||||
} else {
|
} else {
|
||||||
results = append(results, checkResult{catOptionalFeatures, "Terminal", statusWarn, "None found", "Install ghostty, kitty, or alacritty", doctorDocsURL + "#optional-features"})
|
results = append(results, checkResult{catOptionalFeatures, "Terminal", statusWarn, "None found", "Install ghostty, kitty, or alacritty", optionalFeaturesURL})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
networkResult, err := network.DetectNetworkStack()
|
||||||
|
networkStatus, networkMessage, networkDetails := statusOK, "Not available", "Network management"
|
||||||
|
|
||||||
|
if err == nil && networkResult.Backend != network.BackendNone {
|
||||||
|
networkMessage = detectNetworkBackend(networkResult)
|
||||||
|
if doctorVerbose {
|
||||||
|
networkDetails = networkResult.ChosenReason
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
networkStatus = statusInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, checkResult{catOptionalFeatures, "Network", networkStatus, networkMessage, networkDetails, optionalFeaturesURL})
|
||||||
|
|
||||||
deps := []struct {
|
deps := []struct {
|
||||||
name, cmd, altCmd, desc string
|
name, cmd, desc string
|
||||||
important bool
|
important bool
|
||||||
}{
|
}{
|
||||||
{"matugen", "matugen", "", "Dynamic theming", true},
|
{"matugen", "matugen", "Dynamic theming", true},
|
||||||
{"dgop", "dgop", "", "System monitoring", true},
|
{"dgop", "dgop", "System monitoring", true},
|
||||||
{"cava", "cava", "", "Audio visualizer", true},
|
{"cava", "cava", "Audio visualizer", true},
|
||||||
{"khal", "khal", "", "Calendar events", false},
|
{"khal", "khal", "Calendar events", false},
|
||||||
{"Network", "nmcli", "iwctl", "Network management", false},
|
{"danksearch", "dsearch", "File search", false},
|
||||||
{"danksearch", "dsearch", "", "File search", false},
|
{"fprintd", "fprintd-list", "Fingerprint auth", false},
|
||||||
{"loginctl", "loginctl", "", "Session management", false},
|
|
||||||
{"fprintd", "fprintd-list", "", "Fingerprint auth", false},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range deps {
|
for _, d := range deps {
|
||||||
found, foundCmd := utils.CommandExists(d.cmd), d.cmd
|
found := utils.CommandExists(d.cmd)
|
||||||
if !found && d.altCmd != "" && utils.CommandExists(d.altCmd) {
|
|
||||||
found, foundCmd = true, d.altCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case found:
|
case found:
|
||||||
message := "Installed"
|
results = append(results, checkResult{catOptionalFeatures, d.name, statusOK, "Installed", d.desc, optionalFeaturesURL})
|
||||||
details := d.desc
|
|
||||||
if d.name == "Network" {
|
|
||||||
result, err := network.DetectNetworkStack()
|
|
||||||
if err == nil && result.Backend != network.BackendNone {
|
|
||||||
message = detectNetworkBackend() + " (active)"
|
|
||||||
if doctorVerbose {
|
|
||||||
details = result.ChosenReason
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch foundCmd {
|
|
||||||
case "nmcli":
|
|
||||||
message = "NetworkManager (installed)"
|
|
||||||
case "iwctl":
|
|
||||||
message = "iwd (installed)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results = append(results, checkResult{catOptionalFeatures, d.name, statusOK, message, details, doctorDocsURL + "#optional-features"})
|
|
||||||
case d.important:
|
case d.important:
|
||||||
results = append(results, checkResult{catOptionalFeatures, d.name, statusWarn, "Missing", d.desc, doctorDocsURL + "#optional-features"})
|
results = append(results, checkResult{catOptionalFeatures, d.name, statusWarn, "Missing", d.desc, optionalFeaturesURL})
|
||||||
default:
|
default:
|
||||||
results = append(results, checkResult{catOptionalFeatures, d.name, statusInfo, "Not installed", d.desc, doctorDocsURL + "#optional-features"})
|
results = append(results, checkResult{catOptionalFeatures, d.name, statusInfo, "Not installed", d.desc, optionalFeaturesURL})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,6 +890,10 @@ func printResultLine(r checkResult, styles tui.Styles) {
|
|||||||
if doctorVerbose && r.details != "" {
|
if doctorVerbose && r.details != "" {
|
||||||
fmt.Printf(" %s\n", styles.Subtle.Render("└─ "+r.details))
|
fmt.Printf(" %s\n", styles.Subtle.Render("└─ "+r.details))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r.status == statusError || r.status == statusWarn) && r.url != "" {
|
||||||
|
fmt.Printf(" %s\n", styles.Subtle.Render("→ "+r.url))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printSummary(results []checkResult, qsMissingFeatures bool) {
|
func printSummary(results []checkResult, qsMissingFeatures bool) {
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ func (o *OpenSUSEDistribution) GetPackageMappingWithVariants(wm deps.WindowManag
|
|||||||
packages := map[string]PackageMapping{
|
packages := map[string]PackageMapping{
|
||||||
// Standard zypper packages
|
// Standard zypper packages
|
||||||
"git": {Name: "git", Repository: RepoTypeSystem},
|
"git": {Name: "git", Repository: RepoTypeSystem},
|
||||||
"ghostty": {Name: "ghostty", Repository: RepoTypeSystem},
|
|
||||||
"kitty": {Name: "kitty", Repository: RepoTypeSystem},
|
"kitty": {Name: "kitty", Repository: RepoTypeSystem},
|
||||||
"alacritty": {Name: "alacritty", Repository: RepoTypeSystem},
|
"alacritty": {Name: "alacritty", Repository: RepoTypeSystem},
|
||||||
"xdg-desktop-portal-gtk": {Name: "xdg-desktop-portal-gtk", Repository: RepoTypeSystem},
|
"xdg-desktop-portal-gtk": {Name: "xdg-desktop-portal-gtk", Repository: RepoTypeSystem},
|
||||||
@@ -117,6 +116,7 @@ func (o *OpenSUSEDistribution) GetPackageMappingWithVariants(wm deps.WindowManag
|
|||||||
// DMS packages from OBS
|
// DMS packages from OBS
|
||||||
"dms (DankMaterialShell)": o.getDmsMapping(variants["dms (DankMaterialShell)"]),
|
"dms (DankMaterialShell)": o.getDmsMapping(variants["dms (DankMaterialShell)"]),
|
||||||
"quickshell": o.getQuickshellMapping(variants["quickshell"]),
|
"quickshell": o.getQuickshellMapping(variants["quickshell"]),
|
||||||
|
"ghostty": {Name: "ghostty", Repository: RepoTypeOBS, RepoURL: "home:AvengeMedia:danklinux"},
|
||||||
"matugen": {Name: "matugen", Repository: RepoTypeOBS, RepoURL: "home:AvengeMedia:danklinux"},
|
"matugen": {Name: "matugen", Repository: RepoTypeOBS, RepoURL: "home:AvengeMedia:danklinux"},
|
||||||
"dgop": {Name: "dgop", Repository: RepoTypeOBS, RepoURL: "home:AvengeMedia:danklinux"},
|
"dgop": {Name: "dgop", Repository: RepoTypeOBS, RepoURL: "home:AvengeMedia:danklinux"},
|
||||||
}
|
}
|
||||||
|
|||||||
20
core/internal/utils/dbus.go
Normal file
20
core/internal/utils/dbus.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsDBusServiceAvailable(busName string) bool {
|
||||||
|
conn, err := dbus.ConnectSystemBus()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
obj := conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
|
||||||
|
var owned bool
|
||||||
|
if err := obj.Call("org.freedesktop.DBus.NameHasOwner", 0, busName).Store(&owned); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return owned
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppChecker interface {
|
type AppChecker interface {
|
||||||
@@ -43,16 +42,3 @@ func AnyCommandExists(cmds ...string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsServiceActive(name string, userService bool) bool {
|
|
||||||
if !CommandExists("systemctl") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
args := []string{"is-active", name}
|
|
||||||
if userService {
|
|
||||||
args = []string{"--user", "is-active", name}
|
|
||||||
}
|
|
||||||
output, _ := exec.Command("systemctl", args...).Output()
|
|
||||||
return strings.EqualFold(strings.TrimSpace(string(output)), "active")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,12 +11,18 @@ let
|
|||||||
|
|
||||||
inherit (config.services.greetd.settings.default_session) user;
|
inherit (config.services.greetd.settings.default_session) user;
|
||||||
|
|
||||||
|
compositorPackage =
|
||||||
|
let
|
||||||
|
configured = lib.attrByPath [ "programs" cfg.compositor.name "package" ] null config;
|
||||||
|
in
|
||||||
|
if configured != null then configured else builtins.getAttr cfg.compositor.name pkgs;
|
||||||
|
|
||||||
cacheDir = "/var/lib/dms-greeter";
|
cacheDir = "/var/lib/dms-greeter";
|
||||||
greeterScript = pkgs.writeShellScriptBin "dms-greeter" ''
|
greeterScript = pkgs.writeShellScriptBin "dms-greeter" ''
|
||||||
export PATH=$PATH:${
|
export PATH=$PATH:${
|
||||||
lib.makeBinPath [
|
lib.makeBinPath [
|
||||||
cfg.quickshell.package
|
cfg.quickshell.package
|
||||||
config.programs.${cfg.compositor.name}.package
|
compositorPackage
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
${
|
${
|
||||||
@@ -64,6 +70,7 @@ in
|
|||||||
"niri"
|
"niri"
|
||||||
"hyprland"
|
"hyprland"
|
||||||
"sway"
|
"sway"
|
||||||
|
"labwc"
|
||||||
];
|
];
|
||||||
description = "Compositor to run greeter in";
|
description = "Compositor to run greeter in";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ in
|
|||||||
default = hasPluginSettings;
|
default = hasPluginSettings;
|
||||||
description = ''Whether to manage plugin settings. Automatically enabled if any plugins have settings configured.'';
|
description = ''Whether to manage plugin settings. Automatically enabled if any plugins have settings configured.'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.target = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = config.wayland.systemd.target;
|
||||||
|
defaultText = lib.literalExpression "config.wayland.systemd.target";
|
||||||
|
description = "Systemd target to bind to.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
@@ -84,8 +91,8 @@ in
|
|||||||
systemd.user.services.dms = lib.mkIf cfg.systemd.enable {
|
systemd.user.services.dms = lib.mkIf cfg.systemd.enable {
|
||||||
Unit = {
|
Unit = {
|
||||||
Description = "DankMaterialShell";
|
Description = "DankMaterialShell";
|
||||||
PartOf = [ config.wayland.systemd.target ];
|
PartOf = [ cfg.systemd.target ];
|
||||||
After = [ config.wayland.systemd.target ];
|
After = [ cfg.systemd.target ];
|
||||||
};
|
};
|
||||||
|
|
||||||
Service = {
|
Service = {
|
||||||
@@ -93,7 +100,7 @@ in
|
|||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
};
|
};
|
||||||
|
|
||||||
Install.WantedBy = [ config.wayland.systemd.target ];
|
Install.WantedBy = [ cfg.systemd.target ];
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.stateFile."DankMaterialShell/session.json" = lib.mkIf (cfg.session != { }) {
|
xdg.stateFile."DankMaterialShell/session.json" = lib.mkIf (cfg.session != { }) {
|
||||||
|
|||||||
@@ -20,15 +20,19 @@ in
|
|||||||
imports = [
|
imports = [
|
||||||
(import ./options.nix args)
|
(import ./options.nix args)
|
||||||
];
|
];
|
||||||
|
options.programs.dank-material-shell.systemd.target = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Systemd target to bind to.";
|
||||||
|
default = "graphical-session.target";
|
||||||
|
};
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
systemd.user.services.dms = lib.mkIf cfg.systemd.enable {
|
systemd.user.services.dms = lib.mkIf cfg.systemd.enable {
|
||||||
description = "DankMaterialShell";
|
description = "DankMaterialShell";
|
||||||
path = lib.mkForce [ ];
|
path = lib.mkForce [ ];
|
||||||
|
|
||||||
partOf = [ "graphical-session.target" ];
|
partOf = [ cfg.systemd.target ];
|
||||||
after = [ "graphical-session.target" ];
|
after = [ cfg.systemd.target ];
|
||||||
wantedBy = [ "graphical-session.target" ];
|
wantedBy = [ cfg.systemd.target ];
|
||||||
restartIfChanged = cfg.systemd.restartIfChanged;
|
restartIfChanged = cfg.systemd.restartIfChanged;
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Saffron Bloom
|
Spicy Miso
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ Singleton {
|
|||||||
Quickshell.execDetached(["cp", strip(from), strip(to)]);
|
Quickshell.execDetached(["cp", strip(from), strip(to)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isSteamApp(appId: string): bool {
|
||||||
|
return appId && /^steam_app_\d+$/.test(appId);
|
||||||
|
}
|
||||||
|
|
||||||
function moddedAppId(appId: string): string {
|
function moddedAppId(appId: string): string {
|
||||||
const subs = SettingsData.appIdSubstitutions || [];
|
const subs = SettingsData.appIdSubstitutions || [];
|
||||||
for (let i = 0; i < subs.length; i++) {
|
for (let i = 0; i < subs.length; i++) {
|
||||||
@@ -60,6 +64,9 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const steamMatch = appId.match(/^steam_app_(\d+)$/);
|
||||||
|
if (steamMatch)
|
||||||
|
return `steam_icon_${steamMatch[1]}`;
|
||||||
return appId;
|
return appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,15 +82,19 @@ Singleton {
|
|||||||
popoutOpening();
|
popoutOpening();
|
||||||
}
|
}
|
||||||
|
|
||||||
let justClosedSamePopout = false;
|
let movedFromOtherScreen = false;
|
||||||
for (const otherScreenName in currentPopoutsByScreen) {
|
for (const otherScreenName in currentPopoutsByScreen) {
|
||||||
if (otherScreenName === screenName)
|
if (otherScreenName === screenName)
|
||||||
continue;
|
continue;
|
||||||
const otherPopout = currentPopoutsByScreen[otherScreenName];
|
const otherPopout = currentPopoutsByScreen[otherScreenName];
|
||||||
if (!otherPopout)
|
if (!otherPopout)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (otherPopout === popout) {
|
if (otherPopout === popout) {
|
||||||
justClosedSamePopout = true;
|
movedFromOtherScreen = true;
|
||||||
|
currentPopoutsByScreen[otherScreenName] = null;
|
||||||
|
currentPopoutTriggers[otherScreenName] = null;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (otherPopout.dashVisible !== undefined) {
|
if (otherPopout.dashVisible !== undefined) {
|
||||||
@@ -112,7 +116,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPopout === popout && popout.shouldBeVisible) {
|
if (currentPopout === popout && popout.shouldBeVisible && !movedFromOtherScreen) {
|
||||||
if (triggerId !== undefined && currentPopoutTriggers[screenName] === triggerId) {
|
if (triggerId !== undefined && currentPopoutTriggers[screenName] === triggerId) {
|
||||||
if (popout.dashVisible !== undefined) {
|
if (popout.dashVisible !== undefined) {
|
||||||
popout.dashVisible = false;
|
popout.dashVisible = false;
|
||||||
@@ -139,6 +143,7 @@ Singleton {
|
|||||||
popout.currentTabIndex = tabIndex;
|
popout.currentTabIndex = tabIndex;
|
||||||
}
|
}
|
||||||
currentPopoutTriggers[screenName] = triggerId;
|
currentPopoutTriggers[screenName] = triggerId;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPopoutTriggers[screenName] = triggerId;
|
currentPopoutTriggers[screenName] = triggerId;
|
||||||
@@ -153,16 +158,8 @@ Singleton {
|
|||||||
ModalManager.closeAllModalsExcept(null);
|
ModalManager.closeAllModalsExcept(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (justClosedSamePopout) {
|
if (movedFromOtherScreen) {
|
||||||
Qt.callLater(() => {
|
popout.open();
|
||||||
if (popout.dashVisible !== undefined) {
|
|
||||||
popout.dashVisible = true;
|
|
||||||
} else if (popout.notificationHistoryVisible !== undefined) {
|
|
||||||
popout.notificationHistoryVisible = true;
|
|
||||||
} else {
|
|
||||||
popout.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
if (popout.dashVisible !== undefined) {
|
if (popout.dashVisible !== undefined) {
|
||||||
popout.dashVisible = true;
|
popout.dashVisible = true;
|
||||||
|
|||||||
@@ -122,6 +122,21 @@ Rectangle {
|
|||||||
contentHeight: audioColumn.height
|
contentHeight: audioColumn.height
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
property int maxPinnedInputs: 3
|
||||||
|
|
||||||
|
function normalizePinList(value) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return value.filter(v => v)
|
||||||
|
if (typeof value === "string" && value.length > 0)
|
||||||
|
return [value]
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPinnedInputs() {
|
||||||
|
const pins = SettingsData.audioInputDevicePins || {}
|
||||||
|
return normalizePinList(pins["preferredInput"])
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: audioColumn
|
id: audioColumn
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -133,16 +148,20 @@ Rectangle {
|
|||||||
const nodes = Pipewire.nodes.values.filter(node => {
|
const nodes = Pipewire.nodes.values.filter(node => {
|
||||||
return node.audio && !node.isSink && !node.isStream;
|
return node.audio && !node.isSink && !node.isStream;
|
||||||
});
|
});
|
||||||
const pins = SettingsData.audioInputDevicePins || {};
|
const pinnedList = audioContent.getPinnedInputs();
|
||||||
const pinnedName = pins["preferredInput"];
|
|
||||||
|
|
||||||
let sorted = [...nodes];
|
let sorted = [...nodes];
|
||||||
sorted.sort((a, b) => {
|
sorted.sort((a, b) => {
|
||||||
// Pinned device first
|
// Pinned device first
|
||||||
if (a.name === pinnedName && b.name !== pinnedName)
|
const aPinnedIndex = pinnedList.indexOf(a.name)
|
||||||
return -1;
|
const bPinnedIndex = pinnedList.indexOf(b.name)
|
||||||
if (b.name === pinnedName && a.name !== pinnedName)
|
if (aPinnedIndex !== -1 || bPinnedIndex !== -1) {
|
||||||
return 1;
|
if (aPinnedIndex === -1)
|
||||||
|
return 1
|
||||||
|
if (bPinnedIndex === -1)
|
||||||
|
return -1
|
||||||
|
return aPinnedIndex - bPinnedIndex
|
||||||
|
}
|
||||||
// Then active device
|
// Then active device
|
||||||
if (a === AudioService.source && b !== AudioService.source)
|
if (a === AudioService.source && b !== AudioService.source)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -224,7 +243,7 @@ Rectangle {
|
|||||||
height: 28
|
height: 28
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.audioInputDevicePins || {})["preferredInput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05);
|
return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +256,7 @@ Rectangle {
|
|||||||
name: "push_pin"
|
name: "push_pin"
|
||||||
size: 16
|
size: 16
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.audioInputDevicePins || {})["preferredInput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -245,12 +264,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
const isThisDevicePinned = (SettingsData.audioInputDevicePins || {})["preferredInput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin");
|
return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin");
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.audioInputDevicePins || {})["preferredInput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -261,16 +280,24 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const pins = JSON.parse(JSON.stringify(SettingsData.audioInputDevicePins || {}));
|
const pins = JSON.parse(JSON.stringify(SettingsData.audioInputDevicePins || {}))
|
||||||
const isCurrentlyPinned = pins["preferredInput"] === modelData.name;
|
let pinnedList = audioContent.normalizePinList(pins["preferredInput"])
|
||||||
|
const pinIndex = pinnedList.indexOf(modelData.name)
|
||||||
|
|
||||||
if (isCurrentlyPinned) {
|
if (pinIndex !== -1) {
|
||||||
delete pins["preferredInput"];
|
pinnedList.splice(pinIndex, 1)
|
||||||
} else {
|
} else {
|
||||||
pins["preferredInput"] = modelData.name;
|
pinnedList.unshift(modelData.name)
|
||||||
|
if (pinnedList.length > audioContent.maxPinnedInputs)
|
||||||
|
pinnedList = pinnedList.slice(0, audioContent.maxPinnedInputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsData.set("audioInputDevicePins", pins);
|
if (pinnedList.length > 0)
|
||||||
|
pins["preferredInput"] = pinnedList
|
||||||
|
else
|
||||||
|
delete pins["preferredInput"]
|
||||||
|
|
||||||
|
SettingsData.set("audioInputDevicePins", pins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,6 +132,21 @@ Rectangle {
|
|||||||
contentHeight: audioColumn.height
|
contentHeight: audioColumn.height
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
property int maxPinnedOutputs: 3
|
||||||
|
|
||||||
|
function normalizePinList(value) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return value.filter(v => v)
|
||||||
|
if (typeof value === "string" && value.length > 0)
|
||||||
|
return [value]
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPinnedOutputs() {
|
||||||
|
const pins = SettingsData.audioOutputDevicePins || {}
|
||||||
|
return normalizePinList(pins["preferredOutput"])
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: audioColumn
|
id: audioColumn
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -143,16 +158,20 @@ Rectangle {
|
|||||||
const nodes = Pipewire.nodes.values.filter(node => {
|
const nodes = Pipewire.nodes.values.filter(node => {
|
||||||
return node.audio && node.isSink && !node.isStream;
|
return node.audio && node.isSink && !node.isStream;
|
||||||
});
|
});
|
||||||
const pins = SettingsData.audioOutputDevicePins || {};
|
const pinnedList = audioContent.getPinnedOutputs();
|
||||||
const pinnedName = pins["preferredOutput"];
|
|
||||||
|
|
||||||
let sorted = [...nodes];
|
let sorted = [...nodes];
|
||||||
sorted.sort((a, b) => {
|
sorted.sort((a, b) => {
|
||||||
// Pinned device first
|
// Pinned device first
|
||||||
if (a.name === pinnedName && b.name !== pinnedName)
|
const aPinnedIndex = pinnedList.indexOf(a.name)
|
||||||
return -1;
|
const bPinnedIndex = pinnedList.indexOf(b.name)
|
||||||
if (b.name === pinnedName && a.name !== pinnedName)
|
if (aPinnedIndex !== -1 || bPinnedIndex !== -1) {
|
||||||
return 1;
|
if (aPinnedIndex === -1)
|
||||||
|
return 1
|
||||||
|
if (bPinnedIndex === -1)
|
||||||
|
return -1
|
||||||
|
return aPinnedIndex - bPinnedIndex
|
||||||
|
}
|
||||||
// Then active device
|
// Then active device
|
||||||
if (a === AudioService.sink && b !== AudioService.sink)
|
if (a === AudioService.sink && b !== AudioService.sink)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -236,7 +255,7 @@ Rectangle {
|
|||||||
height: 28
|
height: 28
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.audioOutputDevicePins || {})["preferredOutput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05);
|
return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +268,7 @@ Rectangle {
|
|||||||
name: "push_pin"
|
name: "push_pin"
|
||||||
size: 16
|
size: 16
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.audioOutputDevicePins || {})["preferredOutput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -257,12 +276,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
const isThisDevicePinned = (SettingsData.audioOutputDevicePins || {})["preferredOutput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin");
|
return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin");
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.audioOutputDevicePins || {})["preferredOutput"] === modelData.name;
|
const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name);
|
||||||
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
return isThisDevicePinned ? Theme.primary : Theme.surfaceText;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -273,16 +292,24 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const pins = JSON.parse(JSON.stringify(SettingsData.audioOutputDevicePins || {}));
|
const pins = JSON.parse(JSON.stringify(SettingsData.audioOutputDevicePins || {}))
|
||||||
const isCurrentlyPinned = pins["preferredOutput"] === modelData.name;
|
let pinnedList = audioContent.normalizePinList(pins["preferredOutput"])
|
||||||
|
const pinIndex = pinnedList.indexOf(modelData.name)
|
||||||
|
|
||||||
if (isCurrentlyPinned) {
|
if (pinIndex !== -1) {
|
||||||
delete pins["preferredOutput"];
|
pinnedList.splice(pinIndex, 1)
|
||||||
} else {
|
} else {
|
||||||
pins["preferredOutput"] = modelData.name;
|
pinnedList.unshift(modelData.name)
|
||||||
|
if (pinnedList.length > audioContent.maxPinnedOutputs)
|
||||||
|
pinnedList = pinnedList.slice(0, audioContent.maxPinnedOutputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsData.set("audioOutputDevicePins", pins);
|
if (pinnedList.length > 0)
|
||||||
|
pins["preferredOutput"] = pinnedList
|
||||||
|
else
|
||||||
|
delete pins["preferredOutput"]
|
||||||
|
|
||||||
|
SettingsData.set("audioOutputDevicePins", pins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,21 @@ Rectangle {
|
|||||||
contentHeight: bluetoothColumn.height
|
contentHeight: bluetoothColumn.height
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
property int maxPinnedDevices: 3
|
||||||
|
|
||||||
|
function normalizePinList(value) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return value.filter(v => v)
|
||||||
|
if (typeof value === "string" && value.length > 0)
|
||||||
|
return [value]
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPinnedDevices() {
|
||||||
|
const pins = SettingsData.bluetoothDevicePins || {}
|
||||||
|
return normalizePinList(pins["preferredDevice"])
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: bluetoothColumn
|
id: bluetoothColumn
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -162,14 +177,18 @@ Rectangle {
|
|||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
|
if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
const pins = SettingsData.bluetoothDevicePins || {}
|
const pinnedList = bluetoothContent.getPinnedDevices()
|
||||||
const pinnedAddr = pins["preferredDevice"]
|
|
||||||
|
|
||||||
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
|
||||||
devices.sort((a, b) => {
|
devices.sort((a, b) => {
|
||||||
// Pinned device first
|
// Pinned device first
|
||||||
if (a.address === pinnedAddr && b.address !== pinnedAddr) return -1
|
const aPinnedIndex = pinnedList.indexOf(a.address)
|
||||||
if (b.address === pinnedAddr && a.address !== pinnedAddr) return 1
|
const bPinnedIndex = pinnedList.indexOf(b.address)
|
||||||
|
if (aPinnedIndex !== -1 || bPinnedIndex !== -1) {
|
||||||
|
if (aPinnedIndex === -1) return 1
|
||||||
|
if (bPinnedIndex === -1) return -1
|
||||||
|
return aPinnedIndex - bPinnedIndex
|
||||||
|
}
|
||||||
// Then connected devices
|
// Then connected devices
|
||||||
if (a.connected && !b.connected) return -1
|
if (a.connected && !b.connected) return -1
|
||||||
if (!a.connected && b.connected) return 1
|
if (!a.connected && b.connected) return 1
|
||||||
@@ -302,7 +321,7 @@ Rectangle {
|
|||||||
height: 28
|
height: 28
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.bluetoothDevicePins || {})["preferredDevice"] === modelData.address
|
const isThisDevicePinned = bluetoothContent.getPinnedDevices().includes(modelData.address)
|
||||||
return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05)
|
return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +334,7 @@ Rectangle {
|
|||||||
name: "push_pin"
|
name: "push_pin"
|
||||||
size: 16
|
size: 16
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.bluetoothDevicePins || {})["preferredDevice"] === modelData.address
|
const isThisDevicePinned = bluetoothContent.getPinnedDevices().includes(modelData.address)
|
||||||
return isThisDevicePinned ? Theme.primary : Theme.surfaceText
|
return isThisDevicePinned ? Theme.primary : Theme.surfaceText
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -323,12 +342,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
const isThisDevicePinned = (SettingsData.bluetoothDevicePins || {})["preferredDevice"] === modelData.address
|
const isThisDevicePinned = bluetoothContent.getPinnedDevices().includes(modelData.address)
|
||||||
return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin")
|
return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin")
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: {
|
color: {
|
||||||
const isThisDevicePinned = (SettingsData.bluetoothDevicePins || {})["preferredDevice"] === modelData.address
|
const isThisDevicePinned = bluetoothContent.getPinnedDevices().includes(modelData.address)
|
||||||
return isThisDevicePinned ? Theme.primary : Theme.surfaceText
|
return isThisDevicePinned ? Theme.primary : Theme.surfaceText
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -340,14 +359,22 @@ Rectangle {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const pins = JSON.parse(JSON.stringify(SettingsData.bluetoothDevicePins || {}))
|
const pins = JSON.parse(JSON.stringify(SettingsData.bluetoothDevicePins || {}))
|
||||||
const isCurrentlyPinned = pins["preferredDevice"] === modelData.address
|
let pinnedList = bluetoothContent.normalizePinList(pins["preferredDevice"])
|
||||||
|
const pinIndex = pinnedList.indexOf(modelData.address)
|
||||||
|
|
||||||
if (isCurrentlyPinned) {
|
if (pinIndex !== -1) {
|
||||||
delete pins["preferredDevice"]
|
pinnedList.splice(pinIndex, 1)
|
||||||
} else {
|
} else {
|
||||||
pins["preferredDevice"] = modelData.address
|
pinnedList.unshift(modelData.address)
|
||||||
|
if (pinnedList.length > bluetoothContent.maxPinnedDevices)
|
||||||
|
pinnedList = pinnedList.slice(0, bluetoothContent.maxPinnedDevices)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pinnedList.length > 0)
|
||||||
|
pins["preferredDevice"] = pinnedList
|
||||||
|
else
|
||||||
|
delete pins["preferredDevice"]
|
||||||
|
|
||||||
SettingsData.set("bluetoothDevicePins", pins)
|
SettingsData.set("bluetoothDevicePins", pins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,20 +463,39 @@ Rectangle {
|
|||||||
contentHeight: wifiColumn.height
|
contentHeight: wifiColumn.height
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
|
property int maxPinnedNetworks: 3
|
||||||
|
|
||||||
|
function normalizePinList(value) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return value.filter(v => v)
|
||||||
|
if (typeof value === "string" && value.length > 0)
|
||||||
|
return [value]
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPinnedNetworks() {
|
||||||
|
const pins = SettingsData.wifiNetworkPins || {}
|
||||||
|
return normalizePinList(pins["preferredWifi"])
|
||||||
|
}
|
||||||
|
|
||||||
property var frozenNetworks: []
|
property var frozenNetworks: []
|
||||||
property bool menuOpen: false
|
property bool menuOpen: false
|
||||||
property var sortedNetworks: {
|
property var sortedNetworks: {
|
||||||
const ssid = NetworkService.currentWifiSSID;
|
const ssid = NetworkService.currentWifiSSID;
|
||||||
const networks = NetworkService.wifiNetworks;
|
const networks = NetworkService.wifiNetworks;
|
||||||
const pins = SettingsData.wifiNetworkPins || {};
|
const pinnedList = getPinnedNetworks()
|
||||||
const pinnedSSID = pins["preferredWifi"];
|
|
||||||
|
|
||||||
let sorted = [...networks];
|
let sorted = [...networks];
|
||||||
sorted.sort((a, b) => {
|
sorted.sort((a, b) => {
|
||||||
if (a.ssid === pinnedSSID && b.ssid !== pinnedSSID)
|
const aPinnedIndex = pinnedList.indexOf(a.ssid)
|
||||||
return -1;
|
const bPinnedIndex = pinnedList.indexOf(b.ssid)
|
||||||
if (b.ssid === pinnedSSID && a.ssid !== pinnedSSID)
|
if (aPinnedIndex !== -1 || bPinnedIndex !== -1) {
|
||||||
return 1;
|
if (aPinnedIndex === -1)
|
||||||
|
return 1
|
||||||
|
if (bPinnedIndex === -1)
|
||||||
|
return -1
|
||||||
|
return aPinnedIndex - bPinnedIndex
|
||||||
|
}
|
||||||
if (a.ssid === ssid)
|
if (a.ssid === ssid)
|
||||||
return -1;
|
return -1;
|
||||||
if (b.ssid === ssid)
|
if (b.ssid === ssid)
|
||||||
@@ -625,7 +644,7 @@ Rectangle {
|
|||||||
height: 28
|
height: 28
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
color: {
|
color: {
|
||||||
const isThisNetworkPinned = (SettingsData.wifiNetworkPins || {})["preferredWifi"] === modelData.ssid;
|
const isThisNetworkPinned = wifiContent.getPinnedNetworks().includes(modelData.ssid);
|
||||||
return isThisNetworkPinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05);
|
return isThisNetworkPinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +657,7 @@ Rectangle {
|
|||||||
name: "push_pin"
|
name: "push_pin"
|
||||||
size: 16
|
size: 16
|
||||||
color: {
|
color: {
|
||||||
const isThisNetworkPinned = (SettingsData.wifiNetworkPins || {})["preferredWifi"] === modelData.ssid;
|
const isThisNetworkPinned = wifiContent.getPinnedNetworks().includes(modelData.ssid);
|
||||||
return isThisNetworkPinned ? Theme.primary : Theme.surfaceText;
|
return isThisNetworkPinned ? Theme.primary : Theme.surfaceText;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -646,12 +665,12 @@ Rectangle {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
const isThisNetworkPinned = (SettingsData.wifiNetworkPins || {})["preferredWifi"] === modelData.ssid;
|
const isThisNetworkPinned = wifiContent.getPinnedNetworks().includes(modelData.ssid);
|
||||||
return isThisNetworkPinned ? I18n.tr("Pinned") : I18n.tr("Pin");
|
return isThisNetworkPinned ? I18n.tr("Pinned") : I18n.tr("Pin");
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: {
|
color: {
|
||||||
const isThisNetworkPinned = (SettingsData.wifiNetworkPins || {})["preferredWifi"] === modelData.ssid;
|
const isThisNetworkPinned = wifiContent.getPinnedNetworks().includes(modelData.ssid);
|
||||||
return isThisNetworkPinned ? Theme.primary : Theme.surfaceText;
|
return isThisNetworkPinned ? Theme.primary : Theme.surfaceText;
|
||||||
}
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -662,16 +681,24 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const pins = JSON.parse(JSON.stringify(SettingsData.wifiNetworkPins || {}));
|
const pins = JSON.parse(JSON.stringify(SettingsData.wifiNetworkPins || {}))
|
||||||
const isCurrentlyPinned = pins["preferredWifi"] === modelData.ssid;
|
let pinnedList = wifiContent.normalizePinList(pins["preferredWifi"])
|
||||||
|
const pinIndex = pinnedList.indexOf(modelData.ssid)
|
||||||
|
|
||||||
if (isCurrentlyPinned) {
|
if (pinIndex !== -1) {
|
||||||
delete pins["preferredWifi"];
|
pinnedList.splice(pinIndex, 1)
|
||||||
} else {
|
} else {
|
||||||
pins["preferredWifi"] = modelData.ssid;
|
pinnedList.unshift(modelData.ssid)
|
||||||
|
if (pinnedList.length > wifiContent.maxPinnedNetworks)
|
||||||
|
pinnedList = pinnedList.slice(0, wifiContent.maxPinnedNetworks)
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsData.set("wifiNetworkPins", pins);
|
if (pinnedList.length > 0)
|
||||||
|
pins["preferredWifi"] = pinnedList
|
||||||
|
else
|
||||||
|
delete pins["preferredWifi"]
|
||||||
|
|
||||||
|
SettingsData.set("wifiNetworkPins", pins)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ BasePill {
|
|||||||
property real micAccumulator: 0
|
property real micAccumulator: 0
|
||||||
property real volumeAccumulator: 0
|
property real volumeAccumulator: 0
|
||||||
property real brightnessAccumulator: 0
|
property real brightnessAccumulator: 0
|
||||||
|
readonly property real vIconSize: Theme.barIconSize(root.barThickness, -4)
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
active: root.showPrinterIcon
|
active: root.showPrinterIcon
|
||||||
@@ -214,7 +215,25 @@ BasePill {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function hasNoVisibleIcons() {
|
function hasNoVisibleIcons() {
|
||||||
return !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon && !root.showVpnIcon && !root.showBrightnessIcon && !root.showMicIcon && !root.showBatteryIcon && !root.showPrinterIcon && !root.showScreenSharingIcon;
|
if (root.showScreenSharingIcon && NiriService.hasCasts)
|
||||||
|
return false;
|
||||||
|
if (root.showNetworkIcon && NetworkService.networkAvailable)
|
||||||
|
return false;
|
||||||
|
if (root.showVpnIcon && NetworkService.vpnAvailable && NetworkService.vpnConnected)
|
||||||
|
return false;
|
||||||
|
if (root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled)
|
||||||
|
return false;
|
||||||
|
if (root.showAudioIcon)
|
||||||
|
return false;
|
||||||
|
if (root.showMicIcon)
|
||||||
|
return false;
|
||||||
|
if (root.showBrightnessIcon && DisplayService.brightnessAvailable && root.hasPinnedBrightnessDevice())
|
||||||
|
return false;
|
||||||
|
if (root.showBatteryIcon && BatteryService.batteryAvailable)
|
||||||
|
return false;
|
||||||
|
if (root.showPrinterIcon && CupsService.cupsAvailable && root.hasPrintJobs())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
content: Component {
|
content: Component {
|
||||||
@@ -225,56 +244,74 @@ BasePill {
|
|||||||
Column {
|
Column {
|
||||||
id: controlColumn
|
id: controlColumn
|
||||||
visible: root.isVerticalOrientation
|
visible: root.isVerticalOrientation
|
||||||
anchors.centerIn: parent
|
width: root.vIconSize
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: "screen_record"
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: NiriService.hasActiveCast ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showScreenSharingIcon && NiriService.hasCasts
|
visible: root.showScreenSharingIcon && NiriService.hasCasts
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "screen_record"
|
||||||
|
size: root.vIconSize
|
||||||
|
color: NiriService.hasActiveCast ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: root.getNetworkIconName()
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: root.getNetworkIconColor()
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showNetworkIcon && NetworkService.networkAvailable
|
visible: root.showNetworkIcon && NetworkService.networkAvailable
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: root.getNetworkIconName()
|
||||||
|
size: root.vIconSize
|
||||||
|
color: root.getNetworkIconColor()
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: "vpn_lock"
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: NetworkService.vpnConnected ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showVpnIcon && NetworkService.vpnAvailable && NetworkService.vpnConnected
|
visible: root.showVpnIcon && NetworkService.vpnAvailable && NetworkService.vpnConnected
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "vpn_lock"
|
||||||
|
size: root.vIconSize
|
||||||
|
color: NetworkService.vpnConnected ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: "bluetooth"
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: BluetoothService.connected ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
visible: root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "bluetooth"
|
||||||
|
size: root.vIconSize
|
||||||
|
color: BluetoothService.connected ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
width: audioIconV.implicitWidth + 4
|
width: root.vIconSize
|
||||||
height: audioIconV.implicitHeight + (root.showAudioPercent ? audioPercentV.implicitHeight : 0) + 4
|
height: root.vIconSize + (root.showAudioPercent ? audioPercentV.implicitHeight + 2 : 0)
|
||||||
color: "transparent"
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showAudioIcon
|
visible: root.showAudioIcon
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
id: audioIconV
|
id: audioIconV
|
||||||
name: root.getVolumeIconName()
|
name: root.getVolumeIconName()
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
size: root.vIconSize
|
||||||
color: Theme.widgetIconColor
|
color: Theme.widgetIconColor
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -301,21 +338,18 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
width: micIconV.implicitWidth + 4
|
width: root.vIconSize
|
||||||
height: micIconV.implicitHeight + (root.showAudioPercent ? micPercentV.implicitHeight : 0) + 4
|
height: root.vIconSize + (root.showMicPercent ? micPercentV.implicitHeight + 2 : 0)
|
||||||
color: "transparent"
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showMicIcon
|
visible: root.showMicIcon
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
id: micIconV
|
id: micIconV
|
||||||
name: root.getMicIconName()
|
name: root.getMicIconName()
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
size: root.vIconSize
|
||||||
color: root.getMicIconColor()
|
color: root.getMicIconColor()
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -342,21 +376,18 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
width: brightnessIconV.implicitWidth + 4
|
width: root.vIconSize
|
||||||
height: brightnessIconV.implicitHeight + (root.showBrightnessPercent ? brightnessPercentV.implicitHeight : 0) + 4
|
height: root.vIconSize + (root.showBrightnessPercent ? brightnessPercentV.implicitHeight + 2 : 0)
|
||||||
color: "transparent"
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showBrightnessIcon && DisplayService.brightnessAvailable && root.hasPinnedBrightnessDevice()
|
visible: root.showBrightnessIcon && DisplayService.brightnessAvailable && root.hasPinnedBrightnessDevice()
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
id: brightnessIconV
|
id: brightnessIconV
|
||||||
name: root.getBrightnessIconName()
|
name: root.getBrightnessIconName()
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
size: root.vIconSize
|
||||||
color: Theme.widgetIconColor
|
color: Theme.widgetIconColor
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -380,28 +411,43 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: root.getBatteryIconColor()
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showBatteryIcon && BatteryService.batteryAvailable
|
visible: root.showBatteryIcon && BatteryService.batteryAvailable
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
|
||||||
|
size: root.vIconSize
|
||||||
|
color: root.getBatteryIconColor()
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: "print"
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: Theme.primary
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.showPrinterIcon && CupsService.cupsAvailable && root.hasPrintJobs()
|
visible: root.showPrinterIcon && CupsService.cupsAvailable && root.hasPrintJobs()
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "print"
|
||||||
|
size: root.vIconSize
|
||||||
|
color: Theme.primary
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankIcon {
|
Item {
|
||||||
name: "settings"
|
width: root.vIconSize
|
||||||
size: Theme.barIconSize(root.barThickness, -4)
|
height: root.vIconSize
|
||||||
color: root.isActive ? Theme.primary : Theme.widgetIconColor
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: root.hasNoVisibleIcons()
|
visible: root.hasNoVisibleIcons()
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "settings"
|
||||||
|
size: root.vIconSize
|
||||||
|
color: root.isActive ? Theme.primary : Theme.widgetIconColor
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -155,9 +155,17 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
size: 18
|
||||||
|
name: "sports_esports"
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
visible: root.isVerticalOrientation && activeWindow && activeWindow.appId && appIcon.status !== Image.Ready && Paths.isSteamApp(activeWindow.appId)
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: root.isVerticalOrientation && activeWindow && activeWindow.appId && appIcon.status !== Image.Ready
|
visible: root.isVerticalOrientation && activeWindow && activeWindow.appId && appIcon.status !== Image.Ready && !Paths.isSteamApp(activeWindow.appId)
|
||||||
text: {
|
text: {
|
||||||
if (!activeWindow || !activeWindow.appId)
|
if (!activeWindow || !activeWindow.appId)
|
||||||
return "?";
|
return "?";
|
||||||
|
|||||||
@@ -393,9 +393,19 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: (widgetData?.runningAppsCompactMode !== undefined ? widgetData.runningAppsCompactMode : SettingsData.runningAppsCompactMode) ? Math.round((parent.width - Theme.barIconSize(root.barThickness)) / 2) : Theme.spacingXS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
size: Theme.barIconSize(root.barThickness)
|
||||||
|
name: "sports_esports"
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
visible: !iconImg.visible && Paths.isSteamApp(appId)
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: !iconImg.visible
|
visible: !iconImg.visible && !Paths.isSteamApp(appId)
|
||||||
text: {
|
text: {
|
||||||
root._desktopEntriesUpdateTrigger;
|
root._desktopEntriesUpdateTrigger;
|
||||||
if (!appId)
|
if (!appId)
|
||||||
@@ -628,9 +638,19 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: (widgetData?.runningAppsCompactMode !== undefined ? widgetData.runningAppsCompactMode : SettingsData.runningAppsCompactMode) ? Math.round((parent.width - Theme.barIconSize(root.barThickness)) / 2) : Theme.spacingXS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
size: Theme.barIconSize(root.barThickness)
|
||||||
|
name: "sports_esports"
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
visible: !iconImg.visible && Paths.isSteamApp(appId)
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: !iconImg.visible
|
visible: !iconImg.visible && !Paths.isSteamApp(appId)
|
||||||
text: {
|
text: {
|
||||||
root._desktopEntriesUpdateTrigger;
|
root._desktopEntriesUpdateTrigger;
|
||||||
if (!appId)
|
if (!appId)
|
||||||
|
|||||||
@@ -265,6 +265,7 @@ Item {
|
|||||||
|
|
||||||
if (!byApp[key]) {
|
if (!byApp[key]) {
|
||||||
const isQuickshell = keyBase === "org.quickshell";
|
const isQuickshell = keyBase === "org.quickshell";
|
||||||
|
const isSteamApp = Paths.isSteamApp(keyBase);
|
||||||
const moddedId = Paths.moddedAppId(keyBase);
|
const moddedId = Paths.moddedAppId(keyBase);
|
||||||
const desktopEntry = DesktopEntries.heuristicLookup(moddedId);
|
const desktopEntry = DesktopEntries.heuristicLookup(moddedId);
|
||||||
const icon = Paths.getAppIcon(keyBase, desktopEntry);
|
const icon = Paths.getAppIcon(keyBase, desktopEntry);
|
||||||
@@ -272,6 +273,7 @@ Item {
|
|||||||
"type": "icon",
|
"type": "icon",
|
||||||
"icon": icon,
|
"icon": icon,
|
||||||
"isQuickshell": isQuickshell,
|
"isQuickshell": isQuickshell,
|
||||||
|
"isSteamApp": isSteamApp,
|
||||||
"active": !!((w.activated || w.is_focused) || (CompositorService.isNiri && w.is_focused)),
|
"active": !!((w.activated || w.is_focused) || (CompositorService.isNiri && w.is_focused)),
|
||||||
"count": 1,
|
"count": 1,
|
||||||
"windowId": w.address || w.id,
|
"windowId": w.address || w.id,
|
||||||
@@ -1135,7 +1137,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: modelData.icon
|
source: modelData.icon
|
||||||
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
|
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
|
||||||
visible: !modelData.isQuickshell
|
visible: !modelData.isQuickshell && !modelData.isSteamApp
|
||||||
}
|
}
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
@@ -1151,6 +1153,22 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: modelData.icon
|
||||||
|
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
|
||||||
|
visible: modelData.isSteamApp && modelData.icon
|
||||||
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
size: root.appIconSize
|
||||||
|
name: "sports_esports"
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
|
||||||
|
visible: modelData.isSteamApp && !modelData.icon
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: rowAppMouseArea
|
id: rowAppMouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -1229,7 +1247,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: modelData.icon
|
source: modelData.icon
|
||||||
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
|
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
|
||||||
visible: !modelData.isQuickshell
|
visible: !modelData.isQuickshell && !modelData.isSteamApp
|
||||||
}
|
}
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
@@ -1245,6 +1263,22 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: modelData.icon
|
||||||
|
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
|
||||||
|
visible: modelData.isSteamApp && modelData.icon
|
||||||
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
size: root.appIconSize
|
||||||
|
name: "sports_esports"
|
||||||
|
color: Theme.widgetTextColor
|
||||||
|
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
|
||||||
|
visible: modelData.isSteamApp && !modelData.icon
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: colAppMouseArea
|
id: colAppMouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ Item {
|
|||||||
width: actualIconSize
|
width: actualIconSize
|
||||||
height: actualIconSize
|
height: actualIconSize
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: iconImg.status !== Image.Ready
|
visible: iconImg.status !== Image.Ready && appData && appData.appId && !Paths.isSteamApp(appData.appId)
|
||||||
color: Theme.surfaceLight
|
color: Theme.surfaceLight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
border.width: 1
|
border.width: 1
|
||||||
@@ -425,6 +425,14 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
size: actualIconSize
|
||||||
|
name: "sports_esports"
|
||||||
|
color: Theme.surfaceText
|
||||||
|
visible: iconImg.status !== Image.Ready && appData && appData.appId && Paths.isSteamApp(appData.appId)
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
anchors.horizontalCenter: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right ? undefined : parent.horizontalCenter
|
anchors.horizontalCenter: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right ? undefined : parent.horizontalCenter
|
||||||
anchors.verticalCenter: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right ? parent.verticalCenter : undefined
|
anchors.verticalCenter: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right ? parent.verticalCenter : undefined
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
export WLR_DRM_DEVICES=/dev/dri/card1
|
|
||||||
|
|
||||||
COMPOSITOR=""
|
COMPOSITOR=""
|
||||||
COMPOSITOR_CONFIG=""
|
COMPOSITOR_CONFIG=""
|
||||||
DMS_PATH="dms-greeter"
|
DMS_PATH="dms-greeter"
|
||||||
@@ -16,7 +14,7 @@ dms-greeter - DankMaterialShell greeter launcher
|
|||||||
Usage: dms-greeter --command COMPOSITOR [OPTIONS]
|
Usage: dms-greeter --command COMPOSITOR [OPTIONS]
|
||||||
|
|
||||||
Required:
|
Required:
|
||||||
--command COMPOSITOR Compositor to use (niri, hyprland, sway, scroll or mangowc)
|
--command COMPOSITOR Compositor to use (niri, hyprland, sway, scroll, mangowc, or labwc)
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-C, --config PATH Custom compositor config file
|
-C, --config PATH Custom compositor config file
|
||||||
@@ -33,6 +31,7 @@ Examples:
|
|||||||
dms-greeter --command scroll -p /home/user/.config/quickshell/custom-dms
|
dms-greeter --command scroll -p /home/user/.config/quickshell/custom-dms
|
||||||
dms-greeter --command niri --cache-dir /tmp/dmsgreeter
|
dms-greeter --command niri --cache-dir /tmp/dmsgreeter
|
||||||
dms-greeter --command mangowc
|
dms-greeter --command mangowc
|
||||||
|
dms-greeter --command labwc
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +230,15 @@ SCROLL_EOF
|
|||||||
exec scroll -c "$COMPOSITOR_CONFIG"
|
exec scroll -c "$COMPOSITOR_CONFIG"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
labwc)
|
||||||
|
if [[ -n "$COMPOSITOR_CONFIG" ]]; then
|
||||||
|
exec labwc --config "$COMPOSITOR_CONFIG" --session "$QS_CMD"
|
||||||
|
else
|
||||||
|
exec labwc --session "$QS_CMD"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
mangowc)
|
mangowc)
|
||||||
if [[ -n "$COMPOSITOR_CONFIG" ]]; then
|
if [[ -n "$COMPOSITOR_CONFIG" ]]; then
|
||||||
exec mango -c "$COMPOSITOR_CONFIG" -s "$QS_CMD && mmsg -d quit"
|
exec mango -c "$COMPOSITOR_CONFIG" -s "$QS_CMD && mmsg -d quit"
|
||||||
@@ -241,7 +249,7 @@ SCROLL_EOF
|
|||||||
|
|
||||||
*)
|
*)
|
||||||
echo "Error: Unsupported compositor: $COMPOSITOR" >&2
|
echo "Error: Unsupported compositor: $COMPOSITOR" >&2
|
||||||
echo "Supported compositors: niri, hyprland, sway, mangowc" >&2
|
echo "Supported compositors: niri, hyprland, sway, scroll, mangowc, labwc" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -262,9 +262,7 @@ DankOSD {
|
|||||||
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
|
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
|
||||||
|
|
||||||
function onVolumeChanged() {
|
function onVolumeChanged() {
|
||||||
if (!vertSlider.dragging) {
|
vertSlider.value = Math.min(100, Math.round(AudioService.sink.audio.volume * 100));
|
||||||
vertSlider.value = Math.min(100, Math.round(AudioService.sink.audio.volume * 100));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,10 +177,11 @@ Item {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
if (!SystemUpdateService.shellVersion)
|
if (!SystemUpdateService.shellVersion && !DMSService.cliVersion)
|
||||||
return "dms";
|
return "dms";
|
||||||
|
|
||||||
let version = SystemUpdateService.shellVersion;
|
let version = SystemUpdateService.shellVersion || "";
|
||||||
|
let cliVersion = DMSService.cliVersion || "";
|
||||||
|
|
||||||
// Debian/Ubuntu/OpenSUSE git format: 1.0.3+git2264.c5c5ce84
|
// Debian/Ubuntu/OpenSUSE git format: 1.0.3+git2264.c5c5ce84
|
||||||
let match = version.match(/^([\d.]+)\+git(\d+)\./);
|
let match = version.match(/^([\d.]+)\+git(\d+)\./);
|
||||||
@@ -191,7 +192,25 @@ Item {
|
|||||||
// Fedora COPR git format: 0.0.git.2267.d430cae9
|
// Fedora COPR git format: 0.0.git.2267.d430cae9
|
||||||
match = version.match(/^[\d.]+\.git\.(\d+)\./);
|
match = version.match(/^[\d.]+\.git\.(\d+)\./);
|
||||||
if (match) {
|
if (match) {
|
||||||
return `dms (git) v1.0.3-${match[1]}`;
|
function extractBaseVersion(value) {
|
||||||
|
if (!value)
|
||||||
|
return "";
|
||||||
|
let baseMatch = value.match(/(\d+\.\d+\.\d+)/);
|
||||||
|
if (baseMatch)
|
||||||
|
return baseMatch[1];
|
||||||
|
baseMatch = value.match(/(\d+\.\d+)/);
|
||||||
|
if (baseMatch)
|
||||||
|
return baseMatch[1];
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
let baseVersion = extractBaseVersion(cliVersion);
|
||||||
|
if (!baseVersion)
|
||||||
|
baseVersion = extractBaseVersion(SystemUpdateService.semverVersion);
|
||||||
|
if (baseVersion) {
|
||||||
|
return `dms (git) v${baseVersion}-${match[1]}`;
|
||||||
|
}
|
||||||
|
return `dms (git) v${match[1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stable release format: 1.0.3
|
// Stable release format: 1.0.3
|
||||||
@@ -200,6 +219,18 @@ Item {
|
|||||||
return `dms v${match[1]}`;
|
return `dms v${match[1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!version && cliVersion) {
|
||||||
|
match = cliVersion.match(/^([\d.]+)\+git(\d+)\./);
|
||||||
|
if (match) {
|
||||||
|
return `dms (git) v${match[1]}-${match[2]}`;
|
||||||
|
}
|
||||||
|
match = cliVersion.match(/^([\d.]+)$/);
|
||||||
|
if (match) {
|
||||||
|
return `dms v${match[1]}`;
|
||||||
|
}
|
||||||
|
return `dms ${cliVersion}`;
|
||||||
|
}
|
||||||
|
|
||||||
return `dms ${version}`;
|
return `dms ${version}`;
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeXLarge
|
font.pixelSize: Theme.fontSizeXLarge
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ Item {
|
|||||||
SettingsButtonGroupRow {
|
SettingsButtonGroupRow {
|
||||||
text: I18n.tr("Position")
|
text: I18n.tr("Position")
|
||||||
model: ["Top", "Bottom", "Left", "Right"]
|
model: ["Top", "Bottom", "Left", "Right"]
|
||||||
|
buttonPadding: Theme.spacingS
|
||||||
|
minButtonWidth: 44
|
||||||
|
textSize: Theme.fontSizeSmall
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
switch (SettingsData.dockPosition) {
|
switch (SettingsData.dockPosition) {
|
||||||
case SettingsData.Position.Top:
|
case SettingsData.Position.Top:
|
||||||
@@ -129,6 +132,9 @@ Item {
|
|||||||
tags: ["dock", "indicator", "style", "circle", "line"]
|
tags: ["dock", "indicator", "style", "circle", "line"]
|
||||||
text: I18n.tr("Indicator Style")
|
text: I18n.tr("Indicator Style")
|
||||||
model: ["Circle", "Line"]
|
model: ["Circle", "Line"]
|
||||||
|
buttonPadding: Theme.spacingS
|
||||||
|
minButtonWidth: 44
|
||||||
|
textSize: Theme.fontSizeSmall
|
||||||
currentIndex: SettingsData.dockIndicatorStyle === "circle" ? 0 : 1
|
currentIndex: SettingsData.dockIndicatorStyle === "circle" ? 0 : 1
|
||||||
onSelectionChanged: (index, selected) => {
|
onSelectionChanged: (index, selected) => {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@@ -225,6 +231,9 @@ Item {
|
|||||||
description: I18n.tr("Choose the border accent color")
|
description: I18n.tr("Choose the border accent color")
|
||||||
visible: SettingsData.dockBorderEnabled
|
visible: SettingsData.dockBorderEnabled
|
||||||
model: ["Surface", "Secondary", "Primary"]
|
model: ["Surface", "Secondary", "Primary"]
|
||||||
|
buttonPadding: Theme.spacingS
|
||||||
|
minButtonWidth: 44
|
||||||
|
textSize: Theme.fontSizeSmall
|
||||||
currentIndex: {
|
currentIndex: {
|
||||||
switch (SettingsData.dockBorderColor) {
|
switch (SettingsData.dockBorderColor) {
|
||||||
case "surfaceText":
|
case "surfaceText":
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Item {
|
|||||||
property string expandedVpnUuid: ""
|
property string expandedVpnUuid: ""
|
||||||
property string expandedWifiSsid: ""
|
property string expandedWifiSsid: ""
|
||||||
property string expandedEthDevice: ""
|
property string expandedEthDevice: ""
|
||||||
|
property int maxPinnedWifiNetworks: 3
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
NetworkService.addRef();
|
NetworkService.addRef();
|
||||||
@@ -30,6 +31,40 @@ Item {
|
|||||||
vpnFileBrowserLoader.item.open();
|
vpnFileBrowserLoader.item.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePinList(value) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return value.filter(v => v)
|
||||||
|
if (typeof value === "string" && value.length > 0)
|
||||||
|
return [value]
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPinnedWifiNetworks() {
|
||||||
|
const pins = SettingsData.wifiNetworkPins || {}
|
||||||
|
return normalizePinList(pins["preferredWifi"])
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleWifiPin(ssid) {
|
||||||
|
const pins = JSON.parse(JSON.stringify(SettingsData.wifiNetworkPins || {}))
|
||||||
|
let pinnedList = normalizePinList(pins["preferredWifi"])
|
||||||
|
const pinIndex = pinnedList.indexOf(ssid)
|
||||||
|
|
||||||
|
if (pinIndex !== -1) {
|
||||||
|
pinnedList.splice(pinIndex, 1)
|
||||||
|
} else {
|
||||||
|
pinnedList.unshift(ssid)
|
||||||
|
if (pinnedList.length > maxPinnedWifiNetworks)
|
||||||
|
pinnedList = pinnedList.slice(0, maxPinnedWifiNetworks)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinnedList.length > 0)
|
||||||
|
pins["preferredWifi"] = pinnedList
|
||||||
|
else
|
||||||
|
delete pins["preferredWifi"]
|
||||||
|
|
||||||
|
SettingsData.set("wifiNetworkPins", pins)
|
||||||
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
id: vpnFileBrowserLoader
|
id: vpnFileBrowserLoader
|
||||||
active: false
|
active: false
|
||||||
@@ -1025,15 +1060,19 @@ Item {
|
|||||||
model: {
|
model: {
|
||||||
const ssid = NetworkService.currentWifiSSID;
|
const ssid = NetworkService.currentWifiSSID;
|
||||||
const networks = NetworkService.wifiNetworks || [];
|
const networks = NetworkService.wifiNetworks || [];
|
||||||
const pins = SettingsData.wifiNetworkPins || {};
|
const pinnedList = networkTab.getPinnedWifiNetworks();
|
||||||
const pinnedSSID = pins["preferredWifi"];
|
|
||||||
|
|
||||||
let sorted = [...networks];
|
let sorted = [...networks];
|
||||||
sorted.sort((a, b) => {
|
sorted.sort((a, b) => {
|
||||||
if (a.ssid === pinnedSSID && b.ssid !== pinnedSSID)
|
const aPinnedIndex = pinnedList.indexOf(a.ssid)
|
||||||
return -1;
|
const bPinnedIndex = pinnedList.indexOf(b.ssid)
|
||||||
if (b.ssid === pinnedSSID && a.ssid !== pinnedSSID)
|
if (aPinnedIndex !== -1 || bPinnedIndex !== -1) {
|
||||||
return 1;
|
if (aPinnedIndex === -1)
|
||||||
|
return 1
|
||||||
|
if (bPinnedIndex === -1)
|
||||||
|
return -1
|
||||||
|
return aPinnedIndex - bPinnedIndex
|
||||||
|
}
|
||||||
if (a.ssid === ssid)
|
if (a.ssid === ssid)
|
||||||
return -1;
|
return -1;
|
||||||
if (b.ssid === ssid)
|
if (b.ssid === ssid)
|
||||||
@@ -1049,7 +1088,7 @@ Item {
|
|||||||
required property int index
|
required property int index
|
||||||
|
|
||||||
readonly property bool isConnected: modelData.ssid === NetworkService.currentWifiSSID
|
readonly property bool isConnected: modelData.ssid === NetworkService.currentWifiSSID
|
||||||
readonly property bool isPinned: (SettingsData.wifiNetworkPins || {})["preferredWifi"] === modelData.ssid
|
readonly property bool isPinned: networkTab.getPinnedWifiNetworks().includes(modelData.ssid)
|
||||||
readonly property bool isExpanded: networkTab.expandedWifiSsid === modelData.ssid
|
readonly property bool isExpanded: networkTab.expandedWifiSsid === modelData.ssid
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -1224,13 +1263,7 @@ Item {
|
|||||||
buttonSize: 28
|
buttonSize: 28
|
||||||
iconColor: isPinned ? Theme.primary : Theme.surfaceVariantText
|
iconColor: isPinned ? Theme.primary : Theme.surfaceVariantText
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const pins = JSON.parse(JSON.stringify(SettingsData.wifiNetworkPins || {}));
|
networkTab.toggleWifiPin(modelData.ssid)
|
||||||
if (isPinned) {
|
|
||||||
delete pins["preferredWifi"];
|
|
||||||
} else {
|
|
||||||
pins["preferredWifi"] = modelData.ssid;
|
|
||||||
}
|
|
||||||
SettingsData.set("wifiNetworkPins", pins);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -270,7 +270,9 @@ FloatingWindow {
|
|||||||
root.updateFilteredPlugins();
|
root.updateFilteredPlugins();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
thirdPartyConfirmModal.visible = true;
|
thirdPartyConfirmLoader.active = true;
|
||||||
|
if (thirdPartyConfirmLoader.item)
|
||||||
|
thirdPartyConfirmLoader.item.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,119 +670,132 @@ FloatingWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingWindow {
|
LazyLoader {
|
||||||
id: thirdPartyConfirmModal
|
id: thirdPartyConfirmLoader
|
||||||
|
active: false
|
||||||
|
|
||||||
objectName: "thirdPartyConfirm"
|
FloatingWindow {
|
||||||
title: I18n.tr("Third-Party Plugin Warning")
|
id: thirdPartyConfirmModal
|
||||||
implicitWidth: 500
|
|
||||||
implicitHeight: 350
|
|
||||||
color: Theme.surfaceContainer
|
|
||||||
visible: false
|
|
||||||
|
|
||||||
FocusScope {
|
function show() {
|
||||||
anchors.fill: parent
|
visible = true;
|
||||||
focus: true
|
|
||||||
|
|
||||||
Keys.onPressed: event => {
|
|
||||||
if (event.key === Qt.Key_Escape) {
|
|
||||||
thirdPartyConfirmModal.visible = false;
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
function hide() {
|
||||||
|
visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
objectName: "thirdPartyConfirm"
|
||||||
|
title: I18n.tr("Third-Party Plugin Warning")
|
||||||
|
implicitWidth: 500
|
||||||
|
implicitHeight: 350
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
FocusScope {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingL
|
focus: true
|
||||||
spacing: Theme.spacingL
|
|
||||||
|
|
||||||
Row {
|
Keys.onPressed: event => {
|
||||||
width: parent.width
|
if (event.key === Qt.Key_Escape) {
|
||||||
spacing: Theme.spacingM
|
thirdPartyConfirmModal.hide();
|
||||||
|
event.accepted = true;
|
||||||
DankIcon {
|
|
||||||
name: "warning"
|
|
||||||
size: Theme.iconSize
|
|
||||||
color: Theme.warning
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Third-Party Plugin Warning")
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width - parent.spacing * 2 - Theme.iconSize - parent.children[1].implicitWidth - closeConfirmBtn.width
|
|
||||||
height: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
id: closeConfirmBtn
|
|
||||||
iconName: "close"
|
|
||||||
iconSize: Theme.iconSize - 2
|
|
||||||
iconColor: Theme.outline
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
onClicked: thirdPartyConfirmModal.visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
width: parent.width
|
|
||||||
text: I18n.tr("Third-party plugins are created by the community and are not officially supported by DankMaterialShell.\n\nThese plugins may pose security and privacy risks - install at your own risk.")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
spacing: Theme.spacingS
|
anchors.margins: Theme.spacingL
|
||||||
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
StyledText {
|
Row {
|
||||||
text: I18n.tr("• Plugins may contain bugs or security issues")
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
spacing: Theme.spacingM
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
|
DankIcon {
|
||||||
|
name: "warning"
|
||||||
|
size: Theme.iconSize
|
||||||
|
color: Theme.warning
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Third-Party Plugin Warning")
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - parent.spacing * 2 - Theme.iconSize - parent.children[1].implicitWidth - closeConfirmBtn.width
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: closeConfirmBtn
|
||||||
|
iconName: "close"
|
||||||
|
iconSize: Theme.iconSize - 2
|
||||||
|
iconColor: Theme.outline
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: thirdPartyConfirmModal.hide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("• Review code before installation when possible")
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
text: I18n.tr("Third-party plugins are created by the community and are not officially supported by DankMaterialShell.\n\nThese plugins may pose security and privacy risks - install at your own risk.")
|
||||||
color: Theme.surfaceVariantText
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
Column {
|
||||||
text: I18n.tr("• Install only from trusted sources")
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
spacing: Theme.spacingS
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
StyledText {
|
||||||
width: parent.width
|
text: I18n.tr("• Plugins may contain bugs or security issues")
|
||||||
height: parent.height - parent.spacing * 3 - y
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
}
|
color: Theme.surfaceVariantText
|
||||||
|
}
|
||||||
|
|
||||||
Row {
|
StyledText {
|
||||||
anchors.right: parent.right
|
text: I18n.tr("• Review code before installation when possible")
|
||||||
spacing: Theme.spacingM
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
}
|
||||||
|
|
||||||
DankButton {
|
StyledText {
|
||||||
text: I18n.tr("Cancel")
|
text: I18n.tr("• Install only from trusted sources")
|
||||||
iconName: "close"
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
onClicked: thirdPartyConfirmModal.visible = false
|
color: Theme.surfaceVariantText
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankButton {
|
Item {
|
||||||
text: I18n.tr("I Understand")
|
width: parent.width
|
||||||
iconName: "check"
|
height: parent.height - parent.spacing * 3 - y
|
||||||
onClicked: {
|
}
|
||||||
SessionData.setShowThirdPartyPlugins(true);
|
|
||||||
root.updateFilteredPlugins();
|
Row {
|
||||||
thirdPartyConfirmModal.visible = false;
|
anchors.right: parent.right
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
DankButton {
|
||||||
|
text: I18n.tr("Cancel")
|
||||||
|
iconName: "close"
|
||||||
|
onClicked: thirdPartyConfirmModal.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
DankButton {
|
||||||
|
text: I18n.tr("I Understand")
|
||||||
|
iconName: "check"
|
||||||
|
onClicked: {
|
||||||
|
SessionData.setShowThirdPartyPlugins(true);
|
||||||
|
root.updateFilteredPlugins();
|
||||||
|
thirdPartyConfirmModal.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ StyledRect {
|
|||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
id: headerIcon
|
id: headerIcon
|
||||||
@@ -69,6 +70,8 @@ StyledRect {
|
|||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: root.title !== ""
|
visible: root.title !== ""
|
||||||
|
width: parent.width - (headerIcon.visible ? headerIcon.width + parent.spacing : 0)
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -402,6 +402,24 @@ Item {
|
|||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cloneWidgetData(widget) {
|
||||||
|
if (typeof widget === "string")
|
||||||
|
return {
|
||||||
|
"id": widget,
|
||||||
|
"enabled": true
|
||||||
|
};
|
||||||
|
var result = {
|
||||||
|
"id": widget.id,
|
||||||
|
"enabled": widget.enabled
|
||||||
|
};
|
||||||
|
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon"];
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
if (widget[keys[i]] !== undefined)
|
||||||
|
result[keys[i]] = widget[keys[i]];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function handleItemEnabledChanged(sectionId, itemId, enabled) {
|
function handleItemEnabledChanged(sectionId, itemId, enabled) {
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).slice();
|
||||||
for (var i = 0; i < widgets.length; i++) {
|
for (var i = 0; i < widgets.length; i++) {
|
||||||
@@ -409,43 +427,8 @@ Item {
|
|||||||
var widgetId = typeof widget === "string" ? widget : widget.id;
|
var widgetId = typeof widget === "string" ? widget : widget.id;
|
||||||
if (widgetId !== itemId)
|
if (widgetId !== itemId)
|
||||||
continue;
|
continue;
|
||||||
|
var newWidget = cloneWidgetData(widget);
|
||||||
if (typeof widget === "string") {
|
newWidget.enabled = enabled;
|
||||||
widgets[i] = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": enabled
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": enabled
|
|
||||||
};
|
|
||||||
if (widget.size !== undefined)
|
|
||||||
newWidget.size = widget.size;
|
|
||||||
if (widget.selectedGpuIndex !== undefined)
|
|
||||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex;
|
|
||||||
else if (widget.id === "gpuTemp")
|
|
||||||
newWidget.selectedGpuIndex = 0;
|
|
||||||
if (widget.pciId !== undefined)
|
|
||||||
newWidget.pciId = widget.pciId;
|
|
||||||
else if (widget.id === "gpuTemp")
|
|
||||||
newWidget.pciId = "";
|
|
||||||
if (widget.id === "controlCenterButton") {
|
|
||||||
newWidget.showNetworkIcon = widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon;
|
|
||||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon;
|
|
||||||
newWidget.showAudioIcon = widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon;
|
|
||||||
newWidget.showAudioPercent = widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent;
|
|
||||||
newWidget.showVpnIcon = widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon;
|
|
||||||
newWidget.showBrightnessIcon = widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon;
|
|
||||||
newWidget.showBrightnessPercent = widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent;
|
|
||||||
newWidget.showMicIcon = widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon;
|
|
||||||
newWidget.showMicPercent = widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent;
|
|
||||||
newWidget.showBatteryIcon = widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon;
|
|
||||||
newWidget.showPrinterIcon = widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon;
|
|
||||||
newWidget.showScreenSharingIcon = widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon;
|
|
||||||
}
|
|
||||||
widgets[i] = newWidget;
|
widgets[i] = newWidget;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -458,130 +441,36 @@ Item {
|
|||||||
|
|
||||||
function handleSpacerSizeChanged(sectionId, widgetIndex, newSize) {
|
function handleSpacerSizeChanged(sectionId, widgetIndex, newSize) {
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).slice();
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
if (widgetIndex < 0 || widgetIndex >= widgets.length)
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
var widget = widgets[widgetIndex];
|
var widget = widgets[widgetIndex];
|
||||||
var widgetId = typeof widget === "string" ? widget : widget.id;
|
var widgetId = typeof widget === "string" ? widget : widget.id;
|
||||||
if (widgetId !== "spacer") {
|
if (widgetId !== "spacer")
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
return;
|
||||||
}
|
var newWidget = cloneWidgetData(widget);
|
||||||
|
newWidget.size = newSize;
|
||||||
if (typeof widget === "string") {
|
|
||||||
widgets[widgetIndex] = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": true,
|
|
||||||
"size": newSize
|
|
||||||
};
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled,
|
|
||||||
"size": newSize
|
|
||||||
};
|
|
||||||
if (widget.selectedGpuIndex !== undefined)
|
|
||||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex;
|
|
||||||
if (widget.pciId !== undefined)
|
|
||||||
newWidget.pciId = widget.pciId;
|
|
||||||
if (widget.id === "controlCenterButton") {
|
|
||||||
newWidget.showNetworkIcon = widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon;
|
|
||||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon;
|
|
||||||
newWidget.showAudioIcon = widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon;
|
|
||||||
newWidget.showAudioPercent = widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent;
|
|
||||||
newWidget.showVpnIcon = widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon;
|
|
||||||
newWidget.showBrightnessIcon = widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon;
|
|
||||||
newWidget.showBrightnessPercent = widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent;
|
|
||||||
newWidget.showMicIcon = widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon;
|
|
||||||
newWidget.showMicPercent = widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent;
|
|
||||||
newWidget.showBatteryIcon = widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon;
|
|
||||||
newWidget.showPrinterIcon = widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon;
|
|
||||||
newWidget.showScreenSharingIcon = widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon;
|
|
||||||
}
|
|
||||||
widgets[widgetIndex] = newWidget;
|
widgets[widgetIndex] = newWidget;
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGpuSelectionChanged(sectionId, widgetIndex, selectedGpuIndex) {
|
function handleGpuSelectionChanged(sectionId, widgetIndex, selectedGpuIndex) {
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).slice();
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
if (widgetIndex < 0 || widgetIndex >= widgets.length)
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
var pciId = DgopService.availableGpus && DgopService.availableGpus.length > selectedGpuIndex ? DgopService.availableGpus[selectedGpuIndex].pciId : "";
|
var pciId = DgopService.availableGpus && DgopService.availableGpus.length > selectedGpuIndex ? DgopService.availableGpus[selectedGpuIndex].pciId : "";
|
||||||
var widget = widgets[widgetIndex];
|
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
||||||
if (typeof widget === "string") {
|
newWidget.selectedGpuIndex = selectedGpuIndex;
|
||||||
widgets[widgetIndex] = {
|
newWidget.pciId = pciId;
|
||||||
"id": widget,
|
|
||||||
"enabled": true,
|
|
||||||
"selectedGpuIndex": selectedGpuIndex,
|
|
||||||
"pciId": pciId
|
|
||||||
};
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled,
|
|
||||||
"selectedGpuIndex": selectedGpuIndex,
|
|
||||||
"pciId": pciId
|
|
||||||
};
|
|
||||||
if (widget.size !== undefined)
|
|
||||||
newWidget.size = widget.size;
|
|
||||||
widgets[widgetIndex] = newWidget;
|
widgets[widgetIndex] = newWidget;
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDiskMountSelectionChanged(sectionId, widgetIndex, mountPath) {
|
function handleDiskMountSelectionChanged(sectionId, widgetIndex, mountPath) {
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).slice();
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
if (widgetIndex < 0 || widgetIndex >= widgets.length)
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
return;
|
||||||
}
|
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
||||||
|
newWidget.mountPath = mountPath;
|
||||||
var widget = widgets[widgetIndex];
|
|
||||||
if (typeof widget === "string") {
|
|
||||||
widgets[widgetIndex] = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": true,
|
|
||||||
"mountPath": mountPath
|
|
||||||
};
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled,
|
|
||||||
"mountPath": mountPath
|
|
||||||
};
|
|
||||||
if (widget.size !== undefined)
|
|
||||||
newWidget.size = widget.size;
|
|
||||||
if (widget.selectedGpuIndex !== undefined)
|
|
||||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex;
|
|
||||||
if (widget.pciId !== undefined)
|
|
||||||
newWidget.pciId = widget.pciId;
|
|
||||||
if (widget.id === "controlCenterButton") {
|
|
||||||
newWidget.showNetworkIcon = widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon;
|
|
||||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon;
|
|
||||||
newWidget.showAudioIcon = widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon;
|
|
||||||
newWidget.showAudioPercent = widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent;
|
|
||||||
newWidget.showVpnIcon = widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon;
|
|
||||||
newWidget.showBrightnessIcon = widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon;
|
|
||||||
newWidget.showBrightnessPercent = widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent;
|
|
||||||
newWidget.showMicIcon = widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon;
|
|
||||||
newWidget.showMicPercent = widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent;
|
|
||||||
newWidget.showBatteryIcon = widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon;
|
|
||||||
newWidget.showPrinterIcon = widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon;
|
|
||||||
newWidget.showScreenSharingIcon = widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon;
|
|
||||||
}
|
|
||||||
widgets[widgetIndex] = newWidget;
|
widgets[widgetIndex] = newWidget;
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
@@ -590,33 +479,8 @@ Item {
|
|||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).slice();
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length)
|
if (widgetIndex < 0 || widgetIndex >= widgets.length)
|
||||||
return;
|
return;
|
||||||
|
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
||||||
var widget = widgets[widgetIndex];
|
|
||||||
if (typeof widget === "string") {
|
|
||||||
widget = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled !== undefined ? widget.enabled : true,
|
|
||||||
"showNetworkIcon": widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon,
|
|
||||||
"showBluetoothIcon": widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon,
|
|
||||||
"showAudioIcon": widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon,
|
|
||||||
"showAudioPercent": widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent,
|
|
||||||
"showVpnIcon": widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon,
|
|
||||||
"showBrightnessIcon": widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon,
|
|
||||||
"showBrightnessPercent": widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent,
|
|
||||||
"showMicIcon": widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon,
|
|
||||||
"showMicPercent": widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent,
|
|
||||||
"showBatteryIcon": widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon,
|
|
||||||
"showPrinterIcon": widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon,
|
|
||||||
"showScreenSharingIcon": widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon
|
|
||||||
};
|
|
||||||
newWidget[settingName] = value;
|
newWidget[settingName] = value;
|
||||||
|
|
||||||
widgets[widgetIndex] = newWidget;
|
widgets[widgetIndex] = newWidget;
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
@@ -641,47 +505,8 @@ Item {
|
|||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
||||||
var widget = widgets[widgetIndex];
|
newWidget.minimumWidth = enabled;
|
||||||
if (typeof widget === "string") {
|
|
||||||
widgets[widgetIndex] = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": true,
|
|
||||||
"minimumWidth": enabled
|
|
||||||
};
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled,
|
|
||||||
"minimumWidth": enabled
|
|
||||||
};
|
|
||||||
if (widget.size !== undefined)
|
|
||||||
newWidget.size = widget.size;
|
|
||||||
if (widget.selectedGpuIndex !== undefined)
|
|
||||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex;
|
|
||||||
if (widget.pciId !== undefined)
|
|
||||||
newWidget.pciId = widget.pciId;
|
|
||||||
if (widget.mountPath !== undefined)
|
|
||||||
newWidget.mountPath = widget.mountPath;
|
|
||||||
if (widget.showSwap !== undefined)
|
|
||||||
newWidget.showSwap = widget.showSwap;
|
|
||||||
if (widget.id === "controlCenterButton") {
|
|
||||||
newWidget.showNetworkIcon = widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon;
|
|
||||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon;
|
|
||||||
newWidget.showAudioIcon = widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon;
|
|
||||||
newWidget.showAudioPercent = widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent;
|
|
||||||
newWidget.showVpnIcon = widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon;
|
|
||||||
newWidget.showBrightnessIcon = widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon;
|
|
||||||
newWidget.showBrightnessPercent = widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent;
|
|
||||||
newWidget.showMicIcon = widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon;
|
|
||||||
newWidget.showMicPercent = widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent;
|
|
||||||
newWidget.showBatteryIcon = widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon;
|
|
||||||
newWidget.showPrinterIcon = widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon;
|
|
||||||
newWidget.showScreenSharingIcon = widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon;
|
|
||||||
}
|
|
||||||
widgets[widgetIndex] = newWidget;
|
widgets[widgetIndex] = newWidget;
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
@@ -692,143 +517,41 @@ Item {
|
|||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
||||||
var widget = widgets[widgetIndex];
|
newWidget.showSwap = enabled;
|
||||||
if (typeof widget === "string") {
|
|
||||||
widgets[widgetIndex] = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": true,
|
|
||||||
"showSwap": enabled
|
|
||||||
};
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled,
|
|
||||||
"showSwap": enabled
|
|
||||||
};
|
|
||||||
if (widget.size !== undefined)
|
|
||||||
newWidget.size = widget.size;
|
|
||||||
if (widget.selectedGpuIndex !== undefined)
|
|
||||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex;
|
|
||||||
if (widget.pciId !== undefined)
|
|
||||||
newWidget.pciId = widget.pciId;
|
|
||||||
if (widget.mountPath !== undefined)
|
|
||||||
newWidget.mountPath = widget.mountPath;
|
|
||||||
if (widget.minimumWidth !== undefined)
|
|
||||||
newWidget.minimumWidth = widget.minimumWidth;
|
|
||||||
if (widget.mediaSize !== undefined)
|
|
||||||
newWidget.mediaSize = widget.mediaSize;
|
|
||||||
if (widget.clockCompactMode !== undefined)
|
|
||||||
newWidget.clockCompactMode = widget.clockCompactMode;
|
|
||||||
if (widget.focusedWindowCompactMode !== undefined)
|
|
||||||
newWidget.focusedWindowCompactMode = widget.focusedWindowCompactMode;
|
|
||||||
if (widget.runningAppsCompactMode !== undefined)
|
|
||||||
newWidget.runningAppsCompactMode = widget.runningAppsCompactMode;
|
|
||||||
if (widget.keyboardLayoutNameCompactMode !== undefined)
|
|
||||||
newWidget.keyboardLayoutNameCompactMode = widget.keyboardLayoutNameCompactMode;
|
|
||||||
if (widget.id === "controlCenterButton") {
|
|
||||||
newWidget.showNetworkIcon = widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon;
|
|
||||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon;
|
|
||||||
newWidget.showAudioIcon = widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon;
|
|
||||||
newWidget.showAudioPercent = widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent;
|
|
||||||
newWidget.showVpnIcon = widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon;
|
|
||||||
newWidget.showBrightnessIcon = widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon;
|
|
||||||
newWidget.showBrightnessPercent = widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent;
|
|
||||||
newWidget.showMicIcon = widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon;
|
|
||||||
newWidget.showMicPercent = widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent;
|
|
||||||
newWidget.showBatteryIcon = widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon;
|
|
||||||
newWidget.showPrinterIcon = widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon;
|
|
||||||
newWidget.showScreenSharingIcon = widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon;
|
|
||||||
}
|
|
||||||
widgets[widgetIndex] = newWidget;
|
widgets[widgetIndex] = newWidget;
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCompactModeChanged(sectionId, widgetId, value) {
|
function handleCompactModeChanged(sectionId, widgetId, value) {
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).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 currentId = typeof widget === "string" ? widget : widget.id;
|
var currentId = typeof widget === "string" ? widget : widget.id;
|
||||||
|
|
||||||
if (currentId !== widgetId)
|
if (currentId !== widgetId)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (typeof widget === "string") {
|
var newWidget = cloneWidgetData(widget);
|
||||||
widgets[i] = {
|
|
||||||
"id": widget,
|
|
||||||
"enabled": true
|
|
||||||
};
|
|
||||||
widget = widgets[i];
|
|
||||||
} else {
|
|
||||||
var newWidget = {
|
|
||||||
"id": widget.id,
|
|
||||||
"enabled": widget.enabled
|
|
||||||
};
|
|
||||||
if (widget.size !== undefined)
|
|
||||||
newWidget.size = widget.size;
|
|
||||||
if (widget.selectedGpuIndex !== undefined)
|
|
||||||
newWidget.selectedGpuIndex = widget.selectedGpuIndex;
|
|
||||||
if (widget.pciId !== undefined)
|
|
||||||
newWidget.pciId = widget.pciId;
|
|
||||||
if (widget.mountPath !== undefined)
|
|
||||||
newWidget.mountPath = widget.mountPath;
|
|
||||||
if (widget.minimumWidth !== undefined)
|
|
||||||
newWidget.minimumWidth = widget.minimumWidth;
|
|
||||||
if (widget.showSwap !== undefined)
|
|
||||||
newWidget.showSwap = widget.showSwap;
|
|
||||||
if (widget.mediaSize !== undefined)
|
|
||||||
newWidget.mediaSize = widget.mediaSize;
|
|
||||||
if (widget.clockCompactMode !== undefined)
|
|
||||||
newWidget.clockCompactMode = widget.clockCompactMode;
|
|
||||||
if (widget.focusedWindowCompactMode !== undefined)
|
|
||||||
newWidget.focusedWindowCompactMode = widget.focusedWindowCompactMode;
|
|
||||||
if (widget.runningAppsCompactMode !== undefined)
|
|
||||||
newWidget.runningAppsCompactMode = widget.runningAppsCompactMode;
|
|
||||||
if (widget.keyboardLayoutNameCompactMode !== undefined)
|
|
||||||
newWidget.keyboardLayoutNameCompactMode = widget.keyboardLayoutNameCompactMode;
|
|
||||||
if (widget.id === "controlCenterButton") {
|
|
||||||
newWidget.showNetworkIcon = widget.showNetworkIcon ?? SettingsData.controlCenterShowNetworkIcon;
|
|
||||||
newWidget.showBluetoothIcon = widget.showBluetoothIcon ?? SettingsData.controlCenterShowBluetoothIcon;
|
|
||||||
newWidget.showAudioIcon = widget.showAudioIcon ?? SettingsData.controlCenterShowAudioIcon;
|
|
||||||
newWidget.showAudioPercent = widget.showAudioPercent ?? SettingsData.controlCenterShowAudioPercent;
|
|
||||||
newWidget.showVpnIcon = widget.showVpnIcon ?? SettingsData.controlCenterShowVpnIcon;
|
|
||||||
newWidget.showBrightnessIcon = widget.showBrightnessIcon ?? SettingsData.controlCenterShowBrightnessIcon;
|
|
||||||
newWidget.showBrightnessPercent = widget.showBrightnessPercent ?? SettingsData.controlCenterShowBrightnessPercent;
|
|
||||||
newWidget.showMicIcon = widget.showMicIcon ?? SettingsData.controlCenterShowMicIcon;
|
|
||||||
newWidget.showMicPercent = widget.showMicPercent ?? SettingsData.controlCenterShowMicPercent;
|
|
||||||
newWidget.showBatteryIcon = widget.showBatteryIcon ?? SettingsData.controlCenterShowBatteryIcon;
|
|
||||||
newWidget.showPrinterIcon = widget.showPrinterIcon ?? SettingsData.controlCenterShowPrinterIcon;
|
|
||||||
newWidget.showScreenSharingIcon = widget.showScreenSharingIcon ?? SettingsData.controlCenterShowScreenSharingIcon;
|
|
||||||
}
|
|
||||||
widgets[i] = newWidget;
|
|
||||||
widget = newWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (widgetId) {
|
switch (widgetId) {
|
||||||
case "music":
|
case "music":
|
||||||
widget.mediaSize = value;
|
newWidget.mediaSize = value;
|
||||||
break;
|
break;
|
||||||
case "clock":
|
case "clock":
|
||||||
widget.clockCompactMode = value;
|
newWidget.clockCompactMode = value;
|
||||||
break;
|
break;
|
||||||
case "focusedWindow":
|
case "focusedWindow":
|
||||||
widget.focusedWindowCompactMode = value;
|
newWidget.focusedWindowCompactMode = value;
|
||||||
break;
|
break;
|
||||||
case "runningApps":
|
case "runningApps":
|
||||||
widget.runningAppsCompactMode = value;
|
newWidget.runningAppsCompactMode = value;
|
||||||
break;
|
break;
|
||||||
case "keyboard_layout_name":
|
case "keyboard_layout_name":
|
||||||
widget.keyboardLayoutNameCompactMode = value;
|
newWidget.keyboardLayoutNameCompactMode = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
widgets[i] = newWidget;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,19 @@ Column {
|
|||||||
signal minimumWidthChanged(string sectionId, int widgetIndex, bool enabled)
|
signal minimumWidthChanged(string sectionId, int widgetIndex, bool enabled)
|
||||||
signal showSwapChanged(string sectionId, int widgetIndex, bool enabled)
|
signal showSwapChanged(string sectionId, int widgetIndex, bool enabled)
|
||||||
|
|
||||||
|
function cloneWidgetData(widget) {
|
||||||
|
var result = {
|
||||||
|
"id": widget.id,
|
||||||
|
"enabled": widget.enabled
|
||||||
|
};
|
||||||
|
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon"];
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
if (widget[keys[i]] !== undefined)
|
||||||
|
result[keys[i]] = widget[keys[i]];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: implicitHeight
|
height: implicitHeight
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
@@ -727,13 +740,7 @@ Column {
|
|||||||
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 => root.cloneWidgetData(item)));
|
||||||
return ({
|
|
||||||
"id": item.id,
|
|
||||||
"enabled": item.enabled,
|
|
||||||
"size": item.size
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delegateItem.x = 0;
|
delegateItem.x = 0;
|
||||||
|
|||||||
@@ -63,15 +63,15 @@ Item {
|
|||||||
onToggled: checked => SettingsData.set("showWorkspaceApps", checked)
|
onToggled: checked => SettingsData.set("showWorkspaceApps", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
width: parent.width - Theme.spacingL
|
width: parent.width
|
||||||
spacing: Theme.spacingL
|
height: maxAppsColumn.height
|
||||||
visible: SettingsData.showWorkspaceApps
|
visible: SettingsData.showWorkspaceApps
|
||||||
opacity: visible ? 1 : 0
|
opacity: visible ? 1 : 0
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingL
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
id: maxAppsColumn
|
||||||
|
x: Theme.spacingL
|
||||||
width: 120
|
width: 120
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
@@ -80,14 +80,15 @@ Item {
|
|||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
DankTextField {
|
DankTextField {
|
||||||
width: 100
|
width: 100
|
||||||
height: 28
|
height: 28
|
||||||
placeholderText: "#ffffff"
|
placeholderText: "3"
|
||||||
text: SettingsData.maxWorkspaceIcons
|
text: SettingsData.maxWorkspaceIcons
|
||||||
maximumLength: 7
|
maximumLength: 2
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
topPadding: Theme.spacingXS
|
topPadding: Theme.spacingXS
|
||||||
bottomPadding: Theme.spacingXS
|
bottomPadding: Theme.spacingXS
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property string currentVersion: "1.2"
|
readonly property string currentVersion: "1.2"
|
||||||
readonly property bool changelogEnabled: false
|
readonly property bool changelogEnabled: true
|
||||||
|
|
||||||
readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) + "/DankMaterialShell"
|
readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) + "/DankMaterialShell"
|
||||||
readonly property string changelogMarkerPath: configDir + "/.changelog-" + currentVersion
|
readonly property string changelogMarkerPath: configDir + "/.changelog-" + currentVersion
|
||||||
|
|||||||
@@ -287,11 +287,14 @@ Singleton {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODIFICATION: Treat Launchers as persistent instances like Daemons
|
if (isDaemon) {
|
||||||
if (isDaemon || isLauncher) {
|
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
||||||
|
newDaemons[pluginId] = comp;
|
||||||
|
pluginDaemonComponents = newDaemons;
|
||||||
|
} else if (isLauncher) {
|
||||||
const instance = comp.createObject(root, {
|
const instance = comp.createObject(root, {
|
||||||
"pluginId": pluginId,
|
"pluginId": pluginId,
|
||||||
"pluginService": root // Inject PluginService
|
"pluginService": root
|
||||||
});
|
});
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
console.error("PluginService: failed to instantiate plugin:", pluginId, comp.errorString());
|
console.error("PluginService: failed to instantiate plugin:", pluginId, comp.errorString());
|
||||||
@@ -302,15 +305,9 @@ Singleton {
|
|||||||
newInstances[pluginId] = instance;
|
newInstances[pluginId] = instance;
|
||||||
pluginInstances = newInstances;
|
pluginInstances = newInstances;
|
||||||
|
|
||||||
if (isDaemon) {
|
const newLaunchers = Object.assign({}, pluginLauncherComponents);
|
||||||
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
newLaunchers[pluginId] = comp;
|
||||||
newDaemons[pluginId] = comp;
|
pluginLauncherComponents = newLaunchers;
|
||||||
pluginDaemonComponents = newDaemons;
|
|
||||||
} else {
|
|
||||||
const newLaunchers = Object.assign({}, pluginLauncherComponents);
|
|
||||||
newLaunchers[pluginId] = comp;
|
|
||||||
pluginLauncherComponents = newLaunchers;
|
|
||||||
}
|
|
||||||
} else if (isDesktop) {
|
} else if (isDesktop) {
|
||||||
const newDesktop = Object.assign({}, pluginDesktopComponents);
|
const newDesktop = Object.assign({}, pluginDesktopComponents);
|
||||||
newDesktop[pluginId] = comp;
|
newDesktop[pluginId] = comp;
|
||||||
|
|||||||
@@ -754,7 +754,7 @@ Singleton {
|
|||||||
"humidity": Math.round(hourly.relative_humidity_2m?.[i] || 0),
|
"humidity": Math.round(hourly.relative_humidity_2m?.[i] || 0),
|
||||||
"wind": Math.round(hourly.wind_speed_10m?.[i] || 0),
|
"wind": Math.round(hourly.wind_speed_10m?.[i] || 0),
|
||||||
"pressure": Math.round(hourly.surface_pressure?.[i] || 0),
|
"pressure": Math.round(hourly.surface_pressure?.[i] || 0),
|
||||||
"precipitationProbability": Math.round(hourly.precipitation_probability_max?.[0] || 0),
|
"precipitationProbability": Math.round(hourly.precipitation_probability?.[i] || 0),
|
||||||
"visibility": Math.round(hourly.visibility?.[i] || 0),
|
"visibility": Math.round(hourly.visibility?.[i] || 0),
|
||||||
"isDay": isDay
|
"isDay": isDay
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v1.4-unstable
|
v1.2.3
|
||||||
|
|||||||
Reference in New Issue
Block a user