mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-03 02:52:07 -04:00
Compare commits
120 Commits
1452c85946
...
v1.4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f24cf37ca | ||
|
|
01218f34cb | ||
|
|
9da58d8296 | ||
|
|
af0038e634 | ||
|
|
05c312b9eb | ||
|
|
89d5c958c4 | ||
|
|
e4d86ad595 | ||
|
|
532b54a028 | ||
|
|
504d027c3f | ||
|
|
e8f95f4533 | ||
|
|
b83256c83a | ||
|
|
8e2cd21be8 | ||
|
|
c5413608da | ||
|
|
586bcad442 | ||
|
|
3b3d10f730 | ||
|
|
4834891b36 | ||
|
|
f60e65aecb | ||
|
|
01387b0123 | ||
|
|
1476658c23 | ||
|
|
7861c6e316 | ||
|
|
d2247d7b24 | ||
|
|
2ff78d4a02 | ||
|
|
785243ce5f | ||
|
|
0e1b868384 | ||
|
|
2b08e800e8 | ||
|
|
74e4f8ea1e | ||
|
|
9c58569b4c | ||
|
|
29de677e00 | ||
|
|
fae4944845 | ||
|
|
07a0ac4b7d | ||
|
|
b2d8f4d73b | ||
|
|
fe58c45233 | ||
|
|
3ea4e389eb | ||
|
|
7276f295fc | ||
|
|
93ed96a789 | ||
|
|
bea325e94c | ||
|
|
2f8f1c30ad | ||
|
|
f859a14173 | ||
|
|
153f39da48 | ||
|
|
e4accdd1c7 | ||
|
|
a2c89e0a8c | ||
|
|
e282831c2e | ||
|
|
5c5ff6195a | ||
|
|
c4bbf54679 | ||
|
|
98acafb4b8 | ||
|
|
da20681fc0 | ||
|
|
b38cb961b2 | ||
|
|
7a0bb07518 | ||
|
|
403e3e90a2 | ||
|
|
50b91f14b6 | ||
|
|
b3df47fce0 | ||
|
|
09bd65d746 | ||
|
|
020d56ab7f | ||
|
|
f3bee65da9 | ||
|
|
b14b0946e2 | ||
|
|
ca44205f1c | ||
|
|
2d39e8fd2a | ||
|
|
6d4df6e927 | ||
|
|
b8ab86e6c0 | ||
|
|
837329a6d8 | ||
|
|
8c6c2ffd23 | ||
|
|
ad3c8b6755 | ||
|
|
03a8e1e0d5 | ||
|
|
4d4d3c20a1 | ||
|
|
cef16d6bc9 | ||
|
|
aafaad1791 | ||
|
|
7906fdc2b0 | ||
|
|
397650ca52 | ||
|
|
826207006a | ||
|
|
58c2fcd31c | ||
|
|
b2a2b425ec | ||
|
|
942c9c9609 | ||
|
|
46d6e1cff3 | ||
|
|
a4137c57c1 | ||
|
|
1ad8b627f1 | ||
|
|
58a02ce290 | ||
|
|
8e1ad1a2be | ||
|
|
68cd7ab32c | ||
|
|
f649ce9a8e | ||
|
|
c4df242f07 | ||
|
|
26846c8d55 | ||
|
|
31b44a667c | ||
|
|
4f3b73ee21 | ||
|
|
4cfae91f02 | ||
|
|
8d947a6e95 | ||
|
|
1e84d4252c | ||
|
|
76072e1d4c | ||
|
|
6408dce4a9 | ||
|
|
0b2e1cca38 | ||
|
|
c1bfd8c0b7 | ||
|
|
90ffa5833b | ||
|
|
169c669286 | ||
|
|
f8350deafc | ||
|
|
0286a1b80b | ||
|
|
7c3e6c1f02 | ||
|
|
d2d72db3c9 | ||
|
|
f81f861408 | ||
|
|
af494543f5 | ||
|
|
db4de55338 | ||
|
|
37ecbbbbde | ||
|
|
d6a6d2a438 | ||
|
|
bf1c6eec74 | ||
|
|
0ddae80584 | ||
|
|
5c96c03bfa | ||
|
|
dfe36e47d8 | ||
|
|
63e1b75e57 | ||
|
|
29efdd8598 | ||
|
|
34d03cf11b | ||
|
|
c339389d44 | ||
|
|
af5f6eb656 | ||
|
|
a6d28e2553 | ||
|
|
6213267908 | ||
|
|
d084114149 | ||
|
|
f6d99eca0d | ||
|
|
722eb3289e | ||
|
|
b7f2bdcb2d | ||
|
|
11c20db6e6 | ||
|
|
8a4e3f8bb1 | ||
|
|
bc8fe97c13 | ||
|
|
47262155aa |
13
.github/workflows/run-obs.yml
vendored
13
.github/workflows/run-obs.yml
vendored
@@ -9,8 +9,8 @@ on:
|
|||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
- dms
|
- dms
|
||||||
- dms-greeter
|
|
||||||
- dms-git
|
- dms-git
|
||||||
|
- dms-greeter
|
||||||
- all
|
- all
|
||||||
default: "dms"
|
default: "dms"
|
||||||
rebuild_release:
|
rebuild_release:
|
||||||
@@ -119,8 +119,9 @@ jobs:
|
|||||||
echo "🔄 Manual rebuild requested: $PKG (db$REBUILD)"
|
echo "🔄 Manual rebuild requested: $PKG (db$REBUILD)"
|
||||||
|
|
||||||
elif [[ "$PKG" == "all" ]]; then
|
elif [[ "$PKG" == "all" ]]; then
|
||||||
# Check each stable 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")
|
||||||
if check_dms_stable; then
|
if check_dms_stable; then
|
||||||
PACKAGES_TO_UPDATE+=("dms")
|
PACKAGES_TO_UPDATE+=("dms")
|
||||||
if [[ -n "$LATEST_TAG" ]]; then
|
if [[ -n "$LATEST_TAG" ]]; then
|
||||||
@@ -139,7 +140,7 @@ jobs:
|
|||||||
else
|
else
|
||||||
echo "packages=" >> $GITHUB_OUTPUT
|
echo "packages=" >> $GITHUB_OUTPUT
|
||||||
echo "has_updates=false" >> $GITHUB_OUTPUT
|
echo "has_updates=false" >> $GITHUB_OUTPUT
|
||||||
echo "✓ Both packages up to date"
|
echo "✓ All packages up to date"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [[ "$PKG" == "dms-git" ]]; then
|
elif [[ "$PKG" == "dms-git" ]]; then
|
||||||
@@ -244,7 +245,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Update dms-git spec version
|
- name: Update dms-git spec version
|
||||||
if: contains(steps.packages.outputs.packages, 'dms-git')
|
if: contains(steps.packages.outputs.packages, 'dms-git') || steps.packages.outputs.packages == 'all'
|
||||||
run: |
|
run: |
|
||||||
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
|
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
|
||||||
COMMIT_COUNT=$(git rev-list --count HEAD)
|
COMMIT_COUNT=$(git rev-list --count HEAD)
|
||||||
@@ -265,7 +266,7 @@ jobs:
|
|||||||
} > distro/opensuse/dms-git.spec
|
} > distro/opensuse/dms-git.spec
|
||||||
|
|
||||||
- name: Update Debian dms-git changelog version
|
- name: Update Debian dms-git changelog version
|
||||||
if: contains(steps.packages.outputs.packages, 'dms-git')
|
if: contains(steps.packages.outputs.packages, 'dms-git') || steps.packages.outputs.packages == 'all'
|
||||||
run: |
|
run: |
|
||||||
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
|
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
|
||||||
COMMIT_COUNT=$(git rev-list --count HEAD)
|
COMMIT_COUNT=$(git rev-list --count HEAD)
|
||||||
@@ -388,7 +389,7 @@ jobs:
|
|||||||
UPLOADED_PACKAGES=()
|
UPLOADED_PACKAGES=()
|
||||||
SKIPPED_PACKAGES=()
|
SKIPPED_PACKAGES=()
|
||||||
|
|
||||||
# PACKAGES can be space-separated list (e.g., "dms dms-greeter" from "all" check)
|
# PACKAGES can be space-separated list (e.g., "dms-git dms" from "all" check)
|
||||||
# Loop through each package and upload
|
# Loop through each package and upload
|
||||||
for PKG in $PACKAGES; do
|
for PKG in $PACKAGES; do
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
16
.github/workflows/run-ppa.yml
vendored
16
.github/workflows/run-ppa.yml
vendored
@@ -4,15 +4,9 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
package:
|
package:
|
||||||
description: "Package to upload"
|
description: "Package to upload (dms, dms-git, dms-greeter, or all)"
|
||||||
required: true
|
required: false
|
||||||
type: choice
|
default: "dms-git"
|
||||||
options:
|
|
||||||
- dms
|
|
||||||
- dms-greeter
|
|
||||||
- dms-git
|
|
||||||
- all
|
|
||||||
default: "dms"
|
|
||||||
rebuild_release:
|
rebuild_release:
|
||||||
description: "Release number for rebuilds (e.g., 2, 3, 4 for ppa2, ppa3, ppa4)"
|
description: "Release number for rebuilds (e.g., 2, 3, 4 for ppa2, ppa3, ppa4)"
|
||||||
required: false
|
required: false
|
||||||
@@ -145,7 +139,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Fallback
|
# Fallback
|
||||||
echo "packages=dms" >> $GITHUB_OUTPUT
|
echo "packages=dms-git" >> $GITHUB_OUTPUT
|
||||||
echo "has_updates=true" >> $GITHUB_OUTPUT
|
echo "has_updates=true" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -215,7 +209,7 @@ jobs:
|
|||||||
echo "✓ Using rebuild release number: ppa$REBUILD_RELEASE"
|
echo "✓ Using rebuild release number: ppa$REBUILD_RELEASE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# PACKAGES can be space-separated list (e.g., "dms-git dms dms-greeter" from "all" check)
|
# PACKAGES can be space-separated list (e.g., "dms-git dms" from "all" check)
|
||||||
# Loop through each package and upload
|
# Loop through each package and upload
|
||||||
for PKG in $PACKAGES; do
|
for PKG in $PACKAGES; do
|
||||||
# Map package to PPA name
|
# Map package to PPA name
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ require (
|
|||||||
github.com/sblinch/kdl-go v0.0.0-20260121213736-8b7053306ca6
|
github.com/sblinch/kdl-go v0.0.0-20260121213736-8b7053306ca6
|
||||||
github.com/spf13/cobra v1.10.2
|
github.com/spf13/cobra v1.10.2
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/yeqown/go-qrcode/v2 v2.2.5
|
|
||||||
github.com/yeqown/go-qrcode/writer/standard v1.3.0
|
|
||||||
github.com/yuin/goldmark v1.7.16
|
github.com/yuin/goldmark v1.7.16
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
go.etcd.io/bbolt v1.4.3
|
go.etcd.io/bbolt v1.4.3
|
||||||
@@ -34,19 +32,15 @@ require (
|
|||||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/fogleman/gg v1.3.0 // indirect
|
|
||||||
github.com/go-git/gcfg/v2 v2.0.2 // indirect
|
github.com/go-git/gcfg/v2 v2.0.2 // indirect
|
||||||
github.com/go-git/go-billy/v6 v6.0.0-20260209124918-37866f83c2d3 // indirect
|
github.com/go-git/go-billy/v6 v6.0.0-20260209124918-37866f83c2d3 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
|
||||||
github.com/sergi/go-diff v1.4.0 // indirect
|
github.com/sergi/go-diff v1.4.0 // indirect
|
||||||
github.com/stretchr/objx v0.5.3 // indirect
|
github.com/stretchr/objx v0.5.3 // indirect
|
||||||
github.com/yeqown/reedsolomon v1.0.0 // indirect
|
|
||||||
golang.org/x/crypto v0.48.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.50.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
12
core/go.sum
12
core/go.sum
@@ -58,8 +58,6 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
|
|||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
|
||||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
@@ -77,8 +75,6 @@ github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/
|
|||||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
|
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
|
||||||
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
@@ -119,8 +115,6 @@ github.com/pilebones/go-udev v0.9.1 h1:uN72M1C1fgzhsVmBGEM8w9RD1JY4iVsPZpr+Z6rb3
|
|||||||
github.com/pilebones/go-udev v0.9.1/go.mod h1:Bgcl07crebF3JSeS4+nuaRvhWFdCeFoBhXXeAp93XNo=
|
github.com/pilebones/go-udev v0.9.1/go.mod h1:Bgcl07crebF3JSeS4+nuaRvhWFdCeFoBhXXeAp93XNo=
|
||||||
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
|
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
|
||||||
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
|
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
@@ -148,12 +142,6 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
|
|||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
github.com/yeqown/go-qrcode/v2 v2.2.5 h1:HCOe2bSjkhZyYoyyNaXNzh4DJZll6inVJQQw+8228Zk=
|
|
||||||
github.com/yeqown/go-qrcode/v2 v2.2.5/go.mod h1:uHpt9CM0V1HeXLz+Wg5MN50/sI/fQhfkZlOM+cOTHxw=
|
|
||||||
github.com/yeqown/go-qrcode/writer/standard v1.3.0 h1:chdyhEfRtUPgQtuPeaWVGQ/TQx4rE1PqeoW3U+53t34=
|
|
||||||
github.com/yeqown/go-qrcode/writer/standard v1.3.0/go.mod h1:O4MbzsotGCvy8upYPCR91j81dr5XLT7heuljcNXW+oQ=
|
|
||||||
github.com/yeqown/reedsolomon v1.0.0 h1:x1h/Ej/uJnNu8jaX7GLHBWmZKCAWjEJTetkqaabr4B0=
|
|
||||||
github.com/yeqown/reedsolomon v1.0.0/go.mod h1:P76zpcn2TCuL0ul1Fso373qHRc69LKwAw/Iy6g1WiiM=
|
|
||||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
|
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
|
||||||
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||||
|
|||||||
@@ -1062,62 +1062,6 @@ func (_c *MockBackend_GetWiFiNetworkDetails_Call) RunAndReturn(run func(string)
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWiFiQRCodeContent provides a mock function with given fields: ssid
|
|
||||||
func (_m *MockBackend) GetWiFiQRCodeContent(ssid string) (string, error) {
|
|
||||||
ret := _m.Called(ssid)
|
|
||||||
|
|
||||||
if len(ret) == 0 {
|
|
||||||
panic("no return value specified for GetWiFiQRCodeContent")
|
|
||||||
}
|
|
||||||
|
|
||||||
var r0 string
|
|
||||||
var r1 error
|
|
||||||
if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
|
|
||||||
return rf(ssid)
|
|
||||||
}
|
|
||||||
if rf, ok := ret.Get(0).(func(string) string); ok {
|
|
||||||
r0 = rf(ssid)
|
|
||||||
} else {
|
|
||||||
r0 = ret.Get(0).(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
|
||||||
r1 = rf(ssid)
|
|
||||||
} else {
|
|
||||||
r1 = ret.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// MockBackend_GetWiFiQRCodeContent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWiFiQRCodeContent'
|
|
||||||
type MockBackend_GetWiFiQRCodeContent_Call struct {
|
|
||||||
*mock.Call
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWiFiQRCodeContent is a helper method to define mock.On call
|
|
||||||
// - ssid string
|
|
||||||
func (_e *MockBackend_Expecter) GetWiFiQRCodeContent(ssid interface{}) *MockBackend_GetWiFiQRCodeContent_Call {
|
|
||||||
return &MockBackend_GetWiFiQRCodeContent_Call{Call: _e.mock.On("GetWiFiQRCodeContent", ssid)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_c *MockBackend_GetWiFiQRCodeContent_Call) Run(run func(ssid string)) *MockBackend_GetWiFiQRCodeContent_Call {
|
|
||||||
_c.Call.Run(func(args mock.Arguments) {
|
|
||||||
run(args[0].(string))
|
|
||||||
})
|
|
||||||
return _c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_c *MockBackend_GetWiFiQRCodeContent_Call) Return(_a0 string, _a1 error) *MockBackend_GetWiFiQRCodeContent_Call {
|
|
||||||
_c.Call.Return(_a0, _a1)
|
|
||||||
return _c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_c *MockBackend_GetWiFiQRCodeContent_Call) RunAndReturn(run func(string) (string, error)) *MockBackend_GetWiFiQRCodeContent_Call {
|
|
||||||
_c.Call.Return(run)
|
|
||||||
return _c
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWiredConnections provides a mock function with no fields
|
// GetWiredConnections provides a mock function with no fields
|
||||||
func (_m *MockBackend) GetWiredConnections() ([]network.WiredConnection, error) {
|
func (_m *MockBackend) GetWiredConnections() ([]network.WiredConnection, error) {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ type Backend interface {
|
|||||||
ScanWiFi() error
|
ScanWiFi() error
|
||||||
ScanWiFiDevice(device string) error
|
ScanWiFiDevice(device string) error
|
||||||
GetWiFiNetworkDetails(ssid string) (*NetworkInfoResponse, error)
|
GetWiFiNetworkDetails(ssid string) (*NetworkInfoResponse, error)
|
||||||
GetWiFiQRCodeContent(ssid string) (string, error)
|
|
||||||
GetWiFiDevices() []WiFiDevice
|
GetWiFiDevices() []WiFiDevice
|
||||||
|
|
||||||
ConnectWiFi(req ConnectionRequest) error
|
ConnectWiFi(req ConnectionRequest) error
|
||||||
|
|||||||
@@ -111,10 +111,6 @@ func (b *HybridIwdNetworkdBackend) GetWiFiNetworkDetails(ssid string) (*NetworkI
|
|||||||
return b.wifi.GetWiFiNetworkDetails(ssid)
|
return b.wifi.GetWiFiNetworkDetails(ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *HybridIwdNetworkdBackend) GetWiFiQRCodeContent(ssid string) (string, error) {
|
|
||||||
return b.wifi.GetWiFiQRCodeContent(ssid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *HybridIwdNetworkdBackend) ConnectWiFi(req ConnectionRequest) error {
|
func (b *HybridIwdNetworkdBackend) ConnectWiFi(req ConnectionRequest) error {
|
||||||
if err := b.wifi.ConnectWiFi(req); err != nil {
|
if err := b.wifi.ConnectWiFi(req); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (b *IWDBackend) GetWiredConnections() ([]WiredConnection, error) {
|
func (b *IWDBackend) GetWiredConnections() ([]WiredConnection, error) {
|
||||||
return nil, fmt.Errorf("wired connections not supported by iwd")
|
return nil, fmt.Errorf("wired connections not supported by iwd")
|
||||||
@@ -115,19 +112,3 @@ func (b *IWDBackend) getWiFiDevicesLocked() []WiFiDevice {
|
|||||||
Networks: b.state.WiFiNetworks,
|
Networks: b.state.WiFiNetworks,
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *IWDBackend) GetWiFiQRCodeContent(ssid string) (string, error) {
|
|
||||||
path := iwdConfigPath(ssid)
|
|
||||||
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("no saved iwd config for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
passphrase, err := parseIWDPassphrase(string(data))
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to read passphrase for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return FormatWiFiQRString("WPA", ssid, passphrase), nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ func (b *SystemdNetworkdBackend) GetWiFiNetworkDetails(ssid string) (*NetworkInf
|
|||||||
return nil, fmt.Errorf("WiFi details not supported by networkd backend")
|
return nil, fmt.Errorf("WiFi details not supported by networkd backend")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemdNetworkdBackend) GetWiFiQRCodeContent(ssid string) (string, error) {
|
|
||||||
return "", fmt.Errorf("WiFi QR Code not supported by networkd backend")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *SystemdNetworkdBackend) ConnectWiFi(req ConnectionRequest) error {
|
func (b *SystemdNetworkdBackend) ConnectWiFi(req ConnectionRequest) error {
|
||||||
return fmt.Errorf("WiFi connect not supported by networkd backend")
|
return fmt.Errorf("WiFi connect not supported by networkd backend")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,65 +196,6 @@ func (b *NetworkManagerBackend) GetWiFiNetworkDetails(ssid string) (*NetworkInfo
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *NetworkManagerBackend) GetWiFiQRCodeContent(ssid string) (string, error) {
|
|
||||||
conn, err := b.findConnection(ssid)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("no saved connection for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
connSettings, err := conn.GetSettings()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to get settings for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
secSettings, ok := connSettings["802-11-wireless-security"]
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("network `%s` has no security settings", ssid)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyMgmt, ok := secSettings["key-mgmt"].(string)
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("failed to identify security type of network `%s`", ssid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var securityType string
|
|
||||||
switch keyMgmt {
|
|
||||||
case "none":
|
|
||||||
authAlg, _ := secSettings["auth-alg"].(string)
|
|
||||||
switch authAlg {
|
|
||||||
case "open":
|
|
||||||
securityType = "nopass"
|
|
||||||
default:
|
|
||||||
securityType = "WEP"
|
|
||||||
}
|
|
||||||
case "ieee8021x":
|
|
||||||
securityType = "WEP"
|
|
||||||
default:
|
|
||||||
securityType = "WPA"
|
|
||||||
}
|
|
||||||
|
|
||||||
if securityType != "WPA" {
|
|
||||||
return "", fmt.Errorf("QR code generation only supports WPA connections, `%s` uses %s", ssid, securityType)
|
|
||||||
}
|
|
||||||
|
|
||||||
secrets, err := conn.GetSecrets("802-11-wireless-security")
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to retrieve connection secrets for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
secSecrets, ok := secrets["802-11-wireless-security"]
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("failed to retrieve password for `%s`", ssid)
|
|
||||||
}
|
|
||||||
|
|
||||||
psk, ok := secSecrets["psk"].(string)
|
|
||||||
if !ok {
|
|
||||||
return "", fmt.Errorf("failed to retrieve password for `%s`", ssid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return FormatWiFiQRString(securityType, ssid, psk), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *NetworkManagerBackend) ConnectWiFi(req ConnectionRequest) error {
|
func (b *NetworkManagerBackend) ConnectWiFi(req ConnectionRequest) error {
|
||||||
devInfo, err := b.getWifiDeviceForConnection(req.Device)
|
devInfo, err := b.getWifiDeviceForConnection(req.Device)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
|
||||||
@@ -41,10 +40,6 @@ func HandleRequest(conn net.Conn, req models.Request, manager *Manager) {
|
|||||||
handleSetPreference(conn, req, manager)
|
handleSetPreference(conn, req, manager)
|
||||||
case "network.info":
|
case "network.info":
|
||||||
handleGetNetworkInfo(conn, req, manager)
|
handleGetNetworkInfo(conn, req, manager)
|
||||||
case "network.qrcode":
|
|
||||||
handleGetNetworkQRCode(conn, req, manager)
|
|
||||||
case "network.delete-qrcode":
|
|
||||||
handleDeleteQRCode(conn, req, manager)
|
|
||||||
case "network.ethernet.info":
|
case "network.ethernet.info":
|
||||||
handleGetWiredNetworkInfo(conn, req, manager)
|
handleGetWiredNetworkInfo(conn, req, manager)
|
||||||
case "network.subscribe":
|
case "network.subscribe":
|
||||||
@@ -325,42 +320,6 @@ func handleGetNetworkInfo(conn net.Conn, req models.Request, manager *Manager) {
|
|||||||
models.Respond(conn, req.ID, network)
|
models.Respond(conn, req.ID, network)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGetNetworkQRCode(conn net.Conn, req models.Request, manager *Manager) {
|
|
||||||
ssid, err := params.String(req.Params, "ssid")
|
|
||||||
if err != nil {
|
|
||||||
models.RespondError(conn, req.ID, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
content, err := manager.GetNetworkQRCode(ssid)
|
|
||||||
if err != nil {
|
|
||||||
models.RespondError(conn, req.ID, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
models.Respond(conn, req.ID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleDeleteQRCode(conn net.Conn, req models.Request, _ *Manager) {
|
|
||||||
path, err := params.String(req.Params, "path")
|
|
||||||
if err != nil {
|
|
||||||
models.RespondError(conn, req.ID, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isValidQRCodePath(path) {
|
|
||||||
models.RespondError(conn, req.ID, "invalid QR code path")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Remove(path); err != nil {
|
|
||||||
models.RespondError(conn, req.ID, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "QR code file deleted"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleGetWiredNetworkInfo(conn net.Conn, req models.Request, manager *Manager) {
|
func handleGetWiredNetworkInfo(conn net.Conn, req models.Request, manager *Manager) {
|
||||||
uuid, err := params.String(req.Params, "uuid")
|
uuid, err := params.String(req.Params, "uuid")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/yeqown/go-qrcode/v2"
|
|
||||||
"github.com/yeqown/go-qrcode/writer/standard"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewManager() (*Manager, error) {
|
func NewManager() (*Manager, error) {
|
||||||
@@ -440,43 +438,6 @@ func (m *Manager) GetNetworkInfoDetailed(ssid string) (*NetworkInfoResponse, err
|
|||||||
return m.backend.GetWiFiNetworkDetails(ssid)
|
return m.backend.GetWiFiNetworkDetails(ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) GetNetworkQRCode(ssid string) ([2]string, error) {
|
|
||||||
content, err := m.backend.GetWiFiQRCodeContent(ssid)
|
|
||||||
if err != nil {
|
|
||||||
return [2]string{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
qrc, err := qrcode.New(content)
|
|
||||||
if err != nil {
|
|
||||||
return [2]string{}, fmt.Errorf("failed to create QR code for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pathThemed, pathNormal := qrCodePaths(ssid)
|
|
||||||
|
|
||||||
wThemed, err := standard.New(
|
|
||||||
pathThemed,
|
|
||||||
standard.WithBuiltinImageEncoder(standard.PNG_FORMAT),
|
|
||||||
standard.WithBgTransparent(),
|
|
||||||
standard.WithFgColorRGBHex("#ffffff"),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return [2]string{}, fmt.Errorf("failed to create QR code writer: %w", err)
|
|
||||||
}
|
|
||||||
if err := qrc.Save(wThemed); err != nil {
|
|
||||||
return [2]string{}, fmt.Errorf("failed to save QR code for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
wNormal, err := standard.New(pathNormal, standard.WithBuiltinImageEncoder(standard.PNG_FORMAT))
|
|
||||||
if err != nil {
|
|
||||||
return [2]string{}, fmt.Errorf("failed to create QR code writer: %w", err)
|
|
||||||
}
|
|
||||||
if err := qrc.Save(wNormal); err != nil {
|
|
||||||
return [2]string{}, fmt.Errorf("failed to save QR code for `%s`: %w", ssid, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [2]string{pathThemed, pathNormal}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) ToggleWiFi() error {
|
func (m *Manager) ToggleWiFi() error {
|
||||||
enabled, err := m.backend.GetWiFiEnabled()
|
enabled, err := m.backend.GetWiFiEnabled()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
package network
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const qrCodeTmpPrefix = "/tmp/dank-wifi-qrcode-"
|
|
||||||
|
|
||||||
func FormatWiFiQRString(securityType, ssid, password string) string {
|
|
||||||
return fmt.Sprintf("WIFI:T:%s;S:%s;P:%s;;", securityType, ssid, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
func qrCodePaths(ssid string) (themed, normal string) {
|
|
||||||
safe := sanitizeSSIDForPath(ssid)
|
|
||||||
themed = fmt.Sprintf("%s%s-themed.png", qrCodeTmpPrefix, safe)
|
|
||||||
normal = fmt.Sprintf("%s%s-normal.png", qrCodeTmpPrefix, safe)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidQRCodePath(path string) bool {
|
|
||||||
clean := filepath.Clean(path)
|
|
||||||
return strings.HasPrefix(clean, qrCodeTmpPrefix) && strings.HasSuffix(clean, ".png")
|
|
||||||
}
|
|
||||||
|
|
||||||
var safePathChar = regexp.MustCompile(`[^a-zA-Z0-9_-]`)
|
|
||||||
|
|
||||||
func sanitizeSSIDForPath(ssid string) string {
|
|
||||||
return safePathChar.ReplaceAllString(ssid, "_")
|
|
||||||
}
|
|
||||||
|
|
||||||
var iwdVerbatimSSID = regexp.MustCompile(`^[a-zA-Z0-9 _-]+$`)
|
|
||||||
|
|
||||||
func iwdConfigPath(ssid string) string {
|
|
||||||
switch {
|
|
||||||
case iwdVerbatimSSID.MatchString(ssid):
|
|
||||||
return fmt.Sprintf("/var/lib/iwd/%s.psk", ssid)
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("/var/lib/iwd/=%x.psk", []byte(ssid))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseIWDPassphrase(data string) (string, error) {
|
|
||||||
inSecurity := false
|
|
||||||
for _, line := range strings.Split(data, "\n") {
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
switch {
|
|
||||||
case line == "[Security]":
|
|
||||||
inSecurity = true
|
|
||||||
case strings.HasPrefix(line, "["):
|
|
||||||
inSecurity = false
|
|
||||||
case inSecurity && strings.HasPrefix(line, "Passphrase="):
|
|
||||||
return strings.TrimPrefix(line, "Passphrase="), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("no passphrase found in iwd config")
|
|
||||||
}
|
|
||||||
@@ -27,12 +27,12 @@ override_dh_auto_build:
|
|||||||
# Verify core directory exists (native package format has source at root)
|
# Verify core directory exists (native package format has source at root)
|
||||||
test -d core || (echo "ERROR: core directory not found!" && exit 1)
|
test -d core || (echo "ERROR: core directory not found!" && exit 1)
|
||||||
|
|
||||||
# Pin go.mod and vendor/modules.txt to the installed Go toolchain version
|
# Patch go.mod to use Go 1.24 base version (Debian 13 has 1.23.x, may vary)
|
||||||
GO_INSTALLED=$$(go version | grep -oP 'go\K[0-9]+\.[0-9]+'); \
|
sed -i 's/^go 1\.24\.[0-9]*/go 1.24/' core/go.mod
|
||||||
sed -i "s/^go [0-9]\+\.[0-9]\+\(\.[0-9]*\)\?$$/go $${GO_INSTALLED}/" core/go.mod; \
|
|
||||||
sed -i "s/^\(## explicit; go \)[0-9]\+\.[0-9]\+\(\.[0-9]*\)\?$$/\1$${GO_INSTALLED}/" core/vendor/modules.txt
|
|
||||||
|
|
||||||
# Build dms-cli (single shell to preserve variables; arch: Debian amd64/arm64 -> Makefile amd64/arm64)
|
# Build dms-cli from source using vendored dependencies
|
||||||
|
# Extract version info and build in single shell to preserve variables
|
||||||
|
# Architecture mapping: Debian amd64/arm64 -> Makefile amd64/arm64
|
||||||
VERSION="$(UPSTREAM_VERSION)"; \
|
VERSION="$(UPSTREAM_VERSION)"; \
|
||||||
COMMIT=$$(echo "$(UPSTREAM_VERSION)" | grep -oP '(?<=git)[0-9]+\.[a-f0-9]+' | cut -d. -f2 | head -c8 || echo "unknown"); \
|
COMMIT=$$(echo "$(UPSTREAM_VERSION)" | grep -oP '(?<=git)[0-9]+\.[a-f0-9]+' | cut -d. -f2 | head -c8 || echo "unknown"); \
|
||||||
if [ "$(DEB_HOST_ARCH)" = "amd64" ]; then \
|
if [ "$(DEB_HOST_ARCH)" = "amd64" ]; then \
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<service name="download_url">
|
<service name="download_url">
|
||||||
<param name="protocol">https</param>
|
<param name="protocol">https</param>
|
||||||
<param name="host">github.com</param>
|
<param name="host">github.com</param>
|
||||||
<param name="path">/AvengeMedia/DankMaterialShell/releases/download/v1.4.3/dms-qml.tar.gz</param>
|
<param name="path">/AvengeMedia/DankMaterialShell/releases/download/v1.4.2/dms-qml.tar.gz</param>
|
||||||
<param name="filename">dms-qml.tar.gz</param>
|
<param name="filename">dms-qml.tar.gz</param>
|
||||||
</service>
|
</service>
|
||||||
</services>
|
</services>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
dms-greeter (1.4.3db1) unstable; urgency=medium
|
dms-greeter (1.4.2db8) unstable; urgency=medium
|
||||||
|
|
||||||
* Update to v1.4.3 stable release
|
* Initial Debian OBS package
|
||||||
|
* Port from Ubuntu/Fedora packaging
|
||||||
|
|
||||||
-- Avenge Media <AvengeMedia.US@gmail.com> Tue, 25 Feb 2026 02:40:00 +0000
|
-- Avenge Media <AvengeMedia.US@gmail.com> Sat, 21 Feb 2026 00:00:00 +0000
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
%global debug_package %{nil}
|
%global debug_package %{nil}
|
||||||
%global version {{{ git_repo_version }}}
|
%global version {{{ git_repo_version }}}
|
||||||
%global pkg_summary DankMaterialShell - Material 3 inspired shell for Wayland compositors
|
%global pkg_summary DankMaterialShell - Material 3 inspired shell for Wayland compositors
|
||||||
%global go_toolchain_version 1.25.7
|
|
||||||
|
|
||||||
Name: dms
|
Name: dms
|
||||||
Epoch: 2
|
Epoch: 2
|
||||||
@@ -15,12 +14,12 @@ License: MIT
|
|||||||
URL: https://github.com/AvengeMedia/DankMaterialShell
|
URL: https://github.com/AvengeMedia/DankMaterialShell
|
||||||
VCS: {{{ git_repo_vcs }}}
|
VCS: {{{ git_repo_vcs }}}
|
||||||
Source0: {{{ git_repo_pack }}}
|
Source0: {{{ git_repo_pack }}}
|
||||||
Source1: https://go.dev/dl/go%{go_toolchain_version}.linux-amd64.tar.gz
|
|
||||||
Source2: https://go.dev/dl/go%{go_toolchain_version}.linux-arm64.tar.gz
|
|
||||||
|
|
||||||
BuildRequires: git-core
|
BuildRequires: git-core
|
||||||
BuildRequires: gzip
|
BuildRequires: gzip
|
||||||
|
BuildRequires: golang >= 1.24
|
||||||
BuildRequires: make
|
BuildRequires: make
|
||||||
|
BuildRequires: wget
|
||||||
BuildRequires: systemd-rpm-macros
|
BuildRequires: systemd-rpm-macros
|
||||||
|
|
||||||
# Core requirements
|
# Core requirements
|
||||||
@@ -29,7 +28,7 @@ Requires: accountsservice
|
|||||||
Requires: dms-cli = %{epoch}:%{version}-%{release}
|
Requires: dms-cli = %{epoch}:%{version}-%{release}
|
||||||
Requires: dgop
|
Requires: dgop
|
||||||
|
|
||||||
# Core utilities (Recommended for DMS functionality)
|
# Core utilities (Highly recommended for DMS functionality)
|
||||||
Recommends: cava
|
Recommends: cava
|
||||||
Recommends: danksearch
|
Recommends: danksearch
|
||||||
Recommends: matugen
|
Recommends: matugen
|
||||||
@@ -67,28 +66,6 @@ Provides native DBus bindings, NetworkManager integration, and system utilities.
|
|||||||
VERSION="%{version}"
|
VERSION="%{version}"
|
||||||
COMMIT=$(echo "%{version}" | grep -oP '[a-f0-9]{7,}' | head -n1 || echo "unknown")
|
COMMIT=$(echo "%{version}" | grep -oP '[a-f0-9]{7,}' | head -n1 || echo "unknown")
|
||||||
|
|
||||||
# Use pinned bundled Go toolchain (deterministic across chroots)
|
|
||||||
case "%{_arch}" in
|
|
||||||
x86_64)
|
|
||||||
GO_TARBALL="%{_sourcedir}/go%{go_toolchain_version}.linux-amd64.tar.gz"
|
|
||||||
;;
|
|
||||||
aarch64)
|
|
||||||
GO_TARBALL="%{_sourcedir}/go%{go_toolchain_version}.linux-arm64.tar.gz"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported architecture for bundled Go: %{_arch}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
rm -rf .go
|
|
||||||
tar -xzf "$GO_TARBALL"
|
|
||||||
mv go .go
|
|
||||||
export GOROOT="$PWD/.go"
|
|
||||||
export PATH="$GOROOT/bin:$PATH"
|
|
||||||
export GOTOOLCHAIN=local
|
|
||||||
go version
|
|
||||||
|
|
||||||
cd core
|
cd core
|
||||||
make dist VERSION="$VERSION" COMMIT="$COMMIT"
|
make dist VERSION="$VERSION" COMMIT="$COMMIT"
|
||||||
|
|
||||||
|
|||||||
@@ -56,10 +56,8 @@ mkdir -p $HOME $GOCACHE $GOMODCACHE
|
|||||||
# OBS has no network access, so use local toolchain only
|
# OBS has no network access, so use local toolchain only
|
||||||
export GOTOOLCHAIN=local
|
export GOTOOLCHAIN=local
|
||||||
|
|
||||||
# Pin go.mod and vendor/modules.txt to the installed Go toolchain version
|
# Patch go.mod to use base Go version (e.g., go 1.24 instead of go 1.24.6)
|
||||||
GO_INSTALLED=$(go version | grep -oP 'go\K[0-9]+\.[0-9]+')
|
sed -i 's/^go 1\.24\.[0-9]*/go 1.24/' core/go.mod
|
||||||
sed -i "s/^go [0-9]\+\.[0-9]\+\(\.[0-9]*\)\?$/go ${GO_INSTALLED}/" core/go.mod
|
|
||||||
sed -i "s/^\(## explicit; go \)[0-9]\+\.[0-9]\+\(\.[0-9]*\)\?$/\1${GO_INSTALLED}/" core/vendor/modules.txt
|
|
||||||
|
|
||||||
# Extract version info for embedding in binary
|
# Extract version info for embedding in binary
|
||||||
VERSION="%{version}"
|
VERSION="%{version}"
|
||||||
|
|||||||
@@ -419,9 +419,6 @@ if [[ "$UPLOAD_OPENSUSE" == true ]] && [[ -f "distro/opensuse/$PACKAGE.spec" ]];
|
|||||||
sed -i "s/VERSION_PLACEHOLDER/${DMS_GREETER_BASE_VERSION}/g" "$WORK_DIR/$PACKAGE.spec"
|
sed -i "s/VERSION_PLACEHOLDER/${DMS_GREETER_BASE_VERSION}/g" "$WORK_DIR/$PACKAGE.spec"
|
||||||
sed -i "s/RELEASE_PLACEHOLDER/${DMS_GREETER_RELEASE}/g" "$WORK_DIR/$PACKAGE.spec"
|
sed -i "s/RELEASE_PLACEHOLDER/${DMS_GREETER_RELEASE}/g" "$WORK_DIR/$PACKAGE.spec"
|
||||||
sed -i "s/CHANGELOG_DATE_PLACEHOLDER/${CHANGELOG_DATE}/g" "$WORK_DIR/$PACKAGE.spec"
|
sed -i "s/CHANGELOG_DATE_PLACEHOLDER/${CHANGELOG_DATE}/g" "$WORK_DIR/$PACKAGE.spec"
|
||||||
# Explicitly set Version:/Release: in case the spec uses %{version} macro
|
|
||||||
sed -i "s/^Version:.*/Version: ${DMS_GREETER_BASE_VERSION}/" "$WORK_DIR/$PACKAGE.spec"
|
|
||||||
sed -i "s/^Release:.*/Release: ${DMS_GREETER_RELEASE}%{?dist}/" "$WORK_DIR/$PACKAGE.spec"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "$WORK_DIR/.osc/$PACKAGE.spec" ]]; then
|
if [[ -f "$WORK_DIR/.osc/$PACKAGE.spec" ]]; then
|
||||||
@@ -816,9 +813,6 @@ if [[ "$UPLOAD_DEBIAN" == true ]] && [[ -d "distro/debian/$PACKAGE/debian" ]]; t
|
|||||||
sed -i "s/VERSION_PLACEHOLDER/${DMS_GREETER_BASE_VERSION}/g" "$WORK_DIR/$PACKAGE.spec"
|
sed -i "s/VERSION_PLACEHOLDER/${DMS_GREETER_BASE_VERSION}/g" "$WORK_DIR/$PACKAGE.spec"
|
||||||
sed -i "s/RELEASE_PLACEHOLDER/${DMS_GREETER_RELEASE}/g" "$WORK_DIR/$PACKAGE.spec"
|
sed -i "s/RELEASE_PLACEHOLDER/${DMS_GREETER_RELEASE}/g" "$WORK_DIR/$PACKAGE.spec"
|
||||||
sed -i "s/CHANGELOG_DATE_PLACEHOLDER/${CHANGELOG_DATE}/g" "$WORK_DIR/$PACKAGE.spec"
|
sed -i "s/CHANGELOG_DATE_PLACEHOLDER/${CHANGELOG_DATE}/g" "$WORK_DIR/$PACKAGE.spec"
|
||||||
# Explicitly set Version:/Release: in case the spec uses %{version} macro
|
|
||||||
sed -i "s/^Version:.*/Version: ${DMS_GREETER_BASE_VERSION}/" "$WORK_DIR/$PACKAGE.spec"
|
|
||||||
sed -i "s/^Release:.*/Release: ${DMS_GREETER_RELEASE}%{?dist}/" "$WORK_DIR/$PACKAGE.spec"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,6 @@
|
|||||||
with pkgs;
|
with pkgs;
|
||||||
[
|
[
|
||||||
go_1_25
|
go_1_25
|
||||||
go-mockery_2
|
|
||||||
gopls
|
gopls
|
||||||
delve
|
delve
|
||||||
go-tools
|
go-tools
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
The Wolverine
|
Saffron Bloom
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Effects
|
|
||||||
import qs.Common
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var level: Theme.elevationLevel2
|
|
||||||
property string direction: Theme.elevationLightDirection
|
|
||||||
property real fallbackOffset: 4
|
|
||||||
|
|
||||||
property color targetColor: "white"
|
|
||||||
property real targetRadius: Theme.cornerRadius
|
|
||||||
property color borderColor: "transparent"
|
|
||||||
property real borderWidth: 0
|
|
||||||
|
|
||||||
property bool shadowEnabled: Theme.elevationEnabled
|
|
||||||
property real shadowBlurPx: level && level.blurPx !== undefined ? level.blurPx : 0
|
|
||||||
property real shadowSpreadPx: level && level.spreadPx !== undefined ? level.spreadPx : 0
|
|
||||||
property real shadowOffsetX: Theme.elevationOffsetXFor(level, direction, fallbackOffset)
|
|
||||||
property real shadowOffsetY: Theme.elevationOffsetYFor(level, direction, fallbackOffset)
|
|
||||||
property color shadowColor: Theme.elevationShadowColor(level)
|
|
||||||
property real shadowOpacity: 1
|
|
||||||
property real blurMax: Theme.elevationBlurMax
|
|
||||||
|
|
||||||
property alias sourceRect: sourceRect
|
|
||||||
|
|
||||||
layer.enabled: shadowEnabled
|
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
|
||||||
autoPaddingEnabled: true
|
|
||||||
shadowEnabled: true
|
|
||||||
blurEnabled: false
|
|
||||||
maskEnabled: false
|
|
||||||
shadowBlur: Math.max(0, Math.min(1, root.shadowBlurPx / Math.max(1, root.blurMax)))
|
|
||||||
shadowScale: 1 + (2 * root.shadowSpreadPx) / Math.max(1, Math.min(root.width, root.height))
|
|
||||||
shadowHorizontalOffset: root.shadowOffsetX
|
|
||||||
shadowVerticalOffset: root.shadowOffsetY
|
|
||||||
blurMax: root.blurMax
|
|
||||||
shadowColor: root.shadowColor
|
|
||||||
shadowOpacity: root.shadowOpacity
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: sourceRect
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: root.targetRadius
|
|
||||||
color: root.targetColor
|
|
||||||
border.color: root.borderColor
|
|
||||||
border.width: root.borderWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ import "settings/SettingsStore.js" as Store
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property int settingsConfigVersion: 6
|
readonly property int settingsConfigVersion: 5
|
||||||
|
|
||||||
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
|
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
|
||||||
|
|
||||||
@@ -165,24 +165,6 @@ Singleton {
|
|||||||
property int modalCustomAnimationDuration: 150
|
property int modalCustomAnimationDuration: 150
|
||||||
property bool enableRippleEffects: true
|
property bool enableRippleEffects: true
|
||||||
onEnableRippleEffectsChanged: saveSettings()
|
onEnableRippleEffectsChanged: saveSettings()
|
||||||
property bool m3ElevationEnabled: true
|
|
||||||
onM3ElevationEnabledChanged: saveSettings()
|
|
||||||
property int m3ElevationIntensity: 12
|
|
||||||
onM3ElevationIntensityChanged: saveSettings()
|
|
||||||
property int m3ElevationOpacity: 30
|
|
||||||
onM3ElevationOpacityChanged: saveSettings()
|
|
||||||
property string m3ElevationColorMode: "default"
|
|
||||||
onM3ElevationColorModeChanged: saveSettings()
|
|
||||||
property string m3ElevationLightDirection: "top"
|
|
||||||
onM3ElevationLightDirectionChanged: saveSettings()
|
|
||||||
property string m3ElevationCustomColor: "#000000"
|
|
||||||
onM3ElevationCustomColorChanged: saveSettings()
|
|
||||||
property bool modalElevationEnabled: true
|
|
||||||
onModalElevationEnabledChanged: saveSettings()
|
|
||||||
property bool popoutElevationEnabled: true
|
|
||||||
onPopoutElevationEnabledChanged: saveSettings()
|
|
||||||
property bool barElevationEnabled: true
|
|
||||||
onBarElevationEnabledChanged: saveSettings()
|
|
||||||
property string wallpaperFillMode: "Fill"
|
property string wallpaperFillMode: "Fill"
|
||||||
property bool blurredWallpaperLayer: false
|
property bool blurredWallpaperLayer: false
|
||||||
property bool blurWallpaperOnOverview: false
|
property bool blurWallpaperOnOverview: false
|
||||||
@@ -620,7 +602,7 @@ Singleton {
|
|||||||
"scrollYBehavior": "workspace",
|
"scrollYBehavior": "workspace",
|
||||||
"shadowIntensity": 0,
|
"shadowIntensity": 0,
|
||||||
"shadowOpacity": 60,
|
"shadowOpacity": 60,
|
||||||
"shadowColorMode": "default",
|
"shadowColorMode": "text",
|
||||||
"shadowCustomColor": "#000000",
|
"shadowCustomColor": "#000000",
|
||||||
"clickThrough": false
|
"clickThrough": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -673,232 +673,6 @@ Singleton {
|
|||||||
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
|
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
|
||||||
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
|
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
|
||||||
|
|
||||||
readonly property bool elevationEnabled: typeof SettingsData !== "undefined" && (SettingsData.m3ElevationEnabled ?? true)
|
|
||||||
readonly property real elevationBlurMax: typeof SettingsData !== "undefined" && SettingsData.m3ElevationIntensity !== undefined ? Math.min(128, Math.max(32, SettingsData.m3ElevationIntensity * 2)) : 64
|
|
||||||
|
|
||||||
readonly property real _elevMult: typeof SettingsData !== "undefined" && SettingsData.m3ElevationIntensity !== undefined ? SettingsData.m3ElevationIntensity / 12 : 1
|
|
||||||
readonly property real _opMult: typeof SettingsData !== "undefined" && SettingsData.m3ElevationOpacity !== undefined ? SettingsData.m3ElevationOpacity / 60 : 1
|
|
||||||
function normalizeElevationDirection(direction) {
|
|
||||||
switch (direction) {
|
|
||||||
case "top":
|
|
||||||
case "topLeft":
|
|
||||||
case "topRight":
|
|
||||||
case "bottom":
|
|
||||||
case "bottomLeft":
|
|
||||||
case "bottomRight":
|
|
||||||
case "left":
|
|
||||||
case "right":
|
|
||||||
case "autoBar":
|
|
||||||
return direction;
|
|
||||||
default:
|
|
||||||
return "top";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property string elevationLightDirection: {
|
|
||||||
if (typeof SettingsData === "undefined" || !SettingsData.m3ElevationLightDirection)
|
|
||||||
return "top";
|
|
||||||
switch (SettingsData.m3ElevationLightDirection) {
|
|
||||||
case "autoBar":
|
|
||||||
case "top":
|
|
||||||
case "topLeft":
|
|
||||||
case "topRight":
|
|
||||||
case "bottom":
|
|
||||||
return SettingsData.m3ElevationLightDirection;
|
|
||||||
default:
|
|
||||||
return "top";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly property real _elevDiagRatio: 0.55
|
|
||||||
readonly property string _globalElevationDirForTokens: {
|
|
||||||
const normalized = normalizeElevationDirection(elevationLightDirection);
|
|
||||||
return normalized === "autoBar" ? "top" : normalized;
|
|
||||||
}
|
|
||||||
readonly property real _elevDirX: {
|
|
||||||
switch (_globalElevationDirForTokens) {
|
|
||||||
case "topLeft":
|
|
||||||
case "bottomLeft":
|
|
||||||
case "left":
|
|
||||||
return 1;
|
|
||||||
case "topRight":
|
|
||||||
case "bottomRight":
|
|
||||||
case "right":
|
|
||||||
return -1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly property real _elevDirY: {
|
|
||||||
switch (_globalElevationDirForTokens) {
|
|
||||||
case "bottom":
|
|
||||||
case "bottomLeft":
|
|
||||||
case "bottomRight":
|
|
||||||
return -1;
|
|
||||||
case "left":
|
|
||||||
case "right":
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly property real _elevDirXScale: (_globalElevationDirForTokens === "left" || _globalElevationDirForTokens === "right") ? 1 : _elevDiagRatio
|
|
||||||
|
|
||||||
readonly property var elevationLevel1: ({
|
|
||||||
blurPx: 4 * _elevMult,
|
|
||||||
offsetX: 1 * _elevMult * _elevDirXScale * _elevDirX,
|
|
||||||
offsetY: 1 * _elevMult * _elevDirY,
|
|
||||||
spreadPx: 0,
|
|
||||||
alpha: 0.2 * _opMult
|
|
||||||
})
|
|
||||||
readonly property var elevationLevel2: ({
|
|
||||||
blurPx: 8 * _elevMult,
|
|
||||||
offsetX: 4 * _elevMult * _elevDirXScale * _elevDirX,
|
|
||||||
offsetY: 4 * _elevMult * _elevDirY,
|
|
||||||
spreadPx: 0,
|
|
||||||
alpha: 0.25 * _opMult
|
|
||||||
})
|
|
||||||
readonly property var elevationLevel3: ({
|
|
||||||
blurPx: 12 * _elevMult,
|
|
||||||
offsetX: 6 * _elevMult * _elevDirXScale * _elevDirX,
|
|
||||||
offsetY: 6 * _elevMult * _elevDirY,
|
|
||||||
spreadPx: 0,
|
|
||||||
alpha: 0.3 * _opMult
|
|
||||||
})
|
|
||||||
readonly property var elevationLevel4: ({
|
|
||||||
blurPx: 16 * _elevMult,
|
|
||||||
offsetX: 8 * _elevMult * _elevDirXScale * _elevDirX,
|
|
||||||
offsetY: 8 * _elevMult * _elevDirY,
|
|
||||||
spreadPx: 0,
|
|
||||||
alpha: 0.3 * _opMult
|
|
||||||
})
|
|
||||||
readonly property var elevationLevel5: ({
|
|
||||||
blurPx: 20 * _elevMult,
|
|
||||||
offsetX: 10 * _elevMult * _elevDirXScale * _elevDirX,
|
|
||||||
offsetY: 10 * _elevMult * _elevDirY,
|
|
||||||
spreadPx: 0,
|
|
||||||
alpha: 0.3 * _opMult
|
|
||||||
})
|
|
||||||
|
|
||||||
function elevationOffsetMagnitude(level, fallback, direction) {
|
|
||||||
if (!level) {
|
|
||||||
return fallback !== undefined ? Math.abs(fallback) : 0;
|
|
||||||
}
|
|
||||||
const yMag = Math.abs(level.offsetY !== undefined ? level.offsetY : 0);
|
|
||||||
if (yMag > 0)
|
|
||||||
return yMag;
|
|
||||||
const xMag = Math.abs(level.offsetX !== undefined ? level.offsetX : 0);
|
|
||||||
if (xMag > 0) {
|
|
||||||
if (direction === "left" || direction === "right")
|
|
||||||
return xMag;
|
|
||||||
return xMag / _elevDiagRatio;
|
|
||||||
}
|
|
||||||
return fallback !== undefined ? Math.abs(fallback) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function elevationOffsetXFor(level, direction, fallback) {
|
|
||||||
const dir = normalizeElevationDirection(direction || elevationLightDirection);
|
|
||||||
const mag = elevationOffsetMagnitude(level, fallback, dir);
|
|
||||||
switch (dir) {
|
|
||||||
case "topLeft":
|
|
||||||
case "bottomLeft":
|
|
||||||
return mag * _elevDiagRatio;
|
|
||||||
case "topRight":
|
|
||||||
case "bottomRight":
|
|
||||||
return -mag * _elevDiagRatio;
|
|
||||||
case "left":
|
|
||||||
return mag;
|
|
||||||
case "right":
|
|
||||||
return -mag;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function elevationOffsetYFor(level, direction, fallback) {
|
|
||||||
const dir = normalizeElevationDirection(direction || elevationLightDirection);
|
|
||||||
const mag = elevationOffsetMagnitude(level, fallback, dir);
|
|
||||||
switch (dir) {
|
|
||||||
case "bottom":
|
|
||||||
case "bottomLeft":
|
|
||||||
case "bottomRight":
|
|
||||||
return -mag;
|
|
||||||
case "left":
|
|
||||||
case "right":
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return mag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function elevationOffsetX(level, fallback) {
|
|
||||||
return elevationOffsetXFor(level, elevationLightDirection, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function elevationOffsetY(level, fallback) {
|
|
||||||
return elevationOffsetYFor(level, elevationLightDirection, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function elevationRenderPadding(level, direction, fallbackOffset, extraPadding, minPadding) {
|
|
||||||
const dir = direction !== undefined ? direction : elevationLightDirection;
|
|
||||||
const blur = (level && level.blurPx !== undefined) ? Math.max(0, level.blurPx) : 0;
|
|
||||||
const spread = (level && level.spreadPx !== undefined) ? Math.max(0, level.spreadPx) : 0;
|
|
||||||
const fallback = fallbackOffset !== undefined ? fallbackOffset : 0;
|
|
||||||
const extra = extraPadding !== undefined ? extraPadding : 8;
|
|
||||||
const minPad = minPadding !== undefined ? minPadding : 16;
|
|
||||||
const offsetX = Math.abs(elevationOffsetXFor(level, dir, fallback));
|
|
||||||
const offsetY = Math.abs(elevationOffsetYFor(level, dir, fallback));
|
|
||||||
return Math.max(minPad, blur + spread + Math.max(offsetX, offsetY) + extra);
|
|
||||||
}
|
|
||||||
|
|
||||||
function elevationShadowColor(level) {
|
|
||||||
const alpha = (level && level.alpha !== undefined) ? level.alpha : 0.3;
|
|
||||||
let r = 0;
|
|
||||||
let g = 0;
|
|
||||||
let b = 0;
|
|
||||||
|
|
||||||
if (typeof SettingsData !== "undefined") {
|
|
||||||
const mode = SettingsData.m3ElevationColorMode || "default";
|
|
||||||
if (mode === "default") {
|
|
||||||
r = 0;
|
|
||||||
g = 0;
|
|
||||||
b = 0;
|
|
||||||
} else if (mode === "text") {
|
|
||||||
r = surfaceText.r;
|
|
||||||
g = surfaceText.g;
|
|
||||||
b = surfaceText.b;
|
|
||||||
} else if (mode === "primary") {
|
|
||||||
r = primary.r;
|
|
||||||
g = primary.g;
|
|
||||||
b = primary.b;
|
|
||||||
} else if (mode === "surfaceVariant") {
|
|
||||||
r = surfaceVariant.r;
|
|
||||||
g = surfaceVariant.g;
|
|
||||||
b = surfaceVariant.b;
|
|
||||||
} else if (mode === "custom" && SettingsData.m3ElevationCustomColor) {
|
|
||||||
const c = Qt.color(SettingsData.m3ElevationCustomColor);
|
|
||||||
r = c.r;
|
|
||||||
g = c.g;
|
|
||||||
b = c.b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Qt.rgba(r, g, b, alpha);
|
|
||||||
}
|
|
||||||
function elevationTintOpacity(level) {
|
|
||||||
if (!level)
|
|
||||||
return 0;
|
|
||||||
if (level === elevationLevel1)
|
|
||||||
return 0.05;
|
|
||||||
if (level === elevationLevel2)
|
|
||||||
return 0.08;
|
|
||||||
if (level === elevationLevel3)
|
|
||||||
return 0.11;
|
|
||||||
if (level === elevationLevel4)
|
|
||||||
return 0.12;
|
|
||||||
if (level === elevationLevel5)
|
|
||||||
return 0.14;
|
|
||||||
return 0.08;
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property var animationDurations: [
|
readonly property var animationDurations: [
|
||||||
{
|
{
|
||||||
"shorter": 0,
|
"shorter": 0,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ var SPEC = {
|
|||||||
widgetColorMode: { def: "default" },
|
widgetColorMode: { def: "default" },
|
||||||
controlCenterTileColorMode: { def: "primary" },
|
controlCenterTileColorMode: { def: "primary" },
|
||||||
buttonColorMode: { def: "primary" },
|
buttonColorMode: { def: "primary" },
|
||||||
cornerRadius: { def: 16, onChange: "updateCompositorLayout" },
|
cornerRadius: { def: 12, onChange: "updateCompositorLayout" },
|
||||||
niriLayoutGapsOverride: { def: -1, onChange: "updateCompositorLayout" },
|
niriLayoutGapsOverride: { def: -1, onChange: "updateCompositorLayout" },
|
||||||
niriLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" },
|
niriLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" },
|
||||||
niriLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" },
|
niriLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" },
|
||||||
@@ -46,15 +46,6 @@ var SPEC = {
|
|||||||
modalAnimationSpeed: { def: 1 },
|
modalAnimationSpeed: { def: 1 },
|
||||||
modalCustomAnimationDuration: { def: 150 },
|
modalCustomAnimationDuration: { def: 150 },
|
||||||
enableRippleEffects: { def: true },
|
enableRippleEffects: { def: true },
|
||||||
m3ElevationEnabled: { def: true },
|
|
||||||
m3ElevationIntensity: { def: 12 },
|
|
||||||
m3ElevationOpacity: { def: 30 },
|
|
||||||
m3ElevationColorMode: { def: "default" },
|
|
||||||
m3ElevationLightDirection: { def: "top" },
|
|
||||||
m3ElevationCustomColor: { def: "#000000" },
|
|
||||||
modalElevationEnabled: { def: true },
|
|
||||||
popoutElevationEnabled: { def: true },
|
|
||||||
barElevationEnabled: { def: true },
|
|
||||||
wallpaperFillMode: { def: "Fill" },
|
wallpaperFillMode: { def: "Fill" },
|
||||||
blurredWallpaperLayer: { def: false },
|
blurredWallpaperLayer: { def: false },
|
||||||
blurWallpaperOnOverview: { def: false },
|
blurWallpaperOnOverview: { def: false },
|
||||||
@@ -434,7 +425,7 @@ var SPEC = {
|
|||||||
scrollYBehavior: "workspace",
|
scrollYBehavior: "workspace",
|
||||||
shadowIntensity: 0,
|
shadowIntensity: 0,
|
||||||
shadowOpacity: 60,
|
shadowOpacity: 60,
|
||||||
shadowColorMode: "default",
|
shadowColorMode: "text",
|
||||||
shadowCustomColor: "#000000",
|
shadowCustomColor: "#000000",
|
||||||
clickThrough: false
|
clickThrough: false
|
||||||
}], onChange: "updateBarConfigs"
|
}], onChange: "updateBarConfigs"
|
||||||
|
|||||||
@@ -226,25 +226,6 @@ function migrateToVersion(obj, targetVersion) {
|
|||||||
settings.configVersion = 5;
|
settings.configVersion = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentVersion < 6) {
|
|
||||||
console.info("Migrating settings from version", currentVersion, "to version 6");
|
|
||||||
|
|
||||||
if (settings.barElevationEnabled === undefined) {
|
|
||||||
var legacyBars = Array.isArray(settings.barConfigs) ? settings.barConfigs : [];
|
|
||||||
var hadLegacyBarShadowEnabled = false;
|
|
||||||
for (var j = 0; j < legacyBars.length; j++) {
|
|
||||||
var legacyIntensity = Number(legacyBars[j] && legacyBars[j].shadowIntensity);
|
|
||||||
if (!isNaN(legacyIntensity) && legacyIntensity > 0) {
|
|
||||||
hadLegacyBarShadowEnabled = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings.barElevationEnabled = hadLegacyBarShadowEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.configVersion = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -365,23 +365,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: wifiQRCodeModalLoader
|
|
||||||
active: false
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.wifiQRCodeModalLoader = wifiQRCodeModalLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
WifiQRCodeModal {
|
|
||||||
id: wifiQRCodeModalItem
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
PopoutService.wifiQRCodeModal = wifiQRCodeModalItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
id: polkitAuthModalLoader
|
id: polkitAuthModalLoader
|
||||||
active: false
|
active: false
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ Item {
|
|||||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
||||||
property color backgroundColor: Theme.surfaceContainer
|
property color backgroundColor: Theme.surfaceContainer
|
||||||
property color borderColor: Theme.outlineMedium
|
property color borderColor: Theme.outlineMedium
|
||||||
property real borderWidth: 0
|
property real borderWidth: 1
|
||||||
property real cornerRadius: Theme.cornerRadius
|
property real cornerRadius: Theme.cornerRadius
|
||||||
property bool enableShadow: true
|
property bool enableShadow: false
|
||||||
property alias modalFocusScope: focusScope
|
property alias modalFocusScope: focusScope
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
property bool shouldHaveFocus: shouldBeVisible
|
property bool shouldHaveFocus: shouldBeVisible
|
||||||
@@ -142,11 +142,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var shadowLevel: Theme.elevationLevel3
|
readonly property real shadowBuffer: 5
|
||||||
readonly property real shadowFallbackOffset: 6
|
|
||||||
readonly property real shadowRenderPadding: (root.enableShadow && Theme.elevationEnabled && SettingsData.modalElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, Theme.elevationLightDirection, shadowFallbackOffset, 8, 16) : 0
|
|
||||||
readonly property real shadowMotionPadding: animationType === "slide" ? 30 : Math.max(0, animationOffset)
|
|
||||||
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
|
||||||
readonly property real alignedWidth: Theme.px(modalWidth, dpr)
|
readonly property real alignedWidth: Theme.px(modalWidth, dpr)
|
||||||
readonly property real alignedHeight: Theme.px(modalHeight, dpr)
|
readonly property real alignedHeight: Theme.px(modalHeight, dpr)
|
||||||
|
|
||||||
@@ -381,16 +377,12 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Rectangle {
|
||||||
id: modalShadowLayer
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
level: root.shadowLevel
|
color: root.backgroundColor
|
||||||
fallbackOffset: root.shadowFallbackOffset
|
border.color: root.borderColor
|
||||||
targetRadius: root.cornerRadius
|
border.width: root.borderWidth
|
||||||
targetColor: root.backgroundColor
|
radius: root.cornerRadius
|
||||||
borderColor: root.borderColor
|
|
||||||
borderWidth: root.borderWidth
|
|
||||||
shadowEnabled: root.enableShadow && Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
|
|||||||
@@ -162,11 +162,6 @@ Item {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
property string fileSearchType: "all"
|
|
||||||
property string fileSearchExt: ""
|
|
||||||
property string fileSearchFolder: ""
|
|
||||||
property string fileSearchSort: "score"
|
|
||||||
|
|
||||||
property string pluginFilter: ""
|
property string pluginFilter: ""
|
||||||
property string activePluginName: ""
|
property string activePluginName: ""
|
||||||
property var activePluginCategories: []
|
property var activePluginCategories: []
|
||||||
@@ -351,10 +346,6 @@ Item {
|
|||||||
previousSearchMode = "all";
|
previousSearchMode = "all";
|
||||||
autoSwitchedToFiles = false;
|
autoSwitchedToFiles = false;
|
||||||
isFileSearching = false;
|
isFileSearching = false;
|
||||||
fileSearchType = "all";
|
|
||||||
fileSearchExt = "";
|
|
||||||
fileSearchFolder = "";
|
|
||||||
fileSearchSort = "score";
|
|
||||||
sections = [];
|
sections = [];
|
||||||
flatModel = [];
|
flatModel = [];
|
||||||
selectedFlatIndex = 0;
|
selectedFlatIndex = 0;
|
||||||
@@ -408,34 +399,6 @@ Item {
|
|||||||
performSearch();
|
performSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFileSearchType(type) {
|
|
||||||
if (fileSearchType === type)
|
|
||||||
return;
|
|
||||||
fileSearchType = type;
|
|
||||||
performFileSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setFileSearchExt(ext) {
|
|
||||||
if (fileSearchExt === ext)
|
|
||||||
return;
|
|
||||||
fileSearchExt = ext;
|
|
||||||
performFileSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setFileSearchFolder(folder) {
|
|
||||||
if (fileSearchFolder === folder)
|
|
||||||
return;
|
|
||||||
fileSearchFolder = folder;
|
|
||||||
performFileSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setFileSearchSort(sort) {
|
|
||||||
if (fileSearchSort === sort)
|
|
||||||
return;
|
|
||||||
fileSearchSort = sort;
|
|
||||||
performFileSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearPluginFilter() {
|
function clearPluginFilter() {
|
||||||
if (pluginFilter) {
|
if (pluginFilter) {
|
||||||
pluginFilter = "";
|
pluginFilter = "";
|
||||||
@@ -864,20 +827,10 @@ Item {
|
|||||||
var params = {
|
var params = {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
fuzzy: true,
|
fuzzy: true,
|
||||||
sort: fileSearchSort || "score",
|
sort: "score",
|
||||||
desc: true
|
desc: true
|
||||||
};
|
};
|
||||||
|
|
||||||
if (DSearchService.supportsTypeFilter) {
|
|
||||||
params.type = (fileSearchType && fileSearchType !== "all") ? fileSearchType : "all";
|
|
||||||
}
|
|
||||||
if (fileSearchExt) {
|
|
||||||
params.ext = fileSearchExt;
|
|
||||||
}
|
|
||||||
if (fileSearchFolder) {
|
|
||||||
params.folder = fileSearchFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
DSearchService.search(fileQuery, params, function (response) {
|
DSearchService.search(fileQuery, params, function (response) {
|
||||||
isFileSearching = false;
|
isFileSearching = false;
|
||||||
if (response.error)
|
if (response.error)
|
||||||
@@ -887,73 +840,34 @@ Item {
|
|||||||
|
|
||||||
for (var i = 0; i < hits.length; i++) {
|
for (var i = 0; i < hits.length; i++) {
|
||||||
var hit = hits[i];
|
var hit = hits[i];
|
||||||
var docTypes = hit.locations?.doc_type;
|
|
||||||
var isDir = docTypes ? !!docTypes["dir"] : false;
|
|
||||||
fileItems.push(transformFileResult({
|
fileItems.push(transformFileResult({
|
||||||
path: hit.id || "",
|
path: hit.id || "",
|
||||||
score: hit.score || 0,
|
score: hit.score || 0
|
||||||
is_dir: isDir
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileSections = [];
|
var fileSection = {
|
||||||
var showType = fileSearchType || "all";
|
id: "files",
|
||||||
|
title: I18n.tr("Files"),
|
||||||
if (showType === "all" && DSearchService.supportsTypeFilter) {
|
icon: "folder",
|
||||||
var onlyFiles = [];
|
priority: 4,
|
||||||
var onlyDirs = [];
|
items: fileItems,
|
||||||
for (var j = 0; j < fileItems.length; j++) {
|
collapsed: collapsedSections["files"] || false,
|
||||||
if (fileItems[j].data?.is_dir)
|
flatStartIndex: 0
|
||||||
onlyDirs.push(fileItems[j]);
|
};
|
||||||
else
|
|
||||||
onlyFiles.push(fileItems[j]);
|
|
||||||
}
|
|
||||||
if (onlyFiles.length > 0) {
|
|
||||||
fileSections.push({
|
|
||||||
id: "files",
|
|
||||||
title: I18n.tr("Files"),
|
|
||||||
icon: "insert_drive_file",
|
|
||||||
priority: 4,
|
|
||||||
items: onlyFiles,
|
|
||||||
collapsed: collapsedSections["files"] || false,
|
|
||||||
flatStartIndex: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (onlyDirs.length > 0) {
|
|
||||||
fileSections.push({
|
|
||||||
id: "folders",
|
|
||||||
title: I18n.tr("Folders"),
|
|
||||||
icon: "folder",
|
|
||||||
priority: 4.1,
|
|
||||||
items: onlyDirs,
|
|
||||||
collapsed: collapsedSections["folders"] || false,
|
|
||||||
flatStartIndex: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var filesIcon = showType === "dir" ? "folder" : showType === "file" ? "insert_drive_file" : "folder";
|
|
||||||
var filesTitle = showType === "dir" ? I18n.tr("Folders") : I18n.tr("Files");
|
|
||||||
if (fileItems.length > 0) {
|
|
||||||
fileSections.push({
|
|
||||||
id: "files",
|
|
||||||
title: filesTitle,
|
|
||||||
icon: filesIcon,
|
|
||||||
priority: 4,
|
|
||||||
items: fileItems,
|
|
||||||
collapsed: collapsedSections["files"] || false,
|
|
||||||
flatStartIndex: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var newSections;
|
var newSections;
|
||||||
if (searchMode === "files") {
|
if (searchMode === "files") {
|
||||||
newSections = fileSections;
|
newSections = fileItems.length > 0 ? [fileSection] : [];
|
||||||
} else {
|
} else {
|
||||||
var existingNonFile = sections.filter(function (s) {
|
var existingNonFile = sections.filter(function (s) {
|
||||||
return s.id !== "files" && s.id !== "folders";
|
return s.id !== "files";
|
||||||
});
|
});
|
||||||
newSections = existingNonFile.concat(fileSections);
|
if (fileItems.length > 0) {
|
||||||
|
newSections = existingNonFile.concat([fileSection]);
|
||||||
|
} else {
|
||||||
|
newSections = existingNonFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
newSections.sort(function (a, b) {
|
newSections.sort(function (a, b) {
|
||||||
return a.priority - b.priority;
|
return a.priority - b.priority;
|
||||||
@@ -999,7 +913,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function transformFileResult(file) {
|
function transformFileResult(file) {
|
||||||
return Transform.transformFileResult(file, I18n.tr("Open"), I18n.tr("Open folder"), I18n.tr("Copy path"), I18n.tr("Open in terminal"));
|
return Transform.transformFileResult(file, I18n.tr("Open"), I18n.tr("Open folder"), I18n.tr("Copy path"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectTrigger(query) {
|
function detectTrigger(query) {
|
||||||
@@ -1667,9 +1581,6 @@ Item {
|
|||||||
case "copy_path":
|
case "copy_path":
|
||||||
copyToClipboard(item.data.path);
|
copyToClipboard(item.data.path);
|
||||||
break;
|
break;
|
||||||
case "open_terminal":
|
|
||||||
openTerminal(item.data.path);
|
|
||||||
break;
|
|
||||||
case "copy":
|
case "copy":
|
||||||
copyToClipboard(item.name);
|
copyToClipboard(item.name);
|
||||||
break;
|
break;
|
||||||
@@ -1751,16 +1662,6 @@ Item {
|
|||||||
Qt.openUrlExternally("file://" + folder);
|
Qt.openUrlExternally("file://" + folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
function openTerminal(path) {
|
|
||||||
if (!path)
|
|
||||||
return;
|
|
||||||
var terminal = Quickshell.env("TERMINAL") || "xterm";
|
|
||||||
Quickshell.execDetached({
|
|
||||||
command: [terminal],
|
|
||||||
workingDirectory: path
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyToClipboard(text) {
|
function copyToClipboard(text) {
|
||||||
if (!text)
|
if (!text)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
@@ -76,7 +75,7 @@ Item {
|
|||||||
return Theme.primary;
|
return Theme.primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 0
|
readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 1
|
||||||
|
|
||||||
signal dialogClosed
|
signal dialogClosed
|
||||||
|
|
||||||
@@ -108,10 +107,6 @@ Item {
|
|||||||
spotlightContent.controller.activePluginId = "";
|
spotlightContent.controller.activePluginId = "";
|
||||||
spotlightContent.controller.activePluginName = "";
|
spotlightContent.controller.activePluginName = "";
|
||||||
spotlightContent.controller.pluginFilter = "";
|
spotlightContent.controller.pluginFilter = "";
|
||||||
spotlightContent.controller.fileSearchType = "all";
|
|
||||||
spotlightContent.controller.fileSearchExt = "";
|
|
||||||
spotlightContent.controller.fileSearchFolder = "";
|
|
||||||
spotlightContent.controller.fileSearchSort = "score";
|
|
||||||
spotlightContent.controller.collapsedSections = {};
|
spotlightContent.controller.collapsedSections = {};
|
||||||
spotlightContent.controller.selectedFlatIndex = 0;
|
spotlightContent.controller.selectedFlatIndex = 0;
|
||||||
spotlightContent.controller.selectedItem = null;
|
spotlightContent.controller.selectedItem = null;
|
||||||
@@ -391,16 +386,12 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Rectangle {
|
||||||
id: launcherShadowLayer
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
level: Theme.elevationLevel3
|
color: root.backgroundColor
|
||||||
fallbackOffset: 6
|
border.color: root.borderColor
|
||||||
targetColor: root.backgroundColor
|
border.width: root.borderWidth
|
||||||
borderColor: root.borderColor
|
radius: root.cornerRadius
|
||||||
borderWidth: root.borderWidth
|
|
||||||
targetRadius: root.cornerRadius
|
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -116,43 +116,31 @@ function transformBuiltInLauncherItem(item, pluginId, openLabel) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformFileResult(file, openLabel, openFolderLabel, copyPathLabel, openTerminalLabel) {
|
function transformFileResult(file, openLabel, openFolderLabel, copyPathLabel) {
|
||||||
var filename = file.path ? file.path.split("/").pop() : "";
|
var filename = file.path ? file.path.split("/").pop() : "";
|
||||||
var dirname = file.path ? file.path.substring(0, file.path.lastIndexOf("/")) : "";
|
var dirname = file.path ? file.path.substring(0, file.path.lastIndexOf("/")) : "";
|
||||||
var isDir = file.is_dir || false;
|
|
||||||
|
|
||||||
var actions = [];
|
|
||||||
if (isDir) {
|
|
||||||
if (openTerminalLabel) {
|
|
||||||
actions.push({
|
|
||||||
name: openTerminalLabel,
|
|
||||||
icon: "terminal",
|
|
||||||
action: "open_terminal"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
actions.push({
|
|
||||||
name: openFolderLabel,
|
|
||||||
icon: "folder_open",
|
|
||||||
action: "open_folder"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
actions.push({
|
|
||||||
name: copyPathLabel,
|
|
||||||
icon: "content_copy",
|
|
||||||
action: "copy_path"
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: file.path || "",
|
id: file.path || "",
|
||||||
type: "file",
|
type: "file",
|
||||||
name: filename,
|
name: filename,
|
||||||
subtitle: dirname,
|
subtitle: dirname,
|
||||||
icon: isDir ? "folder" : Utils.getFileIcon(filename),
|
icon: Utils.getFileIcon(filename),
|
||||||
iconType: "material",
|
iconType: "material",
|
||||||
section: "files",
|
section: "files",
|
||||||
data: file,
|
data: file,
|
||||||
actions: actions,
|
actions: [
|
||||||
|
{
|
||||||
|
name: openFolderLabel,
|
||||||
|
icon: "folder_open",
|
||||||
|
action: "open_folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: copyPathLabel,
|
||||||
|
icon: "content_copy",
|
||||||
|
action: "copy_path"
|
||||||
|
}
|
||||||
|
],
|
||||||
primaryAction: {
|
primaryAction: {
|
||||||
name: openLabel,
|
name: openLabel,
|
||||||
icon: "open_in_new",
|
icon: "open_in_new",
|
||||||
|
|||||||
@@ -549,151 +549,8 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: fileFilterRow
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: showFileFilters ? fileFilterContent.height : 0
|
height: parent.height - searchField.height - categoryRow.height - actionPanel.height - Theme.spacingXS * (categoryRow.visible ? 3 : 2)
|
||||||
visible: showFileFilters
|
|
||||||
|
|
||||||
readonly property bool showFileFilters: controller.searchMode === "files"
|
|
||||||
|
|
||||||
Behavior on height {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: fileFilterContent
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: typeChips
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: 2
|
|
||||||
visible: DSearchService.supportsTypeFilter
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: [
|
|
||||||
{
|
|
||||||
id: "all",
|
|
||||||
label: I18n.tr("All"),
|
|
||||||
icon: "search"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "file",
|
|
||||||
label: I18n.tr("Files"),
|
|
||||||
icon: "insert_drive_file"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "dir",
|
|
||||||
label: I18n.tr("Folders"),
|
|
||||||
icon: "folder"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
required property var modelData
|
|
||||||
required property int index
|
|
||||||
|
|
||||||
width: chipContent.width + Theme.spacingM * 2
|
|
||||||
height: sortDropdown.height
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: controller.fileSearchType === modelData.id || chipArea.containsMouse ? Theme.primaryContainer : "transparent"
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: chipContent
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
name: modelData.icon
|
|
||||||
size: 14
|
|
||||||
color: controller.fileSearchType === modelData.id ? Theme.primary : Theme.surfaceVariantText
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: modelData.label
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: controller.fileSearchType === modelData.id ? Theme.primary : Theme.surfaceText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: chipArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: controller.setFileSearchType(modelData.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 1
|
|
||||||
height: 20
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: Theme.outlineMedium
|
|
||||||
visible: typeChips.visible
|
|
||||||
}
|
|
||||||
|
|
||||||
DankDropdown {
|
|
||||||
id: sortDropdown
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: Math.min(130, parent.width / 3)
|
|
||||||
compactMode: true
|
|
||||||
dropdownWidth: 130
|
|
||||||
popupWidth: 150
|
|
||||||
maxPopupHeight: 200
|
|
||||||
currentValue: {
|
|
||||||
switch (controller.fileSearchSort) {
|
|
||||||
case "score":
|
|
||||||
return I18n.tr("Score");
|
|
||||||
case "name":
|
|
||||||
return I18n.tr("Name");
|
|
||||||
case "modified":
|
|
||||||
return I18n.tr("Modified");
|
|
||||||
case "size":
|
|
||||||
return I18n.tr("Size");
|
|
||||||
default:
|
|
||||||
return I18n.tr("Score");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options: [I18n.tr("Score"), I18n.tr("Name"), I18n.tr("Modified"), I18n.tr("Size")]
|
|
||||||
|
|
||||||
onValueChanged: value => {
|
|
||||||
var sortMap = {};
|
|
||||||
sortMap[I18n.tr("Score")] = "score";
|
|
||||||
sortMap[I18n.tr("Name")] = "name";
|
|
||||||
sortMap[I18n.tr("Modified")] = "modified";
|
|
||||||
sortMap[I18n.tr("Size")] = "size";
|
|
||||||
controller.setFileSearchSort(sortMap[value] || "score");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankTextField {
|
|
||||||
id: extFilterField
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: Math.min(100, parent.width / 4)
|
|
||||||
height: sortDropdown.height
|
|
||||||
placeholderText: I18n.tr("ext")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
showClearButton: text.length > 0
|
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
controller.setFileSearchExt(text.trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height - searchField.height - categoryRow.height - fileFilterRow.height - actionPanel.height - Theme.spacingXS * ((categoryRow.visible ? 1 : 0) + (fileFilterRow.visible ? 1 : 0) + 2)
|
|
||||||
opacity: root.parentModal?.isClosing ? 0 : 1
|
opacity: root.parentModal?.isClosing ? 0 : 1
|
||||||
|
|
||||||
ResultsList {
|
ResultsList {
|
||||||
@@ -729,9 +586,6 @@ FocusScope {
|
|||||||
function onSearchQueryRequested(query) {
|
function onSearchQueryRequested(query) {
|
||||||
searchField.text = query;
|
searchField.text = query;
|
||||||
}
|
}
|
||||||
function onModeChanged() {
|
|
||||||
extFilterField.text = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ Rectangle {
|
|||||||
font.family: Theme.fontFamily
|
font.family: Theme.fontFamily
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
clip: true
|
|
||||||
visible: (root.item?.subtitle ?? "").length > 0
|
visible: (root.item?.subtitle ?? "").length > 0
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
}
|
}
|
||||||
@@ -182,7 +181,7 @@ Rectangle {
|
|||||||
case "plugin":
|
case "plugin":
|
||||||
return I18n.tr("Plugin");
|
return I18n.tr("Plugin");
|
||||||
case "file":
|
case "file":
|
||||||
return root.item.data?.is_dir ? I18n.tr("Folder") : I18n.tr("File");
|
return I18n.tr("File");
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -435,15 +435,7 @@ Item {
|
|||||||
var mode = root.controller?.searchMode ?? "all";
|
var mode = root.controller?.searchMode ?? "all";
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "files":
|
case "files":
|
||||||
var fileType = root.controller?.fileSearchType ?? "all";
|
return "folder_open";
|
||||||
switch (fileType) {
|
|
||||||
case "dir":
|
|
||||||
return "folder_open";
|
|
||||||
case "file":
|
|
||||||
return "insert_drive_file";
|
|
||||||
default:
|
|
||||||
return "folder_open";
|
|
||||||
}
|
|
||||||
case "plugins":
|
case "plugins":
|
||||||
return "extension";
|
return "extension";
|
||||||
case "apps":
|
case "apps":
|
||||||
@@ -473,15 +465,7 @@ Item {
|
|||||||
return I18n.tr("Type to search files");
|
return I18n.tr("Type to search files");
|
||||||
if (root.controller.searchQuery.length < 2)
|
if (root.controller.searchQuery.length < 2)
|
||||||
return I18n.tr("Type at least 2 characters");
|
return I18n.tr("Type at least 2 characters");
|
||||||
var fileType = root.controller?.fileSearchType ?? "all";
|
return I18n.tr("No files found");
|
||||||
switch (fileType) {
|
|
||||||
case "dir":
|
|
||||||
return I18n.tr("No folders found");
|
|
||||||
case "file":
|
|
||||||
return I18n.tr("No files found");
|
|
||||||
default:
|
|
||||||
return I18n.tr("No results found");
|
|
||||||
}
|
|
||||||
case "plugins":
|
case "plugins":
|
||||||
return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
|
return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
|
||||||
case "apps":
|
case "apps":
|
||||||
|
|||||||
@@ -1,170 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
import qs.Modals.Common
|
|
||||||
import qs.Modals.FileBrowser
|
|
||||||
import qs.Common
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
DankModal {
|
|
||||||
id: root
|
|
||||||
visible: false
|
|
||||||
layerNamespace: "dms:wifi-qrcode"
|
|
||||||
|
|
||||||
property bool disablePopupTransparency: true
|
|
||||||
property string wifiSSID: ""
|
|
||||||
property string themedQrCodePath: ""
|
|
||||||
property string normalQrCodePath: ""
|
|
||||||
modalWidth: 420
|
|
||||||
modalHeight: 480
|
|
||||||
onBackgroundClicked: hide()
|
|
||||||
onOpened: {
|
|
||||||
Qt.callLater(() => {
|
|
||||||
modalFocusScope.forceActiveFocus();
|
|
||||||
contentLoader.item.wifiSSID = wifiSSID;
|
|
||||||
contentLoader.item.themedQrCodePath = themedQrCodePath;
|
|
||||||
contentLoader.item.saveBrowserLoader = saveBrowserLoader;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function show(ssid) {
|
|
||||||
wifiSSID = ssid;
|
|
||||||
fetchNetworkQRCode(ssid);
|
|
||||||
}
|
|
||||||
|
|
||||||
function hide() {
|
|
||||||
if (themedQrCodePath !== "") {
|
|
||||||
deleteQRCodeFile(themedQrCodePath);
|
|
||||||
}
|
|
||||||
if (normalQrCodePath !== "") {
|
|
||||||
deleteQRCodeFile(normalQrCodePath);
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchNetworkQRCode(ssid) {
|
|
||||||
// TODO: Add loading UI?
|
|
||||||
|
|
||||||
DMSService.sendRequest("network.qrcode", {
|
|
||||||
ssid: ssid
|
|
||||||
}, response => {
|
|
||||||
if (response.error) {
|
|
||||||
ToastService.showError("Failed to fetch network QR code: ", JSON.stringify(response.error));
|
|
||||||
} else if (response.result) {
|
|
||||||
themedQrCodePath = response.result[0];
|
|
||||||
normalQrCodePath = response.result[1];
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteQRCodeFile(path) {
|
|
||||||
DMSService.sendRequest("network.delete-qrcode", {
|
|
||||||
path: path
|
|
||||||
}, response => {
|
|
||||||
if (response.error) {
|
|
||||||
ToastService.showError(`Failed to remove QR code at ${path}: `, JSON.stringify(response.error));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: saveBrowserLoader
|
|
||||||
active: false
|
|
||||||
|
|
||||||
FileBrowserSurfaceModal {
|
|
||||||
id: saveBrowser
|
|
||||||
|
|
||||||
browserTitle: I18n.tr("Save QR Code")
|
|
||||||
browserIcon: "qr_code"
|
|
||||||
browserType: "default"
|
|
||||||
fileExtensions: ["*.png"]
|
|
||||||
allowStacking: true
|
|
||||||
saveMode: true
|
|
||||||
defaultFileName: `${root.wifiSSID ?? "wifi-qrcode"}.png`
|
|
||||||
onFileSelected: path => {
|
|
||||||
const cleanPath = decodeURI(path.toString().replace(/^file:\/\//, ''));
|
|
||||||
const fileName = cleanPath.split('/').pop();
|
|
||||||
const fileUrl = "file://" + cleanPath;
|
|
||||||
|
|
||||||
copyQrCodeProcess.exec(["cp", root.normalQrCodePath, cleanPath, "-f"])
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: copyQrCodeProcess
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
saveBrowser.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
content: Component {
|
|
||||||
Item {
|
|
||||||
id: theItem
|
|
||||||
property alias themedQrCodePath: qrCodeImg.source
|
|
||||||
property var saveBrowserLoader: null
|
|
||||||
property string wifiSSID: ""
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Theme.spacingL
|
|
||||||
spacing: Theme.spacingL
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: modalTitle
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("WiFi QR code for ") + theItem.wifiSSID
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Bold
|
|
||||||
Layout.alignment: Qt.AlignLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
iconName: "save"
|
|
||||||
iconSize: Theme.iconSize - 4
|
|
||||||
iconColor: Theme.surfaceText
|
|
||||||
onClicked: {
|
|
||||||
saveBrowserLoader.active = true;
|
|
||||||
if (saveBrowserLoader.item) {
|
|
||||||
saveBrowserLoader.item.open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
}
|
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
iconName: "close"
|
|
||||||
iconSize: Theme.iconSize - 4
|
|
||||||
iconColor: Theme.surfaceText
|
|
||||||
onClicked: root.hide()
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: qrCodeImg
|
|
||||||
height: parent.height - parent.spacing - modalTitle.height
|
|
||||||
width: height
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
MultiEffect {
|
|
||||||
source: qrCodeImg
|
|
||||||
anchors.fill: source
|
|
||||||
colorization: 1.0
|
|
||||||
colorizationColor: Theme.primary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
layerNamespace: "dms:control-center"
|
layerNamespace: "dms:control-center"
|
||||||
fullHeightSurface: false
|
fullHeightSurface: true
|
||||||
|
|
||||||
property string expandedSection: ""
|
property string expandedSection: ""
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
|
|||||||
@@ -651,7 +651,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: pinButton
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: optionsButton.width + Theme.spacingM + Theme.spacingS
|
anchors.rightMargin: optionsButton.width + Theme.spacingM + Theme.spacingS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@@ -712,19 +711,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
id: qrCodeButton
|
|
||||||
visible: modelData.secured && modelData.saved
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: optionsButton.width + pinWifiRow.width + 3 * Theme.spacingM + Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
iconName: "qr_code"
|
|
||||||
buttonSize: 28
|
|
||||||
onClicked: {
|
|
||||||
PopoutService.showWifiQRCodeModal(modelData.ssid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankRipple {
|
DankRipple {
|
||||||
id: wifiRipple
|
id: wifiRipple
|
||||||
cornerRadius: parent.radius
|
cornerRadius: parent.radius
|
||||||
@@ -733,7 +719,7 @@ Rectangle {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: networkMouseArea
|
id: networkMouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.rightMargin: optionsButton.width + pinWifiRow.width + (qrCodeButton.visible ? qrCodeButton.width : 0) + Theme.spacingS * 5 + Theme.spacingM
|
anchors.rightMargin: optionsButton.width + Theme.spacingM + Theme.spacingS + pinWifiRow.width + Theme.spacingS * 4
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onPressed: mouse => wifiRipple.trigger(mouse.x, mouse.y)
|
onPressed: mouse => wifiRipple.trigger(mouse.x, mouse.y)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import QtQuick.Shapes
|
import QtQuick.Shapes
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -52,43 +53,15 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// M3 elevation shadow — Level 2 baseline (navigation bar), with per-bar override support
|
readonly property real shadowIntensity: barConfig?.shadowIntensity ?? 0
|
||||||
readonly property bool hasPerBarOverride: (barConfig?.shadowIntensity ?? 0) > 0
|
readonly property bool shadowEnabled: shadowIntensity > 0
|
||||||
readonly property var elevLevel: Theme.elevationLevel2
|
readonly property int blurMax: 64
|
||||||
readonly property bool shadowEnabled: (Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || hasPerBarOverride
|
readonly property real shadowBlurPx: shadowIntensity * 0.2
|
||||||
readonly property string autoBarShadowDirection: isTop ? "top" : (isBottom ? "bottom" : (isLeft ? "left" : (isRight ? "right" : "top")))
|
readonly property real shadowBlur: Math.max(0, Math.min(1, shadowBlurPx / blurMax))
|
||||||
readonly property string globalShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
readonly property real shadowOpacity: (barConfig?.shadowOpacity ?? 60) / 100
|
||||||
readonly property string perBarShadowDirectionMode: barConfig?.shadowDirectionMode ?? "inherit"
|
readonly property string shadowColorMode: barConfig?.shadowColorMode ?? "text"
|
||||||
readonly property string perBarManualShadowDirection: {
|
readonly property color shadowBaseColor: {
|
||||||
switch (barConfig?.shadowDirection) {
|
switch (shadowColorMode) {
|
||||||
case "top":
|
|
||||||
case "topLeft":
|
|
||||||
case "topRight":
|
|
||||||
case "bottom":
|
|
||||||
return barConfig.shadowDirection;
|
|
||||||
default:
|
|
||||||
return "top";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly property string effectiveShadowDirection: {
|
|
||||||
if (!hasPerBarOverride)
|
|
||||||
return globalShadowDirection;
|
|
||||||
switch (perBarShadowDirectionMode) {
|
|
||||||
case "autoBar":
|
|
||||||
return autoBarShadowDirection;
|
|
||||||
case "manual":
|
|
||||||
return perBarManualShadowDirection === "autoBar" ? autoBarShadowDirection : perBarManualShadowDirection;
|
|
||||||
default:
|
|
||||||
return globalShadowDirection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per-bar override values (when barConfig.shadowIntensity > 0)
|
|
||||||
readonly property real overrideBlurPx: (barConfig?.shadowIntensity ?? 0) * 0.2
|
|
||||||
readonly property real overrideOpacity: (barConfig?.shadowOpacity ?? 60) / 100
|
|
||||||
readonly property string overrideColorMode: barConfig?.shadowColorMode ?? "default"
|
|
||||||
readonly property color overrideBaseColor: {
|
|
||||||
switch (overrideColorMode) {
|
|
||||||
case "surface":
|
case "surface":
|
||||||
return Theme.surface;
|
return Theme.surface;
|
||||||
case "primary":
|
case "primary":
|
||||||
@@ -98,16 +71,10 @@ Item {
|
|||||||
case "custom":
|
case "custom":
|
||||||
return barConfig?.shadowCustomColor ?? "#000000";
|
return barConfig?.shadowCustomColor ?? "#000000";
|
||||||
default:
|
default:
|
||||||
return "#000000";
|
return Theme.surfaceText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
readonly property color shadowColor: Theme.withAlpha(shadowBaseColor, shadowOpacity * barWindow._backgroundAlpha)
|
||||||
// Resolved values — per-bar override wins if set, otherwise use global M3 elevation
|
|
||||||
readonly property real shadowBlurPx: hasPerBarOverride ? overrideBlurPx : (elevLevel.blurPx ?? 8)
|
|
||||||
readonly property color shadowColor: hasPerBarOverride ? Theme.withAlpha(overrideBaseColor, overrideOpacity) : Theme.elevationShadowColor(elevLevel)
|
|
||||||
readonly property real shadowOffsetMagnitude: hasPerBarOverride ? (overrideBlurPx * 0.5) : Theme.elevationOffsetMagnitude(elevLevel, 4, effectiveShadowDirection)
|
|
||||||
readonly property real shadowOffsetX: Theme.elevationOffsetXFor(hasPerBarOverride ? null : elevLevel, effectiveShadowDirection, shadowOffsetMagnitude)
|
|
||||||
readonly property real shadowOffsetY: Theme.elevationOffsetYFor(hasPerBarOverride ? null : elevLevel, effectiveShadowDirection, shadowOffsetMagnitude)
|
|
||||||
|
|
||||||
readonly property string mainPath: generatePathForPosition(width, height)
|
readonly property string mainPath: generatePathForPosition(width, height)
|
||||||
readonly property string borderFullPath: generateBorderFullPath(width, height)
|
readonly property string borderFullPath: generateBorderFullPath(width, height)
|
||||||
@@ -151,28 +118,42 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Loader {
|
||||||
id: barShadow
|
id: shadowLoader
|
||||||
visible: root.shadowEnabled && root.width > 0 && root.height > 0
|
anchors.fill: parent
|
||||||
|
active: root.shadowEnabled && mainPathCorrectShape
|
||||||
|
asynchronous: false
|
||||||
|
sourceComponent: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
// Size to the bar's rectangular body, excluding gothic wing extensions
|
layer.enabled: true
|
||||||
x: root.isRight ? root.wing : 0
|
layer.smooth: true
|
||||||
y: root.isBottom ? root.wing : 0
|
layer.samples: 8
|
||||||
width: axis.isVertical ? (parent.width - root.wing) : parent.width
|
layer.textureSize: Qt.size(Math.round(width * barWindow._dpr * 2), Math.round(height * barWindow._dpr * 2))
|
||||||
height: axis.isVertical ? parent.height : (parent.height - root.wing)
|
layer.effect: MultiEffect {
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowBlur: root.shadowBlur
|
||||||
|
shadowColor: root.shadowColor
|
||||||
|
shadowVerticalOffset: root.isTop ? root.shadowBlurPx * 0.5 : (root.isBottom ? -root.shadowBlurPx * 0.5 : 0)
|
||||||
|
shadowHorizontalOffset: root.isLeft ? root.shadowBlurPx * 0.5 : (root.isRight ? -root.shadowBlurPx * 0.5 : 0)
|
||||||
|
autoPaddingEnabled: true
|
||||||
|
}
|
||||||
|
|
||||||
shadowEnabled: root.shadowEnabled
|
Shape {
|
||||||
level: root.hasPerBarOverride ? null : root.elevLevel
|
anchors.fill: parent
|
||||||
direction: root.effectiveShadowDirection
|
preferredRendererType: Shape.CurveRenderer
|
||||||
fallbackOffset: 4
|
|
||||||
targetRadius: root.rt
|
|
||||||
targetColor: barWindow._bgColor
|
|
||||||
|
|
||||||
shadowBlurPx: root.shadowBlurPx
|
ShapePath {
|
||||||
shadowOffsetX: root.shadowOffsetX
|
fillColor: barWindow._bgColor
|
||||||
shadowOffsetY: root.shadowOffsetY
|
strokeColor: "transparent"
|
||||||
shadowColor: root.shadowColor
|
strokeWidth: 0
|
||||||
blurMax: Theme.elevationBlurMax
|
|
||||||
|
PathSvg {
|
||||||
|
path: root.mainPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
|||||||
@@ -140,20 +140,6 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
readonly property real _dpr: CompositorService.getScreenScale(barWindow.screen)
|
readonly property real _dpr: CompositorService.getScreenScale(barWindow.screen)
|
||||||
|
|
||||||
// Shadow buffer: extra window space for shadow to render beyond bar bounds
|
|
||||||
readonly property bool _shadowActive: (Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || (barConfig?.shadowIntensity ?? 0) > 0
|
|
||||||
readonly property real _shadowBuffer: {
|
|
||||||
if (!_shadowActive)
|
|
||||||
return 0;
|
|
||||||
const hasOverride = (barConfig?.shadowIntensity ?? 0) > 0;
|
|
||||||
if (hasOverride) {
|
|
||||||
const blur = (barConfig.shadowIntensity ?? 0) * 0.2;
|
|
||||||
const offset = blur * 0.5;
|
|
||||||
return Theme.snap(Math.max(16, blur + offset + 8), _dpr);
|
|
||||||
}
|
|
||||||
return Theme.snap(Theme.elevationRenderPadding(Theme.elevationLevel2, "top", 4, 8, 16), _dpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
property string screenName: modelData.name
|
property string screenName: modelData.name
|
||||||
|
|
||||||
property bool hasMaximizedToplevel: false
|
property bool hasMaximizedToplevel: false
|
||||||
@@ -368,8 +354,8 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
screen: modelData
|
screen: modelData
|
||||||
implicitHeight: !isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) + _shadowBuffer : 0
|
implicitHeight: !isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) : 0
|
||||||
implicitWidth: isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) + _shadowBuffer : 0
|
implicitWidth: isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) : 0
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
property var nativeInhibitor: null
|
property var nativeInhibitor: null
|
||||||
@@ -638,7 +624,7 @@ PanelWindow {
|
|||||||
Item {
|
Item {
|
||||||
id: topBarCore
|
id: topBarCore
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
layer.enabled: false
|
layer.enabled: true
|
||||||
|
|
||||||
property bool autoHide: barConfig?.autoHide ?? false
|
property bool autoHide: barConfig?.autoHide ?? false
|
||||||
property bool revealSticky: false
|
property bool revealSticky: false
|
||||||
|
|||||||
@@ -167,22 +167,9 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: headerInfoColumn
|
|
||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: parent.width - Theme.iconSizeLarge - 32 - Theme.spacingM * 2
|
width: parent.width - Theme.iconSizeLarge - 32 - Theme.spacingM * 2
|
||||||
readonly property string timeInfoText: {
|
|
||||||
if (!BatteryService.batteryAvailable)
|
|
||||||
return "Power profile management available";
|
|
||||||
const time = BatteryService.formatTimeRemaining();
|
|
||||||
if (time !== "Unknown") {
|
|
||||||
return BatteryService.isCharging ? `Time until full: ${time}` : `Time remaining: ${time}`;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
readonly property bool showPowerRate: BatteryService.batteryAvailable && Math.abs(BatteryService.changeRate) > 0.05
|
|
||||||
readonly property bool isOnAC: BatteryService.batteryAvailable && (BatteryService.isCharging || BatteryService.isPluggedIn)
|
|
||||||
readonly property bool isDischarging: BatteryService.batteryAvailable && !BatteryService.isCharging && !BatteryService.isPluggedIn
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
@@ -220,35 +207,21 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
StyledText {
|
||||||
width: parent.width
|
text: {
|
||||||
spacing: Theme.spacingS
|
if (!BatteryService.batteryAvailable)
|
||||||
visible: headerInfoColumn.timeInfoText.length > 0
|
return "Power profile management available";
|
||||||
|
const time = BatteryService.formatTimeRemaining();
|
||||||
StyledText {
|
if (time !== "Unknown") {
|
||||||
id: powerRateText
|
return BatteryService.isCharging ? `Time until full: ${time}` : `Time remaining: ${time}`;
|
||||||
text: `${headerInfoColumn.isOnAC ? "+" : (headerInfoColumn.isDischarging ? "-" : "")}${Math.abs(BatteryService.changeRate).toFixed(1)}W`
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: {
|
|
||||||
if (headerInfoColumn.isOnAC) {
|
|
||||||
return Theme.primary;
|
|
||||||
}
|
|
||||||
if (headerInfoColumn.isDischarging) {
|
|
||||||
return Theme.warning;
|
|
||||||
}
|
|
||||||
return Theme.surfaceTextMedium;
|
|
||||||
}
|
}
|
||||||
font.weight: Font.Medium
|
return "";
|
||||||
visible: headerInfoColumn.showPowerRate
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: headerInfoColumn.timeInfoText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceTextMedium
|
|
||||||
elide: Text.ElideRight
|
|
||||||
width: parent.width - (powerRateText.visible ? (powerRateText.implicitWidth + parent.spacing) : 0)
|
|
||||||
}
|
}
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
visible: text.length > 0
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: parent.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,21 +29,12 @@ Loader {
|
|||||||
|
|
||||||
readonly property bool orientationMatches: (axis?.isVertical ?? false) === isInColumn
|
readonly property bool orientationMatches: (axis?.isVertical ?? false) === isInColumn
|
||||||
|
|
||||||
readonly property bool widgetEnabled: widgetData?.enabled !== false
|
|
||||||
|
|
||||||
active: orientationMatches && getWidgetVisible(widgetId, DgopService.dgopAvailable) && (widgetId !== "music" || MprisController.activePlayer !== null)
|
active: orientationMatches && getWidgetVisible(widgetId, DgopService.dgopAvailable) && (widgetId !== "music" || MprisController.activePlayer !== null)
|
||||||
sourceComponent: getWidgetComponent(widgetId, components)
|
sourceComponent: getWidgetComponent(widgetId, components)
|
||||||
|
opacity: getWidgetEnabled(widgetData?.enabled) ? 1 : 0
|
||||||
|
|
||||||
signal contentItemReady(var item)
|
signal contentItemReady(var item)
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: root.item
|
|
||||||
when: root.item && !root.widgetEnabled
|
|
||||||
property: "visible"
|
|
||||||
value: false
|
|
||||||
restoreMode: Binding.RestoreBinding
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
Binding {
|
||||||
target: root.item
|
target: root.item
|
||||||
when: root.item && "parentScreen" in root.item
|
when: root.item && "parentScreen" in root.item
|
||||||
@@ -278,4 +269,8 @@ Loader {
|
|||||||
|
|
||||||
return widgetVisibility[widgetId] ?? true;
|
return widgetVisibility[widgetId] ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWidgetEnabled(enabled) {
|
||||||
|
return enabled !== false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ BasePill {
|
|||||||
|
|
||||||
property var widgetData: null
|
property var widgetData: null
|
||||||
property string mountPath: (widgetData && widgetData.mountPath !== undefined) ? widgetData.mountPath : "/"
|
property string mountPath: (widgetData && widgetData.mountPath !== undefined) ? widgetData.mountPath : "/"
|
||||||
property int diskUsageMode: (widgetData && widgetData.diskUsageMode !== undefined) ? widgetData.diskUsageMode : 0
|
|
||||||
property bool isHovered: mouseArea.containsMouse
|
property bool isHovered: mouseArea.containsMouse
|
||||||
property bool isAutoHideBar: false
|
property bool isAutoHideBar: false
|
||||||
|
|
||||||
@@ -131,13 +130,7 @@ BasePill {
|
|||||||
if (root.diskUsagePercent === undefined || root.diskUsagePercent === null || root.diskUsagePercent === 0) {
|
if (root.diskUsagePercent === undefined || root.diskUsagePercent === null || root.diskUsagePercent === 0) {
|
||||||
return "--";
|
return "--";
|
||||||
}
|
}
|
||||||
if (!root.selectedMount) return "--";
|
return root.diskUsagePercent.toFixed(0);
|
||||||
switch (root.diskUsageMode) {
|
|
||||||
case 1: return root.selectedMount.size || "--";
|
|
||||||
case 2: return root.selectedMount.avail || "--";
|
|
||||||
case 3: return (root.selectedMount.avail || "--") + " / " + (root.selectedMount.size || "--");
|
|
||||||
default: return root.diskUsagePercent.toFixed(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
||||||
color: Theme.widgetTextColor
|
color: Theme.widgetTextColor
|
||||||
@@ -185,13 +178,7 @@ BasePill {
|
|||||||
if (root.diskUsagePercent === undefined || root.diskUsagePercent === null || root.diskUsagePercent === 0) {
|
if (root.diskUsagePercent === undefined || root.diskUsagePercent === null || root.diskUsagePercent === 0) {
|
||||||
return "--%";
|
return "--%";
|
||||||
}
|
}
|
||||||
if (!root.selectedMount) return "--%";
|
return root.diskUsagePercent.toFixed(0) + "%";
|
||||||
switch (root.diskUsageMode) {
|
|
||||||
case 1: return root.selectedMount.size || "--";
|
|
||||||
case 2: return root.selectedMount.avail || "--";
|
|
||||||
case 3: return (root.selectedMount.avail || "--") + " / " + (root.selectedMount.size || "--");
|
|
||||||
default: return root.diskUsagePercent.toFixed(0) + "%";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
||||||
color: Theme.widgetTextColor
|
color: Theme.widgetTextColor
|
||||||
@@ -202,14 +189,7 @@ BasePill {
|
|||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: diskBaseline
|
id: diskBaseline
|
||||||
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
||||||
text: {
|
text: "100%"
|
||||||
switch (root.diskUsageMode) {
|
|
||||||
case 3: return "888.8G / 888.8G";
|
|
||||||
case 1:
|
|
||||||
case 2: return "888.8G";
|
|
||||||
default: return "100%";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.max(diskBaseline.width, paintedWidth)
|
width: Math.max(diskBaseline.width, paintedWidth)
|
||||||
|
|||||||
@@ -178,9 +178,8 @@ BasePill {
|
|||||||
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
||||||
const globalPos = parent.mapToItem(null, 0, 0);
|
const globalPos = parent.mapToItem(null, 0, 0);
|
||||||
const currentScreen = root.parentScreen || Screen;
|
const currentScreen = root.parentScreen || Screen;
|
||||||
const barPosition = root.axis?.edge === "left" ? 2 : (root.axis?.edge === "right" ? 3 : (root.axis?.edge === "top" ? 0 : 1));
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, parent.width);
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, parent.width, root.barSpacing, barPosition, root.barConfig);
|
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen);
|
||||||
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen, barPosition, root.barThickness, root.barSpacing, root.barConfig);
|
|
||||||
}
|
}
|
||||||
root.clicked();
|
root.clicked();
|
||||||
}
|
}
|
||||||
@@ -335,9 +334,8 @@ BasePill {
|
|||||||
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
||||||
const globalPos = mapToItem(null, 0, 0);
|
const globalPos = mapToItem(null, 0, 0);
|
||||||
const currentScreen = root.parentScreen || Screen;
|
const currentScreen = root.parentScreen || Screen;
|
||||||
const barPosition = root.axis?.edge === "left" ? 2 : (root.axis?.edge === "right" ? 3 : (root.axis?.edge === "top" ? 0 : 1));
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, root.width);
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, root.width, root.barSpacing, barPosition, root.barConfig);
|
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen);
|
||||||
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen, barPosition, root.barThickness, root.barSpacing, root.barConfig);
|
|
||||||
}
|
}
|
||||||
root.clicked();
|
root.clicked();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ BasePill {
|
|||||||
property var widgetData: null
|
property var widgetData: null
|
||||||
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
property bool minimumWidth: (widgetData && widgetData.minimumWidth !== undefined) ? widgetData.minimumWidth : true
|
||||||
property bool showSwap: (widgetData && widgetData.showSwap !== undefined) ? widgetData.showSwap : false
|
property bool showSwap: (widgetData && widgetData.showSwap !== undefined) ? widgetData.showSwap : false
|
||||||
property bool showInGb: (widgetData && widgetData.showInGb !== undefined) ? widgetData.showInGb : false
|
|
||||||
readonly property real swapUsage: DgopService.totalSwapKB > 0 ? (DgopService.usedSwapKB / DgopService.totalSwapKB) * 100 : 0
|
readonly property real swapUsage: DgopService.totalSwapKB > 0 ? (DgopService.usedSwapKB / DgopService.totalSwapKB) * 100 : 0
|
||||||
|
|
||||||
signal ramClicked
|
signal ramClicked
|
||||||
@@ -60,10 +59,6 @@ BasePill {
|
|||||||
return "--";
|
return "--";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.showInGb) {
|
|
||||||
return (DgopService.usedMemoryMB / 1024).toFixed(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DgopService.memoryUsage.toFixed(0);
|
return DgopService.memoryUsage.toFixed(0);
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
||||||
@@ -118,14 +113,13 @@ BasePill {
|
|||||||
id: ramBaseline
|
id: ramBaseline
|
||||||
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
||||||
text: {
|
text: {
|
||||||
let baseText = root.showInGb ? "88.8 GB" : "88%";
|
|
||||||
if (!root.showSwap) {
|
if (!root.showSwap) {
|
||||||
return baseText;
|
return "88%";
|
||||||
}
|
}
|
||||||
if (root.swapUsage < 10) {
|
if (root.swapUsage < 10) {
|
||||||
return baseText + " · 0%";
|
return "88% · 0%";
|
||||||
}
|
}
|
||||||
return baseText + " · 88%";
|
return "88% · 88%";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,16 +127,10 @@ BasePill {
|
|||||||
id: ramText
|
id: ramText
|
||||||
text: {
|
text: {
|
||||||
if (DgopService.memoryUsage === undefined || DgopService.memoryUsage === null || DgopService.memoryUsage === 0) {
|
if (DgopService.memoryUsage === undefined || DgopService.memoryUsage === null || DgopService.memoryUsage === 0) {
|
||||||
return root.showInGb ? "-- GB" : "--%";
|
return "--%";
|
||||||
}
|
|
||||||
|
|
||||||
let ramText = "";
|
|
||||||
if (root.showInGb) {
|
|
||||||
ramText = (DgopService.usedMemoryMB / 1024).toFixed(1) + " GB";
|
|
||||||
} else {
|
|
||||||
ramText = DgopService.memoryUsage.toFixed(0) + "%";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ramText = DgopService.memoryUsage.toFixed(0) + "%";
|
||||||
if (root.showSwap && DgopService.totalSwapKB > 0) {
|
if (root.showSwap && DgopService.totalSwapKB > 0) {
|
||||||
return ramText + " · " + root.swapUsage.toFixed(0) + "%";
|
return ramText + " · " + root.swapUsage.toFixed(0) + "%";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,6 @@ BasePill {
|
|||||||
return `${id}::${tooltipTitle}`;
|
return `${id}::${tooltipTitle}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! TODO - replace with either native dbus client (like plugins use) or just a DMS cli or something
|
|
||||||
function callContextMenuFallback(trayItemId, globalX, globalY) {
|
|
||||||
const script = ['ITEMS=$(dbus-send --session --print-reply --dest=org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.freedesktop.DBus.Properties.Get string:org.kde.StatusNotifierWatcher string:RegisteredStatusNotifierItems 2>/dev/null)', 'while IFS= read -r line; do', ' line="${line#*\\\"}"', ' line="${line%\\\"*}"', ' [ -z "$line" ] && continue', ' BUS="${line%%/*}"', ' OBJ="/${line#*/}"', ' ID=$(dbus-send --session --print-reply --dest="$BUS" "$OBJ" org.freedesktop.DBus.Properties.Get string:org.kde.StatusNotifierItem string:Id 2>/dev/null | grep -oP "(?<=\\\")(.*?)(?=\\\")" | tail -1)', ' if [ "$ID" = "$1" ]; then', ' dbus-send --session --type=method_call --dest="$BUS" "$OBJ" org.kde.StatusNotifierItem.ContextMenu int32:"$2" int32:"$3"', ' exit 0', ' fi', 'done <<< "$ITEMS"',].join("\n");
|
|
||||||
Quickshell.execDetached(["bash", "-c", script, "_", trayItemId, String(globalX), String(globalY)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
property int _trayOrderTrigger: 0
|
property int _trayOrderTrigger: 0
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -386,11 +380,8 @@ BasePill {
|
|||||||
return;
|
return;
|
||||||
if (mouse.button !== Qt.RightButton)
|
if (mouse.button !== Qt.RightButton)
|
||||||
return;
|
return;
|
||||||
if (!delegateRoot.trayItem?.hasMenu) {
|
if (!delegateRoot.trayItem?.hasMenu)
|
||||||
const gp = trayItemArea.mapToGlobal(mouse.x, mouse.y);
|
|
||||||
root.callContextMenuFallback(delegateRoot.trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
root.menuOpen = false;
|
root.menuOpen = false;
|
||||||
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
}
|
}
|
||||||
@@ -646,11 +637,8 @@ BasePill {
|
|||||||
return;
|
return;
|
||||||
if (mouse.button !== Qt.RightButton)
|
if (mouse.button !== Qt.RightButton)
|
||||||
return;
|
return;
|
||||||
if (!delegateRoot.trayItem?.hasMenu) {
|
if (!delegateRoot.trayItem?.hasMenu)
|
||||||
const gp = trayItemArea.mapToGlobal(mouse.x, mouse.y);
|
|
||||||
root.callContextMenuFallback(delegateRoot.trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
root.menuOpen = false;
|
root.menuOpen = false;
|
||||||
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
root.showForTrayItem(delegateRoot.trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
}
|
}
|
||||||
@@ -940,10 +928,9 @@ BasePill {
|
|||||||
}
|
}
|
||||||
})(), overflowMenu.dpr)
|
})(), overflowMenu.dpr)
|
||||||
|
|
||||||
readonly property var elev: Theme.elevationLevel2
|
property real shadowBlurPx: 10
|
||||||
property real shadowBlurPx: elev && elev.blurPx !== undefined ? elev.blurPx : 8
|
property real shadowSpreadPx: 0
|
||||||
property real shadowSpreadPx: elev && elev.spreadPx !== undefined ? elev.spreadPx : 0
|
property real shadowBaseAlpha: 0.60
|
||||||
property real shadowBaseAlpha: elev && elev.alpha !== undefined ? elev.alpha : 0.25
|
|
||||||
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
||||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||||
|
|
||||||
@@ -964,26 +951,37 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Item {
|
||||||
id: bgShadowLayer
|
id: bgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
level: menuContainer.elev
|
layer.enabled: true
|
||||||
fallbackOffset: 4
|
|
||||||
shadowBlurPx: menuContainer.shadowBlurPx
|
|
||||||
shadowSpreadPx: menuContainer.shadowSpreadPx
|
|
||||||
shadowColor: {
|
|
||||||
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
|
||||||
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
|
||||||
}
|
|
||||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
|
||||||
targetRadius: Theme.cornerRadius
|
|
||||||
sourceRect.antialiasing: true
|
|
||||||
sourceRect.smooth: true
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
layer.smooth: true
|
layer.smooth: true
|
||||||
layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
|
layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
layer.samples: 4
|
layer.samples: 4
|
||||||
|
|
||||||
|
readonly property int blurMax: 64
|
||||||
|
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
autoPaddingEnabled: true
|
||||||
|
shadowEnabled: true
|
||||||
|
blurEnabled: false
|
||||||
|
maskEnabled: false
|
||||||
|
shadowBlur: Math.max(0, Math.min(1, menuContainer.shadowBlurPx / bgShadowLayer.blurMax))
|
||||||
|
shadowScale: 1 + (2 * menuContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
antialiasing: true
|
||||||
|
smooth: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
@@ -1067,11 +1065,9 @@ BasePill {
|
|||||||
root.menuOpen = false;
|
root.menuOpen = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!trayItem.hasMenu) {
|
|
||||||
const gp = itemArea.mapToGlobal(mouse.x, mouse.y);
|
if (!trayItem.hasMenu)
|
||||||
root.callContextMenuFallback(trayItem.id, Math.round(gp.x), Math.round(gp.y));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
root.showForTrayItem(trayItem, menuContainer, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
root.showForTrayItem(trayItem, menuContainer, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1402,10 +1398,9 @@ BasePill {
|
|||||||
}
|
}
|
||||||
})(), menuWindow.dpr)
|
})(), menuWindow.dpr)
|
||||||
|
|
||||||
readonly property var elev: Theme.elevationLevel2
|
property real shadowBlurPx: 10
|
||||||
property real shadowBlurPx: elev && elev.blurPx !== undefined ? elev.blurPx : 8
|
property real shadowSpreadPx: 0
|
||||||
property real shadowSpreadPx: elev && elev.spreadPx !== undefined ? elev.spreadPx : 0
|
property real shadowBaseAlpha: 0.60
|
||||||
property real shadowBaseAlpha: elev && elev.alpha !== undefined ? elev.alpha : 0.25
|
|
||||||
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
||||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||||
|
|
||||||
@@ -1426,24 +1421,35 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Item {
|
||||||
id: menuBgShadowLayer
|
id: menuBgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
level: menuContainer.elev
|
layer.enabled: true
|
||||||
fallbackOffset: 4
|
|
||||||
shadowBlurPx: menuContainer.shadowBlurPx
|
|
||||||
shadowSpreadPx: menuContainer.shadowSpreadPx
|
|
||||||
shadowColor: {
|
|
||||||
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
|
||||||
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
|
||||||
}
|
|
||||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
|
||||||
targetRadius: Theme.cornerRadius
|
|
||||||
sourceRect.antialiasing: true
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
layer.smooth: true
|
layer.smooth: true
|
||||||
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
|
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
|
|
||||||
|
readonly property int blurMax: 64
|
||||||
|
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
autoPaddingEnabled: true
|
||||||
|
shadowEnabled: true
|
||||||
|
blurEnabled: false
|
||||||
|
maskEnabled: false
|
||||||
|
shadowBlur: Math.max(0, Math.min(1, menuContainer.shadowBlurPx / menuBgShadowLayer.blurMax))
|
||||||
|
shadowScale: 1 + (2 * menuContainer.shadowSpreadPx) / Math.max(1, Math.min(menuBgShadowLayer.width, menuBgShadowLayer.height))
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
antialiasing: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QsMenuAnchor {
|
QsMenuAnchor {
|
||||||
|
|||||||
@@ -177,9 +177,8 @@ BasePill {
|
|||||||
if (popoutTarget && popoutTarget.setTriggerPosition) {
|
if (popoutTarget && popoutTarget.setTriggerPosition) {
|
||||||
const globalPos = root.visualContent.mapToItem(null, 0, 0);
|
const globalPos = root.visualContent.mapToItem(null, 0, 0);
|
||||||
const currentScreen = parentScreen || Screen;
|
const currentScreen = parentScreen || Screen;
|
||||||
const barPosition = root.axis?.edge === "left" ? 2 : (root.axis?.edge === "right" ? 3 : (root.axis?.edge === "top" ? 0 : 1));
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, root.visualWidth);
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, root.visualWidth, root.barSpacing, barPosition, root.barConfig);
|
popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen);
|
||||||
popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen, barPosition, barThickness, root.barSpacing, root.barConfig);
|
|
||||||
}
|
}
|
||||||
root.clicked();
|
root.clicked();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,18 +89,14 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
id: volumeShadowLayer
|
layer.effect: MultiEffect {
|
||||||
anchors.fill: parent
|
shadowEnabled: true
|
||||||
z: -1
|
shadowHorizontalOffset: 0
|
||||||
level: Theme.elevationLevel2
|
shadowVerticalOffset: 8
|
||||||
fallbackOffset: 4
|
shadowBlur: 1.0
|
||||||
targetRadius: volumePanel.radius
|
shadowColor: Qt.rgba(0, 0, 0, 0.4)
|
||||||
targetColor: volumePanel.color
|
shadowOpacity: 0.7
|
||||||
borderColor: volumePanel.border.color
|
|
||||||
borderWidth: volumePanel.border.width
|
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -227,18 +223,14 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
id: audioDevicesShadowLayer
|
layer.effect: MultiEffect {
|
||||||
anchors.fill: parent
|
shadowEnabled: true
|
||||||
z: -1
|
shadowHorizontalOffset: 0
|
||||||
level: Theme.elevationLevel2
|
shadowVerticalOffset: 8
|
||||||
fallbackOffset: 4
|
shadowBlur: 1.0
|
||||||
targetRadius: audioDevicesPanel.radius
|
shadowColor: Qt.rgba(0, 0, 0, 0.4)
|
||||||
targetColor: audioDevicesPanel.color
|
shadowOpacity: 0.7
|
||||||
borderColor: audioDevicesPanel.border.color
|
|
||||||
borderWidth: audioDevicesPanel.border.width
|
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -381,18 +373,14 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
id: playersShadowLayer
|
layer.effect: MultiEffect {
|
||||||
anchors.fill: parent
|
shadowEnabled: true
|
||||||
z: -1
|
shadowHorizontalOffset: 0
|
||||||
level: Theme.elevationLevel2
|
shadowVerticalOffset: 8
|
||||||
fallbackOffset: 4
|
shadowBlur: 1.0
|
||||||
targetRadius: playersPanel.radius
|
shadowColor: Qt.rgba(0, 0, 0, 0.4)
|
||||||
targetColor: playersPanel.color
|
shadowOpacity: 0.7
|
||||||
borderColor: playersPanel.border.color
|
|
||||||
borderWidth: playersPanel.border.width
|
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|||||||
@@ -529,15 +529,14 @@ Item {
|
|||||||
onClicked: activePlayer && activePlayer.togglePlaying()
|
onClicked: activePlayer && activePlayer.togglePlaying()
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
anchors.fill: parent
|
layer.effect: MultiEffect {
|
||||||
z: -1
|
shadowEnabled: true
|
||||||
level: Theme.elevationLevel1
|
shadowHorizontalOffset: 0
|
||||||
fallbackOffset: 1
|
shadowVerticalOffset: 0
|
||||||
targetRadius: parent.radius
|
shadowBlur: 1.0
|
||||||
targetColor: parent.color
|
shadowColor: Qt.rgba(0, 0, 0, 0.3)
|
||||||
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
shadowOpacity: 0.3
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,15 +241,14 @@ Item {
|
|||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
layer.enabled: Theme.elevationEnabled
|
layer.enabled: true
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: Theme.elevationEnabled
|
shadowEnabled: true
|
||||||
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel1)
|
shadowHorizontalOffset: 0
|
||||||
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel1, 1)
|
shadowVerticalOffset: 4
|
||||||
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined ? Theme.elevationLevel1.blurPx : 4) / Theme.elevationBlurMax)) : 0
|
shadowBlur: 0.8
|
||||||
blurMax: Theme.elevationBlurMax
|
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
||||||
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel1)
|
shadowOpacity: 0.2
|
||||||
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,14 +812,14 @@ Item {
|
|||||||
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
|
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
|
||||||
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
|
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
|
||||||
|
|
||||||
layer.enabled: Theme.elevationEnabled
|
layer.enabled: true
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: Theme.elevationEnabled
|
shadowEnabled: true
|
||||||
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel2)
|
shadowHorizontalOffset: 0
|
||||||
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel2, 4)
|
shadowVerticalOffset: 4
|
||||||
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel2 && Theme.elevationLevel2.blurPx !== undefined ? Theme.elevationLevel2.blurPx : 8) / Theme.elevationBlurMax)) : 0
|
shadowBlur: 0.8
|
||||||
blurMax: Theme.elevationBlurMax
|
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
||||||
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel2)
|
shadowOpacity: 0.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,14 +834,14 @@ Item {
|
|||||||
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
|
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
|
||||||
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
|
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
|
||||||
|
|
||||||
layer.enabled: Theme.elevationEnabled
|
layer.enabled: true
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: Theme.elevationEnabled
|
shadowEnabled: true
|
||||||
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel2)
|
shadowHorizontalOffset: 0
|
||||||
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel2, 4)
|
shadowVerticalOffset: 4
|
||||||
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel2 && Theme.elevationLevel2.blurPx !== undefined ? Theme.elevationLevel2.blurPx : 8) / Theme.elevationBlurMax)) : 0
|
shadowBlur: 0.8
|
||||||
blurMax: Theme.elevationBlurMax
|
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
||||||
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel2)
|
shadowOpacity: 0.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,11 +41,6 @@ Singleton {
|
|||||||
property string lockDateFormat: ""
|
property string lockDateFormat: ""
|
||||||
property bool lockScreenShowPowerActions: true
|
property bool lockScreenShowPowerActions: true
|
||||||
property bool lockScreenShowProfileImage: true
|
property bool lockScreenShowProfileImage: true
|
||||||
property bool powerActionConfirm: true
|
|
||||||
property real powerActionHoldDuration: 0.5
|
|
||||||
property var powerMenuActions: ["reboot", "logout", "poweroff", "lock", "suspend", "restart"]
|
|
||||||
property string powerMenuDefaultAction: "logout"
|
|
||||||
property bool powerMenuGridLayout: false
|
|
||||||
property var screenPreferences: ({})
|
property var screenPreferences: ({})
|
||||||
property int animationSpeed: 2
|
property int animationSpeed: 2
|
||||||
property string wallpaperFillMode: "Fill"
|
property string wallpaperFillMode: "Fill"
|
||||||
@@ -80,11 +75,6 @@ Singleton {
|
|||||||
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : "";
|
lockDateFormat = settings.lockDateFormat !== undefined ? settings.lockDateFormat : "";
|
||||||
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true;
|
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true;
|
||||||
lockScreenShowProfileImage = settings.lockScreenShowProfileImage !== undefined ? settings.lockScreenShowProfileImage : true;
|
lockScreenShowProfileImage = settings.lockScreenShowProfileImage !== undefined ? settings.lockScreenShowProfileImage : true;
|
||||||
powerActionConfirm = settings.powerActionConfirm !== undefined ? settings.powerActionConfirm : true;
|
|
||||||
powerActionHoldDuration = settings.powerActionHoldDuration !== undefined ? settings.powerActionHoldDuration : 0.5;
|
|
||||||
powerMenuActions = settings.powerMenuActions !== undefined ? settings.powerMenuActions : ["reboot", "logout", "poweroff", "lock", "suspend", "restart"];
|
|
||||||
powerMenuDefaultAction = settings.powerMenuDefaultAction !== undefined ? settings.powerMenuDefaultAction : "logout";
|
|
||||||
powerMenuGridLayout = settings.powerMenuGridLayout !== undefined ? settings.powerMenuGridLayout : false;
|
|
||||||
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({});
|
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({});
|
||||||
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : 2;
|
animationSpeed = settings.animationSpeed !== undefined ? settings.animationSpeed : 2;
|
||||||
wallpaperFillMode = settings.wallpaperFillMode !== undefined ? settings.wallpaperFillMode : "Fill";
|
wallpaperFillMode = settings.wallpaperFillMode !== undefined ? settings.wallpaperFillMode : "Fill";
|
||||||
|
|||||||
@@ -1231,12 +1231,6 @@ Item {
|
|||||||
LockPowerMenu {
|
LockPowerMenu {
|
||||||
id: powerMenu
|
id: powerMenu
|
||||||
showLogout: false
|
showLogout: false
|
||||||
powerActionConfirmOverride: GreetdSettings.powerActionConfirm
|
|
||||||
powerActionHoldDurationOverride: GreetdSettings.powerActionHoldDuration
|
|
||||||
powerMenuActionsOverride: GreetdSettings.powerMenuActions
|
|
||||||
powerMenuDefaultActionOverride: GreetdSettings.powerMenuDefaultAction
|
|
||||||
powerMenuGridLayoutOverride: GreetdSettings.powerMenuGridLayout
|
|
||||||
requiredActions: ["poweroff"]
|
|
||||||
onClosed: {
|
onClosed: {
|
||||||
if (isPrimaryScreen && inputField && inputField.forceActiveFocus) {
|
if (isPrimaryScreen && inputField && inputField.forceActiveFocus) {
|
||||||
Qt.callLater(() => inputField.forceActiveFocus());
|
Qt.callLater(() => inputField.forceActiveFocus());
|
||||||
|
|||||||
@@ -24,20 +24,13 @@ Rectangle {
|
|||||||
property real holdProgress: 0
|
property real holdProgress: 0
|
||||||
property bool showHoldHint: false
|
property bool showHoldHint: false
|
||||||
|
|
||||||
property var powerActionConfirmOverride: undefined
|
readonly property bool needsConfirmation: SettingsData.powerActionConfirm
|
||||||
property var powerActionHoldDurationOverride: undefined
|
readonly property int holdDurationMs: SettingsData.powerActionHoldDuration * 1000
|
||||||
property var powerMenuActionsOverride: undefined
|
|
||||||
property var powerMenuDefaultActionOverride: undefined
|
|
||||||
property var powerMenuGridLayoutOverride: undefined
|
|
||||||
property var requiredActions: []
|
|
||||||
|
|
||||||
readonly property bool needsConfirmation: powerActionConfirmOverride !== undefined ? powerActionConfirmOverride : SettingsData.powerActionConfirm
|
|
||||||
readonly property int holdDurationMs: (powerActionHoldDurationOverride !== undefined ? powerActionHoldDurationOverride : SettingsData.powerActionHoldDuration) * 1000
|
|
||||||
|
|
||||||
signal closed
|
signal closed
|
||||||
|
|
||||||
function updateVisibleActions() {
|
function updateVisibleActions() {
|
||||||
const allActions = powerMenuActionsOverride !== undefined ? powerMenuActionsOverride : ((typeof SettingsData !== "undefined" && SettingsData.powerMenuActions) ? SettingsData.powerMenuActions : ["logout", "suspend", "hibernate", "reboot", "poweroff"]);
|
const allActions = (typeof SettingsData !== "undefined" && SettingsData.powerMenuActions) ? SettingsData.powerMenuActions : ["logout", "suspend", "hibernate", "reboot", "poweroff"];
|
||||||
const hibernateSupported = (typeof SessionService !== "undefined" && SessionService.hibernateSupported) || false;
|
const hibernateSupported = (typeof SessionService !== "undefined" && SessionService.hibernateSupported) || false;
|
||||||
let filtered = allActions.filter(action => {
|
let filtered = allActions.filter(action => {
|
||||||
if (action === "hibernate" && !hibernateSupported)
|
if (action === "hibernate" && !hibernateSupported)
|
||||||
@@ -51,14 +44,9 @@ Rectangle {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const action of requiredActions) {
|
|
||||||
if (!filtered.includes(action))
|
|
||||||
filtered.push(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
visibleActions = filtered;
|
visibleActions = filtered;
|
||||||
|
|
||||||
useGridLayout = powerMenuGridLayoutOverride !== undefined ? powerMenuGridLayoutOverride : ((typeof SettingsData !== "undefined" && SettingsData.powerMenuGridLayout !== undefined) ? SettingsData.powerMenuGridLayout : false);
|
useGridLayout = (typeof SettingsData !== "undefined" && SettingsData.powerMenuGridLayout !== undefined) ? SettingsData.powerMenuGridLayout : false;
|
||||||
if (!useGridLayout)
|
if (!useGridLayout)
|
||||||
return;
|
return;
|
||||||
const count = visibleActions.length;
|
const count = visibleActions.length;
|
||||||
@@ -85,7 +73,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultActionIndex() {
|
function getDefaultActionIndex() {
|
||||||
const defaultAction = powerMenuDefaultActionOverride !== undefined ? powerMenuDefaultActionOverride : ((typeof SettingsData !== "undefined" && SettingsData.powerMenuDefaultAction) ? SettingsData.powerMenuDefaultAction : "suspend");
|
const defaultAction = (typeof SettingsData !== "undefined" && SettingsData.powerMenuDefaultAction) ? SettingsData.powerMenuDefaultAction : "suspend";
|
||||||
const index = visibleActions.indexOf(defaultAction);
|
const index = visibleActions.indexOf(defaultAction);
|
||||||
return index >= 0 ? index : 0;
|
return index >= 0 ? index : 0;
|
||||||
}
|
}
|
||||||
@@ -792,9 +780,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
readonly property real totalMs: root.holdDurationMs
|
readonly property real totalMs: SettingsData.powerActionHoldDuration * 1000
|
||||||
readonly property int remainingMs: Math.ceil(totalMs * (1 - root.holdProgress))
|
readonly property int remainingMs: Math.ceil(totalMs * (1 - root.holdProgress))
|
||||||
readonly property real durationSec: root.holdDurationMs / 1000
|
|
||||||
text: {
|
text: {
|
||||||
if (root.showHoldHint)
|
if (root.showHoldHint)
|
||||||
return I18n.tr("Hold longer to confirm");
|
return I18n.tr("Hold longer to confirm");
|
||||||
@@ -805,7 +792,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
if (totalMs < 1000)
|
if (totalMs < 1000)
|
||||||
return I18n.tr("Hold to confirm (%1 ms)").arg(totalMs);
|
return I18n.tr("Hold to confirm (%1 ms)").arg(totalMs);
|
||||||
return I18n.tr("Hold to confirm (%1s)").arg(durationSec);
|
return I18n.tr("Hold to confirm (%1s)").arg(SettingsData.powerActionHoldDuration);
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: root.showHoldHint ? Theme.warning : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
color: root.showHoldHint ? Theme.warning : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -31,21 +30,7 @@ Rectangle {
|
|||||||
width: parent ? parent.width : 400
|
width: parent ? parent.width : 400
|
||||||
height: baseCardHeight + contentItem.extraHeight
|
height: baseCardHeight + contentItem.extraHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
clip: false
|
clip: true
|
||||||
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
|
||||||
|
|
||||||
ElevationShadow {
|
|
||||||
id: shadowLayer
|
|
||||||
anchors.fill: parent
|
|
||||||
z: -1
|
|
||||||
level: Theme.elevationLevel1
|
|
||||||
fallbackOffset: 1
|
|
||||||
targetRadius: root.radius
|
|
||||||
targetColor: root.color
|
|
||||||
borderColor: root.border.color
|
|
||||||
borderWidth: root.border.width
|
|
||||||
shadowEnabled: root.shadowsAllowed
|
|
||||||
}
|
|
||||||
|
|
||||||
color: {
|
color: {
|
||||||
if (isSelected && keyboardNavigationActive)
|
if (isSelected && keyboardNavigationActive)
|
||||||
@@ -64,7 +49,7 @@ Rectangle {
|
|||||||
return 1.5;
|
return 1.5;
|
||||||
if (historyItem.urgency === 2)
|
if (historyItem.urgency === 2)
|
||||||
return 2;
|
return 2;
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on border.color {
|
Behavior on border.color {
|
||||||
|
|||||||
@@ -232,11 +232,6 @@ Item {
|
|||||||
height: parent.height - filterChips.height - Theme.spacingS
|
height: parent.height - filterChips.height - Theme.spacingS
|
||||||
clip: true
|
clip: true
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
readonly property real horizontalShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
|
|
||||||
readonly property real verticalShadowGutter: Theme.snap(Math.max(Theme.spacingS, 8), 1)
|
|
||||||
readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
|
|
||||||
topMargin: verticalShadowGutter
|
|
||||||
bottomMargin: verticalShadowGutter
|
|
||||||
|
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
id: historyModel
|
id: historyModel
|
||||||
@@ -268,14 +263,13 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
width: ListView.view.width
|
width: ListView.view.width
|
||||||
height: historyCard.height + historyListView.delegateShadowGutter
|
height: historyCard.height
|
||||||
clip: false
|
clip: true
|
||||||
|
|
||||||
HistoryNotificationCard {
|
HistoryNotificationCard {
|
||||||
id: historyCard
|
id: historyCard
|
||||||
width: Math.max(0, parent.width - (historyListView.horizontalShadowGutter * 2))
|
width: parent.width
|
||||||
y: historyListView.delegateShadowGutter / 2
|
x: delegateRoot.swipeOffset
|
||||||
x: historyListView.horizontalShadowGutter + delegateRoot.swipeOffset
|
|
||||||
historyItem: modelData
|
historyItem: modelData
|
||||||
isSelected: root.keyboardActive && root.selectedIndex === index
|
isSelected: root.keyboardActive && root.selectedIndex === index
|
||||||
keyboardNavigationActive: root.keyboardActive
|
keyboardNavigationActive: root.keyboardActive
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ DankListView {
|
|||||||
property real swipingCardOffset: 0
|
property real swipingCardOffset: 0
|
||||||
property real __pendingStableHeight: 0
|
property real __pendingStableHeight: 0
|
||||||
property real __heightUpdateThreshold: 20
|
property real __heightUpdateThreshold: 20
|
||||||
readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0
|
|
||||||
readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1)
|
|
||||||
readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1)
|
|
||||||
readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
@@ -60,26 +56,21 @@ DankListView {
|
|||||||
let delta = 0;
|
let delta = 0;
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const item = itemAtIndex(i);
|
const item = itemAtIndex(i);
|
||||||
if (item && item.children[0] && item.children[0].isAnimating) {
|
if (item && item.children[0] && item.children[0].isAnimating)
|
||||||
const targetDelegateHeight = item.children[0].targetHeight + listView.delegateShadowGutter;
|
delta += item.children[0].targetHeight - item.height;
|
||||||
delta += targetDelegateHeight - item.height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const targetHeight = contentHeight + delta;
|
const targetHeight = contentHeight + delta;
|
||||||
// During expansion, always update immediately without threshold check
|
// During expansion, always update immediately without threshold check
|
||||||
stableContentHeight = targetHeight;
|
stableContentHeight = targetHeight;
|
||||||
} else {
|
} else {
|
||||||
__pendingStableHeight = contentHeight;
|
__pendingStableHeight = contentHeight;
|
||||||
heightUpdateDebounce.stop();
|
heightUpdateDebounce.restart();
|
||||||
stableContentHeight = __pendingStableHeight;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
model: NotificationService.groupedNotifications
|
model: NotificationService.groupedNotifications
|
||||||
spacing: Theme.spacingL
|
spacing: Theme.spacingL
|
||||||
topMargin: shadowVerticalGutter
|
|
||||||
bottomMargin: shadowVerticalGutter
|
|
||||||
|
|
||||||
onIsUserScrollingChanged: {
|
onIsUserScrollingChanged: {
|
||||||
if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) {
|
if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) {
|
||||||
@@ -143,7 +134,8 @@ DankListView {
|
|||||||
readonly property real dismissThreshold: width * 0.35
|
readonly property real dismissThreshold: width * 0.35
|
||||||
property bool __delegateInitialized: false
|
property bool __delegateInitialized: false
|
||||||
|
|
||||||
readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 && (index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1)
|
readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 &&
|
||||||
|
(index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1)
|
||||||
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? listView.swipingCardOffset * 0.10 : 0
|
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? listView.swipingCardOffset * 0.10 : 0
|
||||||
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0
|
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0
|
||||||
readonly property real swipeFadeStartOffset: width * 0.75
|
readonly property real swipeFadeStartOffset: width * 0.75
|
||||||
@@ -157,14 +149,13 @@ DankListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
width: ListView.view.width
|
width: ListView.view.width
|
||||||
height: notificationCard.height + listView.delegateShadowGutter
|
height: notificationCard.height
|
||||||
clip: false
|
clip: notificationCard.isAnimating
|
||||||
|
|
||||||
NotificationCard {
|
NotificationCard {
|
||||||
id: notificationCard
|
id: notificationCard
|
||||||
width: Math.max(0, parent.width - (listView.shadowHorizontalGutter * 2))
|
width: parent.width
|
||||||
y: listView.delegateShadowGutter / 2
|
x: delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence
|
||||||
x: listView.shadowHorizontalGutter + delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence
|
|
||||||
listLevelAdjacentScaleInfluence: delegateRoot.adjacentScaleInfluence
|
listLevelAdjacentScaleInfluence: delegateRoot.adjacentScaleInfluence
|
||||||
listLevelScaleAnimationsEnabled: listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe
|
listLevelScaleAnimationsEnabled: listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe
|
||||||
notificationGroup: modelData
|
notificationGroup: modelData
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -39,14 +38,7 @@ Rectangle {
|
|||||||
height: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
height: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
||||||
readonly property real targetHeight: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
readonly property real targetHeight: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
scale: (cardHoverHandler.hovered ? 1.004 : 1.0) * listLevelAdjacentScaleInfluence
|
scale: (cardHoverHandler.hovered ? 1.01 : 1.0) * listLevelAdjacentScaleInfluence
|
||||||
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
|
||||||
readonly property var shadowElevation: Theme.elevationLevel1
|
|
||||||
readonly property real baseShadowBlurPx: (shadowElevation && shadowElevation.blurPx !== undefined) ? shadowElevation.blurPx : 4
|
|
||||||
readonly property real hoverShadowBlurBoost: cardHoverHandler.hovered ? Math.min(2, baseShadowBlurPx * 0.25) : 0
|
|
||||||
property real shadowBlurPx: shadowsAllowed ? (baseShadowBlurPx + hoverShadowBlurBoost) : 0
|
|
||||||
property real shadowOffsetXPx: shadowsAllowed ? Theme.elevationOffsetX(shadowElevation) : 0
|
|
||||||
property real shadowOffsetYPx: shadowsAllowed ? (Theme.elevationOffsetY(shadowElevation, 1) + (cardHoverHandler.hovered ? 0.35 : 0)) : 0
|
|
||||||
property bool __initialized: false
|
property bool __initialized: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -64,27 +56,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on shadowBlurPx {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on shadowOffsetXPx {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on shadowOffsetYPx {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on border.color {
|
Behavior on border.color {
|
||||||
enabled: root.__initialized
|
enabled: root.__initialized
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
@@ -124,31 +95,14 @@ Rectangle {
|
|||||||
if (notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical) {
|
if (notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
clip: false
|
clip: true
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
id: cardHoverHandler
|
id: cardHoverHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
|
||||||
id: shadowLayer
|
|
||||||
anchors.fill: parent
|
|
||||||
z: -1
|
|
||||||
level: root.shadowElevation
|
|
||||||
targetRadius: root.radius
|
|
||||||
targetColor: root.color
|
|
||||||
borderColor: root.border.color
|
|
||||||
borderWidth: root.border.width
|
|
||||||
shadowBlurPx: root.shadowBlurPx
|
|
||||||
shadowSpreadPx: 0
|
|
||||||
shadowOffsetX: root.shadowOffsetXPx
|
|
||||||
shadowOffsetY: root.shadowOffsetYPx
|
|
||||||
shadowColor: root.shadowElevation ? Theme.elevationShadowColor(root.shadowElevation) : "transparent"
|
|
||||||
shadowEnabled: root.shadowsAllowed
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
@@ -350,13 +304,8 @@ Rectangle {
|
|||||||
|
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
||||||
root.userInitiatedExpansion = true;
|
|
||||||
const messageId = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.notification && notificationGroup.latestNotification.notification.id) ? (notificationGroup.latestNotification.notification.id + "_desc") : "";
|
const messageId = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.notification && notificationGroup.latestNotification.notification.id) ? (notificationGroup.latestNotification.notification.id + "_desc") : "";
|
||||||
NotificationService.toggleMessageExpansion(messageId);
|
NotificationService.toggleMessageExpansion(messageId);
|
||||||
Qt.callLater(() => {
|
|
||||||
if (root && !root.isAnimating)
|
|
||||||
root.userInitiatedExpansion = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,7 +419,9 @@ Rectangle {
|
|||||||
id: delegateRect
|
id: delegateRect
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
readonly property bool isAdjacentToSwipe: root.swipingNotificationIndex !== -1 && (expandedDelegateWrapper.index === root.swipingNotificationIndex - 1 || expandedDelegateWrapper.index === root.swipingNotificationIndex + 1)
|
readonly property bool isAdjacentToSwipe: root.swipingNotificationIndex !== -1 &&
|
||||||
|
(expandedDelegateWrapper.index === root.swipingNotificationIndex - 1 ||
|
||||||
|
expandedDelegateWrapper.index === root.swipingNotificationIndex + 1)
|
||||||
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? root.swipingNotificationOffset * 0.10 : 0
|
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? root.swipingNotificationOffset * 0.10 : 0
|
||||||
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(root.swipingNotificationOffset) / width * 0.02 : 1.0
|
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(root.swipingNotificationOffset) / width * 0.02 : 1.0
|
||||||
|
|
||||||
@@ -654,12 +605,7 @@ Rectangle {
|
|||||||
|
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (!parent.hoveredLink && (bodyText.hasMoreText || messageExpanded)) {
|
if (!parent.hoveredLink && (bodyText.hasMoreText || messageExpanded)) {
|
||||||
root.userInitiatedExpansion = true;
|
|
||||||
NotificationService.toggleMessageExpansion(modelData?.notification?.id || "");
|
NotificationService.toggleMessageExpansion(modelData?.notification?.id || "");
|
||||||
Qt.callLater(() => {
|
|
||||||
if (root && !root.isAnimating)
|
|
||||||
root.userInitiatedExpansion = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,22 +7,15 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
layerNamespace: "dms:notification-center-popout"
|
layerNamespace: "dms:notification-center-popout"
|
||||||
fullHeightSurface: false
|
fullHeightSurface: true
|
||||||
|
|
||||||
property bool notificationHistoryVisible: false
|
property bool notificationHistoryVisible: false
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
property real stablePopupHeight: 400
|
property real stablePopupHeight: 400
|
||||||
property real _lastAlignedContentHeight: -1
|
property real _lastAlignedContentHeight: -1
|
||||||
property bool _pendingSizedOpen: false
|
|
||||||
|
|
||||||
function updateStablePopupHeight() {
|
function updateStablePopupHeight() {
|
||||||
const item = contentLoader.item;
|
const item = contentLoader.item;
|
||||||
if (item && !root.shouldBeVisible) {
|
|
||||||
const notificationList = findChild(item, "notificationList");
|
|
||||||
if (notificationList && typeof notificationList.forceLayout === "function") {
|
|
||||||
notificationList.forceLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const target = item ? Theme.px(item.implicitHeight, dpr) : 400;
|
const target = item ? Theme.px(item.implicitHeight, dpr) : 400;
|
||||||
if (Math.abs(target - _lastAlignedContentHeight) < 0.5)
|
if (Math.abs(target - _lastAlignedContentHeight) < 0.5)
|
||||||
return;
|
return;
|
||||||
@@ -33,7 +26,7 @@ DankPopout {
|
|||||||
NotificationKeyboardController {
|
NotificationKeyboardController {
|
||||||
id: keyboardController
|
id: keyboardController
|
||||||
listView: null
|
listView: null
|
||||||
isOpen: root.shouldBeVisible
|
isOpen: notificationHistoryVisible
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
notificationHistoryVisible = false;
|
notificationHistoryVisible = false;
|
||||||
}
|
}
|
||||||
@@ -47,42 +40,20 @@ DankPopout {
|
|||||||
suspendShadowWhileResizing: false
|
suspendShadowWhileResizing: false
|
||||||
|
|
||||||
screen: triggerScreen
|
screen: triggerScreen
|
||||||
|
shouldBeVisible: notificationHistoryVisible
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
notificationHistoryVisible = !notificationHistoryVisible;
|
notificationHistoryVisible = !notificationHistoryVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
function openSized() {
|
|
||||||
if (!notificationHistoryVisible)
|
|
||||||
return;
|
|
||||||
|
|
||||||
primeContent();
|
|
||||||
if (contentLoader.item) {
|
|
||||||
updateStablePopupHeight();
|
|
||||||
_pendingSizedOpen = false;
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (!notificationHistoryVisible)
|
|
||||||
return;
|
|
||||||
updateStablePopupHeight();
|
|
||||||
open();
|
|
||||||
clearPrimedContent();
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pendingSizedOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onBackgroundClicked: {
|
onBackgroundClicked: {
|
||||||
notificationHistoryVisible = false;
|
notificationHistoryVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onNotificationHistoryVisibleChanged: {
|
onNotificationHistoryVisibleChanged: {
|
||||||
if (notificationHistoryVisible) {
|
if (notificationHistoryVisible) {
|
||||||
openSized();
|
open();
|
||||||
} else {
|
} else {
|
||||||
_pendingSizedOpen = false;
|
|
||||||
clearPrimedContent();
|
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,17 +82,6 @@ DankPopout {
|
|||||||
target: contentLoader
|
target: contentLoader
|
||||||
function onLoaded() {
|
function onLoaded() {
|
||||||
root.updateStablePopupHeight();
|
root.updateStablePopupHeight();
|
||||||
if (root._pendingSizedOpen && root.notificationHistoryVisible) {
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (!root._pendingSizedOpen || !root.notificationHistoryVisible)
|
|
||||||
return;
|
|
||||||
root.updateStablePopupHeight();
|
|
||||||
root._pendingSizedOpen = false;
|
|
||||||
root.open();
|
|
||||||
root.clearPrimedContent();
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (root.shouldBeVisible)
|
if (root.shouldBeVisible)
|
||||||
Qt.callLater(root.setupKeyboardNavigation);
|
Qt.callLater(root.setupKeyboardNavigation);
|
||||||
}
|
}
|
||||||
@@ -179,8 +139,7 @@ DankPopout {
|
|||||||
baseHeight += Theme.spacingM * 2;
|
baseHeight += Theme.spacingM * 2;
|
||||||
|
|
||||||
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0;
|
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0;
|
||||||
const currentListHeight = root.shouldBeVisible ? notificationList.stableContentHeight : notificationList.listContentHeight;
|
let listHeight = notificationHeader.currentTab === 0 ? notificationList.stableContentHeight : Math.max(200, NotificationService.historyList.length * 80);
|
||||||
let listHeight = notificationHeader.currentTab === 0 ? currentListHeight : Math.max(200, NotificationService.historyList.length * 80);
|
|
||||||
if (notificationHeader.currentTab === 0 && NotificationService.groupedNotifications.length === 0) {
|
if (notificationHeader.currentTab === 0 && NotificationService.groupedNotifications.length === 0) {
|
||||||
listHeight = 200;
|
listHeight = 200;
|
||||||
}
|
}
|
||||||
@@ -274,21 +233,13 @@ DankPopout {
|
|||||||
expanded: notificationHeader.showSettings
|
expanded: notificationHeader.showSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
KeyboardNavigatedNotificationList {
|
||||||
|
id: notificationList
|
||||||
|
objectName: "notificationList"
|
||||||
visible: notificationHeader.currentTab === 0
|
visible: notificationHeader.currentTab === 0
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2
|
height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2
|
||||||
|
cardAnimateExpansion: true
|
||||||
KeyboardNavigatedNotificationList {
|
|
||||||
id: notificationList
|
|
||||||
objectName: "notificationList"
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: -shadowHorizontalGutter
|
|
||||||
anchors.rightMargin: -shadowHorizontalGutter
|
|
||||||
anchors.topMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
|
||||||
anchors.bottomMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
|
||||||
cardAnimateExpansion: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryNotificationList {
|
HistoryNotificationList {
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ PanelWindow {
|
|||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
readonly property real contentImplicitWidth: screen ? Math.min(400, Math.max(320, screen.width * 0.23)) : 380
|
implicitWidth: screen ? Math.min(400, Math.max(320, screen.width * 0.23)) : 380
|
||||||
readonly property real contentImplicitHeight: {
|
implicitHeight: {
|
||||||
if (SettingsData.notificationPopupPrivacyMode && !descriptionExpanded)
|
if (SettingsData.notificationPopupPrivacyMode && !descriptionExpanded)
|
||||||
return basePopupHeightPrivacy;
|
return basePopupHeightPrivacy;
|
||||||
if (!descriptionExpanded)
|
if (!descriptionExpanded)
|
||||||
@@ -130,8 +130,6 @@ PanelWindow {
|
|||||||
return basePopupHeight + bodyTextHeight - collapsedBodyHeight;
|
return basePopupHeight + bodyTextHeight - collapsedBodyHeight;
|
||||||
return basePopupHeight;
|
return basePopupHeight;
|
||||||
}
|
}
|
||||||
implicitWidth: contentImplicitWidth + (windowShadowPad * 2)
|
|
||||||
implicitHeight: contentImplicitHeight + (windowShadowPad * 2)
|
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
Behavior on implicitHeight {
|
||||||
enabled: !exiting && !_isDestroying
|
enabled: !exiting && !_isDestroying
|
||||||
@@ -184,15 +182,11 @@ PanelWindow {
|
|||||||
property bool isTopCenter: SettingsData.notificationPopupPosition === -1
|
property bool isTopCenter: SettingsData.notificationPopupPosition === -1
|
||||||
property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter
|
property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter
|
||||||
property bool isCenterPosition: isTopCenter || isBottomCenter
|
property bool isCenterPosition: isTopCenter || isBottomCenter
|
||||||
readonly property real maxPopupShadowBlurPx: Math.max((Theme.elevationLevel3 && Theme.elevationLevel3.blurPx !== undefined) ? Theme.elevationLevel3.blurPx : 12, (Theme.elevationLevel4 && Theme.elevationLevel4.blurPx !== undefined) ? Theme.elevationLevel4.blurPx : 16)
|
|
||||||
readonly property real maxPopupShadowOffsetXPx: Math.max(Math.abs(Theme.elevationOffsetX(Theme.elevationLevel3)), Math.abs(Theme.elevationOffsetX(Theme.elevationLevel4)))
|
|
||||||
readonly property real maxPopupShadowOffsetYPx: Math.max(Math.abs(Theme.elevationOffsetY(Theme.elevationLevel3, 6)), Math.abs(Theme.elevationOffsetY(Theme.elevationLevel4, 8)))
|
|
||||||
readonly property real windowShadowPad: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled ? Theme.snap(Math.max(16, maxPopupShadowBlurPx + Math.max(maxPopupShadowOffsetXPx, maxPopupShadowOffsetYPx) + 8), dpr) : 0
|
|
||||||
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
anchors.left: true
|
anchors.bottom: true
|
||||||
anchors.bottom: false
|
anchors.left: SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom
|
||||||
anchors.right: false
|
anchors.right: SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Right
|
||||||
|
|
||||||
mask: contentInputMask
|
mask: contentInputMask
|
||||||
|
|
||||||
@@ -211,10 +205,10 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
margins {
|
margins {
|
||||||
top: getWindowTopMargin()
|
top: _storedTopMargin
|
||||||
bottom: 0
|
bottom: _storedBottomMargin
|
||||||
left: getWindowLeftMargin()
|
left: getLeftMargin()
|
||||||
right: 0
|
right: getRightMargin()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBarInfo() {
|
function getBarInfo() {
|
||||||
@@ -256,7 +250,7 @@ PanelWindow {
|
|||||||
|
|
||||||
function getLeftMargin() {
|
function getLeftMargin() {
|
||||||
if (isCenterPosition)
|
if (isCenterPosition)
|
||||||
return screen ? (screen.width - alignedWidth) / 2 : 0;
|
return screen ? (screen.width - implicitWidth) / 2 : 0;
|
||||||
|
|
||||||
const popupPos = SettingsData.notificationPopupPosition;
|
const popupPos = SettingsData.notificationPopupPosition;
|
||||||
const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom;
|
const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom;
|
||||||
@@ -280,56 +274,23 @@ PanelWindow {
|
|||||||
return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance;
|
return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getContentX() {
|
|
||||||
if (!screen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const popupPos = SettingsData.notificationPopupPosition;
|
|
||||||
const barLeft = getLeftMargin();
|
|
||||||
const barRight = getRightMargin();
|
|
||||||
|
|
||||||
if (isCenterPosition)
|
|
||||||
return Theme.snap((screen.width - alignedWidth) / 2, dpr);
|
|
||||||
if (popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom)
|
|
||||||
return Theme.snap(barLeft, dpr);
|
|
||||||
return Theme.snap(screen.width - alignedWidth - barRight, dpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getContentY() {
|
|
||||||
if (!screen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const popupPos = SettingsData.notificationPopupPosition;
|
|
||||||
const barTop = getTopMargin();
|
|
||||||
const barBottom = getBottomMargin();
|
|
||||||
const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left;
|
|
||||||
if (isTop)
|
|
||||||
return Theme.snap(barTop, dpr);
|
|
||||||
return Theme.snap(screen.height - alignedHeight - barBottom, dpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWindowLeftMargin() {
|
|
||||||
if (!screen)
|
|
||||||
return 0;
|
|
||||||
return Theme.snap(getContentX() - windowShadowPad, dpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWindowTopMargin() {
|
|
||||||
if (!screen)
|
|
||||||
return 0;
|
|
||||||
return Theme.snap(getContentY() - windowShadowPad, dpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property bool screenValid: win.screen && !_isDestroying
|
readonly property bool screenValid: win.screen && !_isDestroying
|
||||||
readonly property real dpr: screenValid ? CompositorService.getScreenScale(win.screen) : 1
|
readonly property real dpr: screenValid ? CompositorService.getScreenScale(win.screen) : 1
|
||||||
readonly property real alignedWidth: Theme.px(Math.max(0, implicitWidth - (windowShadowPad * 2)), dpr)
|
readonly property real alignedWidth: Theme.px(implicitWidth, dpr)
|
||||||
readonly property real alignedHeight: Theme.px(Math.max(0, implicitHeight - (windowShadowPad * 2)), dpr)
|
readonly property real alignedHeight: Theme.px(implicitHeight, dpr)
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
x: Theme.snap(windowShadowPad, dpr)
|
x: Theme.snap((win.width - alignedWidth) / 2, dpr)
|
||||||
y: Theme.snap(windowShadowPad, dpr)
|
y: {
|
||||||
|
const isTop = isTopCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Left;
|
||||||
|
if (isTop) {
|
||||||
|
return Theme.snap(screenY, dpr);
|
||||||
|
} else {
|
||||||
|
return Theme.snap(win.height - alignedHeight - screenY, dpr);
|
||||||
|
}
|
||||||
|
}
|
||||||
width: alignedWidth
|
width: alignedWidth
|
||||||
height: alignedHeight
|
height: alignedHeight
|
||||||
visible: !win._finalized
|
visible: !win._finalized
|
||||||
@@ -352,13 +313,12 @@ PanelWindow {
|
|||||||
readonly property bool swipeActive: swipeDragHandler.active
|
readonly property bool swipeActive: swipeDragHandler.active
|
||||||
property bool swipeDismissing: false
|
property bool swipeDismissing: false
|
||||||
|
|
||||||
readonly property bool shadowsAllowed: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled
|
readonly property real radiusForShadow: Theme.cornerRadius
|
||||||
readonly property var elevLevel: cardHoverHandler.hovered ? Theme.elevationLevel4 : Theme.elevationLevel3
|
property real shadowBlurPx: SettingsData.notificationPopupShadowEnabled ? ((2 + radiusForShadow * 0.2) * (cardHoverHandler.hovered ? 1.2 : 1)) : 0
|
||||||
readonly property real cardInset: Theme.snap(4, win.dpr)
|
property real shadowSpreadPx: SettingsData.notificationPopupShadowEnabled ? (radiusForShadow * (cardHoverHandler.hovered ? 0.06 : 0)) : 0
|
||||||
readonly property real shadowRenderPadding: shadowsAllowed ? Theme.snap(Math.max(16, shadowBlurPx + Math.max(Math.abs(shadowOffsetX), Math.abs(shadowOffsetY)) + 8), win.dpr) : 0
|
property real shadowBaseAlpha: 0.35
|
||||||
property real shadowBlurPx: shadowsAllowed ? (elevLevel && elevLevel.blurPx !== undefined ? elevLevel.blurPx : 12) : 0
|
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
||||||
property real shadowOffsetX: shadowsAllowed ? Theme.elevationOffsetX(elevLevel) : 0
|
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||||
property real shadowOffsetY: shadowsAllowed ? Theme.elevationOffsetY(elevLevel, 6) : 0
|
|
||||||
|
|
||||||
Behavior on shadowBlurPx {
|
Behavior on shadowBlurPx {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -367,50 +327,50 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on shadowOffsetX {
|
Behavior on shadowSpreadPx {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on shadowOffsetY {
|
Item {
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.shortDuration
|
|
||||||
easing.type: Theme.standardEasing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ElevationShadow {
|
|
||||||
id: bgShadowLayer
|
id: bgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: -content.shadowRenderPadding
|
anchors.margins: Theme.snap(4, win.dpr)
|
||||||
level: content.elevLevel
|
layer.enabled: !win._isDestroying && win.screenValid
|
||||||
fallbackOffset: 6
|
layer.smooth: false
|
||||||
shadowBlurPx: content.shadowBlurPx
|
|
||||||
shadowOffsetX: content.shadowOffsetX
|
|
||||||
shadowOffsetY: content.shadowOffsetY
|
|
||||||
shadowColor: content.shadowsAllowed && content.elevLevel ? Theme.elevationShadowColor(content.elevLevel) : "transparent"
|
|
||||||
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed
|
|
||||||
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
|
|
||||||
sourceRect.anchors.fill: undefined
|
readonly property int blurMax: 64
|
||||||
sourceRect.x: content.shadowRenderPadding + content.cardInset
|
|
||||||
sourceRect.y: content.shadowRenderPadding + content.cardInset
|
layer.effect: MultiEffect {
|
||||||
sourceRect.width: Math.max(0, content.width - (content.cardInset * 2))
|
id: shadowFx
|
||||||
sourceRect.height: Math.max(0, content.height - (content.cardInset * 2))
|
autoPaddingEnabled: true
|
||||||
sourceRect.radius: Theme.cornerRadius
|
shadowEnabled: SettingsData.notificationPopupShadowEnabled
|
||||||
sourceRect.color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
blurEnabled: false
|
||||||
sourceRect.border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
maskEnabled: false
|
||||||
sourceRect.border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
shadowBlur: Math.max(0, Math.min(1, content.shadowBlurPx / bgShadowLayer.blurMax))
|
||||||
|
shadowScale: 1 + (2 * content.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, content.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
x: bgShadowLayer.sourceRect.x
|
id: shadowShapeSource
|
||||||
y: bgShadowLayer.sourceRect.y
|
anchors.fill: parent
|
||||||
width: bgShadowLayer.sourceRect.width
|
radius: Theme.cornerRadius
|
||||||
height: bgShadowLayer.sourceRect.height
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
radius: bgShadowLayer.sourceRect.radius
|
border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
||||||
|
border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: shadowShapeSource.radius
|
||||||
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical
|
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical
|
||||||
opacity: 1
|
opacity: 1
|
||||||
clip: true
|
clip: true
|
||||||
@@ -439,7 +399,7 @@ PanelWindow {
|
|||||||
Item {
|
Item {
|
||||||
id: backgroundContainer
|
id: backgroundContainer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: content.cardInset
|
anchors.margins: Theme.snap(4, win.dpr)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
|
|||||||
@@ -351,7 +351,6 @@ Item {
|
|||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: root.widgetEnabled && root.activeComponent !== null
|
|
||||||
sourceComponent: root.activeComponent
|
sourceComponent: root.activeComponent
|
||||||
|
|
||||||
function reloadComponent() {
|
function reloadComponent() {
|
||||||
|
|||||||
@@ -878,17 +878,12 @@ Item {
|
|||||||
x: hoveredButton ? hoveredButton.mapToItem(aboutTab, hoveredButton.width / 2, 0).x - width / 2 : 0
|
x: hoveredButton ? hoveredButton.mapToItem(aboutTab, hoveredButton.width / 2, 0).x - width / 2 : 0
|
||||||
y: hoveredButton ? communityIcons.mapToItem(aboutTab, 0, 0).y - height - 8 : 0
|
y: hoveredButton ? communityIcons.mapToItem(aboutTab, 0, 0).y - height - 8 : 0
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
anchors.fill: parent
|
layer.effect: MultiEffect {
|
||||||
z: -1
|
shadowEnabled: true
|
||||||
level: Theme.elevationLevel1
|
shadowOpacity: 0.15
|
||||||
fallbackOffset: 1
|
shadowVerticalOffset: 2
|
||||||
targetRadius: communityTooltip.radius
|
shadowBlur: 0.5
|
||||||
targetColor: communityTooltip.color
|
|
||||||
borderColor: communityTooltip.border.color
|
|
||||||
borderWidth: communityTooltip.border.width
|
|
||||||
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
|||||||
@@ -52,11 +52,9 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _isBarActive(c) {
|
function _isBarActive(c) {
|
||||||
if (!c.enabled)
|
if (!c.enabled) return false;
|
||||||
return false;
|
|
||||||
const prefs = c.screenPreferences || ["all"];
|
const prefs = c.screenPreferences || ["all"];
|
||||||
if (prefs.length > 0)
|
if (prefs.length > 0) return true;
|
||||||
return true;
|
|
||||||
return (c.showOnLastDisplay ?? true) && Quickshell.screens.length === 1;
|
return (c.showOnLastDisplay ?? true) && Quickshell.screens.length === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +64,7 @@ Item {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const hasHorizontal = configs.some(c => {
|
const hasHorizontal = configs.some(c => {
|
||||||
if (!_isBarActive(c))
|
if (!_isBarActive(c)) return false;
|
||||||
return false;
|
|
||||||
const p = c.position ?? SettingsData.Position.Top;
|
const p = c.position ?? SettingsData.Position.Top;
|
||||||
return p === SettingsData.Position.Top || p === SettingsData.Position.Bottom;
|
return p === SettingsData.Position.Top || p === SettingsData.Position.Bottom;
|
||||||
});
|
});
|
||||||
@@ -75,8 +72,7 @@ Item {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const hasVertical = configs.some(c => {
|
const hasVertical = configs.some(c => {
|
||||||
if (!_isBarActive(c))
|
if (!_isBarActive(c)) return false;
|
||||||
return false;
|
|
||||||
const p = c.position ?? SettingsData.Position.Top;
|
const p = c.position ?? SettingsData.Position.Top;
|
||||||
return p === SettingsData.Position.Left || p === SettingsData.Position.Right;
|
return p === SettingsData.Position.Left || p === SettingsData.Position.Right;
|
||||||
});
|
});
|
||||||
@@ -140,9 +136,7 @@ Item {
|
|||||||
scrollYBehavior: defaultBar.scrollYBehavior ?? "workspace",
|
scrollYBehavior: defaultBar.scrollYBehavior ?? "workspace",
|
||||||
shadowIntensity: defaultBar.shadowIntensity ?? 0,
|
shadowIntensity: defaultBar.shadowIntensity ?? 0,
|
||||||
shadowOpacity: defaultBar.shadowOpacity ?? 60,
|
shadowOpacity: defaultBar.shadowOpacity ?? 60,
|
||||||
shadowDirectionMode: defaultBar.shadowDirectionMode ?? "inherit",
|
shadowColorMode: defaultBar.shadowColorMode ?? "text",
|
||||||
shadowDirection: defaultBar.shadowDirection ?? "top",
|
|
||||||
shadowColorMode: defaultBar.shadowColorMode ?? "default",
|
|
||||||
shadowCustomColor: defaultBar.shadowCustomColor ?? "#000000"
|
shadowCustomColor: defaultBar.shadowCustomColor ?? "#000000"
|
||||||
};
|
};
|
||||||
SettingsData.addBarConfig(newBar);
|
SettingsData.addBarConfig(newBar);
|
||||||
@@ -1044,237 +1038,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
|
||||||
id: shadowCard
|
|
||||||
iconName: "layers"
|
|
||||||
title: I18n.tr("Shadow Override", "bar shadow settings card")
|
|
||||||
settingKey: "barShadow"
|
|
||||||
collapsible: true
|
|
||||||
expanded: true
|
|
||||||
visible: selectedBarConfig?.enabled
|
|
||||||
|
|
||||||
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
|
|
||||||
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "default") === "custom"
|
|
||||||
readonly property string directionSource: selectedBarConfig?.shadowDirectionMode ?? "inherit"
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
width: parent.width
|
|
||||||
text: I18n.tr("Enable a custom override below to set per-bar shadow intensity, opacity, and color.")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsToggleRow {
|
|
||||||
text: I18n.tr("Custom Shadow Override")
|
|
||||||
description: I18n.tr("Override the global shadow with per-bar settings")
|
|
||||||
checked: shadowCard.shadowActive
|
|
||||||
onToggled: checked => {
|
|
||||||
if (checked) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowIntensity: 12,
|
|
||||||
shadowOpacity: 60
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowIntensity: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
visible: shadowCard.shadowActive
|
|
||||||
text: I18n.tr("Intensity", "shadow intensity slider")
|
|
||||||
minimum: 0
|
|
||||||
maximum: 100
|
|
||||||
unit: "px"
|
|
||||||
defaultValue: 12
|
|
||||||
value: selectedBarConfig?.shadowIntensity ?? 0
|
|
||||||
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowIntensity: newValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
visible: shadowCard.shadowActive
|
|
||||||
text: I18n.tr("Opacity")
|
|
||||||
minimum: 10
|
|
||||||
maximum: 100
|
|
||||||
unit: "%"
|
|
||||||
defaultValue: 60
|
|
||||||
value: selectedBarConfig?.shadowOpacity ?? 60
|
|
||||||
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowOpacity: newValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsDropdownRow {
|
|
||||||
visible: shadowCard.shadowActive
|
|
||||||
text: I18n.tr("Direction Source", "bar shadow direction source")
|
|
||||||
description: I18n.tr("Choose how this bar resolves shadow direction")
|
|
||||||
settingKey: "barShadowDirectionSource"
|
|
||||||
options: [I18n.tr("Inherit Global (Default)", "bar shadow direction source option"), I18n.tr("Auto (Bar-aware)", "bar shadow direction source option"), I18n.tr("Manual", "bar shadow direction source option")]
|
|
||||||
currentValue: {
|
|
||||||
switch (shadowCard.directionSource) {
|
|
||||||
case "autoBar":
|
|
||||||
return I18n.tr("Auto (Bar-aware)", "bar shadow direction source option");
|
|
||||||
case "manual":
|
|
||||||
return I18n.tr("Manual", "bar shadow direction source option");
|
|
||||||
default:
|
|
||||||
return I18n.tr("Inherit Global (Default)", "bar shadow direction source option");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onValueChanged: value => {
|
|
||||||
if (value === I18n.tr("Auto (Bar-aware)", "bar shadow direction source option")) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirectionMode: "autoBar"
|
|
||||||
});
|
|
||||||
} else if (value === I18n.tr("Manual", "bar shadow direction source option")) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirectionMode: "manual"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirectionMode: "inherit"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsDropdownRow {
|
|
||||||
visible: shadowCard.shadowActive && shadowCard.directionSource === "manual"
|
|
||||||
text: I18n.tr("Manual Direction", "bar manual shadow direction")
|
|
||||||
description: I18n.tr("Use a fixed shadow direction for this bar")
|
|
||||||
settingKey: "barShadowDirectionManual"
|
|
||||||
options: [I18n.tr("Top", "shadow direction option"), I18n.tr("Top Left", "shadow direction option"), I18n.tr("Top Right", "shadow direction option"), I18n.tr("Bottom", "shadow direction option")]
|
|
||||||
currentValue: {
|
|
||||||
switch (selectedBarConfig?.shadowDirection) {
|
|
||||||
case "topLeft":
|
|
||||||
return I18n.tr("Top Left", "shadow direction option");
|
|
||||||
case "topRight":
|
|
||||||
return I18n.tr("Top Right", "shadow direction option");
|
|
||||||
case "bottom":
|
|
||||||
return I18n.tr("Bottom", "shadow direction option");
|
|
||||||
default:
|
|
||||||
return I18n.tr("Top", "shadow direction option");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onValueChanged: value => {
|
|
||||||
if (value === I18n.tr("Top Left", "shadow direction option")) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirection: "topLeft"
|
|
||||||
});
|
|
||||||
} else if (value === I18n.tr("Top Right", "shadow direction option")) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirection: "topRight"
|
|
||||||
});
|
|
||||||
} else if (value === I18n.tr("Bottom", "shadow direction option")) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirection: "bottom"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowDirection: "top"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
visible: shadowCard.shadowActive
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Color")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingM
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: shadowColorGroup.implicitHeight
|
|
||||||
|
|
||||||
DankButtonGroup {
|
|
||||||
id: shadowColorGroup
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
buttonPadding: parent.width < 420 ? Theme.spacingXS : Theme.spacingS
|
|
||||||
minButtonWidth: parent.width < 420 ? 36 : 56
|
|
||||||
textSize: parent.width < 420 ? Theme.fontSizeSmall : Theme.fontSizeMedium
|
|
||||||
model: [I18n.tr("Default (Black)"), I18n.tr("Surface", "shadow color option"), I18n.tr("Primary"), I18n.tr("Secondary"), I18n.tr("Custom")]
|
|
||||||
selectionMode: "single"
|
|
||||||
currentIndex: {
|
|
||||||
switch (selectedBarConfig?.shadowColorMode || "default") {
|
|
||||||
case "surface":
|
|
||||||
return 1;
|
|
||||||
case "primary":
|
|
||||||
return 2;
|
|
||||||
case "secondary":
|
|
||||||
return 3;
|
|
||||||
case "custom":
|
|
||||||
return 4;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onSelectionChanged: (index, selected) => {
|
|
||||||
if (!selected)
|
|
||||||
return;
|
|
||||||
let mode = "default";
|
|
||||||
switch (index) {
|
|
||||||
case 1:
|
|
||||||
mode = "surface";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mode = "primary";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
mode = "secondary";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
mode = "custom";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowColorMode: mode
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: selectedBarConfig?.shadowColorMode === "custom"
|
|
||||||
width: 32
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: selectedBarConfig?.shadowCustomColor ?? "#000000"
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
PopoutService.colorPickerModal.selectedColor = selectedBarConfig?.shadowCustomColor ?? "#000000";
|
|
||||||
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Color");
|
|
||||||
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowCustomColor: color.toString()
|
|
||||||
});
|
|
||||||
};
|
|
||||||
PopoutService.colorPickerModal.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
iconName: "rounded_corner"
|
iconName: "rounded_corner"
|
||||||
title: I18n.tr("Corners & Background")
|
title: I18n.tr("Corners & Background")
|
||||||
@@ -1377,6 +1140,134 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsCard {
|
||||||
|
id: shadowCard
|
||||||
|
iconName: "layers"
|
||||||
|
title: I18n.tr("Shadow", "bar shadow settings card")
|
||||||
|
settingKey: "barShadow"
|
||||||
|
collapsible: true
|
||||||
|
expanded: false
|
||||||
|
visible: selectedBarConfig?.enabled
|
||||||
|
|
||||||
|
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
|
||||||
|
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "text") === "custom"
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
text: I18n.tr("Intensity", "shadow intensity slider")
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
unit: "%"
|
||||||
|
value: selectedBarConfig?.shadowIntensity ?? 0
|
||||||
|
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowIntensity: newValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
visible: shadowCard.shadowActive
|
||||||
|
text: I18n.tr("Opacity")
|
||||||
|
minimum: 10
|
||||||
|
maximum: 100
|
||||||
|
unit: "%"
|
||||||
|
value: selectedBarConfig?.shadowOpacity ?? 60
|
||||||
|
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowOpacity: newValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
visible: shadowCard.shadowActive
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Color")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingM
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
height: shadowColorGroup.implicitHeight
|
||||||
|
|
||||||
|
DankButtonGroup {
|
||||||
|
id: shadowColorGroup
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
buttonPadding: parent.width < 420 ? Theme.spacingXS : Theme.spacingS
|
||||||
|
minButtonWidth: parent.width < 420 ? 36 : 56
|
||||||
|
textSize: parent.width < 420 ? Theme.fontSizeSmall : Theme.fontSizeMedium
|
||||||
|
model: [I18n.tr("Text", "shadow color option"), I18n.tr("Surface", "shadow color option"), I18n.tr("Primary"), I18n.tr("Secondary"), I18n.tr("Custom")]
|
||||||
|
selectionMode: "single"
|
||||||
|
currentIndex: {
|
||||||
|
switch (selectedBarConfig?.shadowColorMode || "text") {
|
||||||
|
case "surface":
|
||||||
|
return 1;
|
||||||
|
case "primary":
|
||||||
|
return 2;
|
||||||
|
case "secondary":
|
||||||
|
return 3;
|
||||||
|
case "custom":
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSelectionChanged: (index, selected) => {
|
||||||
|
if (!selected)
|
||||||
|
return;
|
||||||
|
let mode = "text";
|
||||||
|
switch (index) {
|
||||||
|
case 1:
|
||||||
|
mode = "surface";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mode = "primary";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
mode = "secondary";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
mode = "custom";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowColorMode: mode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: selectedBarConfig?.shadowColorMode === "custom"
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
radius: 16
|
||||||
|
color: selectedBarConfig?.shadowCustomColor ?? "#000000"
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
PopoutService.colorPickerModal.selectedColor = selectedBarConfig?.shadowCustomColor ?? "#000000";
|
||||||
|
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Color");
|
||||||
|
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowCustomColor: color.toString()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
PopoutService.colorPickerModal.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsToggleCard {
|
SettingsToggleCard {
|
||||||
iconName: "border_style"
|
iconName: "border_style"
|
||||||
title: I18n.tr("Border")
|
title: I18n.tr("Border")
|
||||||
|
|||||||
@@ -1281,15 +1281,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
iconName: "qr_code"
|
|
||||||
buttonSize: 28
|
|
||||||
visible: modelData.secured && modelData.saved
|
|
||||||
onClicked: {
|
|
||||||
PopoutService.showWifiQRCodeModal(modelData.ssid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
iconName: isPinned ? "push_pin" : "push_pin"
|
iconName: isPinned ? "push_pin" : "push_pin"
|
||||||
buttonSize: 28
|
buttonSize: 28
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ Item {
|
|||||||
settingKey: "notificationPopupShadowEnabled"
|
settingKey: "notificationPopupShadowEnabled"
|
||||||
tags: ["notification", "popup", "shadow", "radius", "rounded"]
|
tags: ["notification", "popup", "shadow", "radius", "rounded"]
|
||||||
text: I18n.tr("Popup Shadow")
|
text: I18n.tr("Popup Shadow")
|
||||||
description: I18n.tr("Show drop shadow on notification popups. Requires M3 Elevation to be enabled in Theme & Colors.")
|
description: I18n.tr("Show drop shadow on notification popups")
|
||||||
checked: SettingsData.notificationPopupShadowEnabled
|
checked: SettingsData.notificationPopupShadowEnabled
|
||||||
onToggled: checked => SettingsData.set("notificationPopupShadowEnabled", checked)
|
onToggled: checked => SettingsData.set("notificationPopupShadowEnabled", checked)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,15 +126,6 @@ Item {
|
|||||||
return Theme.warning;
|
return Theme.warning;
|
||||||
}
|
}
|
||||||
|
|
||||||
function openM3ShadowColorPicker() {
|
|
||||||
PopoutService.colorPickerModal.selectedColor = SettingsData.m3ElevationCustomColor ?? "#000000";
|
|
||||||
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Shadow Color");
|
|
||||||
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
|
||||||
SettingsData.set("m3ElevationCustomColor", color.toString());
|
|
||||||
};
|
|
||||||
PopoutService.colorPickerModal.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatThemeAutoTime(isoString) {
|
function formatThemeAutoTime(isoString) {
|
||||||
if (!isoString)
|
if (!isoString)
|
||||||
return "";
|
return "";
|
||||||
@@ -1601,189 +1592,6 @@ Item {
|
|||||||
defaultValue: 12
|
defaultValue: 12
|
||||||
onSliderValueChanged: newValue => SettingsData.setCornerRadius(newValue)
|
onSliderValueChanged: newValue => SettingsData.setCornerRadius(newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsToggleRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "lift", "m3", "material"]
|
|
||||||
settingKey: "m3ElevationEnabled"
|
|
||||||
text: I18n.tr("Shadows")
|
|
||||||
description: I18n.tr("Material inspired shadows and elevation on modals, popouts, and dialogs")
|
|
||||||
checked: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onToggled: checked => SettingsData.set("m3ElevationEnabled", checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "intensity", "blur", "m3"]
|
|
||||||
settingKey: "m3ElevationIntensity"
|
|
||||||
text: I18n.tr("Shadow Intensity")
|
|
||||||
description: I18n.tr("Controls the base blur radius and offset of shadows")
|
|
||||||
value: SettingsData.m3ElevationIntensity ?? 12
|
|
||||||
minimum: 0
|
|
||||||
maximum: 100
|
|
||||||
unit: "px"
|
|
||||||
defaultValue: 12
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onSliderValueChanged: newValue => SettingsData.set("m3ElevationIntensity", newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "opacity", "transparency", "m3"]
|
|
||||||
settingKey: "m3ElevationOpacity"
|
|
||||||
text: I18n.tr("Shadow Opacity")
|
|
||||||
description: I18n.tr("Controls the transparency of the shadow")
|
|
||||||
value: SettingsData.m3ElevationOpacity ?? 30
|
|
||||||
minimum: 0
|
|
||||||
maximum: 100
|
|
||||||
unit: "%"
|
|
||||||
defaultValue: 30
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onSliderValueChanged: newValue => SettingsData.set("m3ElevationOpacity", newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsDropdownRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "color", "m3"]
|
|
||||||
settingKey: "m3ElevationColorMode"
|
|
||||||
text: I18n.tr("Shadow Color")
|
|
||||||
description: I18n.tr("Base color for shadows (opacity is applied automatically)")
|
|
||||||
options: [I18n.tr("Default (Black)", "shadow color option"), I18n.tr("Text Color", "shadow color option"), I18n.tr("Primary", "shadow color option"), I18n.tr("Surface Variant", "shadow color option"), I18n.tr("Custom", "shadow color option")]
|
|
||||||
currentValue: {
|
|
||||||
switch (SettingsData.m3ElevationColorMode) {
|
|
||||||
case "text":
|
|
||||||
return I18n.tr("Text Color", "shadow color option");
|
|
||||||
case "primary":
|
|
||||||
return I18n.tr("Primary", "shadow color option");
|
|
||||||
case "surfaceVariant":
|
|
||||||
return I18n.tr("Surface Variant", "shadow color option");
|
|
||||||
case "custom":
|
|
||||||
return I18n.tr("Custom", "shadow color option");
|
|
||||||
default:
|
|
||||||
return I18n.tr("Default (Black)", "shadow color option");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onValueChanged: value => {
|
|
||||||
if (value === I18n.tr("Primary", "shadow color option")) {
|
|
||||||
SettingsData.set("m3ElevationColorMode", "primary");
|
|
||||||
} else if (value === I18n.tr("Surface Variant", "shadow color option")) {
|
|
||||||
SettingsData.set("m3ElevationColorMode", "surfaceVariant");
|
|
||||||
} else if (value === I18n.tr("Custom", "shadow color option")) {
|
|
||||||
SettingsData.set("m3ElevationColorMode", "custom");
|
|
||||||
openM3ShadowColorPicker();
|
|
||||||
} else if (value === I18n.tr("Text Color", "shadow color option")) {
|
|
||||||
SettingsData.set("m3ElevationColorMode", "text");
|
|
||||||
} else {
|
|
||||||
SettingsData.set("m3ElevationColorMode", "default");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsDropdownRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "direction", "light", "advanced", "m3"]
|
|
||||||
settingKey: "m3ElevationLightDirection"
|
|
||||||
text: I18n.tr("Light Direction")
|
|
||||||
description: I18n.tr("Controls shadow cast direction for elevation layers")
|
|
||||||
options: [I18n.tr("Auto (Bar-aware)", "shadow direction option"), I18n.tr("Top (Default)", "shadow direction option"), I18n.tr("Top Left", "shadow direction option"), I18n.tr("Top Right", "shadow direction option"), I18n.tr("Bottom", "shadow direction option")]
|
|
||||||
currentValue: {
|
|
||||||
switch (SettingsData.m3ElevationLightDirection) {
|
|
||||||
case "autoBar":
|
|
||||||
return I18n.tr("Auto (Bar-aware)", "shadow direction option");
|
|
||||||
case "topLeft":
|
|
||||||
return I18n.tr("Top Left", "shadow direction option");
|
|
||||||
case "topRight":
|
|
||||||
return I18n.tr("Top Right", "shadow direction option");
|
|
||||||
case "bottom":
|
|
||||||
return I18n.tr("Bottom", "shadow direction option");
|
|
||||||
default:
|
|
||||||
return I18n.tr("Top (Default)", "shadow direction option");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onValueChanged: value => {
|
|
||||||
if (value === I18n.tr("Auto (Bar-aware)", "shadow direction option")) {
|
|
||||||
SettingsData.set("m3ElevationLightDirection", "autoBar");
|
|
||||||
} else if (value === I18n.tr("Top Left", "shadow direction option")) {
|
|
||||||
SettingsData.set("m3ElevationLightDirection", "topLeft");
|
|
||||||
} else if (value === I18n.tr("Top Right", "shadow direction option")) {
|
|
||||||
SettingsData.set("m3ElevationLightDirection", "topRight");
|
|
||||||
} else if (value === I18n.tr("Bottom", "shadow direction option")) {
|
|
||||||
SettingsData.set("m3ElevationLightDirection", "bottom");
|
|
||||||
} else {
|
|
||||||
SettingsData.set("m3ElevationLightDirection", "top");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
visible: (SettingsData.m3ElevationEnabled ?? true) && SettingsData.m3ElevationColorMode === "custom"
|
|
||||||
width: parent.width
|
|
||||||
implicitHeight: 36
|
|
||||||
height: implicitHeight
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Custom Shadow Color")
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 26
|
|
||||||
height: 26
|
|
||||||
radius: 13
|
|
||||||
color: SettingsData.m3ElevationCustomColor ?? "#000000"
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: openM3ShadowColorPicker()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsToggleRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "modal", "dialog", "m3"]
|
|
||||||
settingKey: "modalElevationEnabled"
|
|
||||||
text: I18n.tr("Modal Shadows")
|
|
||||||
description: I18n.tr("Shadow elevation on modals and dialogs")
|
|
||||||
checked: SettingsData.modalElevationEnabled ?? true
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onToggled: checked => SettingsData.set("modalElevationEnabled", checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsToggleRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "popout", "popup", "osd", "dropdown", "m3"]
|
|
||||||
settingKey: "popoutElevationEnabled"
|
|
||||||
text: I18n.tr("Popout Shadows")
|
|
||||||
description: I18n.tr("Shadow elevation on popouts, OSDs, and dropdowns")
|
|
||||||
checked: SettingsData.popoutElevationEnabled ?? true
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onToggled: checked => SettingsData.set("popoutElevationEnabled", checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsToggleRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["elevation", "shadow", "bar", "panel", "navigation", "m3"]
|
|
||||||
settingKey: "barElevationEnabled"
|
|
||||||
text: I18n.tr("Bar Shadows")
|
|
||||||
description: I18n.tr("Shadow elevation on bars and panels")
|
|
||||||
checked: SettingsData.barElevationEnabled ?? true
|
|
||||||
visible: SettingsData.m3ElevationEnabled ?? true
|
|
||||||
onToggled: checked => SettingsData.set("barElevationEnabled", checked)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
@@ -2329,40 +2137,12 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["icon", "theme", "system"]
|
|
||||||
title: I18n.tr("Icon Theme")
|
|
||||||
settingKey: "iconTheme"
|
|
||||||
|
|
||||||
SettingsDropdownRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["icon", "theme", "system"]
|
|
||||||
settingKey: "iconTheme"
|
|
||||||
text: I18n.tr("Icon Theme")
|
|
||||||
description: I18n.tr("DankShell & System Icons (requires restart)")
|
|
||||||
currentValue: SettingsData.iconTheme
|
|
||||||
enableFuzzySearch: true
|
|
||||||
popupWidthOffset: 100
|
|
||||||
maxPopupHeight: 236
|
|
||||||
options: cachedIconThemes
|
|
||||||
onValueChanged: value => {
|
|
||||||
SettingsData.setIconTheme(value);
|
|
||||||
if (Quickshell.env("QT_QPA_PLATFORMTHEME") != "gtk3" && Quickshell.env("QT_QPA_PLATFORMTHEME") != "qt6ct" && Quickshell.env("QT_QPA_PLATFORMTHEME_QT6") != "qt6ct") {
|
|
||||||
ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
tab: "theme"
|
tab: "theme"
|
||||||
tags: ["matugen", "templates", "theming"]
|
tags: ["matugen", "templates", "theming"]
|
||||||
title: I18n.tr("Matugen Templates")
|
title: I18n.tr("Matugen Templates")
|
||||||
settingKey: "matugenTemplates"
|
settingKey: "matugenTemplates"
|
||||||
iconName: "auto_awesome"
|
iconName: "auto_awesome"
|
||||||
collapsible: true
|
|
||||||
expanded: false
|
|
||||||
visible: Theme.matugenAvailable
|
visible: Theme.matugenAvailable
|
||||||
|
|
||||||
SettingsToggleRow {
|
SettingsToggleRow {
|
||||||
@@ -2667,6 +2447,32 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsCard {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["icon", "theme", "system"]
|
||||||
|
title: I18n.tr("Icon Theme")
|
||||||
|
settingKey: "iconTheme"
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["icon", "theme", "system"]
|
||||||
|
settingKey: "iconTheme"
|
||||||
|
text: I18n.tr("Icon Theme")
|
||||||
|
description: I18n.tr("DankShell & System Icons (requires restart)")
|
||||||
|
currentValue: SettingsData.iconTheme
|
||||||
|
enableFuzzySearch: true
|
||||||
|
popupWidthOffset: 100
|
||||||
|
maxPopupHeight: 236
|
||||||
|
options: cachedIconThemes
|
||||||
|
onValueChanged: value => {
|
||||||
|
SettingsData.setIconTheme(value);
|
||||||
|
if (Quickshell.env("QT_QPA_PLATFORMTHEME") != "gtk3" && Quickshell.env("QT_QPA_PLATFORMTHEME") != "qt6ct" && Quickshell.env("QT_QPA_PLATFORMTHEME_QT6") != "qt6ct") {
|
||||||
|
ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
tab: "theme"
|
tab: "theme"
|
||||||
tags: ["system", "app", "theming", "gtk", "qt"]
|
tags: ["system", "app", "theming", "gtk", "qt"]
|
||||||
|
|||||||
@@ -663,15 +663,14 @@ Item {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
layer.enabled: Theme.elevationEnabled
|
layer.enabled: true
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: Theme.elevationEnabled
|
shadowEnabled: true
|
||||||
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel1)
|
shadowHorizontalOffset: 0
|
||||||
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel1, 1)
|
shadowVerticalOffset: 4
|
||||||
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined ? Theme.elevationLevel1.blurPx : 4) / Theme.elevationBlurMax)) : 0
|
shadowBlur: 0.8
|
||||||
blurMax: Theme.elevationBlurMax
|
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
||||||
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel1)
|
shadowOpacity: 0.2
|
||||||
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -216,15 +216,6 @@ Rectangle {
|
|||||||
onToggled: checked => root.updateConfig("showMemoryGraph", checked)
|
onToggled: checked => root.updateConfig("showMemoryGraph", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
DankToggle {
|
|
||||||
width: parent.width - Theme.spacingM * 2
|
|
||||||
x: Theme.spacingM
|
|
||||||
text: I18n.tr("Show Memory in GB")
|
|
||||||
visible: root.cfg.showMemory
|
|
||||||
checked: root.cfg.showInGb ?? false
|
|
||||||
onToggled: checked => root.updateConfig("showInGb", checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsDivider {}
|
SettingsDivider {}
|
||||||
|
|
||||||
DankToggle {
|
DankToggle {
|
||||||
|
|||||||
@@ -398,14 +398,10 @@ Item {
|
|||||||
widgetObj.runningAppsCurrentWorkspace = SettingsData.runningAppsCurrentWorkspace;
|
widgetObj.runningAppsCurrentWorkspace = SettingsData.runningAppsCurrentWorkspace;
|
||||||
widgetObj.runningAppsCurrentMonitor = false;
|
widgetObj.runningAppsCurrentMonitor = false;
|
||||||
}
|
}
|
||||||
if (widgetId === "diskUsage") {
|
if (widgetId === "diskUsage")
|
||||||
widgetObj.mountPath = "/";
|
widgetObj.mountPath = "/";
|
||||||
widgetObj.diskUsageMode = 0;
|
|
||||||
}
|
|
||||||
if (widgetId === "cpuUsage" || widgetId === "memUsage" || widgetId === "cpuTemp" || widgetId === "gpuTemp")
|
if (widgetId === "cpuUsage" || widgetId === "memUsage" || widgetId === "cpuTemp" || widgetId === "gpuTemp")
|
||||||
widgetObj.minimumWidth = true;
|
widgetObj.minimumWidth = true;
|
||||||
if (widgetId === "memUsage")
|
|
||||||
widgetObj.showInGb = false;
|
|
||||||
|
|
||||||
var widgets = getWidgetsForSection(targetSection).slice();
|
var widgets = getWidgetsForSection(targetSection).slice();
|
||||||
widgets.push(widgetObj);
|
widgets.push(widgetObj);
|
||||||
@@ -429,7 +425,7 @@ Item {
|
|||||||
"id": widget.id,
|
"id": widget.id,
|
||||||
"enabled": widget.enabled
|
"enabled": widget.enabled
|
||||||
};
|
};
|
||||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
||||||
for (var i = 0; i < keys.length; i++) {
|
for (var i = 0; i < keys.length; i++) {
|
||||||
if (widget[keys[i]] !== undefined)
|
if (widget[keys[i]] !== undefined)
|
||||||
result[keys[i]] = widget[keys[i]];
|
result[keys[i]] = widget[keys[i]];
|
||||||
@@ -540,30 +536,6 @@ Item {
|
|||||||
setWidgetsForSection(sectionId, widgets);
|
setWidgetsForSection(sectionId, widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleShowInGbChanged(sectionId, widgetIndex, enabled) {
|
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
|
||||||
newWidget.showInGb = enabled;
|
|
||||||
widgets[widgetIndex] = newWidget;
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDiskUsageModeChanged(sectionId, widgetIndex, mode) {
|
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var newWidget = cloneWidgetData(widgets[widgetIndex]);
|
|
||||||
newWidget.diskUsageMode = mode;
|
|
||||||
widgets[widgetIndex] = newWidget;
|
|
||||||
setWidgetsForSection(sectionId, widgets);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value) {
|
function handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value) {
|
||||||
var widgets = getWidgetsForSection(sectionId).slice();
|
var widgets = getWidgetsForSection(sectionId).slice();
|
||||||
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
if (widgetIndex < 0 || widgetIndex >= widgets.length) {
|
||||||
@@ -629,8 +601,6 @@ Item {
|
|||||||
item.pciId = widget.pciId;
|
item.pciId = widget.pciId;
|
||||||
if (widget.mountPath !== undefined)
|
if (widget.mountPath !== undefined)
|
||||||
item.mountPath = widget.mountPath;
|
item.mountPath = widget.mountPath;
|
||||||
if (widget.diskUsageMode !== undefined)
|
|
||||||
item.diskUsageMode = widget.diskUsageMode;
|
|
||||||
if (widget.showNetworkIcon !== undefined)
|
if (widget.showNetworkIcon !== undefined)
|
||||||
item.showNetworkIcon = widget.showNetworkIcon;
|
item.showNetworkIcon = widget.showNetworkIcon;
|
||||||
if (widget.showBluetoothIcon !== undefined)
|
if (widget.showBluetoothIcon !== undefined)
|
||||||
@@ -659,8 +629,6 @@ Item {
|
|||||||
item.minimumWidth = widget.minimumWidth;
|
item.minimumWidth = widget.minimumWidth;
|
||||||
if (widget.showSwap !== undefined)
|
if (widget.showSwap !== undefined)
|
||||||
item.showSwap = widget.showSwap;
|
item.showSwap = widget.showSwap;
|
||||||
if (widget.showInGb !== undefined)
|
|
||||||
item.showInGb = widget.showInGb;
|
|
||||||
if (widget.mediaSize !== undefined)
|
if (widget.mediaSize !== undefined)
|
||||||
item.mediaSize = widget.mediaSize;
|
item.mediaSize = widget.mediaSize;
|
||||||
if (widget.clockCompactMode !== undefined)
|
if (widget.clockCompactMode !== undefined)
|
||||||
@@ -957,12 +925,6 @@ Item {
|
|||||||
onShowSwapChanged: (sectionId, index, enabled) => {
|
onShowSwapChanged: (sectionId, index, enabled) => {
|
||||||
widgetsTab.handleShowSwapChanged(sectionId, index, enabled);
|
widgetsTab.handleShowSwapChanged(sectionId, index, enabled);
|
||||||
}
|
}
|
||||||
onShowInGbChanged: (sectionId, index, enabled) => {
|
|
||||||
widgetsTab.handleShowInGbChanged(sectionId, index, enabled);
|
|
||||||
}
|
|
||||||
onDiskUsageModeChanged: (sectionId, widgetIndex, mode) => {
|
|
||||||
widgetsTab.handleDiskUsageModeChanged(sectionId, widgetIndex, mode);
|
|
||||||
}
|
|
||||||
onCompactModeChanged: (widgetId, value) => {
|
onCompactModeChanged: (widgetId, value) => {
|
||||||
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
||||||
}
|
}
|
||||||
@@ -1021,12 +983,6 @@ Item {
|
|||||||
onShowSwapChanged: (sectionId, index, enabled) => {
|
onShowSwapChanged: (sectionId, index, enabled) => {
|
||||||
widgetsTab.handleShowSwapChanged(sectionId, index, enabled);
|
widgetsTab.handleShowSwapChanged(sectionId, index, enabled);
|
||||||
}
|
}
|
||||||
onShowInGbChanged: (sectionId, index, enabled) => {
|
|
||||||
widgetsTab.handleShowInGbChanged(sectionId, index, enabled);
|
|
||||||
}
|
|
||||||
onDiskUsageModeChanged: (sectionId, widgetIndex, mode) => {
|
|
||||||
widgetsTab.handleDiskUsageModeChanged(sectionId, widgetIndex, mode);
|
|
||||||
}
|
|
||||||
onCompactModeChanged: (widgetId, value) => {
|
onCompactModeChanged: (widgetId, value) => {
|
||||||
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
||||||
}
|
}
|
||||||
@@ -1085,12 +1041,6 @@ Item {
|
|||||||
onShowSwapChanged: (sectionId, index, enabled) => {
|
onShowSwapChanged: (sectionId, index, enabled) => {
|
||||||
widgetsTab.handleShowSwapChanged(sectionId, index, enabled);
|
widgetsTab.handleShowSwapChanged(sectionId, index, enabled);
|
||||||
}
|
}
|
||||||
onShowInGbChanged: (sectionId, index, enabled) => {
|
|
||||||
widgetsTab.handleShowInGbChanged(sectionId, index, enabled);
|
|
||||||
}
|
|
||||||
onDiskUsageModeChanged: (sectionId, widgetIndex, mode) => {
|
|
||||||
widgetsTab.handleDiskUsageModeChanged(sectionId, widgetIndex, mode);
|
|
||||||
}
|
|
||||||
onCompactModeChanged: (widgetId, value) => {
|
onCompactModeChanged: (widgetId, value) => {
|
||||||
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ Column {
|
|||||||
signal privacySettingChanged(string sectionId, int widgetIndex, string settingName, bool value)
|
signal privacySettingChanged(string sectionId, int widgetIndex, string settingName, bool value)
|
||||||
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)
|
||||||
signal showInGbChanged(string sectionId, int widgetIndex, bool enabled)
|
|
||||||
signal diskUsageModeChanged(string sectionId, int widgetIndex, int mode)
|
|
||||||
signal overflowSettingChanged(string sectionId, int widgetIndex, string settingName, var value)
|
signal overflowSettingChanged(string sectionId, int widgetIndex, string settingName, var value)
|
||||||
|
|
||||||
function cloneWidgetData(widget) {
|
function cloneWidgetData(widget) {
|
||||||
@@ -39,7 +37,7 @@ Column {
|
|||||||
"id": widget.id,
|
"id": widget.id,
|
||||||
"enabled": widget.enabled
|
"enabled": widget.enabled
|
||||||
};
|
};
|
||||||
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "minimumWidth", "showSwap", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge"];
|
||||||
for (var i = 0; i < keys.length; i++) {
|
for (var i = 0; i < keys.length; i++) {
|
||||||
if (widget[keys[i]] !== undefined)
|
if (widget[keys[i]] !== undefined)
|
||||||
result[keys[i]] = widget[keys[i]];
|
result[keys[i]] = widget[keys[i]];
|
||||||
@@ -69,6 +67,53 @@ Column {
|
|||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
height: 1
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
visible: root.sectionId === "center"
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: indexCenterButton
|
||||||
|
buttonSize: 28
|
||||||
|
iconName: "format_list_numbered"
|
||||||
|
iconSize: 16
|
||||||
|
iconColor: SettingsData.centeringMode === "index" ? Theme.primary : Theme.outline
|
||||||
|
onClicked: {
|
||||||
|
console.log("Centering mode changed to: index");
|
||||||
|
SettingsData.set("centeringMode", "index");
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
sharedTooltip.show("Index Centering", indexCenterButton, 0, 0, "bottom");
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
sharedTooltip.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: geometricCenterButton
|
||||||
|
buttonSize: 28
|
||||||
|
iconName: "center_focus_weak"
|
||||||
|
iconSize: 16
|
||||||
|
iconColor: SettingsData.centeringMode === "geometric" ? Theme.primary : Theme.outline
|
||||||
|
onClicked: {
|
||||||
|
console.log("Centering mode changed to: geometric");
|
||||||
|
SettingsData.set("centeringMode", "geometric");
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
sharedTooltip.show("Geometric Centering", geometricCenterButton, 0, 0, "bottom");
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
sharedTooltip.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -90,7 +135,6 @@ Column {
|
|||||||
height: 70
|
height: 70
|
||||||
z: held ? 2 : 1
|
z: held ? 2 : 1
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: itemBackground
|
id: itemBackground
|
||||||
|
|
||||||
@@ -231,34 +275,6 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
id: diskMenuButton
|
|
||||||
visible: modelData.id === "diskUsage"
|
|
||||||
buttonSize: 32
|
|
||||||
iconName: "more_vert"
|
|
||||||
iconSize: 18
|
|
||||||
iconColor: Theme.outline
|
|
||||||
onClicked: {
|
|
||||||
diskUsageContextMenu.widgetData = modelData;
|
|
||||||
diskUsageContextMenu.sectionId = root.sectionId;
|
|
||||||
diskUsageContextMenu.widgetIndex = index;
|
|
||||||
|
|
||||||
var buttonPos = diskMenuButton.mapToItem(root, 0, 0);
|
|
||||||
var xPos = buttonPos.x - diskUsageContextMenu.width - Theme.spacingS;
|
|
||||||
if (xPos < 0)
|
|
||||||
xPos = buttonPos.x + diskMenuButton.width + Theme.spacingS;
|
|
||||||
var yPos = buttonPos.y - diskUsageContextMenu.height / 2 + diskMenuButton.height / 2;
|
|
||||||
if (yPos < 0)
|
|
||||||
yPos = Theme.spacingS;
|
|
||||||
else if (yPos + diskUsageContextMenu.height > root.height)
|
|
||||||
yPos = root.height - diskUsageContextMenu.height - Theme.spacingS;
|
|
||||||
|
|
||||||
diskUsageContextMenu.x = xPos;
|
|
||||||
diskUsageContextMenu.y = yPos;
|
|
||||||
diskUsageContextMenu.open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: 32
|
width: 32
|
||||||
height: 32
|
height: 32
|
||||||
@@ -338,36 +354,23 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
id: memMenuButton
|
id: showSwapButton
|
||||||
|
buttonSize: 28
|
||||||
visible: modelData.id === "memUsage"
|
visible: modelData.id === "memUsage"
|
||||||
buttonSize: 32
|
iconName: "swap_horiz"
|
||||||
iconName: "more_vert"
|
iconSize: 16
|
||||||
iconSize: 18
|
iconColor: (modelData.showSwap !== undefined ? modelData.showSwap : false) ? Theme.primary : Theme.outline
|
||||||
iconColor: Theme.outline
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
memUsageContextMenu.widgetData = modelData;
|
var currentEnabled = modelData.showSwap !== undefined ? modelData.showSwap : false;
|
||||||
memUsageContextMenu.sectionId = root.sectionId;
|
root.showSwapChanged(root.sectionId, index, !currentEnabled);
|
||||||
memUsageContextMenu.widgetIndex = index;
|
}
|
||||||
|
onEntered: {
|
||||||
var buttonPos = memMenuButton.mapToItem(root, 0, 0);
|
var currentEnabled = modelData.showSwap !== undefined ? modelData.showSwap : false;
|
||||||
var popupWidth = memUsageContextMenu.width;
|
const tooltipText = currentEnabled ? "Hide Swap" : "Show Swap";
|
||||||
var popupHeight = memUsageContextMenu.height;
|
sharedTooltip.show(tooltipText, showSwapButton, 0, 0, "bottom");
|
||||||
|
}
|
||||||
var xPos = buttonPos.x - popupWidth - Theme.spacingS;
|
onExited: {
|
||||||
if (xPos < 0) {
|
sharedTooltip.hide();
|
||||||
xPos = buttonPos.x + memMenuButton.width + Theme.spacingS;
|
|
||||||
}
|
|
||||||
|
|
||||||
var yPos = buttonPos.y - popupHeight / 2 + memMenuButton.height / 2;
|
|
||||||
if (yPos < 0) {
|
|
||||||
yPos = Theme.spacingS;
|
|
||||||
} else if (yPos + popupHeight > root.height) {
|
|
||||||
yPos = root.height - popupHeight - Theme.spacingS;
|
|
||||||
}
|
|
||||||
|
|
||||||
memUsageContextMenu.x = xPos;
|
|
||||||
memUsageContextMenu.y = yPos;
|
|
||||||
memUsageContextMenu.open();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,257 +799,6 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup {
|
|
||||||
id: memUsageContextMenu
|
|
||||||
|
|
||||||
property var widgetData: null
|
|
||||||
property string sectionId: ""
|
|
||||||
property int widgetIndex: -1
|
|
||||||
|
|
||||||
width: 200
|
|
||||||
height: 80
|
|
||||||
padding: 0
|
|
||||||
modal: true
|
|
||||||
focus: true
|
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: Theme.surfaceContainer
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
|
||||||
border.width: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Item {
|
|
||||||
Column {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Theme.spacingS
|
|
||||||
spacing: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 32
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: swapToggleArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "swap_horiz"
|
|
||||||
size: 16
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Show Swap")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Normal
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankToggle {
|
|
||||||
id: swapToggle
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: 40
|
|
||||||
height: 20
|
|
||||||
checked: memUsageContextMenu.widgetData?.showSwap ?? false
|
|
||||||
onToggled: {
|
|
||||||
root.showSwapChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, toggled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: swapToggleArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
swapToggle.checked = !swapToggle.checked;
|
|
||||||
root.showSwapChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, swapToggle.checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 32
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: gbToggleArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: "straighten"
|
|
||||||
size: 16
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Show in GB")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Normal
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankToggle {
|
|
||||||
id: gbToggle
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
width: 40
|
|
||||||
height: 20
|
|
||||||
checked: memUsageContextMenu.widgetData?.showInGb ?? false
|
|
||||||
onToggled: {
|
|
||||||
root.showInGbChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, toggled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: gbToggleArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onPressed: {
|
|
||||||
gbToggle.checked = !gbToggle.checked;
|
|
||||||
root.showInGbChanged(memUsageContextMenu.sectionId, memUsageContextMenu.widgetIndex, gbToggle.checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Popup {
|
|
||||||
id: diskUsageContextMenu
|
|
||||||
|
|
||||||
property var widgetData: null
|
|
||||||
property string sectionId: ""
|
|
||||||
property int widgetIndex: -1
|
|
||||||
readonly property var currentWidgetData: (widgetIndex >= 0 && widgetIndex < root.items.length) ? root.items[widgetIndex] : widgetData
|
|
||||||
|
|
||||||
width: 240
|
|
||||||
height: diskMenuColumn.implicitHeight + Theme.spacingS * 2
|
|
||||||
padding: 0
|
|
||||||
modal: true
|
|
||||||
focus: true
|
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: Theme.surfaceContainer
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
|
||||||
border.width: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Item {
|
|
||||||
Column {
|
|
||||||
id: diskMenuColumn
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Theme.spacingS
|
|
||||||
spacing: 2
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 32
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: I18n.tr("Disk Usage Display")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
font.weight: Font.Medium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: [
|
|
||||||
{ label: I18n.tr("Percentage"), mode: 0, icon: "percent" },
|
|
||||||
{ label: I18n.tr("Total"), mode: 1, icon: "storage" },
|
|
||||||
{ label: I18n.tr("Remaining"), mode: 2, icon: "hourglass_empty" },
|
|
||||||
{ label: I18n.tr("Remaining / Total"), mode: 3, icon: "pie_chart" }
|
|
||||||
]
|
|
||||||
|
|
||||||
delegate: Rectangle {
|
|
||||||
required property var modelData
|
|
||||||
required property int index
|
|
||||||
|
|
||||||
width: diskMenuColumn.width
|
|
||||||
height: 32
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: diskOptionArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
|
||||||
|
|
||||||
function isSelected() {
|
|
||||||
return (diskUsageContextMenu.currentWidgetData?.diskUsageMode ?? 0) === modelData.mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: modelData.icon
|
|
||||||
size: 16
|
|
||||||
color: isSelected() ? Theme.primary : Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: modelData.label
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: isSelected() ? Theme.primary : Theme.surfaceText
|
|
||||||
font.weight: isSelected() ? Font.Medium : Font.Normal
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
name: "check"
|
|
||||||
size: 16
|
|
||||||
color: Theme.primary
|
|
||||||
visible: isSelected()
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: diskOptionArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
root.diskUsageModeChanged(diskUsageContextMenu.sectionId, diskUsageContextMenu.widgetIndex, modelData.mode);
|
|
||||||
diskUsageContextMenu.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Popup {
|
Popup {
|
||||||
id: controlCenterContextMenu
|
id: controlCenterContextMenu
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -95,6 +96,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
layer.enabled: true
|
||||||
opacity: shouldBeVisible ? 1 : 0
|
opacity: shouldBeVisible ? 1 : 0
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -404,15 +406,13 @@ PanelWindow {
|
|||||||
onClicked: ToastService.hideToast()
|
onClicked: ToastService.hideToast()
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
layer.effect: MultiEffect {
|
||||||
anchors.fill: parent
|
shadowEnabled: true
|
||||||
z: -1
|
shadowHorizontalOffset: 0
|
||||||
level: Theme.elevationLevel3
|
shadowVerticalOffset: 4
|
||||||
fallbackOffset: 6
|
shadowBlur: 0.8
|
||||||
targetRadius: toast.radius
|
shadowColor: Qt.rgba(0, 0, 0, 0.3)
|
||||||
targetColor: toast.color
|
shadowOpacity: 0.3
|
||||||
shadowOpacity: Theme.elevationLevel3 && Theme.elevationLevel3.alpha !== undefined ? Theme.elevationLevel3.alpha : 0.3
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
@@ -16,61 +17,59 @@ Item {
|
|||||||
|
|
||||||
readonly property var allWorkspaces: Hyprland.workspaces?.values || []
|
readonly property var allWorkspaces: Hyprland.workspaces?.values || []
|
||||||
readonly property var allWorkspaceIds: {
|
readonly property var allWorkspaceIds: {
|
||||||
const workspaces = allWorkspaces;
|
const workspaces = allWorkspaces
|
||||||
if (!workspaces || workspaces.length === 0)
|
if (!workspaces || workspaces.length === 0) return []
|
||||||
return [];
|
|
||||||
try {
|
try {
|
||||||
const ids = workspaces.map(ws => ws?.id).filter(id => id !== null && id !== undefined);
|
const ids = workspaces.map(ws => ws?.id).filter(id => id !== null && id !== undefined)
|
||||||
return ids.sort((a, b) => a - b);
|
return ids.sort((a, b) => a - b)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var thisMonitorWorkspaceIds: {
|
readonly property var thisMonitorWorkspaceIds: {
|
||||||
const workspaces = allWorkspaces;
|
const workspaces = allWorkspaces
|
||||||
const mon = monitor;
|
const mon = monitor
|
||||||
if (!workspaces || workspaces.length === 0 || !mon)
|
if (!workspaces || workspaces.length === 0 || !mon) return []
|
||||||
return [];
|
|
||||||
try {
|
try {
|
||||||
const filtered = workspaces.filter(ws => ws?.monitor?.name === mon.name);
|
const filtered = workspaces.filter(ws => ws?.monitor?.name === mon.name)
|
||||||
return filtered.map(ws => ws?.id).filter(id => id !== null && id !== undefined).sort((a, b) => a - b);
|
return filtered.map(ws => ws?.id).filter(id => id !== null && id !== undefined).sort((a, b) => a - b)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var displayedWorkspaceIds: {
|
readonly property var displayedWorkspaceIds: {
|
||||||
if (!allWorkspaceIds || allWorkspaceIds.length === 0) {
|
if (!allWorkspaceIds || allWorkspaceIds.length === 0) {
|
||||||
const result = [];
|
const result = []
|
||||||
for (let i = 1; i <= workspacesShown; i++) {
|
for (let i = 1; i <= workspacesShown; i++) {
|
||||||
result.push(i);
|
result.push(i)
|
||||||
}
|
}
|
||||||
return result;
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const maxExisting = Math.max(...allWorkspaceIds);
|
const maxExisting = Math.max(...allWorkspaceIds)
|
||||||
const totalNeeded = Math.max(workspacesShown, allWorkspaceIds.length);
|
const totalNeeded = Math.max(workspacesShown, allWorkspaceIds.length)
|
||||||
const result = [];
|
const result = []
|
||||||
|
|
||||||
for (let i = 1; i <= maxExisting; i++) {
|
for (let i = 1; i <= maxExisting; i++) {
|
||||||
result.push(i);
|
result.push(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
let nextId = maxExisting + 1;
|
let nextId = maxExisting + 1
|
||||||
while (result.length < totalNeeded) {
|
while (result.length < totalNeeded) {
|
||||||
result.push(nextId);
|
result.push(nextId)
|
||||||
nextId++;
|
nextId++
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const result = [];
|
const result = []
|
||||||
for (let i = 1; i <= workspacesShown; i++) {
|
for (let i = 1; i <= workspacesShown; i++) {
|
||||||
result.push(i);
|
result.push(i)
|
||||||
}
|
}
|
||||||
return result;
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,27 +81,24 @@ Item {
|
|||||||
readonly property int effectiveRows: Math.max(SettingsData.overviewRows, Math.ceil(displayWorkspaceCount / effectiveColumns))
|
readonly property int effectiveRows: Math.max(SettingsData.overviewRows, Math.ceil(displayWorkspaceCount / effectiveColumns))
|
||||||
|
|
||||||
function getWorkspaceMonitorName(workspaceId) {
|
function getWorkspaceMonitorName(workspaceId) {
|
||||||
if (!allWorkspaces || !workspaceId)
|
if (!allWorkspaces || !workspaceId) return ""
|
||||||
return "";
|
|
||||||
try {
|
try {
|
||||||
const ws = allWorkspaces.find(w => w?.id === workspaceId);
|
const ws = allWorkspaces.find(w => w?.id === workspaceId)
|
||||||
return ws?.monitor?.name ?? "";
|
return ws?.monitor?.name ?? ""
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return "";
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function workspaceHasWindows(workspaceId) {
|
function workspaceHasWindows(workspaceId) {
|
||||||
if (!workspaceId)
|
if (!workspaceId) return false
|
||||||
return false;
|
|
||||||
try {
|
try {
|
||||||
const workspace = allWorkspaces.find(ws => ws?.id === workspaceId);
|
const workspace = allWorkspaces.find(ws => ws?.id === workspaceId)
|
||||||
if (!workspace)
|
if (!workspace) return false
|
||||||
return false;
|
const toplevels = workspace?.toplevels?.values || []
|
||||||
const toplevels = workspace?.toplevels?.values || [];
|
return toplevels.length > 0
|
||||||
return toplevels.length > 0;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,16 +124,16 @@ Item {
|
|||||||
implicitHeight: overviewBackground.implicitHeight + Theme.spacingL * 2
|
implicitHeight: overviewBackground.implicitHeight + Theme.spacingL * 2
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Hyprland.refreshToplevels();
|
Hyprland.refreshToplevels()
|
||||||
Hyprland.refreshWorkspaces();
|
Hyprland.refreshWorkspaces()
|
||||||
Hyprland.refreshMonitors();
|
Hyprland.refreshMonitors()
|
||||||
}
|
}
|
||||||
|
|
||||||
onOverviewOpenChanged: {
|
onOverviewOpenChanged: {
|
||||||
if (overviewOpen) {
|
if (overviewOpen) {
|
||||||
Hyprland.refreshToplevels();
|
Hyprland.refreshToplevels()
|
||||||
Hyprland.refreshWorkspaces();
|
Hyprland.refreshWorkspaces()
|
||||||
Hyprland.refreshMonitors();
|
Hyprland.refreshMonitors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,15 +148,15 @@ Item {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceContainer
|
color: Theme.surfaceContainer
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
anchors.fill: parent
|
layer.effect: MultiEffect {
|
||||||
z: -1
|
shadowEnabled: true
|
||||||
level: Theme.elevationLevel2
|
shadowBlur: 0.5
|
||||||
fallbackOffset: 4
|
shadowHorizontalOffset: 0
|
||||||
targetRadius: Theme.cornerRadius
|
shadowVerticalOffset: 4
|
||||||
targetColor: Theme.surfaceContainer
|
shadowColor: Theme.shadowStrong
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
shadowOpacity: 1
|
||||||
shadowEnabled: Theme.elevationEnabled
|
blurMax: 32
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@@ -221,8 +217,8 @@ Item {
|
|||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.draggingTargetWorkspace === -1) {
|
if (root.draggingTargetWorkspace === -1) {
|
||||||
root.overviewOpen = false;
|
root.overviewOpen = false
|
||||||
Hyprland.dispatch(`workspace ${workspaceValue}`);
|
Hyprland.dispatch(`workspace ${workspaceValue}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,15 +226,13 @@ Item {
|
|||||||
DropArea {
|
DropArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onEntered: {
|
onEntered: {
|
||||||
root.draggingTargetWorkspace = workspaceValue;
|
root.draggingTargetWorkspace = workspaceValue
|
||||||
if (root.draggingFromWorkspace == root.draggingTargetWorkspace)
|
if (root.draggingFromWorkspace == root.draggingTargetWorkspace) return
|
||||||
return;
|
hoveredWhileDragging = true
|
||||||
hoveredWhileDragging = true;
|
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
hoveredWhileDragging = false;
|
hoveredWhileDragging = false
|
||||||
if (root.draggingTargetWorkspace == workspaceValue)
|
if (root.draggingTargetWorkspace == workspaceValue) root.draggingTargetWorkspace = -1
|
||||||
root.draggingTargetWorkspace = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,28 +250,27 @@ Item {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
values: {
|
values: {
|
||||||
const workspaces = root.allWorkspaces;
|
const workspaces = root.allWorkspaces
|
||||||
const minId = root.minWorkspaceId;
|
const minId = root.minWorkspaceId
|
||||||
const maxId = root.maxWorkspaceId;
|
const maxId = root.maxWorkspaceId
|
||||||
|
|
||||||
if (!workspaces || workspaces.length === 0)
|
if (!workspaces || workspaces.length === 0) return []
|
||||||
return [];
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = [];
|
const result = []
|
||||||
for (const workspace of workspaces) {
|
for (const workspace of workspaces) {
|
||||||
const wsId = workspace?.id ?? -1;
|
const wsId = workspace?.id ?? -1
|
||||||
if (wsId >= minId && wsId <= maxId) {
|
if (wsId >= minId && wsId <= maxId) {
|
||||||
const toplevels = workspace?.toplevels?.values || [];
|
const toplevels = workspace?.toplevels?.values || []
|
||||||
for (const toplevel of toplevels) {
|
for (const toplevel of toplevels) {
|
||||||
result.push(toplevel);
|
result.push(toplevel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("OverviewWidget filter error:", e);
|
console.error("OverviewWidget filter error:", e)
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,19 +282,17 @@ Item {
|
|||||||
readonly property int windowWorkspaceId: modelData?.workspace?.id ?? -1
|
readonly property int windowWorkspaceId: modelData?.workspace?.id ?? -1
|
||||||
|
|
||||||
function getWorkspaceIndex() {
|
function getWorkspaceIndex() {
|
||||||
if (!root.displayedWorkspaceIds || root.displayedWorkspaceIds.length === 0)
|
if (!root.displayedWorkspaceIds || root.displayedWorkspaceIds.length === 0) return 0
|
||||||
return 0;
|
if (!windowWorkspaceId || windowWorkspaceId < 0) return 0
|
||||||
if (!windowWorkspaceId || windowWorkspaceId < 0)
|
|
||||||
return 0;
|
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i < root.displayedWorkspaceIds.length; i++) {
|
for (let i = 0; i < root.displayedWorkspaceIds.length; i++) {
|
||||||
if (root.displayedWorkspaceIds[i] === windowWorkspaceId) {
|
if (root.displayedWorkspaceIds[i] === windowWorkspaceId) {
|
||||||
return i;
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,48 +325,48 @@ Item {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
||||||
drag.target: parent
|
drag.target: parent
|
||||||
|
|
||||||
onPressed: mouse => {
|
onPressed: (mouse) => {
|
||||||
root.draggingFromWorkspace = windowData?.workspace.id;
|
root.draggingFromWorkspace = windowData?.workspace.id
|
||||||
window.pressed = true;
|
window.pressed = true
|
||||||
window.Drag.active = true;
|
window.Drag.active = true
|
||||||
window.Drag.source = window;
|
window.Drag.source = window
|
||||||
window.Drag.hotSpot.x = mouse.x;
|
window.Drag.hotSpot.x = mouse.x
|
||||||
window.Drag.hotSpot.y = mouse.y;
|
window.Drag.hotSpot.y = mouse.y
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: {
|
onReleased: {
|
||||||
const targetWorkspace = root.draggingTargetWorkspace;
|
const targetWorkspace = root.draggingTargetWorkspace
|
||||||
window.pressed = false;
|
window.pressed = false
|
||||||
window.Drag.active = false;
|
window.Drag.active = false
|
||||||
root.draggingFromWorkspace = -1;
|
root.draggingFromWorkspace = -1
|
||||||
root.draggingTargetWorkspace = -1;
|
root.draggingTargetWorkspace = -1
|
||||||
|
|
||||||
if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
|
if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
|
||||||
Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace},address:${windowData?.address}`);
|
Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace},address:${windowData?.address}`)
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
Hyprland.refreshToplevels();
|
Hyprland.refreshToplevels()
|
||||||
Hyprland.refreshWorkspaces();
|
Hyprland.refreshWorkspaces()
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
window.x = window.initX;
|
window.x = window.initX
|
||||||
window.y = window.initY;
|
window.y = window.initY
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
window.x = window.initX;
|
window.x = window.initX
|
||||||
window.y = window.initY;
|
window.y = window.initY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: event => {
|
onClicked: (event) => {
|
||||||
if (!windowData || !windowData.address)
|
if (!windowData || !windowData.address) return
|
||||||
return;
|
|
||||||
if (event.button === Qt.LeftButton) {
|
if (event.button === Qt.LeftButton) {
|
||||||
root.overviewOpen = false;
|
root.overviewOpen = false
|
||||||
Hyprland.dispatch(`focuswindow address:${windowData.address}`);
|
Hyprland.dispatch(`focuswindow address:${windowData.address}`)
|
||||||
event.accepted = true;
|
event.accepted = true
|
||||||
} else if (event.button === Qt.MiddleButton) {
|
} else if (event.button === Qt.MiddleButton) {
|
||||||
Hyprland.dispatch(`closewindow address:${windowData.address}`);
|
Hyprland.dispatch(`closewindow address:${windowData.address}`)
|
||||||
event.accepted = true;
|
event.accepted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property string currentVersion: "1.4"
|
readonly property string currentVersion: "1.4"
|
||||||
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
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtCore
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
@@ -11,9 +13,6 @@ Singleton {
|
|||||||
|
|
||||||
property bool dsearchAvailable: false
|
property bool dsearchAvailable: false
|
||||||
property int searchIdCounter: 0
|
property int searchIdCounter: 0
|
||||||
property int indexVersion: 0
|
|
||||||
property bool supportsTypeFilter: false
|
|
||||||
property bool versionChecked: false
|
|
||||||
|
|
||||||
signal searchResultsReceived(var results)
|
signal searchResultsReceived(var results)
|
||||||
signal statsReceived(var stats)
|
signal statsReceived(var stats)
|
||||||
@@ -27,157 +26,118 @@ Singleton {
|
|||||||
stdout: SplitParser {
|
stdout: SplitParser {
|
||||||
onRead: line => {
|
onRead: line => {
|
||||||
if (line && line.trim().length > 0) {
|
if (line && line.trim().length > 0) {
|
||||||
root.dsearchAvailable = true;
|
root.dsearchAvailable = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
root.dsearchAvailable = false;
|
root.dsearchAvailable = false
|
||||||
} else {
|
|
||||||
root._checkVersion();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _checkVersion() {
|
|
||||||
Proc.runCommand("dsearch-version", ["dsearch", "version", "--json"], (stdout, exitCode) => {
|
|
||||||
root.versionChecked = true;
|
|
||||||
if (exitCode !== 0)
|
|
||||||
return;
|
|
||||||
const response = JSON.parse(stdout);
|
|
||||||
root.indexVersion = response.index_schema || 0;
|
|
||||||
root.supportsTypeFilter = root.indexVersion >= 2;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function ping(callback) {
|
function ping(callback) {
|
||||||
if (!dsearchAvailable) {
|
if (!dsearchAvailable) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "error": "dsearch not available" })
|
||||||
"error": "dsearch not available"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Proc.runCommand("dsearch-ping", ["dsearch", "ping", "--json"], (stdout, exitCode) => {
|
Proc.runCommand("dsearch-ping", ["dsearch", "ping", "--json"], (stdout, exitCode) => {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(stdout);
|
const response = JSON.parse(stdout)
|
||||||
callback({
|
callback({ "result": response })
|
||||||
"result": response
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
callback({
|
callback({ "error": "failed to parse ping response" })
|
||||||
"error": "failed to parse ping response"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback({
|
callback({ "error": "ping failed" })
|
||||||
"error": "ping failed"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(query, params, callback) {
|
function search(query, params, callback) {
|
||||||
if (!query || query.length === 0) {
|
if (!query || query.length === 0) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "error": "query is required" })
|
||||||
"error": "query is required"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dsearchAvailable) {
|
if (!dsearchAvailable) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "error": "dsearch not available" })
|
||||||
"error": "dsearch not available"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = ["dsearch", "search", query, "--json"];
|
const args = ["dsearch", "search", query, "--json"]
|
||||||
|
|
||||||
if (params) {
|
if (params) {
|
||||||
if (params.limit !== undefined) {
|
if (params.limit !== undefined) {
|
||||||
args.push("-n", String(params.limit));
|
args.push("-n", String(params.limit))
|
||||||
}
|
|
||||||
if (params.type) {
|
|
||||||
args.push("-t", params.type);
|
|
||||||
}
|
}
|
||||||
if (params.ext) {
|
if (params.ext) {
|
||||||
args.push("-e", params.ext);
|
args.push("-e", params.ext)
|
||||||
}
|
|
||||||
if (params.folder) {
|
|
||||||
args.push("--folder", params.folder);
|
|
||||||
}
|
}
|
||||||
if (params.field) {
|
if (params.field) {
|
||||||
args.push("-f", params.field);
|
args.push("-f", params.field)
|
||||||
}
|
}
|
||||||
if (params.fuzzy) {
|
if (params.fuzzy) {
|
||||||
args.push("--fuzzy");
|
args.push("--fuzzy")
|
||||||
}
|
}
|
||||||
if (params.sort) {
|
if (params.sort) {
|
||||||
args.push("--sort", params.sort);
|
args.push("--sort", params.sort)
|
||||||
}
|
}
|
||||||
if (params.desc !== undefined) {
|
if (params.desc !== undefined) {
|
||||||
args.push("--desc=" + (params.desc ? "true" : "false"));
|
args.push("--desc=" + (params.desc ? "true" : "false"))
|
||||||
}
|
}
|
||||||
if (params.minSize !== undefined) {
|
if (params.minSize !== undefined) {
|
||||||
args.push("--min-size", String(params.minSize));
|
args.push("--min-size", String(params.minSize))
|
||||||
}
|
}
|
||||||
if (params.maxSize !== undefined) {
|
if (params.maxSize !== undefined) {
|
||||||
args.push("--max-size", String(params.maxSize));
|
args.push("--max-size", String(params.maxSize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Proc.runCommand("dsearch-search", args, (stdout, exitCode) => {
|
Proc.runCommand("dsearch-search", args, (stdout, exitCode) => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(stdout);
|
const response = JSON.parse(stdout)
|
||||||
searchResultsReceived(response);
|
searchResultsReceived(response)
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "result": response })
|
||||||
"result": response
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const error = "failed to parse search response";
|
const error = "failed to parse search response"
|
||||||
errorOccurred(error);
|
errorOccurred(error)
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "error": error })
|
||||||
"error": error
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (exitCode === 124) {
|
} else if (exitCode === 124) {
|
||||||
const error = "search timed out";
|
const error = "search timed out"
|
||||||
errorOccurred(error);
|
errorOccurred(error)
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "error": error })
|
||||||
"error": error
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const error = "search failed";
|
const error = "search failed"
|
||||||
errorOccurred(error);
|
errorOccurred(error)
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({ "error": error })
|
||||||
"error": error
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 100, 5000);
|
}, 100, 5000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function rediscover() {
|
function rediscover() {
|
||||||
checkProcess.running = true;
|
checkProcess.running = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ Singleton {
|
|||||||
property var notificationModal: null
|
property var notificationModal: null
|
||||||
property var wifiPasswordModal: null
|
property var wifiPasswordModal: null
|
||||||
property var wifiPasswordModalLoader: null
|
property var wifiPasswordModalLoader: null
|
||||||
property var wifiQRCodeModal: null
|
|
||||||
property var wifiQRCodeModalLoader: null
|
|
||||||
property var polkitAuthModal: null
|
property var polkitAuthModal: null
|
||||||
property var polkitAuthModalLoader: null
|
property var polkitAuthModalLoader: null
|
||||||
property var bluetoothPairingModal: null
|
property var bluetoothPairingModal: null
|
||||||
@@ -663,13 +661,6 @@ Singleton {
|
|||||||
wifiPasswordModal.show(ssid);
|
wifiPasswordModal.show(ssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showWifiQRCodeModal(ssid) {
|
|
||||||
if (wifiQRCodeModalLoader)
|
|
||||||
wifiQRCodeModalLoader.active = true;
|
|
||||||
if (wifiQRCodeModal)
|
|
||||||
wifiQRCodeModal.show(ssid);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showHiddenNetworkModal() {
|
function showHiddenNetworkModal() {
|
||||||
if (wifiPasswordModalLoader)
|
if (wifiPasswordModalLoader)
|
||||||
wifiPasswordModalLoader.active = true;
|
wifiPasswordModalLoader.active = true;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v1.5-beta
|
v1.4.3
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ Item {
|
|||||||
sourceComponent: IconImage {
|
sourceComponent: IconImage {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: root.iconPath
|
source: root.iconPath
|
||||||
backer.sourceSize: Qt.size(root.iconSize * 2, root.iconSize * 2)
|
backer.sourceSize: Qt.size(root.iconSize, root.iconSize)
|
||||||
mipmap: true
|
mipmap: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
visible: status === Image.Ready
|
visible: status === Image.Ready
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Window
|
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
@@ -19,30 +18,9 @@ Rectangle {
|
|||||||
|
|
||||||
signal imageSaved(string filePath)
|
signal imageSaved(string filePath)
|
||||||
|
|
||||||
property string _pendingSavePath: ""
|
|
||||||
property var _attachedWindow: root.Window.window
|
|
||||||
|
|
||||||
on_AttachedWindowChanged: {
|
|
||||||
if (_attachedWindow && _pendingSavePath !== "") {
|
|
||||||
Qt.callLater(function () {
|
|
||||||
if (root._pendingSavePath !== "") {
|
|
||||||
let path = root._pendingSavePath;
|
|
||||||
root._pendingSavePath = "";
|
|
||||||
root.saveImageToFile(path);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveImageToFile(filePath) {
|
function saveImageToFile(filePath) {
|
||||||
if (activeImage.status !== Image.Ready)
|
if (activeImage.status !== Image.Ready)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!activeImage.Window.window) {
|
|
||||||
_pendingSavePath = filePath;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
activeImage.grabToImage(function (result) {
|
activeImage.grabToImage(function (result) {
|
||||||
if (result && result.saveToFile(filePath)) {
|
if (result && result.saveToFile(filePath)) {
|
||||||
root.imageSaved(filePath);
|
root.imageSaved(filePath);
|
||||||
@@ -81,8 +59,6 @@ Rectangle {
|
|||||||
mipmap: true
|
mipmap: true
|
||||||
cache: true
|
cache: true
|
||||||
visible: false
|
visible: false
|
||||||
sourceSize.width: Math.max(width * 2, 128)
|
|
||||||
sourceSize.height: Math.max(height * 2, 128)
|
|
||||||
source: !root.shouldProbe ? root.imageSource : ""
|
source: !root.shouldProbe ? root.imageSource : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import "../Common/fzf.js" as Fzf
|
import "../Common/fzf.js" as Fzf
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
@@ -253,8 +254,6 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Rectangle {
|
contentItem: Rectangle {
|
||||||
id: contentSurface
|
|
||||||
|
|
||||||
LayoutMirroring.enabled: I18n.isRtl
|
LayoutMirroring.enabled: I18n.isRtl
|
||||||
LayoutMirroring.childrenInherit: true
|
LayoutMirroring.childrenInherit: true
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
|
||||||
@@ -262,17 +261,12 @@ Item {
|
|||||||
border.width: 2
|
border.width: 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
id: shadowLayer
|
layer.effect: MultiEffect {
|
||||||
anchors.fill: parent
|
shadowEnabled: true
|
||||||
z: -1
|
shadowBlur: 0.4
|
||||||
level: Theme.elevationLevel2
|
shadowColor: Theme.shadowStrong
|
||||||
fallbackOffset: 4
|
shadowVerticalOffset: 4
|
||||||
targetRadius: contentSurface.radius
|
|
||||||
targetColor: contentSurface.color
|
|
||||||
borderColor: contentSurface.border.color
|
|
||||||
borderWidth: contentSurface.border.width
|
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -131,20 +132,16 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Rectangle {
|
contentItem: Rectangle {
|
||||||
id: contentSurface
|
|
||||||
color: Theme.surface
|
color: Theme.surface
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
ElevationShadow {
|
layer.enabled: true
|
||||||
id: shadowLayer
|
layer.effect: MultiEffect {
|
||||||
anchors.fill: parent
|
shadowEnabled: true
|
||||||
z: -1
|
shadowColor: Theme.shadowStrong
|
||||||
level: Theme.elevationLevel2
|
shadowBlur: 0.8
|
||||||
fallbackOffset: 4
|
shadowHorizontalOffset: 0
|
||||||
targetRadius: contentSurface.radius
|
shadowVerticalOffset: 4
|
||||||
targetColor: contentSurface.color
|
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
|
||||||
shadowEnabled: Theme.elevationEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -256,7 +257,11 @@ PanelWindow {
|
|||||||
scale: shouldBeVisible ? 1 : 0.9
|
scale: shouldBeVisible ? 1 : 0.9
|
||||||
|
|
||||||
property bool childHovered: false
|
property bool childHovered: false
|
||||||
|
property real shadowBlurPx: 10
|
||||||
|
property real shadowSpreadPx: 0
|
||||||
|
property real shadowBaseAlpha: 0.60
|
||||||
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
||||||
|
readonly property real effectiveShadowAlpha: shouldBeVisible ? Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha)) : 0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: background
|
id: background
|
||||||
@@ -268,20 +273,38 @@ PanelWindow {
|
|||||||
z: -1
|
z: -1
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Item {
|
||||||
id: bgShadowLayer
|
id: bgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: osdContainer.popupSurfaceAlpha >= 0.95
|
visible: osdContainer.popupSurfaceAlpha >= 0.95
|
||||||
z: -1
|
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
level: Theme.elevationLevel3
|
layer.smooth: false
|
||||||
fallbackOffset: 6
|
|
||||||
targetRadius: Theme.cornerRadius
|
|
||||||
targetColor: Theme.surfaceContainer
|
|
||||||
borderColor: Theme.outlineMedium
|
|
||||||
borderWidth: 1
|
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
|
||||||
layer.textureSize: Qt.size(Math.round(width * root.dpr), Math.round(height * root.dpr))
|
layer.textureSize: Qt.size(Math.round(width * root.dpr), Math.round(height * root.dpr))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
|
|
||||||
|
readonly property int blurMax: 64
|
||||||
|
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
id: shadowFx
|
||||||
|
autoPaddingEnabled: true
|
||||||
|
shadowEnabled: true
|
||||||
|
blurEnabled: false
|
||||||
|
maskEnabled: false
|
||||||
|
shadowBlur: Math.max(0, Math.min(1, osdContainer.shadowBlurPx / bgShadowLayer.blurMax))
|
||||||
|
shadowScale: 1 + (2 * osdContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, osdContainer.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
border.color: Theme.outlineMedium
|
||||||
|
border.width: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -30,7 +31,6 @@ Item {
|
|||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
property bool fullHeightSurface: false
|
property bool fullHeightSurface: false
|
||||||
property bool _primeContent: false
|
|
||||||
property bool _resizeActive: false
|
property bool _resizeActive: false
|
||||||
property real _surfaceMarginLeft: 0
|
property real _surfaceMarginLeft: 0
|
||||||
property real _surfaceW: 0
|
property real _surfaceW: 0
|
||||||
@@ -77,38 +77,6 @@ Item {
|
|||||||
|
|
||||||
property int effectiveBarPosition: 0
|
property int effectiveBarPosition: 0
|
||||||
property real effectiveBarBottomGap: 0
|
property real effectiveBarBottomGap: 0
|
||||||
readonly property string autoBarShadowDirection: {
|
|
||||||
const section = triggerSection || "center";
|
|
||||||
switch (effectiveBarPosition) {
|
|
||||||
case SettingsData.Position.Top:
|
|
||||||
if (section === "left")
|
|
||||||
return "topLeft";
|
|
||||||
if (section === "right")
|
|
||||||
return "topRight";
|
|
||||||
return "top";
|
|
||||||
case SettingsData.Position.Bottom:
|
|
||||||
if (section === "left")
|
|
||||||
return "bottomLeft";
|
|
||||||
if (section === "right")
|
|
||||||
return "bottomRight";
|
|
||||||
return "bottom";
|
|
||||||
case SettingsData.Position.Left:
|
|
||||||
if (section === "left")
|
|
||||||
return "topLeft";
|
|
||||||
if (section === "right")
|
|
||||||
return "bottomLeft";
|
|
||||||
return "left";
|
|
||||||
case SettingsData.Position.Right:
|
|
||||||
if (section === "left")
|
|
||||||
return "topRight";
|
|
||||||
if (section === "right")
|
|
||||||
return "bottomRight";
|
|
||||||
return "right";
|
|
||||||
default:
|
|
||||||
return "top";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readonly property string effectiveShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
|
||||||
|
|
||||||
// Snapshot mask geometry to prevent background damage on bar updates
|
// Snapshot mask geometry to prevent background damage on bar updates
|
||||||
property real _frozenMaskX: 0
|
property real _frozenMaskX: 0
|
||||||
@@ -121,14 +89,6 @@ Item {
|
|||||||
effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
|
effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function primeContent() {
|
|
||||||
_primeContent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearPrimedContent() {
|
|
||||||
_primeContent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) {
|
function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) {
|
||||||
triggerX = x;
|
triggerX = x;
|
||||||
triggerY = y;
|
triggerY = y;
|
||||||
@@ -192,7 +152,6 @@ Item {
|
|||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
shouldBeVisible = false;
|
shouldBeVisible = false;
|
||||||
_primeContent = false;
|
|
||||||
PopoutManager.popoutChanged();
|
PopoutManager.popoutChanged();
|
||||||
closeTimer.restart();
|
closeTimer.restart();
|
||||||
}
|
}
|
||||||
@@ -238,11 +197,7 @@ Item {
|
|||||||
readonly property real screenHeight: screen ? screen.height : 0
|
readonly property real screenHeight: screen ? screen.height : 0
|
||||||
readonly property real dpr: screen ? screen.devicePixelRatio : 1
|
readonly property real dpr: screen ? screen.devicePixelRatio : 1
|
||||||
|
|
||||||
readonly property var shadowLevel: Theme.elevationLevel3
|
readonly property real shadowBuffer: 5
|
||||||
readonly property real shadowFallbackOffset: 6
|
|
||||||
readonly property real shadowRenderPadding: (Theme.elevationEnabled && SettingsData.popoutElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, effectiveShadowDirection, shadowFallbackOffset, 8, 16) : 0
|
|
||||||
readonly property real shadowMotionPadding: Math.max(0, animationOffset)
|
|
||||||
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
|
||||||
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
||||||
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
||||||
|
|
||||||
@@ -302,30 +257,29 @@ Item {
|
|||||||
}
|
}
|
||||||
})(), dpr)
|
})(), dpr)
|
||||||
|
|
||||||
readonly property real triggeringBarLeftExclusion: (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? Math.max(0, barX + barWidth) : 0
|
|
||||||
readonly property real triggeringBarTopExclusion: (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? Math.max(0, barY + barHeight) : 0
|
|
||||||
readonly property real triggeringBarRightExclusion: (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? Math.max(0, screenWidth - barX) : 0
|
|
||||||
readonly property real triggeringBarBottomExclusion: (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? Math.max(0, screenHeight - barY) : 0
|
|
||||||
|
|
||||||
readonly property real maskX: {
|
readonly property real maskX: {
|
||||||
|
const triggeringBarX = (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? barWidth : 0;
|
||||||
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
|
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
|
||||||
return Math.max(triggeringBarLeftExclusion, adjacentLeftBar);
|
return Math.max(triggeringBarX, adjacentLeftBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real maskY: {
|
readonly property real maskY: {
|
||||||
|
const triggeringBarY = (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? barHeight : 0;
|
||||||
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
|
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
|
||||||
return Math.max(triggeringBarTopExclusion, adjacentTopBar);
|
return Math.max(triggeringBarY, adjacentTopBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real maskWidth: {
|
readonly property real maskWidth: {
|
||||||
|
const triggeringBarRight = (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? barWidth : 0;
|
||||||
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
|
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
|
||||||
const rightExclusion = Math.max(triggeringBarRightExclusion, adjacentRightBar);
|
const rightExclusion = Math.max(triggeringBarRight, adjacentRightBar);
|
||||||
return Math.max(100, screenWidth - maskX - rightExclusion);
|
return Math.max(100, screenWidth - maskX - rightExclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real maskHeight: {
|
readonly property real maskHeight: {
|
||||||
|
const triggeringBarBottom = (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? barHeight : 0;
|
||||||
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
|
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
|
||||||
const bottomExclusion = Math.max(triggeringBarBottomExclusion, adjacentBottomBar);
|
const bottomExclusion = Math.max(triggeringBarBottom, adjacentBottomBar);
|
||||||
return Math.max(100, screenHeight - maskY - bottomExclusion);
|
return Math.max(100, screenHeight - maskY - bottomExclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +289,7 @@ Item {
|
|||||||
visible: false
|
visible: false
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (typeof updatesEnabled !== "undefined" && !root.overlayContent)
|
if (typeof updatesEnabled !== "undefined")
|
||||||
updatesEnabled = false;
|
updatesEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,7 +395,7 @@ Item {
|
|||||||
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
||||||
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
||||||
|
|
||||||
mask: useBackgroundWindow ? contentInputMask : null
|
mask: (useBackgroundWindow && _fullHeight) ? contentInputMask : null
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
id: contentInputMask
|
id: contentInputMask
|
||||||
@@ -451,10 +405,10 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
id: contentMaskRect
|
id: contentMaskRect
|
||||||
visible: false
|
visible: false
|
||||||
x: contentContainer.x
|
x: contentContainer.x - root.shadowBuffer
|
||||||
y: contentContainer.y
|
y: contentContainer.y - root.shadowBuffer
|
||||||
width: root.alignedWidth
|
width: root.alignedWidth + root.shadowBuffer * 2
|
||||||
height: root.alignedHeight
|
height: root.alignedHeight + root.shadowBuffer * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -526,20 +480,42 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationShadow {
|
Rectangle {
|
||||||
id: shadowSource
|
id: shadowSource
|
||||||
|
anchors.centerIn: parent
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: "black"
|
||||||
|
visible: false
|
||||||
opacity: contentWrapper.opacity
|
opacity: contentWrapper.opacity
|
||||||
scale: contentWrapper.scale
|
scale: contentWrapper.scale
|
||||||
x: contentWrapper.x
|
x: contentWrapper.x
|
||||||
y: contentWrapper.y
|
y: contentWrapper.y
|
||||||
level: root.shadowLevel
|
|
||||||
direction: root.effectiveShadowDirection
|
property real shadowBlurPx: 10
|
||||||
fallbackOffset: root.shadowFallbackOffset
|
property real shadowSpreadPx: 0
|
||||||
targetRadius: Theme.cornerRadius
|
property real shadowBaseAlpha: 0.60
|
||||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
|
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||||
|
readonly property int blurMax: 64
|
||||||
|
|
||||||
|
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
|
||||||
|
layer.smooth: false
|
||||||
|
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
id: shadowFx
|
||||||
|
autoPaddingEnabled: true
|
||||||
|
shadowEnabled: true
|
||||||
|
blurEnabled: false
|
||||||
|
maskEnabled: false
|
||||||
|
shadowBlur: Math.max(0, Math.min(1, shadowSource.shadowBlurPx / shadowSource.blurMax))
|
||||||
|
shadowScale: 1 + (2 * shadowSource.shadowSpreadPx) / Math.max(1, Math.min(shadowSource.width, shadowSource.height))
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, shadowSource.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -570,13 +546,13 @@ Item {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
border.color: Theme.outlineMedium
|
border.color: Theme.outlineMedium
|
||||||
border.width: 0
|
border.width: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: root._primeContent || shouldBeVisible || contentWindow.visible
|
active: shouldBeVisible || contentWindow.visible
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,11 +53,8 @@
|
|||||||
--m3-radius: 12px;
|
--m3-radius: 12px;
|
||||||
--m3-radius-sm: 10px;
|
--m3-radius-sm: 10px;
|
||||||
--m3-elev-0: none;
|
--m3-elev-0: none;
|
||||||
--m3-elev-1: 0 1px 2px color-mix(in srgb, var(--md-sys-color-shadow) 8%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 6%, transparent);
|
--m3-elev-1: 0 1px 2px rgba(0,0,0,.08), 0 1px 3px rgba(0,0,0,.06);
|
||||||
--m3-elev-2: 0 2px 6px color-mix(in srgb, var(--md-sys-color-shadow) 10%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 6%, transparent);
|
--m3-elev-2: 0 2px 6px rgba(0,0,0,.10), 0 1px 3px rgba(0,0,0,.06);
|
||||||
--m3-elev-3: 0 11px 7px color-mix(in srgb, var(--md-sys-color-shadow) 19%, transparent), 0 13px 25px color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent);
|
|
||||||
--m3-elev-4: 0 14px 12px color-mix(in srgb, var(--md-sys-color-shadow) 17%, transparent), 0 20px 40px color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent);
|
|
||||||
--m3-elev-5: 0 17px 17px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent), 0 27px 55px color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent);
|
|
||||||
|
|
||||||
--tab-height: 34px;
|
--tab-height: 34px;
|
||||||
--urlbar-height: 38px;
|
--urlbar-height: 38px;
|
||||||
@@ -121,11 +118,8 @@
|
|||||||
--md-sys-color-surface-container-high: {{colors.surface_container_high.dark.hex}};
|
--md-sys-color-surface-container-high: {{colors.surface_container_high.dark.hex}};
|
||||||
--md-sys-color-surface-container-highest: {{colors.surface_container_highest.dark.hex}};
|
--md-sys-color-surface-container-highest: {{colors.surface_container_highest.dark.hex}};
|
||||||
|
|
||||||
--m3-elev-1: 0 1px 2px color-mix(in srgb, var(--md-sys-color-shadow) 50%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 35%, transparent);
|
--m3-elev-1: 0 1px 2px rgba(0,0,0,.50), 0 1px 3px rgba(0,0,0,.35);
|
||||||
--m3-elev-2: 0 4px 10px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 35%, transparent);
|
--m3-elev-2: 0 4px 10px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.35);
|
||||||
--m3-elev-3: 0 11px 7px color-mix(in srgb, var(--md-sys-color-shadow) 45%, transparent), 0 13px 25px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent);
|
|
||||||
--m3-elev-4: 0 14px 12px color-mix(in srgb, var(--md-sys-color-shadow) 42%, transparent), 0 20px 40px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent);
|
|
||||||
--m3-elev-5: 0 17px 17px color-mix(in srgb, var(--md-sys-color-shadow) 40%, transparent), 0 27px 55px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent);
|
|
||||||
|
|
||||||
--state-hover: color-mix(in srgb, var(--md-sys-color-on-surface) 6%, transparent);
|
--state-hover: color-mix(in srgb, var(--md-sys-color-on-surface) 6%, transparent);
|
||||||
--state-press: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent);
|
--state-press: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent);
|
||||||
|
|||||||
@@ -4,12 +4,10 @@ return {
|
|||||||
priority = 1000,
|
priority = 1000,
|
||||||
config = function()
|
config = function()
|
||||||
require('base16-colorscheme').setup({
|
require('base16-colorscheme').setup({
|
||||||
|
base00 = '{{dank16.color0.default.hex}}',
|
||||||
base00 = '{{colors.background.dark.hex}}',
|
base01 = '{{dank16.color0.default.hex}}',
|
||||||
base01 = '{{colors.surface_container_low.dark.hex}}',
|
base02 = '{{dank16.color8.default.hex}}',
|
||||||
base02 = '{{colors.surface_container.dark.hex}}',
|
base03 = '{{dank16.color8.default.hex}}',
|
||||||
base03 = '{{dank16.color8.dark.hex}}',
|
|
||||||
base0B = '{{dank16.color3.dark.hex}}',
|
|
||||||
base04 = '{{dank16.color7.default.hex}}',
|
base04 = '{{dank16.color7.default.hex}}',
|
||||||
base05 = '{{dank16.color15.default.hex}}',
|
base05 = '{{dank16.color15.default.hex}}',
|
||||||
base06 = '{{dank16.color15.default.hex}}',
|
base06 = '{{dank16.color15.default.hex}}',
|
||||||
@@ -17,12 +15,65 @@ return {
|
|||||||
base08 = '{{dank16.color9.default.hex}}',
|
base08 = '{{dank16.color9.default.hex}}',
|
||||||
base09 = '{{dank16.color9.default.hex}}',
|
base09 = '{{dank16.color9.default.hex}}',
|
||||||
base0A = '{{dank16.color12.default.hex}}',
|
base0A = '{{dank16.color12.default.hex}}',
|
||||||
|
base0B = '{{dank16.color10.default.hex}}',
|
||||||
base0C = '{{dank16.color14.default.hex}}',
|
base0C = '{{dank16.color14.default.hex}}',
|
||||||
base0D = '{{dank16.color12.default.hex}}',
|
base0D = '{{dank16.color12.default.hex}}',
|
||||||
base0E = '{{dank16.color13.default.hex}}',
|
base0E = '{{dank16.color13.default.hex}}',
|
||||||
base0F = '{{dank16.color13.default.hex}}',
|
base0F = '{{dank16.color13.default.hex}}',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'Visual', {
|
||||||
|
bg = '{{dank16.color8.default.hex}}',
|
||||||
|
fg = '{{dank16.color15.default.hex}}',
|
||||||
|
bold = true
|
||||||
|
})
|
||||||
|
vim.api.nvim_set_hl(0, 'Statusline', {
|
||||||
|
bg = '{{dank16.color12.default.hex}}',
|
||||||
|
fg = '{{dank16.color0.default.hex}}',
|
||||||
|
})
|
||||||
|
vim.api.nvim_set_hl(0, 'LineNr', { fg = '{{dank16.color8.default.hex}}' })
|
||||||
|
vim.api.nvim_set_hl(0, 'CursorLineNr', { fg = '{{dank16.color14.default.hex}}', bold = true })
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'Statement', {
|
||||||
|
fg = '{{dank16.color13.default.hex}}',
|
||||||
|
bold = true
|
||||||
|
})
|
||||||
|
vim.api.nvim_set_hl(0, 'Keyword', { link = 'Statement' })
|
||||||
|
vim.api.nvim_set_hl(0, 'Repeat', { link = 'Statement' })
|
||||||
|
vim.api.nvim_set_hl(0, 'Conditional', { link = 'Statement' })
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'Function', {
|
||||||
|
fg = '{{dank16.color12.default.hex}}',
|
||||||
|
bold = true
|
||||||
|
})
|
||||||
|
vim.api.nvim_set_hl(0, 'Macro', {
|
||||||
|
fg = '{{dank16.color12.default.hex}}',
|
||||||
|
italic = true
|
||||||
|
})
|
||||||
|
vim.api.nvim_set_hl(0, '@function.macro', { link = 'Macro' })
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'Type', {
|
||||||
|
fg = '{{dank16.color14.default.hex}}',
|
||||||
|
bold = true,
|
||||||
|
italic = true
|
||||||
|
})
|
||||||
|
vim.api.nvim_set_hl(0, 'Structure', { link = 'Type' })
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'String', {
|
||||||
|
fg = '{{dank16.color10.default.hex}}',
|
||||||
|
italic = true
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'Operator', { fg = '{{dank16.color7.default.hex}}' })
|
||||||
|
vim.api.nvim_set_hl(0, 'Delimiter', { fg = '{{dank16.color7.default.hex}}' })
|
||||||
|
vim.api.nvim_set_hl(0, '@punctuation.bracket', { link = 'Delimiter' })
|
||||||
|
vim.api.nvim_set_hl(0, '@punctuation.delimiter', { link = 'Delimiter' })
|
||||||
|
|
||||||
|
vim.api.nvim_set_hl(0, 'Comment', {
|
||||||
|
fg = '{{dank16.color8.default.hex}}',
|
||||||
|
italic = true
|
||||||
|
})
|
||||||
|
|
||||||
local current_file_path = vim.fn.stdpath("config") .. "/lua/plugins/dankcolors.lua"
|
local current_file_path = vim.fn.stdpath("config") .. "/lua/plugins/dankcolors.lua"
|
||||||
if not _G._matugen_theme_watcher then
|
if not _G._matugen_theme_watcher then
|
||||||
local uv = vim.uv or vim.loop
|
local uv = vim.uv or vim.loop
|
||||||
|
|||||||
@@ -2400,74 +2400,6 @@
|
|||||||
],
|
],
|
||||||
"description": "0 = square corners"
|
"description": "0 = square corners"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"section": "m3ElevationEnabled",
|
|
||||||
"label": "M3 Elevation & Shadows",
|
|
||||||
"tabIndex": 10,
|
|
||||||
"category": "Theme & Colors",
|
|
||||||
"keywords": [
|
|
||||||
"appearance",
|
|
||||||
"elevation",
|
|
||||||
"lift",
|
|
||||||
"material",
|
|
||||||
"m3",
|
|
||||||
"shadow",
|
|
||||||
"shadows",
|
|
||||||
"theme"
|
|
||||||
],
|
|
||||||
"description": "Material Design 3 shadows and elevation on modals, popouts, and dialogs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"section": "modalElevationEnabled",
|
|
||||||
"label": "Modal Shadows",
|
|
||||||
"tabIndex": 10,
|
|
||||||
"category": "Theme & Colors",
|
|
||||||
"keywords": [
|
|
||||||
"dialog",
|
|
||||||
"elevation",
|
|
||||||
"m3",
|
|
||||||
"material",
|
|
||||||
"modal",
|
|
||||||
"shadow",
|
|
||||||
"shadows"
|
|
||||||
],
|
|
||||||
"description": "Shadow elevation on modals and dialogs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"section": "popoutElevationEnabled",
|
|
||||||
"label": "Popout Shadows",
|
|
||||||
"tabIndex": 10,
|
|
||||||
"category": "Theme & Colors",
|
|
||||||
"keywords": [
|
|
||||||
"dropdown",
|
|
||||||
"elevation",
|
|
||||||
"m3",
|
|
||||||
"material",
|
|
||||||
"osd",
|
|
||||||
"popout",
|
|
||||||
"popup",
|
|
||||||
"shadow",
|
|
||||||
"shadows"
|
|
||||||
],
|
|
||||||
"description": "Shadow elevation on popouts, OSDs, and dropdowns"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"section": "barElevationEnabled",
|
|
||||||
"label": "Bar Shadows",
|
|
||||||
"tabIndex": 10,
|
|
||||||
"category": "Theme & Colors",
|
|
||||||
"keywords": [
|
|
||||||
"bar",
|
|
||||||
"elevation",
|
|
||||||
"m3",
|
|
||||||
"material",
|
|
||||||
"navigation",
|
|
||||||
"panel",
|
|
||||||
"shadow",
|
|
||||||
"shadows"
|
|
||||||
],
|
|
||||||
"description": "Shadow elevation on bars and panels"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"section": "cursorSize",
|
"section": "cursorSize",
|
||||||
"label": "Cursor Size",
|
"label": "Cursor Size",
|
||||||
|
|||||||
Reference in New Issue
Block a user