mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
Compare commits
18 Commits
e6c3ae9397
...
6297b0679c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6297b0679c | ||
|
|
d62ef635a7 | ||
|
|
c53836040f | ||
|
|
0b638bf85f | ||
|
|
7f6a71b964 | ||
|
|
1b4363a54a | ||
|
|
16d168c970 | ||
|
|
4606d7960e | ||
|
|
4eee126d26 | ||
|
|
dde426658f | ||
|
|
f6874fbcad | ||
|
|
621d4e4d92 | ||
|
|
76062231fd | ||
|
|
261f55fea5 | ||
|
|
202cf4bcc9 | ||
|
|
b7572f727f | ||
|
|
50ab346d58 | ||
|
|
b11b375848 |
20
.github/workflows/go-ci.yml
vendored
20
.github/workflows/go-ci.yml
vendored
@@ -7,9 +7,18 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'core/**'
|
- 'core/**'
|
||||||
- '.github/workflows/go-ci.yml'
|
- '.github/workflows/go-ci.yml'
|
||||||
|
pull_request:
|
||||||
|
branches: [master, main]
|
||||||
|
paths:
|
||||||
|
- 'core/**'
|
||||||
|
- '.github/workflows/go-ci.yml'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: go-ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
lint-and-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -32,11 +41,20 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Run golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v6
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
working-directory: core
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test -v ./...
|
run: go test -v ./...
|
||||||
|
|
||||||
- name: Build dms
|
- name: Build dms
|
||||||
run: go build -v ./cmd/dms
|
run: go build -v ./cmd/dms
|
||||||
|
|
||||||
|
- name: Build dms (distropkg)
|
||||||
|
run: go build -v -tags distro_binary ./cmd/dms
|
||||||
|
|
||||||
- name: Build dankinstall
|
- name: Build dankinstall
|
||||||
run: go build -v ./cmd/dankinstall
|
run: go build -v ./cmd/dankinstall
|
||||||
|
|||||||
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@@ -132,38 +132,40 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build-core
|
needs: build-core
|
||||||
steps:
|
steps:
|
||||||
|
- name: Create GitHub App token
|
||||||
|
id: app_token
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.APP_ID }}
|
||||||
|
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ steps.app_token.outputs.token }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Update VERSION
|
- name: Update VERSION
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.app_token.outputs.token }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
git config user.name "github-actions[bot]"
|
git config user.name "dms-ci[bot]"
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
git config user.email "dms-ci[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
version="${GITHUB_REF#refs/tags/}"
|
version="${GITHUB_REF#refs/tags/}"
|
||||||
version_no_v="${version#v}"
|
|
||||||
echo "Updating to version: $version"
|
echo "Updating to version: $version"
|
||||||
|
|
||||||
# Update VERSION file in quickshell/
|
|
||||||
echo "${version}" > quickshell/VERSION
|
echo "${version}" > quickshell/VERSION
|
||||||
|
|
||||||
git add quickshell/VERSION
|
git add quickshell/VERSION
|
||||||
|
|
||||||
if ! git diff --cached --quiet; then
|
if ! git diff --cached --quiet; then
|
||||||
git commit -m "chore: bump version to $version"
|
git commit -m "chore: bump version to $version"
|
||||||
git push origin HEAD:master || git push origin HEAD:main
|
git pull --rebase origin master
|
||||||
echo "Pushed version updates to master"
|
git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:master
|
||||||
else
|
|
||||||
echo "No version changes needed"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Force-push the tag to point to the commit with updated VERSION
|
|
||||||
git tag -f "${version}"
|
git tag -f "${version}"
|
||||||
git push -f origin "${version}"
|
git push -f https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git "${version}"
|
||||||
|
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|||||||
66
.github/workflows/update-vendor-hash.yml
vendored
66
.github/workflows/update-vendor-hash.yml
vendored
@@ -1,6 +1,7 @@
|
|||||||
name: Update Vendor Hash
|
name: Update Vendor Hash
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- "core/go.mod"
|
- "core/go.mod"
|
||||||
@@ -8,14 +9,25 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-vendor-hash:
|
update-vendor-hash:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: Create GitHub App token
|
||||||
|
id: app_token
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.APP_ID }}
|
||||||
|
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
token: ${{ steps.app_token.outputs.token }}
|
||||||
|
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v31
|
uses: cachix/install-nix-action@v31
|
||||||
@@ -23,68 +35,32 @@ jobs:
|
|||||||
- name: Update vendorHash in flake.nix
|
- name: Update vendorHash in flake.nix
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Try to build and capture the expected hash from error message
|
|
||||||
echo "Attempting nix build to get new vendorHash..."
|
echo "Attempting nix build to get new vendorHash..."
|
||||||
|
|
||||||
if output=$(nix build .#dmsCli 2>&1); then
|
if output=$(nix build .#dmsCli 2>&1); then
|
||||||
echo "Build succeeded, no hash update needed"
|
echo "Build succeeded, no hash update needed"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extract the expected hash from the error message
|
|
||||||
new_hash=$(echo "$output" | grep -oP "got:\s+\K\S+" | head -n1)
|
new_hash=$(echo "$output" | grep -oP "got:\s+\K\S+" | head -n1)
|
||||||
|
[ -n "$new_hash" ] || { echo "Could not extract new vendorHash"; echo "$output"; exit 1; }
|
||||||
if [ -z "$new_hash" ]; then
|
|
||||||
echo "Could not extract new vendorHash from build output"
|
|
||||||
echo "Build output:"
|
|
||||||
echo "$output"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "New vendorHash: $new_hash"
|
|
||||||
|
|
||||||
# Get current hash from flake.nix
|
|
||||||
current_hash=$(grep -oP 'vendorHash = "\K[^"]+' flake.nix)
|
current_hash=$(grep -oP 'vendorHash = "\K[^"]+' flake.nix)
|
||||||
echo "Current vendorHash: $current_hash"
|
[ "$current_hash" = "$new_hash" ] && { echo "vendorHash already up to date"; exit 0; }
|
||||||
|
|
||||||
if [ "$current_hash" = "$new_hash" ]; then
|
|
||||||
echo "vendorHash is already up to date"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update the hash in flake.nix
|
|
||||||
sed -i "s|vendorHash = \"$current_hash\"|vendorHash = \"$new_hash\"|" flake.nix
|
sed -i "s|vendorHash = \"$current_hash\"|vendorHash = \"$new_hash\"|" flake.nix
|
||||||
|
|
||||||
# Verify the build works with the new hash
|
|
||||||
echo "Verifying build with new vendorHash..."
|
echo "Verifying build with new vendorHash..."
|
||||||
nix build .#dmsCli
|
nix build .#dmsCli
|
||||||
|
|
||||||
echo "vendorHash updated successfully!"
|
echo "vendorHash updated successfully!"
|
||||||
|
|
||||||
- name: Commit and push vendorHash update
|
- name: Commit and push vendorHash update
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.app_token.outputs.token }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
if ! git diff --quiet flake.nix; then
|
if ! git diff --quiet flake.nix; then
|
||||||
git config user.name "github-actions[bot]"
|
git config user.name "dms-ci[bot]"
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
git config user.email "dms-ci[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
git add flake.nix
|
git add flake.nix
|
||||||
git commit -m "nix: update vendorHash for go.mod changes"
|
git commit -m "nix: update vendorHash for go.mod changes" || exit 0
|
||||||
|
git pull --rebase origin master
|
||||||
for attempt in 1 2 3; do
|
git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:master
|
||||||
if git push; then
|
|
||||||
echo "Successfully pushed vendorHash update"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo "Push attempt $attempt failed, pulling and retrying..."
|
|
||||||
git pull --rebase
|
|
||||||
sleep $((attempt*2))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Failed to push after retries" >&2
|
|
||||||
exit 1
|
|
||||||
else
|
else
|
||||||
echo "No changes to flake.nix"
|
echo "No changes to flake.nix"
|
||||||
fi
|
fi
|
||||||
|
|||||||
77
core/.golangci.yml
Normal file
77
core/.golangci.yml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
linters-settings:
|
||||||
|
errcheck:
|
||||||
|
check-type-assertions: false
|
||||||
|
check-blank: false
|
||||||
|
exclude-functions:
|
||||||
|
# Cleanup/destroy operations
|
||||||
|
- (io.Closer).Close
|
||||||
|
- (*os.File).Close
|
||||||
|
- (net.Conn).Close
|
||||||
|
- (*net.Conn).Close
|
||||||
|
# Signal handling
|
||||||
|
- (*os.Process).Signal
|
||||||
|
- (*os.Process).Kill
|
||||||
|
# DBus cleanup
|
||||||
|
- (*github.com/godbus/dbus/v5.Conn).RemoveMatchSignal
|
||||||
|
- (*github.com/godbus/dbus/v5.Conn).RemoveSignal
|
||||||
|
# Encoding to network connections (if conn is bad, nothing we can do)
|
||||||
|
- (*encoding/json.Encoder).Encode
|
||||||
|
- (net.Conn).Write
|
||||||
|
# Command execution where failure is expected/ignored
|
||||||
|
- (*os/exec.Cmd).Run
|
||||||
|
- (*os/exec.Cmd).Start
|
||||||
|
# Flush operations
|
||||||
|
- (*bufio.Writer).Flush
|
||||||
|
# Scanning user input
|
||||||
|
- fmt.Scanln
|
||||||
|
- fmt.Scanf
|
||||||
|
# Parse operations where default value is acceptable
|
||||||
|
- fmt.Sscanf
|
||||||
|
# Flag operations
|
||||||
|
- (*github.com/spf13/pflag.FlagSet).MarkHidden
|
||||||
|
# Binary encoding to buffer (can't fail for basic types)
|
||||||
|
- binary.Write
|
||||||
|
# File operations in cleanup paths
|
||||||
|
- os.Rename
|
||||||
|
- os.Remove
|
||||||
|
- (*os.File).WriteString
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
- govet
|
||||||
|
- unused
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- gosimple
|
||||||
|
# Exclude cleanup/teardown method calls from errcheck
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
|
text: "Error return value of `.+\\.(Destroy|Release|Stop|Close|Roundtrip|Store)` is not checked"
|
||||||
|
# Exclude internal state update methods that are best-effort
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
|
text: "Error return value of `[mb]\\.\\w*(update|initialize|recreate|acquire|enumerate|list|List|Ensure|refresh|Lock)\\w*` is not checked"
|
||||||
|
# Exclude SetMode on wayland power controls (best-effort)
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
|
text: "Error return value of `.+\\.SetMode` is not checked"
|
||||||
|
# Exclude AddMatchSignal which is best-effort monitoring setup
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
|
text: "Error return value of `.+\\.AddMatchSignal` is not checked"
|
||||||
|
# Exclude wayland pkg from errcheck and ineffassign (generated code patterns)
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
|
- ineffassign
|
||||||
|
path: pkg/go-wayland/
|
||||||
|
# Exclude proto pkg from ineffassign (generated protocol code)
|
||||||
|
- linters:
|
||||||
|
- ineffassign
|
||||||
|
path: internal/proto/
|
||||||
|
# binary.Write to bytes.Buffer can't fail
|
||||||
|
- linters:
|
||||||
|
- errcheck
|
||||||
|
text: "Error return value of `binary\\.Write` is not checked"
|
||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/greeter"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/greeter"
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
var greeterCmd = &cobra.Command{
|
var greeterCmd = &cobra.Command{
|
||||||
@@ -258,7 +260,7 @@ func disableDisplayManager(dmName string) (bool, error) {
|
|||||||
} else if shouldDisable {
|
} else if shouldDisable {
|
||||||
return actionTaken, fmt.Errorf("%s is still in state '%s' after %s operation", dmName, enabledState, actionVerb)
|
return actionTaken, fmt.Errorf("%s is still in state '%s' after %s operation", dmName, enabledState, actionVerb)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(" ✓ %s %s (now: %s)\n", strings.Title(actionVerb), dmName, enabledState)
|
fmt.Printf(" ✓ %s %s (now: %s)\n", cases.Title(language.English).String(actionVerb), dmName, enabledState)
|
||||||
}
|
}
|
||||||
|
|
||||||
actionTaken = true
|
actionTaken = true
|
||||||
|
|||||||
18
core/go.mod
18
core/go.mod
@@ -9,24 +9,24 @@ require (
|
|||||||
github.com/charmbracelet/lipgloss v1.1.0
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
github.com/charmbracelet/log v0.4.2
|
github.com/charmbracelet/log v0.4.2
|
||||||
github.com/fsnotify/fsnotify v1.9.0
|
github.com/fsnotify/fsnotify v1.9.0
|
||||||
github.com/godbus/dbus/v5 v5.1.0
|
github.com/godbus/dbus/v5 v5.2.0
|
||||||
github.com/holoplot/go-evdev v0.0.0-20250804134636-ab1d56a1fe83
|
github.com/holoplot/go-evdev v0.0.0-20250804134636-ab1d56a1fe83
|
||||||
github.com/spf13/cobra v1.10.1
|
github.com/spf13/cobra v1.10.1
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6
|
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||||
github.com/clipperhouse/displaywidth v0.5.0 // indirect
|
github.com/clipperhouse/displaywidth v0.6.0 // indirect
|
||||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||||
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.6.1 // indirect
|
github.com/cloudflare/circl v1.6.1 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.6.0 // indirect
|
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // 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-20251111123000-fb5ff8f3f0b0 // indirect
|
github.com/go-git/go-billy/v6 v6.0.0-20251126203821-7f9c95185ee0 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
github.com/go-logfmt/logfmt v0.6.1 // 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.4.0 // indirect
|
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
||||||
@@ -34,7 +34,7 @@ require (
|
|||||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
github.com/pjbgf/sha1cd v0.5.0 // 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
|
||||||
golang.org/x/crypto v0.44.0 // indirect
|
golang.org/x/crypto v0.45.0 // indirect
|
||||||
golang.org/x/net v0.47.0 // indirect
|
golang.org/x/net v0.47.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,12 +43,12 @@ require (
|
|||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.3.3 // indirect
|
github.com/charmbracelet/colorprofile v0.3.3 // indirect
|
||||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.11.0 // indirect
|
github.com/charmbracelet/x/ansi v0.11.2 // indirect
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
|
github.com/charmbracelet/x/cellbuf v0.0.14 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
github.com/go-git/go-git/v6 v6.0.0-20251112161705-8cc3e21f07a9
|
github.com/go-git/go-git/v6 v6.0.0-20251128074608-48f817f57805
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0
|
github.com/lucasb-eyer/go-colorful v1.3.0
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
@@ -63,6 +63,6 @@ require (
|
|||||||
github.com/spf13/pflag v1.0.10 // indirect
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
golang.org/x/sys v0.38.0
|
golang.org/x/sys v0.38.0
|
||||||
golang.org/x/text v0.31.0 // indirect
|
golang.org/x/text v0.31.0
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
16
core/go.sum
16
core/go.sum
@@ -26,12 +26,16 @@ github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsy
|
|||||||
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
||||||
github.com/charmbracelet/x/ansi v0.11.0 h1:uuIVK7GIplwX6UBIz8S2TF8nkr7xRlygSsBRjSJqIvA=
|
github.com/charmbracelet/x/ansi v0.11.0 h1:uuIVK7GIplwX6UBIz8S2TF8nkr7xRlygSsBRjSJqIvA=
|
||||||
github.com/charmbracelet/x/ansi v0.11.0/go.mod h1:uQt8bOrq/xgXjlGcFMc8U2WYbnxyjrKhnvTQluvfCaE=
|
github.com/charmbracelet/x/ansi v0.11.0/go.mod h1:uQt8bOrq/xgXjlGcFMc8U2WYbnxyjrKhnvTQluvfCaE=
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.2 h1:XAG3FSjiVtFvgEgGrNBkCNNYrsucAt8c6bfxHyROLLs=
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.2/go.mod h1:9tY2bzX5SiJCU0iWyskjBeI2BRQfvPqI+J760Mjf+Rg=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
|
github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
|
github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA=
|
||||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||||
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||||
github.com/clipperhouse/displaywidth v0.5.0 h1:AIG5vQaSL2EKqzt0M9JMnvNxOCRTKUc4vUnLWGgP89I=
|
github.com/clipperhouse/displaywidth v0.5.0 h1:AIG5vQaSL2EKqzt0M9JMnvNxOCRTKUc4vUnLWGgP89I=
|
||||||
github.com/clipperhouse/displaywidth v0.5.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
github.com/clipperhouse/displaywidth v0.5.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
||||||
|
github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s=
|
||||||
|
github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
||||||
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||||
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
|
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
|
||||||
@@ -41,6 +45,8 @@ github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZ
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
|
github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
|
||||||
github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -58,14 +64,20 @@ github.com/go-git/gcfg/v2 v2.0.2 h1:MY5SIIfTGGEMhdA7d7JePuVVxtKL7Hp+ApGDJAJ7dpo=
|
|||||||
github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs=
|
github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs=
|
||||||
github.com/go-git/go-billy/v6 v6.0.0-20251111123000-fb5ff8f3f0b0 h1:EC9n6hr6yKDoVJ6g7Ko523LbbceJfR0ohbOp809Fyf4=
|
github.com/go-git/go-billy/v6 v6.0.0-20251111123000-fb5ff8f3f0b0 h1:EC9n6hr6yKDoVJ6g7Ko523LbbceJfR0ohbOp809Fyf4=
|
||||||
github.com/go-git/go-billy/v6 v6.0.0-20251111123000-fb5ff8f3f0b0/go.mod h1:E3VhlS+AKkrq6ZNn1axE2/nDRJ87l1FJk9r5HT2vPX0=
|
github.com/go-git/go-billy/v6 v6.0.0-20251111123000-fb5ff8f3f0b0/go.mod h1:E3VhlS+AKkrq6ZNn1axE2/nDRJ87l1FJk9r5HT2vPX0=
|
||||||
|
github.com/go-git/go-billy/v6 v6.0.0-20251126203821-7f9c95185ee0 h1:eY5aB2GXiVdgTueBcqsBt53WuJTRZAuCdIS/86Pcq5c=
|
||||||
|
github.com/go-git/go-billy/v6 v6.0.0-20251126203821-7f9c95185ee0/go.mod h1:0NjwVNrwtVFZBReAp5OoGklGJIgJFEbVyHneAr4lc8k=
|
||||||
github.com/go-git/go-git-fixtures/v5 v5.1.1 h1:OH8i1ojV9bWfr0ZfasfpgtUXQHQyVS8HXik/V1C099w=
|
github.com/go-git/go-git-fixtures/v5 v5.1.1 h1:OH8i1ojV9bWfr0ZfasfpgtUXQHQyVS8HXik/V1C099w=
|
||||||
github.com/go-git/go-git-fixtures/v5 v5.1.1/go.mod h1:Altk43lx3b1ks+dVoAG2300o5WWUnktvfY3VI6bcaXU=
|
github.com/go-git/go-git-fixtures/v5 v5.1.1/go.mod h1:Altk43lx3b1ks+dVoAG2300o5WWUnktvfY3VI6bcaXU=
|
||||||
github.com/go-git/go-git/v6 v6.0.0-20251112161705-8cc3e21f07a9 h1:SOFrnF9LCssC6q6Rb0084Bzg2aBYbe8QXv9xKGXmt/w=
|
github.com/go-git/go-git/v6 v6.0.0-20251112161705-8cc3e21f07a9 h1:SOFrnF9LCssC6q6Rb0084Bzg2aBYbe8QXv9xKGXmt/w=
|
||||||
github.com/go-git/go-git/v6 v6.0.0-20251112161705-8cc3e21f07a9/go.mod h1:0wtvm/JfPC9RFVEAP3ks0ec5h64/qmZkTTUE3pjz7Hc=
|
github.com/go-git/go-git/v6 v6.0.0-20251112161705-8cc3e21f07a9/go.mod h1:0wtvm/JfPC9RFVEAP3ks0ec5h64/qmZkTTUE3pjz7Hc=
|
||||||
|
github.com/go-git/go-git/v6 v6.0.0-20251128074608-48f817f57805 h1:jxQ3BzYeErNRvlI/4+0mpwqMzvB4g97U+ksfgvrUEbY=
|
||||||
|
github.com/go-git/go-git/v6 v6.0.0-20251128074608-48f817f57805/go.mod h1:dIwT3uWK1ooHInyVnK2JS5VfQ3peVGYaw2QPqX7uFvs=
|
||||||
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
||||||
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
||||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
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.0 h1:3WexO+U+yg9T70v9FdHr9kCxYlazaAXUhx2VMkbfax8=
|
||||||
|
github.com/godbus/dbus/v5 v5.2.0/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
||||||
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=
|
||||||
@@ -127,8 +139,12 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
|
|||||||
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=
|
||||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||||
|
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||||
|
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||||
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 h1:zfMcR1Cs4KNuomFFgGefv5N0czO2XZpUbxGUy8i8ug0=
|
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 h1:zfMcR1Cs4KNuomFFgGefv5N0czO2XZpUbxGUy8i8ug0=
|
||||||
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0=
|
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0=
|
||||||
|
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 h1:DHNhtq3sNNzrvduZZIiFyXWOL9IWaDPHqTnLJp+rCBY=
|
||||||
|
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0=
|
||||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ func SyncDMSConfigs(dmsPath string, logFunc func(string), sudoPassword string) e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runSudoCmd(sudoPassword, "rm", "-f", link.target)
|
runSudoCmd(sudoPassword, "rm", "-f", link.target) //nolint:errcheck
|
||||||
|
|
||||||
if err := runSudoCmd(sudoPassword, "ln", "-sf", link.source, link.target); err != nil {
|
if err := runSudoCmd(sudoPassword, "ln", "-sf", link.source, link.target); err != nil {
|
||||||
logFunc(fmt.Sprintf("⚠ Warning: Failed to create symlink for %s: %v", link.desc, err))
|
logFunc(fmt.Sprintf("⚠ Warning: Failed to create symlink for %s: %v", link.desc, err))
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func (d *DiscoveryConfig) FindJSONFiles() ([]string, error) {
|
|||||||
func expandPath(path string) (string, error) {
|
func expandPath(path string) (string, error) {
|
||||||
expandedPath := os.ExpandEnv(path)
|
expandedPath := os.ExpandEnv(path)
|
||||||
|
|
||||||
if filepath.HasPrefix(expandedPath, "~") {
|
if strings.HasPrefix(expandedPath, "~") {
|
||||||
home, err := os.UserHomeDir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
|
||||||
)
|
)
|
||||||
@@ -118,7 +119,7 @@ func (j *JSONFileProvider) GetCheatSheet() (*keybinds.CheatSheet, error) {
|
|||||||
func expandPath(path string) (string, error) {
|
func expandPath(path string) (string, error) {
|
||||||
expandedPath := os.ExpandEnv(path)
|
expandedPath := os.ExpandEnv(path)
|
||||||
|
|
||||||
if filepath.HasPrefix(expandedPath, "~") {
|
if strings.HasPrefix(expandedPath, "~") {
|
||||||
home, err := os.UserHomeDir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func (l *FileLogger) writeToFile(message string) {
|
|||||||
redacted := l.redactPassword(message)
|
redacted := l.redactPassword(message)
|
||||||
timestamp := time.Now().Format("15:04:05.000")
|
timestamp := time.Now().Format("15:04:05.000")
|
||||||
|
|
||||||
l.writer.WriteString(fmt.Sprintf("[%s] %s\n", timestamp, redacted))
|
l.writer.WriteString(fmt.Sprintf("[%s] %s\n", timestamp, redacted)) //nolint:errcheck
|
||||||
l.writer.Flush()
|
l.writer.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ func (l *FileLogger) Close() error {
|
|||||||
defer l.mu.Unlock()
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
footer := fmt.Sprintf("\n=== DankInstall Log End ===\nCompleted: %s\n", time.Now().Format(time.RFC3339))
|
footer := fmt.Sprintf("\n=== DankInstall Log End ===\nCompleted: %s\n", time.Now().Format(time.RFC3339))
|
||||||
l.writer.WriteString(footer)
|
l.writer.WriteString(footer) //nolint:errcheck
|
||||||
l.writer.Flush()
|
l.writer.Flush()
|
||||||
|
|
||||||
if err := l.file.Sync(); err != nil {
|
if err := l.file.Sync(); err != nil {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func (m *Manager) Install(plugin Plugin) error {
|
|||||||
|
|
||||||
if !repoExists {
|
if !repoExists {
|
||||||
if err := m.gitClient.PlainClone(repoPath, plugin.Repo); err != nil {
|
if err := m.gitClient.PlainClone(repoPath, plugin.Repo); err != nil {
|
||||||
m.fs.RemoveAll(repoPath)
|
m.fs.RemoveAll(repoPath) //nolint:errcheck
|
||||||
return fmt.Errorf("failed to clone repository: %w", err)
|
return fmt.Errorf("failed to clone repository: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -130,7 +130,7 @@ func (m *Manager) Install(plugin Plugin) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := m.gitClient.PlainClone(pluginPath, plugin.Repo); err != nil {
|
if err := m.gitClient.PlainClone(pluginPath, plugin.Repo); err != nil {
|
||||||
m.fs.RemoveAll(pluginPath)
|
m.fs.RemoveAll(pluginPath) //nolint:errcheck
|
||||||
return fmt.Errorf("failed to clone plugin: %w", err)
|
return fmt.Errorf("failed to clone plugin: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ func (b *DDCBackend) probeDDCDevice(bus int) (*ddcDevice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dummy := make([]byte, 32)
|
dummy := make([]byte, 32)
|
||||||
syscall.Read(fd, dummy)
|
syscall.Read(fd, dummy) //nolint:errcheck
|
||||||
|
|
||||||
writebuf := []byte{0x00}
|
writebuf := []byte{0x00}
|
||||||
n, err := syscall.Write(fd, writebuf)
|
n, err := syscall.Write(fd, writebuf)
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ type DBusConn interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LogindBackend struct {
|
type LogindBackend struct {
|
||||||
conn DBusConn
|
conn DBusConn
|
||||||
connOnce bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogindBackend() (*LogindBackend, error) {
|
func NewLogindBackend() (*LogindBackend, error) {
|
||||||
|
|||||||
@@ -251,14 +251,14 @@ func (m *Manager) CreatePrinter(name, deviceURI, ppd string, shared bool, errorP
|
|||||||
}
|
}
|
||||||
|
|
||||||
if usedPkHelper {
|
if usedPkHelper {
|
||||||
m.pkHelper.PrinterSetEnabled(name, true)
|
m.pkHelper.PrinterSetEnabled(name, true) //nolint:errcheck
|
||||||
m.pkHelper.PrinterSetAcceptJobs(name, true, "")
|
m.pkHelper.PrinterSetAcceptJobs(name, true, "") //nolint:errcheck
|
||||||
} else {
|
} else {
|
||||||
if err := m.client.ResumePrinter(name); isAuthError(err) && m.pkHelper != nil {
|
if err := m.client.ResumePrinter(name); isAuthError(err) && m.pkHelper != nil {
|
||||||
m.pkHelper.PrinterSetEnabled(name, true)
|
m.pkHelper.PrinterSetEnabled(name, true) //nolint:errcheck
|
||||||
}
|
}
|
||||||
if err := m.client.AcceptJobs(name); isAuthError(err) && m.pkHelper != nil {
|
if err := m.client.AcceptJobs(name); isAuthError(err) && m.pkHelper != nil {
|
||||||
m.pkHelper.PrinterSetAcceptJobs(name, true, "")
|
m.pkHelper.PrinterSetAcceptJobs(name, true, "") //nolint:errcheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/godbus/dbus/v5"
|
"github.com/godbus/dbus/v5"
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -118,12 +120,6 @@ func (a *SecretAgent) GetSecrets(
|
|||||||
log.Infof("[SecretAgent] GetSecrets called: path=%s, setting=%s, hints=%v, flags=%d",
|
log.Infof("[SecretAgent] GetSecrets called: path=%s, setting=%s, hints=%v, flags=%d",
|
||||||
path, settingName, hints, flags)
|
path, settingName, hints, flags)
|
||||||
|
|
||||||
const (
|
|
||||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1
|
|
||||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2
|
|
||||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4
|
|
||||||
)
|
|
||||||
|
|
||||||
connType, displayName, vpnSvc := readConnTypeAndName(conn)
|
connType, displayName, vpnSvc := readConnTypeAndName(conn)
|
||||||
ssid := readSSID(conn)
|
ssid := readSSID(conn)
|
||||||
fields := fieldsNeeded(settingName, hints)
|
fields := fieldsNeeded(settingName, hints)
|
||||||
@@ -378,7 +374,7 @@ func (a *SecretAgent) GetSecrets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if settingName == "vpn" && a.backend != nil && (vpnUsername != "" || reply.Save) {
|
if settingName == "vpn" && a.backend != nil && (vpnUsername != "" || reply.Save) {
|
||||||
pw, _ := reply.Secrets["password"]
|
pw := reply.Secrets["password"]
|
||||||
a.backend.pendingVPNSaveMu.Lock()
|
a.backend.pendingVPNSaveMu.Lock()
|
||||||
a.backend.pendingVPNSave = &pendingVPNCredentials{
|
a.backend.pendingVPNSave = &pendingVPNCredentials{
|
||||||
ConnectionPath: string(path),
|
ConnectionPath: string(path),
|
||||||
@@ -620,11 +616,12 @@ func vpnFieldMeta(field, vpnService string) (label string, isSecret bool) {
|
|||||||
case "private-key-password":
|
case "private-key-password":
|
||||||
return "Private Key Password", true
|
return "Private Key Password", true
|
||||||
}
|
}
|
||||||
|
titleCaser := cases.Title(language.English)
|
||||||
if strings.HasSuffix(field, "password") || strings.HasSuffix(field, "secret") ||
|
if strings.HasSuffix(field, "password") || strings.HasSuffix(field, "secret") ||
|
||||||
strings.HasSuffix(field, "pass") || strings.HasSuffix(field, "psk") {
|
strings.HasSuffix(field, "pass") || strings.HasSuffix(field, "psk") {
|
||||||
return strings.Title(strings.ReplaceAll(field, "-", " ")), true
|
return titleCaser.String(strings.ReplaceAll(field, "-", " ")), true
|
||||||
}
|
}
|
||||||
return strings.Title(strings.ReplaceAll(field, "-", " ")), false
|
return titleCaser.String(strings.ReplaceAll(field, "-", " ")), false
|
||||||
}
|
}
|
||||||
|
|
||||||
func readVPNPasswordFlags(conn map[string]nmVariantMap, settingName string) uint32 {
|
func readVPNPasswordFlags(conn map[string]nmVariantMap, settingName string) uint32 {
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ package network
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HybridIwdNetworkdBackend struct {
|
type HybridIwdNetworkdBackend struct {
|
||||||
wifi *IWDBackend
|
wifi *IWDBackend
|
||||||
l3 *SystemdNetworkdBackend
|
l3 *SystemdNetworkdBackend
|
||||||
onStateChange func()
|
onStateChange func()
|
||||||
stateMutex sync.RWMutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHybridIwdNetworkdBackend(w *IWDBackend, n *SystemdNetworkdBackend) (*HybridIwdNetworkdBackend, error) {
|
func NewHybridIwdNetworkdBackend(w *IWDBackend, n *SystemdNetworkdBackend) (*HybridIwdNetworkdBackend, error) {
|
||||||
@@ -120,7 +118,7 @@ func (b *HybridIwdNetworkdBackend) ConnectWiFi(req ConnectionRequest) error {
|
|||||||
|
|
||||||
ws, err := b.wifi.GetCurrentState()
|
ws, err := b.wifi.GetCurrentState()
|
||||||
if err == nil && ws.WiFiDevice != "" {
|
if err == nil && ws.WiFiDevice != "" {
|
||||||
b.l3.EnsureDhcpUp(ws.WiFiDevice)
|
b.l3.EnsureDhcpUp(ws.WiFiDevice) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/godbus/dbus/v5"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ func (b *IWDBackend) OnUserCanceledPrompt() {
|
|||||||
|
|
||||||
if cancelledSSID != "" {
|
if cancelledSSID != "" {
|
||||||
if err := b.ForgetWiFiNetwork(cancelledSSID); err != nil {
|
if err := b.ForgetWiFiNetwork(cancelledSSID); err != nil {
|
||||||
|
log.Warnf("failed to forget cancelled WiFi network %s: %v", cancelledSSID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -319,7 +319,6 @@ func handleConnection(conn net.Conn) {
|
|||||||
capsData, _ := json.Marshal(caps)
|
capsData, _ := json.Marshal(caps)
|
||||||
conn.Write(capsData)
|
conn.Write(capsData)
|
||||||
conn.Write([]byte("\n"))
|
conn.Write([]byte("\n"))
|
||||||
|
|
||||||
scanner := bufio.NewScanner(conn)
|
scanner := bufio.NewScanner(conn)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Bytes()
|
line := scanner.Bytes()
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ func (m Model) viewSelectTerminal() string {
|
|||||||
b.WriteString(title)
|
b.WriteString(title)
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
|
|
||||||
options := []struct {
|
var options []struct {
|
||||||
name string
|
name string
|
||||||
description string
|
description string
|
||||||
}{}
|
}
|
||||||
|
|
||||||
if m.osInfo != nil && m.osInfo.Distribution.ID == "gentoo" {
|
if m.osInfo != nil && m.osInfo.Distribution.ID == "gentoo" {
|
||||||
options = []struct {
|
options = []struct {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VersionInfo struct {
|
type VersionInfo struct {
|
||||||
@@ -33,7 +35,11 @@ func (d *DefaultVersionFetcher) GetCurrentVersion(dmsPath string) (string, error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer os.Chdir(originalDir)
|
defer func() {
|
||||||
|
if err := os.Chdir(originalDir); err != nil {
|
||||||
|
log.Warnf("failed to change back to original directory: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err := os.Chdir(dmsPath); err != nil {
|
if err := os.Chdir(dmsPath); err != nil {
|
||||||
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
||||||
@@ -70,7 +76,11 @@ func (d *DefaultVersionFetcher) GetLatestVersion(dmsPath string) (string, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer os.Chdir(originalDir)
|
defer func() {
|
||||||
|
if err := os.Chdir(originalDir); err != nil {
|
||||||
|
log.Warnf("failed to change back to original directory: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err := os.Chdir(dmsPath); err != nil {
|
if err := os.Chdir(dmsPath); err != nil {
|
||||||
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
||||||
@@ -85,7 +95,9 @@ func (d *DefaultVersionFetcher) GetLatestVersion(dmsPath string) (string, error)
|
|||||||
if _, err := tagCmd.Output(); err == nil {
|
if _, err := tagCmd.Output(); err == nil {
|
||||||
// Add timeout to git fetch to prevent hanging
|
// Add timeout to git fetch to prevent hanging
|
||||||
fetchCmd := exec.Command("timeout", "5s", "git", "fetch", "origin", "--tags", "--quiet")
|
fetchCmd := exec.Command("timeout", "5s", "git", "fetch", "origin", "--tags", "--quiet")
|
||||||
fetchCmd.Run()
|
if err := fetchCmd.Run(); err != nil {
|
||||||
|
log.Debugf("git fetch tags failed (continuing with local tags): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
latestTagCmd := exec.Command("git", "tag", "-l", "v*", "--sort=-version:refname")
|
latestTagCmd := exec.Command("git", "tag", "-l", "v*", "--sort=-version:refname")
|
||||||
latestTagOutput, err := latestTagCmd.Output()
|
latestTagOutput, err := latestTagCmd.Output()
|
||||||
@@ -109,7 +121,9 @@ func (d *DefaultVersionFetcher) GetLatestVersion(dmsPath string) (string, error)
|
|||||||
|
|
||||||
// Add timeout to git fetch to prevent hanging
|
// Add timeout to git fetch to prevent hanging
|
||||||
fetchCmd := exec.Command("timeout", "5s", "git", "fetch", "origin", currentBranch, "--quiet")
|
fetchCmd := exec.Command("timeout", "5s", "git", "fetch", "origin", currentBranch, "--quiet")
|
||||||
fetchCmd.Run()
|
if err := fetchCmd.Run(); err != nil {
|
||||||
|
log.Debugf("git fetch branch failed (continuing with local ref): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
remoteRevCmd := exec.Command("git", "rev-parse", "--short", fmt.Sprintf("origin/%s", currentBranch))
|
remoteRevCmd := exec.Command("git", "rev-parse", "--short", fmt.Sprintf("origin/%s", currentBranch))
|
||||||
remoteRevOutput, err := remoteRevCmd.Output()
|
remoteRevOutput, err := remoteRevCmd.Output()
|
||||||
@@ -236,10 +250,10 @@ func CompareVersions(v1, v2 string) int {
|
|||||||
for i := 0; i < maxLen; i++ {
|
for i := 0; i < maxLen; i++ {
|
||||||
var p1, p2 int
|
var p1, p2 int
|
||||||
if i < len(parts1) {
|
if i < len(parts1) {
|
||||||
fmt.Sscanf(parts1[i], "%d", &p1)
|
fmt.Sscanf(parts1[i], "%d", &p1) //nolint:errcheck
|
||||||
}
|
}
|
||||||
if i < len(parts2) {
|
if i < len(parts2) {
|
||||||
fmt.Sscanf(parts2[i], "%d", &p2)
|
fmt.Sscanf(parts2[i], "%d", &p2) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
if p1 < p2 {
|
if p1 < p2 {
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ func (i *Display) Sync() (*Callback, error) {
|
|||||||
PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
|
PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
|
||||||
l += 4
|
l += 4
|
||||||
PutUint32(_reqBuf[l:l+4], callback.ID())
|
PutUint32(_reqBuf[l:l+4], callback.ID())
|
||||||
l += 4
|
|
||||||
err := i.Context().WriteMsg(_reqBuf[:], nil)
|
err := i.Context().WriteMsg(_reqBuf[:], nil)
|
||||||
return callback, err
|
return callback, err
|
||||||
}
|
}
|
||||||
@@ -109,7 +108,6 @@ func (i *Display) GetRegistry() (*Registry, error) {
|
|||||||
PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
|
PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff))
|
||||||
l += 4
|
l += 4
|
||||||
PutUint32(_reqBuf[l:l+4], registry.ID())
|
PutUint32(_reqBuf[l:l+4], registry.ID())
|
||||||
l += 4
|
|
||||||
err := i.Context().WriteMsg(_reqBuf[:], nil)
|
err := i.Context().WriteMsg(_reqBuf[:], nil)
|
||||||
return registry, err
|
return registry, err
|
||||||
}
|
}
|
||||||
@@ -223,7 +221,6 @@ func (i *Display) Dispatch(opcode uint32, fd int, data []byte) {
|
|||||||
messageLen := PaddedLen(int(Uint32(data[l : l+4])))
|
messageLen := PaddedLen(int(Uint32(data[l : l+4])))
|
||||||
l += 4
|
l += 4
|
||||||
e.Message = String(data[l : l+messageLen])
|
e.Message = String(data[l : l+messageLen])
|
||||||
l += messageLen
|
|
||||||
|
|
||||||
i.errorHandler(e)
|
i.errorHandler(e)
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
pname = "dmsCli";
|
pname = "dmsCli";
|
||||||
src = ./core;
|
src = ./core;
|
||||||
vendorHash = "sha256-nc4CvEPfJ6l16/zmhnXr1jqpi6BeSXd3g/51djbEfpQ=";
|
vendorHash = "sha256-XBPJVgncI98VFch3wwkq1/m5Jm7DrV4oGS2p1bPJRag=";
|
||||||
|
|
||||||
subPackages = ["cmd/dms"];
|
subPackages = ["cmd/dms"];
|
||||||
|
|
||||||
|
|||||||
@@ -108,10 +108,13 @@ Item {
|
|||||||
id: barRepeaterModel
|
id: barRepeaterModel
|
||||||
values: {
|
values: {
|
||||||
const configs = SettingsData.barConfigs;
|
const configs = SettingsData.barConfigs;
|
||||||
return configs.map(c => ({
|
return configs
|
||||||
id: c.id,
|
.map(c => ({ id: c.id, position: c.position }))
|
||||||
position: c.position
|
.sort((a, b) => {
|
||||||
}));
|
const aVertical = a.position === SettingsData.Position.Left || a.position === SettingsData.Position.Right;
|
||||||
|
const bVertical = b.position === SettingsData.Position.Left || b.position === SettingsData.Position.Right;
|
||||||
|
return aVertical - bVertical;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +123,7 @@ Item {
|
|||||||
delegate: Loader {
|
delegate: Loader {
|
||||||
id: barLoader
|
id: barLoader
|
||||||
required property var modelData
|
required property var modelData
|
||||||
property var barConfig: SettingsData.getBarConfig(modelData.id)
|
property var barConfig: SettingsData.barConfigs.find(cfg => cfg.id === modelData.id) || null
|
||||||
active: barConfig?.enabled ?? false
|
active: barConfig?.enabled ?? false
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
|
||||||
@@ -360,11 +363,33 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsModal {
|
LazyLoader {
|
||||||
id: settingsModal
|
id: settingsModalLoader
|
||||||
|
|
||||||
|
active: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
PopoutService.settingsModal = settingsModal;
|
PopoutService.settingsModalLoader = settingsModalLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
if (active && item) {
|
||||||
|
PopoutService.settingsModal = item;
|
||||||
|
PopoutService._onSettingsModalLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsModal {
|
||||||
|
id: settingsModal
|
||||||
|
property bool wasShown: false
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
wasShown = true;
|
||||||
|
} else if (wasShown) {
|
||||||
|
PopoutService.unloadSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +559,6 @@ Item {
|
|||||||
hyprKeybindsModalLoader: hyprKeybindsModalLoader
|
hyprKeybindsModalLoader: hyprKeybindsModalLoader
|
||||||
dankBarRepeater: dankBarRepeater
|
dankBarRepeater: dankBarRepeater
|
||||||
hyprlandOverviewLoader: hyprlandOverviewLoader
|
hyprlandOverviewLoader: hyprlandOverviewLoader
|
||||||
settingsModal: settingsModal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ Item {
|
|||||||
required property var hyprKeybindsModalLoader
|
required property var hyprKeybindsModalLoader
|
||||||
required property var dankBarRepeater
|
required property var dankBarRepeater
|
||||||
required property var hyprlandOverviewLoader
|
required property var hyprlandOverviewLoader
|
||||||
required property var settingsModal
|
|
||||||
|
|
||||||
function getFirstBar() {
|
function getFirstBar() {
|
||||||
if (!root.dankBarRepeater || root.dankBarRepeater.count === 0)
|
if (!root.dankBarRepeater || root.dankBarRepeater.count === 0)
|
||||||
@@ -533,17 +532,17 @@ Item {
|
|||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function open(): string {
|
function open(): string {
|
||||||
root.settingsModal.show();
|
PopoutService.openSettings();
|
||||||
return "SETTINGS_OPEN_SUCCESS";
|
return "SETTINGS_OPEN_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function close(): string {
|
function close(): string {
|
||||||
root.settingsModal.hide();
|
PopoutService.closeSettings();
|
||||||
return "SETTINGS_CLOSE_SUCCESS";
|
return "SETTINGS_CLOSE_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle(): string {
|
function toggle(): string {
|
||||||
root.settingsModal.toggle();
|
PopoutService.toggleSettings();
|
||||||
return "SETTINGS_TOGGLE_SUCCESS";
|
return "SETTINGS_TOGGLE_SUCCESS";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,12 +551,17 @@ Item {
|
|||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function browse(type: string) {
|
function browse(type: string) {
|
||||||
if (type === "wallpaper") {
|
const modal = PopoutService.settingsModal;
|
||||||
root.settingsModal.wallpaperBrowser.allowStacking = false;
|
if (modal) {
|
||||||
root.settingsModal.wallpaperBrowser.open();
|
if (type === "wallpaper") {
|
||||||
} else if (type === "profile") {
|
modal.wallpaperBrowser.allowStacking = false;
|
||||||
root.settingsModal.profileBrowser.allowStacking = false;
|
modal.wallpaperBrowser.open();
|
||||||
root.settingsModal.profileBrowser.open();
|
} else if (type === "profile") {
|
||||||
|
modal.profileBrowser.allowStacking = false;
|
||||||
|
modal.profileBrowser.open();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PopoutService.openSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +172,7 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SessionData.isGreeterMode ? GreetdSettings.wallpaperFillMode : SettingsData.wallpaperFillMode)
|
||||||
|
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
@@ -218,14 +220,16 @@ Variants {
|
|||||||
duration: 1000
|
duration: 1000
|
||||||
easing.type: Easing.InOutCubic
|
easing.type: Easing.InOutCubic
|
||||||
onFinished: {
|
onFinished: {
|
||||||
|
const tempSource = nextWallpaper.source;
|
||||||
|
if (tempSource && nextWallpaper.status === Image.Ready && !tempSource.toString().startsWith("#")) {
|
||||||
|
currentWallpaper.source = tempSource;
|
||||||
|
}
|
||||||
|
root.transitionProgress = 0.0;
|
||||||
|
currentWallpaper.opacity = 1;
|
||||||
|
nextWallpaper.opacity = 0;
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
|
|
||||||
currentWallpaper.source = nextWallpaper.source;
|
|
||||||
}
|
|
||||||
nextWallpaper.source = "";
|
nextWallpaper.source = "";
|
||||||
currentWallpaper.opacity = 1;
|
|
||||||
nextWallpaper.opacity = 0;
|
|
||||||
root.transitionProgress = 0.0;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ Rectangle {
|
|||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.settingsButtonClicked();
|
root.settingsButtonClicked();
|
||||||
settingsModal.show();
|
PopoutService.openSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,32 +28,9 @@ Item {
|
|||||||
readonly property real wing: gothEnabled ? barWindow._wingR : 0
|
readonly property real wing: gothEnabled ? barWindow._wingR : 0
|
||||||
readonly property real rt: (barConfig?.squareCorners ?? false) ? 0 : Theme.cornerRadius
|
readonly property real rt: (barConfig?.squareCorners ?? false) ? 0 : Theme.cornerRadius
|
||||||
|
|
||||||
property string _cachedMainPath: ""
|
readonly property string mainPath: generatePathForPosition(width, height)
|
||||||
property string _cachedBorderFullPath: ""
|
readonly property string borderFullPath: generateBorderFullPath(width, height)
|
||||||
property string _cachedBorderEdgePath: ""
|
readonly property string borderEdgePath: generateBorderEdgePath(width, height)
|
||||||
property string _pathKey: ""
|
|
||||||
|
|
||||||
readonly property string currentPathKey: `${width}|${height}|${barPos}|${wing}|${rt}|${barBorder.inset}`
|
|
||||||
|
|
||||||
onCurrentPathKeyChanged: {
|
|
||||||
if (_pathKey !== currentPathKey) {
|
|
||||||
_pathKey = currentPathKey;
|
|
||||||
_cachedMainPath = generatePathForPosition();
|
|
||||||
_cachedBorderFullPath = generateBorderFullPath();
|
|
||||||
_cachedBorderEdgePath = generateBorderEdgePath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
_pathKey = currentPathKey;
|
|
||||||
_cachedMainPath = generatePathForPosition();
|
|
||||||
_cachedBorderFullPath = generateBorderFullPath();
|
|
||||||
_cachedBorderEdgePath = generateBorderEdgePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property string mainPath: _cachedMainPath
|
|
||||||
readonly property string borderFullPath: _cachedBorderFullPath
|
|
||||||
readonly property string borderEdgePath: _cachedBorderEdgePath
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -90,24 +67,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape {
|
|
||||||
id: barTint
|
|
||||||
anchors.fill: parent
|
|
||||||
preferredRendererType: Shape.CurveRenderer
|
|
||||||
|
|
||||||
readonly property real alphaTint: (barWindow._bgColor?.a ?? 1) < 0.99 ? (Theme.stateLayerOpacity ?? 0) : 0
|
|
||||||
|
|
||||||
ShapePath {
|
|
||||||
fillColor: Qt.rgba(Theme.surface.r, Theme.surface.g, Theme.surface.b, barTint.alphaTint)
|
|
||||||
strokeColor: "transparent"
|
|
||||||
strokeWidth: 0
|
|
||||||
|
|
||||||
PathSvg {
|
|
||||||
path: root.mainPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Shape {
|
Shape {
|
||||||
id: barBorder
|
id: barBorder
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -134,16 +93,16 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generatePathForPosition() {
|
function generatePathForPosition(w, h) {
|
||||||
if (isTop)
|
if (isTop)
|
||||||
return generateTopPath();
|
return generateTopPath(w, h);
|
||||||
if (isBottom)
|
if (isBottom)
|
||||||
return generateBottomPath();
|
return generateBottomPath(w, h);
|
||||||
if (isLeft)
|
if (isLeft)
|
||||||
return generateLeftPath();
|
return generateLeftPath(w, h);
|
||||||
if (isRight)
|
if (isRight)
|
||||||
return generateRightPath();
|
return generateRightPath(w, h);
|
||||||
return generateTopPath();
|
return generateTopPath(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateBorderPathForPosition() {
|
function generateBorderPathForPosition() {
|
||||||
@@ -158,15 +117,11 @@ Item {
|
|||||||
return generateTopBorderPath();
|
return generateTopBorderPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateTopPath() {
|
function generateTopPath(w, h) {
|
||||||
const w = width;
|
h = h - wing;
|
||||||
const h = height - wing;
|
|
||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = `M ${cr} 0`;
|
let d = `M ${cr} 0`;
|
||||||
d += ` L ${w - cr} 0`;
|
d += ` L ${w - cr} 0`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
@@ -191,19 +146,16 @@ Item {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateBottomPath() {
|
function generateBottomPath(w, h) {
|
||||||
const w = width;
|
const fullH = h;
|
||||||
const h = height - wing;
|
h = h - wing;
|
||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
let d = `M ${cr} ${fullH}`;
|
||||||
return "";
|
d += ` L ${w - cr} ${fullH}`;
|
||||||
|
|
||||||
let d = `M ${cr} ${height}`;
|
|
||||||
d += ` L ${w - cr} ${height}`;
|
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 ${w} ${height - cr}`;
|
d += ` A ${cr} ${cr} 0 0 0 ${w} ${fullH - cr}`;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d += ` L ${w} 0`;
|
d += ` L ${w} 0`;
|
||||||
d += ` A ${r} ${r} 0 0 1 ${w - r} ${r}`;
|
d += ` A ${r} ${r} 0 0 1 ${w - r} ${r}`;
|
||||||
@@ -217,22 +169,18 @@ Item {
|
|||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 0 ${cr}`;
|
d += ` A ${cr} ${cr} 0 0 0 0 ${cr}`;
|
||||||
}
|
}
|
||||||
d += ` L 0 ${height - cr}`;
|
d += ` L 0 ${fullH - cr}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 ${cr} ${height}`;
|
d += ` A ${cr} ${cr} 0 0 0 ${cr} ${fullH}`;
|
||||||
d += " Z";
|
d += " Z";
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateLeftPath() {
|
function generateLeftPath(w, h) {
|
||||||
const w = width - wing;
|
w = w - wing;
|
||||||
const h = height;
|
|
||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = `M 0 ${cr}`;
|
let d = `M 0 ${cr}`;
|
||||||
d += ` L 0 ${h - cr}`;
|
d += ` L 0 ${h - cr}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
@@ -257,19 +205,16 @@ Item {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateRightPath() {
|
function generateRightPath(w, h) {
|
||||||
const w = width - wing;
|
const fullW = w;
|
||||||
const h = height;
|
w = w - wing;
|
||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
let d = `M ${fullW} ${cr}`;
|
||||||
return "";
|
d += ` L ${fullW} ${h - cr}`;
|
||||||
|
|
||||||
let d = `M ${width} ${cr}`;
|
|
||||||
d += ` L ${width} ${h - cr}`;
|
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${width - cr} ${h}`;
|
d += ` A ${cr} ${cr} 0 0 1 ${fullW - cr} ${h}`;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d += ` L 0 ${h}`;
|
d += ` L 0 ${h}`;
|
||||||
d += ` A ${r} ${r} 0 0 0 ${r} ${h - r}`;
|
d += ` A ${r} ${r} 0 0 0 ${r} ${h - r}`;
|
||||||
@@ -283,9 +228,9 @@ Item {
|
|||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${cr} 0`;
|
d += ` A ${cr} ${cr} 0 0 1 ${cr} 0`;
|
||||||
}
|
}
|
||||||
d += ` L ${width - cr} 0`;
|
d += ` L ${fullW - cr} 0`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${width} ${cr}`;
|
d += ` A ${cr} ${cr} 0 0 1 ${fullW} ${cr}`;
|
||||||
d += " Z";
|
d += " Z";
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -296,9 +241,6 @@ Item {
|
|||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d = `M ${w} ${h + r}`;
|
d = `M ${w} ${h + r}`;
|
||||||
@@ -321,9 +263,6 @@ Item {
|
|||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (w <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d = `M ${w} 0`;
|
d = `M ${w} 0`;
|
||||||
@@ -347,9 +286,6 @@ Item {
|
|||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d = `M ${w + r} ${h}`;
|
d = `M ${w + r} ${h}`;
|
||||||
@@ -372,9 +308,6 @@ Item {
|
|||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d = `M 0 ${h}`;
|
d = `M 0 ${h}`;
|
||||||
@@ -392,26 +325,24 @@ Item {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateBorderFullPath() {
|
function generateBorderFullPath(fullW, fullH) {
|
||||||
const i = barBorder.inset;
|
const i = barBorder.inset;
|
||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (isTop) {
|
if (isTop) {
|
||||||
const w = width - i * 2;
|
const w = fullW - i * 2;
|
||||||
const h = height - wing - i * 2;
|
const h = fullH - wing - i * 2;
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = `M ${i + cr} ${i}`;
|
let d = `M ${i + cr} ${i}`;
|
||||||
d += ` L ${i + w - cr} ${i}`;
|
d += ` L ${i + w - cr} ${i}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${i + w} ${i + cr}`;
|
d += ` A ${cr} ${cr} 0 0 1 ${i + w} ${i + cr}`;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d += ` L ${i + w} ${height - i}`;
|
d += ` L ${i + w} ${fullH - i}`;
|
||||||
d += ` A ${r} ${r} 0 0 0 ${i + w - r} ${i + h}`;
|
d += ` A ${r} ${r} 0 0 0 ${i + w - r} ${i + h}`;
|
||||||
d += ` L ${i + r} ${i + h}`;
|
d += ` L ${i + r} ${i + h}`;
|
||||||
d += ` A ${r} ${r} 0 0 0 ${i} ${height - i}`;
|
d += ` A ${r} ${r} 0 0 0 ${i} ${fullH - i}`;
|
||||||
} else {
|
} else {
|
||||||
d += ` L ${i + w} ${i + h - cr}`;
|
d += ` L ${i + w} ${i + h - cr}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
@@ -428,15 +359,13 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
const w = width - i * 2;
|
const w = fullW - i * 2;
|
||||||
const h = height - wing - i * 2;
|
const h = fullH - wing - i * 2;
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = `M ${i + cr} ${height - i}`;
|
let d = `M ${i + cr} ${fullH - i}`;
|
||||||
d += ` L ${i + w - cr} ${height - i}`;
|
d += ` L ${i + w - cr} ${fullH - i}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 ${i + w} ${height - i - cr}`;
|
d += ` A ${cr} ${cr} 0 0 0 ${i + w} ${fullH - i - cr}`;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d += ` L ${i + w} ${i}`;
|
d += ` L ${i + w} ${i}`;
|
||||||
d += ` A ${r} ${r} 0 0 1 ${i + w - r} ${i + r}`;
|
d += ` A ${r} ${r} 0 0 1 ${i + w - r} ${i + r}`;
|
||||||
@@ -450,28 +379,26 @@ Item {
|
|||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 ${i} ${i + cr}`;
|
d += ` A ${cr} ${cr} 0 0 0 ${i} ${i + cr}`;
|
||||||
}
|
}
|
||||||
d += ` L ${i} ${height - i - cr}`;
|
d += ` L ${i} ${fullH - i - cr}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 ${i + cr} ${height - i}`;
|
d += ` A ${cr} ${cr} 0 0 0 ${i + cr} ${fullH - i}`;
|
||||||
d += " Z";
|
d += " Z";
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLeft) {
|
if (isLeft) {
|
||||||
const w = width - wing - i * 2;
|
const w = fullW - wing - i * 2;
|
||||||
const h = height - i * 2;
|
const h = fullH - i * 2;
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = `M ${i} ${i + cr}`;
|
let d = `M ${i} ${i + cr}`;
|
||||||
d += ` L ${i} ${i + h - cr}`;
|
d += ` L ${i} ${i + h - cr}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 0 ${i + cr} ${i + h}`;
|
d += ` A ${cr} ${cr} 0 0 0 ${i + cr} ${i + h}`;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d += ` L ${width - i} ${i + h}`;
|
d += ` L ${fullW - i} ${i + h}`;
|
||||||
d += ` A ${r} ${r} 0 0 1 ${i + w} ${i + h - r}`;
|
d += ` A ${r} ${r} 0 0 1 ${i + w} ${i + h - r}`;
|
||||||
d += ` L ${i + w} ${i + r}`;
|
d += ` L ${i + w} ${i + r}`;
|
||||||
d += ` A ${r} ${r} 0 0 1 ${width - i} ${i}`;
|
d += ` A ${r} ${r} 0 0 1 ${fullW - i} ${i}`;
|
||||||
} else {
|
} else {
|
||||||
d += ` L ${i + w - cr} ${i + h}`;
|
d += ` L ${i + w - cr} ${i + h}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
@@ -488,15 +415,13 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isRight) {
|
if (isRight) {
|
||||||
const w = width - wing - i * 2;
|
const w = fullW - wing - i * 2;
|
||||||
const h = height - i * 2;
|
const h = fullH - i * 2;
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = `M ${width - i} ${i + cr}`;
|
let d = `M ${fullW - i} ${i + cr}`;
|
||||||
d += ` L ${width - i} ${i + h - cr}`;
|
d += ` L ${fullW - i} ${i + h - cr}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${width - i - cr} ${i + h}`;
|
d += ` A ${cr} ${cr} 0 0 1 ${fullW - i - cr} ${i + h}`;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
d += ` L ${i} ${i + h}`;
|
d += ` L ${i} ${i + h}`;
|
||||||
d += ` A ${r} ${r} 0 0 0 ${i + r} ${i + h - r}`;
|
d += ` A ${r} ${r} 0 0 0 ${i + r} ${i + h - r}`;
|
||||||
@@ -510,9 +435,9 @@ Item {
|
|||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${wing + i + cr} ${i}`;
|
d += ` A ${cr} ${cr} 0 0 1 ${wing + i + cr} ${i}`;
|
||||||
}
|
}
|
||||||
d += ` L ${width - i - cr} ${i}`;
|
d += ` L ${fullW - i - cr} ${i}`;
|
||||||
if (cr > 0)
|
if (cr > 0)
|
||||||
d += ` A ${cr} ${cr} 0 0 1 ${width - i} ${i + cr}`;
|
d += ` A ${cr} ${cr} 0 0 1 ${fullW - i} ${i + cr}`;
|
||||||
d += " Z";
|
d += " Z";
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -520,16 +445,14 @@ Item {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateBorderEdgePath() {
|
function generateBorderEdgePath(fullW, fullH) {
|
||||||
const i = barBorder.inset;
|
const i = barBorder.inset;
|
||||||
const r = wing;
|
const r = wing;
|
||||||
const cr = rt;
|
const cr = rt;
|
||||||
|
|
||||||
if (isTop) {
|
if (isTop) {
|
||||||
const w = width - i * 2;
|
const w = fullW - i * 2;
|
||||||
const h = height - wing - i * 2;
|
const h = fullH - wing - i * 2;
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
@@ -549,9 +472,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
const w = width - i * 2;
|
const w = fullW - i * 2;
|
||||||
if (w <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
@@ -571,10 +492,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isLeft) {
|
if (isLeft) {
|
||||||
const w = width - wing - i * 2;
|
const w = fullW - wing - i * 2;
|
||||||
const h = height - i * 2;
|
const h = fullH - i * 2;
|
||||||
if (h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
@@ -594,9 +513,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isRight) {
|
if (isRight) {
|
||||||
const h = height - i * 2;
|
const h = fullH - i * 2;
|
||||||
if (h <= 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
let d = "";
|
let d = "";
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
|
|||||||
@@ -140,7 +140,9 @@ PanelWindow {
|
|||||||
property real wingtipsRadius: barConfig?.gothCornerRadiusOverride ? (barConfig?.gothCornerRadiusValue ?? 12) : Theme.cornerRadius
|
property real wingtipsRadius: barConfig?.gothCornerRadiusOverride ? (barConfig?.gothCornerRadiusValue ?? 12) : Theme.cornerRadius
|
||||||
readonly property real _wingR: Math.max(0, wingtipsRadius)
|
readonly property real _wingR: Math.max(0, wingtipsRadius)
|
||||||
readonly property color _surfaceContainer: Theme.surfaceContainer
|
readonly property color _surfaceContainer: Theme.surfaceContainer
|
||||||
readonly property real _backgroundAlpha: topBarCore?.backgroundTransparency ?? (barConfig?.transparency ?? 1.0)
|
readonly property string _barId: barConfig?.id ?? "default"
|
||||||
|
readonly property var _liveBarConfig: SettingsData.barConfigs.find(c => c.id === _barId) || barConfig
|
||||||
|
readonly property real _backgroundAlpha: _liveBarConfig?.transparency ?? 1.0
|
||||||
readonly property color _bgColor: Theme.withAlpha(_surfaceContainer, _backgroundAlpha)
|
readonly property color _bgColor: Theme.withAlpha(_surfaceContainer, _backgroundAlpha)
|
||||||
readonly property real _dpr: CompositorService.getScreenScale(barWindow.screen)
|
readonly property real _dpr: CompositorService.getScreenScale(barWindow.screen)
|
||||||
|
|
||||||
@@ -419,7 +421,6 @@ PanelWindow {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
|
||||||
property real backgroundTransparency: barConfig?.transparency ?? 1.0
|
|
||||||
property bool autoHide: barConfig?.autoHide ?? false
|
property bool autoHide: barConfig?.autoHide ?? false
|
||||||
property bool revealSticky: false
|
property bool revealSticky: false
|
||||||
|
|
||||||
@@ -471,7 +472,6 @@ PanelWindow {
|
|||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onBarConfigChanged() {
|
function onBarConfigChanged() {
|
||||||
topBarCore.backgroundTransparency = barConfig?.transparency ?? 1.0;
|
|
||||||
topBarCore.autoHide = barConfig?.autoHide ?? false;
|
topBarCore.autoHide = barConfig?.autoHide ?? false;
|
||||||
revealHold.interval = barConfig?.autoHideDelay ?? 250;
|
revealHold.interval = barConfig?.autoHideDelay ?? 250;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ BasePill {
|
|||||||
|
|
||||||
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
||||||
readonly property bool playerAvailable: activePlayer !== null
|
readonly property bool playerAvailable: activePlayer !== null
|
||||||
|
readonly property bool __isChromeBrowser: {
|
||||||
|
if (!activePlayer?.identity)
|
||||||
|
return false;
|
||||||
|
const id = activePlayer.identity.toLowerCase();
|
||||||
|
return id.includes("chrome") || id.includes("chromium");
|
||||||
|
}
|
||||||
|
readonly property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
|
||||||
property bool compactMode: false
|
property bool compactMode: false
|
||||||
property var widgetData: null
|
property var widgetData: null
|
||||||
readonly property int textWidth: {
|
readonly property int textWidth: {
|
||||||
@@ -49,14 +56,8 @@ BasePill {
|
|||||||
|
|
||||||
wheelEvent.accepted = true;
|
wheelEvent.accepted = true;
|
||||||
|
|
||||||
// If volume is not supported, return early to avoid error logs but accepting the scroll,
|
|
||||||
// to keep the consistency of not scrolling workspaces when scrolling in the media widget.
|
|
||||||
if (!activePlayer.volumeSupported) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const delta = wheelEvent.angleDelta.y;
|
const delta = wheelEvent.angleDelta.y;
|
||||||
const currentVolume = (activePlayer.volume * 100) || 0;
|
const currentVolume = usePlayerVolume ? (activePlayer.volume * 100) : ((AudioService.sink?.audio?.volume ?? 0) * 100);
|
||||||
|
|
||||||
let newVolume;
|
let newVolume;
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
@@ -65,7 +66,11 @@ BasePill {
|
|||||||
newVolume = Math.max(0, currentVolume - 5);
|
newVolume = Math.max(0, currentVolume - 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
activePlayer.volume = newVolume / 100;
|
if (usePlayerVolume) {
|
||||||
|
activePlayer.volume = newVolume / 100;
|
||||||
|
} else if (AudioService.sink?.audio) {
|
||||||
|
AudioService.sink.audio.volume = newVolume / 100;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content: Component {
|
content: Component {
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ DankPopout {
|
|||||||
let settingsIndex = SettingsData.weatherEnabled ? 4 : 3;
|
let settingsIndex = SettingsData.weatherEnabled ? 4 : 3;
|
||||||
if (index === settingsIndex) {
|
if (index === settingsIndex) {
|
||||||
dashVisible = false;
|
dashVisible = false;
|
||||||
settingsModal.show();
|
PopoutService.openSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,18 @@ DankOSD {
|
|||||||
readonly property var player: MprisController.activePlayer
|
readonly property var player: MprisController.activePlayer
|
||||||
readonly property int currentVolume: player ? Math.min(100, Math.round(player.volume * 100)) : 0
|
readonly property int currentVolume: player ? Math.min(100, Math.round(player.volume * 100)) : 0
|
||||||
readonly property bool volumeSupported: player?.volumeSupported ?? false
|
readonly property bool volumeSupported: player?.volumeSupported ?? false
|
||||||
|
property bool _suppressNewPlayer: false
|
||||||
|
|
||||||
|
onPlayerChanged: {
|
||||||
|
_suppressNewPlayer = true;
|
||||||
|
_suppressTimer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: _suppressTimer
|
||||||
|
interval: 2000
|
||||||
|
onTriggered: _suppressNewPlayer = false
|
||||||
|
}
|
||||||
|
|
||||||
osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2)
|
osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2)
|
||||||
osdHeight: useVertical ? Math.min(260, Screen.height - Theme.spacingM * 2) : (40 + Theme.spacingS * 2)
|
osdHeight: useVertical ? Math.min(260, Screen.height - Theme.spacingM * 2) : (40 + Theme.spacingS * 2)
|
||||||
@@ -41,7 +53,7 @@ DankOSD {
|
|||||||
target: player
|
target: player
|
||||||
|
|
||||||
function onVolumeChanged() {
|
function onVolumeChanged() {
|
||||||
if (SettingsData.osdMediaVolumeEnabled && volumeSupported) {
|
if (SettingsData.osdMediaVolumeEnabled && volumeSupported && !_suppressNewPlayer) {
|
||||||
root.show();
|
root.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (root.contentHeight === 0 && item) {
|
if (root.contentHeight === 0 && item) {
|
||||||
root.contentHeight = item.implicitHeight + Theme.spacingS * 2
|
root.contentHeight = Qt.binding(() => item.implicitHeight + Theme.spacingS * 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,16 @@ import QtQuick
|
|||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Widgets
|
|
||||||
import Quickshell.Io
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Modules
|
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
model: {
|
model: {
|
||||||
if (SessionData.isGreeterMode) {
|
if (SessionData.isGreeterMode) {
|
||||||
return Quickshell.screens
|
return Quickshell.screens;
|
||||||
}
|
}
|
||||||
return SettingsData.getFilteredScreens("wallpaper")
|
return SettingsData.getFilteredScreens("wallpaper");
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
@@ -52,9 +49,9 @@ Variants {
|
|||||||
target: SessionData
|
target: SessionData
|
||||||
function onIsLightModeChanged() {
|
function onIsLightModeChanged() {
|
||||||
if (SessionData.perModeWallpaper) {
|
if (SessionData.perModeWallpaper) {
|
||||||
var newSource = SessionData.getMonitorWallpaper(modelData.name) || ""
|
var newSource = SessionData.getMonitorWallpaper(modelData.name) || "";
|
||||||
if (newSource !== root.source) {
|
if (newSource !== root.source) {
|
||||||
root.source = newSource
|
root.source = newSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,19 +59,19 @@ Variants {
|
|||||||
onTransitionTypeChanged: {
|
onTransitionTypeChanged: {
|
||||||
if (transitionType === "random") {
|
if (transitionType === "random") {
|
||||||
if (SessionData.includedTransitions.length === 0) {
|
if (SessionData.includedTransitions.length === 0) {
|
||||||
actualTransitionType = "none"
|
actualTransitionType = "none";
|
||||||
} else {
|
} else {
|
||||||
actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
|
actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actualTransitionType = transitionType
|
actualTransitionType = transitionType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onActualTransitionTypeChanged: {
|
onActualTransitionTypeChanged: {
|
||||||
if (actualTransitionType === "none") {
|
if (actualTransitionType === "none") {
|
||||||
currentWallpaper.visible = true
|
currentWallpaper.visible = true;
|
||||||
nextWallpaper.visible = false
|
nextWallpaper.visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
property real transitionProgress: 0
|
property real transitionProgress: 0
|
||||||
@@ -94,103 +91,110 @@ Variants {
|
|||||||
property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready
|
property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready
|
||||||
|
|
||||||
function getFillMode(modeName) {
|
function getFillMode(modeName) {
|
||||||
switch(modeName) {
|
switch (modeName) {
|
||||||
case "Stretch": return Image.Stretch
|
case "Stretch":
|
||||||
case "Fit":
|
return Image.Stretch;
|
||||||
case "PreserveAspectFit": return Image.PreserveAspectFit
|
case "Fit":
|
||||||
case "Fill":
|
case "PreserveAspectFit":
|
||||||
case "PreserveAspectCrop": return Image.PreserveAspectCrop
|
return Image.PreserveAspectFit;
|
||||||
case "Tile": return Image.Tile
|
case "Fill":
|
||||||
case "TileVertically": return Image.TileVertically
|
case "PreserveAspectCrop":
|
||||||
case "TileHorizontally": return Image.TileHorizontally
|
return Image.PreserveAspectCrop;
|
||||||
case "Pad": return Image.Pad
|
case "Tile":
|
||||||
default: return Image.PreserveAspectCrop
|
return Image.Tile;
|
||||||
|
case "TileVertically":
|
||||||
|
return Image.TileVertically;
|
||||||
|
case "TileHorizontally":
|
||||||
|
return Image.TileHorizontally;
|
||||||
|
case "Pad":
|
||||||
|
return Image.Pad;
|
||||||
|
default:
|
||||||
|
return Image.PreserveAspectCrop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (source) {
|
if (source) {
|
||||||
const formattedSource = source.startsWith("file://") ? source : "file://" + source
|
const formattedSource = source.startsWith("file://") ? source : "file://" + source;
|
||||||
setWallpaperImmediate(formattedSource)
|
setWallpaperImmediate(formattedSource);
|
||||||
}
|
}
|
||||||
isInitialized = true
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSourceChanged: {
|
onSourceChanged: {
|
||||||
const isColor = source.startsWith("#")
|
const isColor = source.startsWith("#");
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
setWallpaperImmediate("")
|
setWallpaperImmediate("");
|
||||||
} else if (isColor) {
|
} else if (isColor) {
|
||||||
setWallpaperImmediate("")
|
setWallpaperImmediate("");
|
||||||
} else {
|
} else {
|
||||||
if (!isInitialized || !currentWallpaper.source) {
|
if (!isInitialized || !currentWallpaper.source) {
|
||||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source)
|
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source);
|
||||||
isInitialized = true
|
isInitialized = true;
|
||||||
} else if (CompositorService.isNiri && SessionData.isSwitchingMode) {
|
} else if (CompositorService.isNiri && SessionData.isSwitchingMode) {
|
||||||
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source)
|
setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source);
|
||||||
} else {
|
} else {
|
||||||
changeWallpaper(source.startsWith("file://") ? source : "file://" + source)
|
changeWallpaper(source.startsWith("file://") ? source : "file://" + source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWallpaperImmediate(newSource) {
|
function setWallpaperImmediate(newSource) {
|
||||||
transitionAnimation.stop()
|
transitionAnimation.stop();
|
||||||
root.transitionProgress = 0.0
|
root.transitionProgress = 0.0;
|
||||||
currentWallpaper.source = newSource
|
currentWallpaper.source = newSource;
|
||||||
nextWallpaper.source = ""
|
nextWallpaper.source = "";
|
||||||
currentWallpaper.visible = true
|
currentWallpaper.visible = true;
|
||||||
nextWallpaper.visible = false
|
nextWallpaper.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeWallpaper(newPath, force) {
|
function changeWallpaper(newPath, force) {
|
||||||
if (!force && newPath === currentWallpaper.source)
|
if (!force && newPath === currentWallpaper.source)
|
||||||
return
|
return;
|
||||||
if (!newPath || newPath.startsWith("#"))
|
if (!newPath || newPath.startsWith("#"))
|
||||||
return
|
return;
|
||||||
|
|
||||||
if (root.transitioning) {
|
if (root.transitioning) {
|
||||||
transitionAnimation.stop()
|
transitionAnimation.stop();
|
||||||
root.transitionProgress = 0
|
root.transitionProgress = 0;
|
||||||
currentWallpaper.source = nextWallpaper.source
|
currentWallpaper.source = nextWallpaper.source;
|
||||||
nextWallpaper.source = ""
|
nextWallpaper.source = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no current wallpaper, set immediately to avoid scaling issues
|
// If no current wallpaper, set immediately to avoid scaling issues
|
||||||
if (!currentWallpaper.source) {
|
if (!currentWallpaper.source) {
|
||||||
setWallpaperImmediate(newPath)
|
setWallpaperImmediate(newPath);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If transition is "none", set immediately
|
// If transition is "none", set immediately
|
||||||
if (root.transitionType === "random") {
|
if (root.transitionType === "random") {
|
||||||
if (SessionData.includedTransitions.length === 0) {
|
if (SessionData.includedTransitions.length === 0) {
|
||||||
root.actualTransitionType = "none"
|
root.actualTransitionType = "none";
|
||||||
} else {
|
} else {
|
||||||
root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
|
root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.actualTransitionType === "none") {
|
if (root.actualTransitionType === "none") {
|
||||||
setWallpaperImmediate(newPath)
|
setWallpaperImmediate(newPath);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.actualTransitionType === "wipe") {
|
if (root.actualTransitionType === "wipe") {
|
||||||
root.wipeDirection = Math.random() * 4
|
root.wipeDirection = Math.random() * 4;
|
||||||
} else if (root.actualTransitionType === "disc") {
|
} else if (root.actualTransitionType === "disc") {
|
||||||
root.discCenterX = Math.random()
|
root.discCenterX = Math.random();
|
||||||
root.discCenterY = Math.random()
|
root.discCenterY = Math.random();
|
||||||
} else if (root.actualTransitionType === "stripes") {
|
} else if (root.actualTransitionType === "stripes") {
|
||||||
root.stripesCount = Math.round(Math.random() * 20 + 4)
|
root.stripesCount = Math.round(Math.random() * 20 + 4);
|
||||||
root.stripesAngle = Math.random() * 360
|
root.stripesAngle = Math.random() * 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextWallpaper.source = newPath
|
nextWallpaper.source = newPath;
|
||||||
|
|
||||||
if (nextWallpaper.status === Image.Ready) {
|
if (nextWallpaper.status === Image.Ready) {
|
||||||
transitionAnimation.start()
|
transitionAnimation.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +231,7 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,20 +244,20 @@ Variants {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
smooth: true
|
smooth: true
|
||||||
cache: true
|
cache: true
|
||||||
|
sourceSize: Qt.size(modelData.width, modelData.height)
|
||||||
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
fillMode: root.getFillMode(SettingsData.wallpaperFillMode)
|
||||||
|
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
if (status !== Image.Ready)
|
if (status !== Image.Ready)
|
||||||
return
|
return;
|
||||||
|
|
||||||
if (root.actualTransitionType === "none") {
|
if (root.actualTransitionType === "none") {
|
||||||
currentWallpaper.source = source
|
currentWallpaper.source = source;
|
||||||
nextWallpaper.source = ""
|
nextWallpaper.source = "";
|
||||||
root.transitionProgress = 0.0
|
root.transitionProgress = 0.0;
|
||||||
} else {
|
} else {
|
||||||
visible = true
|
visible = true;
|
||||||
if (!root.transitioning) {
|
if (!root.transitioning) {
|
||||||
transitionAnimation.start()
|
transitionAnimation.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,21 +270,21 @@ Variants {
|
|||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
switch (root.actualTransitionType) {
|
switch (root.actualTransitionType) {
|
||||||
case "fade":
|
case "fade":
|
||||||
return fadeComp
|
return fadeComp;
|
||||||
case "wipe":
|
case "wipe":
|
||||||
return wipeComp
|
return wipeComp;
|
||||||
case "disc":
|
case "disc":
|
||||||
return discComp
|
return discComp;
|
||||||
case "stripes":
|
case "stripes":
|
||||||
return stripesComp
|
return stripesComp;
|
||||||
case "iris bloom":
|
case "iris bloom":
|
||||||
return irisComp
|
return irisComp;
|
||||||
case "pixelate":
|
case "pixelate":
|
||||||
return pixelateComp
|
return pixelateComp;
|
||||||
case "portal":
|
case "portal":
|
||||||
return portalComp
|
return portalComp;
|
||||||
default:
|
default:
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,15 +453,17 @@ Variants {
|
|||||||
duration: root.actualTransitionType === "none" ? 0 : 1000
|
duration: root.actualTransitionType === "none" ? 0 : 1000
|
||||||
easing.type: Easing.InOutCubic
|
easing.type: Easing.InOutCubic
|
||||||
onFinished: {
|
onFinished: {
|
||||||
|
const tempSource = nextWallpaper.source;
|
||||||
|
if (tempSource && nextWallpaper.status === Image.Ready && !tempSource.toString().startsWith("#")) {
|
||||||
|
currentWallpaper.source = tempSource;
|
||||||
|
}
|
||||||
|
root.transitionProgress = 0.0;
|
||||||
|
currentWallpaper.visible = root.actualTransitionType === "none";
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
|
nextWallpaper.source = "";
|
||||||
currentWallpaper.source = nextWallpaper.source
|
nextWallpaper.visible = false;
|
||||||
}
|
});
|
||||||
nextWallpaper.source = ""
|
|
||||||
nextWallpaper.visible = false
|
|
||||||
currentWallpaper.visible = root.actualTransitionType === "none"
|
|
||||||
root.transitionProgress = 0.0
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import "../Common/markdown2html.js" as Markdown2Html
|
import "../Common/markdown2html.js" as Markdown2Html
|
||||||
|
|
||||||
@@ -28,108 +26,106 @@ Singleton {
|
|||||||
property int maxIngressPerSecond: 20
|
property int maxIngressPerSecond: 20
|
||||||
property double _lastIngressSec: 0
|
property double _lastIngressSec: 0
|
||||||
property int _ingressCountThisSec: 0
|
property int _ingressCountThisSec: 0
|
||||||
property int maxStoredNotifications: 300
|
property int maxStoredNotifications: 50
|
||||||
|
|
||||||
property var _dismissQueue: []
|
property var _dismissQueue: []
|
||||||
property int _dismissBatchSize: 8
|
property int _dismissBatchSize: 8
|
||||||
property int _dismissTickMs: 8
|
property int _dismissTickMs: 8
|
||||||
property bool _suspendGrouping: false
|
property bool _suspendGrouping: false
|
||||||
property var _groupCache: ({
|
property var _groupCache: ({
|
||||||
"notifications": [],
|
"notifications": [],
|
||||||
"popups": []
|
"popups": []
|
||||||
})
|
})
|
||||||
property bool _groupsDirty: false
|
property bool _groupsDirty: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
_recomputeGroups()
|
_recomputeGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _nowSec() {
|
function _nowSec() {
|
||||||
return Date.now() / 1000.0
|
return Date.now() / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _ingressAllowed(notif) {
|
function _ingressAllowed(notif) {
|
||||||
const t = _nowSec()
|
const t = _nowSec();
|
||||||
if (t - _lastIngressSec >= 1.0) {
|
if (t - _lastIngressSec >= 1.0) {
|
||||||
_lastIngressSec = t
|
_lastIngressSec = t;
|
||||||
_ingressCountThisSec = 0
|
_ingressCountThisSec = 0;
|
||||||
}
|
}
|
||||||
_ingressCountThisSec += 1
|
_ingressCountThisSec += 1;
|
||||||
if (notif.urgency === NotificationUrgency.Critical) {
|
if (notif.urgency === NotificationUrgency.Critical) {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return _ingressCountThisSec <= maxIngressPerSecond
|
return _ingressCountThisSec <= maxIngressPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _enqueuePopup(wrapper) {
|
function _enqueuePopup(wrapper) {
|
||||||
if (notificationQueue.length >= maxQueueSize) {
|
if (notificationQueue.length >= maxQueueSize) {
|
||||||
const gk = getGroupKey(wrapper)
|
const gk = getGroupKey(wrapper);
|
||||||
let idx = notificationQueue.findIndex(w => w && getGroupKey(w) === gk && w.urgency !== NotificationUrgency.Critical)
|
let idx = notificationQueue.findIndex(w => w && getGroupKey(w) === gk && w.urgency !== NotificationUrgency.Critical);
|
||||||
if (idx === -1) {
|
if (idx === -1) {
|
||||||
idx = notificationQueue.findIndex(w => w && w.urgency !== NotificationUrgency.Critical)
|
idx = notificationQueue.findIndex(w => w && w.urgency !== NotificationUrgency.Critical);
|
||||||
}
|
}
|
||||||
if (idx === -1) {
|
if (idx === -1) {
|
||||||
idx = 0
|
idx = 0;
|
||||||
}
|
}
|
||||||
const victim = notificationQueue[idx]
|
const victim = notificationQueue[idx];
|
||||||
if (victim) {
|
if (victim) {
|
||||||
victim.popup = false
|
victim.popup = false;
|
||||||
}
|
}
|
||||||
notificationQueue.splice(idx, 1)
|
notificationQueue.splice(idx, 1);
|
||||||
}
|
}
|
||||||
notificationQueue = [...notificationQueue, wrapper]
|
notificationQueue = [...notificationQueue, wrapper];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _initWrapperPersistence(wrapper) {
|
function _initWrapperPersistence(wrapper) {
|
||||||
const timeoutMs = wrapper.timer ? wrapper.timer.interval : 5000
|
const timeoutMs = wrapper.timer ? wrapper.timer.interval : 5000;
|
||||||
const isCritical = wrapper.notification && wrapper.notification.urgency === NotificationUrgency.Critical
|
const isCritical = wrapper.notification && wrapper.notification.urgency === NotificationUrgency.Critical;
|
||||||
wrapper.isPersistent = isCritical || (timeoutMs === 0)
|
wrapper.isPersistent = isCritical || (timeoutMs === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _trimStored() {
|
function _trimStored() {
|
||||||
if (notifications.length > maxStoredNotifications) {
|
if (notifications.length > maxStoredNotifications) {
|
||||||
const overflow = notifications.length - maxStoredNotifications
|
const overflow = notifications.length - maxStoredNotifications;
|
||||||
const toDrop = []
|
const toDrop = [];
|
||||||
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
||||||
const w = notifications[i]
|
const w = notifications[i];
|
||||||
if (w && w.notification && w.urgency !== NotificationUrgency.Critical) {
|
if (w && w.notification && w.urgency !== NotificationUrgency.Critical) {
|
||||||
toDrop.push(w)
|
toDrop.push(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
for (var i = notifications.length - 1; i >= 0 && toDrop.length < overflow; --i) {
|
||||||
const w = notifications[i]
|
const w = notifications[i];
|
||||||
if (w && w.notification && toDrop.indexOf(w) === -1) {
|
if (w && w.notification && toDrop.indexOf(w) === -1) {
|
||||||
toDrop.push(w)
|
toDrop.push(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const w of toDrop) {
|
for (const w of toDrop) {
|
||||||
try {
|
try {
|
||||||
w.notification.dismiss()
|
w.notification.dismiss();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOverlayOpen() {
|
function onOverlayOpen() {
|
||||||
popupsDisabled = true
|
popupsDisabled = true;
|
||||||
addGate.stop()
|
addGate.stop();
|
||||||
addGateBusy = false
|
addGateBusy = false;
|
||||||
|
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
for (const w of visibleNotifications) {
|
for (const w of visibleNotifications) {
|
||||||
if (w) {
|
if (w) {
|
||||||
w.popup = false
|
w.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
_recomputeGroupsLater()
|
_recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOverlayClose() {
|
function onOverlayClose() {
|
||||||
popupsDisabled = false
|
popupsDisabled = false;
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -138,8 +134,8 @@ Singleton {
|
|||||||
running: false
|
running: false
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
addGateBusy = false
|
addGateBusy = false;
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +146,7 @@ Singleton {
|
|||||||
running: root.allWrappers.length > 0 || visibleNotifications.length > 0
|
running: root.allWrappers.length > 0 || visibleNotifications.length > 0
|
||||||
triggeredOnStart: false
|
triggeredOnStart: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
root.timeUpdateTick = !root.timeUpdateTick
|
root.timeUpdateTick = !root.timeUpdateTick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,23 +156,21 @@ Singleton {
|
|||||||
repeat: true
|
repeat: true
|
||||||
running: false
|
running: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
let n = Math.min(_dismissBatchSize, _dismissQueue.length)
|
let n = Math.min(_dismissBatchSize, _dismissQueue.length);
|
||||||
for (var i = 0; i < n; ++i) {
|
for (var i = 0; i < n; ++i) {
|
||||||
const w = _dismissQueue.pop()
|
const w = _dismissQueue.pop();
|
||||||
try {
|
try {
|
||||||
if (w && w.notification) {
|
if (w && w.notification) {
|
||||||
w.notification.dismiss()
|
w.notification.dismiss();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_dismissQueue.length === 0) {
|
if (_dismissQueue.length === 0) {
|
||||||
dismissPump.stop()
|
dismissPump.stop();
|
||||||
_suspendGrouping = false
|
_suspendGrouping = false;
|
||||||
bulkDismissing = false
|
bulkDismissing = false;
|
||||||
popupsDisabled = false
|
popupsDisabled = false;
|
||||||
_recomputeGroupsLater()
|
_recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,52 +206,50 @@ Singleton {
|
|||||||
persistenceSupported: true
|
persistenceSupported: true
|
||||||
|
|
||||||
onNotification: notif => {
|
onNotification: notif => {
|
||||||
notif.tracked = true
|
notif.tracked = true;
|
||||||
|
|
||||||
if (!_ingressAllowed(notif)) {
|
if (!_ingressAllowed(notif)) {
|
||||||
if (notif.urgency !== NotificationUrgency.Critical) {
|
if (notif.urgency !== NotificationUrgency.Critical) {
|
||||||
try {
|
try {
|
||||||
notif.dismiss()
|
notif.dismiss();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
return;
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SettingsData.soundsEnabled && SettingsData.soundNewNotification) {
|
if (SettingsData.soundsEnabled && SettingsData.soundNewNotification) {
|
||||||
if (notif.urgency === NotificationUrgency.Critical) {
|
if (notif.urgency === NotificationUrgency.Critical) {
|
||||||
AudioService.playCriticalNotificationSound()
|
AudioService.playCriticalNotificationSound();
|
||||||
} else {
|
} else {
|
||||||
AudioService.playNormalNotificationSound()
|
AudioService.playNormalNotificationSound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldShowPopup = !root.popupsDisabled && !SessionData.doNotDisturb
|
const shouldShowPopup = !root.popupsDisabled && !SessionData.doNotDisturb;
|
||||||
const isTransient = notif.transient
|
const isTransient = notif.transient;
|
||||||
const wrapper = notifComponent.createObject(root, {
|
const wrapper = notifComponent.createObject(root, {
|
||||||
"popup": shouldShowPopup,
|
"popup": shouldShowPopup,
|
||||||
"notification": notif
|
"notification": notif
|
||||||
})
|
});
|
||||||
|
|
||||||
if (wrapper) {
|
if (wrapper) {
|
||||||
root.allWrappers.push(wrapper)
|
root.allWrappers.push(wrapper);
|
||||||
if (!isTransient) {
|
if (!isTransient) {
|
||||||
root.notifications.push(wrapper)
|
root.notifications.push(wrapper);
|
||||||
_trimStored()
|
_trimStored();
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
_initWrapperPersistence(wrapper)
|
_initWrapperPersistence(wrapper);
|
||||||
})
|
});
|
||||||
|
|
||||||
if (shouldShowPopup) {
|
if (shouldShowPopup) {
|
||||||
_enqueuePopup(wrapper)
|
_enqueuePopup(wrapper);
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_recomputeGroupsLater()
|
_recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,80 +263,80 @@ Singleton {
|
|||||||
|
|
||||||
onPopupChanged: {
|
onPopupChanged: {
|
||||||
if (!popup) {
|
if (!popup) {
|
||||||
removeFromVisibleNotifications(wrapper)
|
removeFromVisibleNotifications(wrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property Timer timer: Timer {
|
readonly property Timer timer: Timer {
|
||||||
interval: {
|
interval: {
|
||||||
if (!wrapper.notification) {
|
if (!wrapper.notification) {
|
||||||
return 5000
|
return 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (wrapper.notification.urgency) {
|
switch (wrapper.notification.urgency) {
|
||||||
case NotificationUrgency.Low:
|
case NotificationUrgency.Low:
|
||||||
return SettingsData.notificationTimeoutLow
|
return SettingsData.notificationTimeoutLow;
|
||||||
case NotificationUrgency.Critical:
|
case NotificationUrgency.Critical:
|
||||||
return SettingsData.notificationTimeoutCritical
|
return SettingsData.notificationTimeoutCritical;
|
||||||
default:
|
default:
|
||||||
return SettingsData.notificationTimeoutNormal
|
return SettingsData.notificationTimeoutNormal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
repeat: false
|
repeat: false
|
||||||
running: false
|
running: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (interval > 0) {
|
if (interval > 0) {
|
||||||
wrapper.popup = false
|
wrapper.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property date time: new Date()
|
readonly property date time: new Date()
|
||||||
readonly property string timeStr: {
|
readonly property string timeStr: {
|
||||||
root.timeUpdateTick
|
root.timeUpdateTick;
|
||||||
root.clockFormatChanged
|
root.clockFormatChanged;
|
||||||
|
|
||||||
const now = new Date()
|
const now = new Date();
|
||||||
const diff = now.getTime() - time.getTime()
|
const diff = now.getTime() - time.getTime();
|
||||||
const minutes = Math.floor(diff / 60000)
|
const minutes = Math.floor(diff / 60000);
|
||||||
const hours = Math.floor(minutes / 60)
|
const hours = Math.floor(minutes / 60);
|
||||||
|
|
||||||
if (hours < 1) {
|
if (hours < 1) {
|
||||||
if (minutes < 1) {
|
if (minutes < 1) {
|
||||||
return "now"
|
return "now";
|
||||||
}
|
}
|
||||||
return `${minutes}m ago`
|
return `${minutes}m ago`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||||
const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate())
|
const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate());
|
||||||
const daysDiff = Math.floor((nowDate - timeDate) / (1000 * 60 * 60 * 24))
|
const daysDiff = Math.floor((nowDate - timeDate) / (1000 * 60 * 60 * 24));
|
||||||
|
|
||||||
if (daysDiff === 0) {
|
if (daysDiff === 0) {
|
||||||
return formatTime(time)
|
return formatTime(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daysDiff === 1) {
|
if (daysDiff === 1) {
|
||||||
return `yesterday, ${formatTime(time)}`
|
return `yesterday, ${formatTime(time)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${daysDiff} days ago`
|
return `${daysDiff} days ago`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTime(date) {
|
function formatTime(date) {
|
||||||
let use24Hour = true
|
let use24Hour = true;
|
||||||
try {
|
try {
|
||||||
if (typeof SettingsData !== "undefined" && SettingsData.use24HourClock !== undefined) {
|
if (typeof SettingsData !== "undefined" && SettingsData.use24HourClock !== undefined) {
|
||||||
use24Hour = SettingsData.use24HourClock
|
use24Hour = SettingsData.use24HourClock;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
use24Hour = true
|
use24Hour = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use24Hour) {
|
if (use24Hour) {
|
||||||
return date.toLocaleTimeString(Qt.locale(), "HH:mm")
|
return date.toLocaleTimeString(Qt.locale(), "HH:mm");
|
||||||
} else {
|
} else {
|
||||||
return date.toLocaleTimeString(Qt.locale(), "h:mm AP")
|
return date.toLocaleTimeString(Qt.locale(), "h:mm AP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,27 +345,27 @@ Singleton {
|
|||||||
readonly property string body: notification.body
|
readonly property string body: notification.body
|
||||||
readonly property string htmlBody: {
|
readonly property string htmlBody: {
|
||||||
if (body && (body.includes('<') && body.includes('>'))) {
|
if (body && (body.includes('<') && body.includes('>'))) {
|
||||||
return body
|
return body;
|
||||||
}
|
}
|
||||||
return Markdown2Html.markdownToHtml(body)
|
return Markdown2Html.markdownToHtml(body);
|
||||||
}
|
}
|
||||||
readonly property string appIcon: notification.appIcon
|
readonly property string appIcon: notification.appIcon
|
||||||
readonly property string appName: {
|
readonly property string appName: {
|
||||||
if (notification.appName == "") {
|
if (notification.appName == "") {
|
||||||
const entry = DesktopEntries.heuristicLookup(notification.desktopEntry)
|
const entry = DesktopEntries.heuristicLookup(notification.desktopEntry);
|
||||||
if (entry && entry.name) {
|
if (entry && entry.name) {
|
||||||
return entry.name.toLowerCase()
|
return entry.name.toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return notification.appName || "app"
|
return notification.appName || "app";
|
||||||
}
|
}
|
||||||
readonly property string desktopEntry: notification.desktopEntry
|
readonly property string desktopEntry: notification.desktopEntry
|
||||||
readonly property string image: notification.image
|
readonly property string image: notification.image
|
||||||
readonly property string cleanImage: {
|
readonly property string cleanImage: {
|
||||||
if (!image) {
|
if (!image) {
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
return Paths.strip(image)
|
return Paths.strip(image);
|
||||||
}
|
}
|
||||||
readonly property int urgency: notification.urgency
|
readonly property int urgency: notification.urgency
|
||||||
readonly property list<NotificationAction> actions: notification.actions
|
readonly property list<NotificationAction> actions: notification.actions
|
||||||
@@ -382,26 +374,26 @@ Singleton {
|
|||||||
target: wrapper.notification.Retainable
|
target: wrapper.notification.Retainable
|
||||||
|
|
||||||
function onDropped(): void {
|
function onDropped(): void {
|
||||||
root.allWrappers = root.allWrappers.filter(w => w !== wrapper)
|
root.allWrappers = root.allWrappers.filter(w => w !== wrapper);
|
||||||
root.notifications = root.notifications.filter(w => w !== wrapper)
|
root.notifications = root.notifications.filter(w => w !== wrapper);
|
||||||
|
|
||||||
if (root.bulkDismissing) {
|
if (root.bulkDismissing) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupKey = getGroupKey(wrapper)
|
const groupKey = getGroupKey(wrapper);
|
||||||
const remainingInGroup = root.notifications.filter(n => getGroupKey(n) === groupKey)
|
const remainingInGroup = root.notifications.filter(n => getGroupKey(n) === groupKey);
|
||||||
|
|
||||||
if (remainingInGroup.length <= 1) {
|
if (remainingInGroup.length <= 1) {
|
||||||
clearGroupExpansionState(groupKey)
|
clearGroupExpansionState(groupKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupExpansionStates()
|
cleanupExpansionStates();
|
||||||
root._recomputeGroupsLater()
|
root._recomputeGroupsLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAboutToDestroy(): void {
|
function onAboutToDestroy(): void {
|
||||||
wrapper.destroy()
|
wrapper.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,146 +406,145 @@ Singleton {
|
|||||||
function clearAllPopups() {
|
function clearAllPopups() {
|
||||||
for (const w of visibleNotifications) {
|
for (const w of visibleNotifications) {
|
||||||
if (w) {
|
if (w) {
|
||||||
w.popup = false
|
w.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearAllNotifications() {
|
function clearAllNotifications() {
|
||||||
bulkDismissing = true
|
bulkDismissing = true;
|
||||||
popupsDisabled = true
|
popupsDisabled = true;
|
||||||
addGate.stop()
|
addGate.stop();
|
||||||
addGateBusy = false
|
addGateBusy = false;
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
|
|
||||||
for (const w of allWrappers) {
|
for (const w of allWrappers) {
|
||||||
if (w) {
|
if (w) {
|
||||||
w.popup = false
|
w.popup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
|
|
||||||
_dismissQueue = notifications.slice()
|
_dismissQueue = notifications.slice();
|
||||||
if (notifications.length) {
|
if (notifications.length) {
|
||||||
notifications = []
|
notifications = [];
|
||||||
}
|
}
|
||||||
expandedGroups = {}
|
expandedGroups = {};
|
||||||
expandedMessages = {}
|
expandedMessages = {};
|
||||||
|
|
||||||
_suspendGrouping = true
|
_suspendGrouping = true;
|
||||||
|
|
||||||
if (!dismissPump.running && _dismissQueue.length) {
|
if (!dismissPump.running && _dismissQueue.length) {
|
||||||
dismissPump.start()
|
dismissPump.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissNotification(wrapper) {
|
function dismissNotification(wrapper) {
|
||||||
if (!wrapper || !wrapper.notification) {
|
if (!wrapper || !wrapper.notification) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
wrapper.popup = false
|
wrapper.popup = false;
|
||||||
wrapper.notification.dismiss()
|
wrapper.notification.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
function disablePopups(disable) {
|
function disablePopups(disable) {
|
||||||
popupsDisabled = disable
|
popupsDisabled = disable;
|
||||||
if (disable) {
|
if (disable) {
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
for (const notif of visibleNotifications) {
|
for (const notif of visibleNotifications) {
|
||||||
notif.popup = false
|
notif.popup = false;
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processQueue() {
|
function processQueue() {
|
||||||
if (addGateBusy) {
|
if (addGateBusy) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (popupsDisabled) {
|
if (popupsDisabled) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (SessionData.doNotDisturb) {
|
if (SessionData.doNotDisturb) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (notificationQueue.length === 0) {
|
if (notificationQueue.length === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activePopupCount = visibleNotifications.filter(n => n && n.popup).length
|
const activePopupCount = visibleNotifications.filter(n => n && n.popup).length;
|
||||||
if (activePopupCount >= 4) {
|
if (activePopupCount >= 4) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = notificationQueue.shift()
|
const next = notificationQueue.shift();
|
||||||
|
|
||||||
next.seq = ++seqCounter
|
next.seq = ++seqCounter;
|
||||||
visibleNotifications = [...visibleNotifications, next]
|
visibleNotifications = [...visibleNotifications, next];
|
||||||
next.popup = true
|
next.popup = true;
|
||||||
|
|
||||||
if (next.timer.interval > 0) {
|
if (next.timer.interval > 0) {
|
||||||
next.timer.start()
|
next.timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
addGateBusy = true
|
addGateBusy = true;
|
||||||
addGate.restart()
|
addGate.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFromVisibleNotifications(wrapper) {
|
function removeFromVisibleNotifications(wrapper) {
|
||||||
visibleNotifications = visibleNotifications.filter(n => n !== wrapper)
|
visibleNotifications = visibleNotifications.filter(n => n !== wrapper);
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
function releaseWrapper(w) {
|
function releaseWrapper(w) {
|
||||||
visibleNotifications = visibleNotifications.filter(n => n !== w)
|
visibleNotifications = visibleNotifications.filter(n => n !== w);
|
||||||
notificationQueue = notificationQueue.filter(n => n !== w)
|
notificationQueue = notificationQueue.filter(n => n !== w);
|
||||||
|
|
||||||
if (w && w.destroy && !w.isPersistent && notifications.indexOf(w) === -1) {
|
if (w && w.destroy && !w.isPersistent && notifications.indexOf(w) === -1) {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
try {
|
try {
|
||||||
w.destroy()
|
w.destroy();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGroupKey(wrapper) {
|
function getGroupKey(wrapper) {
|
||||||
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
if (wrapper.desktopEntry && wrapper.desktopEntry !== "") {
|
||||||
return wrapper.desktopEntry.toLowerCase()
|
return wrapper.desktopEntry.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper.appName.toLowerCase()
|
return wrapper.appName.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _recomputeGroups() {
|
function _recomputeGroups() {
|
||||||
if (_suspendGrouping) {
|
if (_suspendGrouping) {
|
||||||
_groupsDirty = true
|
_groupsDirty = true;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
_groupCache = {
|
_groupCache = {
|
||||||
"notifications": _calcGroupedNotifications(),
|
"notifications": _calcGroupedNotifications(),
|
||||||
"popups": _calcGroupedPopups()
|
"popups": _calcGroupedPopups()
|
||||||
}
|
};
|
||||||
_groupsDirty = false
|
_groupsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _recomputeGroupsLater() {
|
function _recomputeGroupsLater() {
|
||||||
_groupsDirty = true
|
_groupsDirty = true;
|
||||||
if (!groupsDebounce.running) {
|
if (!groupsDebounce.running) {
|
||||||
groupsDebounce.start()
|
groupsDebounce.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _calcGroupedNotifications() {
|
function _calcGroupedNotifications() {
|
||||||
const groups = {}
|
const groups = {};
|
||||||
|
|
||||||
for (const notif of notifications) {
|
for (const notif of notifications) {
|
||||||
if (!notif) continue
|
if (!notif)
|
||||||
const groupKey = getGroupKey(notif)
|
continue;
|
||||||
|
const groupKey = getGroupKey(notif);
|
||||||
if (!groups[groupKey]) {
|
if (!groups[groupKey]) {
|
||||||
groups[groupKey] = {
|
groups[groupKey] = {
|
||||||
"key": groupKey,
|
"key": groupKey,
|
||||||
@@ -562,34 +553,35 @@ Singleton {
|
|||||||
"latestNotification": null,
|
"latestNotification": null,
|
||||||
"count": 0,
|
"count": 0,
|
||||||
"hasInlineReply": false
|
"hasInlineReply": false
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
groups[groupKey].notifications.unshift(notif)
|
groups[groupKey].notifications.unshift(notif);
|
||||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
groups[groupKey].latestNotification = groups[groupKey].notifications[0];
|
||||||
groups[groupKey].count = groups[groupKey].notifications.length
|
groups[groupKey].count = groups[groupKey].notifications.length;
|
||||||
|
|
||||||
if (notif.notification.hasInlineReply) {
|
if (notif.notification.hasInlineReply) {
|
||||||
groups[groupKey].hasInlineReply = true
|
groups[groupKey].hasInlineReply = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(groups).sort((a, b) => {
|
return Object.values(groups).sort((a, b) => {
|
||||||
const aUrgency = a.latestNotification.urgency || NotificationUrgency.Low
|
const aUrgency = a.latestNotification.urgency || NotificationUrgency.Low;
|
||||||
const bUrgency = b.latestNotification.urgency || NotificationUrgency.Low
|
const bUrgency = b.latestNotification.urgency || NotificationUrgency.Low;
|
||||||
if (aUrgency !== bUrgency) {
|
if (aUrgency !== bUrgency) {
|
||||||
return bUrgency - aUrgency
|
return bUrgency - aUrgency;
|
||||||
}
|
}
|
||||||
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime()
|
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _calcGroupedPopups() {
|
function _calcGroupedPopups() {
|
||||||
const groups = {}
|
const groups = {};
|
||||||
|
|
||||||
for (const notif of popups) {
|
for (const notif of popups) {
|
||||||
if (!notif) continue
|
if (!notif)
|
||||||
const groupKey = getGroupKey(notif)
|
continue;
|
||||||
|
const groupKey = getGroupKey(notif);
|
||||||
if (!groups[groupKey]) {
|
if (!groups[groupKey]) {
|
||||||
groups[groupKey] = {
|
groups[groupKey] = {
|
||||||
"key": groupKey,
|
"key": groupKey,
|
||||||
@@ -598,92 +590,92 @@ Singleton {
|
|||||||
"latestNotification": null,
|
"latestNotification": null,
|
||||||
"count": 0,
|
"count": 0,
|
||||||
"hasInlineReply": false
|
"hasInlineReply": false
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
groups[groupKey].notifications.unshift(notif)
|
groups[groupKey].notifications.unshift(notif);
|
||||||
groups[groupKey].latestNotification = groups[groupKey].notifications[0]
|
groups[groupKey].latestNotification = groups[groupKey].notifications[0];
|
||||||
groups[groupKey].count = groups[groupKey].notifications.length
|
groups[groupKey].count = groups[groupKey].notifications.length;
|
||||||
|
|
||||||
if (notif.notification.hasInlineReply) {
|
if (notif.notification.hasInlineReply) {
|
||||||
groups[groupKey].hasInlineReply = true
|
groups[groupKey].hasInlineReply = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(groups).sort((a, b) => {
|
return Object.values(groups).sort((a, b) => {
|
||||||
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime()
|
return b.latestNotification.time.getTime() - a.latestNotification.time.getTime();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleGroupExpansion(groupKey) {
|
function toggleGroupExpansion(groupKey) {
|
||||||
let newExpandedGroups = {}
|
let newExpandedGroups = {};
|
||||||
for (const key in expandedGroups) {
|
for (const key in expandedGroups) {
|
||||||
newExpandedGroups[key] = expandedGroups[key]
|
newExpandedGroups[key] = expandedGroups[key];
|
||||||
}
|
}
|
||||||
newExpandedGroups[groupKey] = !newExpandedGroups[groupKey]
|
newExpandedGroups[groupKey] = !newExpandedGroups[groupKey];
|
||||||
expandedGroups = newExpandedGroups
|
expandedGroups = newExpandedGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissGroup(groupKey) {
|
function dismissGroup(groupKey) {
|
||||||
const group = groupedNotifications.find(g => g.key === groupKey)
|
const group = groupedNotifications.find(g => g.key === groupKey);
|
||||||
if (group) {
|
if (group) {
|
||||||
for (const notif of group.notifications) {
|
for (const notif of group.notifications) {
|
||||||
if (notif && notif.notification) {
|
if (notif && notif.notification) {
|
||||||
notif.notification.dismiss()
|
notif.notification.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const notif of allWrappers) {
|
for (const notif of allWrappers) {
|
||||||
if (notif && notif.notification && getGroupKey(notif) === groupKey) {
|
if (notif && notif.notification && getGroupKey(notif) === groupKey) {
|
||||||
notif.notification.dismiss()
|
notif.notification.dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearGroupExpansionState(groupKey) {
|
function clearGroupExpansionState(groupKey) {
|
||||||
let newExpandedGroups = {}
|
let newExpandedGroups = {};
|
||||||
for (const key in expandedGroups) {
|
for (const key in expandedGroups) {
|
||||||
if (key !== groupKey && expandedGroups[key]) {
|
if (key !== groupKey && expandedGroups[key]) {
|
||||||
newExpandedGroups[key] = true
|
newExpandedGroups[key] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandedGroups = newExpandedGroups
|
expandedGroups = newExpandedGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupExpansionStates() {
|
function cleanupExpansionStates() {
|
||||||
const currentGroupKeys = new Set(groupedNotifications.map(g => g.key))
|
const currentGroupKeys = new Set(groupedNotifications.map(g => g.key));
|
||||||
const currentMessageIds = new Set()
|
const currentMessageIds = new Set();
|
||||||
for (const group of groupedNotifications) {
|
for (const group of groupedNotifications) {
|
||||||
for (const notif of group.notifications) {
|
for (const notif of group.notifications) {
|
||||||
if (notif && notif.notification) {
|
if (notif && notif.notification) {
|
||||||
currentMessageIds.add(notif.notification.id)
|
currentMessageIds.add(notif.notification.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let newExpandedGroups = {}
|
let newExpandedGroups = {};
|
||||||
for (const key in expandedGroups) {
|
for (const key in expandedGroups) {
|
||||||
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
if (currentGroupKeys.has(key) && expandedGroups[key]) {
|
||||||
newExpandedGroups[key] = true
|
newExpandedGroups[key] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandedGroups = newExpandedGroups
|
expandedGroups = newExpandedGroups;
|
||||||
let newExpandedMessages = {}
|
let newExpandedMessages = {};
|
||||||
for (const messageId in expandedMessages) {
|
for (const messageId in expandedMessages) {
|
||||||
if (currentMessageIds.has(messageId) && expandedMessages[messageId]) {
|
if (currentMessageIds.has(messageId) && expandedMessages[messageId]) {
|
||||||
newExpandedMessages[messageId] = true
|
newExpandedMessages[messageId] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandedMessages = newExpandedMessages
|
expandedMessages = newExpandedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMessageExpansion(messageId) {
|
function toggleMessageExpansion(messageId) {
|
||||||
let newExpandedMessages = {}
|
let newExpandedMessages = {};
|
||||||
for (const key in expandedMessages) {
|
for (const key in expandedMessages) {
|
||||||
newExpandedMessages[key] = expandedMessages[key]
|
newExpandedMessages[key] = expandedMessages[key];
|
||||||
}
|
}
|
||||||
newExpandedMessages[messageId] = !newExpandedMessages[messageId]
|
newExpandedMessages[messageId] = !newExpandedMessages[messageId];
|
||||||
expandedMessages = newExpandedMessages
|
expandedMessages = newExpandedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -692,13 +684,13 @@ Singleton {
|
|||||||
if (SessionData.doNotDisturb) {
|
if (SessionData.doNotDisturb) {
|
||||||
// Hide all current popups when DND is enabled
|
// Hide all current popups when DND is enabled
|
||||||
for (const notif of visibleNotifications) {
|
for (const notif of visibleNotifications) {
|
||||||
notif.popup = false
|
notif.popup = false;
|
||||||
}
|
}
|
||||||
visibleNotifications = []
|
visibleNotifications = [];
|
||||||
notificationQueue = []
|
notificationQueue = [];
|
||||||
} else {
|
} else {
|
||||||
// Re-enable popup processing when DND is disabled
|
// Re-enable popup processing when DND is disabled
|
||||||
processQueue()
|
processQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -706,7 +698,7 @@ Singleton {
|
|||||||
Connections {
|
Connections {
|
||||||
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
target: typeof SettingsData !== "undefined" ? SettingsData : null
|
||||||
function onUse24HourClockChanged() {
|
function onUse24HourClockChanged() {
|
||||||
root.clockFormatChanged = !root.clockFormatChanged
|
root.clockFormatChanged = !root.clockFormatChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Singleton {
|
|||||||
property var systemUpdatePopout: null
|
property var systemUpdatePopout: null
|
||||||
|
|
||||||
property var settingsModal: null
|
property var settingsModal: null
|
||||||
|
property var settingsModalLoader: null
|
||||||
property var clipboardHistoryModal: null
|
property var clipboardHistoryModal: null
|
||||||
property var spotlightModal: null
|
property var spotlightModal: null
|
||||||
property var powerMenuModal: null
|
property var powerMenuModal: null
|
||||||
@@ -191,14 +192,50 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool _settingsWantsOpen: false
|
||||||
|
property bool _settingsWantsToggle: false
|
||||||
|
|
||||||
function openSettings() {
|
function openSettings() {
|
||||||
settingsModal?.show();
|
if (settingsModal) {
|
||||||
|
settingsModal.show();
|
||||||
|
} else if (settingsModalLoader) {
|
||||||
|
_settingsWantsOpen = true;
|
||||||
|
_settingsWantsToggle = false;
|
||||||
|
settingsModalLoader.activeAsync = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeSettings() {
|
function closeSettings() {
|
||||||
settingsModal?.close();
|
settingsModal?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleSettings() {
|
||||||
|
if (settingsModal) {
|
||||||
|
settingsModal.toggle();
|
||||||
|
} else if (settingsModalLoader) {
|
||||||
|
_settingsWantsToggle = true;
|
||||||
|
_settingsWantsOpen = false;
|
||||||
|
settingsModalLoader.activeAsync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unloadSettings() {
|
||||||
|
if (settingsModalLoader) {
|
||||||
|
settingsModal = null;
|
||||||
|
settingsModalLoader.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _onSettingsModalLoaded() {
|
||||||
|
if (_settingsWantsOpen) {
|
||||||
|
_settingsWantsOpen = false;
|
||||||
|
settingsModal?.show();
|
||||||
|
} else if (_settingsWantsToggle) {
|
||||||
|
_settingsWantsToggle = false;
|
||||||
|
settingsModal?.toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function openClipboardHistory() {
|
function openClipboardHistory() {
|
||||||
clipboardHistoryModal?.show();
|
clipboardHistoryModal?.show();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user