1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-02 18:42:06 -04:00

Compare commits

..

25 Commits

Author SHA1 Message Date
bbedward
03a8e1e0d5 clipboard: fix memory leak from unbounded offer maps and unguarded file reads 2026-02-20 11:42:14 -05:00
bbedward
4d4d3c20a1 keybinds/niri: fix quote preservation 2026-02-20 11:42:14 -05:00
bbedward
cef16d6bc9 dankdash: fix widgets across different bar section fixes #1764s 2026-02-20 11:42:14 -05:00
bbedward
aafaad1791 core/screenshot: light cleanups 2026-02-20 11:42:14 -05:00
Patrick Fischer
7906fdc2b0 screensaver: emit ActiveChanged on lock/unlock (#1761) 2026-02-20 11:42:14 -05:00
Triệu Kha
397650ca52 clipboard: improve image thumbnail (#1759)
- thumbnail image is now bigger
- circular mask has been replaced with rounded rectangular mask
2026-02-20 11:42:14 -05:00
purian23
826207006a template: Default install method 2026-02-20 11:42:14 -05:00
purian23
58c2fcd31c issues: Template fix 2026-02-20 11:42:14 -05:00
purian23
b2a2b425ec templates: Fix GitHub issue labels 2026-02-20 11:42:14 -05:00
shorinkiwata
942c9c9609 feat(distros): allow CatOS to run DMS installer (#1768)
- This PR adds support for **CatOS**
- CatOS is fully compatible with Arch Linux
2026-02-20 11:42:14 -05:00
purian23
46d6e1cff3 templates: Update DMS issue formats 2026-02-20 11:42:14 -05:00
bbedward
a4137c57c1 running apps: fix ordering on niri 2026-02-19 20:46:26 -05:00
bbedward
1ad8b627f1 launcher: fix premature exit of file search fixes #1749 2026-02-19 16:47:34 -05:00
Jonas Bloch
58a02ce290 Search keybinds fixes (#1748)
* fix: close keybind cheatsheet on escape press

* feat: match all space separated words in keybind cheatsheet search
2026-02-19 16:27:14 -05:00
bbedward
8e1ad1a2be audio: fix hide device not working 2026-02-19 16:24:48 -05:00
bbedward
68cd7ab32c i18n: term sync 2026-02-19 14:11:21 -05:00
Youseffo13
f649ce9a8e Added missing i18n strings and changed reset button (#1746)
* Update it.json

* Enhance SettingsSliderRow: add resetText property and update reset button styling

* added i18n strings

* adjust reset button width to be dynamic based on content size

* added i18n strings

* Update template.json

* reverted changes

* Update it.json

* Update template.json
2026-02-19 14:11:21 -05:00
bbedward
c4df242f07 dankbar: remove behaviors from monitoring widgets 2026-02-19 14:11:21 -05:00
bbedward
26846c8d55 dgop: round computed values to match display format 2026-02-19 14:11:21 -05:00
bbedward
31b44a667c flake: fix dev flake for go 1.25 and ashellchheck 2026-02-19 14:11:21 -05:00
bbedward
4f3b73ee21 hyprland: add serial to output model generator 2026-02-19 09:22:56 -05:00
bbedward
4cfae91f02 dock: fix context menu styling fixes #1742 2026-02-19 09:22:56 -05:00
bbedward
8d947a6e95 dock: fix transparency setting fixes #1739 2026-02-19 09:22:56 -05:00
bbedward
1e84d4252c launcher: improve perf of settings search 2026-02-19 09:22:56 -05:00
bbedward
76072e1d4c launcher: always heuristic lookup cached entries 2026-02-19 09:22:56 -05:00
65 changed files with 2313 additions and 2504 deletions

View File

@@ -8,31 +8,31 @@ body:
value: |
## DankMaterialShell Bug Report
Limit your report to one issue per submission unless closely related
- type: checkboxes
- type: dropdown
id: compositor
attributes:
label: Compositor
options:
- label: Niri
- label: Hyprland
- label: MangoWC (dwl)
- label: Sway
- Niri
- Hyprland
- MangoWC (dwl)
- Sway
validations:
required: true
- type: checkboxes
- type: dropdown
id: distribution
attributes:
label: Distribution
options:
- label: Arch Linux
- label: CachyOS
- label: Fedora
- label: NixOS
- label: Debian
- label: Ubuntu
- label: Gentoo
- label: OpenSUSE
- label: Other (specify below)
- Arch Linux
- CachyOS
- Fedora
- NixOS
- Debian
- Ubuntu
- Gentoo
- OpenSUSE
- Other (specify below)
validations:
required: true
- type: input
@@ -42,12 +42,45 @@ body:
placeholder: e.g., PikaOS, Void Linux, etc.
validations:
required: false
- type: dropdown
id: installation_method
attributes:
label: Select your Installation Method
options:
- DankInstaller
- Distro Packaging
- Source
validations:
required: true
- type: dropdown
id: original_installation_method_different
attributes:
label: Was your original Installation method different?
options:
- "Yes"
- No (specify below)
default: 0
validations:
required: false
- type: input
id: original_installation_method_specify
attributes:
label: If no, specify
placeholder: e.g., Distro Packaging, then Source
validations:
required: false
- type: textarea
id: dms_doctor
attributes:
label: dms doctor -vC
description: Output of `dms doctor -vC` command
description: Output of `dms doctor -vC` command — paste between the lines below to keep it collapsed in the issue
placeholder: Paste the output of `dms doctor -vC` here
value: |
<details>
<summary>Click to expand</summary>
</details>
validations:
required: true
- type: textarea
@@ -69,7 +102,7 @@ body:
- type: textarea
id: steps_to_reproduce
attributes:
label: Steps to Reproduce & Installation Method
label: Steps to Reproduce
description: Please provide detailed steps to reproduce the issue
placeholder: |
1. ...

View File

@@ -23,18 +23,25 @@ body:
placeholder: Why is this feature important?
validations:
required: false
- type: checkboxes
- type: dropdown
id: compositor
attributes:
label: Compositor(s)
description: Is this feature specific to one or more compositors?
options:
- label: All compositors
- label: Niri
- label: Hyprland
- label: MangoWC (dwl)
- label: Sway
- label: Other (specify below)
- All compositors
- Niri
- Hyprland
- MangoWC (dwl)
- Sway
- Other (specify below)
validations:
required: true
- type: input
id: compositor_other
attributes:
label: If Other, please specify
placeholder: e.g., Wayfire, Mutter, etc.
validations:
required: false
- type: textarea

View File

@@ -7,32 +7,87 @@ body:
attributes:
value: |
## DankMaterialShell Support Request
- type: checkboxes
- type: dropdown
id: compositor
attributes:
label: Compositor
options:
- label: Niri
- label: Hyprland
- label: MangoWC (dwl)
- label: Sway
- label: Other (specify below)
- Niri
- Hyprland
- MangoWC (dwl)
- Sway
- Other (specify below)
validations:
required: true
- type: input
id: compositor_other
attributes:
label: If Other, please specify
placeholder: e.g., Wayfire, Mutter, etc.
validations:
required: false
- type: input
- type: dropdown
id: distribution
attributes:
label: Distribution
description: Which Linux distribution are you using? (e.g., Arch, Fedora, Debian, etc.)
placeholder: Your Linux distribution
options:
- Arch Linux
- CachyOS
- Fedora
- NixOS
- Debian
- Ubuntu
- Gentoo
- OpenSUSE
- Other (specify below)
validations:
required: true
- type: input
id: distribution_other
attributes:
label: If Other, please specify
placeholder: e.g., PikaOS, Void Linux, etc.
validations:
required: false
- type: dropdown
id: installation_method
attributes:
label: Select your Installation Method
options:
- DankInstaller
- Distro Packaging
- Source
validations:
required: true
- type: dropdown
id: original_installation_method_different
attributes:
label: Was your original Installation method different?
options:
- "Yes"
- No (specify below)
default: 0
validations:
required: false
- type: input
id: original_installation_method_specify
attributes:
label: If no, specify
placeholder: e.g., Distro Packaging, then Source
validations:
required: false
- type: textarea
id: dms_doctor
attributes:
label: dms doctor -vC
description: Output of `dms doctor -vC` command
description: Output of `dms doctor -vC` command — paste between the lines below to keep it collapsed in the issue
placeholder: Paste the output of `dms doctor -vC` here
value: |
<details>
<summary>Click to expand</summary>
</details>
validations:
required: false
- type: textarea

View File

@@ -1,383 +0,0 @@
name: Update OBS Packages
on:
workflow_dispatch:
inputs:
package:
description: "Package to update (dms, dms-git, or all)"
required: false
default: "all"
force_upload:
description: "Force upload without version check"
required: false
default: "false"
type: choice
options:
- "false"
- "true"
rebuild_release:
description: "Release number for rebuilds (e.g., 2, 3, 4 to increment spec Release)"
required: false
default: ""
push:
tags:
- "v*"
schedule:
- cron: "0 */3 * * *" # Every 3 hours for dms-git builds
jobs:
check-updates:
name: Check for updates
runs-on: ubuntu-latest
outputs:
has_updates: ${{ steps.check.outputs.has_updates }}
packages: ${{ steps.check.outputs.packages }}
version: ${{ steps.check.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install OSC
run: |
sudo apt-get update
sudo apt-get install -y osc
mkdir -p ~/.config/osc
cat > ~/.config/osc/oscrc << EOF
[general]
apiurl = https://api.opensuse.org
[https://api.opensuse.org]
user = ${{ secrets.OBS_USERNAME }}
pass = ${{ secrets.OBS_PASSWORD }}
EOF
chmod 600 ~/.config/osc/oscrc
- name: Check for updates
id: check
run: |
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/ ]]; then
echo "packages=dms" >> $GITHUB_OUTPUT
VERSION="${GITHUB_REF#refs/tags/}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "Triggered by tag: $VERSION (always update)"
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "packages=dms-git" >> $GITHUB_OUTPUT
echo "Checking if dms-git source has changed..."
# Get current commit hash (8 chars to match spec format)
CURRENT_COMMIT=$(git rev-parse --short=8 HEAD)
# Check OBS for last uploaded commit
OBS_BASE="$HOME/.cache/osc-checkouts"
mkdir -p "$OBS_BASE"
OBS_PROJECT="home:AvengeMedia:dms-git"
if [[ -d "$OBS_BASE/$OBS_PROJECT/dms-git" ]]; then
cd "$OBS_BASE/$OBS_PROJECT/dms-git"
osc up -q 2>/dev/null || true
# Extract commit hash from spec Version line & format like; 0.6.2+git2264.a679be68
if [[ -f "dms-git.spec" ]]; then
OBS_COMMIT=$(grep "^Version:" "dms-git.spec" | grep -oP '\.[a-f0-9]{8}' | tr -d '.' || echo "")
if [[ -n "$OBS_COMMIT" ]]; then
if [[ "$CURRENT_COMMIT" == "$OBS_COMMIT" ]]; then
echo "has_updates=false" >> $GITHUB_OUTPUT
echo "📋 Commit $CURRENT_COMMIT already uploaded to OBS, skipping"
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 New commit detected: $CURRENT_COMMIT (OBS has $OBS_COMMIT)"
fi
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 Could not extract OBS commit, proceeding with update"
fi
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 No spec file in OBS, proceeding with update"
fi
cd "${{ github.workspace }}"
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 First upload to OBS, update needed"
fi
elif [[ "${{ github.event.inputs.force_upload }}" == "true" ]]; then
PKG="${{ github.event.inputs.package }}"
if [[ -z "$PKG" || "$PKG" == "all" ]]; then
echo "packages=all" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "🚀 Force upload: all packages"
else
echo "packages=$PKG" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "🚀 Force upload: $PKG"
fi
elif [[ -n "${{ github.event.inputs.package }}" ]]; then
echo "packages=${{ github.event.inputs.package }}" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "Manual trigger: ${{ github.event.inputs.package }}"
else
echo "packages=all" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
fi
update-obs:
name: Upload to OBS
needs: check-updates
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
if: |
github.event.inputs.force_upload == 'true' ||
github.event_name == 'workflow_dispatch' ||
needs.check-updates.outputs.has_updates == 'true'
steps:
- name: Generate GitHub App Token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Check if last commit was automated
id: check-loop
run: |
LAST_COMMIT_MSG=$(git log -1 --pretty=%B | head -1)
if [[ "$LAST_COMMIT_MSG" == "ci: Auto-update PPA packages"* ]] || [[ "$LAST_COMMIT_MSG" == "ci: Auto-update OBS packages"* ]]; then
echo "⏭️ Last commit was automated ($LAST_COMMIT_MSG), skipping to prevent infinite loop"
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "✅ Last commit was not automated, proceeding"
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: Determine packages to update
if: steps.check-loop.outputs.skip != 'true'
id: packages
run: |
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" =~ ^refs/tags/ ]]; then
echo "packages=dms" >> $GITHUB_OUTPUT
VERSION="${GITHUB_REF#refs/tags/}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Triggered by tag: $VERSION"
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
echo "Triggered by schedule: updating git package"
elif [[ -n "${{ github.event.inputs.package }}" ]]; then
echo "packages=${{ github.event.inputs.package }}" >> $GITHUB_OUTPUT
echo "Manual trigger: ${{ github.event.inputs.package }}"
else
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
fi
- name: Update dms-git spec version
if: steps.check-loop.outputs.skip != 'true' && (contains(steps.packages.outputs.packages, 'dms-git') || steps.packages.outputs.packages == 'all')
run: |
# Get commit info for dms-git versioning
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
COMMIT_COUNT=$(git rev-list --count HEAD)
BASE_VERSION=$(grep -oP '^Version:\s+\K[0-9.]+' distro/opensuse/dms.spec | head -1 || echo "0.6.2")
NEW_VERSION="${BASE_VERSION}+git${COMMIT_COUNT}.${COMMIT_HASH}"
echo "📦 Updating dms-git.spec to version: $NEW_VERSION"
# Update version in spec
sed -i "s/^Version:.*/Version: $NEW_VERSION/" distro/opensuse/dms-git.spec
# Add changelog entry
DATE_STR=$(date "+%a %b %d %Y")
CHANGELOG_ENTRY="* $DATE_STR Avenge Media <AvengeMedia.US@gmail.com> - ${NEW_VERSION}-1\n- Git snapshot (commit $COMMIT_COUNT: $COMMIT_HASH)"
sed -i "/%changelog/a\\$CHANGELOG_ENTRY" distro/opensuse/dms-git.spec
- name: Update Debian dms-git changelog version
if: steps.check-loop.outputs.skip != 'true' && (contains(steps.packages.outputs.packages, 'dms-git') || steps.packages.outputs.packages == 'all')
run: |
# Get commit info for dms-git versioning
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
COMMIT_COUNT=$(git rev-list --count HEAD)
BASE_VERSION=$(grep -oP '^Version:\s+\K[0-9.]+' distro/opensuse/dms.spec | head -1 || echo "0.6.2")
# Debian version format: 0.6.2+git2256.9162e314
NEW_VERSION="${BASE_VERSION}+git${COMMIT_COUNT}.${COMMIT_HASH}"
echo "📦 Updating Debian dms-git changelog to version: $NEW_VERSION"
CHANGELOG_DATE=$(date -R)
CHANGELOG_FILE="distro/debian/dms-git/debian/changelog"
# Get current version from changelog
CURRENT_VERSION=$(head -1 "$CHANGELOG_FILE" | sed 's/.*(\([^)]*\)).*/\1/')
echo "Current Debian version: $CURRENT_VERSION"
echo "New version: $NEW_VERSION"
# Only update if version changed
if [ "$CURRENT_VERSION" != "$NEW_VERSION" ]; then
# Create new changelog entry at top
TEMP_CHANGELOG=$(mktemp)
cat > "$TEMP_CHANGELOG" << EOF
dms-git ($NEW_VERSION) nightly; urgency=medium
* Git snapshot (commit $COMMIT_COUNT: $COMMIT_HASH)
-- Avenge Media <AvengeMedia.US@gmail.com> $CHANGELOG_DATE
EOF
# Prepend to existing changelog
cat "$CHANGELOG_FILE" >> "$TEMP_CHANGELOG"
mv "$TEMP_CHANGELOG" "$CHANGELOG_FILE"
echo "✓ Updated Debian changelog: $CURRENT_VERSION → $NEW_VERSION"
else
echo "✓ Debian changelog already at version $NEW_VERSION"
fi
- name: Update dms stable version
if: steps.check-loop.outputs.skip != 'true' && steps.packages.outputs.version != ''
run: |
VERSION="${{ steps.packages.outputs.version }}"
VERSION_NO_V="${VERSION#v}"
echo "Updating packaging to version $VERSION_NO_V"
# Update openSUSE dms spec (stable only)
sed -i "s/^Version:.*/Version: $VERSION_NO_V/" distro/opensuse/dms.spec
# Update openSUSE spec changelog
DATE_STR=$(date "+%a %b %d %Y")
CHANGELOG_ENTRY="* $DATE_STR AvengeMedia <maintainer@avengemedia.com> - ${VERSION_NO_V}-1\\n- Update to stable $VERSION release\\n- Bug fixes and improvements"
sed -i "/%changelog/a\\$CHANGELOG_ENTRY\\n" distro/opensuse/dms.spec
# Update Debian _service files (both tar_scm and download_url formats)
for service in distro/debian/*/_service; do
if [[ -f "$service" ]]; then
# Update tar_scm revision parameter (for dms-git)
sed -i "s|<param name=\"revision\">v[0-9.]*</param>|<param name=\"revision\">$VERSION</param>|" "$service"
# Update download_url paths (for dms stable)
sed -i "s|/v[0-9.]\+/|/$VERSION/|g" "$service"
sed -i "s|/tags/v[0-9.]\+\.tar\.gz|/tags/$VERSION.tar.gz|g" "$service"
fi
done
# Update Debian changelog for dms stable
if [[ -f "distro/debian/dms/debian/changelog" ]]; then
CHANGELOG_DATE=$(date -R)
TEMP_CHANGELOG=$(mktemp)
cat > "$TEMP_CHANGELOG" << EOF
dms ($VERSION_NO_V) stable; urgency=medium
* Update to $VERSION stable release
* Bug fixes and improvements
-- Avenge Media <AvengeMedia.US@gmail.com> $CHANGELOG_DATE
EOF
cat "distro/debian/dms/debian/changelog" >> "$TEMP_CHANGELOG"
mv "$TEMP_CHANGELOG" "distro/debian/dms/debian/changelog"
echo "✓ Updated Debian changelog to $VERSION_NO_V"
fi
- name: Install Go
if: steps.check-loop.outputs.skip != 'true'
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: Install OSC
if: steps.check-loop.outputs.skip != 'true'
run: |
sudo apt-get update
sudo apt-get install -y osc
mkdir -p ~/.config/osc
cat > ~/.config/osc/oscrc << EOF
[general]
apiurl = https://api.opensuse.org
[https://api.opensuse.org]
user = ${{ secrets.OBS_USERNAME }}
pass = ${{ secrets.OBS_PASSWORD }}
EOF
chmod 600 ~/.config/osc/oscrc
- name: Upload to OBS
if: steps.check-loop.outputs.skip != 'true'
env:
FORCE_UPLOAD: ${{ github.event.inputs.force_upload }}
REBUILD_RELEASE: ${{ github.event.inputs.rebuild_release }}
run: |
PACKAGES="${{ steps.packages.outputs.packages }}"
MESSAGE="Automated update from GitHub Actions"
if [[ -n "${{ steps.packages.outputs.version }}" ]]; then
MESSAGE="Update to ${{ steps.packages.outputs.version }}"
fi
if [[ "$PACKAGES" == "all" ]]; then
bash distro/scripts/obs-upload.sh dms "$MESSAGE"
bash distro/scripts/obs-upload.sh dms-git "Automated git update"
else
bash distro/scripts/obs-upload.sh "$PACKAGES" "$MESSAGE"
fi
- name: Get changed packages
if: steps.check-loop.outputs.skip != 'true'
id: changed-packages
run: |
# Check if there are any changes to commit
if git diff --exit-code distro/debian/ distro/opensuse/ >/dev/null 2>&1; then
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "📋 No changelog or spec changes to commit"
else
echo "has_changes=true" >> $GITHUB_OUTPUT
# Get list of changed packages for commit message
CHANGED_DEB=$(git diff --name-only distro/debian/ 2>/dev/null | grep 'debian/changelog' | xargs dirname 2>/dev/null | xargs dirname 2>/dev/null | xargs basename 2>/dev/null | tr '\n' ', ' | sed 's/, $//' || echo "")
CHANGED_SUSE=$(git diff --name-only distro/opensuse/ 2>/dev/null | grep '\.spec$' | sed 's|distro/opensuse/||' | sed 's/\.spec$//' | tr '\n' ', ' | sed 's/, $//' || echo "")
PKGS=$(echo "$CHANGED_DEB,$CHANGED_SUSE" | tr ',' '\n' | grep -v '^$' | sort -u | tr '\n' ',' | sed 's/,$//')
echo "packages=$PKGS" >> $GITHUB_OUTPUT
echo "📋 Changed packages: $PKGS"
fi
- name: Commit packaging changes
if: steps.check-loop.outputs.skip != 'true' && steps.changed-packages.outputs.has_changes == 'true'
run: |
git config user.name "dms-ci[bot]"
git config user.email "dms-ci[bot]@users.noreply.github.com"
git add distro/debian/*/debian/changelog distro/opensuse/*.spec
git commit -m "ci: Auto-update OBS packages [${{ steps.changed-packages.outputs.packages }}]" -m "🤖 Automated by GitHub Actions"
git pull --rebase origin master
git push
- name: Summary
run: |
echo "### OBS Package Update Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Packages**: ${{ steps.packages.outputs.packages }}" >> $GITHUB_STEP_SUMMARY
if [[ -n "${{ steps.packages.outputs.version }}" ]]; then
echo "- **Version**: ${{ steps.packages.outputs.version }}" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.check-updates.outputs.has_updates }}" == "false" ]]; then
echo "- **Status**: Skipped (no changes detected)" >> $GITHUB_STEP_SUMMARY
fi
echo "- **Project**: https://build.opensuse.org/project/show/home:AvengeMedia" >> $GITHUB_STEP_SUMMARY

View File

@@ -1,298 +0,0 @@
name: Update PPA Packages
on:
workflow_dispatch:
inputs:
package:
description: "Package to upload (dms, dms-git, dms-greeter, or all)"
required: false
default: "dms-git"
force_upload:
description: "Force upload without version check"
required: false
default: "false"
type: choice
options:
- "false"
- "true"
rebuild_release:
description: "Release number for rebuilds (e.g., 2, 3, 4 for ppa2, ppa3, ppa4)"
required: false
default: ""
schedule:
- cron: "0 */3 * * *" # Every 3 hours for dms-git builds
jobs:
check-updates:
name: Check for updates
runs-on: ubuntu-latest
outputs:
has_updates: ${{ steps.check.outputs.has_updates }}
packages: ${{ steps.check.outputs.packages }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for updates
id: check
run: |
if [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "packages=dms-git" >> $GITHUB_OUTPUT
echo "Checking if dms-git source has changed..."
# Get current commit hash (8 chars to match changelog format)
CURRENT_COMMIT=$(git rev-parse --short=8 HEAD)
# Extract commit hash from changelog
# Format: dms-git (0.6.2+git2264.c5c5ce84) questing; urgency=medium
CHANGELOG_FILE="distro/ubuntu/dms-git/debian/changelog"
if [[ -f "$CHANGELOG_FILE" ]]; then
CHANGELOG_COMMIT=$(head -1 "$CHANGELOG_FILE" | grep -oP '\.[a-f0-9]{8}' | tr -d '.' || echo "")
if [[ -n "$CHANGELOG_COMMIT" ]]; then
if [[ "$CURRENT_COMMIT" == "$CHANGELOG_COMMIT" ]]; then
echo "has_updates=false" >> $GITHUB_OUTPUT
echo "📋 Commit $CURRENT_COMMIT already in changelog, skipping upload"
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 New commit detected: $CURRENT_COMMIT (changelog has $CHANGELOG_COMMIT)"
fi
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 Could not extract commit from changelog, proceeding with upload"
fi
else
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "📋 No changelog file found, proceeding with upload"
fi
elif [[ -n "${{ github.event.inputs.package }}" ]]; then
echo "packages=${{ github.event.inputs.package }}" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
echo "Manual trigger: ${{ github.event.inputs.package }}"
else
echo "packages=dms-git" >> $GITHUB_OUTPUT
echo "has_updates=true" >> $GITHUB_OUTPUT
fi
upload-ppa:
name: Upload to PPA
needs: check-updates
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
if: |
github.event.inputs.force_upload == 'true' ||
github.event_name == 'workflow_dispatch' ||
needs.check-updates.outputs.has_updates == 'true'
steps:
- name: Generate GitHub App Token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Check if last commit was automated
id: check-loop
run: |
LAST_COMMIT_MSG=$(git log -1 --pretty=%B | head -1)
if [[ "$LAST_COMMIT_MSG" == "ci: Auto-update PPA packages"* ]] || [[ "$LAST_COMMIT_MSG" == "ci: Auto-update OBS packages"* ]]; then
echo "⏭️ Last commit was automated ($LAST_COMMIT_MSG), skipping to prevent infinite loop"
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "✅ Last commit was not automated, proceeding"
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: Set up Go
if: steps.check-loop.outputs.skip != 'true'
uses: actions/setup-go@v5
with:
go-version: "1.24"
cache: false
- name: Install build dependencies
if: steps.check-loop.outputs.skip != 'true'
run: |
sudo apt-get update
sudo apt-get install -y \
debhelper \
devscripts \
dput \
lftp \
build-essential \
fakeroot \
dpkg-dev
- name: Configure GPG
if: steps.check-loop.outputs.skip != 'true'
env:
GPG_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
echo "$GPG_KEY" | gpg --import
GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{print $2}' | cut -d'/' -f2)
echo "DEBSIGN_KEYID=$GPG_KEY_ID" >> $GITHUB_ENV
- name: Determine packages to upload
if: steps.check-loop.outputs.skip != 'true'
id: packages
run: |
if [[ "${{ github.event.inputs.force_upload }}" == "true" ]]; then
PKG="${{ github.event.inputs.package }}"
if [[ -z "$PKG" || "$PKG" == "all" ]]; then
echo "packages=all" >> $GITHUB_OUTPUT
echo "🚀 Force upload: all packages"
else
echo "packages=$PKG" >> $GITHUB_OUTPUT
echo "🚀 Force upload: $PKG"
fi
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
echo "Triggered by schedule: uploading git package"
elif [[ -n "${{ github.event.inputs.package }}" ]]; then
# Manual package selection should respect change detection
SELECTED_PKG="${{ github.event.inputs.package }}"
UPDATED_PKG="${{ needs.check-updates.outputs.packages }}"
# Check if manually selected package is in the updated list
if [[ "$UPDATED_PKG" == *"$SELECTED_PKG"* ]] || [[ "$SELECTED_PKG" == "all" ]]; then
echo "packages=$SELECTED_PKG" >> $GITHUB_OUTPUT
echo "📦 Manual selection (has updates): $SELECTED_PKG"
else
echo "packages=" >> $GITHUB_OUTPUT
echo "⚠️ Manual selection '$SELECTED_PKG' has no updates - skipping (use force_upload to override)"
fi
else
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
fi
- name: Upload to PPA
if: steps.check-loop.outputs.skip != 'true'
run: |
PACKAGES="${{ steps.packages.outputs.packages }}"
REBUILD_RELEASE="${{ github.event.inputs.rebuild_release }}"
if [[ -z "$PACKAGES" ]]; then
echo "No packages selected for upload. Skipping."
exit 0
fi
# Build command arguments
BUILD_ARGS=()
if [[ -n "$REBUILD_RELEASE" ]]; then
BUILD_ARGS+=("$REBUILD_RELEASE")
echo "✓ Using rebuild release number: ppa$REBUILD_RELEASE"
fi
if [[ "$PACKAGES" == "all" ]]; then
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Uploading dms to PPA..."
if [ -n "$REBUILD_RELEASE" ]; then
echo "🔄 Using rebuild release number: ppa$REBUILD_RELEASE"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
bash distro/scripts/ppa-upload.sh dms dms questing "${BUILD_ARGS[@]}"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Uploading dms-git to PPA..."
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
bash distro/scripts/ppa-upload.sh dms-git dms-git questing "${BUILD_ARGS[@]}"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Uploading dms-greeter to PPA..."
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
bash distro/scripts/ppa-upload.sh dms-greeter danklinux questing "${BUILD_ARGS[@]}"
else
# Map package to PPA name
case "$PACKAGES" in
dms)
PPA_NAME="dms"
;;
dms-git)
PPA_NAME="dms-git"
;;
dms-greeter)
PPA_NAME="danklinux"
;;
*)
PPA_NAME="$PACKAGES"
;;
esac
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Uploading $PACKAGES to PPA..."
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
bash distro/scripts/ppa-upload.sh "$PACKAGES" "$PPA_NAME" questing "${BUILD_ARGS[@]}"
fi
- name: Get changed packages
if: steps.check-loop.outputs.skip != 'true'
id: changed-packages
run: |
# Check if there are any changelog changes to commit
if git diff --exit-code distro/ubuntu/ >/dev/null 2>&1; then
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "📋 No changelog changes to commit"
else
echo "has_changes=true" >> $GITHUB_OUTPUT
# Get list of changed packages for commit message (deduplicate)
CHANGED=$(git diff --name-only distro/ubuntu/ | grep 'debian/changelog' | sed 's|/debian/changelog||' | xargs -I{} basename {} | sort -u | tr '\n' ',' | sed 's/,$//')
echo "packages=$CHANGED" >> $GITHUB_OUTPUT
echo "📋 Changed packages: $CHANGED"
echo "📋 Debug - Changed files:"
git diff --name-only distro/ubuntu/ | grep 'debian/changelog' || echo "No changelog files found"
fi
- name: Commit changelog changes
if: steps.check-loop.outputs.skip != 'true' && steps.changed-packages.outputs.has_changes == 'true'
run: |
git config user.name "dms-ci[bot]"
git config user.email "dms-ci[bot]@users.noreply.github.com"
git add distro/ubuntu/*/debian/changelog
git commit -m "ci: Auto-update PPA packages [${{ steps.changed-packages.outputs.packages }}]" -m "🤖 Automated by GitHub Actions"
git pull --rebase origin master
git push
- name: Summary
run: |
echo "### PPA Package Upload Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Packages**: ${{ steps.packages.outputs.packages }}" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.check-updates.outputs.has_updates }}" == "false" ]]; then
echo "- **Status**: Skipped (no changes detected)" >> $GITHUB_STEP_SUMMARY
fi
PACKAGES="${{ steps.packages.outputs.packages }}"
if [[ "$PACKAGES" == "all" ]]; then
echo "- **PPA dms**: https://launchpad.net/~avengemedia/+archive/ubuntu/dms/+packages" >> $GITHUB_STEP_SUMMARY
echo "- **PPA dms-git**: https://launchpad.net/~avengemedia/+archive/ubuntu/dms-git/+packages" >> $GITHUB_STEP_SUMMARY
echo "- **PPA danklinux**: https://launchpad.net/~avengemedia/+archive/ubuntu/danklinux/+packages" >> $GITHUB_STEP_SUMMARY
elif [[ "$PACKAGES" == "dms" ]]; then
echo "- **PPA**: https://launchpad.net/~avengemedia/+archive/ubuntu/dms/+packages" >> $GITHUB_STEP_SUMMARY
elif [[ "$PACKAGES" == "dms-git" ]]; then
echo "- **PPA**: https://launchpad.net/~avengemedia/+archive/ubuntu/dms-git/+packages" >> $GITHUB_STEP_SUMMARY
elif [[ "$PACKAGES" == "dms-greeter" ]]; then
echo "- **PPA**: https://launchpad.net/~avengemedia/+archive/ubuntu/danklinux/+packages" >> $GITHUB_STEP_SUMMARY
fi
if [[ -n "${{ steps.packages.outputs.version }}" ]]; then
echo "- **Version**: ${{ steps.packages.outputs.version }}" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "Builds will appear once Launchpad processes the uploads." >> $GITHUB_STEP_SUMMARY

View File

@@ -5,11 +5,13 @@ repos:
- id: trailing-whitespace
- id: check-yaml
- id: end-of-file-fixer
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.10.0.1
- repo: local
hooks:
- id: shellcheck
args: [-e, SC2164, -e, SC2001, -e, SC2012, -e, SC2317]
name: shellcheck
entry: shellcheck -e SC2164 -e SC2001 -e SC2012 -e SC2317
language: system
types: [shell]
- repo: local
hooks:
- id: go-mod-tidy

View File

@@ -22,7 +22,7 @@ nix develop
This will provide:
- Go 1.24 toolchain (go, gopls, delve, go-tools) and GNU Make
- Go 1.25+ toolchain (go, gopls, delve, go-tools) and GNU Make
- Quickshell and required QML packages
- Properly configured QML2_IMPORT_PATH

View File

@@ -96,7 +96,7 @@ The on-screen preview displays the selected format. JSON output includes hex, RG
## Building
Requires Go 1.24+
Requires Go 1.25+
**Development build:**

View File

@@ -26,6 +26,9 @@ func init() {
Register("cachyos", "#08A283", FamilyArch, func(config DistroConfig, logChan chan<- string) Distribution {
return NewArchDistribution(config, logChan)
})
Register("catos", "#1793D1", FamilyArch, func(config DistroConfig, logChan chan<- string) Distribution {
return NewArchDistribution(config, logChan)
})
Register("endeavouros", "#7F3FBF", FamilyArch, func(config DistroConfig, logChan chan<- string) Distribution {
return NewArchDistribution(config, logChan)
})

View File

@@ -341,6 +341,8 @@ func (n *NiriProvider) buildActionFromNode(bindNode *document.Node) string {
val := arg.ValueString()
if val == "" {
parts = append(parts, `""`)
} else if strings.ContainsAny(val, " \t") {
parts = append(parts, `"`+strings.ReplaceAll(val, `"`, `\"`)+`"`)
} else {
parts = append(parts, val)
}

View File

@@ -232,8 +232,15 @@ func (m *Manager) setupDataDeviceSync() {
return
}
prevOffer := m.currentOffer
m.currentOffer = offer
if prevOffer != nil && prevOffer != offer {
m.offerMutex.Lock()
delete(m.offerMimeTypes, prevOffer)
m.offerMutex.Unlock()
}
m.offerMutex.RLock()
mimes := m.offerMimeTypes[offer]
m.offerMutex.RUnlock()
@@ -587,20 +594,26 @@ func (m *Manager) uriListPreview(data []byte) (string, bool) {
uris = strings.Split(text, "\n")
}
if len(uris) > 1 {
return fmt.Sprintf("[[ %d files ]]", len(uris)), false
}
if len(uris) == 1 && strings.HasPrefix(uris[0], "file://") {
filePath := strings.TrimPrefix(uris[0], "file://")
if info, err := os.Stat(filePath); err == nil && !info.IsDir() {
info, err := os.Stat(filePath)
if err != nil || info.IsDir() {
return m.textPreview(data), false
}
cfg := m.getConfig()
if info.Size() <= cfg.MaxEntrySize {
if imgData, err := os.ReadFile(filePath); err == nil {
if config, imgFmt, err := image.DecodeConfig(bytes.NewReader(imgData)); err == nil {
return fmt.Sprintf("[[ file %s %s %dx%d ]]", filepath.Base(filePath), imgFmt, config.Width, config.Height), true
}
}
return fmt.Sprintf("[[ file %s ]]", filepath.Base(filePath)), false
}
}
if len(uris) > 1 {
return fmt.Sprintf("[[ %d files ]]", len(uris)), false
return fmt.Sprintf("[[ file %s ]]", filepath.Base(filePath)), false
}
return m.textPreview(data), false
@@ -623,6 +636,11 @@ func (m *Manager) tryReadImageFromURI(data []byte) ([]byte, string, bool) {
return nil, "", false
}
cfg := m.getConfig()
if info.Size() > cfg.MaxEntrySize {
return nil, "", false
}
imgData, err := os.ReadFile(filePath)
if err != nil {
return nil, "", false

View File

@@ -16,4 +16,8 @@ const (
dbusScreensaverPath = "/ScreenSaver"
dbusScreensaverPath2 = "/org/freedesktop/ScreenSaver"
dbusScreensaverInterface = "org.freedesktop.ScreenSaver"
dbusGnomeScreensaverName = "org.gnome.ScreenSaver"
dbusGnomeScreensaverPath = "/org/gnome/ScreenSaver"
dbusGnomeScreensaverInterface = "org.gnome.ScreenSaver"
)

View File

@@ -191,6 +191,12 @@ func (m *Manager) Close() {
return true
})
m.screensaverSubscribers.Range(func(key string, ch chan ScreensaverState) bool {
close(ch)
m.screensaverSubscribers.Delete(key)
return true
})
if m.systemConn != nil {
m.systemConn.Close()
}

View File

@@ -1,6 +1,7 @@
package freedesktop
import (
"fmt"
"path/filepath"
"strings"
"sync/atomic"
@@ -15,45 +16,9 @@ type screensaverHandler struct {
manager *Manager
}
func (m *Manager) initializeScreensaver() error {
if m.sessionConn == nil {
m.stateMutex.Lock()
m.state.Screensaver.Available = false
m.stateMutex.Unlock()
return nil
}
reply, err := m.sessionConn.RequestName(dbusScreensaverName, dbus.NameFlagDoNotQueue)
if err != nil {
log.Warnf("Failed to request screensaver name: %v", err)
m.stateMutex.Lock()
m.state.Screensaver.Available = false
m.stateMutex.Unlock()
return nil
}
if reply != dbus.RequestNameReplyPrimaryOwner {
log.Warnf("Screensaver name already owned by another process")
m.stateMutex.Lock()
m.state.Screensaver.Available = false
m.stateMutex.Unlock()
return nil
}
handler := &screensaverHandler{manager: m}
if err := m.sessionConn.Export(handler, dbusScreensaverPath, dbusScreensaverInterface); err != nil {
log.Warnf("Failed to export screensaver on %s: %v", dbusScreensaverPath, err)
return nil
}
if err := m.sessionConn.Export(handler, dbusScreensaverPath2, dbusScreensaverInterface); err != nil {
log.Warnf("Failed to export screensaver on %s: %v", dbusScreensaverPath2, err)
return nil
}
screensaverIface := introspect.Interface{
Name: dbusScreensaverInterface,
func screensaverIntrospectIface(ifaceName string) introspect.Interface {
return introspect.Interface{
Name: ifaceName,
Methods: []introspect.Method{
{
Name: "Inhibit",
@@ -69,40 +34,106 @@ func (m *Manager) initializeScreensaver() error {
{Name: "cookie", Type: "u", Direction: "in"},
},
},
{
Name: "GetActive",
Args: []introspect.Arg{
{Name: "active", Type: "b", Direction: "out"},
},
},
{
Name: "SetActive",
Args: []introspect.Arg{
{Name: "active", Type: "b", Direction: "in"},
},
},
{
Name: "Lock",
},
},
Signals: []introspect.Signal{
{
Name: "ActiveChanged",
Args: []introspect.Arg{
{Name: "new_value", Type: "b"},
},
},
},
}
}
func (m *Manager) initializeScreensaver() error {
if m.sessionConn == nil {
m.stateMutex.Lock()
m.state.Screensaver.Available = false
m.stateMutex.Unlock()
return nil
}
introNode := &introspect.Node{
Name: dbusScreensaverPath,
Interfaces: []introspect.Interface{
introspect.IntrospectData,
screensaverIface,
},
}
if err := m.sessionConn.Export(introspect.NewIntrospectable(introNode), dbusScreensaverPath, "org.freedesktop.DBus.Introspectable"); err != nil {
log.Warnf("Failed to export introspectable on %s: %v", dbusScreensaverPath, err)
}
handler := &screensaverHandler{manager: m}
introNode2 := &introspect.Node{
Name: dbusScreensaverPath2,
Interfaces: []introspect.Interface{
introspect.IntrospectData,
screensaverIface,
},
}
if err := m.sessionConn.Export(introspect.NewIntrospectable(introNode2), dbusScreensaverPath2, "org.freedesktop.DBus.Introspectable"); err != nil {
log.Warnf("Failed to export introspectable on %s: %v", dbusScreensaverPath2, err)
m.screensaverFreedesktopClaimed = m.claimScreensaverName(handler,
dbusScreensaverName, dbusScreensaverInterface, dbusScreensaverPath, dbusScreensaverPath2)
m.screensaverGnomeClaimed = m.claimScreensaverName(handler,
dbusGnomeScreensaverName, dbusGnomeScreensaverInterface, dbusGnomeScreensaverPath)
if !m.screensaverFreedesktopClaimed && !m.screensaverGnomeClaimed {
log.Warn("No screensaver interface could be claimed")
m.stateMutex.Lock()
m.state.Screensaver.Available = false
m.stateMutex.Unlock()
return nil
}
go m.watchPeerDisconnects()
m.stateMutex.Lock()
m.state.Screensaver.Available = true
m.state.Screensaver.Active = false
m.state.Screensaver.Inhibited = false
m.state.Screensaver.Inhibitors = []ScreensaverInhibitor{}
m.stateMutex.Unlock()
log.Info("Screensaver inhibit listener initialized")
log.Info("Screensaver listener initialized")
return nil
}
func (m *Manager) claimScreensaverName(handler *screensaverHandler, name, iface string, paths ...dbus.ObjectPath) bool {
reply, err := m.sessionConn.RequestName(name, dbus.NameFlagDoNotQueue)
if err != nil {
log.Warnf("Failed to request screensaver name %s: %v", name, err)
return false
}
if reply != dbus.RequestNameReplyPrimaryOwner {
log.Warnf("Screensaver name %s already owned by another process", name)
return false
}
if err := m.exportScreensaverOnPaths(handler, iface, paths...); err != nil {
log.Warnf("Failed to export screensaver on %s: %v", name, err)
return false
}
log.Infof("Claimed %s on session bus", name)
return true
}
// exportScreensaverOnPaths exports the handler and introspection on the given
// paths under the specified interface name.
func (m *Manager) exportScreensaverOnPaths(handler *screensaverHandler, ifaceName string, paths ...dbus.ObjectPath) error {
iface := screensaverIntrospectIface(ifaceName)
for _, path := range paths {
if err := m.sessionConn.Export(handler, path, ifaceName); err != nil {
return fmt.Errorf("export handler on %s: %w", path, err)
}
node := &introspect.Node{
Name: string(path),
Interfaces: []introspect.Interface{
introspect.IntrospectData,
iface,
},
}
if err := m.sessionConn.Export(introspect.NewIntrospectable(node), path, "org.freedesktop.DBus.Introspectable"); err != nil {
log.Warnf("Failed to export introspectable on %s: %v", path, err)
}
}
return nil
}
@@ -268,3 +299,51 @@ func (m *Manager) NotifyScreensaverSubscribers() {
return true
})
}
func (h *screensaverHandler) GetActive() (bool, *dbus.Error) {
h.manager.stateMutex.RLock()
active := h.manager.state.Screensaver.Active
h.manager.stateMutex.RUnlock()
return active, nil
}
func (h *screensaverHandler) SetActive(active bool) *dbus.Error {
h.manager.SetScreenLockActive(active)
return nil
}
func (h *screensaverHandler) Lock() *dbus.Error {
h.manager.SetScreenLockActive(true)
return nil
}
func (m *Manager) SetScreenLockActive(active bool) {
m.stateMutex.Lock()
changed := m.state.Screensaver.Active != active
m.state.Screensaver.Active = active
m.stateMutex.Unlock()
if !changed {
return
}
log.Infof("Screen lock active changed: %v", active)
defer m.NotifyScreensaverSubscribers()
if m.sessionConn == nil {
return
}
if m.screensaverFreedesktopClaimed {
if err := m.sessionConn.Emit(dbusScreensaverPath, dbusScreensaverInterface+".ActiveChanged", active); err != nil {
log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusScreensaverPath, err)
}
if err := m.sessionConn.Emit(dbusScreensaverPath2, dbusScreensaverInterface+".ActiveChanged", active); err != nil {
log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusScreensaverPath2, err)
}
}
if m.screensaverGnomeClaimed {
if err := m.sessionConn.Emit(dbusGnomeScreensaverPath, dbusGnomeScreensaverInterface+".ActiveChanged", active); err != nil {
log.Warnf("Failed to emit ActiveChanged on %s: %v", dbusGnomeScreensaverPath, err)
}
}
}

View File

@@ -0,0 +1,102 @@
package freedesktop
import (
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestSetScreenLockActive_ChangesState(t *testing.T) {
manager := &Manager{
state: &FreedeskState{
Screensaver: ScreensaverState{Available: true},
},
stateMutex: sync.RWMutex{},
}
assert.False(t, manager.GetScreensaverState().Active)
manager.SetScreenLockActive(true)
assert.True(t, manager.GetScreensaverState().Active)
manager.SetScreenLockActive(false)
assert.False(t, manager.GetScreensaverState().Active)
}
func TestSetScreenLockActive_NoChangeNoDuplicate(t *testing.T) {
ch := make(chan ScreensaverState, 64)
manager := &Manager{
state: &FreedeskState{
Screensaver: ScreensaverState{Available: true, Active: false},
},
stateMutex: sync.RWMutex{},
}
manager.screensaverSubscribers.Store("test", ch)
defer manager.screensaverSubscribers.Delete("test")
// Setting to same value should not notify
manager.SetScreenLockActive(false)
select {
case <-ch:
t.Fatal("should not have received notification for no-change")
case <-time.After(50 * time.Millisecond):
// Expected: no notification
}
}
func TestSetScreenLockActive_NotifiesSubscribers(t *testing.T) {
ch := make(chan ScreensaverState, 64)
manager := &Manager{
state: &FreedeskState{
Screensaver: ScreensaverState{Available: true, Active: false},
},
stateMutex: sync.RWMutex{},
}
manager.screensaverSubscribers.Store("test", ch)
defer manager.screensaverSubscribers.Delete("test")
manager.SetScreenLockActive(true)
select {
case state := <-ch:
assert.True(t, state.Active)
case <-time.After(time.Second):
t.Fatal("timeout waiting for subscriber notification")
}
}
func TestSetScreenLockActive_NilSessionConn(t *testing.T) {
manager := &Manager{
state: &FreedeskState{
Screensaver: ScreensaverState{Available: true},
},
stateMutex: sync.RWMutex{},
}
assert.NotPanics(t, func() {
manager.SetScreenLockActive(true)
})
assert.True(t, manager.GetScreensaverState().Active)
}
func TestGetActive_ReturnsCurrentState(t *testing.T) {
manager := &Manager{
state: &FreedeskState{
Screensaver: ScreensaverState{Available: true, Active: true},
},
stateMutex: sync.RWMutex{},
}
handler := &screensaverHandler{manager: manager}
active, dbusErr := handler.GetActive()
assert.Nil(t, dbusErr)
assert.True(t, active)
}
func TestScreensaverState_ActiveDefaultsFalse(t *testing.T) {
state := ScreensaverState{}
assert.False(t, state.Active)
}

View File

@@ -39,6 +39,7 @@ type ScreensaverInhibitor struct {
type ScreensaverState struct {
Available bool `json:"available"`
Active bool `json:"active"`
Inhibited bool `json:"inhibited"`
Inhibitors []ScreensaverInhibitor `json:"inhibitors"`
}
@@ -50,14 +51,16 @@ type FreedeskState struct {
}
type Manager struct {
state *FreedeskState
stateMutex sync.RWMutex
systemConn *dbus.Conn
sessionConn *dbus.Conn
accountsObj dbus.BusObject
settingsObj dbus.BusObject
currentUID uint64
subscribers syncmap.Map[string, chan FreedeskState]
screensaverSubscribers syncmap.Map[string, chan ScreensaverState]
screensaverCookieCounter uint32
state *FreedeskState
stateMutex sync.RWMutex
systemConn *dbus.Conn
sessionConn *dbus.Conn
accountsObj dbus.BusObject
settingsObj dbus.BusObject
currentUID uint64
subscribers syncmap.Map[string, chan FreedeskState]
screensaverSubscribers syncmap.Map[string, chan ScreensaverState]
screensaverCookieCounter uint32
screensaverFreedesktopClaimed bool
screensaverGnomeClaimed bool
}

View File

@@ -1516,7 +1516,11 @@ func Start(printDocs bool) error {
}
}()
loginctlReady := make(chan struct{})
freedesktopReady := make(chan struct{})
go func() {
defer close(loginctlReady)
if err := InitializeLoginctlManager(); err != nil {
log.Warnf("Loginctl manager unavailable: %v", err)
} else {
@@ -1525,6 +1529,7 @@ func Start(printDocs bool) error {
}()
go func() {
defer close(freedesktopReady)
if err := InitializeFreedeskManager(); err != nil {
log.Warnf("Freedesktop manager unavailable: %v", err)
} else if freedesktopManager != nil {
@@ -1533,6 +1538,31 @@ func Start(printDocs bool) error {
}
}()
// Bridge loginctl lock state to the freedesktop/gnome screensaver
// ActiveChanged signal so apps like Bitwarden can detect screen lock.
go func() {
<-loginctlReady
<-freedesktopReady
if loginctlManager == nil || freedesktopManager == nil {
return
}
ch := loginctlManager.Subscribe("dms-lock-bridge")
defer loginctlManager.Unsubscribe("dms-lock-bridge")
initial := loginctlManager.GetState()
lastLocked := initial.Locked
freedesktopManager.SetScreenLockActive(lastLocked)
for state := range ch {
if state.Locked != lastLocked {
lastLocked = state.Locked
freedesktopManager.SetScreenLockActive(lastLocked)
}
}
}()
if err := InitializeWaylandManager(); err != nil {
log.Warnf("Wayland manager unavailable: %v", err)
}

View File

@@ -162,7 +162,7 @@ func TestCleanupStaleSockets(t *testing.T) {
tempDir := t.TempDir()
t.Setenv("XDG_RUNTIME_DIR", tempDir)
staleSocket := filepath.Join(tempDir, "danklinux-999999.sock")
staleSocket := filepath.Join(tempDir, "danklinux-4194305.sock")
err := os.WriteFile(staleSocket, []byte{}, 0o600)
require.NoError(t, err)

View File

@@ -181,7 +181,7 @@
buildInputs =
with pkgs;
[
go_1_24
go_1_25
gopls
delve
go-tools
@@ -189,6 +189,7 @@
prek
uv # for prek
shellcheck
# Nix development tools
nixd

View File

@@ -142,6 +142,8 @@ Singleton {
if (tabIndex !== undefined && popout.currentTabIndex !== undefined) {
popout.currentTabIndex = tabIndex;
}
if (popout.updateSurfacePosition)
popout.updateSurfacePosition();
currentPopoutTriggers[screenName] = triggerId;
return;
}

View File

@@ -18,7 +18,7 @@ FloatingWindow {
}
objectName: "changelogModal"
title: "What's New"
title: i18n("What's New")
minimumSize: Qt.size(modalWidth, modalHeight)
maximumSize: Qt.size(modalWidth, modalHeight)
color: Theme.surfaceContainer
@@ -81,7 +81,7 @@ FloatingWindow {
onClicked: root.dismiss()
DankTooltip {
text: "Close"
text: i18n("Close")
}
}
}
@@ -125,7 +125,7 @@ FloatingWindow {
spacing: Theme.spacingM
DankButton {
text: "Read Full Release Notes"
text: i18n("Read Full Release Notes")
iconName: "open_in_new"
backgroundColor: Theme.surfaceContainerHighest
textColor: Theme.surfaceText
@@ -133,7 +133,7 @@ FloatingWindow {
}
DankButton {
text: "Got It"
text: i18n("Got It")
iconName: "check"
backgroundColor: Theme.primary
textColor: Theme.primaryText

View File

@@ -12,7 +12,7 @@ Singleton {
readonly property int popoutWidth: 550
readonly property int popoutHeight: 500
readonly property int itemHeight: 72
readonly property int thumbnailSize: 48
readonly property int thumbnailSize: 100
readonly property int retryInterval: 50
readonly property int viewportBuffer: 100
readonly property int extendedBuffer: 200

View File

@@ -84,7 +84,8 @@ Rectangle {
anchors.right: actionButtons.left
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
height: contentColumn.implicitHeight
// height: contentColumn.implicitHeight
height: ClipboardConstants.itemHeight
clip: true
ClipboardThumbnail {
@@ -92,7 +93,7 @@ Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: entryType === "image" ? ClipboardConstants.thumbnailSize : Theme.iconSize
height: entryType === "image" ? ClipboardConstants.thumbnailSize : Theme.iconSize
height: entryType === "image" ? ClipboardConstants.itemHeight - 4 : Theme.iconSize // 100 - 4 = 96, 96:72 = 4:3
entry: root.entry
entryType: root.entryType
modal: root.modal

View File

@@ -137,23 +137,23 @@ Item {
anchors.margins: 2
source: thumbnailImage
maskEnabled: true
maskSource: clipboardCircularMask
maskSource: clipboardRoundedRectangularMask
visible: entryType === "image" && thumbnailImage.status === Image.Ready && thumbnailImage.source != ""
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
Item {
id: clipboardCircularMask
width: ClipboardConstants.thumbnailSize - 4
height: ClipboardConstants.thumbnailSize - 4
id: clipboardRoundedRectangularMask
width: ClipboardConstants.thumbnailSize
height: ClipboardConstants.itemHeight - 4
layer.enabled: true
layer.smooth: true
visible: false
Rectangle {
anchors.fill: parent
radius: width / 2
radius: Theme.cornerRadius / 2 // Thumbnail corner radius is divided by 2 so it doesnt look weird on large corner radius (eg: 32px)
color: "black"
antialiasing: true
}

View File

@@ -684,12 +684,15 @@ Item {
if (searchMode === "all") {
if (searchQuery && searchQuery.length >= 2) {
_pluginPhasePending = true;
_pluginPhaseForceFirst = shouldResetSelection;
_phase1Items = allItems;
_phase1Items = allItems.slice();
pluginPhaseTimer.restart();
isSearching = true;
searchCompleted();
return;
if (allItems.length === 0) {
_pluginPhaseForceFirst = shouldResetSelection;
isSearching = true;
searchCompleted();
return;
}
_pluginPhaseForceFirst = false;
} else if (!searchQuery) {
var emptyTriggerOrdered = getEmptyTriggerPluginsOrdered();
for (var i = 0; i < emptyTriggerOrdered.length; i++) {
@@ -1614,25 +1617,41 @@ Item {
itemExecuted();
}
function launchApp(app) {
function _resolveDesktopEntry(app) {
if (!app)
return null;
if (app.command)
return app;
var id = app.id || app.execString || app.exec || "";
if (!id)
return null;
return DesktopEntries.heuristicLookup(id);
}
function launchApp(app) {
var entry = _resolveDesktopEntry(app);
if (!entry)
return;
SessionService.launchDesktopEntry(app);
AppUsageHistoryData.addAppUsage(app);
SessionService.launchDesktopEntry(entry);
AppUsageHistoryData.addAppUsage(entry);
}
function launchAppWithNvidia(app) {
if (!app)
var entry = _resolveDesktopEntry(app);
if (!entry)
return;
SessionService.launchDesktopEntry(app, true);
AppUsageHistoryData.addAppUsage(app);
SessionService.launchDesktopEntry(entry, true);
AppUsageHistoryData.addAppUsage(entry);
}
function launchAppAction(actionItem) {
if (!actionItem || !actionItem.parentApp || !actionItem.actionData)
if (!actionItem || !actionItem.actionData)
return;
SessionService.launchDesktopAction(actionItem.parentApp, actionItem.actionData);
AppUsageHistoryData.addAppUsage(actionItem.parentApp);
var entry = _resolveDesktopEntry(actionItem.parentApp);
if (!entry)
return;
SessionService.launchDesktopAction(entry, actionItem.actionData);
AppUsageHistoryData.addAppUsage(entry);
}
function openFile(path) {

View File

@@ -470,9 +470,6 @@ FocusScope {
onTextChanged: {
controller.setSearchQuery(text);
if (text.length === 0) {
controller.restorePreviousMode();
}
if (actionPanel.expanded) {
actionPanel.hide();
}

View File

@@ -123,6 +123,7 @@ DankModal {
function generateCategories(query) {
const lowerQuery = query ? query.toLowerCase().trim() : "";
const lowerQueryWords = query.split(/\s+/);
const processed = {};
for (const cat in rawBinds) {
@@ -135,10 +136,25 @@ DankModal {
const keyLower = bind.key.toLowerCase();
const descLower = bind.desc.toLowerCase();
const actionLower = bind.action.toLowerCase();
if (!(lowerQuery.length === 0 || keyLower.includes(lowerQuery) || descLower.includes(lowerQuery) || catLower.includes(lowerQuery) || actionLower.includes(lowerQuery)))
continue;
if (bind.hideOnOverlay)
continue;
let shouldContinue = false;
for (let j = 0; j < lowerQueryWords.length; j++) {
const word = lowerQueryWords[j];
if (!(
word.length === 0 ||
keyLower.includes(word) ||
descLower.includes(word) ||
catLower.includes(word) ||
actionLower.includes(word)
)) {
shouldContinue = true;
break;
}
}
if (shouldContinue)
continue;
if (bind.subcat) {
hasSubcats = true;

View File

@@ -40,6 +40,24 @@ Rectangle {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
Item {
height: 1
width: parent.width - headerText.width - settingsButton.width
}
DankActionButton {
id: settingsButton
anchors.verticalCenter: parent.verticalCenter
iconName: "settings"
buttonSize: 28
iconSize: 16
iconColor: Theme.surfaceVariantText
onClicked: {
PopoutService.closeControlCenter();
PopoutService.openSettingsWithTab("audio");
}
}
}
Row {
@@ -151,8 +169,11 @@ Rectangle {
Repeater {
model: ScriptModel {
values: {
const hidden = SessionData.hiddenInputDeviceNames ?? [];
const nodes = Pipewire.nodes.values.filter(node => {
return node.audio && !node.isSink && !node.isStream;
if (!node.audio || node.isSink || node.isStream)
return false;
return !hidden.includes(node.name);
});
const pinnedList = audioContent.getPinnedInputs();

View File

@@ -40,6 +40,24 @@ Rectangle {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
Item {
height: 1
width: parent.width - headerText.width - settingsButton.width
}
DankActionButton {
id: settingsButton
anchors.verticalCenter: parent.verticalCenter
iconName: "settings"
buttonSize: 28
iconSize: 16
iconColor: Theme.surfaceVariantText
onClicked: {
PopoutService.closeControlCenter();
PopoutService.openSettingsWithTab("audio");
}
}
}
Row {
@@ -161,8 +179,11 @@ Rectangle {
Repeater {
model: ScriptModel {
values: {
const hidden = SessionData.hiddenOutputDeviceNames ?? [];
const nodes = Pipewire.nodes.values.filter(node => {
return node.audio && node.isSink && !node.isStream;
if (!node.audio || !node.isSink || node.isStream)
return false;
return !hidden.includes(node.name);
});
const pinnedList = audioContent.getPinnedOutputs();

View File

@@ -811,7 +811,7 @@ Item {
} else {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 0, (effectiveBarConfig?.id ?? "default") + "-0");
PopoutManager.requestPopout(dankDashPopoutLoader.item, 0, (effectiveBarConfig?.id ?? "default") + "-" + section + "-0");
}
}
}
@@ -867,7 +867,7 @@ Item {
} else {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 1, (effectiveBarConfig?.id ?? "default") + "-1");
PopoutManager.requestPopout(dankDashPopoutLoader.item, 1, (effectiveBarConfig?.id ?? "default") + "-" + section + "-1");
}
}
}
@@ -926,7 +926,7 @@ Item {
} else {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 3, (effectiveBarConfig?.id ?? "default") + "-3");
PopoutManager.requestPopout(dankDashPopoutLoader.item, 3, (effectiveBarConfig?.id ?? "default") + "-" + section + "-3");
}
}
}

View File

@@ -80,7 +80,7 @@ PanelWindow {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 2, (barConfig?.id ?? "default") + "-2");
PopoutManager.requestPopout(dankDashPopoutLoader.item, 2, (barConfig?.id ?? "default") + "-" + section + "-2");
}
readonly property var dBarLayer: {

View File

@@ -99,13 +99,6 @@ BasePill {
width: implicitWidth
height: implicitHeight
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
StyledTextMetrics {
id: cpuBaseline
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)

View File

@@ -99,13 +99,6 @@ BasePill {
width: implicitWidth
height: implicitHeight
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
StyledTextMetrics {
id: tempBaseline
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)

View File

@@ -193,13 +193,6 @@ BasePill {
}
width: Math.max(diskBaseline.width, paintedWidth)
Behavior on width {
NumberAnimation {
duration: 120
easing.type: Easing.OutCubic
}
}
}
}
}

View File

@@ -167,13 +167,6 @@ BasePill {
width: implicitWidth
height: implicitHeight
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
StyledTextMetrics {
id: gpuTempBaseline
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)

View File

@@ -110,13 +110,6 @@ BasePill {
}
width: Math.max(rxBaseline.width, paintedWidth)
Behavior on width {
NumberAnimation {
duration: 120
easing.type: Easing.OutCubic
}
}
}
}
@@ -146,13 +139,6 @@ BasePill {
}
width: Math.max(txBaseline.width, paintedWidth)
Behavior on width {
NumberAnimation {
duration: 120
easing.type: Easing.OutCubic
}
}
}
}
}

View File

@@ -109,13 +109,6 @@ BasePill {
width: implicitWidth
height: implicitHeight
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
StyledTextMetrics {
id: ramBaseline
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)

View File

@@ -138,15 +138,13 @@ BasePill {
readonly property real iconCellSize: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.noBackground) + 6
readonly property string focusedAppId: {
const toplevels = CompositorService.sortedToplevels;
if (!toplevels)
if (!sortedToplevels || sortedToplevels.length === 0)
return "";
let result = "";
for (let i = 0; i < toplevels.length; i++) {
if (toplevels[i].activated)
result = toplevels[i].appId || "";
for (let i = 0; i < sortedToplevels.length; i++) {
if (sortedToplevels[i].activated)
return sortedToplevels[i].appId || "";
}
return result;
return "";
}
visible: windowCount > 0

View File

@@ -553,15 +553,7 @@ Variants {
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency)
border.color: Theme.outlineMedium
border.width: 1
radius: Theme.cornerRadius
}
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
color: Theme.withAlpha(Theme.surfaceContainer, backgroundTransparency)
radius: Theme.cornerRadius
}
}

View File

@@ -165,7 +165,7 @@ PanelWindow {
}
width: Math.min(400, Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
height: menuColumn.implicitHeight + Theme.spacingS * 2
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
@@ -388,18 +388,31 @@ PanelWindow {
radius: Theme.cornerRadius
color: pinArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
StyledText {
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: root.appData && root.appData.isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
spacing: Theme.spacingXS
DankIcon {
anchors.verticalCenter: parent.verticalCenter
name: root.appData && root.appData.isPinned ? "keep_off" : "push_pin"
size: 14
color: Theme.surfaceText
opacity: 0.7
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: root.appData && root.appData.isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
DankRipple {
@@ -448,18 +461,31 @@ PanelWindow {
radius: Theme.cornerRadius
color: nvidiaArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
StyledText {
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Launch on dGPU")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
spacing: Theme.spacingXS
DankIcon {
anchors.verticalCenter: parent.verticalCenter
name: "memory"
size: 14
color: Theme.surfaceText
opacity: 0.7
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Launch on dGPU")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
DankRipple {
@@ -490,23 +516,31 @@ PanelWindow {
radius: Theme.cornerRadius
color: closeArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
StyledText {
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
text: {
if (root.appData && root.appData.type === "grouped") {
return "Close All Windows";
}
return "Close Window";
spacing: Theme.spacingXS
DankIcon {
anchors.verticalCenter: parent.verticalCenter
name: "close"
size: 14
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
opacity: 0.7
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: root.appData && root.appData.type === "grouped" ? I18n.tr("Close All Windows") : I18n.tr("Close Window")
font.pixelSize: Theme.fontSizeSmall
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
font.pixelSize: Theme.fontSizeSmall
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
DankRipple {

View File

@@ -1065,7 +1065,7 @@ Item {
}
StyledText {
text: "Caps Lock is on"
text: I18n.tr("Caps Lock is on")
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
anchors.verticalCenter: parent.verticalCenter

View File

@@ -23,7 +23,7 @@ Rectangle {
spacing: 2
StyledText {
text: "↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text"
text: I18n.tr("↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
width: parent.width

View File

@@ -1061,7 +1061,7 @@ Singleton {
function getHyprlandOutputIdentifier(output, outputName) {
if (SettingsData.displayNameMode === "model" && output?.make && output?.model)
return "desc:" + output.make + " " + output.model;
return "desc:" + output.make + " " + output.model + " " + (output?.serial || "Unknown");
return outputName;
}

View File

@@ -813,7 +813,7 @@ Item {
}
Rectangle {
width: 80
width: resetContentRow.implicitWidth + Theme.spacingM * 2
height: 28
radius: Theme.cornerRadius
color: resetArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariant
@@ -821,6 +821,7 @@ Item {
border.width: 0
Row {
id: resetContentRow
anchors.centerIn: parent
spacing: Theme.spacingXS

View File

@@ -242,7 +242,7 @@ Variants {
Image {
id: nextWallpaper
anchors.fill: parent
visible: true
visible: source !== ""
opacity: 0
layer.enabled: false
asynchronous: true
@@ -512,14 +512,18 @@ Variants {
}
}
MultiEffect {
Loader {
anchors.fill: parent
source: effectLoader.active ? effectLoader.item : currentWallpaper
visible: CompositorService.isNiri && SettingsData.blurWallpaperOnOverview && NiriService.inOverview && currentWallpaper.source !== ""
blurEnabled: true
blur: 0.8
blurMax: 75
autoPaddingEnabled: false
active: CompositorService.isNiri && SettingsData.blurWallpaperOnOverview && NiriService.inOverview && currentWallpaper.source !== ""
sourceComponent: MultiEffect {
anchors.fill: parent
source: effectLoader.active ? effectLoader.item : currentWallpaper
blurEnabled: true
blur: 0.8
blurMax: 75
autoPaddingEnabled: false
}
}
}
}

View File

@@ -288,9 +288,9 @@ Singleton {
const cpu = data.cpu;
cpuSampleCount++;
cpuUsage = cpu.usage || 0;
cpuFrequency = cpu.frequency || 0;
cpuTemperature = cpu.temperature || 0;
cpuUsage = Math.round((cpu.usage || 0) * 10) / 10;
cpuFrequency = Math.round(cpu.frequency || 0);
cpuTemperature = Math.round(cpu.temperature || 0);
cpuCores = cpu.count || 1;
cpuModel = cpu.model || "";
perCoreCpuUsage = cpu.coreUsage || [];
@@ -308,11 +308,12 @@ Singleton {
const freeKB = mem.free || 0;
const usedKB = mem.used !== undefined ? mem.used : (totalKB - availableKB);
totalMemoryMB = totalKB / 1024;
availableMemoryMB = availableKB / 1024;
freeMemoryMB = freeKB / 1024;
usedMemoryMB = usedKB / 1024;
memoryUsage = mem.usedPercent !== undefined ? mem.usedPercent : (totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0);
totalMemoryMB = Math.round(totalKB / 1024);
availableMemoryMB = Math.round(availableKB / 1024);
freeMemoryMB = Math.round(freeKB / 1024);
usedMemoryMB = Math.round(usedKB / 1024);
const rawMemUsage = mem.usedPercent !== undefined ? mem.usedPercent : (totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0);
memoryUsage = Math.round(rawMemUsage * 10) / 10;
totalMemoryKB = totalKB;
usedMemoryKB = usedKB;

View File

@@ -55,7 +55,7 @@ Singleton {
function getOutputIdentifier(output, outputName) {
if (SettingsData.displayNameMode === "model" && output.make && output.model)
return "desc:" + output.make + " " + output.model;
return "desc:" + output.make + " " + output.model + " " + (output.serial || "Unknown");
return outputName;
}

View File

@@ -963,48 +963,34 @@ Singleton {
return enrichedToplevels;
}
function filterCurrentWorkspace(toplevels, screenName) {
let currentWorkspaceId = null;
for (var i = 0; i < allWorkspaces.length; i++) {
const ws = allWorkspaces[i];
if (ws.output === screenName && ws.is_active) {
currentWorkspaceId = ws.id;
break;
}
}
if (currentWorkspaceId === null)
return toplevels;
const workspaceWindows = windows.filter(niriWindow => niriWindow.workspace_id === currentWorkspaceId);
function _matchAndEnrichToplevels(toplevels, niriWindows) {
const usedToplevels = new Set();
const result = [];
for (const niriWindow of workspaceWindows) {
for (const niriWindow of niriWindows) {
let bestMatch = null;
let bestScore = -1;
for (const toplevel of toplevels) {
if (usedToplevels.has(toplevel))
continue;
if (toplevel.appId === niriWindow.app_id) {
let score = 1;
if (toplevel.appId !== niriWindow.app_id)
continue;
if (niriWindow.title && toplevel.title) {
if (toplevel.title === niriWindow.title) {
score = 3;
} else if (toplevel.title.includes(niriWindow.title) || niriWindow.title.includes(toplevel.title)) {
score = 2;
}
let score = 1;
if (niriWindow.title && toplevel.title) {
if (toplevel.title === niriWindow.title) {
score = 3;
} else if (toplevel.title.includes(niriWindow.title) || niriWindow.title.includes(toplevel.title)) {
score = 2;
}
}
if (score > bestScore) {
bestScore = score;
bestMatch = toplevel;
if (score === 3)
break;
}
if (score > bestScore) {
bestScore = score;
bestMatch = toplevel;
if (score === 3)
break;
}
}
@@ -1025,17 +1011,15 @@ Singleton {
return NiriService.focusWindow(niriWindow.id);
},
"close": function () {
if (bestMatch.close) {
if (bestMatch.close)
return bestMatch.close();
}
return false;
}
};
for (let prop in bestMatch) {
if (!(prop in enrichedToplevel)) {
if (!(prop in enrichedToplevel))
enrichedToplevel[prop] = bestMatch[prop];
}
}
result.push(enrichedToplevel);
@@ -1044,6 +1028,26 @@ Singleton {
return result;
}
function filterCurrentWorkspace(toplevels, screenName) {
let currentWorkspaceId = null;
for (var i = 0; i < allWorkspaces.length; i++) {
const ws = allWorkspaces[i];
if (ws.output === screenName && ws.is_active) {
currentWorkspaceId = ws.id;
break;
}
}
if (currentWorkspaceId === null)
return toplevels;
if (toplevels.length > 0 && toplevels[0].niriWorkspaceId !== undefined)
return toplevels.filter(t => t.niriWorkspaceId === currentWorkspaceId);
return _matchAndEnrichToplevels(toplevels, windows.filter(nw => nw.workspace_id === currentWorkspaceId));
}
function filterCurrentDisplay(toplevels, screenName) {
if (!toplevels || toplevels.length === 0 || !screenName)
return toplevels;
@@ -1058,71 +1062,10 @@ Singleton {
if (outputWorkspaceIds.size === 0)
return toplevels;
const displayWindows = windows.filter(niriWindow => outputWorkspaceIds.has(niriWindow.workspace_id));
const usedToplevels = new Set();
const result = [];
if (toplevels.length > 0 && toplevels[0].niriWorkspaceId !== undefined)
return toplevels.filter(t => outputWorkspaceIds.has(t.niriWorkspaceId));
for (const niriWindow of displayWindows) {
let bestMatch = null;
let bestScore = -1;
for (const toplevel of toplevels) {
if (usedToplevels.has(toplevel))
continue;
if (toplevel.appId === niriWindow.app_id) {
let score = 1;
if (niriWindow.title && toplevel.title) {
if (toplevel.title === niriWindow.title) {
score = 3;
} else if (toplevel.title.includes(niriWindow.title) || niriWindow.title.includes(toplevel.title)) {
score = 2;
}
}
if (score > bestScore) {
bestScore = score;
bestMatch = toplevel;
if (score === 3)
break;
}
}
}
if (!bestMatch)
continue;
usedToplevels.add(bestMatch);
const workspace = workspaces[niriWindow.workspace_id];
const isFocused = niriWindow.is_focused ?? (workspace && workspace.active_window_id === niriWindow.id) ?? false;
const enrichedToplevel = {
"appId": bestMatch.appId,
"title": bestMatch.title,
"activated": isFocused,
"niriWindowId": niriWindow.id,
"niriWorkspaceId": niriWindow.workspace_id,
"activate": function () {
return NiriService.focusWindow(niriWindow.id);
},
"close": function () {
if (bestMatch.close) {
return bestMatch.close();
}
return false;
}
};
for (let prop in bestMatch) {
if (!(prop in enrichedToplevel)) {
enrichedToplevel[prop] = bestMatch[prop];
}
}
result.push(enrichedToplevel);
}
return result;
return _matchAndEnrichToplevels(toplevels, windows.filter(nw => outputWorkspaceIds.has(nw.workspace_id)));
}
function generateNiriLayoutConfig() {

View File

@@ -16,6 +16,7 @@ Singleton {
property var registeredCards: ({})
property var settingsIndex: []
property bool indexLoaded: false
property var _translatedCache: []
readonly property var conditionMap: ({
"isNiri": () => CompositorService.isNiri,
@@ -38,9 +39,11 @@ Singleton {
try {
root.settingsIndex = JSON.parse(text());
root.indexLoaded = true;
root._rebuildTranslationCache();
} catch (e) {
console.warn("SettingsSearchService: Failed to parse index:", e);
root.settingsIndex = [];
root._translatedCache = [];
}
}
onLoadFailed: error => console.warn("SettingsSearchService: Failed to load index:", error)
@@ -131,6 +134,27 @@ Singleton {
};
}
function _rebuildTranslationCache() {
var cache = [];
for (var i = 0; i < settingsIndex.length; i++) {
var item = settingsIndex[i];
var t = translateItem(item);
cache.push({
section: t.section,
label: t.label,
tabIndex: t.tabIndex,
category: t.category,
keywords: t.keywords,
icon: t.icon,
description: t.description,
conditionKey: t.conditionKey,
labelLower: t.label.toLowerCase(),
categoryLower: t.category.toLowerCase()
});
}
_translatedCache = cache;
}
function search(text) {
query = text;
if (!text) {
@@ -138,18 +162,19 @@ Singleton {
return;
}
const queryLower = text.toLowerCase().trim();
const queryWords = queryLower.split(/\s+/).filter(w => w.length > 0);
const scored = [];
var queryLower = text.toLowerCase().trim();
var queryWords = queryLower.split(/\s+/).filter(w => w.length > 0);
var scored = [];
var cache = _translatedCache;
for (const item of settingsIndex) {
if (!checkCondition(item))
for (var i = 0; i < cache.length; i++) {
var entry = cache[i];
if (!checkCondition(entry))
continue;
const translated = translateItem(item);
const labelLower = translated.label.toLowerCase();
const categoryLower = translated.category.toLowerCase();
let score = 0;
var labelLower = entry.labelLower;
var categoryLower = entry.categoryLower;
var score = 0;
if (labelLower === queryLower) {
score = 10000;
@@ -162,24 +187,32 @@ Singleton {
}
if (score === 0) {
for (const keyword of item.keywords) {
if (keyword.startsWith(queryLower)) {
score = Math.max(score, 800);
var keywords = entry.keywords;
for (var k = 0; k < keywords.length; k++) {
if (keywords[k].startsWith(queryLower)) {
score = 800;
break;
}
if (keyword.includes(queryLower)) {
score = Math.max(score, 400);
if (keywords[k].includes(queryLower) && score < 400) {
score = 400;
}
}
}
if (score === 0 && queryWords.length > 1) {
let allMatch = true;
for (const word of queryWords) {
const inLabel = labelLower.includes(word);
const inKeywords = item.keywords.some(k => k.includes(word));
const inCategory = categoryLower.includes(word);
if (!inLabel && !inKeywords && !inCategory) {
var allMatch = true;
for (var w = 0; w < queryWords.length; w++) {
var word = queryWords[w];
if (labelLower.includes(word))
continue;
var inKeywords = false;
for (var k = 0; k < entry.keywords.length; k++) {
if (entry.keywords[k].includes(word)) {
inKeywords = true;
break;
}
}
if (!inKeywords && !categoryLower.includes(word)) {
allMatch = false;
break;
}
@@ -190,7 +223,7 @@ Singleton {
if (score > 0) {
scored.push({
item: translated,
item: entry,
score: score
});
}

View File

@@ -109,6 +109,13 @@ Item {
readonly property bool useBackgroundWindow: !CompositorService.isHyprland || CompositorService.useHyprlandFocusGrab
function updateSurfacePosition() {
if (useBackgroundWindow && shouldBeVisible) {
_surfaceMarginLeft = alignedX - shadowBuffer;
_surfaceW = alignedWidth + shadowBuffer * 2;
}
}
function open() {
if (!screen)
return;

View File

@@ -1514,7 +1514,7 @@
{
"term": "Bottom Section",
"context": "Bottom Section",
"reference": "Modules/Settings/WidgetsTab.qml:1005",
"reference": "Modules/Settings/WidgetsTab.qml:1006",
"comment": ""
},
{
@@ -1550,7 +1550,7 @@
{
"term": "Browse",
"context": "theme category option",
"reference": "Modals/DankLauncherV2/Controller.qml:144, Modals/DankLauncherV2/Controller.qml:1039, Modules/Settings/ThemeColorsTab.qml:272, Modules/Settings/PluginsTab.qml:209",
"reference": "Modals/DankLauncherV2/Controller.qml:144, Modals/DankLauncherV2/Controller.qml:1042, Modules/Settings/ThemeColorsTab.qml:272, Modules/Settings/PluginsTab.qml:209",
"comment": ""
},
{
@@ -1703,10 +1703,16 @@
"reference": "Modules/Settings/WidgetsTab.qml:197",
"comment": ""
},
{
"term": "Caps Lock is on",
"context": "Caps Lock is on",
"reference": "Modules/Lock/LockScreenContent.qml:1068",
"comment": ""
},
{
"term": "Center Section",
"context": "Center Section",
"reference": "Modules/Settings/WidgetsTab.qml:947",
"reference": "Modules/Settings/WidgetsTab.qml:948",
"comment": ""
},
{
@@ -2054,7 +2060,7 @@
{
"term": "Close All Windows",
"context": "Close All Windows",
"reference": "Modules/DankBar/Widgets/AppsDockContextMenu.qml:445",
"reference": "Modules/Dock/DockContextMenu.qml:537, Modules/DankBar/Widgets/AppsDockContextMenu.qml:445",
"comment": ""
},
{
@@ -2066,7 +2072,7 @@
{
"term": "Close Window",
"context": "Close Window",
"reference": "dms-plugins/DankHyprlandWindows/DankHyprlandWindows.qml:141, Modules/DankBar/Widgets/AppsDockContextMenu.qml:447",
"reference": "dms-plugins/DankHyprlandWindows/DankHyprlandWindows.qml:141, Modules/Dock/DockContextMenu.qml:537, Modules/DankBar/Widgets/AppsDockContextMenu.qml:447",
"comment": ""
},
{
@@ -2570,7 +2576,7 @@
{
"term": "Copy path",
"context": "Copy path",
"reference": "Modals/DankLauncherV2/Controller.qml:918",
"reference": "Modals/DankLauncherV2/Controller.qml:921",
"comment": ""
},
{
@@ -3530,7 +3536,7 @@
{
"term": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.",
"context": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.",
"reference": "Modules/Settings/WidgetsTab.qml:866",
"reference": "Modules/Settings/WidgetsTab.qml:867",
"comment": ""
},
{
@@ -4454,7 +4460,7 @@
{
"term": "Files",
"context": "Files",
"reference": "Modals/DankLauncherV2/Controller.qml:151, Modals/DankLauncherV2/Controller.qml:853, Modals/DankLauncherV2/LauncherContent.qml:317",
"reference": "Modals/DankLauncherV2/Controller.qml:151, Modals/DankLauncherV2/Controller.qml:856, Modals/DankLauncherV2/LauncherContent.qml:317",
"comment": ""
},
{
@@ -5768,7 +5774,7 @@
{
"term": "Launch",
"context": "Launch",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:154, Modals/DankLauncherV2/Controller.qml:906",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:154, Modals/DankLauncherV2/Controller.qml:909, Modals/DankLauncherV2/Controller.qml:1302",
"comment": ""
},
{
@@ -5780,7 +5786,7 @@
{
"term": "Launch on dGPU",
"context": "Launch on dGPU",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:146, Modals/DankLauncherV2/ActionPanel.qml:66, Modules/Dock/DockContextMenu.qml:457, Modules/DankBar/Widgets/AppsDockContextMenu.qml:401",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:146, Modals/DankLauncherV2/ActionPanel.qml:61, Modules/Dock/DockContextMenu.qml:482, Modules/DankBar/Widgets/AppsDockContextMenu.qml:401",
"comment": ""
},
{
@@ -5828,7 +5834,7 @@
{
"term": "Left Section",
"context": "Left Section",
"reference": "Modules/Settings/WidgetsTab.qml:889",
"reference": "Modules/Settings/WidgetsTab.qml:890",
"comment": ""
},
{
@@ -6440,7 +6446,7 @@
{
"term": "Middle Section",
"context": "Middle Section",
"reference": "Modules/Settings/WidgetsTab.qml:947",
"reference": "Modules/Settings/WidgetsTab.qml:948",
"comment": ""
},
{
@@ -7244,7 +7250,7 @@
{
"term": "No trigger",
"context": "No trigger",
"reference": "Modals/DankLauncherV2/Controller.qml:1041, Modules/Settings/LauncherTab.qml:742",
"reference": "Modals/DankLauncherV2/Controller.qml:1044, Modules/Settings/LauncherTab.qml:742",
"comment": ""
},
{
@@ -7562,7 +7568,7 @@
{
"term": "Open",
"context": "Open",
"reference": "Modals/DankLauncherV2/Controller.qml:910, Modals/DankLauncherV2/Controller.qml:914, Modals/DankLauncherV2/Controller.qml:918, Modules/Notepad/NotepadTextEditor.qml:779, Modules/Settings/NetworkTab.qml:1199, Modules/Settings/NetworkTab.qml:1437, Modules/ControlCenter/Details/NetworkDetail.qml:609",
"reference": "Modals/DankLauncherV2/Controller.qml:913, Modals/DankLauncherV2/Controller.qml:917, Modals/DankLauncherV2/Controller.qml:921, Modules/Notepad/NotepadTextEditor.qml:779, Modules/Settings/NetworkTab.qml:1199, Modules/Settings/NetworkTab.qml:1437, Modules/ControlCenter/Details/NetworkDetail.qml:609",
"comment": ""
},
{
@@ -7592,7 +7598,7 @@
{
"term": "Open folder",
"context": "Open folder",
"reference": "Modals/DankLauncherV2/Controller.qml:918",
"reference": "Modals/DankLauncherV2/Controller.qml:921",
"comment": ""
},
{
@@ -8000,7 +8006,7 @@
{
"term": "Pin to Dock",
"context": "Pin to Dock",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:103, Modules/Dock/DockContextMenu.qml:397, Modules/DankBar/Widgets/AppsDockContextMenu.qml:341",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:103, Modules/Dock/DockContextMenu.qml:409, Modules/DankBar/Widgets/AppsDockContextMenu.qml:341",
"comment": ""
},
{
@@ -8288,7 +8294,7 @@
{
"term": "Precip",
"context": "Precip",
"reference": "dms-plugins/DankDesktopWeather/DankDesktopWeather.qml:437",
"reference": "dms-plugins/DankDesktopWeather/DankDesktopWeather.qml:441",
"comment": ""
},
{
@@ -8336,7 +8342,7 @@
{
"term": "Pressure",
"context": "Pressure",
"reference": "dms-plugins/DankDesktopWeather/DankDesktopWeather.qml:449, Modules/DankDash/WeatherTab.qml:94, Modules/DankDash/WeatherForecastCard.qml:90, Modules/Settings/TimeWeatherTab.qml:980",
"reference": "dms-plugins/DankDesktopWeather/DankDesktopWeather.qml:453, Modules/DankDash/WeatherTab.qml:94, Modules/DankDash/WeatherForecastCard.qml:90, Modules/Settings/TimeWeatherTab.qml:980",
"comment": ""
},
{
@@ -8774,7 +8780,7 @@
{
"term": "Reset",
"context": "Reset",
"reference": "Modals/DankLauncherV2/LauncherContent.qml:815, Modules/Settings/WidgetsTab.qml:835, Modules/ControlCenter/Components/EditControls.qml:232",
"reference": "Modals/DankLauncherV2/LauncherContent.qml:815, Modules/Settings/WidgetsTab.qml:836, Modules/ControlCenter/Components/EditControls.qml:232",
"comment": ""
},
{
@@ -8870,7 +8876,7 @@
{
"term": "Right Section",
"context": "Right Section",
"reference": "Modules/Settings/WidgetsTab.qml:1005",
"reference": "Modules/Settings/WidgetsTab.qml:1006",
"comment": ""
},
{
@@ -9290,7 +9296,7 @@
{
"term": "Select",
"context": "Select",
"reference": "Modals/DankLauncherV2/Controller.qml:1174",
"reference": "Modals/DankLauncherV2/Controller.qml:1177",
"comment": ""
},
{
@@ -10994,7 +11000,7 @@
{
"term": "Top Section",
"context": "Top Section",
"reference": "Modules/Settings/WidgetsTab.qml:889",
"reference": "Modules/Settings/WidgetsTab.qml:890",
"comment": ""
},
{
@@ -11048,7 +11054,7 @@
{
"term": "Trigger: %1",
"context": "Trigger: %1",
"reference": "Modals/DankLauncherV2/Controller.qml:1040, Modules/Settings/LauncherTab.qml:742",
"reference": "Modals/DankLauncherV2/Controller.qml:1043, Modules/Settings/LauncherTab.qml:742",
"comment": ""
},
{
@@ -11258,7 +11264,7 @@
{
"term": "Unpin from Dock",
"context": "Unpin from Dock",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:103, Modules/Dock/DockContextMenu.qml:397, Modules/DankBar/Widgets/AppsDockContextMenu.qml:341",
"reference": "Modals/DankLauncherV2/LauncherContextMenu.qml:103, Modules/Dock/DockContextMenu.qml:409, Modules/DankBar/Widgets/AppsDockContextMenu.qml:341",
"comment": ""
},
{
@@ -12455,6 +12461,12 @@
"reference": "Modules/Settings/TimeWeatherTab.qml:326",
"comment": ""
},
{
"term": "↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text",
"context": "↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text",
"reference": "Modules/Notifications/Center/NotificationKeyboardHints.qml:26",
"comment": ""
},
{
"term": "↑/↓: Navigate • Enter: Paste • Del: Delete • F10: Help",
"context": "Keyboard hints when enter-to-paste is enabled",

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Indicador de Bloq Mayús"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Sección central"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "yyyy - Año (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -105,10 +105,10 @@
"2 minutes": "۲ دقیقه"
},
"2 seconds": {
"2 seconds": ""
"2 seconds": "۲ ثانیه"
},
"20 minutes": {
"20 minutes": ""
"20 minutes": "۲۰ دقیقه"
},
"24-Hour Format": {
"24-Hour Format": "قالب ۲۴ ساعته"
@@ -117,7 +117,7 @@
"24-hour format": "قالب ۲۴ ساعته"
},
"250 ms": {
"250 ms": ""
"250 ms": "۲۵۰ ms"
},
"270°": {
"270°": "۲۷۰°"
@@ -126,7 +126,7 @@
"3 days": "۳ روز"
},
"3 minutes": {
"3 minutes": ""
"3 minutes": "۳ دقیقه"
},
"3 seconds": {
"3 seconds": "۳ ثانیه"
@@ -141,7 +141,7 @@
"3rd party": "شخص ثالث"
},
"4 seconds": {
"4 seconds": ""
"4 seconds": "۴ ثانیه"
},
"5 minutes": {
"5 minutes": "۵ دقیقه"
@@ -150,13 +150,13 @@
"5 seconds": "۵ ثانیه"
},
"500 ms": {
"500 ms": ""
"500 ms": "۵۰۰ ms"
},
"7 days": {
"7 days": "۷ روز"
},
"750 ms": {
"750 ms": ""
"750 ms": "۷۵۰ ms"
},
"8 seconds": {
"8 seconds": "۸ ثانیه"
@@ -171,7 +171,7 @@
"A file with this name already exists. Do you want to overwrite it?": "فایلی با این نام از قبل وجود دارد. آیا می‌خواهید آن را بازنویسی کنید؟"
},
"AC Power": {
"AC Power": ""
"AC Power": "برق AC"
},
"API": {
"API": "API"
@@ -381,7 +381,7 @@
"Apps with custom display name, icon, or launch options. Right-click an app and select 'Edit App' to customize.": "برنامه‌ها با نام نمایشی، آیکون و گزینه‌های اجرای سفارشی. روی یک برنامه راست‌کلیک کرده و «ویرایش برنامه» را برای سفارشی‌سازی انتخاب کنید."
},
"Apps with notification popups muted. Unmute or delete to remove.": {
"Apps with notification popups muted. Unmute or delete to remove.": ""
"Apps with notification popups muted. Unmute or delete to remove.": "برنامه‌هایی که پاپ‌آپ اعلان آن‌ها بی‌صدا شده است. برای حذف، بی‌صدا را بردارید یا برنامه را حذف کنید."
},
"Arrange displays and configure resolution, refresh rate, and VRR": {
"Arrange displays and configure resolution, refresh rate, and VRR": "چیدمان نمایشگرها و پیکربندی وضوح، نرخ تازه‌سازی و VRR"
@@ -524,7 +524,7 @@
"Automatically cycle through wallpapers in the same folder": "تصاویر پس‌زمینه را در همان پوشه به صورت خودکار تغییر بده"
},
"Automatically delete entries older than this": {
"Automatically delete entries older than this": "ورودی‌های قدیمی‌تر از این را به صورت خودکار پاک کن"
"Automatically delete entries older than this": "مدخل‌های قدیمی‌تر از این را به صورت خودکار پاک کن"
},
"Automatically detect location based on IP address": {
"Automatically detect location based on IP address": "تشخیص خودکار موقعیت مکانی بر اساس آدرس IP"
@@ -587,7 +587,7 @@
"Bar Transparency": "شفافیت نوار"
},
"Base duration for animations (drag to use Custom)": {
"Base duration for animations (drag to use Custom)": ""
"Base duration for animations (drag to use Custom)": "مدت زمان پایه برای انیمیشن‌ها (برای استفاده سفارشی بکشید)"
},
"Battery": {
"Battery": "باتری"
@@ -617,10 +617,10 @@
"Bit Depth": "عمق بیت"
},
"Block Out": {
"Block Out": ""
"Block Out": "مسدود کردن خروج"
},
"Block Out From": {
"Block Out From": ""
"Block Out From": "مسدود کردن خروج از"
},
"Block notifications": {
"Block notifications": "مسدود‌کردن اعلان‌ها"
@@ -665,7 +665,7 @@
"Border Thickness": "ضخامت حاشیه"
},
"Border with BG": {
"Border with BG": ""
"Border with BG": "حاشیه با پس‌زمینه"
},
"Bottom": {
"Bottom": "پایین"
@@ -737,7 +737,7 @@
"CUPS not available": "CUPS در دسترس نیست"
},
"Calc": {
"Calc": ""
"Calc": "ماشین حساب"
},
"Calculator": {
"Calculator": "ماشین حساب"
@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "نشانگر Caps Lock"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "بخش مرکزی"
},
@@ -836,7 +839,7 @@
"Choose which monitor shows the lock screen interface. Other monitors will display a solid color for OLED burn-in protection.": "انتخاب کنید که کدام مانیتور رابط صفحه قفل را نشان دهد. مانیتورهای دیگر برای محافظت در برابر سوختگی OLED، رنگ ثابتی را نمایش می‌دهند."
},
"Chroma Style": {
"Chroma Style": ""
"Chroma Style": "استایل رنگی"
},
"Cipher": {
"Cipher": "رمزگذار"
@@ -860,7 +863,7 @@
"Clear History?": "تاریخچه پاک شود؟"
},
"Clear Sky": {
"Clear Sky": ""
"Clear Sky": "آسمان پاک"
},
"Clear all history when server starts": {
"Clear all history when server starts": "هنگام راه‌اندازی سرور تمام تاریخچه را پاک کن"
@@ -917,7 +920,7 @@
"Clipboard Manager": "مدیریت کلیپ‌بورد"
},
"Clipboard behavior setting description": {
"Press Enter to paste, Shift+Enter to copy": ""
"Press Enter to paste, Shift+Enter to copy": "برای الصاق Enter، برای کپی Shift+Enter را فشار دهید"
},
"Clipboard service not available": {
"Clipboard service not available": "سرویس کلیپ‌بورد در دسترس نیست"
@@ -977,16 +980,16 @@
"Color temperature for night mode": "دمای رنگ برای حالت شب"
},
"Color theme for syntax highlighting.": {
"Color theme for syntax highlighting.": ""
"Color theme for syntax highlighting.": "تم رنگی برای برجسته‌سازی کد."
},
"Color theme for syntax highlighting. %1 themes available.": {
"Color theme for syntax highlighting. %1 themes available.": ""
"Color theme for syntax highlighting. %1 themes available.": "تم رنگی برای برجسته‌سازی کد. %1 تم دردسترس است."
},
"Colorful mix of bright contrasting accents.": {
"Colorful mix of bright contrasting accents.": "ترکیب رنگارنگ از رنگ‌های تأکیدی متضاد."
},
"Colorize Active": {
"Colorize Active": ""
"Colorize Active": "رنگ‌آمیزی حالت فعال"
},
"Column": {
"Column": "ستون"
@@ -1049,7 +1052,7 @@
"Configure icons for named workspaces. Icons take priority over numbers when both are enabled.": "آیکون‌ها را برای محیط‌کارهای نام‌دار تنظیم کنید. آیکون‌ها بر شماره‌ها هنگامی که هر دو فعال باشند اولویت دارند."
},
"Configure match criteria and actions": {
"Configure match criteria and actions": "پیکربندی معیارهای انطباق و اقدامات"
"Configure match criteria and actions": "پیکربندی انطباق معیار و اقدامات"
},
"Configure which displays show \"%1": {
"Configure which displays show \"%1\"": "تنظیم کنید که کدام نمایشگر‌ها «%1» را نشان دهند"
@@ -1109,7 +1112,7 @@
"Control Center Tile Color": "رنگ کاشی مرکز کنترل"
},
"Control animation duration for notification popups and history": {
"Control animation duration for notification popups and history": ""
"Control animation duration for notification popups and history": "مدت زمان انیمیشن را برای پاپ‌آپ اعلان‌ها و تاریخچه مشخص کنید"
},
"Control currently playing media": {
"Control currently playing media": "کنترل رسانه درحال پخش"
@@ -1202,7 +1205,7 @@
"Create rules to mute, ignore, hide from history, or override notification priority.": "برای بی‌صدا کردن، نادیده گرفتن، پنهان‌سازی از تاریخچه و یا تغییر اولویت اعلان قاعده ایجاد کنید."
},
"Create rules to mute, ignore, hide from history, or override notification priority. Default only overrides priority; notifications still show normally.": {
"Create rules to mute, ignore, hide from history, or override notification priority. Default only overrides priority; notifications still show normally.": ""
"Create rules to mute, ignore, hide from history, or override notification priority. Default only overrides priority; notifications still show normally.": "برای بی‌صدا کردن، نادیده گرفتن، مخفی‌سازی از تاریخچه، یا تغییر اولویت اعلان‌ها قواعدی ایجاد کنید. در حالت پیش‌فرض، تنها اولویت تغییر می‌کند؛ اعلان‌ها همچنان به‌صورت عادی نمایش داده می‌شوند."
},
"Creating...": {
"Creating...": "درحال ایجاد..."
@@ -1238,7 +1241,7 @@
"Cursor Config Not Configured": "پیکربندی اشاره‌گر موس تنظیم نشده"
},
"Cursor Include Missing": {
"Cursor Include Missing": ""
"Cursor Include Missing": "دستور include اشاره‌گر موس یافت نشد"
},
"Cursor Size": {
"Cursor Size": "اندازه اشاره‌گر موس"
@@ -1319,7 +1322,7 @@
"DWL service not available": "سرویس DWL در دسترس نیست"
},
"Daily": {
"Daily": ""
"Daily": "روزانه"
},
"Daily Forecast": {
"Daily Forecast": "پیش‌بینی روزانه"
@@ -1415,7 +1418,7 @@
"Description": "توضیحات"
},
"Desktop": {
"Desktop": ""
"Desktop": "دسکتاپ"
},
"Desktop Clock": {
"Desktop Clock": "ساعت دسکتاپ"
@@ -1589,7 +1592,7 @@
"Docs": "مستندات"
},
"Documents": {
"Documents": ""
"Documents": "اسناد"
},
"Domain (optional)": {
"Domain (optional)": "دامنه (اختیاری)"
@@ -1604,7 +1607,7 @@
"Door Open": "درب باز"
},
"Downloads": {
"Downloads": ""
"Downloads": "بارگیری‌ها"
},
"Drag to Reorder": {
"Drag to Reorder": "نگه‌داشتن برای بازآرایی"
@@ -1619,7 +1622,7 @@
"Driver": "درایور"
},
"Drizzle": {
"Drizzle": ""
"Drizzle": "باران‌ریزه"
},
"Duplicate": {
"Duplicate": "تکثیر"
@@ -1628,7 +1631,7 @@
"Duplicate Wallpaper with Blur": "تصویر پس‌زمینه تکراری با تاری"
},
"Duration": {
"Duration": ""
"Duration": "مدت زمان"
},
"Dusk (Astronomical Twilight)": {
"Dusk (Astronomical Twilight)": "غروب (گرگ و میش نجومی)"
@@ -1781,16 +1784,16 @@
"Enter this passkey on ": "ورود این کلید عبور در "
},
"Enter to Paste": {
"Enter to Paste": ""
"Enter to Paste": "Enter برای الصاق"
},
"Enterprise": {
"Enterprise": "شرکت"
},
"Entry pinned": {
"Entry pinned": "ورودی سنجاق شد"
"Entry pinned": "مدخل سنجاق شد"
},
"Entry unpinned": {
"Entry unpinned": "سنجاق ورودی برداشته شد"
"Entry unpinned": "سنجاق مدخل برداشته شد"
},
"Environment Variables": {
"Environment Variables": "متغیر‌های محیطی"
@@ -1811,7 +1814,7 @@
"Exponential": "نمایی"
},
"Extra Arguments": {
"Extra Arguments": ""
"Extra Arguments": "آرگومان‌های اضافی"
},
"F1/I: Toggle • F10: Help": {
"F1/I: Toggle • F10: Help": "F1/I: تغییر حالت • F10: راهنما"
@@ -1853,7 +1856,7 @@
"Failed to connect to %1": "اتصال به %1 ناموفق بود"
},
"Failed to copy entry": {
"Failed to copy entry": "کپی ورودی ناموفق بود"
"Failed to copy entry": "کپی مدخل ناموفق بود"
},
"Failed to create printer": {
"Failed to create printer": "ایجاد چاپگر ناموفق بود"
@@ -1925,7 +1928,7 @@
"Failed to pause printer": "توقف چاپگر ناموفق بود"
},
"Failed to pin entry": {
"Failed to pin entry": "سنجاق کردن ورودی ناموفق بود"
"Failed to pin entry": "سنجاق کردن مدخل ناموفق بود"
},
"Failed to print test page": {
"Failed to print test page": "چاپ صفحه تست ناموفق بود"
@@ -1982,7 +1985,7 @@
"Failed to start connection to %1": "شروع اتصال به %1 ناموفق بود"
},
"Failed to unpin entry": {
"Failed to unpin entry": "برداشتن سنجاق ورودی ناموفق بود"
"Failed to unpin entry": "برداشتن سنجاق مدخل ناموفق بود"
},
"Failed to update VPN": {
"Failed to update VPN": "بروزرسانی VPN ناموفق بود"
@@ -2084,7 +2087,7 @@
"Focused Window": "پنجره فوکوس‌شده"
},
"Fog": {
"Fog": ""
"Fog": "مه"
},
"Follow Monitor Focus": {
"Follow Monitor Focus": "فوکوس مانیتور را دنبال کن"
@@ -2144,13 +2147,13 @@
"Forgot network %1": "فراموشی شبکه %1"
},
"Format Legend": {
"Format Legend": "قالب فهرست علائم"
"Format Legend": "راهنمای قالب‌بندی"
},
"Free VRAM/memory when the launcher is closed. May cause a slight delay when reopening.": {
"Free VRAM/memory when the launcher is closed. May cause a slight delay when reopening.": ""
"Free VRAM/memory when the launcher is closed. May cause a slight delay when reopening.": "هنگامی که لانچر بسته شد VRAM/حافظه را آزاد کن. ممکن است باعث اندکی تأخیر هنگام باز کردن مجدد شود."
},
"Freezing Drizzle": {
"Freezing Drizzle": ""
"Freezing Drizzle": "باران‌ریزه یخ‌زن"
},
"Frequency": {
"Frequency": "فرکانس"
@@ -2258,13 +2261,13 @@
"Health": "سلامت"
},
"Heavy Rain": {
"Heavy Rain": ""
"Heavy Rain": "باران سنگین"
},
"Heavy Snow": {
"Heavy Snow": ""
"Heavy Snow": "برف سنگین"
},
"Heavy Snow Showers": {
"Heavy Snow Showers": ""
"Heavy Snow Showers": "برف سنگین پراکنده"
},
"Height": {
"Height": "ارتفاع"
@@ -2285,7 +2288,7 @@
"Hidden": "پنهان"
},
"Hidden (%1)": {
"Hidden (%1)": ""
"Hidden (%1)": "پنهان (%1)"
},
"Hidden Apps": {
"Hidden Apps": "برنامه‌های پنهان"
@@ -2327,13 +2330,13 @@
"Hide cursor when using touch input": "اشاره‌گر موس را هنگام استفاده از ورودی لمسی پنهان کن"
},
"Hide device": {
"Hide device": ""
"Hide device": "پنهان کردن دستگاه"
},
"Hide notification content until expanded": {
"Hide notification content until expanded": ""
"Hide notification content until expanded": "پنهان کردن محتوای اعلان را تا هنگام گسترش"
},
"Hide notification content until expanded; popups show collapsed by default": {
"Hide notification content until expanded; popups show collapsed by default": ""
"Hide notification content until expanded; popups show collapsed by default": "محتوای اعلان را تا هنگام گسترش پنهان کن؛ پاپ‌آپ‌ها به طور پیش‌فرض گسترش‌یافته نمایش داده می‌شوند"
},
"Hide on Touch": {
"Hide on Touch": "هنگام لمس پنهان کن"
@@ -2348,7 +2351,7 @@
"History Settings": "تنظیمات تاریخچه"
},
"History cleared. %1 pinned entries kept.": {
"History cleared. %1 pinned entries kept.": "تاریخچه پاک شد. %1 ورودی سنجاق شده نگه داشته شد."
"History cleared. %1 pinned entries kept.": "تاریخچه پاک شد. %1 مدخل سنجاق شده نگه داشته شد."
},
"Hold Duration": {
"Hold Duration": "مدت زمان نگه‌داشتن"
@@ -2366,7 +2369,7 @@
"Hold to confirm (%1s)": "برای تأیید نگه‌دارید (%1s)"
},
"Home": {
"Home": ""
"Home": "خانه"
},
"Hot Corners": {
"Hot Corners": "گوشه‌های فعال"
@@ -2728,13 +2731,13 @@
"Key": "کلید"
},
"Keybind Sources": {
"Keybind Sources": ""
"Keybind Sources": "منابع نگاشت‌کلیدها"
},
"Keybinds Search Settings": {
"Keybinds Search Settings": "تنظیمات نگاشت‌کلیدهای جستجو"
},
"Keybinds shown alongside regular search results": {
"Keybinds shown alongside regular search results": ""
"Keybinds shown alongside regular search results": "نگاشت‌کلیدها همراه نتایج عادی جستجو نمایش داده می‌شوند"
},
"Keyboard Layout Name": {
"Keyboard Layout Name": "نام چیدمان صفحه‌کلید"
@@ -2743,8 +2746,8 @@
"Keyboard Shortcuts": "میانبر‌های صفحه‌کلید"
},
"Keyboard hints when enter-to-paste is enabled": {
"Shift+Enter: Copy • Shift+Del: Clear All • Esc: Close": "",
"↑/↓: Navigate • Enter: Paste • Del: Delete • F10: Help": ""
"Shift+Enter: Copy • Shift+Del: Clear All • Esc: Close": "Shift+Enter: کپی • Shift+Del: پاک‌کردن همه • Esc: بستن",
"↑/↓: Navigate • Enter: Paste • Del: Delete • F10: Help": "↑/↓: پیمایش • Enter: الصاق • Del: حذف • F10: راهنما"
},
"Keys": {
"Keys": "کلیدها"
@@ -2816,13 +2819,13 @@
"Light Mode": "حالت روشن"
},
"Light Rain": {
"Light Rain": ""
"Light Rain": "باران سبک"
},
"Light Snow": {
"Light Snow": ""
"Light Snow": "برف سبک"
},
"Light Snow Showers": {
"Light Snow Showers": ""
"Light Snow Showers": "برف پراکنده"
},
"Linear": {
"Linear": "خطی"
@@ -2960,10 +2963,10 @@
"Marker Waste Full": "ضایعات مارکر پر است"
},
"Match Criteria": {
"Match Criteria": ""
"Match Criteria": "انطباق معیار"
},
"Matches profile: %1": {
"Matches profile: %1": ""
"Matches profile: %1": "منطبق با پروفایل: %1"
},
"Material Colors": {
"Material Colors": "رنگ‌های Material"
@@ -3005,31 +3008,31 @@
"Max to Edges": "بیشینه تا لبه‌ها"
},
"Maximize": {
"Maximize": ""
"Maximize": "بزرگ‌کردن پنجره"
},
"Maximize Detection": {
"Maximize Detection": "تشخیص بزرگ‌شدن پنجره"
},
"Maximum Entry Size": {
"Maximum Entry Size": "حداکثر اندازه ورودی"
"Maximum Entry Size": "حداکثر اندازه مدخل"
},
"Maximum History": {
"Maximum History": "حداکثر تاریخچه"
},
"Maximum Pinned Entries": {
"Maximum Pinned Entries": "بیشینه ورودی‌های سنجاق شده"
"Maximum Pinned Entries": "بیشینه مدخل‌های سنجاق شده"
},
"Maximum number of clipboard entries to keep": {
"Maximum number of clipboard entries to keep": "بیشینه تعداد ورودی‌های کلیپ‌بورد برای نگه‌داری"
"Maximum number of clipboard entries to keep": "بیشینه تعداد مدخل‌های کلیپ‌بورد برای نگه‌داری"
},
"Maximum number of entries that can be saved": {
"Maximum number of entries that can be saved": "بیشینه تعداد ورودی‌هایی که می‌توانند ذخیره شوند"
"Maximum number of entries that can be saved": "بیشینه تعداد مدخل‌هایی که می‌توانند ذخیره شوند"
},
"Maximum pinned entries reached": {
"Maximum pinned entries reached": "به بیشینه ورودی‌های سنجاق شده رسیدید"
"Maximum pinned entries reached": "به بیشینه مدخل‌های سنجاق شده رسیدید"
},
"Maximum size per clipboard entry": {
"Maximum size per clipboard entry": "بیشینه اندازه برای هر ورودی کلیپ‌بورد"
"Maximum size per clipboard entry": "بیشینه اندازه برای هر مدخل کلیپ‌بورد"
},
"Media": {
"Media": "رسانه"
@@ -3050,7 +3053,7 @@
"Media Needed": "مدیا مورد نیاز است"
},
"Media Playback": {
"Media Playback": ""
"Media Playback": "پخش رسانه"
},
"Media Player": {
"Media Player": "پخش‌کننده رسانه"
@@ -3170,13 +3173,13 @@
"Moving to Paused": "انتقال به حالت متوقف شده"
},
"Music": {
"Music": ""
"Music": "موسیقی"
},
"Mute popups for %1": {
"Mute popups for %1": ""
"Mute popups for %1": "بی‌صدا کردن پاپ‌آپ‌ها را برای %1"
},
"Muted Apps": {
"Muted Apps": ""
"Muted Apps": "برنامه‌های بی‌صدا"
},
"Muted palette with subdued, calming tones.": {
"Muted palette with subdued, calming tones.": "پالت رنگی ساکت با تن‌های ملایم و آرامش‌بخش."
@@ -3329,7 +3332,7 @@
"No apps have been launched yet.": "هیچ برنامه‌ای هنوز اجرا نشده است."
},
"No apps muted. Right-click a notification and choose \"Mute popups\" to add one here.": {
"No apps muted. Right-click a notification and choose \"Mute popups\" to add one here.": ""
"No apps muted. Right-click a notification and choose \"Mute popups\" to add one here.": "هیچ برنامه‌ای بی‌صدا نشده است. برای افزودن یکی به اینجا روی اعلان راست‌کلیک کرده و «بی‌صدا کردن پاپ‌آپ‌ها» را انتخاب کنید."
},
"No battery": {
"No battery": "بدون باتری"
@@ -3341,7 +3344,7 @@
"No changes": "بدون تغییرات"
},
"No clipboard entries found": {
"No clipboard entries found": "هیچ ورودی کلیپ‌بوردی پیدا نشد"
"No clipboard entries found": "هیچ مدخل کلیپ‌بوردی پیدا نشد"
},
"No devices found": {
"No devices found": "دستگاهی یافت نشد"
@@ -3374,7 +3377,7 @@
"No launcher plugins installed.": "هیچ افزونه‌ لانچری نصب نشده است."
},
"No match criteria": {
"No match criteria": ""
"No match criteria": "هیچ انطباق معیاری یافت نشد"
},
"No matches": {
"No matches": "موردی پیدا نشد"
@@ -3401,13 +3404,13 @@
"No profiles": "هیچ پروفایلی یافت نشد"
},
"No recent clipboard entries found": {
"No recent clipboard entries found": "هیچ ورودی کلیپ‌بورد اخیری یافت نشد"
"No recent clipboard entries found": "هیچ مدخل کلیپ‌بورد اخیری یافت نشد"
},
"No results found": {
"No results found": "هیچ نتیجه‌ای یافت نشد"
},
"No saved clipboard entries": {
"No saved clipboard entries": "هیچ ورودی کلیپ‌بوردی ذخیره نشده است"
"No saved clipboard entries": "هیچ مدخل کلیپ‌بوردی ذخیره نشده است"
},
"No trigger": {
"No trigger": "بدون راه‌انداز"
@@ -3536,7 +3539,7 @@
"Opacity": "شفافیت"
},
"Opaque": {
"Opaque": ""
"Opaque": "کدر"
},
"Open": {
"Open": "باز‌کردن"
@@ -3590,7 +3593,7 @@
"Outputs Include Missing": "Include خروجی‌ها یافت نشد"
},
"Overcast": {
"Overcast": ""
"Overcast": "کاملاْ ابری"
},
"Overflow": {
"Overflow": "سرریزی"
@@ -3629,7 +3632,7 @@
"PIN": "PIN"
},
"Pad Hours": {
"Pad Hours": ""
"Pad Hours": "حاشیه‌گذاری ساعات"
},
"Padding": {
"Padding": "فاصله درونی"
@@ -3650,7 +3653,7 @@
"Pairing...": "درحال جفت شدن..."
},
"Partly Cloudy": {
"Partly Cloudy": ""
"Partly Cloudy": "نیمه ابری"
},
"Passkey:": {
"Passkey:": "کلید عبور:"
@@ -3714,7 +3717,7 @@
"Failed to send ping": "ارسال پینگ ناموفق بود",
"Failed to share": "اشتراک‌گذاری ناموفق بود",
"Pairing failed": "جفت‌سازی ناموفق بود",
"Unpair failed": ""
"Unpair failed": "جدا‌سازی ناموفق بود"
},
"Phone Connect file send": {
"Sending": "درحال ارسال"
@@ -3760,7 +3763,7 @@
"Unavailable": "دردسترس نیست"
},
"Pictures": {
"Pictures": ""
"Pictures": "تصاویر"
},
"Pin": {
"Pin": "سنجاق"
@@ -3832,7 +3835,7 @@
"Popup Position": "مکان پاپ‌آپ"
},
"Popup Shadow": {
"Popup Shadow": ""
"Popup Shadow": "سایه پاپ‌آپ"
},
"Popup Transparency": {
"Popup Transparency": "شفافیت پاپ‌آپ"
@@ -3943,7 +3946,7 @@
"Privacy Indicator": "نشانگر حریم خصوصی"
},
"Privacy Mode": {
"Privacy Mode": ""
"Privacy Mode": "حالت حریم خصوصی"
},
"Private Key Password": {
"Private Key Password": "کلید خصوصی گذرواژه"
@@ -3988,7 +3991,7 @@
"Protocol": "پروتکل"
},
"Quick Access": {
"Quick Access": ""
"Quick Access": "دسترسی سریع"
},
"Quick access to application launcher": {
"Quick access to application launcher": "دسترسی سریع به لانچر برنامه"
@@ -4009,7 +4012,7 @@
"Radius": "شعاع"
},
"Rain": {
"Rain": ""
"Rain": "باران"
},
"Rain Chance": {
"Rain Chance": "احتمال بارش"
@@ -4279,10 +4282,10 @@
"Search Options": "گزینه‌های جستجو"
},
"Search by key combo, description, or action name.\n\nDefault action copies the keybind to clipboard.\nRight-click or press Right Arrow to pin frequently used keybinds - they'll appear at the top when not searching.": {
"Search by key combo, description, or action name.\n\nDefault action copies the keybind to clipboard.\nRight-click or press Right Arrow to pin frequently used keybinds - they'll appear at the top when not searching.": ""
"Search by key combo, description, or action name.\n\nDefault action copies the keybind to clipboard.\nRight-click or press Right Arrow to pin frequently used keybinds - they'll appear at the top when not searching.": "با ترکیب کلید‌ها، توضیحات یا نام اقدام‌ جستجو کنید.\n\nاقدام پیش‌فرض نگاشت‌کلید را در کلیپ‌بورد کپی می‌کند.\nبرای سنجاق‌ کردن نگاشت‌کلید‌های پر استفاده راست‌کلیک کنید یا پیکان راست را فشار دهید - آن‌ها هنگام جستجو نکردن در بالای لیست ظاهر خواهند شد."
},
"Search by key combo, description, or action name.\\n\\nDefault action copies the keybind to clipboard.\\nRight-click or press Right Arrow to pin frequently used keybinds - they'll appear at the top when not searching.": {
"Search by key combo, description, or action name.\\n\\nDefault action copies the keybind to clipboard.\\nRight-click or press Right Arrow to pin frequently used keybinds - they'll appear at the top when not searching.": "با ترکیب کلید‌ها، توضیحات یا نام اقدام‌ جستجو کنید.\\n\\اقدام پیش‌فرض نگاشت‌کلید را در کلیپ‌بورد کپی می‌کند.\\nبرای سنجاق‌ کردن نگاشت‌کلید‌های پر استفاده راست‌کلیک کنید یا پیکان راست را فشار دهید - آن‌ها هنگام جستجو نکردن در بالا ظاهر خواهند شد."
"Search by key combo, description, or action name.\\n\\nDefault action copies the keybind to clipboard.\\nRight-click or press Right Arrow to pin frequently used keybinds - they'll appear at the top when not searching.": "با ترکیب کلید‌ها، توضیحات یا نام اقدام‌ جستجو کنید.\\n\\اقدام پیش‌فرض نگاشت‌کلید را در کلیپ‌بورد کپی می‌کند.\\nبرای سنجاق‌ کردن نگاشت‌کلید‌های پر استفاده راست‌کلیک کنید یا پیکان راست را فشار دهید - آن‌ها هنگام جستجو نکردن در بالای لیست ظاهر خواهند شد."
},
"Search file contents": {
"Search file contents": "جستجو در محتوای فایل"
@@ -4330,7 +4333,7 @@
"Select Bar": "انتخاب نوار"
},
"Select Dock Launcher Logo": {
"Select Dock Launcher Logo": ""
"Select Dock Launcher Logo": "لوگوی لانچر داک را انتخاب کنید"
},
"Select Launcher Logo": {
"Select Launcher Logo": "انتخاب لوگوی لانچر"
@@ -4378,7 +4381,7 @@
"Select the palette algorithm used for wallpaper-based colors": "انتخاب الگوریتم پالت رنگی استفاده شده برای رنگ‌های بر اساس تصویر پس‌زمینه"
},
"Select which keybind providers to include": {
"Select which keybind providers to include": ""
"Select which keybind providers to include": "انتخاب کنید که کدام ارائه دهنده نگاشت‌کلید‌ها include شود"
},
"Select which transitions to include in randomization": {
"Select which transitions to include in randomization": "انتخاب کنید کدام گذارها در تصادفی‌سازی باشند"
@@ -4408,13 +4411,13 @@
"Set key and action to save": "کلید و اقدام را برای ذخیره تنظیم کنید"
},
"Set notification rules": {
"Set notification rules": ""
"Set notification rules": "تنظیم قوانین اعلان‌ها"
},
"Setup": {
"Setup": "راه‌اندازی"
},
"Share Gamma Control Settings": {
"Share Gamma Control Settings": ""
"Share Gamma Control Settings": "اشتراک‌گذاری تنظیمات کنترل گاما"
},
"Shell": {
"Shell": "شِل"
@@ -4582,13 +4585,13 @@
"Show darkened overlay behind modal dialogs": "لایه overlay تیره پشت پنجره مودال نمایش بده"
},
"Show device": {
"Show device": ""
"Show device": "نمایش دستگاه"
},
"Show dock when floating windows don't overlap its area": {
"Show dock when floating windows don't overlap its area": "داک را هنگامی که پنجره‌های شناور با محیط آن همپوشانی ندارند نمایش بده"
},
"Show drop shadow on notification popups": {
"Show drop shadow on notification popups": ""
"Show drop shadow on notification popups": "سایه‌افتاده را برای پاپ‌آپ اعلان‌ها نمایش بده"
},
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": {
"Show launcher overlay when typing in Niri overview. Disable to use another launcher.": "لایه overlay لانچر را هنگام تایپ در نمای کلی نیری نمایش بده. برای استفاده از لانچر دیگری غیرفعال کنید."
@@ -4687,7 +4690,7 @@
"Size": "اندازه"
},
"Size Constraints": {
"Size Constraints": ""
"Size Constraints": "محدودیت‌های اندازه"
},
"Size Offset": {
"Size Offset": "آفست اندازه"
@@ -4711,7 +4714,7 @@
"Snap": "چسباندن"
},
"Snow": {
"Snow": ""
"Snow": "برف"
},
"Some plugins require a newer version of DMS:": {
"Some plugins require a newer version of DMS:": "برخی افزونه‌ها نیازمند نسخه جدیدتر DMS هستند:"
@@ -4810,7 +4813,7 @@
"Suspend system after": "تعلیق پس از"
},
"Suspend then Hibernate": {
"Suspend then Hibernate": ""
"Suspend then Hibernate": "تعلیق سپس هایبرنیت"
},
"Swap": {
"Swap": "سواپ"
@@ -4942,7 +4945,7 @@
"This widget prevents GPU power off states, which can significantly impact battery life on laptops. It is not recommended to use this on laptops with hybrid graphics.": "این ابزارک از حالت‌های خاموش شدن GPU جلوگیری می‌کند، که ​​می‌تواند به طور قابل توجهی بر عمر باتری لپ‌تاپ‌ها تأثیر بگذارد. استفاده از این ابزارک در لپ‌تاپ‌هایی با گرافیک هیبریدی توصیه نمی‌شود."
},
"This will delete all unpinned entries. %1 pinned entries will be kept.": {
"This will delete all unpinned entries. %1 pinned entries will be kept.": "این همه ورودی‌های سنجاق نشده را پاک می‌کند. %1 ورودی سنجاق شده نگه داشته می‌شوند."
"This will delete all unpinned entries. %1 pinned entries will be kept.": "این همه مدخل‌های سنجاق نشده را پاک می‌کند. %1 مدخل سنجاق شده نگه داشته می‌شوند."
},
"This will permanently delete all clipboard history.": {
"This will permanently delete all clipboard history.": "این کار تمام تاریخچه کلیپ‌بورد را برای همیشه حذف می‌کند."
@@ -4951,16 +4954,16 @@
"This will permanently remove this saved clipboard item. This action cannot be undone.": "این به طور دائمی این مورد کلیپ‌بورد را حذف خواهد کرد. این عمل برگشت‌ناپذیر است."
},
"Thunderstorm": {
"Thunderstorm": ""
"Thunderstorm": "رعد و برق"
},
"Thunderstorm with Hail": {
"Thunderstorm with Hail": ""
"Thunderstorm with Hail": "رعد و برق با تگرگ"
},
"Tiled": {
"Tiled": ""
"Tiled": "کاشی‌شده"
},
"Tiled State": {
"Tiled State": ""
"Tiled State": "حالت کاشی‌شده"
},
"Tiling": {
"Tiling": "تایلینگ"
@@ -5140,13 +5143,13 @@
"Unknown Title": "عنوان ناشناس"
},
"Unload on Close": {
"Unload on Close": ""
"Unload on Close": "خالی‌کردن هنگام بستن"
},
"Unmute": {
"Unmute": ""
"Unmute": "صدادار کردن"
},
"Unmute popups for %1": {
"Unmute popups for %1": ""
"Unmute popups for %1": "صدادار کردن پاپ‌آپ‌ها را برای %1"
},
"Unnamed Rule": {
"Unnamed Rule": "قاعده بی‌نام"
@@ -5347,7 +5350,7 @@
"Vibrant palette with playful saturation.": "پالتر رنگی پر جنب و جوش با اشباع رنگی سرزنده."
},
"Videos": {
"Videos": ""
"Videos": "ویدئوها"
},
"View Mode": {
"View Mode": "حالت نمایش"
@@ -5619,7 +5622,7 @@
"Thickness": "ضخامت"
},
"brandon": {
"brandon": ""
"brandon": "براندون"
},
"browse themes button | theme browser header | theme browser window title": {
"Browse Themes": "مرور تم‌ها"
@@ -5650,7 +5653,7 @@
"Active tile background and icon color": "رنگ کاشی پس‌زمینه فعال و آیکون"
},
"count of hidden audio devices": {
"Hidden (%1)": ""
"Hidden (%1)": "پنهان (%1)"
},
"current theme label": {
"Current Theme: %1": "تم کنونی: %1"
@@ -5665,7 +5668,7 @@
"Click to select a custom theme JSON file": "برای انتخاب یک فایل JSON قالب سفارشی کلیک کنید"
},
"dark mode wallpaper color picker title": {
"Choose Dark Mode Color": ""
"Choose Dark Mode Color": "انتخاب رنگ حالت تاریک"
},
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
"Select Wallpaper": "انتخاب تصویر پس‌زمینه"
@@ -5686,7 +5689,7 @@
"days": "روز"
},
"default monitor label suffix": {
"(Default)": ""
"(Default)": "(پیش‌فرض)"
},
"dgop not available": {
"dgop not available": "dgop در دسترس نیست"
@@ -5754,7 +5757,7 @@
"No GPUs detected": "هیچ GPUای شناسایی نشد"
},
"empty state in process list": {
"No matching processes": ""
"No matching processes": "فرآیند موردنظر یافت نشد"
},
"empty theme list": {
"No themes found": "هیچ تمی یافت نشد"
@@ -5954,7 +5957,7 @@
"leave empty for default": "برای پیش‌فرض خالی رها کنید"
},
"light mode wallpaper color picker title": {
"Choose Light Mode Color": ""
"Choose Light Mode Color": "انتخاب رنگ حالت روشن"
},
"loading indicator": {
"Loading...": "درحال بارگذاری..."
@@ -6016,7 +6019,7 @@
"nav": "جهت"
},
"neovim template description": {
"Requires lazy plugin manager": ""
"Requires lazy plugin manager": "به مدیریت افزونه lazy نیاز دارد"
},
"network status": {
"Connected": "متصل",
@@ -6032,7 +6035,7 @@
"No custom theme file": "هیچ تم سفارشی یافت نشد"
},
"no monitors available label": {
"No monitors": ""
"No monitors": "بدون مانیتور"
},
"no registry themes installed hint": {
"No themes installed. Browse themes to install from the registry.": "هیچ تمی نصب نشده. تم‌ها را برای نصب از مخزن مرور کنید."
@@ -6082,7 +6085,7 @@
"Enable History": "فعال‌کردن تاریخچه"
},
"notification privacy mode placeholder": {
"Message Content": ""
"Message Content": "محتوای پیام"
},
"notification rule action option": {
"Ignore Completely": "کلاً نادیده بگیر",
@@ -6095,7 +6098,7 @@
},
"notification rule match field option": {
"Body": "بدنه",
"Desktop Entry": "",
"Desktop Entry": "مدخل دسکتاپ",
"Summary": "خلاصه"
},
"notification rule match type option": {
@@ -6115,22 +6118,22 @@
"official": "رسمی"
},
"on Hyprland": {
"on Hyprland": ""
"on Hyprland": "در Hyprland"
},
"on MangoWC": {
"on MangoWC": ""
"on MangoWC": "در MangoWC"
},
"on Miracle WM": {
"on Miracle WM": ""
"on Miracle WM": "در Miracle WM"
},
"on Niri": {
"on Niri": ""
"on Niri": "در Niri"
},
"on Scroll": {
"on Scroll": ""
"on Scroll": "در Scroll"
},
"on Sway": {
"on Sway": ""
"on Sway": "در Sway"
},
"open": {
"open": "باز کردن"
@@ -6180,10 +6183,10 @@
"Select Profile Image": "انتخاب تصویر نمایه"
},
"qt theme env error body": {
"You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.": ""
"You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.": "لازم است یکی از مقادیر زیر را به عنوان متغیر محیطی تنظیم نمایید:\nQT_QPA_PLATFORMTHEME=gtk3 یا\nQT_QPA_PLATFORMTHEME=qt6ct\nو پس از آن، شل را مجدداً راه‌اندازی کنید.\n\nبسته qt6ct نیازمند نصب qt6ct-kde است."
},
"qt theme env error title": {
"Missing Environment Variables": ""
"Missing Environment Variables": "متغیر‌های محیطی یافت نشد"
},
"read-only settings warning for NixOS home-manager users": {
"Settings are read-only. Changes will not persist.": "تنظیمات فقط قابل خواندن هستند. تغییرات حفظ نخواهند شد."
@@ -6243,10 +6246,10 @@
"Load Average": "متوسط بارگذاری"
},
"theme auto mode tab": {
"Location": ""
"Location": "مکان"
},
"theme auto mode tab | wallpaper cycling mode tab": {
"Time": ""
"Time": "زمان"
},
"theme browser description": {
"Install color themes from the DMS theme registry": "نصب تم رنگ‌ها از مخزن تم DMS"
@@ -6267,7 +6270,7 @@
"Search themes...": "جستجوی تم‌ها..."
},
"this app": {
"this app": ""
"this app": "این برنامه"
},
"tile color option": {
"Primary Container": "زمینه اصلی",
@@ -6289,7 +6292,7 @@
"Unknown": "ناشناخته"
},
"up": {
"up": ""
"up": "روشن"
},
"update dms for NM integration.": {
"update dms for NM integration.": "DMS را برای یکپارچه‌سازی NM بروز کنید."
@@ -6304,10 +6307,10 @@
"Requires %1": "به %1 نیاز دارد"
},
"wallpaper color picker title": {
"Choose Wallpaper Color": ""
"Choose Wallpaper Color": "انتخاب رنگ تصویر پس‌زمینه"
},
"wallpaper cycling mode tab": {
"Interval": ""
"Interval": "وقفه"
},
"wallpaper directory file browser title": {
"Select Wallpaper Directory": "انتخاب دایرکتوری تصاویر پس‌زمینه"
@@ -6328,32 +6331,32 @@
"Tile V": "کاشی عمودی"
},
"wallpaper interval": {
"1 hour": "",
"1 hour 30 minutes": "",
"1 minute": "",
"10 seconds": "",
"12 hours": "",
"15 minutes": "",
"15 seconds": "",
"2 hours": "",
"20 seconds": "",
"25 seconds": "",
"3 hours": "",
"30 minutes": "",
"30 seconds": "",
"35 seconds": "",
"4 hours": "",
"40 seconds": "",
"45 seconds": "",
"5 minutes": "",
"5 seconds": "",
"50 seconds": "",
"55 seconds": "",
"6 hours": "",
"8 hours": ""
"1 hour": "۱ ساعت",
"1 hour 30 minutes": "۱ ساعت و نیم",
"1 minute": "۱ دقیقه",
"10 seconds": "۱۰ ثانیه",
"12 hours": "۱۲ ساعت",
"15 minutes": "۱۵ دقیقه",
"15 seconds": "۱۵ ثانیه",
"2 hours": "۲ ساعت",
"20 seconds": "۲۰ ثانیه",
"25 seconds": "۲۵ ثانیه",
"3 hours": "۳ ساعت",
"30 minutes": "۳۰ دقیقه",
"30 seconds": "۳۰ ثانیه",
"35 seconds": "۳۵ ثانیه",
"4 hours": "۴ ساعت",
"40 seconds": "۴۰ ثانیه",
"45 seconds": "۴۵ ثانیه",
"5 minutes": "۵ دقیقه",
"5 seconds": "۵ ثانیه",
"50 seconds": "۵۰ ثانیه",
"55 seconds": "۵۵ ثانیه",
"6 hours": "۶ ساعت",
"8 hours": "۸ ساعت"
},
"wallpaper not set label": {
"Not set": ""
"Not set": "تنظیم نشده"
},
"wallpaper processing error": {
"Wallpaper processing failed": "پردازش تصویر پس‌زمینه ناموفق بود"
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - سال (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Indicateur Verr. Maj."
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Partie centrale"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - Année (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "מחוון Caps Lock"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "קטע אמצעי"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - שנה (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -105,10 +105,10 @@
"2 minutes": "2 perc"
},
"2 seconds": {
"2 seconds": ""
"2 seconds": "2 másodperc"
},
"20 minutes": {
"20 minutes": ""
"20 minutes": "20 perc"
},
"24-Hour Format": {
"24-Hour Format": "24 órás formátum"
@@ -117,7 +117,7 @@
"24-hour format": "24 órás formátum"
},
"250 ms": {
"250 ms": ""
"250 ms": "250 ms"
},
"270°": {
"270°": "270 fok"
@@ -126,7 +126,7 @@
"3 days": "3 nap"
},
"3 minutes": {
"3 minutes": ""
"3 minutes": "3 perc"
},
"3 seconds": {
"3 seconds": "3 másodperc"
@@ -141,7 +141,7 @@
"3rd party": "Harmadik fél"
},
"4 seconds": {
"4 seconds": ""
"4 seconds": "4 másodperc"
},
"5 minutes": {
"5 minutes": "5 perc"
@@ -150,13 +150,13 @@
"5 seconds": "5 másodperc"
},
"500 ms": {
"500 ms": ""
"500 ms": "500 ms"
},
"7 days": {
"7 days": "7 nap"
},
"750 ms": {
"750 ms": ""
"750 ms": "750 ms"
},
"8 seconds": {
"8 seconds": "8 másodperc"
@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Caps Lock jelző"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Középső rész"
},
@@ -5686,7 +5689,7 @@
"days": "nap"
},
"default monitor label suffix": {
"(Default)": ""
"(Default)": "(Alapértelmezett)"
},
"dgop not available": {
"dgop not available": "dgop nem elérhető"
@@ -6328,29 +6331,29 @@
"Tile V": "Függőleges mozaik"
},
"wallpaper interval": {
"1 hour": "",
"1 hour 30 minutes": "",
"1 minute": "",
"10 seconds": "",
"12 hours": "",
"15 minutes": "",
"15 seconds": "",
"2 hours": "",
"20 seconds": "",
"25 seconds": "",
"3 hours": "",
"30 minutes": "",
"30 seconds": "",
"35 seconds": "",
"4 hours": "",
"40 seconds": "",
"45 seconds": "",
"5 minutes": "",
"5 seconds": "",
"50 seconds": "",
"55 seconds": "",
"6 hours": "",
"8 hours": ""
"1 hour": "1 óra",
"1 hour 30 minutes": "1 óra 30 perc",
"1 minute": "1 perc",
"10 seconds": "10 másodperc",
"12 hours": "12 óra",
"15 minutes": "15 perc",
"15 seconds": "15 másodperc",
"2 hours": "2 óra",
"20 seconds": "20 másodperc",
"25 seconds": "25 másodperc",
"3 hours": "3 óra",
"30 minutes": "30 perc",
"30 seconds": "30 másodperc",
"35 seconds": "35 másodperc",
"4 hours": "4 óra",
"40 seconds": "40 másodperc",
"45 seconds": "45 másodperc",
"5 minutes": "5 perc",
"5 seconds": "5 másodperc",
"50 seconds": "50 másodperc",
"55 seconds": "55 másodperc",
"6 hours": "6 óra",
"8 hours": "8 óra"
},
"wallpaper not set label": {
"Not set": ""
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - Év (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -105,10 +105,10 @@
"2 minutes": "2 minuti"
},
"2 seconds": {
"2 seconds": ""
"2 seconds": "2 secondi"
},
"20 minutes": {
"20 minutes": ""
"20 minutes": "20 minuti"
},
"24-Hour Format": {
"24-Hour Format": "Formato 24 Ore"
@@ -117,7 +117,7 @@
"24-hour format": "formato 24 ore"
},
"250 ms": {
"250 ms": ""
"250 ms": "250 mms"
},
"270°": {
"270°": "270°"
@@ -126,7 +126,7 @@
"3 days": "3 giorni"
},
"3 minutes": {
"3 minutes": ""
"3 minutes": "3 minuti"
},
"3 seconds": {
"3 seconds": "3 secondi"
@@ -141,7 +141,7 @@
"3rd party": "terze parti"
},
"4 seconds": {
"4 seconds": ""
"4 seconds": "4 secondi"
},
"5 minutes": {
"5 minutes": "5 minuti"
@@ -150,13 +150,13 @@
"5 seconds": "5 secondi"
},
"500 ms": {
"500 ms": ""
"500 ms": "500 ms"
},
"7 days": {
"7 days": "7 giorni"
},
"750 ms": {
"750 ms": ""
"750 ms": "750 ms"
},
"8 seconds": {
"8 seconds": "8 secondi"
@@ -171,7 +171,7 @@
"A file with this name already exists. Do you want to overwrite it?": "Esiste già un file con questo nome. Vuoi sovrascriverlo?"
},
"AC Power": {
"AC Power": ""
"AC Power": "Alimentazione CA"
},
"API": {
"API": "API"
@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Indicatore Blocco Maiuscole"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Sezione Centrale"
},
@@ -860,7 +863,7 @@
"Clear History?": "Cancellare la Cronologia?"
},
"Clear Sky": {
"Clear Sky": ""
"Clear Sky": "Sereno"
},
"Clear all history when server starts": {
"Clear all history when server starts": "Cancella tutta la cronologia all'avvio del server"
@@ -1415,7 +1418,7 @@
"Description": "Descrizione"
},
"Desktop": {
"Desktop": ""
"Desktop": "Scrivania"
},
"Desktop Clock": {
"Desktop Clock": "Orologio Desktop"
@@ -1589,7 +1592,7 @@
"Docs": "Documentazione"
},
"Documents": {
"Documents": ""
"Documents": "Documenti"
},
"Domain (optional)": {
"Domain (optional)": "Dominio (opzionale)"
@@ -1604,7 +1607,7 @@
"Door Open": "Sportello Aperto"
},
"Downloads": {
"Downloads": ""
"Downloads": "Scaricati"
},
"Drag to Reorder": {
"Drag to Reorder": "Trascina per Riordinare"
@@ -1619,7 +1622,7 @@
"Driver": "Driver"
},
"Drizzle": {
"Drizzle": ""
"Drizzle": "Pioviggine"
},
"Duplicate": {
"Duplicate": "Duplica"
@@ -2084,7 +2087,7 @@
"Focused Window": "Finestra Attiva"
},
"Fog": {
"Fog": ""
"Fog": "Nebbia"
},
"Follow Monitor Focus": {
"Follow Monitor Focus": "Segui lo Schermo Attivo"
@@ -2150,7 +2153,7 @@
"Free VRAM/memory when the launcher is closed. May cause a slight delay when reopening.": "Libera VRAM/memoria alla chiusura del launcher. Potrebbe causare un leggero ritardo alla riapertura."
},
"Freezing Drizzle": {
"Freezing Drizzle": ""
"Freezing Drizzle": "Pioviggine Congelantesi"
},
"Frequency": {
"Frequency": "Frequenza"
@@ -2258,13 +2261,13 @@
"Health": "Salute"
},
"Heavy Rain": {
"Heavy Rain": ""
"Heavy Rain": "Pioggia Forte"
},
"Heavy Snow": {
"Heavy Snow": ""
"Heavy Snow": "Neve Abbondante"
},
"Heavy Snow Showers": {
"Heavy Snow Showers": ""
"Heavy Snow Showers": "Forti Rovesci di Neve"
},
"Height": {
"Height": "Altezza"
@@ -2366,7 +2369,7 @@
"Hold to confirm (%1s)": "Tieni premuto per confermare (%1s)"
},
"Home": {
"Home": ""
"Home": "Home"
},
"Hot Corners": {
"Hot Corners": "Angoli Attivi"
@@ -2816,13 +2819,13 @@
"Light Mode": "Modalità Chiara"
},
"Light Rain": {
"Light Rain": ""
"Light Rain": "Pioggia Leggera"
},
"Light Snow": {
"Light Snow": ""
"Light Snow": "Neve Leggera"
},
"Light Snow Showers": {
"Light Snow Showers": ""
"Light Snow Showers": "Deboli Rovesci di Neve"
},
"Linear": {
"Linear": "Lineare"
@@ -3170,7 +3173,7 @@
"Moving to Paused": "Messa in Pausa"
},
"Music": {
"Music": ""
"Music": "Musica"
},
"Mute popups for %1": {
"Mute popups for %1": "Silenzia popup per %1"
@@ -3590,7 +3593,7 @@
"Outputs Include Missing": "Inclusione Output Mancanti"
},
"Overcast": {
"Overcast": ""
"Overcast": "Coperto"
},
"Overflow": {
"Overflow": "Overflow"
@@ -3650,7 +3653,7 @@
"Pairing...": "Associazione in Corso..."
},
"Partly Cloudy": {
"Partly Cloudy": ""
"Partly Cloudy": "Parzialmente Nuvoloso"
},
"Passkey:": {
"Passkey:": "Passkey:"
@@ -3760,7 +3763,7 @@
"Unavailable": "Non Disponibile"
},
"Pictures": {
"Pictures": ""
"Pictures": "Immagini"
},
"Pin": {
"Pin": "Fissa"
@@ -3988,7 +3991,7 @@
"Protocol": "Protocollo"
},
"Quick Access": {
"Quick Access": ""
"Quick Access": "Accesso Rapido"
},
"Quick access to application launcher": {
"Quick access to application launcher": "Accesso veloce al launcher applicazioni"
@@ -4009,7 +4012,7 @@
"Radius": "Raggio"
},
"Rain": {
"Rain": ""
"Rain": "Pioggia"
},
"Rain Chance": {
"Rain Chance": "Prob. Pioggia"
@@ -4711,7 +4714,7 @@
"Snap": "Aggancia"
},
"Snow": {
"Snow": ""
"Snow": "Neve"
},
"Some plugins require a newer version of DMS:": {
"Some plugins require a newer version of DMS:": "Alcuni plugin richiedono una versione più recente di DMS:"
@@ -4810,7 +4813,7 @@
"Suspend system after": "Sospendi sistema dopo"
},
"Suspend then Hibernate": {
"Suspend then Hibernate": ""
"Suspend then Hibernate": "Sospendi e poi Iberna"
},
"Swap": {
"Swap": "Swap"
@@ -4951,10 +4954,10 @@
"This will permanently remove this saved clipboard item. This action cannot be undone.": "Questo rimuoverà definitivamente questo elemento degli appunti salvato. Questa azione non può essere annullata."
},
"Thunderstorm": {
"Thunderstorm": ""
"Thunderstorm": "Temporale"
},
"Thunderstorm with Hail": {
"Thunderstorm with Hail": ""
"Thunderstorm with Hail": "Temporale con Grandine"
},
"Tiled": {
"Tiled": "Affiancato"
@@ -5347,7 +5350,7 @@
"Vibrant palette with playful saturation.": "Tavolozza vibrante con saturazione giocosa."
},
"Videos": {
"Videos": ""
"Videos": "Video"
},
"View Mode": {
"View Mode": "Modalità Visualizzazione"
@@ -5619,7 +5622,7 @@
"Thickness": "Spessore"
},
"brandon": {
"brandon": ""
"brandon": "brandon"
},
"browse themes button | theme browser header | theme browser window title": {
"Browse Themes": "Sfoglia Temi"
@@ -5665,7 +5668,7 @@
"Click to select a custom theme JSON file": "Clicca per selezionare un file tema JSON personalizzato"
},
"dark mode wallpaper color picker title": {
"Choose Dark Mode Color": ""
"Choose Dark Mode Color": "Scegli Colore Modalità Scura"
},
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
"Select Wallpaper": "Seleziona Sfondo"
@@ -5686,7 +5689,7 @@
"days": "giorni"
},
"default monitor label suffix": {
"(Default)": ""
"(Default)": "(Predefinito)"
},
"dgop not available": {
"dgop not available": "dgop non disponibile"
@@ -5954,7 +5957,7 @@
"leave empty for default": "lascia vuoto per il valore predefinito"
},
"light mode wallpaper color picker title": {
"Choose Light Mode Color": ""
"Choose Light Mode Color": "Scegli Colore Modalità Chiara"
},
"loading indicator": {
"Loading...": "Caricamento..."
@@ -6016,7 +6019,7 @@
"nav": "nav"
},
"neovim template description": {
"Requires lazy plugin manager": ""
"Requires lazy plugin manager": "Richiede lazy plugin manager"
},
"network status": {
"Connected": "Connesso",
@@ -6032,7 +6035,7 @@
"No custom theme file": "Nessun file tema personalizzato"
},
"no monitors available label": {
"No monitors": ""
"No monitors": "Nessun monitor"
},
"no registry themes installed hint": {
"No themes installed. Browse themes to install from the registry.": "Nessun tema installato. Sfoglia i temi dal registro per installarli."
@@ -6115,22 +6118,22 @@
"official": "ufficiale"
},
"on Hyprland": {
"on Hyprland": ""
"on Hyprland": "su Hyprland"
},
"on MangoWC": {
"on MangoWC": ""
"on MangoWC": "su MangoWC"
},
"on Miracle WM": {
"on Miracle WM": ""
"on Miracle WM": "su Miracle WM"
},
"on Niri": {
"on Niri": ""
"on Niri": "su Niri"
},
"on Scroll": {
"on Scroll": ""
"on Scroll": "su Scroll"
},
"on Sway": {
"on Sway": ""
"on Sway": "su Sway"
},
"open": {
"open": "apri"
@@ -6180,10 +6183,10 @@
"Select Profile Image": "Seleziona Immagine Profilo"
},
"qt theme env error body": {
"You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.": ""
"You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.": "Devi impostare una delle seguenti come variabili d'ambiente: \nQT_QPA_PLATFORMTHEME=gtk3 OPPURE \nQT_QPA_PLATFORMTHEME=qt6ct, \ne poi riavviare la shell.\n\nqt6ct richiede che qt6ct-kde sia installato."
},
"qt theme env error title": {
"Missing Environment Variables": ""
"Missing Environment Variables": "Variabili di Ambiente Mancanti"
},
"read-only settings warning for NixOS home-manager users": {
"Settings are read-only. Changes will not persist.": "Le impostazioni sono in sola lettura. Le modifiche non verranno salvate."
@@ -6243,10 +6246,10 @@
"Load Average": "Carico Medio"
},
"theme auto mode tab": {
"Location": ""
"Location": "Posizione"
},
"theme auto mode tab | wallpaper cycling mode tab": {
"Time": ""
"Time": "Tempo"
},
"theme browser description": {
"Install color themes from the DMS theme registry": "Installa temi colore dal registro temi DMS"
@@ -6289,7 +6292,7 @@
"Unknown": "Autore Sconosciuto"
},
"up": {
"up": ""
"up": "acceso da"
},
"update dms for NM integration.": {
"update dms for NM integration.": "aggiorna dms per l'integrazione NM."
@@ -6304,10 +6307,10 @@
"Requires %1": "Richiede %1"
},
"wallpaper color picker title": {
"Choose Wallpaper Color": ""
"Choose Wallpaper Color": "Scegli Colore Sfondo"
},
"wallpaper cycling mode tab": {
"Interval": ""
"Interval": "Intervallo"
},
"wallpaper directory file browser title": {
"Select Wallpaper Directory": "Seleziona Cartella Sfondo"
@@ -6328,32 +6331,32 @@
"Tile V": "Affianca Vert."
},
"wallpaper interval": {
"1 hour": "",
"1 hour 30 minutes": "",
"1 minute": "",
"10 seconds": "",
"12 hours": "",
"15 minutes": "",
"15 seconds": "",
"2 hours": "",
"20 seconds": "",
"25 seconds": "",
"3 hours": "",
"30 minutes": "",
"30 seconds": "",
"35 seconds": "",
"4 hours": "",
"40 seconds": "",
"45 seconds": "",
"5 minutes": "",
"5 seconds": "",
"50 seconds": "",
"55 seconds": "",
"6 hours": "",
"8 hours": ""
"1 hour": "1 ora",
"1 hour 30 minutes": "1 ora 30 minuti",
"1 minute": "1 minuto",
"10 seconds": "10 secondi",
"12 hours": "12 ore",
"15 minutes": "15 minuti",
"15 seconds": "15 secondi",
"2 hours": "2 ore",
"20 seconds": "20 secondi",
"25 seconds": "25 secondi",
"3 hours": "3 ore",
"30 minutes": "30 minuti",
"30 seconds": "30 secondi",
"35 seconds": "35 secondi",
"4 hours": "4 ore",
"40 seconds": "40 secondi",
"45 seconds": "45 secondi",
"5 minutes": "5 minuti",
"5 seconds": "5 secondi",
"50 seconds": "50 secondi",
"55 seconds": "55 secondi",
"6 hours": "6 ore",
"8 hours": "8 ore"
},
"wallpaper not set label": {
"Not set": ""
"Not set": "Non impostato"
},
"wallpaper processing error": {
"Wallpaper processing failed": "Elaborazione dello sfondo fallita"
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - Anno (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Caps Lock インジケーター"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "センターセクション"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - 年2024年"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Caps Lock-indicator"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Middensectie"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - Jaar (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Wskaźnik caps locka"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Sekcja środkowa"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - Rok (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "Caps Lock Göstergesi"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "Orta Bölüm"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - Yıl (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "大小写指示灯"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "中间区域"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yy - 年2024"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -769,6 +769,9 @@
"Caps Lock Indicator": {
"Caps Lock Indicator": "大小寫鎖定指示器"
},
"Caps Lock is on": {
"Caps Lock is on": ""
},
"Center Section": {
"Center Section": "中間區塊"
},
@@ -6429,5 +6432,8 @@
},
"• yyyy - Year (2024)": {
"• yyyy - Year (2024)": "• yyyy - 年 (2024)"
},
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": {
"↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text": ""
}
}

View File

@@ -1987,6 +1987,13 @@
"reference": "",
"comment": ""
},
{
"term": "Caps Lock is on",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{
"term": "Center Section",
"translation": "",
@@ -14531,6 +14538,13 @@
"reference": "",
"comment": ""
},
{
"term": "↑/↓: Nav • Space: Expand • Enter: Action/Expand • E: Text",
"translation": "",
"context": "",
"reference": "",
"comment": ""
},
{
"term": "↑/↓: Navigate • Enter: Paste • Del: Delete • F10: Help",
"translation": "",