mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
Compare commits
11 Commits
0df47d2ce3
...
0ea0602aec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ea0602aec | ||
|
|
46effd2ca4 | ||
|
|
de055e8260 | ||
|
|
c3077304af | ||
|
|
e15135911f | ||
|
|
d430cae944 | ||
|
|
f92dc6f71b | ||
|
|
a679be68b1 | ||
|
|
c5c5ce8409 | ||
|
|
e7cb0d397e | ||
|
|
b84308cb49 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -610,6 +610,8 @@ jobs:
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/.github
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/distro
|
||||
|
||||
echo "%{version}" > %{buildroot}%{_datadir}/quickshell/dms/VERSION
|
||||
|
||||
%posttrans
|
||||
if [ -d "%{_sysconfdir}/xdg/quickshell/dms" ]; then
|
||||
rmdir "%{_sysconfdir}/xdg/quickshell/dms" 2>/dev/null || true
|
||||
|
||||
46
.github/workflows/run-obs.yml
vendored
46
.github/workflows/run-obs.yml
vendored
@@ -62,13 +62,9 @@ jobs:
|
||||
echo "packages=dms-git" >> $GITHUB_OUTPUT
|
||||
echo "Checking if dms-git source has changed..."
|
||||
|
||||
# Get latest commit hash from master branch
|
||||
LATEST_COMMIT=$(git rev-parse origin/master 2>/dev/null || git rev-parse master 2>/dev/null || echo "")
|
||||
# Get current commit hash (8 chars to match spec format)
|
||||
CURRENT_COMMIT=$(git rev-parse --short=8 HEAD)
|
||||
|
||||
if [[ -z "$LATEST_COMMIT" ]]; then
|
||||
echo "has_updates=true" >> $GITHUB_OUTPUT
|
||||
echo "Could not determine git commit, proceeding with update"
|
||||
else
|
||||
# Check OBS for last uploaded commit
|
||||
OBS_BASE="$HOME/.cache/osc-checkouts"
|
||||
mkdir -p "$OBS_BASE"
|
||||
@@ -78,40 +74,32 @@ jobs:
|
||||
cd "$OBS_BASE/$OBS_PROJECT/dms-git"
|
||||
osc up -q 2>/dev/null || true
|
||||
|
||||
# Check tarball age - if older than 3 hours, update needed
|
||||
if [[ -f "dms-git-source.tar.gz" ]]; then
|
||||
TARBALL_MTIME=$(stat -c%Y "dms-git-source.tar.gz" 2>/dev/null || echo "0")
|
||||
CURRENT_TIME=$(date +%s)
|
||||
AGE_SECONDS=$((CURRENT_TIME - TARBALL_MTIME))
|
||||
AGE_HOURS=$((AGE_SECONDS / 3600))
|
||||
# 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 tarball is older than 3 hours, check for new commits
|
||||
if [[ $AGE_HOURS -ge 3 ]]; then
|
||||
# Check if there are new commits in the last 3 hours
|
||||
cd "${{ github.workspace }}"
|
||||
NEW_COMMITS=$(git log --since="3 hours ago" --oneline origin/master 2>/dev/null | wc -l)
|
||||
|
||||
if [[ $NEW_COMMITS -gt 0 ]]; then
|
||||
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 commits detected in last 3 hours, update needed"
|
||||
else
|
||||
echo "has_updates=false" >> $GITHUB_OUTPUT
|
||||
echo "📋 No new commits in last 3 hours, skipping update"
|
||||
fi
|
||||
else
|
||||
echo "has_updates=false" >> $GITHUB_OUTPUT
|
||||
echo "📋 Recent upload exists (< 3 hours), skipping update"
|
||||
echo "📋 New commit detected: $CURRENT_COMMIT (OBS has $OBS_COMMIT)"
|
||||
fi
|
||||
else
|
||||
echo "has_updates=true" >> $GITHUB_OUTPUT
|
||||
echo "📋 No existing tarball in OBS, update needed"
|
||||
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
|
||||
fi
|
||||
elif [[ -n "${{ github.event.inputs.package }}" ]]; then
|
||||
echo "packages=${{ github.event.inputs.package }}" >> $GITHUB_OUTPUT
|
||||
echo "has_updates=true" >> $GITHUB_OUTPUT
|
||||
|
||||
71
.github/workflows/run-ppa.yml
vendored
71
.github/workflows/run-ppa.yml
vendored
@@ -15,9 +15,70 @@ on:
|
||||
- cron: '0 */3 * * *' # Every 3 hours for dms-git builds
|
||||
|
||||
jobs:
|
||||
upload-ppa:
|
||||
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
|
||||
if: |
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
needs.check-updates.outputs.has_updates == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -54,13 +115,13 @@ jobs:
|
||||
id: packages
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "schedule" ]]; then
|
||||
echo "packages=dms-git" >> $GITHUB_OUTPUT
|
||||
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
||||
echo "Triggered by schedule: uploading 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=dms-git" >> $GITHUB_OUTPUT
|
||||
echo "packages=${{ needs.check-updates.outputs.packages }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Upload to PPA
|
||||
@@ -103,6 +164,10 @@ jobs:
|
||||
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
|
||||
|
||||
@@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||
@@ -152,7 +154,55 @@ var pluginsUninstallCmd = &cobra.Command{
|
||||
|
||||
func runVersion(cmd *cobra.Command, args []string) {
|
||||
printASCII()
|
||||
fmt.Printf("%s\n", Version)
|
||||
fmt.Printf("%s\n", formatVersion(Version))
|
||||
}
|
||||
|
||||
// Git builds: dms (git) v0.6.2-XXXX
|
||||
// Stable releases: dms v0.6.2
|
||||
func formatVersion(version string) string {
|
||||
// Arch/Debian/Ubuntu/OpenSUSE git format: 0.6.2+git2264.c5c5ce84
|
||||
re := regexp.MustCompile(`^([\d.]+)\+git(\d+)\.`)
|
||||
if matches := re.FindStringSubmatch(version); matches != nil {
|
||||
return fmt.Sprintf("dms (git) v%s-%s", matches[1], matches[2])
|
||||
}
|
||||
|
||||
// Fedora COPR git format: 0.0.git.2267.d430cae9
|
||||
re = regexp.MustCompile(`^[\d.]+\.git\.(\d+)\.`)
|
||||
if matches := re.FindStringSubmatch(version); matches != nil {
|
||||
baseVersion := getBaseVersion()
|
||||
return fmt.Sprintf("dms (git) v%s-%s", baseVersion, matches[1])
|
||||
}
|
||||
|
||||
// Stable release format: 0.6.2
|
||||
re = regexp.MustCompile(`^([\d.]+)$`)
|
||||
if matches := re.FindStringSubmatch(version); matches != nil {
|
||||
return fmt.Sprintf("dms v%s", matches[1])
|
||||
}
|
||||
|
||||
return fmt.Sprintf("dms %s", version)
|
||||
}
|
||||
|
||||
func getBaseVersion() string {
|
||||
paths := []string{
|
||||
"/usr/share/quickshell/dms/VERSION",
|
||||
"/usr/local/share/quickshell/dms/VERSION",
|
||||
"/etc/xdg/quickshell/dms/VERSION",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
if content, err := os.ReadFile(path); err == nil {
|
||||
ver := strings.TrimSpace(string(content))
|
||||
ver = strings.TrimPrefix(ver, "v")
|
||||
if re := regexp.MustCompile(`^([\d.]+)`); re.MatchString(ver) {
|
||||
if matches := re.FindStringSubmatch(ver); matches != nil {
|
||||
return matches[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return "0.6.2"
|
||||
}
|
||||
|
||||
func startDebugServer() error {
|
||||
|
||||
@@ -40,11 +40,34 @@ var keybindsShowCmd = &cobra.Command{
|
||||
Run: runKeybindsShow,
|
||||
}
|
||||
|
||||
var keybindsSetCmd = &cobra.Command{
|
||||
Use: "set <provider> <key> <action>",
|
||||
Short: "Set a keybind override",
|
||||
Long: "Create or update a keybind override for the specified provider",
|
||||
Args: cobra.ExactArgs(3),
|
||||
Run: runKeybindsSet,
|
||||
}
|
||||
|
||||
var keybindsRemoveCmd = &cobra.Command{
|
||||
Use: "remove <provider> <key>",
|
||||
Short: "Remove a keybind override",
|
||||
Long: "Remove a keybind override from the specified provider",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: runKeybindsRemove,
|
||||
}
|
||||
|
||||
func init() {
|
||||
keybindsShowCmd.Flags().String("path", "", "Override config path for the provider")
|
||||
keybindsSetCmd.Flags().String("desc", "", "Description for hotkey overlay")
|
||||
keybindsSetCmd.Flags().Bool("allow-when-locked", false, "Allow when screen is locked")
|
||||
keybindsSetCmd.Flags().Int("cooldown-ms", 0, "Cooldown in milliseconds")
|
||||
keybindsSetCmd.Flags().Bool("no-repeat", false, "Disable key repeat")
|
||||
keybindsSetCmd.Flags().String("replace-key", "", "Original key to replace (removes old key)")
|
||||
|
||||
keybindsCmd.AddCommand(keybindsListCmd)
|
||||
keybindsCmd.AddCommand(keybindsShowCmd)
|
||||
keybindsCmd.AddCommand(keybindsSetCmd)
|
||||
keybindsCmd.AddCommand(keybindsRemoveCmd)
|
||||
|
||||
keybinds.SetJSONProviderFactory(func(filePath string) (keybinds.Provider, error) {
|
||||
return providers.NewJSONFileProvider(filePath)
|
||||
@@ -82,69 +105,122 @@ func initializeProviders() {
|
||||
}
|
||||
}
|
||||
|
||||
func runKeybindsList(cmd *cobra.Command, args []string) {
|
||||
registry := keybinds.GetDefaultRegistry()
|
||||
providers := registry.List()
|
||||
|
||||
if len(providers) == 0 {
|
||||
func runKeybindsList(_ *cobra.Command, _ []string) {
|
||||
providerList := keybinds.GetDefaultRegistry().List()
|
||||
if len(providerList) == 0 {
|
||||
fmt.Fprintln(os.Stdout, "No providers available")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, "Available providers:")
|
||||
for _, name := range providers {
|
||||
for _, name := range providerList {
|
||||
fmt.Fprintf(os.Stdout, " - %s\n", name)
|
||||
}
|
||||
}
|
||||
|
||||
func runKeybindsShow(cmd *cobra.Command, args []string) {
|
||||
providerName := args[0]
|
||||
registry := keybinds.GetDefaultRegistry()
|
||||
|
||||
customPath, _ := cmd.Flags().GetString("path")
|
||||
if customPath != "" {
|
||||
var provider keybinds.Provider
|
||||
switch providerName {
|
||||
func makeProviderWithPath(name, path string) keybinds.Provider {
|
||||
switch name {
|
||||
case "hyprland":
|
||||
provider = providers.NewHyprlandProvider(customPath)
|
||||
return providers.NewHyprlandProvider(path)
|
||||
case "mangowc":
|
||||
provider = providers.NewMangoWCProvider(customPath)
|
||||
return providers.NewMangoWCProvider(path)
|
||||
case "sway":
|
||||
provider = providers.NewSwayProvider(customPath)
|
||||
return providers.NewSwayProvider(path)
|
||||
case "niri":
|
||||
provider = providers.NewNiriProvider(customPath)
|
||||
return providers.NewNiriProvider(path)
|
||||
default:
|
||||
log.Fatalf("Provider %s does not support custom path", providerName)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func printCheatSheet(provider keybinds.Provider) {
|
||||
sheet, err := provider.GetCheatSheet()
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting cheatsheet: %v", err)
|
||||
}
|
||||
|
||||
output, err := json.MarshalIndent(sheet, "", " ")
|
||||
if err != nil {
|
||||
log.Fatalf("Error generating JSON: %v", err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, string(output))
|
||||
}
|
||||
|
||||
func runKeybindsShow(cmd *cobra.Command, args []string) {
|
||||
providerName := args[0]
|
||||
customPath, _ := cmd.Flags().GetString("path")
|
||||
|
||||
if customPath != "" {
|
||||
provider := makeProviderWithPath(providerName, customPath)
|
||||
if provider == nil {
|
||||
log.Fatalf("Provider %s does not support custom path", providerName)
|
||||
}
|
||||
printCheatSheet(provider)
|
||||
return
|
||||
}
|
||||
|
||||
provider, err := registry.Get(providerName)
|
||||
provider, err := keybinds.GetDefaultRegistry().Get(providerName)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
printCheatSheet(provider)
|
||||
}
|
||||
|
||||
sheet, err := provider.GetCheatSheet()
|
||||
func getWritableProvider(name string) keybinds.WritableProvider {
|
||||
provider, err := keybinds.GetDefaultRegistry().Get(name)
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting cheatsheet: %v", err)
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
writable, ok := provider.(keybinds.WritableProvider)
|
||||
if !ok {
|
||||
log.Fatalf("Provider %s does not support writing keybinds", name)
|
||||
}
|
||||
return writable
|
||||
}
|
||||
|
||||
func runKeybindsSet(cmd *cobra.Command, args []string) {
|
||||
providerName, key, action := args[0], args[1], args[2]
|
||||
writable := getWritableProvider(providerName)
|
||||
|
||||
if replaceKey, _ := cmd.Flags().GetString("replace-key"); replaceKey != "" && replaceKey != key {
|
||||
_ = writable.RemoveBind(replaceKey)
|
||||
}
|
||||
|
||||
output, err := json.MarshalIndent(sheet, "", " ")
|
||||
if err != nil {
|
||||
log.Fatalf("Error generating JSON: %v", err)
|
||||
options := make(map[string]any)
|
||||
if v, _ := cmd.Flags().GetBool("allow-when-locked"); v {
|
||||
options["allow-when-locked"] = true
|
||||
}
|
||||
if v, _ := cmd.Flags().GetInt("cooldown-ms"); v > 0 {
|
||||
options["cooldown-ms"] = v
|
||||
}
|
||||
if v, _ := cmd.Flags().GetBool("no-repeat"); v {
|
||||
options["repeat"] = false
|
||||
}
|
||||
|
||||
desc, _ := cmd.Flags().GetString("desc")
|
||||
if err := writable.SetBind(key, action, desc, options); err != nil {
|
||||
log.Fatalf("Error setting keybind: %v", err)
|
||||
}
|
||||
|
||||
output, _ := json.MarshalIndent(map[string]any{
|
||||
"success": true,
|
||||
"key": key,
|
||||
"action": action,
|
||||
"path": writable.GetOverridePath(),
|
||||
}, "", " ")
|
||||
fmt.Fprintln(os.Stdout, string(output))
|
||||
}
|
||||
|
||||
func runKeybindsRemove(_ *cobra.Command, args []string) {
|
||||
providerName, key := args[0], args[1]
|
||||
writable := getWritableProvider(providerName)
|
||||
|
||||
if err := writable.RemoveBind(key); err != nil {
|
||||
log.Fatalf("Error removing keybind: %v", err)
|
||||
}
|
||||
|
||||
output, _ := json.MarshalIndent(map[string]any{
|
||||
"success": true,
|
||||
"key": key,
|
||||
"removed": true,
|
||||
}, "", " ")
|
||||
fmt.Fprintln(os.Stdout, string(output))
|
||||
}
|
||||
|
||||
@@ -3,14 +3,19 @@ package providers
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
|
||||
"github.com/sblinch/kdl-go"
|
||||
"github.com/sblinch/kdl-go/document"
|
||||
)
|
||||
|
||||
type NiriProvider struct {
|
||||
configDir string
|
||||
dmsBindsIncluded bool
|
||||
parsed bool
|
||||
}
|
||||
|
||||
func NewNiriProvider(configDir string) *NiriProvider {
|
||||
@@ -23,8 +28,7 @@ func NewNiriProvider(configDir string) *NiriProvider {
|
||||
}
|
||||
|
||||
func defaultNiriConfigDir() string {
|
||||
configHome := os.Getenv("XDG_CONFIG_HOME")
|
||||
if configHome != "" {
|
||||
if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
return filepath.Join(configHome, "niri")
|
||||
}
|
||||
|
||||
@@ -40,21 +44,40 @@ func (n *NiriProvider) Name() string {
|
||||
}
|
||||
|
||||
func (n *NiriProvider) GetCheatSheet() (*keybinds.CheatSheet, error) {
|
||||
section, err := ParseNiriKeys(n.configDir)
|
||||
result, err := ParseNiriKeys(n.configDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse niri config: %w", err)
|
||||
}
|
||||
|
||||
n.dmsBindsIncluded = result.DMSBindsIncluded
|
||||
n.parsed = true
|
||||
|
||||
categorizedBinds := make(map[string][]keybinds.Keybind)
|
||||
n.convertSection(section, "", categorizedBinds)
|
||||
n.convertSection(result.Section, "", categorizedBinds)
|
||||
|
||||
return &keybinds.CheatSheet{
|
||||
Title: "Niri Keybinds",
|
||||
Provider: n.Name(),
|
||||
Binds: categorizedBinds,
|
||||
DMSBindsIncluded: result.DMSBindsIncluded,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *NiriProvider) HasDMSBindsIncluded() bool {
|
||||
if n.parsed {
|
||||
return n.dmsBindsIncluded
|
||||
}
|
||||
|
||||
result, err := ParseNiriKeys(n.configDir)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
n.dmsBindsIncluded = result.DMSBindsIncluded
|
||||
n.parsed = true
|
||||
return n.dmsBindsIncluded
|
||||
}
|
||||
|
||||
func (n *NiriProvider) convertSection(section *NiriSection, subcategory string, categorizedBinds map[string][]keybinds.Keybind) {
|
||||
currentSubcat := subcategory
|
||||
if section.Name != "" {
|
||||
@@ -106,19 +129,19 @@ func (n *NiriProvider) categorizeByAction(action string) string {
|
||||
}
|
||||
|
||||
func (n *NiriProvider) convertKeybind(kb *NiriKeyBinding, subcategory string) keybinds.Keybind {
|
||||
key := n.formatKey(kb)
|
||||
desc := kb.Description
|
||||
rawAction := n.formatRawAction(kb.Action, kb.Args)
|
||||
|
||||
if desc == "" {
|
||||
desc = rawAction
|
||||
source := "config"
|
||||
if strings.Contains(kb.Source, "dms/binds.kdl") {
|
||||
source = "dms"
|
||||
}
|
||||
|
||||
return keybinds.Keybind{
|
||||
Key: key,
|
||||
Description: desc,
|
||||
Key: n.formatKey(kb),
|
||||
Description: kb.Description,
|
||||
Action: rawAction,
|
||||
Subcategory: subcategory,
|
||||
Source: source,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +149,15 @@ func (n *NiriProvider) formatRawAction(action string, args []string) string {
|
||||
if len(args) == 0 {
|
||||
return action
|
||||
}
|
||||
|
||||
if action == "spawn" && len(args) >= 3 && args[1] == "-c" {
|
||||
switch args[0] {
|
||||
case "sh", "bash":
|
||||
cmd := strings.Join(args[2:], " ")
|
||||
return fmt.Sprintf("spawn %s -c \"%s\"", args[0], strings.ReplaceAll(cmd, "\"", "\\\""))
|
||||
}
|
||||
}
|
||||
|
||||
return action + " " + strings.Join(args, " ")
|
||||
}
|
||||
|
||||
@@ -135,3 +167,308 @@ func (n *NiriProvider) formatKey(kb *NiriKeyBinding) string {
|
||||
parts = append(parts, kb.Key)
|
||||
return strings.Join(parts, "+")
|
||||
}
|
||||
|
||||
func (n *NiriProvider) GetOverridePath() string {
|
||||
return filepath.Join(n.configDir, "dms", "binds.kdl")
|
||||
}
|
||||
|
||||
func (n *NiriProvider) validateAction(action string) error {
|
||||
action = strings.TrimSpace(action)
|
||||
switch {
|
||||
case action == "":
|
||||
return fmt.Errorf("action cannot be empty")
|
||||
case action == "spawn" || action == "spawn ":
|
||||
return fmt.Errorf("spawn command requires arguments")
|
||||
case strings.HasPrefix(action, "spawn "):
|
||||
rest := strings.TrimSpace(strings.TrimPrefix(action, "spawn "))
|
||||
switch rest {
|
||||
case "":
|
||||
return fmt.Errorf("spawn command requires arguments")
|
||||
case "sh -c \"\"", "sh -c ''", "bash -c \"\"", "bash -c ''":
|
||||
return fmt.Errorf("shell command cannot be empty")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NiriProvider) SetBind(key, action, description string, options map[string]any) error {
|
||||
if err := n.validateAction(action); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
overridePath := n.GetOverridePath()
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(overridePath), 0755); err != nil {
|
||||
return fmt.Errorf("failed to create dms directory: %w", err)
|
||||
}
|
||||
|
||||
existingBinds, err := n.loadOverrideBinds()
|
||||
if err != nil {
|
||||
existingBinds = make(map[string]*overrideBind)
|
||||
}
|
||||
|
||||
existingBinds[key] = &overrideBind{
|
||||
Key: key,
|
||||
Action: action,
|
||||
Description: description,
|
||||
Options: options,
|
||||
}
|
||||
|
||||
return n.writeOverrideBinds(existingBinds)
|
||||
}
|
||||
|
||||
func (n *NiriProvider) RemoveBind(key string) error {
|
||||
existingBinds, err := n.loadOverrideBinds()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
delete(existingBinds, key)
|
||||
return n.writeOverrideBinds(existingBinds)
|
||||
}
|
||||
|
||||
type overrideBind struct {
|
||||
Key string
|
||||
Action string
|
||||
Description string
|
||||
Options map[string]any
|
||||
}
|
||||
|
||||
func (n *NiriProvider) loadOverrideBinds() (map[string]*overrideBind, error) {
|
||||
overridePath := n.GetOverridePath()
|
||||
binds := make(map[string]*overrideBind)
|
||||
|
||||
data, err := os.ReadFile(overridePath)
|
||||
if os.IsNotExist(err) {
|
||||
return binds, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parser := NewNiriParser(filepath.Dir(overridePath))
|
||||
parser.currentSource = overridePath
|
||||
|
||||
doc, err := kdl.Parse(strings.NewReader(string(data)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, node := range doc.Nodes {
|
||||
if node.Name.String() != "binds" || node.Children == nil {
|
||||
continue
|
||||
}
|
||||
for _, child := range node.Children {
|
||||
kb := parser.parseKeybindNode(child, "")
|
||||
if kb == nil {
|
||||
continue
|
||||
}
|
||||
keyStr := parser.formatBindKey(kb)
|
||||
binds[keyStr] = &overrideBind{
|
||||
Key: keyStr,
|
||||
Action: n.formatRawAction(kb.Action, kb.Args),
|
||||
Description: kb.Description,
|
||||
Options: n.extractOptions(child),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return binds, nil
|
||||
}
|
||||
|
||||
func (n *NiriProvider) extractOptions(node *document.Node) map[string]any {
|
||||
if node.Properties == nil {
|
||||
return make(map[string]any)
|
||||
}
|
||||
|
||||
opts := make(map[string]any)
|
||||
if val, ok := node.Properties.Get("repeat"); ok {
|
||||
opts["repeat"] = val.String() == "true"
|
||||
}
|
||||
if val, ok := node.Properties.Get("cooldown-ms"); ok {
|
||||
opts["cooldown-ms"] = val.String()
|
||||
}
|
||||
if val, ok := node.Properties.Get("allow-when-locked"); ok {
|
||||
opts["allow-when-locked"] = val.String() == "true"
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func (n *NiriProvider) isRecentWindowsAction(action string) bool {
|
||||
switch action {
|
||||
case "next-window", "previous-window":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NiriProvider) parseSpawnArgs(s string) []string {
|
||||
var args []string
|
||||
var current strings.Builder
|
||||
var inQuote, escaped bool
|
||||
|
||||
for _, r := range s {
|
||||
switch {
|
||||
case escaped:
|
||||
current.WriteRune(r)
|
||||
escaped = false
|
||||
case r == '\\':
|
||||
escaped = true
|
||||
case r == '"':
|
||||
inQuote = !inQuote
|
||||
case r == ' ' && !inQuote:
|
||||
if current.Len() > 0 {
|
||||
args = append(args, current.String())
|
||||
current.Reset()
|
||||
}
|
||||
default:
|
||||
current.WriteRune(r)
|
||||
}
|
||||
}
|
||||
if current.Len() > 0 {
|
||||
args = append(args, current.String())
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func (n *NiriProvider) buildBindNode(bind *overrideBind) *document.Node {
|
||||
node := document.NewNode()
|
||||
node.SetName(bind.Key)
|
||||
|
||||
if bind.Options != nil {
|
||||
if v, ok := bind.Options["repeat"]; ok && v == false {
|
||||
node.AddProperty("repeat", false, "")
|
||||
}
|
||||
if v, ok := bind.Options["cooldown-ms"]; ok {
|
||||
node.AddProperty("cooldown-ms", v, "")
|
||||
}
|
||||
if v, ok := bind.Options["allow-when-locked"]; ok && v == true {
|
||||
node.AddProperty("allow-when-locked", true, "")
|
||||
}
|
||||
}
|
||||
|
||||
if bind.Description != "" {
|
||||
node.AddProperty("hotkey-overlay-title", bind.Description, "")
|
||||
}
|
||||
|
||||
actionNode := n.buildActionNode(bind.Action)
|
||||
node.AddNode(actionNode)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func (n *NiriProvider) buildActionNode(action string) *document.Node {
|
||||
action = strings.TrimSpace(action)
|
||||
node := document.NewNode()
|
||||
|
||||
if !strings.HasPrefix(action, "spawn ") {
|
||||
node.SetName(action)
|
||||
return node
|
||||
}
|
||||
|
||||
node.SetName("spawn")
|
||||
args := n.parseSpawnArgs(strings.TrimPrefix(action, "spawn "))
|
||||
for _, arg := range args {
|
||||
node.AddArgument(arg, "")
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (n *NiriProvider) writeOverrideBinds(binds map[string]*overrideBind) error {
|
||||
overridePath := n.GetOverridePath()
|
||||
content := n.generateBindsContent(binds)
|
||||
|
||||
if err := n.validateBindsContent(content); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(overridePath, []byte(content), 0644)
|
||||
}
|
||||
|
||||
func (n *NiriProvider) generateBindsContent(binds map[string]*overrideBind) string {
|
||||
if len(binds) == 0 {
|
||||
return "binds {}\n"
|
||||
}
|
||||
|
||||
var regularBinds, recentWindowsBinds []*overrideBind
|
||||
for _, bind := range binds {
|
||||
switch {
|
||||
case n.isRecentWindowsAction(bind.Action):
|
||||
recentWindowsBinds = append(recentWindowsBinds, bind)
|
||||
default:
|
||||
regularBinds = append(regularBinds, bind)
|
||||
}
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
|
||||
sb.WriteString("binds {\n")
|
||||
for _, bind := range regularBinds {
|
||||
n.writeBindNode(&sb, bind, " ")
|
||||
}
|
||||
sb.WriteString("}\n")
|
||||
|
||||
if len(recentWindowsBinds) > 0 {
|
||||
sb.WriteString("\nrecent-windows {\n")
|
||||
sb.WriteString(" binds {\n")
|
||||
for _, bind := range recentWindowsBinds {
|
||||
n.writeBindNode(&sb, bind, " ")
|
||||
}
|
||||
sb.WriteString(" }\n")
|
||||
sb.WriteString("}\n")
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (n *NiriProvider) writeBindNode(sb *strings.Builder, bind *overrideBind, indent string) {
|
||||
node := n.buildBindNode(bind)
|
||||
|
||||
sb.WriteString(indent)
|
||||
sb.WriteString(node.Name.String())
|
||||
|
||||
if node.Properties.Exist() {
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(strings.TrimLeft(node.Properties.String(), " "))
|
||||
}
|
||||
|
||||
sb.WriteString(" { ")
|
||||
if len(node.Children) > 0 {
|
||||
child := node.Children[0]
|
||||
sb.WriteString(child.Name.String())
|
||||
for _, arg := range child.Arguments {
|
||||
sb.WriteString(" ")
|
||||
n.writeQuotedArg(sb, arg.ValueString())
|
||||
}
|
||||
}
|
||||
sb.WriteString("; }\n")
|
||||
}
|
||||
|
||||
func (n *NiriProvider) writeQuotedArg(sb *strings.Builder, val string) {
|
||||
sb.WriteString("\"")
|
||||
sb.WriteString(strings.ReplaceAll(val, "\"", "\\\""))
|
||||
sb.WriteString("\"")
|
||||
}
|
||||
|
||||
func (n *NiriProvider) validateBindsContent(content string) error {
|
||||
tmpFile, err := os.CreateTemp("", "dms-binds-*.kdl")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temp file: %w", err)
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
if _, err := tmpFile.WriteString(content); err != nil {
|
||||
tmpFile.Close()
|
||||
return fmt.Errorf("failed to write temp file: %w", err)
|
||||
}
|
||||
tmpFile.Close()
|
||||
|
||||
cmd := exec.Command("niri", "validate", "-c", tmpFile.Name())
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %s", strings.TrimSpace(string(output)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ type NiriKeyBinding struct {
|
||||
Action string
|
||||
Args []string
|
||||
Description string
|
||||
Source string
|
||||
}
|
||||
|
||||
type NiriSection struct {
|
||||
@@ -29,6 +30,8 @@ type NiriParser struct {
|
||||
processedFiles map[string]bool
|
||||
bindMap map[string]*NiriKeyBinding
|
||||
bindOrder []string
|
||||
currentSource string
|
||||
dmsBindsIncluded bool
|
||||
}
|
||||
|
||||
func NewNiriParser(configDir string) *NiriParser {
|
||||
@@ -37,6 +40,7 @@ func NewNiriParser(configDir string) *NiriParser {
|
||||
processedFiles: make(map[string]bool),
|
||||
bindMap: make(map[string]*NiriKeyBinding),
|
||||
bindOrder: []string{},
|
||||
currentSource: "",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +105,7 @@ func (p *NiriParser) parseFile(filePath, sectionName string) (*NiriSection, erro
|
||||
Name: sectionName,
|
||||
}
|
||||
|
||||
p.currentSource = absPath
|
||||
baseDir := filepath.Dir(absPath)
|
||||
p.processNodes(doc.Nodes, section, baseDir)
|
||||
|
||||
@@ -127,14 +132,14 @@ func (p *NiriParser) handleInclude(node *document.Node, section *NiriSection, ba
|
||||
return
|
||||
}
|
||||
|
||||
includePath := node.Arguments[0].String()
|
||||
includePath = strings.Trim(includePath, "\"")
|
||||
includePath := strings.Trim(node.Arguments[0].String(), "\"")
|
||||
if includePath == "dms/binds.kdl" || strings.HasSuffix(includePath, "/dms/binds.kdl") {
|
||||
p.dmsBindsIncluded = true
|
||||
}
|
||||
|
||||
var fullPath string
|
||||
fullPath := filepath.Join(baseDir, includePath)
|
||||
if filepath.IsAbs(includePath) {
|
||||
fullPath = includePath
|
||||
} else {
|
||||
fullPath = filepath.Join(baseDir, includePath)
|
||||
}
|
||||
|
||||
includedSection, err := p.parseFile(fullPath, "")
|
||||
@@ -145,6 +150,10 @@ func (p *NiriParser) handleInclude(node *document.Node, section *NiriSection, ba
|
||||
section.Children = append(section.Children, includedSection.Children...)
|
||||
}
|
||||
|
||||
func (p *NiriParser) HasDMSBindsIncluded() bool {
|
||||
return p.dmsBindsIncluded
|
||||
}
|
||||
|
||||
func (p *NiriParser) handleRecentWindows(node *document.Node, section *NiriSection) {
|
||||
if node.Children == nil {
|
||||
return
|
||||
@@ -172,7 +181,7 @@ func (p *NiriParser) extractBinds(node *document.Node, section *NiriSection, sub
|
||||
}
|
||||
}
|
||||
|
||||
func (p *NiriParser) parseKeybindNode(node *document.Node, subcategory string) *NiriKeyBinding {
|
||||
func (p *NiriParser) parseKeybindNode(node *document.Node, _ string) *NiriKeyBinding {
|
||||
keyCombo := node.Name.String()
|
||||
if keyCombo == "" {
|
||||
return nil
|
||||
@@ -182,19 +191,18 @@ func (p *NiriParser) parseKeybindNode(node *document.Node, subcategory string) *
|
||||
|
||||
var action string
|
||||
var args []string
|
||||
|
||||
if len(node.Children) > 0 {
|
||||
actionNode := node.Children[0]
|
||||
action = actionNode.Name.String()
|
||||
for _, arg := range actionNode.Arguments {
|
||||
args = append(args, strings.Trim(arg.String(), "\""))
|
||||
args = append(args, arg.ValueString())
|
||||
}
|
||||
}
|
||||
|
||||
description := ""
|
||||
var description string
|
||||
if node.Properties != nil {
|
||||
if val, ok := node.Properties.Get("hotkey-overlay-title"); ok {
|
||||
description = strings.Trim(val.String(), "\"")
|
||||
description = val.ValueString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,26 +212,36 @@ func (p *NiriParser) parseKeybindNode(node *document.Node, subcategory string) *
|
||||
Action: action,
|
||||
Args: args,
|
||||
Description: description,
|
||||
Source: p.currentSource,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *NiriParser) parseKeyCombo(combo string) ([]string, string) {
|
||||
parts := strings.Split(combo, "+")
|
||||
if len(parts) == 0 {
|
||||
|
||||
switch len(parts) {
|
||||
case 0:
|
||||
return nil, combo
|
||||
}
|
||||
|
||||
if len(parts) == 1 {
|
||||
case 1:
|
||||
return nil, parts[0]
|
||||
default:
|
||||
return parts[:len(parts)-1], parts[len(parts)-1]
|
||||
}
|
||||
|
||||
mods := parts[:len(parts)-1]
|
||||
key := parts[len(parts)-1]
|
||||
|
||||
return mods, key
|
||||
}
|
||||
|
||||
func ParseNiriKeys(configDir string) (*NiriSection, error) {
|
||||
type NiriParseResult struct {
|
||||
Section *NiriSection
|
||||
DMSBindsIncluded bool
|
||||
}
|
||||
|
||||
func ParseNiriKeys(configDir string) (*NiriParseResult, error) {
|
||||
parser := NewNiriParser(configDir)
|
||||
return parser.Parse()
|
||||
section, err := parser.Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NiriParseResult{
|
||||
Section: section,
|
||||
DMSBindsIncluded: parser.HasDMSBindsIncluded(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -57,20 +57,20 @@ func TestNiriParseBasicBinds(t *testing.T) {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 3 {
|
||||
t.Errorf("Expected 3 keybinds, got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 3 {
|
||||
t.Errorf("Expected 3 keybinds, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
|
||||
foundClose := false
|
||||
foundFullscreen := false
|
||||
foundTerminal := false
|
||||
|
||||
for _, kb := range section.Keybinds {
|
||||
for _, kb := range result.Section.Keybinds {
|
||||
switch kb.Action {
|
||||
case "close-window":
|
||||
foundClose = true
|
||||
@@ -116,19 +116,19 @@ func TestNiriParseRecentWindows(t *testing.T) {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds from recent-windows, got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds from recent-windows, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
|
||||
foundNext := false
|
||||
foundPrev := false
|
||||
|
||||
for _, kb := range section.Keybinds {
|
||||
for _, kb := range result.Section.Keybinds {
|
||||
switch kb.Action {
|
||||
case "next-window":
|
||||
foundNext = true
|
||||
@@ -172,13 +172,13 @@ include "dms/binds.kdl"
|
||||
t.Fatalf("Failed to write include config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds (1 main + 1 include), got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds (1 main + 1 include), got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,17 +209,17 @@ include "dms/binds.kdl"
|
||||
t.Fatalf("Failed to write include config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 1 {
|
||||
t.Errorf("Expected 1 keybind (later overrides earlier), got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 1 {
|
||||
t.Errorf("Expected 1 keybind (later overrides earlier), got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
|
||||
if len(section.Keybinds) > 0 {
|
||||
kb := section.Keybinds[0]
|
||||
if len(result.Section.Keybinds) > 0 {
|
||||
kb := result.Section.Keybinds[0]
|
||||
if kb.Description != "Override Terminal" {
|
||||
t.Errorf("Expected description 'Override Terminal' (from include), got %q", kb.Description)
|
||||
}
|
||||
@@ -253,13 +253,13 @@ include "config.kdl"
|
||||
t.Fatalf("Failed to write other config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed (should handle circular includes): %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds (circular include handled), got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds (circular include handled), got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,13 +276,13 @@ include "nonexistent/file.kdl"
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed (should skip missing include): %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 1 {
|
||||
t.Errorf("Expected 1 keybind (missing include skipped), got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 1 {
|
||||
t.Errorf("Expected 1 keybind (missing include skipped), got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,13 +305,13 @@ input {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 0 {
|
||||
t.Errorf("Expected 0 keybinds, got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 0 {
|
||||
t.Errorf("Expected 0 keybinds, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,18 +352,18 @@ func TestNiriBindOverrideBehavior(t *testing.T) {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 3 {
|
||||
t.Fatalf("Expected 3 unique keybinds, got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 3 {
|
||||
t.Fatalf("Expected 3 unique keybinds, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
|
||||
var modT *NiriKeyBinding
|
||||
for i := range section.Keybinds {
|
||||
kb := §ion.Keybinds[i]
|
||||
for i := range result.Section.Keybinds {
|
||||
kb := &result.Section.Keybinds[i]
|
||||
if len(kb.Mods) == 1 && kb.Mods[0] == "Mod" && kb.Key == "T" {
|
||||
modT = kb
|
||||
break
|
||||
@@ -416,18 +416,18 @@ binds {
|
||||
t.Fatalf("Failed to write include config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 4 {
|
||||
t.Errorf("Expected 4 unique keybinds, got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 4 {
|
||||
t.Errorf("Expected 4 unique keybinds, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
|
||||
bindMap := make(map[string]*NiriKeyBinding)
|
||||
for i := range section.Keybinds {
|
||||
kb := §ion.Keybinds[i]
|
||||
for i := range result.Section.Keybinds {
|
||||
kb := &result.Section.Keybinds[i]
|
||||
key := ""
|
||||
for _, m := range kb.Mods {
|
||||
key += m + "+"
|
||||
@@ -475,16 +475,16 @@ func TestNiriParseMultipleArgs(t *testing.T) {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
section, err := ParseNiriKeys(tmpDir)
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNiriKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(section.Keybinds) != 1 {
|
||||
t.Fatalf("Expected 1 keybind, got %d", len(section.Keybinds))
|
||||
if len(result.Section.Keybinds) != 1 {
|
||||
t.Fatalf("Expected 1 keybind, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
|
||||
kb := section.Keybinds[0]
|
||||
kb := result.Section.Keybinds[0]
|
||||
if len(kb.Args) != 5 {
|
||||
t.Errorf("Expected 5 args, got %d: %v", len(kb.Args), kb.Args)
|
||||
}
|
||||
|
||||
@@ -186,6 +186,144 @@ func TestNiriDefaultConfigDir(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNiriGenerateBindsContent(t *testing.T) {
|
||||
provider := NewNiriProvider("")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
binds map[string]*overrideBind
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "empty binds",
|
||||
binds: map[string]*overrideBind{},
|
||||
expected: "binds {}\n",
|
||||
},
|
||||
{
|
||||
name: "simple spawn bind",
|
||||
binds: map[string]*overrideBind{
|
||||
"Mod+T": {
|
||||
Key: "Mod+T",
|
||||
Action: "spawn kitty",
|
||||
Description: "Open Terminal",
|
||||
},
|
||||
},
|
||||
expected: `binds {
|
||||
Mod+T hotkey-overlay-title="Open Terminal" { spawn "kitty"; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "spawn with multiple args",
|
||||
binds: map[string]*overrideBind{
|
||||
"Mod+Space": {
|
||||
Key: "Mod+Space",
|
||||
Action: `spawn "dms" "ipc" "call" "spotlight" "toggle"`,
|
||||
Description: "Application Launcher",
|
||||
},
|
||||
},
|
||||
expected: `binds {
|
||||
Mod+Space hotkey-overlay-title="Application Launcher" { spawn "dms" "ipc" "call" "spotlight" "toggle"; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "bind with allow-when-locked",
|
||||
binds: map[string]*overrideBind{
|
||||
"XF86AudioMute": {
|
||||
Key: "XF86AudioMute",
|
||||
Action: `spawn "dms" "ipc" "call" "audio" "mute"`,
|
||||
Options: map[string]any{"allow-when-locked": true},
|
||||
},
|
||||
},
|
||||
expected: `binds {
|
||||
XF86AudioMute allow-when-locked=true { spawn "dms" "ipc" "call" "audio" "mute"; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "simple action without args",
|
||||
binds: map[string]*overrideBind{
|
||||
"Mod+Q": {
|
||||
Key: "Mod+Q",
|
||||
Action: "close-window",
|
||||
Description: "Close Window",
|
||||
},
|
||||
},
|
||||
expected: `binds {
|
||||
Mod+Q hotkey-overlay-title="Close Window" { close-window; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "recent-windows action",
|
||||
binds: map[string]*overrideBind{
|
||||
"Alt+Tab": {
|
||||
Key: "Alt+Tab",
|
||||
Action: "next-window",
|
||||
},
|
||||
},
|
||||
expected: `binds {
|
||||
}
|
||||
|
||||
recent-windows {
|
||||
binds {
|
||||
Alt+Tab { next-window; }
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := provider.generateBindsContent(tt.binds)
|
||||
if result != tt.expected {
|
||||
t.Errorf("generateBindsContent() =\n%q\nwant:\n%q", result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNiriGenerateBindsContentRoundTrip(t *testing.T) {
|
||||
provider := NewNiriProvider("")
|
||||
|
||||
binds := map[string]*overrideBind{
|
||||
"Mod+Space": {
|
||||
Key: "Mod+Space",
|
||||
Action: `spawn "dms" "ipc" "call" "spotlight" "toggle"`,
|
||||
Description: "Application Launcher",
|
||||
},
|
||||
"XF86AudioMute": {
|
||||
Key: "XF86AudioMute",
|
||||
Action: `spawn "dms" "ipc" "call" "audio" "mute"`,
|
||||
Options: map[string]any{"allow-when-locked": true},
|
||||
},
|
||||
"Mod+Q": {
|
||||
Key: "Mod+Q",
|
||||
Action: "close-window",
|
||||
Description: "Close Window",
|
||||
},
|
||||
}
|
||||
|
||||
content := provider.generateBindsContent(binds)
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
configFile := filepath.Join(tmpDir, "config.kdl")
|
||||
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to write temp file: %v", err)
|
||||
}
|
||||
|
||||
result, err := ParseNiriKeys(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse generated content: %v\nContent was:\n%s", err, content)
|
||||
}
|
||||
|
||||
if len(result.Section.Keybinds) != 3 {
|
||||
t.Errorf("Expected 3 keybinds after round-trip, got %d", len(result.Section.Keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNiriProviderWithRealWorldConfig(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configFile := filepath.Join(tmpDir, "config.kdl")
|
||||
|
||||
@@ -5,15 +5,24 @@ type Keybind struct {
|
||||
Description string `json:"desc"`
|
||||
Action string `json:"action,omitempty"`
|
||||
Subcategory string `json:"subcat,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
}
|
||||
|
||||
type CheatSheet struct {
|
||||
Title string `json:"title"`
|
||||
Provider string `json:"provider"`
|
||||
Binds map[string][]Keybind `json:"binds"`
|
||||
DMSBindsIncluded bool `json:"dmsBindsIncluded"`
|
||||
}
|
||||
|
||||
type Provider interface {
|
||||
Name() string
|
||||
GetCheatSheet() (*CheatSheet, error)
|
||||
}
|
||||
|
||||
type WritableProvider interface {
|
||||
Provider
|
||||
SetBind(key, action, description string, options map[string]any) error
|
||||
RemoveBind(key string) error
|
||||
GetOverridePath() string
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
dms-git (0.6.2+git5) nightly; urgency=medium
|
||||
dms-git (0.6.2+git2264.c5c5ce84) nightly; urgency=medium
|
||||
|
||||
* Add VERSION file creation to all distro packages
|
||||
* Fix Fedora COPR to pass VERSION/COMMIT to make dist
|
||||
* Fix obs-upload.sh auto-increment to preserve git hash and add ppa suffix
|
||||
* Fix debian/rules to use source at root level (native format)
|
||||
* Remove incorrect dms-git-source subdirectory references
|
||||
* Fix Build-Depends parsing path issue in obs-upload.sh auto-increment
|
||||
* Fix Build-Depends parsing in obs-upload.sh for proper dependency extraction
|
||||
* Build dms binary from source for true git version strings
|
||||
* Match Fedora COPR git build behavior
|
||||
* Now shows proper git version (e.g., v0.6.2-11-g12e91534)
|
||||
* Add golang-go and make as build dependencies
|
||||
|
||||
-- Avenge Media <AvengeMedia.US@gmail.com> Wed, 27 Nov 2025 04:15:00 -0500
|
||||
-- Avenge Media <AvengeMedia.US@gmail.com> Tue, 03 Dec 2025 01:50:00 +0000
|
||||
|
||||
@@ -27,12 +27,11 @@ override_dh_auto_build:
|
||||
# Patch go.mod to use Go 1.24 base version (Debian 13 has 1.23.x, may vary)
|
||||
sed -i 's/^go 1\.24\.[0-9]*/go 1.24/' core/go.mod
|
||||
|
||||
# Extract version info for embedding
|
||||
VERSION="$(UPSTREAM_VERSION)"
|
||||
COMMIT=$$(echo "$(UPSTREAM_VERSION)" | grep -oP '(?<=git)[0-9]+\.[a-f0-9]+' | cut -d. -f2 | head -c8 || echo "unknown")
|
||||
|
||||
# Build dms-cli from source using vendored dependencies
|
||||
# Extract version info and build in single shell to preserve variables
|
||||
# Architecture mapping: Debian amd64/arm64 -> Makefile amd64/arm64
|
||||
VERSION="$(UPSTREAM_VERSION)"; \
|
||||
COMMIT=$$(echo "$(UPSTREAM_VERSION)" | grep -oP '(?<=git)[0-9]+\.[a-f0-9]+' | cut -d. -f2 | head -c8 || echo "unknown"); \
|
||||
if [ "$(DEB_HOST_ARCH)" = "amd64" ]; then \
|
||||
MAKE_ARCH=amd64; \
|
||||
BINARY_NAME=dms-linux-amd64; \
|
||||
@@ -71,6 +70,8 @@ override_dh_auto_install:
|
||||
rm -rf debian/dms-git/usr/share/quickshell/dms/core \
|
||||
debian/dms-git/usr/share/quickshell/dms/distro
|
||||
|
||||
echo "$(UPSTREAM_VERSION)" > debian/dms-git/usr/share/quickshell/dms/VERSION
|
||||
|
||||
override_dh_auto_clean:
|
||||
# Clean up build artifacts
|
||||
rm -f dms
|
||||
|
||||
@@ -98,8 +98,11 @@ chmod +x %{_builddir}/dgop
|
||||
|
||||
%build
|
||||
# Build DMS CLI from source (core/subdirectory)
|
||||
VERSION="%{version}"
|
||||
COMMIT=$(echo "%{version}" | grep -oP '[a-f0-9]{7,}' | head -n1 || echo "unknown")
|
||||
|
||||
cd core
|
||||
make dist
|
||||
make dist VERSION="$VERSION" COMMIT="$COMMIT"
|
||||
|
||||
%install
|
||||
# Install dms-cli binary (built from source)
|
||||
@@ -132,11 +135,10 @@ install -Dm755 %{_builddir}/dgop %{buildroot}%{_bindir}/dgop
|
||||
# Install systemd user service
|
||||
install -Dm644 assets/systemd/dms.service %{buildroot}%{_userunitdir}/dms.service
|
||||
|
||||
# Install desktop file and icon
|
||||
install -Dm644 assets/dms-open.desktop %{buildroot}%{_datadir}/applications/dms-open.desktop
|
||||
install -Dm644 assets/danklogo.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/danklogo.svg
|
||||
|
||||
# Install shell files to shared data location (from quickshell/ subdirectory)
|
||||
# Install shell files to shared data location
|
||||
install -dm755 %{buildroot}%{_datadir}/quickshell/dms
|
||||
cp -r quickshell/* %{buildroot}%{_datadir}/quickshell/dms/
|
||||
|
||||
@@ -146,13 +148,9 @@ rm -f %{buildroot}%{_datadir}/quickshell/dms/.gitignore
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/.github
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/distro
|
||||
|
||||
echo "%{version}" > %{buildroot}%{_datadir}/quickshell/dms/VERSION
|
||||
|
||||
%posttrans
|
||||
# Clean up old installation path from previous versions
|
||||
if [ -d "%{_sysconfdir}/xdg/quickshell/dms" ]; then
|
||||
rmdir "%{_sysconfdir}/xdg/quickshell/dms" 2>/dev/null || true
|
||||
rmdir "%{_sysconfdir}/xdg/quickshell" 2>/dev/null || true
|
||||
rmdir "%{_sysconfdir}/xdg" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Restart DMS for active users after upgrade
|
||||
if [ "$1" -ge 2 ]; then
|
||||
|
||||
@@ -89,6 +89,6 @@ in {
|
||||
}
|
||||
];
|
||||
|
||||
home.packages = common.packages;
|
||||
home.packages = common.packages ++ [dmsPkgs.dankMaterialShell];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.quickshell.package] ++ common.packages;
|
||||
environment.systemPackages = [cfg.quickshell.package dmsPkgs.dankMaterialShell] ++ common.packages;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,6 +103,8 @@ rm -rf %{buildroot}%{_datadir}/quickshell/dms/.github
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/distro
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/core
|
||||
|
||||
echo "%{version}" > %{buildroot}%{_datadir}/quickshell/dms/VERSION
|
||||
|
||||
%posttrans
|
||||
if [ -d "%{_sysconfdir}/xdg/quickshell/dms" ]; then
|
||||
rmdir "%{_sysconfdir}/xdg/quickshell/dms" 2>/dev/null || true
|
||||
|
||||
@@ -77,12 +77,9 @@ rm -rf %{buildroot}%{_datadir}/quickshell/dms/.github
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/distro
|
||||
rm -rf %{buildroot}%{_datadir}/quickshell/dms/core
|
||||
|
||||
echo "%{version}" > %{buildroot}%{_datadir}/quickshell/dms/VERSION
|
||||
|
||||
%posttrans
|
||||
if [ -d "%{_sysconfdir}/xdg/quickshell/dms" ]; then
|
||||
rmdir "%{_sysconfdir}/xdg/quickshell/dms" 2>/dev/null || true
|
||||
rmdir "%{_sysconfdir}/xdg/quickshell" 2>/dev/null || true
|
||||
rmdir "%{_sysconfdir}/xdg" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ "$1" -ge 2 ]; then
|
||||
pkill -USR1 -x dms >/dev/null 2>&1 || true
|
||||
|
||||
@@ -619,10 +619,10 @@ fi
|
||||
|
||||
# Only auto-increment on manual runs (REBUILD_RELEASE set or not in CI), not automated workflows
|
||||
OLD_DSC_FILE=""
|
||||
if [[ -f "$WORK_DIR/$PACKAGE.dsc" ]]; then
|
||||
OLD_DSC_FILE="$WORK_DIR/$PACKAGE.dsc"
|
||||
elif [[ -f "$WORK_DIR/.osc/sources/$PACKAGE.dsc" ]]; then
|
||||
if [[ -f "$WORK_DIR/.osc/sources/$PACKAGE.dsc" ]]; then
|
||||
OLD_DSC_FILE="$WORK_DIR/.osc/sources/$PACKAGE.dsc"
|
||||
elif [[ -f "$WORK_DIR/.osc/$PACKAGE.dsc" ]]; then
|
||||
OLD_DSC_FILE="$WORK_DIR/.osc/$PACKAGE.dsc"
|
||||
fi
|
||||
|
||||
if [[ "$UPLOAD_DEBIAN" == true ]] && [[ "$SOURCE_FORMAT" == *"native"* ]] && [[ -n "$OLD_DSC_FILE" ]]; then
|
||||
@@ -640,19 +640,16 @@ if [[ "$UPLOAD_DEBIAN" == true ]] && [[ "$SOURCE_FORMAT" == *"native"* ]] && [[
|
||||
echo "==> Local/manual run detected (not in CI)"
|
||||
fi
|
||||
|
||||
if [[ -n "$OLD_DSC_VERSION" ]] && [[ "$OLD_DSC_VERSION" == "$CHANGELOG_VERSION" ]] && [[ "$IS_MANUAL" == true ]]; then
|
||||
echo "==> Detected rebuild of same version $CHANGELOG_VERSION, incrementing version"
|
||||
CHANGELOG_BASE=$(echo "$CHANGELOG_VERSION" | sed 's/ppa[0-9]*$//')
|
||||
OLD_DSC_BASE=$(echo "$OLD_DSC_VERSION" | sed 's/ppa[0-9]*$//')
|
||||
|
||||
if [[ -n "$OLD_DSC_VERSION" ]] && [[ "$OLD_DSC_BASE" == "$CHANGELOG_BASE" ]] && [[ "$IS_MANUAL" == true ]]; then
|
||||
echo "==> Detected rebuild of same base version $CHANGELOG_BASE, incrementing version"
|
||||
|
||||
if [[ "$CHANGELOG_VERSION" =~ ^([0-9.]+)\+git$ ]]; then
|
||||
BASE_VERSION="${BASH_REMATCH[1]}"
|
||||
NEW_VERSION="${BASE_VERSION}+git1"
|
||||
echo " Incrementing git number: $CHANGELOG_VERSION -> $NEW_VERSION"
|
||||
elif [[ "$CHANGELOG_VERSION" =~ ^([0-9.]+)\+git([0-9]+)$ ]]; then
|
||||
BASE_VERSION="${BASH_REMATCH[1]}"
|
||||
GIT_NUM="${BASH_REMATCH[2]}"
|
||||
NEW_GIT_NUM=$((GIT_NUM + 1))
|
||||
NEW_VERSION="${BASE_VERSION}+git${NEW_GIT_NUM}"
|
||||
echo " Incrementing git number: $CHANGELOG_VERSION -> $NEW_VERSION"
|
||||
NEW_VERSION="${BASE_VERSION}+gitppa1"
|
||||
echo " Adding PPA number: $CHANGELOG_VERSION -> $NEW_VERSION"
|
||||
elif [[ "$CHANGELOG_VERSION" =~ ^([0-9.]+)ppa([0-9]+)$ ]]; then
|
||||
BASE_VERSION="${BASH_REMATCH[1]}"
|
||||
PPA_NUM="${BASH_REMATCH[2]}"
|
||||
@@ -664,7 +661,14 @@ if [[ "$UPLOAD_DEBIAN" == true ]] && [[ "$SOURCE_FORMAT" == *"native"* ]] && [[
|
||||
GIT_NUM="${BASH_REMATCH[2]}"
|
||||
GIT_HASH="${BASH_REMATCH[3]}"
|
||||
PPA_NUM="${BASH_REMATCH[5]}"
|
||||
if [[ -n "$PPA_NUM" ]]; then
|
||||
|
||||
# Check if old DSC has ppa suffix even if changelog doesn't
|
||||
if [[ -z "$PPA_NUM" ]] && [[ "$OLD_DSC_VERSION" =~ ppa([0-9]+)$ ]]; then
|
||||
OLD_PPA_NUM="${BASH_REMATCH[1]}"
|
||||
NEW_PPA_NUM=$((OLD_PPA_NUM + 1))
|
||||
NEW_VERSION="${BASE_VERSION}+git${GIT_NUM}${GIT_HASH}ppa${NEW_PPA_NUM}"
|
||||
echo " Incrementing PPA number from old DSC: $OLD_DSC_VERSION -> $NEW_VERSION"
|
||||
elif [[ -n "$PPA_NUM" ]]; then
|
||||
NEW_PPA_NUM=$((PPA_NUM + 1))
|
||||
NEW_VERSION="${BASE_VERSION}+git${GIT_NUM}${GIT_HASH}ppa${NEW_PPA_NUM}"
|
||||
echo " Incrementing PPA number: $CHANGELOG_VERSION -> $NEW_VERSION"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
dms-git (0.6.2+git2169.f7f1bbbdppa10) questing; urgency=medium
|
||||
dms-git (0.6.2+git2264.c5c5ce84) questing; urgency=medium
|
||||
|
||||
* Git snapshot (commit 2169: f7f1bbbd)
|
||||
* Add VERSION file creation to all distro packages
|
||||
* Fix Fedora COPR to pass VERSION/COMMIT to make dist
|
||||
* Fix obs-upload.sh auto-increment to preserve git hash and add ppa suffix
|
||||
* Git snapshot (commit 2264: c5c5ce84)
|
||||
|
||||
-- Avenge Media <AvengeMedia.US@gmail.com> Wed, 26 Nov 2025 21:43:12 -0500
|
||||
-- Avenge Media <AvengeMedia.US@gmail.com> Tue, 03 Dec 2025 01:50:00 +0000
|
||||
|
||||
@@ -62,6 +62,14 @@ override_dh_auto_install:
|
||||
install -Dm644 dms-git-repo/assets/danklogo.svg \
|
||||
debian/dms-git/usr/share/icons/hicolor/scalable/apps/danklogo.svg
|
||||
|
||||
# Create DMS Version file
|
||||
@if [ -f dms-git-repo/.dms-version ]; then \
|
||||
. dms-git-repo/.dms-version; \
|
||||
echo "$$VERSION" > debian/dms-git/usr/share/quickshell/dms/VERSION; \
|
||||
else \
|
||||
echo "dev" > debian/dms-git/usr/share/quickshell/dms/VERSION; \
|
||||
fi
|
||||
|
||||
override_dh_auto_clean:
|
||||
# Don't delete dms-git-repo directory - it's part of the source package (native format)
|
||||
# Clean up build artifacts
|
||||
|
||||
@@ -54,6 +54,9 @@ override_dh_auto_install:
|
||||
install -Dm644 DankMaterialShell-$(BASE_VERSION)/assets/danklogo.svg \
|
||||
debian/dms/usr/share/icons/hicolor/scalable/apps/danklogo.svg
|
||||
|
||||
# Create VERSION file for Quickshell (stable release format)
|
||||
echo "$(BASE_VERSION)" > debian/dms/usr/share/quickshell/dms/VERSION
|
||||
|
||||
# Generate and install shell completions (if applicable)
|
||||
# Uncomment if dms supports completion generation
|
||||
# ./dms completion bash > dms.bash
|
||||
|
||||
11
flake.nix
11
flake.nix
@@ -87,6 +87,17 @@
|
||||
installPhase = ''
|
||||
mkdir -p $out/etc/xdg/quickshell
|
||||
cp -r ./ $out/etc/xdg/quickshell/dms
|
||||
|
||||
# Create DMS Version file
|
||||
echo "${version}" > $out/etc/xdg/quickshell/dms/VERSION
|
||||
|
||||
# Install desktop file
|
||||
mkdir -p $out/share/applications
|
||||
cp ${./assets/dms-open.desktop} $out/share/applications/dms-open.desktop
|
||||
|
||||
# Install icon
|
||||
mkdir -p $out/share/icons/hicolor/scalable/apps
|
||||
cp ${./core/assets/danklogo.svg} $out/share/icons/hicolor/scalable/apps/danklogo.svg
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -15,30 +15,97 @@ Singleton {
|
||||
property bool windowsVisible: false
|
||||
property var targetScreen: null
|
||||
property var persistentModal: null
|
||||
property Item currentDirectContent: null
|
||||
|
||||
readonly property bool hasActiveModal: activeModal !== null
|
||||
readonly property bool hasPersistentModal: persistentModal !== null
|
||||
readonly property bool isPersistentModalActive: hasActiveModal && activeModal === persistentModal
|
||||
readonly property bool shouldShowModal: hasActiveModal
|
||||
readonly property bool shouldKeepWindowsAlive: hasPersistentModal
|
||||
readonly property bool shouldKeepWindowsAlive: hasPersistentModal && targetScreen !== null
|
||||
|
||||
onPersistentModalChanged: {
|
||||
if (!persistentModal)
|
||||
if (!persistentModal) {
|
||||
if (!hasActiveModal)
|
||||
targetScreen = null;
|
||||
return;
|
||||
}
|
||||
if (!targetScreen)
|
||||
targetScreen = CompositorService.focusedScreen;
|
||||
cachedModal = persistentModal;
|
||||
cachedModalWidth = Theme.px(persistentModal.modalWidth, dpr);
|
||||
cachedModalHeight = Theme.px(persistentModal.modalHeight, dpr);
|
||||
cachedModalX = calculateX(persistentModal);
|
||||
cachedModalY = calculateY(persistentModal);
|
||||
cachedAnimationDuration = persistentModal.animationDuration ?? Theme.shortDuration;
|
||||
cachedEnterCurve = persistentModal.animationEnterCurve ?? Theme.expressiveCurves.expressiveFastSpatial;
|
||||
cachedExitCurve = persistentModal.animationExitCurve ?? Theme.expressiveCurves.expressiveFastSpatial;
|
||||
cachedScaleCollapsed = persistentModal.animationScaleCollapsed ?? 0.96;
|
||||
if (persistentModal.directContent) {
|
||||
persistentModal.directContent.parent = directContentWrapper;
|
||||
persistentModal.directContent.anchors.fill = directContentWrapper;
|
||||
updateCachedModalProperties(persistentModal);
|
||||
}
|
||||
|
||||
onActiveModalChanged: updateDirectContent()
|
||||
|
||||
function updateCachedModalProperties(modal) {
|
||||
if (!modal)
|
||||
return;
|
||||
cachedModalWidth = Theme.px(modal.modalWidth, dpr);
|
||||
cachedModalHeight = Theme.px(modal.modalHeight, dpr);
|
||||
cachedModalX = calculateX(modal);
|
||||
cachedModalY = calculateY(modal);
|
||||
cachedAnimationDuration = modal.animationDuration ?? Theme.shortDuration;
|
||||
cachedEnterCurve = modal.animationEnterCurve ?? Theme.expressiveCurves.expressiveFastSpatial;
|
||||
cachedExitCurve = modal.animationExitCurve ?? Theme.expressiveCurves.expressiveFastSpatial;
|
||||
cachedScaleCollapsed = modal.animationScaleCollapsed ?? 0.96;
|
||||
}
|
||||
|
||||
function updateDirectContent() {
|
||||
if (currentDirectContent) {
|
||||
currentDirectContent.visible = false;
|
||||
currentDirectContent.parent = null;
|
||||
currentDirectContent = null;
|
||||
}
|
||||
|
||||
if (!activeModal?.directContent)
|
||||
return;
|
||||
|
||||
currentDirectContent = activeModal.directContent;
|
||||
currentDirectContent.parent = directContentWrapper;
|
||||
currentDirectContent.anchors.fill = directContentWrapper;
|
||||
currentDirectContent.visible = true;
|
||||
}
|
||||
|
||||
function isScreenValid(screen) {
|
||||
if (!screen)
|
||||
return false;
|
||||
for (const s of Quickshell.screens) {
|
||||
if (s === screen || s.name === screen.name)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleScreensChanged() {
|
||||
if (!targetScreen)
|
||||
return;
|
||||
if (isScreenValid(targetScreen))
|
||||
return;
|
||||
|
||||
const newScreen = CompositorService.focusedScreen;
|
||||
if (hasActiveModal) {
|
||||
targetScreen = newScreen;
|
||||
if (cachedModal)
|
||||
updateCachedModalProperties(cachedModal);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasPersistentModal) {
|
||||
targetScreen = newScreen;
|
||||
updateCachedModalProperties(persistentModal);
|
||||
return;
|
||||
}
|
||||
|
||||
targetScreen = null;
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Quickshell
|
||||
function onScreensChanged() {
|
||||
root.handleScreensChanged();
|
||||
}
|
||||
}
|
||||
|
||||
readonly property var screen: backgroundWindow.screen
|
||||
readonly property real dpr: screen ? CompositorService.getScreenScale(screen) : 1
|
||||
readonly property real shadowBuffer: 5
|
||||
@@ -88,18 +155,10 @@ Singleton {
|
||||
function showModal(modal) {
|
||||
wantsToHide = false;
|
||||
targetScreen = CompositorService.focusedScreen;
|
||||
|
||||
activeModal = modal;
|
||||
cachedModal = modal;
|
||||
windowsVisible = true;
|
||||
cachedModalWidth = Theme.px(modal.modalWidth, dpr);
|
||||
cachedModalHeight = Theme.px(modal.modalHeight, dpr);
|
||||
cachedModalX = calculateX(modal);
|
||||
cachedModalY = calculateY(modal);
|
||||
cachedAnimationDuration = modal.animationDuration ?? Theme.shortDuration;
|
||||
cachedEnterCurve = modal.animationEnterCurve ?? Theme.expressiveCurves.expressiveFastSpatial;
|
||||
cachedExitCurve = modal.animationExitCurve ?? Theme.expressiveCurves.expressiveFastSpatial;
|
||||
cachedScaleCollapsed = modal.animationScaleCollapsed ?? 0.96;
|
||||
updateCachedModalProperties(modal);
|
||||
|
||||
if (modal.directContent)
|
||||
Qt.callLater(focusDirectContent);
|
||||
@@ -127,18 +186,39 @@ Singleton {
|
||||
|
||||
function hideModalInstant() {
|
||||
wantsToHide = false;
|
||||
const closingModal = activeModal;
|
||||
activeModal = null;
|
||||
|
||||
if (shouldKeepWindowsAlive) {
|
||||
cachedModal = persistentModal;
|
||||
updateCachedModalProperties(persistentModal);
|
||||
} else {
|
||||
windowsVisible = false;
|
||||
targetScreen = null;
|
||||
}
|
||||
|
||||
cleanupInputMethod();
|
||||
if (closingModal && typeof closingModal.onFullyClosed === "function")
|
||||
closingModal.onFullyClosed();
|
||||
}
|
||||
|
||||
function onCloseAnimationFinished() {
|
||||
if (hasActiveModal)
|
||||
return;
|
||||
|
||||
if (cachedModal && typeof cachedModal.onFullyClosed === "function")
|
||||
cachedModal.onFullyClosed();
|
||||
|
||||
cleanupInputMethod();
|
||||
|
||||
if (shouldKeepWindowsAlive) {
|
||||
cachedModal = persistentModal;
|
||||
updateCachedModalProperties(persistentModal);
|
||||
return;
|
||||
}
|
||||
|
||||
windowsVisible = false;
|
||||
targetScreen = null;
|
||||
}
|
||||
|
||||
function cleanupInputMethod() {
|
||||
@@ -300,21 +380,11 @@ Singleton {
|
||||
width: root.modalWidth
|
||||
height: root.modalHeight
|
||||
|
||||
readonly property bool hasDirectContent: root.cachedModal ? (root.cachedModal.directContent !== null && root.cachedModal.directContent !== undefined) : false
|
||||
readonly property bool hasDirectContent: root.currentDirectContent !== null
|
||||
|
||||
opacity: root.shouldShowModal ? 1 : 0
|
||||
scale: root.shouldShowModal ? 1 : root.cachedScaleCollapsed
|
||||
|
||||
onHasDirectContentChanged: {
|
||||
if (!hasDirectContent)
|
||||
return;
|
||||
const dc = root.cachedModal.directContent;
|
||||
if (dc.parent === directContentWrapper)
|
||||
return;
|
||||
dc.parent = directContentWrapper;
|
||||
dc.anchors.fill = directContentWrapper;
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
id: opacityAnimation
|
||||
|
||||
143
quickshell/Common/KeyUtils.js
Normal file
143
quickshell/Common/KeyUtils.js
Normal file
@@ -0,0 +1,143 @@
|
||||
.pragma library
|
||||
|
||||
const KEY_MAP = {
|
||||
16777234: "Left",
|
||||
16777236: "Right",
|
||||
16777235: "Up",
|
||||
16777237: "Down",
|
||||
44: "Comma",
|
||||
46: "Period",
|
||||
47: "Slash",
|
||||
59: "Semicolon",
|
||||
39: "Apostrophe",
|
||||
91: "BracketLeft",
|
||||
93: "BracketRight",
|
||||
92: "Backslash",
|
||||
45: "Minus",
|
||||
61: "Equal",
|
||||
96: "grave",
|
||||
32: "space",
|
||||
16777225: "Print",
|
||||
16777220: "Return",
|
||||
16777221: "Return",
|
||||
16777217: "Tab",
|
||||
16777219: "BackSpace",
|
||||
16777223: "Delete",
|
||||
16777222: "Insert",
|
||||
16777232: "Home",
|
||||
16777233: "End",
|
||||
16777238: "Page_Up",
|
||||
16777239: "Page_Down",
|
||||
16777216: "Escape",
|
||||
16777252: "Caps_Lock",
|
||||
16777253: "Num_Lock",
|
||||
16777254: "Scroll_Lock",
|
||||
16777224: "Pause",
|
||||
16777330: "XF86AudioRaiseVolume",
|
||||
16777328: "XF86AudioLowerVolume",
|
||||
16777329: "XF86AudioMute",
|
||||
16842808: "XF86AudioMicMute",
|
||||
16777344: "XF86AudioPlay",
|
||||
16777345: "XF86AudioPause",
|
||||
16777346: "XF86AudioStop",
|
||||
16777347: "XF86AudioNext",
|
||||
16777348: "XF86AudioPrev",
|
||||
16842792: "XF86AudioRecord",
|
||||
16842798: "XF86MonBrightnessUp",
|
||||
16842797: "XF86MonBrightnessDown",
|
||||
16842800: "XF86KbdBrightnessUp",
|
||||
16842799: "XF86KbdBrightnessDown",
|
||||
16842796: "XF86PowerOff",
|
||||
16842803: "XF86Sleep",
|
||||
16842804: "XF86WakeUp",
|
||||
16842802: "XF86Eject",
|
||||
16842791: "XF86Calculator",
|
||||
16842806: "XF86Explorer",
|
||||
16842794: "XF86HomePage",
|
||||
16777426: "XF86Search",
|
||||
16777427: "XF86Mail",
|
||||
16777442: "XF86Launch0",
|
||||
16777443: "XF86Launch1",
|
||||
33: "1",
|
||||
64: "2",
|
||||
35: "3",
|
||||
36: "4",
|
||||
37: "5",
|
||||
94: "6",
|
||||
38: "7",
|
||||
42: "8",
|
||||
40: "9",
|
||||
41: "0",
|
||||
60: "Comma",
|
||||
62: "Period",
|
||||
63: "Slash",
|
||||
58: "Semicolon",
|
||||
34: "Apostrophe",
|
||||
123: "BracketLeft",
|
||||
125: "BracketRight",
|
||||
124: "Backslash",
|
||||
95: "Minus",
|
||||
43: "Equal",
|
||||
126: "grave"
|
||||
};
|
||||
|
||||
function xkbKeyFromQtKey(qk) {
|
||||
if (qk >= 65 && qk <= 90)
|
||||
return String.fromCharCode(qk);
|
||||
if (qk >= 48 && qk <= 57)
|
||||
return String.fromCharCode(qk);
|
||||
if (qk >= 16777264 && qk <= 16777298)
|
||||
return "F" + (qk - 16777264 + 1);
|
||||
return KEY_MAP[qk] || "";
|
||||
}
|
||||
|
||||
function modsFromEvent(mods) {
|
||||
var result = [];
|
||||
if (mods & 0x04000000)
|
||||
result.push("Ctrl");
|
||||
if (mods & 0x02000000)
|
||||
result.push("Shift");
|
||||
var hasAlt = mods & 0x08000000;
|
||||
var hasSuper = mods & 0x10000000;
|
||||
if (hasAlt && hasSuper) {
|
||||
result.push("Mod");
|
||||
} else {
|
||||
if (hasAlt)
|
||||
result.push("Alt");
|
||||
if (hasSuper)
|
||||
result.push("Super");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function formatToken(mods, key) {
|
||||
return (mods.length ? mods.join("+") + "+" : "") + key;
|
||||
}
|
||||
|
||||
function normalizeKeyCombo(keyCombo) {
|
||||
if (!keyCombo)
|
||||
return "";
|
||||
return keyCombo.toLowerCase().replace(/\bmod\b/g, "super").replace(/\bsuper\b/g, "super");
|
||||
}
|
||||
|
||||
function getConflictingBinds(keyCombo, currentAction, allBinds) {
|
||||
if (!keyCombo)
|
||||
return [];
|
||||
var conflicts = [];
|
||||
var normalizedKey = normalizeKeyCombo(keyCombo);
|
||||
for (var i = 0; i < allBinds.length; i++) {
|
||||
var bind = allBinds[i];
|
||||
if (bind.action === currentAction)
|
||||
continue;
|
||||
for (var k = 0; k < bind.keys.length; k++) {
|
||||
if (normalizeKeyCombo(bind.keys[k].key) === normalizedKey) {
|
||||
conflicts.push({
|
||||
action: bind.action,
|
||||
desc: bind.desc || bind.action
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return conflicts;
|
||||
}
|
||||
323
quickshell/Common/KeybindActions.js
Normal file
323
quickshell/Common/KeybindActions.js
Normal file
@@ -0,0 +1,323 @@
|
||||
.pragma library
|
||||
|
||||
const ACTION_TYPES = [
|
||||
{ id: "dms", label: "DMS Action", icon: "widgets" },
|
||||
{ id: "compositor", label: "Compositor", icon: "desktop_windows" },
|
||||
{ id: "spawn", label: "Run Command", icon: "terminal" },
|
||||
{ id: "shell", label: "Shell Command", icon: "code" }
|
||||
];
|
||||
|
||||
const DMS_ACTIONS = [
|
||||
{ id: "spawn dms ipc call spotlight toggle", label: "App Launcher: Toggle" },
|
||||
{ id: "spawn dms ipc call spotlight open", label: "App Launcher: Open" },
|
||||
{ id: "spawn dms ipc call spotlight close", label: "App Launcher: Close" },
|
||||
{ id: "spawn dms ipc call clipboard toggle", label: "Clipboard: Toggle" },
|
||||
{ id: "spawn dms ipc call clipboard open", label: "Clipboard: Open" },
|
||||
{ id: "spawn dms ipc call clipboard close", label: "Clipboard: Close" },
|
||||
{ id: "spawn dms ipc call notifications toggle", label: "Notifications: Toggle" },
|
||||
{ id: "spawn dms ipc call notifications open", label: "Notifications: Open" },
|
||||
{ id: "spawn dms ipc call notifications close", label: "Notifications: Close" },
|
||||
{ id: "spawn dms ipc call processlist toggle", label: "Task Manager: Toggle" },
|
||||
{ id: "spawn dms ipc call processlist open", label: "Task Manager: Open" },
|
||||
{ id: "spawn dms ipc call processlist close", label: "Task Manager: Close" },
|
||||
{ id: "spawn dms ipc call processlist focusOrToggle", label: "Task Manager: Focus or Toggle" },
|
||||
{ id: "spawn dms ipc call settings toggle", label: "Settings: Toggle" },
|
||||
{ id: "spawn dms ipc call settings open", label: "Settings: Open" },
|
||||
{ id: "spawn dms ipc call settings close", label: "Settings: Close" },
|
||||
{ id: "spawn dms ipc call settings focusOrToggle", label: "Settings: Focus or Toggle" },
|
||||
{ id: "spawn dms ipc call powermenu toggle", label: "Power Menu: Toggle" },
|
||||
{ id: "spawn dms ipc call powermenu open", label: "Power Menu: Open" },
|
||||
{ id: "spawn dms ipc call powermenu close", label: "Power Menu: Close" },
|
||||
{ id: "spawn dms ipc call control-center toggle", label: "Control Center: Toggle" },
|
||||
{ id: "spawn dms ipc call control-center open", label: "Control Center: Open" },
|
||||
{ id: "spawn dms ipc call control-center close", label: "Control Center: Close" },
|
||||
{ id: "spawn dms ipc call notepad toggle", label: "Notepad: Toggle" },
|
||||
{ id: "spawn dms ipc call notepad open", label: "Notepad: Open" },
|
||||
{ id: "spawn dms ipc call notepad close", label: "Notepad: Close" },
|
||||
{ id: "spawn dms ipc call dash toggle", label: "Dashboard: Toggle" },
|
||||
{ id: "spawn dms ipc call dash open overview", label: "Dashboard: Overview" },
|
||||
{ id: "spawn dms ipc call dash open media", label: "Dashboard: Media" },
|
||||
{ id: "spawn dms ipc call dash open weather", label: "Dashboard: Weather" },
|
||||
{ id: "spawn dms ipc call dankdash wallpaper", label: "Wallpaper Browser" },
|
||||
{ id: "spawn dms ipc call file browse wallpaper", label: "File: Browse Wallpaper" },
|
||||
{ id: "spawn dms ipc call file browse profile", label: "File: Browse Profile" },
|
||||
{ id: "spawn dms ipc call keybinds toggle niri", label: "Keybinds Cheatsheet: Toggle", compositor: "niri" },
|
||||
{ id: "spawn dms ipc call keybinds open niri", label: "Keybinds Cheatsheet: Open", compositor: "niri" },
|
||||
{ id: "spawn dms ipc call keybinds close", label: "Keybinds Cheatsheet: Close" },
|
||||
{ id: "spawn dms ipc call lock lock", label: "Lock Screen" },
|
||||
{ id: "spawn dms ipc call lock demo", label: "Lock Screen: Demo" },
|
||||
{ id: "spawn dms ipc call inhibit toggle", label: "Idle Inhibit: Toggle" },
|
||||
{ id: "spawn dms ipc call inhibit enable", label: "Idle Inhibit: Enable" },
|
||||
{ id: "spawn dms ipc call inhibit disable", label: "Idle Inhibit: Disable" },
|
||||
{ id: "spawn dms ipc call audio increment", label: "Volume Up" },
|
||||
{ id: "spawn dms ipc call audio increment 1", label: "Volume Up (1%)" },
|
||||
{ id: "spawn dms ipc call audio increment 5", label: "Volume Up (5%)" },
|
||||
{ id: "spawn dms ipc call audio increment 10", label: "Volume Up (10%)" },
|
||||
{ id: "spawn dms ipc call audio decrement", label: "Volume Down" },
|
||||
{ id: "spawn dms ipc call audio decrement 1", label: "Volume Down (1%)" },
|
||||
{ id: "spawn dms ipc call audio decrement 5", label: "Volume Down (5%)" },
|
||||
{ id: "spawn dms ipc call audio decrement 10", label: "Volume Down (10%)" },
|
||||
{ id: "spawn dms ipc call audio mute", label: "Volume Mute Toggle" },
|
||||
{ id: "spawn dms ipc call audio micmute", label: "Microphone Mute Toggle" },
|
||||
{ id: "spawn dms ipc call brightness increment", label: "Brightness Up" },
|
||||
{ id: "spawn dms ipc call brightness increment 1", label: "Brightness Up (1%)" },
|
||||
{ id: "spawn dms ipc call brightness increment 5", label: "Brightness Up (5%)" },
|
||||
{ id: "spawn dms ipc call brightness increment 10", label: "Brightness Up (10%)" },
|
||||
{ id: "spawn dms ipc call brightness decrement", label: "Brightness Down" },
|
||||
{ id: "spawn dms ipc call brightness decrement 1", label: "Brightness Down (1%)" },
|
||||
{ id: "spawn dms ipc call brightness decrement 5", label: "Brightness Down (5%)" },
|
||||
{ id: "spawn dms ipc call brightness decrement 10", label: "Brightness Down (10%)" },
|
||||
{ id: "spawn dms ipc call brightness toggleExponential", label: "Brightness: Toggle Exponential" },
|
||||
{ id: "spawn dms ipc call theme toggle", label: "Theme: Toggle Light/Dark" },
|
||||
{ id: "spawn dms ipc call theme light", label: "Theme: Light Mode" },
|
||||
{ id: "spawn dms ipc call theme dark", label: "Theme: Dark Mode" },
|
||||
{ id: "spawn dms ipc call night toggle", label: "Night Mode: Toggle" },
|
||||
{ id: "spawn dms ipc call night enable", label: "Night Mode: Enable" },
|
||||
{ id: "spawn dms ipc call night disable", label: "Night Mode: Disable" },
|
||||
{ id: "spawn dms ipc call bar toggle index 0", label: "Bar: Toggle (Primary)" },
|
||||
{ id: "spawn dms ipc call bar reveal index 0", label: "Bar: Reveal (Primary)" },
|
||||
{ id: "spawn dms ipc call bar hide index 0", label: "Bar: Hide (Primary)" },
|
||||
{ id: "spawn dms ipc call bar toggleAutoHide index 0", label: "Bar: Toggle Auto-Hide (Primary)" },
|
||||
{ id: "spawn dms ipc call bar autoHide index 0", label: "Bar: Enable Auto-Hide (Primary)" },
|
||||
{ id: "spawn dms ipc call bar manualHide index 0", label: "Bar: Disable Auto-Hide (Primary)" },
|
||||
{ id: "spawn dms ipc call dock toggle", label: "Dock: Toggle" },
|
||||
{ id: "spawn dms ipc call dock reveal", label: "Dock: Reveal" },
|
||||
{ id: "spawn dms ipc call dock hide", label: "Dock: Hide" },
|
||||
{ id: "spawn dms ipc call dock toggleAutoHide", label: "Dock: Toggle Auto-Hide" },
|
||||
{ id: "spawn dms ipc call dock autoHide", label: "Dock: Enable Auto-Hide" },
|
||||
{ id: "spawn dms ipc call dock manualHide", label: "Dock: Disable Auto-Hide" },
|
||||
{ id: "spawn dms ipc call mpris playPause", label: "Media: Play/Pause" },
|
||||
{ id: "spawn dms ipc call mpris play", label: "Media: Play" },
|
||||
{ id: "spawn dms ipc call mpris pause", label: "Media: Pause" },
|
||||
{ id: "spawn dms ipc call mpris previous", label: "Media: Previous Track" },
|
||||
{ id: "spawn dms ipc call mpris next", label: "Media: Next Track" },
|
||||
{ id: "spawn dms ipc call mpris stop", label: "Media: Stop" },
|
||||
{ id: "spawn dms ipc call niri screenshot", label: "Screenshot: Interactive", compositor: "niri" },
|
||||
{ id: "spawn dms ipc call niri screenshotScreen", label: "Screenshot: Full Screen", compositor: "niri" },
|
||||
{ id: "spawn dms ipc call niri screenshotWindow", label: "Screenshot: Window", compositor: "niri" },
|
||||
{ id: "spawn dms ipc call hypr toggleOverview", label: "Hyprland: Toggle Overview", compositor: "hyprland" },
|
||||
{ id: "spawn dms ipc call hypr openOverview", label: "Hyprland: Open Overview", compositor: "hyprland" },
|
||||
{ id: "spawn dms ipc call hypr closeOverview", label: "Hyprland: Close Overview", compositor: "hyprland" },
|
||||
{ id: "spawn dms ipc call wallpaper next", label: "Wallpaper: Next" },
|
||||
{ id: "spawn dms ipc call wallpaper prev", label: "Wallpaper: Previous" }
|
||||
];
|
||||
|
||||
const COMPOSITOR_ACTIONS = {
|
||||
"Window": [
|
||||
{ id: "close-window", label: "Close Window" },
|
||||
{ id: "fullscreen-window", label: "Fullscreen" },
|
||||
{ id: "maximize-column", label: "Maximize Column" },
|
||||
{ id: "center-column", label: "Center Column" },
|
||||
{ id: "toggle-window-floating", label: "Toggle Floating" },
|
||||
{ id: "switch-preset-column-width", label: "Cycle Column Width" },
|
||||
{ id: "switch-preset-window-height", label: "Cycle Window Height" },
|
||||
{ id: "consume-or-expel-window-left", label: "Consume/Expel Left" },
|
||||
{ id: "consume-or-expel-window-right", label: "Consume/Expel Right" },
|
||||
{ id: "toggle-column-tabbed-display", label: "Toggle Tabbed" }
|
||||
],
|
||||
"Focus": [
|
||||
{ id: "focus-column-left", label: "Focus Left" },
|
||||
{ id: "focus-column-right", label: "Focus Right" },
|
||||
{ id: "focus-window-down", label: "Focus Down" },
|
||||
{ id: "focus-window-up", label: "Focus Up" },
|
||||
{ id: "focus-column-first", label: "Focus First Column" },
|
||||
{ id: "focus-column-last", label: "Focus Last Column" }
|
||||
],
|
||||
"Move": [
|
||||
{ id: "move-column-left", label: "Move Left" },
|
||||
{ id: "move-column-right", label: "Move Right" },
|
||||
{ id: "move-window-down", label: "Move Down" },
|
||||
{ id: "move-window-up", label: "Move Up" },
|
||||
{ id: "move-column-to-first", label: "Move to First" },
|
||||
{ id: "move-column-to-last", label: "Move to Last" }
|
||||
],
|
||||
"Workspace": [
|
||||
{ id: "focus-workspace-down", label: "Focus Workspace Down" },
|
||||
{ id: "focus-workspace-up", label: "Focus Workspace Up" },
|
||||
{ id: "focus-workspace-previous", label: "Focus Previous Workspace" },
|
||||
{ id: "move-column-to-workspace-down", label: "Move to Workspace Down" },
|
||||
{ id: "move-column-to-workspace-up", label: "Move to Workspace Up" },
|
||||
{ id: "move-workspace-down", label: "Move Workspace Down" },
|
||||
{ id: "move-workspace-up", label: "Move Workspace Up" }
|
||||
],
|
||||
"Monitor": [
|
||||
{ id: "focus-monitor-left", label: "Focus Monitor Left" },
|
||||
{ id: "focus-monitor-right", label: "Focus Monitor Right" },
|
||||
{ id: "focus-monitor-down", label: "Focus Monitor Down" },
|
||||
{ id: "focus-monitor-up", label: "Focus Monitor Up" },
|
||||
{ id: "move-column-to-monitor-left", label: "Move to Monitor Left" },
|
||||
{ id: "move-column-to-monitor-right", label: "Move to Monitor Right" },
|
||||
{ id: "move-column-to-monitor-down", label: "Move to Monitor Down" },
|
||||
{ id: "move-column-to-monitor-up", label: "Move to Monitor Up" }
|
||||
],
|
||||
"Screenshot": [
|
||||
{ id: "screenshot", label: "Screenshot (Interactive)" },
|
||||
{ id: "screenshot-screen", label: "Screenshot Screen" },
|
||||
{ id: "screenshot-window", label: "Screenshot Window" }
|
||||
],
|
||||
"System": [
|
||||
{ id: "toggle-overview", label: "Toggle Overview" },
|
||||
{ id: "show-hotkey-overlay", label: "Show Hotkey Overlay" },
|
||||
{ id: "power-off-monitors", label: "Power Off Monitors" },
|
||||
{ id: "power-on-monitors", label: "Power On Monitors" },
|
||||
{ id: "toggle-keyboard-shortcuts-inhibit", label: "Toggle Shortcuts Inhibit" },
|
||||
{ id: "quit", label: "Quit Niri" },
|
||||
{ id: "suspend", label: "Suspend" }
|
||||
],
|
||||
"Alt-Tab": [
|
||||
{ id: "next-window", label: "Next Window" },
|
||||
{ id: "previous-window", label: "Previous Window" }
|
||||
]
|
||||
};
|
||||
|
||||
const CATEGORY_ORDER = ["DMS", "Execute", "Workspace", "Window", "Monitor", "Screenshot", "System", "Overview", "Alt-Tab", "Other"];
|
||||
|
||||
function getActionTypes() {
|
||||
return ACTION_TYPES;
|
||||
}
|
||||
|
||||
function getDmsActions(isNiri, isHyprland) {
|
||||
const result = [];
|
||||
for (let i = 0; i < DMS_ACTIONS.length; i++) {
|
||||
const action = DMS_ACTIONS[i];
|
||||
if (!action.compositor) {
|
||||
result.push(action);
|
||||
continue;
|
||||
}
|
||||
switch (action.compositor) {
|
||||
case "niri":
|
||||
if (isNiri)
|
||||
result.push(action);
|
||||
break;
|
||||
case "hyprland":
|
||||
if (isHyprland)
|
||||
result.push(action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getCompositorCategories() {
|
||||
return Object.keys(COMPOSITOR_ACTIONS);
|
||||
}
|
||||
|
||||
function getCompositorActions(category) {
|
||||
return COMPOSITOR_ACTIONS[category] || [];
|
||||
}
|
||||
|
||||
function getCategoryOrder() {
|
||||
return CATEGORY_ORDER;
|
||||
}
|
||||
|
||||
function findDmsAction(actionId) {
|
||||
for (let i = 0; i < DMS_ACTIONS.length; i++) {
|
||||
if (DMS_ACTIONS[i].id === actionId)
|
||||
return DMS_ACTIONS[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findCompositorAction(actionId) {
|
||||
for (const cat in COMPOSITOR_ACTIONS) {
|
||||
const acts = COMPOSITOR_ACTIONS[cat];
|
||||
for (let i = 0; i < acts.length; i++) {
|
||||
if (acts[i].id === actionId)
|
||||
return acts[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getActionLabel(action) {
|
||||
if (!action)
|
||||
return "";
|
||||
|
||||
const dmsAct = findDmsAction(action);
|
||||
if (dmsAct)
|
||||
return dmsAct.label;
|
||||
|
||||
const compAct = findCompositorAction(action);
|
||||
if (compAct)
|
||||
return compAct.label;
|
||||
|
||||
if (action.startsWith("spawn sh -c "))
|
||||
return action.slice(12).replace(/^["']|["']$/g, "");
|
||||
if (action.startsWith("spawn "))
|
||||
return action.slice(6);
|
||||
return action;
|
||||
}
|
||||
|
||||
function getActionType(action) {
|
||||
if (!action)
|
||||
return "compositor";
|
||||
if (action.startsWith("spawn dms ipc call "))
|
||||
return "dms";
|
||||
if (action.startsWith("spawn sh -c ") || action.startsWith("spawn bash -c "))
|
||||
return "shell";
|
||||
if (action.startsWith("spawn "))
|
||||
return "spawn";
|
||||
return "compositor";
|
||||
}
|
||||
|
||||
function isDmsAction(action) {
|
||||
if (!action)
|
||||
return false;
|
||||
return action.startsWith("spawn dms ipc call ");
|
||||
}
|
||||
|
||||
function isValidAction(action) {
|
||||
if (!action)
|
||||
return false;
|
||||
switch (action) {
|
||||
case "spawn":
|
||||
case "spawn ":
|
||||
case "spawn sh -c \"\"":
|
||||
case "spawn sh -c ''":
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isKnownCompositorAction(action) {
|
||||
if (!action)
|
||||
return false;
|
||||
return findCompositorAction(action) !== null;
|
||||
}
|
||||
|
||||
function buildSpawnAction(command, args) {
|
||||
if (!command)
|
||||
return "";
|
||||
let parts = [command];
|
||||
if (args && args.length > 0)
|
||||
parts = parts.concat(args.filter(function(a) { return a; }));
|
||||
return "spawn " + parts.join(" ");
|
||||
}
|
||||
|
||||
function buildShellAction(shellCmd) {
|
||||
if (!shellCmd)
|
||||
return "";
|
||||
return "spawn sh -c \"" + shellCmd.replace(/"/g, "\\\"") + "\"";
|
||||
}
|
||||
|
||||
function parseSpawnCommand(action) {
|
||||
if (!action || !action.startsWith("spawn "))
|
||||
return { command: "", args: [] };
|
||||
const rest = action.slice(6);
|
||||
const parts = rest.split(" ").filter(function(p) { return p; });
|
||||
return {
|
||||
command: parts[0] || "",
|
||||
args: parts.slice(1)
|
||||
};
|
||||
}
|
||||
|
||||
function parseShellCommand(action) {
|
||||
if (!action)
|
||||
return "";
|
||||
if (!action.startsWith("spawn sh -c "))
|
||||
return "";
|
||||
var content = action.slice(12);
|
||||
if ((content.startsWith('"') && content.endsWith('"')) || (content.startsWith("'") && content.endsWith("'")))
|
||||
content = content.slice(1, -1);
|
||||
return content.replace(/\\"/g, "\"");
|
||||
}
|
||||
@@ -329,14 +329,16 @@ Item {
|
||||
|
||||
IpcHandler {
|
||||
function toggle(provider: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProvider(provider);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
@@ -344,18 +346,18 @@ Item {
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider}`;
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
}
|
||||
|
||||
function toggleWithPath(provider: string, path: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProviderWithPath(provider, path);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
@@ -363,82 +365,86 @@ Item {
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider} (${path})`;
|
||||
}
|
||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||
}
|
||||
|
||||
function open(provider: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProvider(provider);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return `KEYBINDS_OPEN_SUCCESS: ${provider}`;
|
||||
}
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
}
|
||||
|
||||
function openWithPath(provider: string, path: string): string {
|
||||
if (!provider) {
|
||||
if (!provider)
|
||||
return "ERROR: No provider specified";
|
||||
}
|
||||
|
||||
KeybindsService.loadProviderWithPath(provider, path);
|
||||
KeybindsService.currentProvider = provider;
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return `KEYBINDS_OPEN_SUCCESS: ${provider} (${path})`;
|
||||
}
|
||||
return `KEYBINDS_OPEN_FAILED: ${provider}`;
|
||||
}
|
||||
|
||||
function close(): string {
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "KEYBINDS_CLOSE_FAILED";
|
||||
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
return "KEYBINDS_CLOSE_SUCCESS";
|
||||
}
|
||||
return "KEYBINDS_CLOSE_FAILED";
|
||||
}
|
||||
|
||||
target: "keybinds"
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
function openBinds(): string {
|
||||
if (!CompositorService.isHyprland) {
|
||||
if (!CompositorService.isHyprland)
|
||||
return "HYPR_NOT_AVAILABLE";
|
||||
}
|
||||
KeybindsService.loadProvider("hyprland");
|
||||
|
||||
KeybindsService.currentProvider = "hyprland";
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "HYPR_KEYBINDS_OPEN_FAILED";
|
||||
|
||||
root.hyprKeybindsModalLoader.item.open();
|
||||
return "HYPR_KEYBINDS_OPEN_SUCCESS";
|
||||
}
|
||||
return "HYPR_KEYBINDS_OPEN_FAILED";
|
||||
}
|
||||
|
||||
function closeBinds(): string {
|
||||
if (!CompositorService.isHyprland) {
|
||||
if (!CompositorService.isHyprland)
|
||||
return "HYPR_NOT_AVAILABLE";
|
||||
}
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "HYPR_KEYBINDS_CLOSE_FAILED";
|
||||
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
return "HYPR_KEYBINDS_CLOSE_SUCCESS";
|
||||
}
|
||||
return "HYPR_KEYBINDS_CLOSE_FAILED";
|
||||
}
|
||||
|
||||
function toggleBinds(): string {
|
||||
if (!CompositorService.isHyprland) {
|
||||
if (!CompositorService.isHyprland)
|
||||
return "HYPR_NOT_AVAILABLE";
|
||||
}
|
||||
KeybindsService.loadProvider("hyprland");
|
||||
|
||||
KeybindsService.currentProvider = "hyprland";
|
||||
KeybindsService.loadBinds();
|
||||
root.hyprKeybindsModalLoader.active = true;
|
||||
if (root.hyprKeybindsModalLoader.item) {
|
||||
|
||||
if (!root.hyprKeybindsModalLoader.item)
|
||||
return "HYPR_KEYBINDS_TOGGLE_FAILED";
|
||||
|
||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
||||
root.hyprKeybindsModalLoader.item.close();
|
||||
} else {
|
||||
@@ -446,8 +452,6 @@ Item {
|
||||
}
|
||||
return "HYPR_KEYBINDS_TOGGLE_SUCCESS";
|
||||
}
|
||||
return "HYPR_KEYBINDS_TOGGLE_FAILED";
|
||||
}
|
||||
|
||||
function toggleOverview(): string {
|
||||
if (!CompositorService.isHyprland || !root.hyprlandOverviewLoader.item) {
|
||||
@@ -490,60 +494,108 @@ Item {
|
||||
|
||||
function getBarConfig(selector: string, value: string): var {
|
||||
const barSelectors = ["id", "name", "index"];
|
||||
if (!barSelectors.includes(selector)) return { error: "BAR_INVALID_SELECTOR" };
|
||||
if (!barSelectors.includes(selector))
|
||||
return {
|
||||
error: "BAR_INVALID_SELECTOR"
|
||||
};
|
||||
const index = selector === "index" ? Number(value) : SettingsData.barConfigs.findIndex(bar => bar[selector] == value);
|
||||
const barConfig = SettingsData.barConfigs?.[index];
|
||||
if (!barConfig) return { error: "BAR_NOT_FOUND" };
|
||||
return { barConfig };
|
||||
if (!barConfig)
|
||||
return {
|
||||
error: "BAR_NOT_FOUND"
|
||||
};
|
||||
return {
|
||||
barConfig
|
||||
};
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
function reveal(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {visible: true});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
visible: true
|
||||
});
|
||||
return "BAR_SHOW_SUCCESS";
|
||||
}
|
||||
|
||||
function hide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {visible: false});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
visible: false
|
||||
});
|
||||
return "BAR_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggle(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {visible: !barConfig.visible});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
visible: !barConfig.visible
|
||||
});
|
||||
return !barConfig.visible ? "BAR_SHOW_SUCCESS" : "BAR_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function status(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
return barConfig.visible ? "visible" : "hidden";
|
||||
}
|
||||
|
||||
function autoHide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {autoHide: true});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
autoHide: true
|
||||
});
|
||||
return "BAR_AUTO_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function manualHide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {autoHide: false});
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
autoHide: false
|
||||
});
|
||||
return "BAR_MANUAL_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggleAutoHide(selector: string, value: string): string {
|
||||
const { barConfig, error } = getBarConfig(selector, value);
|
||||
if (error) return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {autoHide: !barConfig.autoHide});
|
||||
return barConfig.autoHide ? "BAR_MANUAL_HIDE_SUCCESS": "BAR_AUTO_HIDE_SUCCESS";
|
||||
const {
|
||||
barConfig,
|
||||
error
|
||||
} = getBarConfig(selector, value);
|
||||
if (error)
|
||||
return error;
|
||||
SettingsData.updateBarConfig(barConfig.id, {
|
||||
autoHide: !barConfig.autoHide
|
||||
});
|
||||
return barConfig.autoHide ? "BAR_MANUAL_HIDE_SUCCESS" : "BAR_AUTO_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
target: "bar"
|
||||
@@ -570,20 +622,20 @@ Item {
|
||||
}
|
||||
|
||||
function autoHide(): string {
|
||||
SettingsData.dockAutoHide = true
|
||||
SettingsData.saveSettings()
|
||||
SettingsData.dockAutoHide = true;
|
||||
SettingsData.saveSettings();
|
||||
return "BAR_AUTO_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function manualHide(): string {
|
||||
SettingsData.dockAutoHide = false
|
||||
SettingsData.saveSettings()
|
||||
SettingsData.dockAutoHide = false;
|
||||
SettingsData.saveSettings();
|
||||
return "BAR_MANUAL_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
function toggleAutoHide(): string {
|
||||
SettingsData.dockAutoHide = !SettingsData.dockAutoHide
|
||||
SettingsData.saveSettings()
|
||||
SettingsData.dockAutoHide = !SettingsData.dockAutoHide;
|
||||
SettingsData.saveSettings();
|
||||
return SettingsData.dockAutoHide ? "BAR_AUTO_HIDE_SUCCESS" : "BAR_MANUAL_HIDE_SUCCESS";
|
||||
}
|
||||
|
||||
@@ -612,49 +664,51 @@ Item {
|
||||
}
|
||||
|
||||
function get(key: string): string {
|
||||
return JSON.stringify(SettingsData?.[key])
|
||||
return JSON.stringify(SettingsData?.[key]);
|
||||
}
|
||||
|
||||
function set(key: string, value: string): string {
|
||||
|
||||
if (!(key in SettingsData)) {
|
||||
console.warn("Cannot set property, not found:", key)
|
||||
return "SETTINGS_INVALID_KEY"
|
||||
console.warn("Cannot set property, not found:", key);
|
||||
return "SETTINGS_INVALID_KEY";
|
||||
}
|
||||
|
||||
const typeName = typeof SettingsData?.[key]
|
||||
const typeName = typeof SettingsData?.[key];
|
||||
|
||||
try {
|
||||
switch (typeName) {
|
||||
case "boolean":
|
||||
if (value === "true" || value === "false") value = (value === "true")
|
||||
else throw `${value} is not a Boolean`
|
||||
break
|
||||
if (value === "true" || value === "false")
|
||||
value = (value === "true");
|
||||
else
|
||||
throw `${value} is not a Boolean`;
|
||||
break;
|
||||
case "number":
|
||||
value = Number(value)
|
||||
if (isNaN(value)) throw `${value} is not a Number`
|
||||
break
|
||||
value = Number(value);
|
||||
if (isNaN(value))
|
||||
throw `${value} is not a Number`;
|
||||
break;
|
||||
case "string":
|
||||
value = String(value)
|
||||
break
|
||||
value = String(value);
|
||||
break;
|
||||
case "object":
|
||||
// NOTE: Parsing lists is messed up upstream and not sure if we want
|
||||
// to make sure objects are well structured or just let people set
|
||||
// whatever they want but risking messed up settings.
|
||||
// Objects & Arrays are disabled for now
|
||||
// https://github.com/quickshell-mirror/quickshell/pull/22
|
||||
throw "Setting Objects and Arrays not supported"
|
||||
throw "Setting Objects and Arrays not supported";
|
||||
default:
|
||||
throw "Unsupported type"
|
||||
throw "Unsupported type";
|
||||
}
|
||||
|
||||
console.warn("Setting:", key, value)
|
||||
SettingsData[key] = value
|
||||
SettingsData.saveSettings()
|
||||
return "SETTINGS_SET_SUCCESS"
|
||||
console.warn("Setting:", key, value);
|
||||
SettingsData[key] = value;
|
||||
SettingsData.saveSettings();
|
||||
return "SETTINGS_SET_SUCCESS";
|
||||
} catch (e) {
|
||||
console.warn("Failed to set property:", key, "error:", e)
|
||||
return "SETTINGS_SET_FAILURE"
|
||||
console.warn("Failed to set property:", key, "error:", e);
|
||||
return "SETTINGS_SET_FAILURE";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,14 +97,12 @@ DankModal {
|
||||
const bind = binds[i];
|
||||
if (bind.subcat) {
|
||||
hasSubcats = true;
|
||||
if (!subcats[bind.subcat]) {
|
||||
if (!subcats[bind.subcat])
|
||||
subcats[bind.subcat] = [];
|
||||
}
|
||||
subcats[bind.subcat].push(bind);
|
||||
} else {
|
||||
if (!subcats["_root"]) {
|
||||
if (!subcats["_root"])
|
||||
subcats["_root"] = [];
|
||||
}
|
||||
subcats["_root"].push(bind);
|
||||
}
|
||||
}
|
||||
@@ -121,12 +119,10 @@ DankModal {
|
||||
|
||||
function distributeCategories(cols) {
|
||||
const columns = [];
|
||||
for (let i = 0; i < cols; i++) {
|
||||
for (let i = 0; i < cols; i++)
|
||||
columns.push([]);
|
||||
}
|
||||
for (let i = 0; i < categoryKeys.length; i++) {
|
||||
for (let i = 0; i < categoryKeys.length; i++)
|
||||
columns[i % cols].push(categoryKeys[i]);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,13 +57,32 @@ FocusScope {
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: topBarLoader
|
||||
id: keybindsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 2
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
sourceComponent: KeybindsTab {
|
||||
parentModal: root.parentModal
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
if (active && item) {
|
||||
Qt.callLater(() => item.forceActiveFocus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: topBarLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 3
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
sourceComponent: DankBarTab {
|
||||
parentModal: root.parentModal
|
||||
}
|
||||
@@ -79,7 +98,7 @@ FocusScope {
|
||||
id: widgetsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 3
|
||||
active: root.currentIndex === 4
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -96,7 +115,7 @@ FocusScope {
|
||||
id: dockLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 4
|
||||
active: root.currentIndex === 5
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -115,7 +134,7 @@ FocusScope {
|
||||
id: displaysLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 5
|
||||
active: root.currentIndex === 6
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -132,7 +151,7 @@ FocusScope {
|
||||
id: networkLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 6
|
||||
active: root.currentIndex === 7
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -149,7 +168,7 @@ FocusScope {
|
||||
id: printerLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 7
|
||||
active: root.currentIndex === 8
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -166,7 +185,7 @@ FocusScope {
|
||||
id: launcherLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 8
|
||||
active: root.currentIndex === 9
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -183,7 +202,7 @@ FocusScope {
|
||||
id: themeColorsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 9
|
||||
active: root.currentIndex === 10
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -200,7 +219,7 @@ FocusScope {
|
||||
id: powerLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 10
|
||||
active: root.currentIndex === 11
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -217,7 +236,7 @@ FocusScope {
|
||||
id: pluginsLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 11
|
||||
active: root.currentIndex === 12
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
@@ -236,7 +255,7 @@ FocusScope {
|
||||
id: aboutLoader
|
||||
|
||||
anchors.fill: parent
|
||||
active: root.currentIndex === 12
|
||||
active: root.currentIndex === 13
|
||||
visible: active
|
||||
focus: active
|
||||
|
||||
|
||||
@@ -22,62 +22,68 @@ Rectangle {
|
||||
"icon": "schedule",
|
||||
"tabIndex": 1
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Keyboard Shortcuts"),
|
||||
"icon": "keyboard",
|
||||
"shortcutsOnly": true,
|
||||
"tabIndex": 2
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Dank Bar"),
|
||||
"icon": "toolbar",
|
||||
"tabIndex": 2
|
||||
"tabIndex": 3
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Widgets"),
|
||||
"icon": "widgets",
|
||||
"tabIndex": 3
|
||||
"tabIndex": 4
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Dock"),
|
||||
"icon": "dock_to_bottom",
|
||||
"tabIndex": 4
|
||||
"tabIndex": 5
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Displays"),
|
||||
"icon": "monitor",
|
||||
"tabIndex": 5
|
||||
"tabIndex": 6
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Network"),
|
||||
"icon": "wifi",
|
||||
"dmsOnly": true,
|
||||
"tabIndex": 6
|
||||
"tabIndex": 7
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Printers"),
|
||||
"icon": "print",
|
||||
"cupsOnly": true,
|
||||
"tabIndex": 7
|
||||
"tabIndex": 8
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Launcher"),
|
||||
"icon": "apps",
|
||||
"tabIndex": 8
|
||||
"tabIndex": 9
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Theme & Colors"),
|
||||
"icon": "palette",
|
||||
"tabIndex": 9
|
||||
"tabIndex": 10
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Power & Security"),
|
||||
"icon": "power",
|
||||
"tabIndex": 10
|
||||
"tabIndex": 11
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("Plugins"),
|
||||
"icon": "extension",
|
||||
"tabIndex": 11
|
||||
"tabIndex": 12
|
||||
},
|
||||
{
|
||||
"text": I18n.tr("About"),
|
||||
"icon": "info",
|
||||
"tabIndex": 12
|
||||
"tabIndex": 13
|
||||
}
|
||||
]
|
||||
readonly property var sidebarItems: allSidebarItems.filter(item => {
|
||||
@@ -85,6 +91,8 @@ Rectangle {
|
||||
return false;
|
||||
if (item.cupsOnly && !CupsService.cupsAvailable)
|
||||
return false;
|
||||
if (item.shortcutsOnly && !KeybindsService.available)
|
||||
return false;
|
||||
return true;
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
@@ -22,7 +17,7 @@ DankPopout {
|
||||
listView: null
|
||||
isOpen: notificationHistoryVisible
|
||||
onClose: () => {
|
||||
notificationHistoryVisible = false
|
||||
notificationHistoryVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,61 +28,72 @@ DankPopout {
|
||||
shouldBeVisible: notificationHistoryVisible
|
||||
|
||||
function toggle() {
|
||||
notificationHistoryVisible = !notificationHistoryVisible
|
||||
notificationHistoryVisible = !notificationHistoryVisible;
|
||||
}
|
||||
|
||||
onBackgroundClicked: {
|
||||
notificationHistoryVisible = false
|
||||
notificationHistoryVisible = false;
|
||||
}
|
||||
|
||||
onNotificationHistoryVisibleChanged: {
|
||||
if (notificationHistoryVisible) {
|
||||
open()
|
||||
open();
|
||||
} else {
|
||||
close()
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
function setupKeyboardNavigation() {
|
||||
if (!contentLoader.item)
|
||||
return;
|
||||
contentLoader.item.externalKeyboardController = keyboardController;
|
||||
|
||||
const notificationList = findChild(contentLoader.item, "notificationList");
|
||||
const notificationHeader = findChild(contentLoader.item, "notificationHeader");
|
||||
|
||||
if (notificationList) {
|
||||
keyboardController.listView = notificationList;
|
||||
notificationList.keyboardController = keyboardController;
|
||||
}
|
||||
if (notificationHeader) {
|
||||
notificationHeader.keyboardController = keyboardController;
|
||||
}
|
||||
|
||||
keyboardController.reset();
|
||||
keyboardController.rebuildFlatNavigation();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: contentLoader
|
||||
function onLoaded() {
|
||||
if (root.shouldBeVisible)
|
||||
Qt.callLater(root.setupKeyboardNavigation);
|
||||
}
|
||||
}
|
||||
|
||||
onShouldBeVisibleChanged: {
|
||||
if (shouldBeVisible) {
|
||||
NotificationService.onOverlayOpen()
|
||||
Qt.callLater(() => {
|
||||
if (contentLoader.item) {
|
||||
contentLoader.item.externalKeyboardController = keyboardController
|
||||
|
||||
const notificationList = findChild(contentLoader.item, "notificationList")
|
||||
const notificationHeader = findChild(contentLoader.item, "notificationHeader")
|
||||
|
||||
if (notificationList) {
|
||||
keyboardController.listView = notificationList
|
||||
notificationList.keyboardController = keyboardController
|
||||
}
|
||||
if (notificationHeader) {
|
||||
notificationHeader.keyboardController = keyboardController
|
||||
}
|
||||
|
||||
keyboardController.reset()
|
||||
keyboardController.rebuildFlatNavigation()
|
||||
}
|
||||
})
|
||||
NotificationService.onOverlayOpen();
|
||||
if (contentLoader.item)
|
||||
Qt.callLater(setupKeyboardNavigation);
|
||||
} else {
|
||||
NotificationService.onOverlayClose()
|
||||
keyboardController.keyboardNavigationActive = false
|
||||
NotificationService.onOverlayClose();
|
||||
keyboardController.keyboardNavigationActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
function findChild(parent, objectName) {
|
||||
if (parent.objectName === objectName) {
|
||||
return parent
|
||||
return parent;
|
||||
}
|
||||
for (let i = 0; i < parent.children.length; i++) {
|
||||
const child = parent.children[i]
|
||||
const result = findChild(child, objectName)
|
||||
const child = parent.children[i];
|
||||
const result = findChild(child, objectName);
|
||||
if (result) {
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
content: Component {
|
||||
@@ -98,24 +104,24 @@ DankPopout {
|
||||
property real cachedHeaderHeight: 32
|
||||
|
||||
implicitHeight: {
|
||||
let baseHeight = Theme.spacingL * 2
|
||||
baseHeight += cachedHeaderHeight
|
||||
baseHeight += Theme.spacingM * 2
|
||||
let baseHeight = Theme.spacingL * 2;
|
||||
baseHeight += cachedHeaderHeight;
|
||||
baseHeight += Theme.spacingM * 2;
|
||||
|
||||
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0
|
||||
let listHeight = notificationList.listContentHeight
|
||||
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0;
|
||||
let listHeight = notificationList.listContentHeight;
|
||||
if (NotificationService.groupedNotifications.length === 0) {
|
||||
listHeight = 200
|
||||
listHeight = 200;
|
||||
}
|
||||
|
||||
const maxContentArea = 600
|
||||
const availableListSpace = Math.max(200, maxContentArea - settingsHeight)
|
||||
const maxContentArea = 600;
|
||||
const availableListSpace = Math.max(200, maxContentArea - settingsHeight);
|
||||
|
||||
baseHeight += settingsHeight
|
||||
baseHeight += Math.min(listHeight, availableListSpace)
|
||||
baseHeight += settingsHeight;
|
||||
baseHeight += Math.min(listHeight, availableListSpace);
|
||||
|
||||
const maxHeight = root.screen ? root.screen.height * 0.8 : Screen.height * 0.8
|
||||
return Math.max(300, Math.min(baseHeight, maxHeight))
|
||||
const maxHeight = root.screen ? root.screen.height * 0.8 : Screen.height * 0.8;
|
||||
return Math.max(300, Math.min(baseHeight, maxHeight));
|
||||
}
|
||||
|
||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
@@ -126,16 +132,16 @@ DankPopout {
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.shouldBeVisible) {
|
||||
forceActiveFocus()
|
||||
forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
root.close()
|
||||
event.accepted = true
|
||||
root.close();
|
||||
event.accepted = true;
|
||||
} else if (externalKeyboardController) {
|
||||
externalKeyboardController.handleKey(event)
|
||||
externalKeyboardController.handleKey(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,10 +149,10 @@ DankPopout {
|
||||
function onShouldBeVisibleChanged() {
|
||||
if (root.shouldBeVisible) {
|
||||
Qt.callLater(() => {
|
||||
notificationContent.forceActiveFocus()
|
||||
})
|
||||
notificationContent.forceActiveFocus();
|
||||
});
|
||||
} else {
|
||||
notificationContent.focus = false
|
||||
notificationContent.focus = false;
|
||||
}
|
||||
}
|
||||
target: root
|
||||
|
||||
@@ -165,12 +165,24 @@ Item {
|
||||
text: {
|
||||
if (!SystemUpdateService.shellVersion) return "dms";
|
||||
|
||||
// Git versioning to show ex: "dms v0.6.2-2223"
|
||||
let version = SystemUpdateService.shellVersion;
|
||||
let match = version.match(/^([\d.]+)\+git(\d+)\./);
|
||||
|
||||
// Debian/Ubuntu/OpenSUSE git format: 0.6.2+git2264.c5c5ce84
|
||||
let match = version.match(/^([\d.]+)\+git(\d+)\./);
|
||||
if (match) {
|
||||
return `dms v${match[1]}-${match[2]}`;
|
||||
return `dms (git) v${match[1]}-${match[2]}`;
|
||||
}
|
||||
|
||||
// Fedora COPR git format: 0.0.git.2267.d430cae9
|
||||
match = version.match(/^[\d.]+\.git\.(\d+)\./);
|
||||
if (match) {
|
||||
return `dms (git) v0.6.2-${match[1]}`;
|
||||
}
|
||||
|
||||
// Stable release format: 0.6.2
|
||||
match = version.match(/^([\d.]+)$/);
|
||||
if (match) {
|
||||
return `dms v${match[1]}`;
|
||||
}
|
||||
|
||||
return `dms ${version}`;
|
||||
|
||||
548
quickshell/Modules/Settings/KeybindsTab.qml
Normal file
548
quickshell/Modules/Settings/KeybindsTab.qml
Normal file
@@ -0,0 +1,548 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: keybindsTab
|
||||
|
||||
property var parentModal: null
|
||||
property string selectedCategory: ""
|
||||
property string searchQuery: ""
|
||||
property string expandedKey: ""
|
||||
property bool showingNewBind: false
|
||||
|
||||
property int _lastDataVersion: -1
|
||||
property var _cachedCategories: []
|
||||
property var _filteredBinds: []
|
||||
|
||||
function _updateFiltered() {
|
||||
const allBinds = KeybindsService.getFlatBinds();
|
||||
if (!searchQuery && !selectedCategory) {
|
||||
_filteredBinds = allBinds;
|
||||
return;
|
||||
}
|
||||
|
||||
const q = searchQuery.toLowerCase();
|
||||
const isOverrideFilter = selectedCategory === "__overrides__";
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < allBinds.length; i++) {
|
||||
const group = allBinds[i];
|
||||
if (q) {
|
||||
let keyMatch = false;
|
||||
for (let k = 0; k < group.keys.length; k++) {
|
||||
if (group.keys[k].key.toLowerCase().indexOf(q) !== -1) {
|
||||
keyMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!keyMatch && group.desc.toLowerCase().indexOf(q) === -1 && group.action.toLowerCase().indexOf(q) === -1)
|
||||
continue;
|
||||
}
|
||||
if (isOverrideFilter) {
|
||||
let hasOverride = false;
|
||||
for (let k = 0; k < group.keys.length; k++) {
|
||||
if (group.keys[k].isOverride) {
|
||||
hasOverride = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasOverride)
|
||||
continue;
|
||||
} else if (selectedCategory && group.category !== selectedCategory) {
|
||||
continue;
|
||||
}
|
||||
result.push(group);
|
||||
}
|
||||
_filteredBinds = result;
|
||||
}
|
||||
|
||||
function _updateCategories() {
|
||||
_cachedCategories = ["__overrides__"].concat(KeybindsService.getCategories());
|
||||
}
|
||||
|
||||
function getCategoryLabel(cat) {
|
||||
if (cat === "__overrides__")
|
||||
return I18n.tr("Overrides");
|
||||
return cat;
|
||||
}
|
||||
|
||||
function toggleExpanded(action) {
|
||||
expandedKey = expandedKey === action ? "" : action;
|
||||
}
|
||||
|
||||
function startNewBind() {
|
||||
showingNewBind = true;
|
||||
expandedKey = "";
|
||||
}
|
||||
|
||||
function cancelNewBind() {
|
||||
showingNewBind = false;
|
||||
}
|
||||
|
||||
function saveNewBind(bindData) {
|
||||
KeybindsService.saveBind("", bindData);
|
||||
showingNewBind = false;
|
||||
}
|
||||
|
||||
function scrollToTop() {
|
||||
flickable.contentY = 0;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: searchDebounce
|
||||
interval: 150
|
||||
onTriggered: keybindsTab._updateFiltered()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: KeybindsService
|
||||
function onBindsLoaded() {
|
||||
keybindsTab._lastDataVersion = KeybindsService._dataVersion;
|
||||
keybindsTab._updateCategories();
|
||||
keybindsTab._updateFiltered();
|
||||
}
|
||||
}
|
||||
|
||||
function _ensureNiriProvider() {
|
||||
if (!KeybindsService.available)
|
||||
return;
|
||||
const cachedProvider = KeybindsService.keybinds?.provider;
|
||||
if (cachedProvider !== "niri" || KeybindsService._dataVersion === 0) {
|
||||
KeybindsService.currentProvider = "niri";
|
||||
KeybindsService.loadBinds();
|
||||
return;
|
||||
}
|
||||
if (_lastDataVersion !== KeybindsService._dataVersion) {
|
||||
_lastDataVersion = KeybindsService._dataVersion;
|
||||
_updateCategories();
|
||||
_updateFiltered();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: _ensureNiriProvider()
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible)
|
||||
return;
|
||||
Qt.callLater(scrollToTop);
|
||||
_ensureNiriProvider();
|
||||
}
|
||||
|
||||
DankFlickable {
|
||||
id: flickable
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
contentWidth: width
|
||||
contentHeight: contentColumn.implicitHeight
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: flickable.width
|
||||
spacing: Theme.spacingL
|
||||
topPadding: Theme.spacingXL
|
||||
bottomPadding: Theme.spacingXL
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: headerSection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: headerSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "keyboard"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - Theme.spacingM * 2
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Keyboard Shortcuts")
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Click any shortcut to edit. Changes save to dms/binds.kdl")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankTextField {
|
||||
id: searchField
|
||||
width: parent.width - addButton.width - Theme.spacingM
|
||||
height: 44
|
||||
placeholderText: I18n.tr("Search keybinds...")
|
||||
leftIconName: "search"
|
||||
onTextChanged: {
|
||||
keybindsTab.searchQuery = text;
|
||||
searchDebounce.restart();
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: addButton
|
||||
width: 44
|
||||
height: 44
|
||||
circular: false
|
||||
iconName: "add"
|
||||
iconSize: Theme.iconSize
|
||||
iconColor: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
enabled: !keybindsTab.showingNewBind
|
||||
opacity: enabled ? 1 : 0.5
|
||||
onClicked: keybindsTab.startNewBind()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: warningSection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.error, 0.15)
|
||||
border.color: Theme.withAlpha(Theme.error, 0.3)
|
||||
border.width: 1
|
||||
visible: !KeybindsService.dmsBindsIncluded && !KeybindsService.loading
|
||||
|
||||
Column {
|
||||
id: warningSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "warning"
|
||||
size: Theme.iconSize
|
||||
color: Theme.error
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - 100 - Theme.spacingM * 2
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Binds Include Missing")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.error
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: fixButton
|
||||
width: fixButtonText.implicitWidth + Theme.spacingL * 2
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: KeybindsService.fixing ? Theme.withAlpha(Theme.error, 0.6) : Theme.error
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
id: fixButtonText
|
||||
text: KeybindsService.fixing ? I18n.tr("Fixing...") : I18n.tr("Fix Now")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surface
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: !KeybindsService.fixing
|
||||
onClicked: KeybindsService.fixDmsBindsInclude()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: categorySection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: categorySection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Flow {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Rectangle {
|
||||
width: allChip.implicitWidth + Theme.spacingL
|
||||
height: 32
|
||||
radius: 16
|
||||
color: !keybindsTab.selectedCategory ? Theme.primary : Theme.surfaceContainerHighest
|
||||
|
||||
StyledText {
|
||||
id: allChip
|
||||
text: I18n.tr("All")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: !keybindsTab.selectedCategory ? Theme.primaryText : Theme.surfaceVariantText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
keybindsTab.selectedCategory = "";
|
||||
keybindsTab._updateFiltered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: keybindsTab._cachedCategories
|
||||
|
||||
delegate: Rectangle {
|
||||
required property string modelData
|
||||
required property int index
|
||||
|
||||
width: catText.implicitWidth + Theme.spacingL
|
||||
height: 32
|
||||
radius: 16
|
||||
color: keybindsTab.selectedCategory === modelData ? Theme.primary : (modelData === "__overrides__" ? Theme.withAlpha(Theme.primary, 0.15) : Theme.surfaceContainerHighest)
|
||||
|
||||
StyledText {
|
||||
id: catText
|
||||
text: keybindsTab.getCategoryLabel(modelData)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: keybindsTab.selectedCategory === modelData ? Theme.primaryText : (modelData === "__overrides__" ? Theme.primary : Theme.surfaceVariantText)
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
keybindsTab.selectedCategory = modelData;
|
||||
keybindsTab._updateFiltered();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: newBindSection.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.color: Theme.outlineVariant
|
||||
border.width: 1
|
||||
visible: keybindsTab.showingNewBind
|
||||
|
||||
Column {
|
||||
id: newBindSection
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "add"
|
||||
size: Theme.iconSize
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("New Keybind")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
KeybindItem {
|
||||
width: parent.width
|
||||
isNew: true
|
||||
isExpanded: true
|
||||
bindData: ({
|
||||
keys: [
|
||||
{
|
||||
key: "",
|
||||
source: "dms",
|
||||
isOverride: true
|
||||
}
|
||||
],
|
||||
action: "",
|
||||
desc: ""
|
||||
})
|
||||
panelWindow: keybindsTab.parentModal
|
||||
onSaveBind: (originalKey, newData) => keybindsTab.saveNewBind(newData)
|
||||
onCancelEdit: keybindsTab.cancelNewBind()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
height: bindsListHeader.implicitHeight + Theme.spacingL * 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||
border.width: 0
|
||||
|
||||
Column {
|
||||
id: bindsListHeader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankIcon {
|
||||
name: "list"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: KeybindsService.loading ? I18n.tr("Shortcuts") : I18n.tr("Shortcuts") + " (" + keybindsTab._filteredBinds.length + ")"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
visible: KeybindsService.loading
|
||||
|
||||
DankIcon {
|
||||
id: loadingIcon
|
||||
name: "sync"
|
||||
size: 20
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
RotationAnimation on rotation {
|
||||
from: 0
|
||||
to: 360
|
||||
duration: 1000
|
||||
loops: Animation.Infinite
|
||||
running: KeybindsService.loading
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Loading keybinds...")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("No keybinds found")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
visible: !KeybindsService.loading && keybindsTab._filteredBinds.length === 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: keybindsTab._filteredBinds
|
||||
objectProp: "action"
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
width: parent.width
|
||||
height: bindItem.height
|
||||
|
||||
KeybindItem {
|
||||
id: bindItem
|
||||
width: Math.min(650, parent.width - Theme.spacingL * 2)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
bindData: modelData
|
||||
isExpanded: keybindsTab.expandedKey === modelData.action
|
||||
panelWindow: keybindsTab.parentModal
|
||||
onToggleExpand: keybindsTab.toggleExpanded(modelData.action)
|
||||
onSaveBind: (originalKey, newData) => {
|
||||
KeybindsService.saveBind(originalKey, newData);
|
||||
keybindsTab.expandedKey = modelData.action;
|
||||
}
|
||||
onRemoveBind: key => KeybindsService.removeBind(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
@@ -22,13 +20,13 @@ PanelWindow {
|
||||
target: ToastService
|
||||
function onToastVisibleChanged() {
|
||||
if (ToastService.toastVisible) {
|
||||
shouldBeVisible = true
|
||||
visible = true
|
||||
shouldBeVisible = true;
|
||||
visible = true;
|
||||
} else {
|
||||
// Freeze the width before starting exit animation
|
||||
frozenWidth = toast.width
|
||||
shouldBeVisible = false
|
||||
closeTimer.restart()
|
||||
frozenWidth = toast.width;
|
||||
shouldBeVisible = false;
|
||||
closeTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +36,7 @@ PanelWindow {
|
||||
interval: Theme.mediumDuration + 50
|
||||
onTriggered: {
|
||||
if (!shouldBeVisible) {
|
||||
visible = false
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +63,7 @@ PanelWindow {
|
||||
Connections {
|
||||
target: ToastService
|
||||
function onResetToastState() {
|
||||
toast.expanded = false
|
||||
toast.expanded = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +74,13 @@ PanelWindow {
|
||||
color: {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
return Theme.error
|
||||
return Theme.error;
|
||||
case ToastService.levelWarn:
|
||||
return Theme.warning
|
||||
return Theme.warning;
|
||||
case ToastService.levelInfo:
|
||||
return Theme.surfaceContainer
|
||||
return Theme.surfaceContainer;
|
||||
default:
|
||||
return Theme.surfaceContainer
|
||||
return Theme.surfaceContainer;
|
||||
}
|
||||
}
|
||||
radius: Theme.cornerRadius
|
||||
@@ -109,13 +107,13 @@ PanelWindow {
|
||||
name: {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
return "error"
|
||||
return "error";
|
||||
case ToastService.levelWarn:
|
||||
return "warning"
|
||||
return "warning";
|
||||
case ToastService.levelInfo:
|
||||
return "info"
|
||||
return "info";
|
||||
default:
|
||||
return "info"
|
||||
return "info";
|
||||
}
|
||||
}
|
||||
size: Theme.iconSize
|
||||
@@ -123,9 +121,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
anchors.left: parent.left
|
||||
@@ -140,9 +138,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
font.weight: Font.Medium
|
||||
@@ -163,9 +161,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
buttonSize: Theme.iconSize + 8
|
||||
@@ -175,11 +173,11 @@ PanelWindow {
|
||||
visible: ToastService.hasDetails
|
||||
|
||||
onClicked: {
|
||||
toast.expanded = !toast.expanded
|
||||
toast.expanded = !toast.expanded;
|
||||
if (toast.expanded) {
|
||||
ToastService.stopTimer()
|
||||
ToastService.stopTimer();
|
||||
} else {
|
||||
ToastService.restartTimer()
|
||||
ToastService.restartTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,9 +190,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
buttonSize: Theme.iconSize + 8
|
||||
@@ -203,7 +201,7 @@ PanelWindow {
|
||||
visible: ToastService.hasDetails || ToastService.currentLevel === ToastService.levelError
|
||||
|
||||
onClicked: {
|
||||
ToastService.hideToast()
|
||||
ToastService.hideToast();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,7 +209,7 @@ PanelWindow {
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: detailsColumn.height + Theme.spacingS * 2
|
||||
color: Qt.rgba(0, 0, 0, 0.2)
|
||||
color: ToastService.currentDetails.length > 0 ? Qt.rgba(0, 0, 0, 0.2) : "transparent"
|
||||
radius: Theme.cornerRadius / 2
|
||||
visible: toast.expanded && ToastService.hasDetails
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -232,9 +230,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
visible: ToastService.currentDetails.length > 0
|
||||
@@ -259,9 +257,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
isMonospace: true
|
||||
@@ -281,9 +279,9 @@ PanelWindow {
|
||||
switch (ToastService.currentLevel) {
|
||||
case ToastService.levelError:
|
||||
case ToastService.levelWarn:
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background;
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
buttonSize: Theme.iconSizeSmall + 8
|
||||
@@ -295,9 +293,9 @@ PanelWindow {
|
||||
property bool showTooltip: false
|
||||
|
||||
onClicked: {
|
||||
Quickshell.execDetached(["wl-copy", ToastService.currentCommand])
|
||||
showTooltip = true
|
||||
tooltipTimer.start()
|
||||
Quickshell.execDetached(["wl-copy", ToastService.currentCommand]);
|
||||
showTooltip = true;
|
||||
tooltipTimer.start();
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -346,7 +344,6 @@ PanelWindow {
|
||||
shadowOpacity: 0.3
|
||||
}
|
||||
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
|
||||
@@ -422,7 +422,6 @@ Singleton {
|
||||
isLabwc = false;
|
||||
compositor = "niri";
|
||||
console.info("CompositorService: Detected Niri with socket:", niriSocket);
|
||||
NiriService.generateNiriBinds();
|
||||
NiriService.generateNiriBlurrule();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
@@ -1,76 +1,353 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import "../Common/KeybindActions.js" as Actions
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property string currentProvider: "hyprland"
|
||||
property var keybinds: ({"title": "", "provider": "", "binds": []})
|
||||
readonly property bool shortcutInhibitorAvailable: {
|
||||
try {
|
||||
return typeof ShortcutInhibitor !== "undefined";
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
property bool available: CompositorService.isNiri && shortcutInhibitorAvailable
|
||||
property string currentProvider: "niri"
|
||||
property bool loading: false
|
||||
property bool saving: false
|
||||
property bool fixing: false
|
||||
property string lastError: ""
|
||||
property bool dmsBindsIncluded: true
|
||||
|
||||
property var _rawData: null
|
||||
property var keybinds: ({})
|
||||
property var _allBinds: ({})
|
||||
property var _categories: []
|
||||
property var _flatCache: []
|
||||
property var displayList: []
|
||||
property int _dataVersion: 0
|
||||
|
||||
readonly property var categoryOrder: Actions.getCategoryOrder()
|
||||
readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation))
|
||||
readonly property string dmsBindsPath: configDir + "/niri/dms/binds.kdl"
|
||||
readonly property var actionTypes: Actions.getActionTypes()
|
||||
readonly property var dmsActions: getDmsActions()
|
||||
|
||||
signal bindsLoaded
|
||||
signal bindSaved(string key)
|
||||
signal bindRemoved(string key)
|
||||
signal dmsBindsFixed
|
||||
|
||||
Component.onCompleted: {
|
||||
if (available)
|
||||
Qt.callLater(loadBinds);
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: CompositorService
|
||||
function onCompositorChanged() {
|
||||
if (CompositorService.isNiri)
|
||||
Qt.callLater(root.loadBinds);
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: getKeybinds
|
||||
id: loadProcess
|
||||
running: false
|
||||
command: {
|
||||
let baseCmd = ["dms", "keybinds", "show"]
|
||||
if (root.overridePath) {
|
||||
baseCmd.push("--path")
|
||||
baseCmd.push(root.overridePath)
|
||||
}
|
||||
baseCmd.push(root.currentProvider)
|
||||
return baseCmd
|
||||
}
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
try {
|
||||
root.keybinds = JSON.parse(text)
|
||||
root._rawData = JSON.parse(text);
|
||||
root._processData();
|
||||
} catch (e) {
|
||||
console.error("[KeybindsService] Error parsing keybinds:", e)
|
||||
console.error("[KeybindsService] Failed to parse binds:", e);
|
||||
}
|
||||
root.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
onExited: exitCode => {
|
||||
if (exitCode !== 0) {
|
||||
console.warn("[KeybindsService] Load process failed with code:", exitCode);
|
||||
root.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onExited: (code) => {
|
||||
if (code !== 0 && code !== 15) {
|
||||
console.warn("[KeybindsService] Process exited with code:", code)
|
||||
Process {
|
||||
id: saveProcess
|
||||
running: false
|
||||
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
if (!text.trim())
|
||||
return;
|
||||
root.lastError = text.trim();
|
||||
ToastService.showError(I18n.tr("Failed to save keybind"), "", root.lastError, "keybinds");
|
||||
}
|
||||
}
|
||||
|
||||
onExited: exitCode => {
|
||||
root.saving = false;
|
||||
if (exitCode === 0) {
|
||||
root.lastError = "";
|
||||
root.loadBinds(false);
|
||||
} else {
|
||||
console.error("[KeybindsService] Save failed with code:", exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 500
|
||||
running: true
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
getKeybinds.running = true
|
||||
Process {
|
||||
id: removeProcess
|
||||
running: false
|
||||
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
if (!text.trim())
|
||||
return;
|
||||
root.lastError = text.trim();
|
||||
ToastService.showError(I18n.tr("Failed to remove keybind"), "", root.lastError, "keybinds");
|
||||
}
|
||||
}
|
||||
|
||||
property string overridePath: ""
|
||||
|
||||
function loadProvider(provider) {
|
||||
root.currentProvider = provider
|
||||
reload()
|
||||
onExited: exitCode => {
|
||||
if (exitCode === 0) {
|
||||
root.lastError = "";
|
||||
root.loadBinds(false);
|
||||
} else {
|
||||
console.error("[KeybindsService] Remove failed with code:", exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadProviderWithPath(provider, path) {
|
||||
root.currentProvider = provider
|
||||
root.overridePath = path
|
||||
reload()
|
||||
Process {
|
||||
id: fixProcess
|
||||
running: false
|
||||
|
||||
stderr: StdioCollector {
|
||||
onStreamFinished: {
|
||||
if (!text.trim())
|
||||
return;
|
||||
root.lastError = text.trim();
|
||||
ToastService.showError(I18n.tr("Failed to add binds include"), "", root.lastError, "keybinds");
|
||||
}
|
||||
}
|
||||
|
||||
function reload() {
|
||||
if (getKeybinds.running) {
|
||||
getKeybinds.running = false
|
||||
onExited: exitCode => {
|
||||
root.fixing = false;
|
||||
if (exitCode === 0) {
|
||||
root.lastError = "";
|
||||
root.dmsBindsIncluded = true;
|
||||
root.dmsBindsFixed();
|
||||
ToastService.showSuccess(I18n.tr("Binds include added"), I18n.tr("dms/binds.kdl is now included in config.kdl"), "", "keybinds");
|
||||
Qt.callLater(root.forceReload);
|
||||
} else {
|
||||
console.error("[KeybindsService] Fix failed with code:", exitCode);
|
||||
}
|
||||
Qt.callLater(function() {
|
||||
getKeybinds.running = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function fixDmsBindsInclude() {
|
||||
if (fixing || dmsBindsIncluded)
|
||||
return;
|
||||
fixing = true;
|
||||
const niriConfigDir = configDir + "/niri";
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
const backupPath = `${niriConfigDir}/config.kdl.dmsbackup${timestamp}`;
|
||||
const script = `mkdir -p "${niriConfigDir}/dms" && touch "${niriConfigDir}/dms/binds.kdl" && cp "${niriConfigDir}/config.kdl" "${backupPath}" && echo 'include "dms/binds.kdl"' >> "${niriConfigDir}/config.kdl"`;
|
||||
fixProcess.command = ["sh", "-c", script];
|
||||
fixProcess.running = true;
|
||||
}
|
||||
|
||||
function forceReload() {
|
||||
_allBinds = {};
|
||||
_flatCache = [];
|
||||
_categories = [];
|
||||
loadBinds(true);
|
||||
}
|
||||
|
||||
function loadBinds(showLoading) {
|
||||
if (loading || !available)
|
||||
return;
|
||||
const hasData = Object.keys(_allBinds).length > 0;
|
||||
loading = showLoading !== false && !hasData;
|
||||
loadProcess.command = ["dms", "keybinds", "show", currentProvider];
|
||||
loadProcess.running = true;
|
||||
}
|
||||
|
||||
function _processData() {
|
||||
keybinds = _rawData || {};
|
||||
if (currentProvider === "niri")
|
||||
dmsBindsIncluded = _rawData?.dmsBindsIncluded ?? true;
|
||||
|
||||
if (!_rawData?.binds) {
|
||||
_allBinds = {};
|
||||
_categories = [];
|
||||
_flatCache = [];
|
||||
displayList = [];
|
||||
_dataVersion++;
|
||||
bindsLoaded();
|
||||
return;
|
||||
}
|
||||
|
||||
const processed = {};
|
||||
const bindsData = _rawData.binds;
|
||||
for (const cat in bindsData) {
|
||||
const binds = bindsData[cat];
|
||||
for (let i = 0; i < binds.length; i++) {
|
||||
const bind = binds[i];
|
||||
const targetCat = Actions.isDmsAction(bind.action) ? "DMS" : cat;
|
||||
if (!processed[targetCat])
|
||||
processed[targetCat] = [];
|
||||
processed[targetCat].push(bind);
|
||||
}
|
||||
}
|
||||
|
||||
const sortedCats = Object.keys(processed).sort((a, b) => {
|
||||
const ai = categoryOrder.indexOf(a);
|
||||
const bi = categoryOrder.indexOf(b);
|
||||
return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
|
||||
});
|
||||
|
||||
const grouped = [];
|
||||
const actionMap = {};
|
||||
for (let ci = 0; ci < sortedCats.length; ci++) {
|
||||
const category = sortedCats[ci];
|
||||
const binds = processed[category];
|
||||
if (!binds)
|
||||
continue;
|
||||
for (let i = 0; i < binds.length; i++) {
|
||||
const bind = binds[i];
|
||||
const action = bind.action || "";
|
||||
const keyData = {
|
||||
key: bind.key || "",
|
||||
source: bind.source || "config",
|
||||
isOverride: bind.source === "dms"
|
||||
};
|
||||
if (actionMap[action]) {
|
||||
actionMap[action].keys.push(keyData);
|
||||
if (!actionMap[action].desc && bind.desc)
|
||||
actionMap[action].desc = bind.desc;
|
||||
} else {
|
||||
const entry = {
|
||||
category: category,
|
||||
action: action,
|
||||
desc: bind.desc || "",
|
||||
keys: [keyData]
|
||||
};
|
||||
actionMap[action] = entry;
|
||||
grouped.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const list = [];
|
||||
for (const cat of sortedCats) {
|
||||
list.push({
|
||||
id: "cat:" + cat,
|
||||
type: "category",
|
||||
name: cat
|
||||
});
|
||||
const binds = processed[cat];
|
||||
if (!binds)
|
||||
continue;
|
||||
for (const bind of binds)
|
||||
list.push({
|
||||
id: "bind:" + bind.key,
|
||||
type: "bind",
|
||||
key: bind.key,
|
||||
desc: bind.desc
|
||||
});
|
||||
}
|
||||
|
||||
_allBinds = processed;
|
||||
_categories = sortedCats;
|
||||
_flatCache = grouped;
|
||||
displayList = list;
|
||||
_dataVersion++;
|
||||
bindsLoaded();
|
||||
}
|
||||
|
||||
function getCategories() {
|
||||
return _categories;
|
||||
}
|
||||
|
||||
function getFlatBinds() {
|
||||
return _flatCache;
|
||||
}
|
||||
|
||||
function saveBind(originalKey, bindData) {
|
||||
if (!bindData.key || !Actions.isValidAction(bindData.action))
|
||||
return;
|
||||
saving = true;
|
||||
const cmd = ["dms", "keybinds", "set", currentProvider, bindData.key, bindData.action, "--desc", bindData.desc || ""];
|
||||
if (originalKey && originalKey !== bindData.key)
|
||||
cmd.push("--replace-key", originalKey);
|
||||
saveProcess.command = cmd;
|
||||
saveProcess.running = true;
|
||||
bindSaved(bindData.key);
|
||||
}
|
||||
|
||||
function removeBind(key) {
|
||||
if (!key)
|
||||
return;
|
||||
removeProcess.command = ["dms", "keybinds", "remove", currentProvider, key];
|
||||
removeProcess.running = true;
|
||||
bindRemoved(key);
|
||||
}
|
||||
|
||||
function isDmsAction(action) {
|
||||
return Actions.isDmsAction(action);
|
||||
}
|
||||
|
||||
function isValidAction(action) {
|
||||
return Actions.isValidAction(action);
|
||||
}
|
||||
|
||||
function getActionType(action) {
|
||||
return Actions.getActionType(action);
|
||||
}
|
||||
|
||||
function getActionLabel(action) {
|
||||
return Actions.getActionLabel(action);
|
||||
}
|
||||
|
||||
function getCompositorCategories() {
|
||||
return Actions.getCompositorCategories();
|
||||
}
|
||||
|
||||
function getCompositorActions(category) {
|
||||
return Actions.getCompositorActions(category);
|
||||
}
|
||||
|
||||
function getDmsActions() {
|
||||
return Actions.getDmsActions(CompositorService.isNiri, CompositorService.isHyprland);
|
||||
}
|
||||
|
||||
function buildSpawnAction(command, args) {
|
||||
return Actions.buildSpawnAction(command, args);
|
||||
}
|
||||
|
||||
function buildShellAction(shellCmd) {
|
||||
return Actions.buildShellAction(shellCmd);
|
||||
}
|
||||
|
||||
function parseSpawnCommand(action) {
|
||||
return Actions.parseSpawnCommand(action);
|
||||
}
|
||||
|
||||
function parseShellCommand(action) {
|
||||
return Actions.parseShellCommand(action);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
||||
binds {
|
||||
Mod+Space hotkey-overlay-title="Application Launcher" {
|
||||
spawn "dms" "ipc" "call" "spotlight" "toggle";
|
||||
}
|
||||
|
||||
Mod+V hotkey-overlay-title="Clipboard Manager" {
|
||||
spawn "dms" "ipc" "call" "clipboard" "toggle";
|
||||
}
|
||||
|
||||
Mod+M hotkey-overlay-title="Task Manager" {
|
||||
spawn "dms" "ipc" "call" "processlist" "toggle";
|
||||
}
|
||||
|
||||
Mod+Comma hotkey-overlay-title="Settings" {
|
||||
spawn "dms" "ipc" "call" "settings" "toggle";
|
||||
}
|
||||
|
||||
Mod+N hotkey-overlay-title="Notification Center" {
|
||||
spawn "dms" "ipc" "call" "notifications" "toggle";
|
||||
}
|
||||
|
||||
Mod+Y hotkey-overlay-title="Browse Wallpapers" {
|
||||
spawn "dms" "ipc" "call" "dankdash" "wallpaper";
|
||||
}
|
||||
|
||||
Mod+Shift+N hotkey-overlay-title="Notepad" {
|
||||
spawn "dms" "ipc" "call" "notepad" "toggle";
|
||||
}
|
||||
|
||||
Mod+Alt+L hotkey-overlay-title="Lock Screen" {
|
||||
spawn "dms" "ipc" "call" "lock" "lock";
|
||||
}
|
||||
|
||||
Ctrl+Alt+Delete hotkey-overlay-title="Task Manager" {
|
||||
spawn "dms" "ipc" "call" "processlist" "toggle";
|
||||
}
|
||||
|
||||
// Audio
|
||||
XF86AudioRaiseVolume allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "increment" "3";
|
||||
}
|
||||
XF86AudioLowerVolume allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "decrement" "3";
|
||||
}
|
||||
XF86AudioMute allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "mute";
|
||||
}
|
||||
XF86AudioMicMute allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "audio" "micmute";
|
||||
}
|
||||
|
||||
// BL
|
||||
XF86MonBrightnessUp allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "brightness" "increment" "5" "";
|
||||
}
|
||||
XF86MonBrightnessDown allow-when-locked=true {
|
||||
spawn "dms" "ipc" "call" "brightness" "decrement" "5" "";
|
||||
}
|
||||
}
|
||||
1012
quickshell/Widgets/KeybindItem.qml
Normal file
1012
quickshell/Widgets/KeybindItem.qml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ LANGUAGES = {
|
||||
"tr": "tr.json",
|
||||
"it": "it.json",
|
||||
"pl": "pl.json",
|
||||
"es": "es.json",
|
||||
}
|
||||
|
||||
def error(msg):
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
3071
quickshell/translations/poexports/es.json
Normal file
3071
quickshell/translations/poexports/es.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -74,6 +74,9 @@
|
||||
"Access to system controls and settings": {
|
||||
"Access to system controls and settings": "Accesso ai controlli e alle impostazioni del sistema"
|
||||
},
|
||||
"Action": {
|
||||
"Action": ""
|
||||
},
|
||||
"Actions": {
|
||||
"Actions": "Azioni"
|
||||
},
|
||||
@@ -113,9 +116,15 @@
|
||||
"Add a VPN in NetworkManager": {
|
||||
"Add a VPN in NetworkManager": "Aggiungi una VPN in NetworkManager"
|
||||
},
|
||||
"Add a border around the dock": {
|
||||
"Add a border around the dock": ""
|
||||
},
|
||||
"Adjust the number of columns in grid view mode.": {
|
||||
"Adjust the number of columns in grid view mode.": "Regola il numero di colonne nella modalità di visualizzazione a griglia."
|
||||
},
|
||||
"Afternoon": {
|
||||
"Afternoon": ""
|
||||
},
|
||||
"All": {
|
||||
"All": "Tutto"
|
||||
},
|
||||
@@ -329,6 +338,12 @@
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": {
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "Collega il blocca schermo ai segnali dbus da loginctl.\nDisabilità se stai usando un blocca schermo esterno"
|
||||
},
|
||||
"Binds Include Missing": {
|
||||
"Binds Include Missing": ""
|
||||
},
|
||||
"Binds include added": {
|
||||
"Binds include added": ""
|
||||
},
|
||||
"Bluetooth": {
|
||||
"Bluetooth": ""
|
||||
},
|
||||
@@ -491,6 +506,12 @@
|
||||
"Click Import to add a .ovpn or .conf": {
|
||||
"Click Import to add a .ovpn or .conf": ""
|
||||
},
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": {
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": ""
|
||||
},
|
||||
"Click to capture": {
|
||||
"Click to capture": ""
|
||||
},
|
||||
"Clipboard History": {
|
||||
"Clipboard History": "Cronologia Clipboard"
|
||||
},
|
||||
@@ -524,6 +545,9 @@
|
||||
"Colorful mix of bright contrasting accents.": {
|
||||
"Colorful mix of bright contrasting accents.": "Mix colorato di accenti contrastanti brillanti."
|
||||
},
|
||||
"Command": {
|
||||
"Command": ""
|
||||
},
|
||||
"Command or script to run instead of the standard hibernate procedure": {
|
||||
"Command or script to run instead of the standard hibernate procedure": "Comando e script da eseguire invece della procedura standard di ibernazione"
|
||||
},
|
||||
@@ -575,6 +599,9 @@
|
||||
"Confirm passkey for ": {
|
||||
"Confirm passkey for ": "Conferma passkey per"
|
||||
},
|
||||
"Conflicts with: %1": {
|
||||
"Conflicts with: %1": ""
|
||||
},
|
||||
"Connect": {
|
||||
"Connect": "Connetti"
|
||||
},
|
||||
@@ -686,12 +713,18 @@
|
||||
"DMS out of date": {
|
||||
"DMS out of date": "DMS obsoleta"
|
||||
},
|
||||
"DMS shell actions (launcher, clipboard, etc.)": {
|
||||
"DMS shell actions (launcher, clipboard, etc.)": ""
|
||||
},
|
||||
"DMS_SOCKET not available": {
|
||||
"DMS_SOCKET not available": "DMS_SOCKET non disponibile"
|
||||
},
|
||||
"DWL service not available": {
|
||||
"DWL service not available": "Servizio DWL non disponibile"
|
||||
},
|
||||
"Daily Forecast": {
|
||||
"Daily Forecast": ""
|
||||
},
|
||||
"Daily at:": {
|
||||
"Daily at:": "Giornalmente alle:"
|
||||
},
|
||||
@@ -722,6 +755,15 @@
|
||||
"Date Format": {
|
||||
"Date Format": "Formato Data"
|
||||
},
|
||||
"Dawn (Astronomical Twilight)": {
|
||||
"Dawn (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dawn (Civil Twilight)": {
|
||||
"Dawn (Civil Twilight)": ""
|
||||
},
|
||||
"Dawn (Nautical Twilight)": {
|
||||
"Dawn (Nautical Twilight)": ""
|
||||
},
|
||||
"Day Temperature": {
|
||||
"Day Temperature": "Temperatura Giorno"
|
||||
},
|
||||
@@ -869,6 +911,15 @@
|
||||
"Duration": {
|
||||
"Duration": "Durata"
|
||||
},
|
||||
"Dusk (Astronomical Twilight)": {
|
||||
"Dusk (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dusk (Civil Twighlight)": {
|
||||
"Dusk (Civil Twighlight)": ""
|
||||
},
|
||||
"Dusk (Nautical Twilight)": {
|
||||
"Dusk (Nautical Twilight)": ""
|
||||
},
|
||||
"Dynamic Theming": {
|
||||
"Dynamic Theming": "Tema dinamico"
|
||||
},
|
||||
@@ -890,6 +941,9 @@
|
||||
"Enable GPU Temperature": {
|
||||
"Enable GPU Temperature": "Abilita Temperatura GPU"
|
||||
},
|
||||
"Enable Overview Overlay": {
|
||||
"Enable Overview Overlay": ""
|
||||
},
|
||||
"Enable System Sounds": {
|
||||
"Enable System Sounds": "Abilita Suoni Sistema"
|
||||
},
|
||||
@@ -974,6 +1028,9 @@
|
||||
"Failed to activate configuration": {
|
||||
"Failed to activate configuration": "Impossibile attivare configurazione"
|
||||
},
|
||||
"Failed to add binds include": {
|
||||
"Failed to add binds include": ""
|
||||
},
|
||||
"Failed to add printer to class": {
|
||||
"Failed to add printer to class": ""
|
||||
},
|
||||
@@ -1040,6 +1097,9 @@
|
||||
"Failed to remove device": {
|
||||
"Failed to remove device": "Impossibile rimuovere dispositivo"
|
||||
},
|
||||
"Failed to remove keybind": {
|
||||
"Failed to remove keybind": ""
|
||||
},
|
||||
"Failed to remove printer from class": {
|
||||
"Failed to remove printer from class": ""
|
||||
},
|
||||
@@ -1049,6 +1109,9 @@
|
||||
"Failed to resume printer": {
|
||||
"Failed to resume printer": "Impossibile riavviare la stampante"
|
||||
},
|
||||
"Failed to save keybind": {
|
||||
"Failed to save keybind": ""
|
||||
},
|
||||
"Failed to set profile image": {
|
||||
"Failed to set profile image": "Impossibile impostare immagine profilo"
|
||||
},
|
||||
@@ -1091,6 +1154,12 @@
|
||||
"Find in note...": {
|
||||
"Find in note...": "Trova in note..."
|
||||
},
|
||||
"Fix Now": {
|
||||
"Fix Now": ""
|
||||
},
|
||||
"Fixing...": {
|
||||
"Fixing...": ""
|
||||
},
|
||||
"Focused Window": {
|
||||
"Focused Window": "Finestra a fuoco"
|
||||
},
|
||||
@@ -1115,6 +1184,9 @@
|
||||
"Force terminal applications to always use dark color schemes": {
|
||||
"Force terminal applications to always use dark color schemes": "Forza applicazioni da terminale ad usare schemi di colori scuri"
|
||||
},
|
||||
"Forecast Not Available": {
|
||||
"Forecast Not Available": ""
|
||||
},
|
||||
"Forget": {
|
||||
"Forget": ""
|
||||
},
|
||||
@@ -1157,6 +1229,9 @@
|
||||
"Github:": {
|
||||
"Github:": "Github:"
|
||||
},
|
||||
"Golden Hour": {
|
||||
"Golden Hour": ""
|
||||
},
|
||||
"Good": {
|
||||
"Good": "Buona"
|
||||
},
|
||||
@@ -1226,9 +1301,15 @@
|
||||
"Hold to confirm (%1s)": {
|
||||
"Hold to confirm (%1s)": ""
|
||||
},
|
||||
"Hotkey overlay title (optional)": {
|
||||
"Hotkey overlay title (optional)": ""
|
||||
},
|
||||
"Hour": {
|
||||
"Hour": "Ore"
|
||||
},
|
||||
"Hourly Forecast": {
|
||||
"Hourly Forecast": ""
|
||||
},
|
||||
"How often to change wallpaper": {
|
||||
"How often to change wallpaper": "Quanto spesso cambiare lo sfondo"
|
||||
},
|
||||
@@ -1328,9 +1409,18 @@
|
||||
"Keeping Awake": {
|
||||
"Keeping Awake": "Mantieni Attivo"
|
||||
},
|
||||
"Key": {
|
||||
"Key": ""
|
||||
},
|
||||
"Keyboard Layout Name": {
|
||||
"Keyboard Layout Name": "Nome Layout Tastiera"
|
||||
},
|
||||
"Keyboard Shortcuts": {
|
||||
"Keyboard Shortcuts": ""
|
||||
},
|
||||
"Keys": {
|
||||
"Keys": ""
|
||||
},
|
||||
"Kill Process": {
|
||||
"Kill Process": "Chiusura Processo"
|
||||
},
|
||||
@@ -1385,6 +1475,9 @@
|
||||
"Lively palette with saturated accents.": {
|
||||
"Lively palette with saturated accents.": "Tavolozza vivace con accenti saturi."
|
||||
},
|
||||
"Loading keybinds...": {
|
||||
"Loading keybinds...": ""
|
||||
},
|
||||
"Loading plugins...": {
|
||||
"Loading plugins...": "Caricamento plugins..."
|
||||
},
|
||||
@@ -1550,6 +1643,9 @@
|
||||
"Monospace Font": {
|
||||
"Monospace Font": "Font Monospace"
|
||||
},
|
||||
"Morning": {
|
||||
"Morning": ""
|
||||
},
|
||||
"Mount": {
|
||||
"Mount": "Monta"
|
||||
},
|
||||
@@ -1598,18 +1694,30 @@
|
||||
"New": {
|
||||
"New": "Nuovo"
|
||||
},
|
||||
"New Key": {
|
||||
"New Key": ""
|
||||
},
|
||||
"New Keybind": {
|
||||
"New Keybind": ""
|
||||
},
|
||||
"New Notification": {
|
||||
"New Notification": "Nuova Notifica"
|
||||
},
|
||||
"New York, NY": {
|
||||
"New York, NY": "New York, NY"
|
||||
},
|
||||
"Night": {
|
||||
"Night": ""
|
||||
},
|
||||
"Night Mode": {
|
||||
"Night Mode": "Modalità Notte"
|
||||
},
|
||||
"Night Temperature": {
|
||||
"Night Temperature": "Temperatura Notte"
|
||||
},
|
||||
"Niri compositor actions (focus, move, etc.)": {
|
||||
"Niri compositor actions (focus, move, etc.)": ""
|
||||
},
|
||||
"No": {
|
||||
"No": ""
|
||||
},
|
||||
@@ -1634,9 +1742,15 @@
|
||||
"No Weather Data Available": {
|
||||
"No Weather Data Available": "Nessun Dato Meteo Disponibile"
|
||||
},
|
||||
"No action": {
|
||||
"No action": ""
|
||||
},
|
||||
"No adapters": {
|
||||
"No adapters": ""
|
||||
},
|
||||
"No changes": {
|
||||
"No changes": ""
|
||||
},
|
||||
"No clipboard entries found": {
|
||||
"No clipboard entries found": "Nessun appunto trovato"
|
||||
},
|
||||
@@ -1652,6 +1766,9 @@
|
||||
"No items added yet": {
|
||||
"No items added yet": "Nessun elemento aggiunto ancora"
|
||||
},
|
||||
"No keybinds found": {
|
||||
"No keybinds found": ""
|
||||
},
|
||||
"No matches": {
|
||||
"No matches": "Nessun risultato"
|
||||
},
|
||||
@@ -1751,6 +1868,9 @@
|
||||
"Open search bar to find text": {
|
||||
"Open search bar to find text": "Apri barra di ricerca per cercare testo"
|
||||
},
|
||||
"Open with...": {
|
||||
"Open with...": ""
|
||||
},
|
||||
"Optional description": {
|
||||
"Optional description": ""
|
||||
},
|
||||
@@ -1778,6 +1898,12 @@
|
||||
"Output Tray Missing": {
|
||||
"Output Tray Missing": "Vassoio Uscita Mancante"
|
||||
},
|
||||
"Override": {
|
||||
"Override": ""
|
||||
},
|
||||
"Overrides": {
|
||||
"Overrides": ""
|
||||
},
|
||||
"Overview": {
|
||||
"Overview": "Panoramica"
|
||||
},
|
||||
@@ -1910,9 +2036,15 @@
|
||||
"Power Profile OSD": {
|
||||
"Power Profile OSD": "OSD Profilo Alimentazione"
|
||||
},
|
||||
"Precipitation Chance": {
|
||||
"Precipitation Chance": ""
|
||||
},
|
||||
"Preference": {
|
||||
"Preference": ""
|
||||
},
|
||||
"Press key...": {
|
||||
"Press key...": ""
|
||||
},
|
||||
"Pressure": {
|
||||
"Pressure": "Pressione"
|
||||
},
|
||||
@@ -2009,6 +2141,9 @@
|
||||
"Refresh": {
|
||||
"Refresh": "Aggiorna"
|
||||
},
|
||||
"Refresh Weather": {
|
||||
"Refresh Weather": ""
|
||||
},
|
||||
"Reject Jobs": {
|
||||
"Reject Jobs": ""
|
||||
},
|
||||
@@ -2069,6 +2204,12 @@
|
||||
"Run User Templates": {
|
||||
"Run User Templates": "Esegui Templates Utente"
|
||||
},
|
||||
"Run a program (e.g., firefox, kitty)": {
|
||||
"Run a program (e.g., firefox, kitty)": ""
|
||||
},
|
||||
"Run a shell command (e.g., notify-send)": {
|
||||
"Run a shell command (e.g., notify-send)": ""
|
||||
},
|
||||
"Running Apps": {
|
||||
"Running Apps": "Apps In Esecuzione"
|
||||
},
|
||||
@@ -2111,6 +2252,9 @@
|
||||
"Screen sharing": {
|
||||
"Screen sharing": "Condivisione schermo"
|
||||
},
|
||||
"Scroll song title": {
|
||||
"Scroll song title": ""
|
||||
},
|
||||
"Scrolling": {
|
||||
"Scrolling": "Scorrimento"
|
||||
},
|
||||
@@ -2123,6 +2267,9 @@
|
||||
"Search for a location...": {
|
||||
"Search for a location...": "Cerca una posizione..."
|
||||
},
|
||||
"Search keybinds...": {
|
||||
"Search keybinds...": ""
|
||||
},
|
||||
"Search plugins...": {
|
||||
"Search plugins...": "Cerca plugins..."
|
||||
},
|
||||
@@ -2141,6 +2288,9 @@
|
||||
"Security": {
|
||||
"Security": ""
|
||||
},
|
||||
"Select Application": {
|
||||
"Select Application": ""
|
||||
},
|
||||
"Select Launcher Logo": {
|
||||
"Select Launcher Logo": "Seleziona Logo Launcher"
|
||||
},
|
||||
@@ -2186,6 +2336,9 @@
|
||||
"Select which transitions to include in randomization": {
|
||||
"Select which transitions to include in randomization": "Seleziona quale transizione includere nella randomizzazione"
|
||||
},
|
||||
"Select...": {
|
||||
"Select...": ""
|
||||
},
|
||||
"Selected image file not found.": {
|
||||
"Selected image file not found.": "Immagine selezionata non trovata"
|
||||
},
|
||||
@@ -2201,12 +2354,21 @@
|
||||
"Set different wallpapers for light and dark mode": {
|
||||
"Set different wallpapers for light and dark mode": "Imposta sfondi differenti per modalità chiara e scura"
|
||||
},
|
||||
"Set key and action to save": {
|
||||
"Set key and action to save": ""
|
||||
},
|
||||
"Settings": {
|
||||
"Settings": "Impostazioni"
|
||||
},
|
||||
"Shell": {
|
||||
"Shell": ""
|
||||
},
|
||||
"Shift+Del: Clear All • Esc: Close": {
|
||||
"Shift+Del: Clear All • Esc: Close": "Shift+Del: Elimina tutto • Esc: Chiude"
|
||||
},
|
||||
"Shortcuts": {
|
||||
"Shortcuts": ""
|
||||
},
|
||||
"Show All Tags": {
|
||||
"Show All Tags": "Mostra tutti i tags"
|
||||
},
|
||||
@@ -2381,6 +2543,12 @@
|
||||
"Storage & Disks": {
|
||||
"Storage & Disks": "Archiviazione & Dischi"
|
||||
},
|
||||
"Sunrise": {
|
||||
"Sunrise": ""
|
||||
},
|
||||
"Sunset": {
|
||||
"Sunset": ""
|
||||
},
|
||||
"Support Development": {
|
||||
"Support Development": "Supporta Sviluppo"
|
||||
},
|
||||
@@ -2504,6 +2672,9 @@
|
||||
"Timed Out": {
|
||||
"Timed Out": "Scaduto"
|
||||
},
|
||||
"Title": {
|
||||
"Title": ""
|
||||
},
|
||||
"To Full": {
|
||||
"To Full": "A Pieno"
|
||||
},
|
||||
@@ -2552,6 +2723,9 @@
|
||||
"Turn off monitors after": {
|
||||
"Turn off monitors after": "Spegni monitors dopo"
|
||||
},
|
||||
"Type": {
|
||||
"Type": ""
|
||||
},
|
||||
"Unavailable": {
|
||||
"Unavailable": ""
|
||||
},
|
||||
@@ -2732,6 +2906,9 @@
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": {
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": "Quando abilitato, le applicazioni sono ordinate alfabeticamente. Quando disabilitato, le applicazioni sono ordinate per frequenza d'uso"
|
||||
},
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": {
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": ""
|
||||
},
|
||||
"Wi-Fi Password": {
|
||||
"Wi-Fi Password": ""
|
||||
},
|
||||
@@ -2774,6 +2951,9 @@
|
||||
"Wind": {
|
||||
"Wind": "Vento"
|
||||
},
|
||||
"Wind Speed": {
|
||||
"Wind Speed": ""
|
||||
},
|
||||
"Workspace": {
|
||||
"Workspace": "Workspace"
|
||||
},
|
||||
@@ -2810,6 +2990,18 @@
|
||||
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
|
||||
"Select Wallpaper": "Seleziona Sfondo"
|
||||
},
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
|
||||
},
|
||||
"dms/binds.kdl is now included in config.kdl": {
|
||||
"dms/binds.kdl is now included in config.kdl": ""
|
||||
},
|
||||
"e.g., firefox, kitty --title foo": {
|
||||
"e.g., firefox, kitty --title foo": ""
|
||||
},
|
||||
"e.g., focus-workspace 3, resize-column -10": {
|
||||
"e.g., focus-workspace 3, resize-column -10": ""
|
||||
},
|
||||
"events": {
|
||||
"events": "eventi"
|
||||
},
|
||||
|
||||
@@ -74,6 +74,9 @@
|
||||
"Access to system controls and settings": {
|
||||
"Access to system controls and settings": "システム制御へのアクセスおよび設定"
|
||||
},
|
||||
"Action": {
|
||||
"Action": ""
|
||||
},
|
||||
"Actions": {
|
||||
"Actions": "アクション"
|
||||
},
|
||||
@@ -113,9 +116,15 @@
|
||||
"Add a VPN in NetworkManager": {
|
||||
"Add a VPN in NetworkManager": "NetworkManagerでVPNを追加"
|
||||
},
|
||||
"Add a border around the dock": {
|
||||
"Add a border around the dock": ""
|
||||
},
|
||||
"Adjust the number of columns in grid view mode.": {
|
||||
"Adjust the number of columns in grid view mode.": "グリッド表示モードでの列数を調整します。"
|
||||
},
|
||||
"Afternoon": {
|
||||
"Afternoon": ""
|
||||
},
|
||||
"All": {
|
||||
"All": "全て"
|
||||
},
|
||||
@@ -329,6 +338,12 @@
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": {
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "ロック画面をloginctlからのdbus信号にバインド。外部ロック画面を使用している場合は無効に"
|
||||
},
|
||||
"Binds Include Missing": {
|
||||
"Binds Include Missing": ""
|
||||
},
|
||||
"Binds include added": {
|
||||
"Binds include added": ""
|
||||
},
|
||||
"Bluetooth": {
|
||||
"Bluetooth": ""
|
||||
},
|
||||
@@ -491,6 +506,12 @@
|
||||
"Click Import to add a .ovpn or .conf": {
|
||||
"Click Import to add a .ovpn or .conf": ""
|
||||
},
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": {
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": ""
|
||||
},
|
||||
"Click to capture": {
|
||||
"Click to capture": ""
|
||||
},
|
||||
"Clipboard History": {
|
||||
"Clipboard History": "クリップボード履歴"
|
||||
},
|
||||
@@ -524,6 +545,9 @@
|
||||
"Colorful mix of bright contrasting accents.": {
|
||||
"Colorful mix of bright contrasting accents.": "明るいコントラストのアクセントのカラフルなミックス。"
|
||||
},
|
||||
"Command": {
|
||||
"Command": ""
|
||||
},
|
||||
"Command or script to run instead of the standard hibernate procedure": {
|
||||
"Command or script to run instead of the standard hibernate procedure": "標準の休止状態手順の代わりにコマンドまたはスクリプトで実行"
|
||||
},
|
||||
@@ -575,6 +599,9 @@
|
||||
"Confirm passkey for ": {
|
||||
"Confirm passkey for ": "パスキーを確認 "
|
||||
},
|
||||
"Conflicts with: %1": {
|
||||
"Conflicts with: %1": ""
|
||||
},
|
||||
"Connect": {
|
||||
"Connect": "接続"
|
||||
},
|
||||
@@ -686,12 +713,18 @@
|
||||
"DMS out of date": {
|
||||
"DMS out of date": "DMSに更新があります"
|
||||
},
|
||||
"DMS shell actions (launcher, clipboard, etc.)": {
|
||||
"DMS shell actions (launcher, clipboard, etc.)": ""
|
||||
},
|
||||
"DMS_SOCKET not available": {
|
||||
"DMS_SOCKET not available": "DMS_SOCKETが利用できません"
|
||||
},
|
||||
"DWL service not available": {
|
||||
"DWL service not available": "DWLサービスが利用できません"
|
||||
},
|
||||
"Daily Forecast": {
|
||||
"Daily Forecast": ""
|
||||
},
|
||||
"Daily at:": {
|
||||
"Daily at:": "毎日:"
|
||||
},
|
||||
@@ -722,6 +755,15 @@
|
||||
"Date Format": {
|
||||
"Date Format": "日付形式"
|
||||
},
|
||||
"Dawn (Astronomical Twilight)": {
|
||||
"Dawn (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dawn (Civil Twilight)": {
|
||||
"Dawn (Civil Twilight)": ""
|
||||
},
|
||||
"Dawn (Nautical Twilight)": {
|
||||
"Dawn (Nautical Twilight)": ""
|
||||
},
|
||||
"Day Temperature": {
|
||||
"Day Temperature": "昼間の温度"
|
||||
},
|
||||
@@ -869,6 +911,15 @@
|
||||
"Duration": {
|
||||
"Duration": "期間"
|
||||
},
|
||||
"Dusk (Astronomical Twilight)": {
|
||||
"Dusk (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dusk (Civil Twighlight)": {
|
||||
"Dusk (Civil Twighlight)": ""
|
||||
},
|
||||
"Dusk (Nautical Twilight)": {
|
||||
"Dusk (Nautical Twilight)": ""
|
||||
},
|
||||
"Dynamic Theming": {
|
||||
"Dynamic Theming": "ダイナミックテーマ"
|
||||
},
|
||||
@@ -890,6 +941,9 @@
|
||||
"Enable GPU Temperature": {
|
||||
"Enable GPU Temperature": "GPU温度を有効にする"
|
||||
},
|
||||
"Enable Overview Overlay": {
|
||||
"Enable Overview Overlay": ""
|
||||
},
|
||||
"Enable System Sounds": {
|
||||
"Enable System Sounds": "システムサウンドを有効に"
|
||||
},
|
||||
@@ -974,6 +1028,9 @@
|
||||
"Failed to activate configuration": {
|
||||
"Failed to activate configuration": "設定が適用できませんでした"
|
||||
},
|
||||
"Failed to add binds include": {
|
||||
"Failed to add binds include": ""
|
||||
},
|
||||
"Failed to add printer to class": {
|
||||
"Failed to add printer to class": ""
|
||||
},
|
||||
@@ -1040,6 +1097,9 @@
|
||||
"Failed to remove device": {
|
||||
"Failed to remove device": "デバイスの削除に失敗しました"
|
||||
},
|
||||
"Failed to remove keybind": {
|
||||
"Failed to remove keybind": ""
|
||||
},
|
||||
"Failed to remove printer from class": {
|
||||
"Failed to remove printer from class": ""
|
||||
},
|
||||
@@ -1049,6 +1109,9 @@
|
||||
"Failed to resume printer": {
|
||||
"Failed to resume printer": "プリンタの再開に失敗しました"
|
||||
},
|
||||
"Failed to save keybind": {
|
||||
"Failed to save keybind": ""
|
||||
},
|
||||
"Failed to set profile image": {
|
||||
"Failed to set profile image": "プロフィール画像の設定に失敗しました"
|
||||
},
|
||||
@@ -1091,6 +1154,12 @@
|
||||
"Find in note...": {
|
||||
"Find in note...": "メモで検索..."
|
||||
},
|
||||
"Fix Now": {
|
||||
"Fix Now": ""
|
||||
},
|
||||
"Fixing...": {
|
||||
"Fixing...": ""
|
||||
},
|
||||
"Focused Window": {
|
||||
"Focused Window": "フォーカスされたウィンドウ"
|
||||
},
|
||||
@@ -1115,6 +1184,9 @@
|
||||
"Force terminal applications to always use dark color schemes": {
|
||||
"Force terminal applications to always use dark color schemes": "端末アプリで常に暗い配色を強制使用"
|
||||
},
|
||||
"Forecast Not Available": {
|
||||
"Forecast Not Available": ""
|
||||
},
|
||||
"Forget": {
|
||||
"Forget": ""
|
||||
},
|
||||
@@ -1157,6 +1229,9 @@
|
||||
"Github:": {
|
||||
"Github:": "GitHub:"
|
||||
},
|
||||
"Golden Hour": {
|
||||
"Golden Hour": ""
|
||||
},
|
||||
"Good": {
|
||||
"Good": "良い"
|
||||
},
|
||||
@@ -1226,9 +1301,15 @@
|
||||
"Hold to confirm (%1s)": {
|
||||
"Hold to confirm (%1s)": ""
|
||||
},
|
||||
"Hotkey overlay title (optional)": {
|
||||
"Hotkey overlay title (optional)": ""
|
||||
},
|
||||
"Hour": {
|
||||
"Hour": "時間"
|
||||
},
|
||||
"Hourly Forecast": {
|
||||
"Hourly Forecast": ""
|
||||
},
|
||||
"How often to change wallpaper": {
|
||||
"How often to change wallpaper": "壁紙を切り替える間隔"
|
||||
},
|
||||
@@ -1328,9 +1409,18 @@
|
||||
"Keeping Awake": {
|
||||
"Keeping Awake": "活動状態を維持"
|
||||
},
|
||||
"Key": {
|
||||
"Key": ""
|
||||
},
|
||||
"Keyboard Layout Name": {
|
||||
"Keyboard Layout Name": "キーボードレイアウト名"
|
||||
},
|
||||
"Keyboard Shortcuts": {
|
||||
"Keyboard Shortcuts": ""
|
||||
},
|
||||
"Keys": {
|
||||
"Keys": ""
|
||||
},
|
||||
"Kill Process": {
|
||||
"Kill Process": "プロセスを強制終了"
|
||||
},
|
||||
@@ -1385,6 +1475,9 @@
|
||||
"Lively palette with saturated accents.": {
|
||||
"Lively palette with saturated accents.": "彩度の高いアクセントを備えた生き生きとしたパレット。"
|
||||
},
|
||||
"Loading keybinds...": {
|
||||
"Loading keybinds...": ""
|
||||
},
|
||||
"Loading plugins...": {
|
||||
"Loading plugins...": "プラグインを読み込んでいます..."
|
||||
},
|
||||
@@ -1550,6 +1643,9 @@
|
||||
"Monospace Font": {
|
||||
"Monospace Font": "等幅フォント"
|
||||
},
|
||||
"Morning": {
|
||||
"Morning": ""
|
||||
},
|
||||
"Mount": {
|
||||
"Mount": "マウント"
|
||||
},
|
||||
@@ -1598,18 +1694,30 @@
|
||||
"New": {
|
||||
"New": "新しい"
|
||||
},
|
||||
"New Key": {
|
||||
"New Key": ""
|
||||
},
|
||||
"New Keybind": {
|
||||
"New Keybind": ""
|
||||
},
|
||||
"New Notification": {
|
||||
"New Notification": "新しい通知"
|
||||
},
|
||||
"New York, NY": {
|
||||
"New York, NY": "New York, NY"
|
||||
},
|
||||
"Night": {
|
||||
"Night": ""
|
||||
},
|
||||
"Night Mode": {
|
||||
"Night Mode": "ナイトモード"
|
||||
},
|
||||
"Night Temperature": {
|
||||
"Night Temperature": "夜間の温度"
|
||||
},
|
||||
"Niri compositor actions (focus, move, etc.)": {
|
||||
"Niri compositor actions (focus, move, etc.)": ""
|
||||
},
|
||||
"No": {
|
||||
"No": ""
|
||||
},
|
||||
@@ -1634,9 +1742,15 @@
|
||||
"No Weather Data Available": {
|
||||
"No Weather Data Available": "気象データはありません"
|
||||
},
|
||||
"No action": {
|
||||
"No action": ""
|
||||
},
|
||||
"No adapters": {
|
||||
"No adapters": ""
|
||||
},
|
||||
"No changes": {
|
||||
"No changes": ""
|
||||
},
|
||||
"No clipboard entries found": {
|
||||
"No clipboard entries found": "クリップボードのエントリが見つかりませんでした"
|
||||
},
|
||||
@@ -1652,6 +1766,9 @@
|
||||
"No items added yet": {
|
||||
"No items added yet": "まだアイテムが追加されていません"
|
||||
},
|
||||
"No keybinds found": {
|
||||
"No keybinds found": ""
|
||||
},
|
||||
"No matches": {
|
||||
"No matches": "一致するものはありません"
|
||||
},
|
||||
@@ -1751,6 +1868,9 @@
|
||||
"Open search bar to find text": {
|
||||
"Open search bar to find text": "検索バーを開いてテキストを検索"
|
||||
},
|
||||
"Open with...": {
|
||||
"Open with...": ""
|
||||
},
|
||||
"Optional description": {
|
||||
"Optional description": ""
|
||||
},
|
||||
@@ -1778,6 +1898,12 @@
|
||||
"Output Tray Missing": {
|
||||
"Output Tray Missing": "アウトプットトレイが見つかりませんでした"
|
||||
},
|
||||
"Override": {
|
||||
"Override": ""
|
||||
},
|
||||
"Overrides": {
|
||||
"Overrides": ""
|
||||
},
|
||||
"Overview": {
|
||||
"Overview": "概要"
|
||||
},
|
||||
@@ -1910,9 +2036,15 @@
|
||||
"Power Profile OSD": {
|
||||
"Power Profile OSD": "電源プロファイルOSD"
|
||||
},
|
||||
"Precipitation Chance": {
|
||||
"Precipitation Chance": ""
|
||||
},
|
||||
"Preference": {
|
||||
"Preference": ""
|
||||
},
|
||||
"Press key...": {
|
||||
"Press key...": ""
|
||||
},
|
||||
"Pressure": {
|
||||
"Pressure": "プレッシャー"
|
||||
},
|
||||
@@ -2009,6 +2141,9 @@
|
||||
"Refresh": {
|
||||
"Refresh": "リフレッシュ"
|
||||
},
|
||||
"Refresh Weather": {
|
||||
"Refresh Weather": ""
|
||||
},
|
||||
"Reject Jobs": {
|
||||
"Reject Jobs": ""
|
||||
},
|
||||
@@ -2069,6 +2204,12 @@
|
||||
"Run User Templates": {
|
||||
"Run User Templates": "ユーザーのテンプレを実行"
|
||||
},
|
||||
"Run a program (e.g., firefox, kitty)": {
|
||||
"Run a program (e.g., firefox, kitty)": ""
|
||||
},
|
||||
"Run a shell command (e.g., notify-send)": {
|
||||
"Run a shell command (e.g., notify-send)": ""
|
||||
},
|
||||
"Running Apps": {
|
||||
"Running Apps": "実行中のアプリ"
|
||||
},
|
||||
@@ -2111,6 +2252,9 @@
|
||||
"Screen sharing": {
|
||||
"Screen sharing": "画面共有"
|
||||
},
|
||||
"Scroll song title": {
|
||||
"Scroll song title": ""
|
||||
},
|
||||
"Scrolling": {
|
||||
"Scrolling": "スクロール"
|
||||
},
|
||||
@@ -2123,6 +2267,9 @@
|
||||
"Search for a location...": {
|
||||
"Search for a location...": "ロケーションを検索..."
|
||||
},
|
||||
"Search keybinds...": {
|
||||
"Search keybinds...": ""
|
||||
},
|
||||
"Search plugins...": {
|
||||
"Search plugins...": "プラグインを検索..."
|
||||
},
|
||||
@@ -2141,6 +2288,9 @@
|
||||
"Security": {
|
||||
"Security": ""
|
||||
},
|
||||
"Select Application": {
|
||||
"Select Application": ""
|
||||
},
|
||||
"Select Launcher Logo": {
|
||||
"Select Launcher Logo": "ランチャーロゴを選ぶ"
|
||||
},
|
||||
@@ -2186,6 +2336,9 @@
|
||||
"Select which transitions to include in randomization": {
|
||||
"Select which transitions to include in randomization": "含めたいトランジションをランダム化に選択"
|
||||
},
|
||||
"Select...": {
|
||||
"Select...": ""
|
||||
},
|
||||
"Selected image file not found.": {
|
||||
"Selected image file not found.": "選択した画像ファイルが見つかりませんでした。"
|
||||
},
|
||||
@@ -2201,12 +2354,21 @@
|
||||
"Set different wallpapers for light and dark mode": {
|
||||
"Set different wallpapers for light and dark mode": "ライトモードとダークモードで異なる壁紙を設定する"
|
||||
},
|
||||
"Set key and action to save": {
|
||||
"Set key and action to save": ""
|
||||
},
|
||||
"Settings": {
|
||||
"Settings": "設定"
|
||||
},
|
||||
"Shell": {
|
||||
"Shell": ""
|
||||
},
|
||||
"Shift+Del: Clear All • Esc: Close": {
|
||||
"Shift+Del: Clear All • Esc: Close": "Shift+Del: すべてクリア • Esc: 閉じる"
|
||||
},
|
||||
"Shortcuts": {
|
||||
"Shortcuts": ""
|
||||
},
|
||||
"Show All Tags": {
|
||||
"Show All Tags": "すべてのタグを表示"
|
||||
},
|
||||
@@ -2381,6 +2543,12 @@
|
||||
"Storage & Disks": {
|
||||
"Storage & Disks": "ストレージとディスク"
|
||||
},
|
||||
"Sunrise": {
|
||||
"Sunrise": ""
|
||||
},
|
||||
"Sunset": {
|
||||
"Sunset": ""
|
||||
},
|
||||
"Support Development": {
|
||||
"Support Development": "開発をサポート"
|
||||
},
|
||||
@@ -2504,6 +2672,9 @@
|
||||
"Timed Out": {
|
||||
"Timed Out": "タイムアウト"
|
||||
},
|
||||
"Title": {
|
||||
"Title": ""
|
||||
},
|
||||
"To Full": {
|
||||
"To Full": "フルへ"
|
||||
},
|
||||
@@ -2552,6 +2723,9 @@
|
||||
"Turn off monitors after": {
|
||||
"Turn off monitors after": "後にモニターの電源を切る"
|
||||
},
|
||||
"Type": {
|
||||
"Type": ""
|
||||
},
|
||||
"Unavailable": {
|
||||
"Unavailable": ""
|
||||
},
|
||||
@@ -2732,6 +2906,9 @@
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": {
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": "有効にすると、アプリはアルファベット順に並べ替えられます。無効にすると、アプリは使用頻度で並べ替えられます。"
|
||||
},
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": {
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": ""
|
||||
},
|
||||
"Wi-Fi Password": {
|
||||
"Wi-Fi Password": ""
|
||||
},
|
||||
@@ -2774,6 +2951,9 @@
|
||||
"Wind": {
|
||||
"Wind": "風"
|
||||
},
|
||||
"Wind Speed": {
|
||||
"Wind Speed": ""
|
||||
},
|
||||
"Workspace": {
|
||||
"Workspace": "ワークスペース"
|
||||
},
|
||||
@@ -2810,6 +2990,18 @@
|
||||
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
|
||||
"Select Wallpaper": "壁紙を選んでください"
|
||||
},
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
|
||||
},
|
||||
"dms/binds.kdl is now included in config.kdl": {
|
||||
"dms/binds.kdl is now included in config.kdl": ""
|
||||
},
|
||||
"e.g., firefox, kitty --title foo": {
|
||||
"e.g., firefox, kitty --title foo": ""
|
||||
},
|
||||
"e.g., focus-workspace 3, resize-column -10": {
|
||||
"e.g., focus-workspace 3, resize-column -10": ""
|
||||
},
|
||||
"events": {
|
||||
"events": "イベント"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -74,6 +74,9 @@
|
||||
"Access to system controls and settings": {
|
||||
"Access to system controls and settings": "Acesso aos controles de sistema e configurações"
|
||||
},
|
||||
"Action": {
|
||||
"Action": ""
|
||||
},
|
||||
"Actions": {
|
||||
"Actions": "Ações"
|
||||
},
|
||||
@@ -113,9 +116,15 @@
|
||||
"Add a VPN in NetworkManager": {
|
||||
"Add a VPN in NetworkManager": "Adicionar um VPN ao NetworkManager"
|
||||
},
|
||||
"Add a border around the dock": {
|
||||
"Add a border around the dock": ""
|
||||
},
|
||||
"Adjust the number of columns in grid view mode.": {
|
||||
"Adjust the number of columns in grid view mode.": ""
|
||||
},
|
||||
"Afternoon": {
|
||||
"Afternoon": ""
|
||||
},
|
||||
"All": {
|
||||
"All": "Todos"
|
||||
},
|
||||
@@ -329,6 +338,12 @@
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": {
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "Vincular o bloqueio de tela aos sinais do DBus do loginctl. Desative se estiver usando um bloqueio de tela externo"
|
||||
},
|
||||
"Binds Include Missing": {
|
||||
"Binds Include Missing": ""
|
||||
},
|
||||
"Binds include added": {
|
||||
"Binds include added": ""
|
||||
},
|
||||
"Bluetooth": {
|
||||
"Bluetooth": ""
|
||||
},
|
||||
@@ -491,6 +506,12 @@
|
||||
"Click Import to add a .ovpn or .conf": {
|
||||
"Click Import to add a .ovpn or .conf": ""
|
||||
},
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": {
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": ""
|
||||
},
|
||||
"Click to capture": {
|
||||
"Click to capture": ""
|
||||
},
|
||||
"Clipboard History": {
|
||||
"Clipboard History": "Histórico da Área de Transferência"
|
||||
},
|
||||
@@ -524,6 +545,9 @@
|
||||
"Colorful mix of bright contrasting accents.": {
|
||||
"Colorful mix of bright contrasting accents.": "Mistura colorida de destaques de cor brilhantes e contrastantes."
|
||||
},
|
||||
"Command": {
|
||||
"Command": ""
|
||||
},
|
||||
"Command or script to run instead of the standard hibernate procedure": {
|
||||
"Command or script to run instead of the standard hibernate procedure": "Comando ou script serão executados em vez do procedimento padrão de hibernação"
|
||||
},
|
||||
@@ -575,6 +599,9 @@
|
||||
"Confirm passkey for ": {
|
||||
"Confirm passkey for ": "Confirmar chave de acesso para "
|
||||
},
|
||||
"Conflicts with: %1": {
|
||||
"Conflicts with: %1": ""
|
||||
},
|
||||
"Connect": {
|
||||
"Connect": "Conectar"
|
||||
},
|
||||
@@ -686,12 +713,18 @@
|
||||
"DMS out of date": {
|
||||
"DMS out of date": "DMS desatualizado"
|
||||
},
|
||||
"DMS shell actions (launcher, clipboard, etc.)": {
|
||||
"DMS shell actions (launcher, clipboard, etc.)": ""
|
||||
},
|
||||
"DMS_SOCKET not available": {
|
||||
"DMS_SOCKET not available": "DMS_SOCKET não está disponível"
|
||||
},
|
||||
"DWL service not available": {
|
||||
"DWL service not available": ""
|
||||
},
|
||||
"Daily Forecast": {
|
||||
"Daily Forecast": ""
|
||||
},
|
||||
"Daily at:": {
|
||||
"Daily at:": "Diária:"
|
||||
},
|
||||
@@ -722,6 +755,15 @@
|
||||
"Date Format": {
|
||||
"Date Format": "Formatação de Data"
|
||||
},
|
||||
"Dawn (Astronomical Twilight)": {
|
||||
"Dawn (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dawn (Civil Twilight)": {
|
||||
"Dawn (Civil Twilight)": ""
|
||||
},
|
||||
"Dawn (Nautical Twilight)": {
|
||||
"Dawn (Nautical Twilight)": ""
|
||||
},
|
||||
"Day Temperature": {
|
||||
"Day Temperature": "Temperatura Diurna"
|
||||
},
|
||||
@@ -869,6 +911,15 @@
|
||||
"Duration": {
|
||||
"Duration": "Duração"
|
||||
},
|
||||
"Dusk (Astronomical Twilight)": {
|
||||
"Dusk (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dusk (Civil Twighlight)": {
|
||||
"Dusk (Civil Twighlight)": ""
|
||||
},
|
||||
"Dusk (Nautical Twilight)": {
|
||||
"Dusk (Nautical Twilight)": ""
|
||||
},
|
||||
"Dynamic Theming": {
|
||||
"Dynamic Theming": "Tematização Dinâmica"
|
||||
},
|
||||
@@ -890,6 +941,9 @@
|
||||
"Enable GPU Temperature": {
|
||||
"Enable GPU Temperature": "Habilitar Temperatura da GPU"
|
||||
},
|
||||
"Enable Overview Overlay": {
|
||||
"Enable Overview Overlay": ""
|
||||
},
|
||||
"Enable System Sounds": {
|
||||
"Enable System Sounds": "Ativar Sons do Sistema"
|
||||
},
|
||||
@@ -974,6 +1028,9 @@
|
||||
"Failed to activate configuration": {
|
||||
"Failed to activate configuration": "Erro ao ativar configuração"
|
||||
},
|
||||
"Failed to add binds include": {
|
||||
"Failed to add binds include": ""
|
||||
},
|
||||
"Failed to add printer to class": {
|
||||
"Failed to add printer to class": ""
|
||||
},
|
||||
@@ -1040,6 +1097,9 @@
|
||||
"Failed to remove device": {
|
||||
"Failed to remove device": "Erro ao remover dispositivo"
|
||||
},
|
||||
"Failed to remove keybind": {
|
||||
"Failed to remove keybind": ""
|
||||
},
|
||||
"Failed to remove printer from class": {
|
||||
"Failed to remove printer from class": ""
|
||||
},
|
||||
@@ -1049,6 +1109,9 @@
|
||||
"Failed to resume printer": {
|
||||
"Failed to resume printer": ""
|
||||
},
|
||||
"Failed to save keybind": {
|
||||
"Failed to save keybind": ""
|
||||
},
|
||||
"Failed to set profile image": {
|
||||
"Failed to set profile image": "Erro ao definir imagem de perfil"
|
||||
},
|
||||
@@ -1091,6 +1154,12 @@
|
||||
"Find in note...": {
|
||||
"Find in note...": "Procurar na nota..."
|
||||
},
|
||||
"Fix Now": {
|
||||
"Fix Now": ""
|
||||
},
|
||||
"Fixing...": {
|
||||
"Fixing...": ""
|
||||
},
|
||||
"Focused Window": {
|
||||
"Focused Window": "Janela Focada"
|
||||
},
|
||||
@@ -1115,6 +1184,9 @@
|
||||
"Force terminal applications to always use dark color schemes": {
|
||||
"Force terminal applications to always use dark color schemes": ""
|
||||
},
|
||||
"Forecast Not Available": {
|
||||
"Forecast Not Available": ""
|
||||
},
|
||||
"Forget": {
|
||||
"Forget": ""
|
||||
},
|
||||
@@ -1157,6 +1229,9 @@
|
||||
"Github:": {
|
||||
"Github:": "Github:"
|
||||
},
|
||||
"Golden Hour": {
|
||||
"Golden Hour": ""
|
||||
},
|
||||
"Good": {
|
||||
"Good": "Bom"
|
||||
},
|
||||
@@ -1226,9 +1301,15 @@
|
||||
"Hold to confirm (%1s)": {
|
||||
"Hold to confirm (%1s)": ""
|
||||
},
|
||||
"Hotkey overlay title (optional)": {
|
||||
"Hotkey overlay title (optional)": ""
|
||||
},
|
||||
"Hour": {
|
||||
"Hour": "Hora"
|
||||
},
|
||||
"Hourly Forecast": {
|
||||
"Hourly Forecast": ""
|
||||
},
|
||||
"How often to change wallpaper": {
|
||||
"How often to change wallpaper": "Tempo entre papéis de parede"
|
||||
},
|
||||
@@ -1328,9 +1409,18 @@
|
||||
"Keeping Awake": {
|
||||
"Keeping Awake": ""
|
||||
},
|
||||
"Key": {
|
||||
"Key": ""
|
||||
},
|
||||
"Keyboard Layout Name": {
|
||||
"Keyboard Layout Name": "Nome de Layout do Teclado"
|
||||
},
|
||||
"Keyboard Shortcuts": {
|
||||
"Keyboard Shortcuts": ""
|
||||
},
|
||||
"Keys": {
|
||||
"Keys": ""
|
||||
},
|
||||
"Kill Process": {
|
||||
"Kill Process": "Matar Processo"
|
||||
},
|
||||
@@ -1385,6 +1475,9 @@
|
||||
"Lively palette with saturated accents.": {
|
||||
"Lively palette with saturated accents.": "Paleta vívida com destaques de cor saturados."
|
||||
},
|
||||
"Loading keybinds...": {
|
||||
"Loading keybinds...": ""
|
||||
},
|
||||
"Loading plugins...": {
|
||||
"Loading plugins...": "Carregando plugins..."
|
||||
},
|
||||
@@ -1550,6 +1643,9 @@
|
||||
"Monospace Font": {
|
||||
"Monospace Font": "Fonte Mono espaço"
|
||||
},
|
||||
"Morning": {
|
||||
"Morning": ""
|
||||
},
|
||||
"Mount": {
|
||||
"Mount": "Ponto de montagem"
|
||||
},
|
||||
@@ -1598,18 +1694,30 @@
|
||||
"New": {
|
||||
"New": "Novo"
|
||||
},
|
||||
"New Key": {
|
||||
"New Key": ""
|
||||
},
|
||||
"New Keybind": {
|
||||
"New Keybind": ""
|
||||
},
|
||||
"New Notification": {
|
||||
"New Notification": "Nova Notificação"
|
||||
},
|
||||
"New York, NY": {
|
||||
"New York, NY": "Nova York, NY"
|
||||
},
|
||||
"Night": {
|
||||
"Night": ""
|
||||
},
|
||||
"Night Mode": {
|
||||
"Night Mode": "Modo Noturno"
|
||||
},
|
||||
"Night Temperature": {
|
||||
"Night Temperature": "Temperatura Noturna"
|
||||
},
|
||||
"Niri compositor actions (focus, move, etc.)": {
|
||||
"Niri compositor actions (focus, move, etc.)": ""
|
||||
},
|
||||
"No": {
|
||||
"No": ""
|
||||
},
|
||||
@@ -1634,9 +1742,15 @@
|
||||
"No Weather Data Available": {
|
||||
"No Weather Data Available": "Informações de Clima não dispóniveis"
|
||||
},
|
||||
"No action": {
|
||||
"No action": ""
|
||||
},
|
||||
"No adapters": {
|
||||
"No adapters": ""
|
||||
},
|
||||
"No changes": {
|
||||
"No changes": ""
|
||||
},
|
||||
"No clipboard entries found": {
|
||||
"No clipboard entries found": "Área de transferência vazia"
|
||||
},
|
||||
@@ -1652,6 +1766,9 @@
|
||||
"No items added yet": {
|
||||
"No items added yet": "Nenhum item adicionado"
|
||||
},
|
||||
"No keybinds found": {
|
||||
"No keybinds found": ""
|
||||
},
|
||||
"No matches": {
|
||||
"No matches": "Nenhuma correspondência"
|
||||
},
|
||||
@@ -1751,6 +1868,9 @@
|
||||
"Open search bar to find text": {
|
||||
"Open search bar to find text": "Abrir barra de pesquisa e encontrar texto"
|
||||
},
|
||||
"Open with...": {
|
||||
"Open with...": ""
|
||||
},
|
||||
"Optional description": {
|
||||
"Optional description": ""
|
||||
},
|
||||
@@ -1778,6 +1898,12 @@
|
||||
"Output Tray Missing": {
|
||||
"Output Tray Missing": ""
|
||||
},
|
||||
"Override": {
|
||||
"Override": ""
|
||||
},
|
||||
"Overrides": {
|
||||
"Overrides": ""
|
||||
},
|
||||
"Overview": {
|
||||
"Overview": "Visão Geral"
|
||||
},
|
||||
@@ -1910,9 +2036,15 @@
|
||||
"Power Profile OSD": {
|
||||
"Power Profile OSD": ""
|
||||
},
|
||||
"Precipitation Chance": {
|
||||
"Precipitation Chance": ""
|
||||
},
|
||||
"Preference": {
|
||||
"Preference": ""
|
||||
},
|
||||
"Press key...": {
|
||||
"Press key...": ""
|
||||
},
|
||||
"Pressure": {
|
||||
"Pressure": "Pressão"
|
||||
},
|
||||
@@ -2009,6 +2141,9 @@
|
||||
"Refresh": {
|
||||
"Refresh": "Recarregar"
|
||||
},
|
||||
"Refresh Weather": {
|
||||
"Refresh Weather": ""
|
||||
},
|
||||
"Reject Jobs": {
|
||||
"Reject Jobs": ""
|
||||
},
|
||||
@@ -2069,6 +2204,12 @@
|
||||
"Run User Templates": {
|
||||
"Run User Templates": "Executar Templates do Usuário"
|
||||
},
|
||||
"Run a program (e.g., firefox, kitty)": {
|
||||
"Run a program (e.g., firefox, kitty)": ""
|
||||
},
|
||||
"Run a shell command (e.g., notify-send)": {
|
||||
"Run a shell command (e.g., notify-send)": ""
|
||||
},
|
||||
"Running Apps": {
|
||||
"Running Apps": "Apps Em Execução"
|
||||
},
|
||||
@@ -2111,6 +2252,9 @@
|
||||
"Screen sharing": {
|
||||
"Screen sharing": ""
|
||||
},
|
||||
"Scroll song title": {
|
||||
"Scroll song title": ""
|
||||
},
|
||||
"Scrolling": {
|
||||
"Scrolling": ""
|
||||
},
|
||||
@@ -2123,6 +2267,9 @@
|
||||
"Search for a location...": {
|
||||
"Search for a location...": "Procurar um local..."
|
||||
},
|
||||
"Search keybinds...": {
|
||||
"Search keybinds...": ""
|
||||
},
|
||||
"Search plugins...": {
|
||||
"Search plugins...": "Buscar plugins..."
|
||||
},
|
||||
@@ -2141,6 +2288,9 @@
|
||||
"Security": {
|
||||
"Security": ""
|
||||
},
|
||||
"Select Application": {
|
||||
"Select Application": ""
|
||||
},
|
||||
"Select Launcher Logo": {
|
||||
"Select Launcher Logo": "Selecionar Logo do Lançador"
|
||||
},
|
||||
@@ -2186,6 +2336,9 @@
|
||||
"Select which transitions to include in randomization": {
|
||||
"Select which transitions to include in randomization": "Selecionar quais transições incluir na randomização"
|
||||
},
|
||||
"Select...": {
|
||||
"Select...": ""
|
||||
},
|
||||
"Selected image file not found.": {
|
||||
"Selected image file not found.": "Imagem selecionada não encontrada."
|
||||
},
|
||||
@@ -2201,12 +2354,21 @@
|
||||
"Set different wallpapers for light and dark mode": {
|
||||
"Set different wallpapers for light and dark mode": "Use papéis de parede diferentes para modos claro e escuro"
|
||||
},
|
||||
"Set key and action to save": {
|
||||
"Set key and action to save": ""
|
||||
},
|
||||
"Settings": {
|
||||
"Settings": "Configurações"
|
||||
},
|
||||
"Shell": {
|
||||
"Shell": ""
|
||||
},
|
||||
"Shift+Del: Clear All • Esc: Close": {
|
||||
"Shift+Del: Clear All • Esc: Close": "Shift+Del: Apagar tudo • Esc: Fechar"
|
||||
},
|
||||
"Shortcuts": {
|
||||
"Shortcuts": ""
|
||||
},
|
||||
"Show All Tags": {
|
||||
"Show All Tags": "Mostrar Todas as Tags"
|
||||
},
|
||||
@@ -2381,6 +2543,12 @@
|
||||
"Storage & Disks": {
|
||||
"Storage & Disks": "Armazenamento & Discos"
|
||||
},
|
||||
"Sunrise": {
|
||||
"Sunrise": ""
|
||||
},
|
||||
"Sunset": {
|
||||
"Sunset": ""
|
||||
},
|
||||
"Support Development": {
|
||||
"Support Development": "Apoie o Desenvolvimento"
|
||||
},
|
||||
@@ -2504,6 +2672,9 @@
|
||||
"Timed Out": {
|
||||
"Timed Out": ""
|
||||
},
|
||||
"Title": {
|
||||
"Title": ""
|
||||
},
|
||||
"To Full": {
|
||||
"To Full": "Para completar"
|
||||
},
|
||||
@@ -2552,6 +2723,9 @@
|
||||
"Turn off monitors after": {
|
||||
"Turn off monitors after": "Desligar monitores depois de"
|
||||
},
|
||||
"Type": {
|
||||
"Type": ""
|
||||
},
|
||||
"Unavailable": {
|
||||
"Unavailable": ""
|
||||
},
|
||||
@@ -2732,6 +2906,9 @@
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": {
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": "Quando ativado, apps são ordenados alfabeticamente. Quando desativado, apps são ordenados por frequência de uso."
|
||||
},
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": {
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": ""
|
||||
},
|
||||
"Wi-Fi Password": {
|
||||
"Wi-Fi Password": ""
|
||||
},
|
||||
@@ -2774,6 +2951,9 @@
|
||||
"Wind": {
|
||||
"Wind": "Vento"
|
||||
},
|
||||
"Wind Speed": {
|
||||
"Wind Speed": ""
|
||||
},
|
||||
"Workspace": {
|
||||
"Workspace": "Área de Trabalho"
|
||||
},
|
||||
@@ -2810,6 +2990,18 @@
|
||||
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
|
||||
"Select Wallpaper": ""
|
||||
},
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
|
||||
},
|
||||
"dms/binds.kdl is now included in config.kdl": {
|
||||
"dms/binds.kdl is now included in config.kdl": ""
|
||||
},
|
||||
"e.g., firefox, kitty --title foo": {
|
||||
"e.g., firefox, kitty --title foo": ""
|
||||
},
|
||||
"e.g., focus-workspace 3, resize-column -10": {
|
||||
"e.g., focus-workspace 3, resize-column -10": ""
|
||||
},
|
||||
"events": {
|
||||
"events": "eventos"
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"%1 characters": "%1 karakter"
|
||||
},
|
||||
"%1 class(es)": {
|
||||
"%1 class(es)": ""
|
||||
"%1 class(es)": "%1 sınıf"
|
||||
},
|
||||
"%1 connected": {
|
||||
"%1 connected": "%1 bağlı"
|
||||
@@ -15,10 +15,10 @@
|
||||
"%1 display(s)": "%1 ekran"
|
||||
},
|
||||
"%1 job(s)": {
|
||||
"%1 job(s)": ""
|
||||
"%1 job(s)": "%1 iş"
|
||||
},
|
||||
"%1 printer(s)": {
|
||||
"%1 printer(s)": ""
|
||||
"%1 printer(s)": "%1 yazıcı"
|
||||
},
|
||||
"%1 widgets": {
|
||||
"%1 widgets": "%1 widget"
|
||||
@@ -51,19 +51,19 @@
|
||||
"A file with this name already exists. Do you want to overwrite it?": "Bu isimde bir dosya zaten var. Üzerine yazmak istiyor musunuz?"
|
||||
},
|
||||
"API": {
|
||||
"API": ""
|
||||
"API": "API"
|
||||
},
|
||||
"Aborted": {
|
||||
"Aborted": ""
|
||||
"Aborted": "Durduruldu"
|
||||
},
|
||||
"About": {
|
||||
"About": "Hakkında"
|
||||
},
|
||||
"Accept Jobs": {
|
||||
"Accept Jobs": ""
|
||||
"Accept Jobs": "İşleri Kabul Et"
|
||||
},
|
||||
"Accepting": {
|
||||
"Accepting": ""
|
||||
"Accepting": "Kabul ediliyor"
|
||||
},
|
||||
"Access clipboard history": {
|
||||
"Access clipboard history": "Pano geçmişine eriş"
|
||||
@@ -74,6 +74,9 @@
|
||||
"Access to system controls and settings": {
|
||||
"Access to system controls and settings": "Sistem kontrolleri ve ayarlara eriş"
|
||||
},
|
||||
"Action": {
|
||||
"Action": ""
|
||||
},
|
||||
"Actions": {
|
||||
"Actions": "Eylemler"
|
||||
},
|
||||
@@ -99,7 +102,7 @@
|
||||
"Add Bar": "Bar Ekle"
|
||||
},
|
||||
"Add Printer": {
|
||||
"Add Printer": ""
|
||||
"Add Printer": "Yazıcı Ekle"
|
||||
},
|
||||
"Add Widget": {
|
||||
"Add Widget": "Widget Ekle"
|
||||
@@ -113,9 +116,15 @@
|
||||
"Add a VPN in NetworkManager": {
|
||||
"Add a VPN in NetworkManager": "NetworkManager'da VPN ekle"
|
||||
},
|
||||
"Add a border around the dock": {
|
||||
"Add a border around the dock": ""
|
||||
},
|
||||
"Adjust the number of columns in grid view mode.": {
|
||||
"Adjust the number of columns in grid view mode.": "Izgara görünümü modunda sütun sayısını ayarla"
|
||||
},
|
||||
"Afternoon": {
|
||||
"Afternoon": ""
|
||||
},
|
||||
"All": {
|
||||
"All": "Tümü"
|
||||
},
|
||||
@@ -329,6 +338,12 @@
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": {
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "Kilit ekranını loginctl'den gelen dbus sinyallerine bağlayın. Harici bir kilit ekranı kullanıyorsanız devre dışı bırakın"
|
||||
},
|
||||
"Binds Include Missing": {
|
||||
"Binds Include Missing": ""
|
||||
},
|
||||
"Binds include added": {
|
||||
"Binds include added": ""
|
||||
},
|
||||
"Bluetooth": {
|
||||
"Bluetooth": "Bluetooth"
|
||||
},
|
||||
@@ -402,7 +417,7 @@
|
||||
"CUPS Missing Filter Warning": "CUPS Eksik Filtre Uyarısı"
|
||||
},
|
||||
"CUPS Print Server": {
|
||||
"CUPS Print Server": ""
|
||||
"CUPS Print Server": "CUPS Yazıcı Sunucusu"
|
||||
},
|
||||
"Camera": {
|
||||
"Camera": "Kamera"
|
||||
@@ -411,10 +426,10 @@
|
||||
"Cancel": "İptal"
|
||||
},
|
||||
"Canceled": {
|
||||
"Canceled": ""
|
||||
"Canceled": "İptal Edildi"
|
||||
},
|
||||
"Capabilities": {
|
||||
"Capabilities": ""
|
||||
"Capabilities": "Yetenekler"
|
||||
},
|
||||
"Capacity": {
|
||||
"Capacity": "Kapasite"
|
||||
@@ -486,11 +501,17 @@
|
||||
"Clear All History?": "Tüm Geçmişi Temizle?"
|
||||
},
|
||||
"Clear All Jobs": {
|
||||
"Clear All Jobs": ""
|
||||
"Clear All Jobs": "Tüm İşleri Temizle"
|
||||
},
|
||||
"Click Import to add a .ovpn or .conf": {
|
||||
"Click Import to add a .ovpn or .conf": ".ovpn veya .conf dosyası eklemek için İçe Aktar'ı tıklayın."
|
||||
},
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": {
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": ""
|
||||
},
|
||||
"Click to capture": {
|
||||
"Click to capture": ""
|
||||
},
|
||||
"Clipboard History": {
|
||||
"Clipboard History": "Pano Geçmişi"
|
||||
},
|
||||
@@ -524,6 +545,9 @@
|
||||
"Colorful mix of bright contrasting accents.": {
|
||||
"Colorful mix of bright contrasting accents.": "Parlak kontrastlı vurguların renkli karışımı."
|
||||
},
|
||||
"Command": {
|
||||
"Command": ""
|
||||
},
|
||||
"Command or script to run instead of the standard hibernate procedure": {
|
||||
"Command or script to run instead of the standard hibernate procedure": "Standart hazırda bekleme prosedürü yerine çalıştırılacak komut veya komut dosyası"
|
||||
},
|
||||
@@ -549,7 +573,7 @@
|
||||
"Compact Mode": "Kompakt Mod"
|
||||
},
|
||||
"Completed": {
|
||||
"Completed": ""
|
||||
"Completed": "Tamamlandı"
|
||||
},
|
||||
"Compositor": {
|
||||
"Compositor": "Kompozitör"
|
||||
@@ -558,7 +582,7 @@
|
||||
"Configuration activated": "Yapılandırma aktifleştirildi"
|
||||
},
|
||||
"Configure a new printer": {
|
||||
"Configure a new printer": ""
|
||||
"Configure a new printer": "Yeni bir yazıcı yapılandır"
|
||||
},
|
||||
"Configure icons for named workspaces. Icons take priority over numbers when both are enabled.": {
|
||||
"Configure icons for named workspaces. Icons take priority over numbers when both are enabled.": "Adlandırılmış çalışma alanları için simgeleri yapılandırın. Her ikisi de etkinleştirildiğinde simgeler sayılara göre önceliklidir."
|
||||
@@ -575,6 +599,9 @@
|
||||
"Confirm passkey for ": {
|
||||
"Confirm passkey for ": "Şunun için şifreyi onayla: "
|
||||
},
|
||||
"Conflicts with: %1": {
|
||||
"Conflicts with: %1": ""
|
||||
},
|
||||
"Connect": {
|
||||
"Connect": "Bağlan"
|
||||
},
|
||||
@@ -636,10 +663,10 @@
|
||||
"Create Dir": "Dizin Oluştur"
|
||||
},
|
||||
"Create Printer": {
|
||||
"Create Printer": ""
|
||||
"Create Printer": "Yazıcı Oluştur"
|
||||
},
|
||||
"Creating...": {
|
||||
"Creating...": ""
|
||||
"Creating...": "Oluşturuluyor..."
|
||||
},
|
||||
"Critical Priority": {
|
||||
"Critical Priority": "Kritik Öncelik"
|
||||
@@ -686,12 +713,18 @@
|
||||
"DMS out of date": {
|
||||
"DMS out of date": "DMS güncel değil"
|
||||
},
|
||||
"DMS shell actions (launcher, clipboard, etc.)": {
|
||||
"DMS shell actions (launcher, clipboard, etc.)": ""
|
||||
},
|
||||
"DMS_SOCKET not available": {
|
||||
"DMS_SOCKET not available": "DMS_SOCKET kullanılamıyor"
|
||||
},
|
||||
"DWL service not available": {
|
||||
"DWL service not available": "DWL hizmeti kullanılamıyor"
|
||||
},
|
||||
"Daily Forecast": {
|
||||
"Daily Forecast": ""
|
||||
},
|
||||
"Daily at:": {
|
||||
"Daily at:": "Her gün saat:"
|
||||
},
|
||||
@@ -722,6 +755,15 @@
|
||||
"Date Format": {
|
||||
"Date Format": "Tarih Biçimi"
|
||||
},
|
||||
"Dawn (Astronomical Twilight)": {
|
||||
"Dawn (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dawn (Civil Twilight)": {
|
||||
"Dawn (Civil Twilight)": ""
|
||||
},
|
||||
"Dawn (Nautical Twilight)": {
|
||||
"Dawn (Nautical Twilight)": ""
|
||||
},
|
||||
"Day Temperature": {
|
||||
"Day Temperature": "Gündüz Sıcaklığı"
|
||||
},
|
||||
@@ -744,10 +786,10 @@
|
||||
"Delete": "Sil"
|
||||
},
|
||||
"Delete Class": {
|
||||
"Delete Class": ""
|
||||
"Delete Class": "Sınıf Sil"
|
||||
},
|
||||
"Delete Printer": {
|
||||
"Delete Printer": ""
|
||||
"Delete Printer": "Yazıcı Sil"
|
||||
},
|
||||
"Delete VPN": {
|
||||
"Delete VPN": "VPN'i Sil"
|
||||
@@ -756,7 +798,7 @@
|
||||
"Derives colors that closely match the underlying image.": "Altta yatan görüntüye çok yakın renkler türetir"
|
||||
},
|
||||
"Description": {
|
||||
"Description": ""
|
||||
"Description": "Tanım"
|
||||
},
|
||||
"Desktop background images": {
|
||||
"Desktop background images": "Masaüstü arkaplan resimleri"
|
||||
@@ -869,6 +911,15 @@
|
||||
"Duration": {
|
||||
"Duration": "Süre"
|
||||
},
|
||||
"Dusk (Astronomical Twilight)": {
|
||||
"Dusk (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dusk (Civil Twighlight)": {
|
||||
"Dusk (Civil Twighlight)": ""
|
||||
},
|
||||
"Dusk (Nautical Twilight)": {
|
||||
"Dusk (Nautical Twilight)": ""
|
||||
},
|
||||
"Dynamic Theming": {
|
||||
"Dynamic Theming": "Dinamik Tema"
|
||||
},
|
||||
@@ -890,6 +941,9 @@
|
||||
"Enable GPU Temperature": {
|
||||
"Enable GPU Temperature": "GPU Sıcaklığını Etkinleştir"
|
||||
},
|
||||
"Enable Overview Overlay": {
|
||||
"Enable Overview Overlay": ""
|
||||
},
|
||||
"Enable System Sounds": {
|
||||
"Enable System Sounds": "Sistem Seslerini Etkinleştir"
|
||||
},
|
||||
@@ -974,8 +1028,11 @@
|
||||
"Failed to activate configuration": {
|
||||
"Failed to activate configuration": "Yapılandırma etkinleştirilemedi"
|
||||
},
|
||||
"Failed to add binds include": {
|
||||
"Failed to add binds include": ""
|
||||
},
|
||||
"Failed to add printer to class": {
|
||||
"Failed to add printer to class": ""
|
||||
"Failed to add printer to class": "Yazıcı sınıfa eklenemedi"
|
||||
},
|
||||
"Failed to cancel all jobs": {
|
||||
"Failed to cancel all jobs": "Tüm işler iptal edemedi"
|
||||
@@ -990,19 +1047,19 @@
|
||||
"Failed to connect to ": "Bağlanılamadı "
|
||||
},
|
||||
"Failed to create printer": {
|
||||
"Failed to create printer": ""
|
||||
"Failed to create printer": "Yazıcı oluşturulamadı"
|
||||
},
|
||||
"Failed to delete VPN": {
|
||||
"Failed to delete VPN": "VPN silinemedi"
|
||||
},
|
||||
"Failed to delete class": {
|
||||
"Failed to delete class": ""
|
||||
"Failed to delete class": "Sınıf silinemedi"
|
||||
},
|
||||
"Failed to delete printer": {
|
||||
"Failed to delete printer": ""
|
||||
"Failed to delete printer": "Yazıcı silinemedi"
|
||||
},
|
||||
"Failed to disable job acceptance": {
|
||||
"Failed to disable job acceptance": ""
|
||||
"Failed to disable job acceptance": "İş kabulü devre dışı bırakılamadı"
|
||||
},
|
||||
"Failed to disconnect VPN": {
|
||||
"Failed to disconnect VPN": "VPN bağlantısı kesilemedi"
|
||||
@@ -1017,10 +1074,10 @@
|
||||
"Failed to enable WiFi": "WiFi etkinleştirilemedi"
|
||||
},
|
||||
"Failed to enable job acceptance": {
|
||||
"Failed to enable job acceptance": ""
|
||||
"Failed to enable job acceptance": "İş kabulü etkinleştirilemedi"
|
||||
},
|
||||
"Failed to hold job": {
|
||||
"Failed to hold job": ""
|
||||
"Failed to hold job": "İş bekletilemedi"
|
||||
},
|
||||
"Failed to import VPN": {
|
||||
"Failed to import VPN": "VPN içe aktarılamadı"
|
||||
@@ -1029,26 +1086,32 @@
|
||||
"Failed to load VPN config": "VPN ayarı yüklenemedi"
|
||||
},
|
||||
"Failed to move job": {
|
||||
"Failed to move job": ""
|
||||
"Failed to move job": "İş taşınamadı"
|
||||
},
|
||||
"Failed to pause printer": {
|
||||
"Failed to pause printer": "Yazıcıyı duraklatma başarısız"
|
||||
},
|
||||
"Failed to print test page": {
|
||||
"Failed to print test page": ""
|
||||
"Failed to print test page": "Test sayfası yazdırılamadı"
|
||||
},
|
||||
"Failed to remove device": {
|
||||
"Failed to remove device": "Cihaz kaldırılamadı"
|
||||
},
|
||||
"Failed to remove keybind": {
|
||||
"Failed to remove keybind": ""
|
||||
},
|
||||
"Failed to remove printer from class": {
|
||||
"Failed to remove printer from class": ""
|
||||
"Failed to remove printer from class": "Yazıcı sınıftan kaldırılamadı"
|
||||
},
|
||||
"Failed to restart job": {
|
||||
"Failed to restart job": ""
|
||||
"Failed to restart job": "İş yeniden başlatılamadı"
|
||||
},
|
||||
"Failed to resume printer": {
|
||||
"Failed to resume printer": "Yazıcıyı devam ettirme başarısız"
|
||||
},
|
||||
"Failed to save keybind": {
|
||||
"Failed to save keybind": ""
|
||||
},
|
||||
"Failed to set profile image": {
|
||||
"Failed to set profile image": "Profil resmi ayarlanamadı"
|
||||
},
|
||||
@@ -1065,19 +1128,19 @@
|
||||
"Failed to update autoconnect": "Otomatik bağlanma güncellenemedi"
|
||||
},
|
||||
"Failed to update description": {
|
||||
"Failed to update description": ""
|
||||
"Failed to update description": "Tanım güncellenemedi"
|
||||
},
|
||||
"Failed to update location": {
|
||||
"Failed to update location": ""
|
||||
"Failed to update location": "Konum güncellenemedi"
|
||||
},
|
||||
"Failed to update sharing": {
|
||||
"Failed to update sharing": ""
|
||||
"Failed to update sharing": "Paylaşım güncellenemedi"
|
||||
},
|
||||
"Feels Like": {
|
||||
"Feels Like": "Hissedilen"
|
||||
},
|
||||
"File": {
|
||||
"File": ""
|
||||
"File": "Dosya"
|
||||
},
|
||||
"File Already Exists": {
|
||||
"File Already Exists": "Dosya Zaten Mevcut"
|
||||
@@ -1091,6 +1154,12 @@
|
||||
"Find in note...": {
|
||||
"Find in note...": "Notta bul..."
|
||||
},
|
||||
"Fix Now": {
|
||||
"Fix Now": ""
|
||||
},
|
||||
"Fixing...": {
|
||||
"Fixing...": ""
|
||||
},
|
||||
"Focused Window": {
|
||||
"Focused Window": "Odaklanılmış Pencere"
|
||||
},
|
||||
@@ -1115,6 +1184,9 @@
|
||||
"Force terminal applications to always use dark color schemes": {
|
||||
"Force terminal applications to always use dark color schemes": "Terminal uygulamalarının her zaman koyu renk şemalarını kullanmasını zorla"
|
||||
},
|
||||
"Forecast Not Available": {
|
||||
"Forecast Not Available": ""
|
||||
},
|
||||
"Forget": {
|
||||
"Forget": "Unut"
|
||||
},
|
||||
@@ -1157,6 +1229,9 @@
|
||||
"Github:": {
|
||||
"Github:": "Github:"
|
||||
},
|
||||
"Golden Hour": {
|
||||
"Golden Hour": ""
|
||||
},
|
||||
"Good": {
|
||||
"Good": "İyi"
|
||||
},
|
||||
@@ -1194,7 +1269,7 @@
|
||||
"Height to Edge Gap (Exclusive Zone)": "Kenar Boşluğu Yüksekliği (Özel Bölge)"
|
||||
},
|
||||
"Held": {
|
||||
"Held": ""
|
||||
"Held": "Bekletildi"
|
||||
},
|
||||
"Hex": {
|
||||
"Hex": "Hex"
|
||||
@@ -1226,9 +1301,15 @@
|
||||
"Hold to confirm (%1s)": {
|
||||
"Hold to confirm (%1s)": "Onaylamak için basılı tutun (%1s)"
|
||||
},
|
||||
"Hotkey overlay title (optional)": {
|
||||
"Hotkey overlay title (optional)": ""
|
||||
},
|
||||
"Hour": {
|
||||
"Hour": "Saat"
|
||||
},
|
||||
"Hourly Forecast": {
|
||||
"Hourly Forecast": ""
|
||||
},
|
||||
"How often to change wallpaper": {
|
||||
"How often to change wallpaper": "Duvar kağıdı değiştirme sıklığı"
|
||||
},
|
||||
@@ -1328,9 +1409,18 @@
|
||||
"Keeping Awake": {
|
||||
"Keeping Awake": "Uyanık Tutuluyor"
|
||||
},
|
||||
"Key": {
|
||||
"Key": ""
|
||||
},
|
||||
"Keyboard Layout Name": {
|
||||
"Keyboard Layout Name": "Klavye Düzeni Adı"
|
||||
},
|
||||
"Keyboard Shortcuts": {
|
||||
"Keyboard Shortcuts": ""
|
||||
},
|
||||
"Keys": {
|
||||
"Keys": ""
|
||||
},
|
||||
"Kill Process": {
|
||||
"Kill Process": "Süreci Öldür"
|
||||
},
|
||||
@@ -1385,6 +1475,9 @@
|
||||
"Lively palette with saturated accents.": {
|
||||
"Lively palette with saturated accents.": "Doygun vurgularla canlı renk paleti."
|
||||
},
|
||||
"Loading keybinds...": {
|
||||
"Loading keybinds...": ""
|
||||
},
|
||||
"Loading plugins...": {
|
||||
"Loading plugins...": "Eklentiler yükleniyor..."
|
||||
},
|
||||
@@ -1392,10 +1485,10 @@
|
||||
"Loading...": "Yükleniyor..."
|
||||
},
|
||||
"Local": {
|
||||
"Local": ""
|
||||
"Local": "Yerel"
|
||||
},
|
||||
"Location": {
|
||||
"Location": ""
|
||||
"Location": "Konum"
|
||||
},
|
||||
"Location Search": {
|
||||
"Location Search": "Konum Arama"
|
||||
@@ -1550,6 +1643,9 @@
|
||||
"Monospace Font": {
|
||||
"Monospace Font": "Sabit Aralıklı Yazı Tipi"
|
||||
},
|
||||
"Morning": {
|
||||
"Morning": ""
|
||||
},
|
||||
"Mount": {
|
||||
"Mount": "Bağlı"
|
||||
},
|
||||
@@ -1598,18 +1694,30 @@
|
||||
"New": {
|
||||
"New": "Yeni"
|
||||
},
|
||||
"New Key": {
|
||||
"New Key": ""
|
||||
},
|
||||
"New Keybind": {
|
||||
"New Keybind": ""
|
||||
},
|
||||
"New Notification": {
|
||||
"New Notification": "Yeni Bildirim"
|
||||
},
|
||||
"New York, NY": {
|
||||
"New York, NY": "New York, NY"
|
||||
},
|
||||
"Night": {
|
||||
"Night": ""
|
||||
},
|
||||
"Night Mode": {
|
||||
"Night Mode": "Gece Modu"
|
||||
},
|
||||
"Night Temperature": {
|
||||
"Night Temperature": "Gece Sıcaklığı"
|
||||
},
|
||||
"Niri compositor actions (focus, move, etc.)": {
|
||||
"Niri compositor actions (focus, move, etc.)": ""
|
||||
},
|
||||
"No": {
|
||||
"No": "Hayır"
|
||||
},
|
||||
@@ -1634,17 +1742,23 @@
|
||||
"No Weather Data Available": {
|
||||
"No Weather Data Available": "Hava Durumu Verileri Mevcut Değil"
|
||||
},
|
||||
"No action": {
|
||||
"No action": ""
|
||||
},
|
||||
"No adapters": {
|
||||
"No adapters": "Bağdaştırıcı yok"
|
||||
},
|
||||
"No changes": {
|
||||
"No changes": ""
|
||||
},
|
||||
"No clipboard entries found": {
|
||||
"No clipboard entries found": "Pano girişleri bulunamadı"
|
||||
},
|
||||
"No devices found": {
|
||||
"No devices found": ""
|
||||
"No devices found": "Aygıt bulunamadı"
|
||||
},
|
||||
"No drivers found": {
|
||||
"No drivers found": ""
|
||||
"No drivers found": "Sürücü bulunamadı"
|
||||
},
|
||||
"No files found": {
|
||||
"No files found": "Dosya bulunamadı"
|
||||
@@ -1652,6 +1766,9 @@
|
||||
"No items added yet": {
|
||||
"No items added yet": "Henüz eklenen öğe yok"
|
||||
},
|
||||
"No keybinds found": {
|
||||
"No keybinds found": ""
|
||||
},
|
||||
"No matches": {
|
||||
"No matches": "Eşleşme yok"
|
||||
},
|
||||
@@ -1665,10 +1782,10 @@
|
||||
"No printer found": "Yazıcı Bulunamadı"
|
||||
},
|
||||
"No printers configured": {
|
||||
"No printers configured": ""
|
||||
"No printers configured": "Hiçbir yazıcı ayarlanmadı"
|
||||
},
|
||||
"No printers found": {
|
||||
"No printers found": ""
|
||||
"No printers found": "Hiçbir yazıcı bulunmadı"
|
||||
},
|
||||
"None": {
|
||||
"None": "Hiçbiri"
|
||||
@@ -1751,11 +1868,14 @@
|
||||
"Open search bar to find text": {
|
||||
"Open search bar to find text": "Metin bulmak için arama çubuğunu aç"
|
||||
},
|
||||
"Open with...": {
|
||||
"Open with...": ""
|
||||
},
|
||||
"Optional description": {
|
||||
"Optional description": ""
|
||||
"Optional description": "Opsiyonel tanım"
|
||||
},
|
||||
"Optional location": {
|
||||
"Optional location": ""
|
||||
"Optional location": "Opsiyonel konum"
|
||||
},
|
||||
"Other": {
|
||||
"Other": "Diğer"
|
||||
@@ -1778,6 +1898,12 @@
|
||||
"Output Tray Missing": {
|
||||
"Output Tray Missing": "Çıktı Tepsisi Yok"
|
||||
},
|
||||
"Override": {
|
||||
"Override": ""
|
||||
},
|
||||
"Overrides": {
|
||||
"Overrides": ""
|
||||
},
|
||||
"Overview": {
|
||||
"Overview": "Genel Görünüm"
|
||||
},
|
||||
@@ -1815,7 +1941,7 @@
|
||||
"Paused": "Duraklatıldı"
|
||||
},
|
||||
"Pending": {
|
||||
"Pending": ""
|
||||
"Pending": "Beklemede"
|
||||
},
|
||||
"Per-Mode Wallpapers": {
|
||||
"Per-Mode Wallpapers": "Moda Özel Duvar Kağıtları"
|
||||
@@ -1910,9 +2036,15 @@
|
||||
"Power Profile OSD": {
|
||||
"Power Profile OSD": "Güç Profili OSD"
|
||||
},
|
||||
"Precipitation Chance": {
|
||||
"Precipitation Chance": ""
|
||||
},
|
||||
"Preference": {
|
||||
"Preference": "Tercih"
|
||||
},
|
||||
"Press key...": {
|
||||
"Press key...": ""
|
||||
},
|
||||
"Pressure": {
|
||||
"Pressure": "Basınç"
|
||||
},
|
||||
@@ -1932,16 +2064,16 @@
|
||||
"Printer": "Yazıcı"
|
||||
},
|
||||
"Printer Classes": {
|
||||
"Printer Classes": ""
|
||||
"Printer Classes": "Yazıcı Sınıfları"
|
||||
},
|
||||
"Printer created successfully": {
|
||||
"Printer created successfully": ""
|
||||
"Printer created successfully": "Yazıcı başarıyla oluşturuldu"
|
||||
},
|
||||
"Printer deleted": {
|
||||
"Printer deleted": ""
|
||||
"Printer deleted": "Yazıcı silindi"
|
||||
},
|
||||
"Printer name (no spaces)": {
|
||||
"Printer name (no spaces)": ""
|
||||
"Printer name (no spaces)": "Yazıcı adı (boşluksuz)"
|
||||
},
|
||||
"Printers": {
|
||||
"Printers": "Yazıcılar"
|
||||
@@ -2004,13 +2136,16 @@
|
||||
"Recently Used Apps": "Son Kullanılan Uygulamalar"
|
||||
},
|
||||
"Recommended available": {
|
||||
"Recommended available": ""
|
||||
"Recommended available": "Önerilen mevcut"
|
||||
},
|
||||
"Refresh": {
|
||||
"Refresh": "Yenile"
|
||||
},
|
||||
"Refresh Weather": {
|
||||
"Refresh Weather": ""
|
||||
},
|
||||
"Reject Jobs": {
|
||||
"Reject Jobs": ""
|
||||
"Reject Jobs": "İşleri Reddet"
|
||||
},
|
||||
"Reload Plugin": {
|
||||
"Reload Plugin": "Eklentiyi Yeniden Yükle"
|
||||
@@ -2069,6 +2204,12 @@
|
||||
"Run User Templates": {
|
||||
"Run User Templates": "Kullanıcı Şablonlarını Çalıştır"
|
||||
},
|
||||
"Run a program (e.g., firefox, kitty)": {
|
||||
"Run a program (e.g., firefox, kitty)": ""
|
||||
},
|
||||
"Run a shell command (e.g., notify-send)": {
|
||||
"Run a shell command (e.g., notify-send)": ""
|
||||
},
|
||||
"Running Apps": {
|
||||
"Running Apps": "Çalışan Uygulamalar"
|
||||
},
|
||||
@@ -2111,6 +2252,9 @@
|
||||
"Screen sharing": {
|
||||
"Screen sharing": "Ekran paylaşımı"
|
||||
},
|
||||
"Scroll song title": {
|
||||
"Scroll song title": ""
|
||||
},
|
||||
"Scrolling": {
|
||||
"Scrolling": "Kaydırma"
|
||||
},
|
||||
@@ -2123,6 +2267,9 @@
|
||||
"Search for a location...": {
|
||||
"Search for a location...": "Bir konum ara..."
|
||||
},
|
||||
"Search keybinds...": {
|
||||
"Search keybinds...": ""
|
||||
},
|
||||
"Search plugins...": {
|
||||
"Search plugins...": "Eklentileri ara..."
|
||||
},
|
||||
@@ -2141,6 +2288,9 @@
|
||||
"Security": {
|
||||
"Security": "Güvenlik"
|
||||
},
|
||||
"Select Application": {
|
||||
"Select Application": ""
|
||||
},
|
||||
"Select Launcher Logo": {
|
||||
"Select Launcher Logo": "Başlatıcı Logosu Seç"
|
||||
},
|
||||
@@ -2160,10 +2310,10 @@
|
||||
"Select an image file...": "Bir resim dosyası seçin..."
|
||||
},
|
||||
"Select device...": {
|
||||
"Select device...": ""
|
||||
"Select device...": "Aygıt seç..."
|
||||
},
|
||||
"Select driver...": {
|
||||
"Select driver...": ""
|
||||
"Select driver...": "Sürücü seç..."
|
||||
},
|
||||
"Select font weight": {
|
||||
"Select font weight": "Yazı tipi ağırlığını seçin"
|
||||
@@ -2186,6 +2336,9 @@
|
||||
"Select which transitions to include in randomization": {
|
||||
"Select which transitions to include in randomization": "Rastgele seçime dahil edilecek geçişleri seçin"
|
||||
},
|
||||
"Select...": {
|
||||
"Select...": ""
|
||||
},
|
||||
"Selected image file not found.": {
|
||||
"Selected image file not found.": "Seçilen resim dosyası bulunamadı."
|
||||
},
|
||||
@@ -2201,12 +2354,21 @@
|
||||
"Set different wallpapers for light and dark mode": {
|
||||
"Set different wallpapers for light and dark mode": "Karanlık ve aydınlık mod için farklı duvar kağıtları ayarlayın"
|
||||
},
|
||||
"Set key and action to save": {
|
||||
"Set key and action to save": ""
|
||||
},
|
||||
"Settings": {
|
||||
"Settings": "Ayarlar"
|
||||
},
|
||||
"Shell": {
|
||||
"Shell": ""
|
||||
},
|
||||
"Shift+Del: Clear All • Esc: Close": {
|
||||
"Shift+Del: Clear All • Esc: Close": "Shift+Del: Tümünü Temizle • Esc: Kapat"
|
||||
},
|
||||
"Shortcuts": {
|
||||
"Shortcuts": ""
|
||||
},
|
||||
"Show All Tags": {
|
||||
"Show All Tags": "Tüm Etiketleri Göster"
|
||||
},
|
||||
@@ -2381,6 +2543,12 @@
|
||||
"Storage & Disks": {
|
||||
"Storage & Disks": "Depolama & Diskler"
|
||||
},
|
||||
"Sunrise": {
|
||||
"Sunrise": ""
|
||||
},
|
||||
"Sunset": {
|
||||
"Sunset": ""
|
||||
},
|
||||
"Support Development": {
|
||||
"Support Development": "Gelişimi Destekle"
|
||||
},
|
||||
@@ -2460,10 +2628,10 @@
|
||||
"Terminals - Always use Dark Theme": "Terminaller - Her zaman Karanlı Tema kullan"
|
||||
},
|
||||
"Test Page": {
|
||||
"Test Page": ""
|
||||
"Test Page": "Test Sayfası"
|
||||
},
|
||||
"Test page sent to printer": {
|
||||
"Test page sent to printer": ""
|
||||
"Test page sent to printer": "Test Sayfası yazıcıya gönderildi"
|
||||
},
|
||||
"Text": {
|
||||
"Text": "Metin"
|
||||
@@ -2504,6 +2672,9 @@
|
||||
"Timed Out": {
|
||||
"Timed Out": "Zaman Aşımı"
|
||||
},
|
||||
"Title": {
|
||||
"Title": ""
|
||||
},
|
||||
"To Full": {
|
||||
"To Full": "Dolmasına"
|
||||
},
|
||||
@@ -2544,7 +2715,7 @@
|
||||
"Top Section": "Üst Bölüm"
|
||||
},
|
||||
"Total Jobs": {
|
||||
"Total Jobs": ""
|
||||
"Total Jobs": "Toplam İşler"
|
||||
},
|
||||
"Transition Effect": {
|
||||
"Transition Effect": "Geçiş Efekti"
|
||||
@@ -2552,6 +2723,9 @@
|
||||
"Turn off monitors after": {
|
||||
"Turn off monitors after": "Şu zaman sonra monitörleri kapat"
|
||||
},
|
||||
"Type": {
|
||||
"Type": ""
|
||||
},
|
||||
"Unavailable": {
|
||||
"Unavailable": "Mevcut Değil"
|
||||
},
|
||||
@@ -2667,7 +2841,7 @@
|
||||
"VRR: ": "VRR: "
|
||||
},
|
||||
"Version": {
|
||||
"Version": ""
|
||||
"Version": "Sürüm"
|
||||
},
|
||||
"Vertical Deck": {
|
||||
"Vertical Deck": "Dikey Deck"
|
||||
@@ -2732,6 +2906,9 @@
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": {
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": "Etkinleştirildiğinde, uygulamalar alfabetik olarak sıralanır. Devre dışı bırakıldığında, uygulamalar kullanım sıklığına göre sıralanır."
|
||||
},
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": {
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": ""
|
||||
},
|
||||
"Wi-Fi Password": {
|
||||
"Wi-Fi Password": "Wi-Fi Parolası"
|
||||
},
|
||||
@@ -2774,6 +2951,9 @@
|
||||
"Wind": {
|
||||
"Wind": "Rüzgar"
|
||||
},
|
||||
"Wind Speed": {
|
||||
"Wind Speed": ""
|
||||
},
|
||||
"Workspace": {
|
||||
"Workspace": "Çalışma Alanı"
|
||||
},
|
||||
@@ -2810,6 +2990,18 @@
|
||||
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
|
||||
"Select Wallpaper": "Duvar Kağıdı Seç"
|
||||
},
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
|
||||
},
|
||||
"dms/binds.kdl is now included in config.kdl": {
|
||||
"dms/binds.kdl is now included in config.kdl": ""
|
||||
},
|
||||
"e.g., firefox, kitty --title foo": {
|
||||
"e.g., firefox, kitty --title foo": ""
|
||||
},
|
||||
"e.g., focus-workspace 3, resize-column -10": {
|
||||
"e.g., focus-workspace 3, resize-column -10": ""
|
||||
},
|
||||
"events": {
|
||||
"events": "etkinlikler"
|
||||
},
|
||||
|
||||
@@ -74,6 +74,9 @@
|
||||
"Access to system controls and settings": {
|
||||
"Access to system controls and settings": "访问系统控制和设置"
|
||||
},
|
||||
"Action": {
|
||||
"Action": ""
|
||||
},
|
||||
"Actions": {
|
||||
"Actions": "操作"
|
||||
},
|
||||
@@ -113,9 +116,15 @@
|
||||
"Add a VPN in NetworkManager": {
|
||||
"Add a VPN in NetworkManager": "在 NetworkManager 中添加 VPN"
|
||||
},
|
||||
"Add a border around the dock": {
|
||||
"Add a border around the dock": ""
|
||||
},
|
||||
"Adjust the number of columns in grid view mode.": {
|
||||
"Adjust the number of columns in grid view mode.": "在网格模式中按需调整列的数量。"
|
||||
},
|
||||
"Afternoon": {
|
||||
"Afternoon": ""
|
||||
},
|
||||
"All": {
|
||||
"All": "全部"
|
||||
},
|
||||
@@ -329,6 +338,12 @@
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": {
|
||||
"Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen": "将锁屏绑定到来自 loginctl 的 dbus 信号。如使用外部锁屏程序,请禁用此项"
|
||||
},
|
||||
"Binds Include Missing": {
|
||||
"Binds Include Missing": ""
|
||||
},
|
||||
"Binds include added": {
|
||||
"Binds include added": ""
|
||||
},
|
||||
"Bluetooth": {
|
||||
"Bluetooth": ""
|
||||
},
|
||||
@@ -491,6 +506,12 @@
|
||||
"Click Import to add a .ovpn or .conf": {
|
||||
"Click Import to add a .ovpn or .conf": ""
|
||||
},
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": {
|
||||
"Click any shortcut to edit. Changes save to dms/binds.kdl": ""
|
||||
},
|
||||
"Click to capture": {
|
||||
"Click to capture": ""
|
||||
},
|
||||
"Clipboard History": {
|
||||
"Clipboard History": "剪切板历史记录"
|
||||
},
|
||||
@@ -524,6 +545,9 @@
|
||||
"Colorful mix of bright contrasting accents.": {
|
||||
"Colorful mix of bright contrasting accents.": "色彩鲜明、对比强烈的配色。"
|
||||
},
|
||||
"Command": {
|
||||
"Command": ""
|
||||
},
|
||||
"Command or script to run instead of the standard hibernate procedure": {
|
||||
"Command or script to run instead of the standard hibernate procedure": "用于替代标准休眠流程的命令或脚本"
|
||||
},
|
||||
@@ -575,6 +599,9 @@
|
||||
"Confirm passkey for ": {
|
||||
"Confirm passkey for ": "确认密钥 "
|
||||
},
|
||||
"Conflicts with: %1": {
|
||||
"Conflicts with: %1": ""
|
||||
},
|
||||
"Connect": {
|
||||
"Connect": "连接"
|
||||
},
|
||||
@@ -686,12 +713,18 @@
|
||||
"DMS out of date": {
|
||||
"DMS out of date": "DMS 不是最新版本"
|
||||
},
|
||||
"DMS shell actions (launcher, clipboard, etc.)": {
|
||||
"DMS shell actions (launcher, clipboard, etc.)": ""
|
||||
},
|
||||
"DMS_SOCKET not available": {
|
||||
"DMS_SOCKET not available": "DMS_SOCKET 不可用"
|
||||
},
|
||||
"DWL service not available": {
|
||||
"DWL service not available": "DWL 服务不可用"
|
||||
},
|
||||
"Daily Forecast": {
|
||||
"Daily Forecast": ""
|
||||
},
|
||||
"Daily at:": {
|
||||
"Daily at:": "在每日:"
|
||||
},
|
||||
@@ -722,6 +755,15 @@
|
||||
"Date Format": {
|
||||
"Date Format": "日期格式"
|
||||
},
|
||||
"Dawn (Astronomical Twilight)": {
|
||||
"Dawn (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dawn (Civil Twilight)": {
|
||||
"Dawn (Civil Twilight)": ""
|
||||
},
|
||||
"Dawn (Nautical Twilight)": {
|
||||
"Dawn (Nautical Twilight)": ""
|
||||
},
|
||||
"Day Temperature": {
|
||||
"Day Temperature": "日间色温"
|
||||
},
|
||||
@@ -869,6 +911,15 @@
|
||||
"Duration": {
|
||||
"Duration": "持续时间"
|
||||
},
|
||||
"Dusk (Astronomical Twilight)": {
|
||||
"Dusk (Astronomical Twilight)": ""
|
||||
},
|
||||
"Dusk (Civil Twighlight)": {
|
||||
"Dusk (Civil Twighlight)": ""
|
||||
},
|
||||
"Dusk (Nautical Twilight)": {
|
||||
"Dusk (Nautical Twilight)": ""
|
||||
},
|
||||
"Dynamic Theming": {
|
||||
"Dynamic Theming": "动态主题"
|
||||
},
|
||||
@@ -890,6 +941,9 @@
|
||||
"Enable GPU Temperature": {
|
||||
"Enable GPU Temperature": "显示 GPU 温度"
|
||||
},
|
||||
"Enable Overview Overlay": {
|
||||
"Enable Overview Overlay": ""
|
||||
},
|
||||
"Enable System Sounds": {
|
||||
"Enable System Sounds": "启用系统声音"
|
||||
},
|
||||
@@ -974,6 +1028,9 @@
|
||||
"Failed to activate configuration": {
|
||||
"Failed to activate configuration": "无法应用配置"
|
||||
},
|
||||
"Failed to add binds include": {
|
||||
"Failed to add binds include": ""
|
||||
},
|
||||
"Failed to add printer to class": {
|
||||
"Failed to add printer to class": ""
|
||||
},
|
||||
@@ -1040,6 +1097,9 @@
|
||||
"Failed to remove device": {
|
||||
"Failed to remove device": "删除设备失败"
|
||||
},
|
||||
"Failed to remove keybind": {
|
||||
"Failed to remove keybind": ""
|
||||
},
|
||||
"Failed to remove printer from class": {
|
||||
"Failed to remove printer from class": ""
|
||||
},
|
||||
@@ -1049,6 +1109,9 @@
|
||||
"Failed to resume printer": {
|
||||
"Failed to resume printer": "无法恢复打印机"
|
||||
},
|
||||
"Failed to save keybind": {
|
||||
"Failed to save keybind": ""
|
||||
},
|
||||
"Failed to set profile image": {
|
||||
"Failed to set profile image": "无法设置个人资料图片"
|
||||
},
|
||||
@@ -1091,6 +1154,12 @@
|
||||
"Find in note...": {
|
||||
"Find in note...": "在便签中查找..."
|
||||
},
|
||||
"Fix Now": {
|
||||
"Fix Now": ""
|
||||
},
|
||||
"Fixing...": {
|
||||
"Fixing...": ""
|
||||
},
|
||||
"Focused Window": {
|
||||
"Focused Window": "当前窗口"
|
||||
},
|
||||
@@ -1115,6 +1184,9 @@
|
||||
"Force terminal applications to always use dark color schemes": {
|
||||
"Force terminal applications to always use dark color schemes": "强制终端应用使用暗色"
|
||||
},
|
||||
"Forecast Not Available": {
|
||||
"Forecast Not Available": ""
|
||||
},
|
||||
"Forget": {
|
||||
"Forget": ""
|
||||
},
|
||||
@@ -1157,6 +1229,9 @@
|
||||
"Github:": {
|
||||
"Github:": "Github:"
|
||||
},
|
||||
"Golden Hour": {
|
||||
"Golden Hour": ""
|
||||
},
|
||||
"Good": {
|
||||
"Good": "良好"
|
||||
},
|
||||
@@ -1226,9 +1301,15 @@
|
||||
"Hold to confirm (%1s)": {
|
||||
"Hold to confirm (%1s)": ""
|
||||
},
|
||||
"Hotkey overlay title (optional)": {
|
||||
"Hotkey overlay title (optional)": ""
|
||||
},
|
||||
"Hour": {
|
||||
"Hour": "小时"
|
||||
},
|
||||
"Hourly Forecast": {
|
||||
"Hourly Forecast": ""
|
||||
},
|
||||
"How often to change wallpaper": {
|
||||
"How often to change wallpaper": "壁纸轮换频率"
|
||||
},
|
||||
@@ -1328,9 +1409,18 @@
|
||||
"Keeping Awake": {
|
||||
"Keeping Awake": "保持活动"
|
||||
},
|
||||
"Key": {
|
||||
"Key": ""
|
||||
},
|
||||
"Keyboard Layout Name": {
|
||||
"Keyboard Layout Name": "键盘布局名称"
|
||||
},
|
||||
"Keyboard Shortcuts": {
|
||||
"Keyboard Shortcuts": ""
|
||||
},
|
||||
"Keys": {
|
||||
"Keys": ""
|
||||
},
|
||||
"Kill Process": {
|
||||
"Kill Process": "结束进程"
|
||||
},
|
||||
@@ -1385,6 +1475,9 @@
|
||||
"Lively palette with saturated accents.": {
|
||||
"Lively palette with saturated accents.": "活力十足的配色,带有高饱和点缀色。"
|
||||
},
|
||||
"Loading keybinds...": {
|
||||
"Loading keybinds...": ""
|
||||
},
|
||||
"Loading plugins...": {
|
||||
"Loading plugins...": "正在加载插件…..."
|
||||
},
|
||||
@@ -1550,6 +1643,9 @@
|
||||
"Monospace Font": {
|
||||
"Monospace Font": "等宽字体"
|
||||
},
|
||||
"Morning": {
|
||||
"Morning": ""
|
||||
},
|
||||
"Mount": {
|
||||
"Mount": "挂载"
|
||||
},
|
||||
@@ -1598,18 +1694,30 @@
|
||||
"New": {
|
||||
"New": "新建"
|
||||
},
|
||||
"New Key": {
|
||||
"New Key": ""
|
||||
},
|
||||
"New Keybind": {
|
||||
"New Keybind": ""
|
||||
},
|
||||
"New Notification": {
|
||||
"New Notification": "新通知"
|
||||
},
|
||||
"New York, NY": {
|
||||
"New York, NY": "纽约,美国纽约州"
|
||||
},
|
||||
"Night": {
|
||||
"Night": ""
|
||||
},
|
||||
"Night Mode": {
|
||||
"Night Mode": "夜间模式"
|
||||
},
|
||||
"Night Temperature": {
|
||||
"Night Temperature": "夜间色温"
|
||||
},
|
||||
"Niri compositor actions (focus, move, etc.)": {
|
||||
"Niri compositor actions (focus, move, etc.)": ""
|
||||
},
|
||||
"No": {
|
||||
"No": ""
|
||||
},
|
||||
@@ -1634,9 +1742,15 @@
|
||||
"No Weather Data Available": {
|
||||
"No Weather Data Available": "暂无天气数据"
|
||||
},
|
||||
"No action": {
|
||||
"No action": ""
|
||||
},
|
||||
"No adapters": {
|
||||
"No adapters": ""
|
||||
},
|
||||
"No changes": {
|
||||
"No changes": ""
|
||||
},
|
||||
"No clipboard entries found": {
|
||||
"No clipboard entries found": "无可用记录"
|
||||
},
|
||||
@@ -1652,6 +1766,9 @@
|
||||
"No items added yet": {
|
||||
"No items added yet": "暂未添加任何项目"
|
||||
},
|
||||
"No keybinds found": {
|
||||
"No keybinds found": ""
|
||||
},
|
||||
"No matches": {
|
||||
"No matches": "未找到匹配项"
|
||||
},
|
||||
@@ -1751,6 +1868,9 @@
|
||||
"Open search bar to find text": {
|
||||
"Open search bar to find text": "打开搜索栏以查找文本"
|
||||
},
|
||||
"Open with...": {
|
||||
"Open with...": ""
|
||||
},
|
||||
"Optional description": {
|
||||
"Optional description": ""
|
||||
},
|
||||
@@ -1778,6 +1898,12 @@
|
||||
"Output Tray Missing": {
|
||||
"Output Tray Missing": "未检测到出纸盒"
|
||||
},
|
||||
"Override": {
|
||||
"Override": ""
|
||||
},
|
||||
"Overrides": {
|
||||
"Overrides": ""
|
||||
},
|
||||
"Overview": {
|
||||
"Overview": "概览"
|
||||
},
|
||||
@@ -1910,9 +2036,15 @@
|
||||
"Power Profile OSD": {
|
||||
"Power Profile OSD": "OSD电源配置"
|
||||
},
|
||||
"Precipitation Chance": {
|
||||
"Precipitation Chance": ""
|
||||
},
|
||||
"Preference": {
|
||||
"Preference": ""
|
||||
},
|
||||
"Press key...": {
|
||||
"Press key...": ""
|
||||
},
|
||||
"Pressure": {
|
||||
"Pressure": "气压"
|
||||
},
|
||||
@@ -2009,6 +2141,9 @@
|
||||
"Refresh": {
|
||||
"Refresh": "刷新"
|
||||
},
|
||||
"Refresh Weather": {
|
||||
"Refresh Weather": ""
|
||||
},
|
||||
"Reject Jobs": {
|
||||
"Reject Jobs": ""
|
||||
},
|
||||
@@ -2069,6 +2204,12 @@
|
||||
"Run User Templates": {
|
||||
"Run User Templates": "运行用户模板"
|
||||
},
|
||||
"Run a program (e.g., firefox, kitty)": {
|
||||
"Run a program (e.g., firefox, kitty)": ""
|
||||
},
|
||||
"Run a shell command (e.g., notify-send)": {
|
||||
"Run a shell command (e.g., notify-send)": ""
|
||||
},
|
||||
"Running Apps": {
|
||||
"Running Apps": "活动应用程序"
|
||||
},
|
||||
@@ -2111,6 +2252,9 @@
|
||||
"Screen sharing": {
|
||||
"Screen sharing": "屏幕分享"
|
||||
},
|
||||
"Scroll song title": {
|
||||
"Scroll song title": ""
|
||||
},
|
||||
"Scrolling": {
|
||||
"Scrolling": "滚动"
|
||||
},
|
||||
@@ -2123,6 +2267,9 @@
|
||||
"Search for a location...": {
|
||||
"Search for a location...": "搜索位置..."
|
||||
},
|
||||
"Search keybinds...": {
|
||||
"Search keybinds...": ""
|
||||
},
|
||||
"Search plugins...": {
|
||||
"Search plugins...": "搜索插件中..."
|
||||
},
|
||||
@@ -2141,6 +2288,9 @@
|
||||
"Security": {
|
||||
"Security": ""
|
||||
},
|
||||
"Select Application": {
|
||||
"Select Application": ""
|
||||
},
|
||||
"Select Launcher Logo": {
|
||||
"Select Launcher Logo": "选择启动器Logo"
|
||||
},
|
||||
@@ -2186,6 +2336,9 @@
|
||||
"Select which transitions to include in randomization": {
|
||||
"Select which transitions to include in randomization": "选择在随机轮换中使用的过渡效果"
|
||||
},
|
||||
"Select...": {
|
||||
"Select...": ""
|
||||
},
|
||||
"Selected image file not found.": {
|
||||
"Selected image file not found.": "未找到所选图像文件。"
|
||||
},
|
||||
@@ -2201,12 +2354,21 @@
|
||||
"Set different wallpapers for light and dark mode": {
|
||||
"Set different wallpapers for light and dark mode": "分别设置浅色/深色模式下的壁纸"
|
||||
},
|
||||
"Set key and action to save": {
|
||||
"Set key and action to save": ""
|
||||
},
|
||||
"Settings": {
|
||||
"Settings": "设置"
|
||||
},
|
||||
"Shell": {
|
||||
"Shell": ""
|
||||
},
|
||||
"Shift+Del: Clear All • Esc: Close": {
|
||||
"Shift+Del: Clear All • Esc: Close": "Shift+Del: 清空 • Esc: 关闭"
|
||||
},
|
||||
"Shortcuts": {
|
||||
"Shortcuts": ""
|
||||
},
|
||||
"Show All Tags": {
|
||||
"Show All Tags": "显示所有标签"
|
||||
},
|
||||
@@ -2381,6 +2543,12 @@
|
||||
"Storage & Disks": {
|
||||
"Storage & Disks": "存储与磁盘"
|
||||
},
|
||||
"Sunrise": {
|
||||
"Sunrise": ""
|
||||
},
|
||||
"Sunset": {
|
||||
"Sunset": ""
|
||||
},
|
||||
"Support Development": {
|
||||
"Support Development": "支持开发"
|
||||
},
|
||||
@@ -2504,6 +2672,9 @@
|
||||
"Timed Out": {
|
||||
"Timed Out": "超时"
|
||||
},
|
||||
"Title": {
|
||||
"Title": ""
|
||||
},
|
||||
"To Full": {
|
||||
"To Full": "充至满电"
|
||||
},
|
||||
@@ -2552,6 +2723,9 @@
|
||||
"Turn off monitors after": {
|
||||
"Turn off monitors after": "在此时间后关闭显示器"
|
||||
},
|
||||
"Type": {
|
||||
"Type": ""
|
||||
},
|
||||
"Unavailable": {
|
||||
"Unavailable": ""
|
||||
},
|
||||
@@ -2732,6 +2906,9 @@
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": {
|
||||
"When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.": "启用后,应用按字母顺序排序;禁用则按使用频率排序"
|
||||
},
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": {
|
||||
"When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.": ""
|
||||
},
|
||||
"Wi-Fi Password": {
|
||||
"Wi-Fi Password": ""
|
||||
},
|
||||
@@ -2774,6 +2951,9 @@
|
||||
"Wind": {
|
||||
"Wind": "风速"
|
||||
},
|
||||
"Wind Speed": {
|
||||
"Wind Speed": ""
|
||||
},
|
||||
"Workspace": {
|
||||
"Workspace": "工作区"
|
||||
},
|
||||
@@ -2810,6 +2990,18 @@
|
||||
"dark mode wallpaper file browser title | light mode wallpaper file browser title | wallpaper file browser title": {
|
||||
"Select Wallpaper": "选择壁纸"
|
||||
},
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": {
|
||||
"dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.": ""
|
||||
},
|
||||
"dms/binds.kdl is now included in config.kdl": {
|
||||
"dms/binds.kdl is now included in config.kdl": ""
|
||||
},
|
||||
"e.g., firefox, kitty --title foo": {
|
||||
"e.g., firefox, kitty --title foo": ""
|
||||
},
|
||||
"e.g., focus-workspace 3, resize-column -10": {
|
||||
"e.g., focus-workspace 3, resize-column -10": ""
|
||||
},
|
||||
"events": {
|
||||
"events": "事件"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -104,13 +104,6 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "7-Day Forecast",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "A file with this name already exists. Do you want to overwrite it?",
|
||||
"translation": "",
|
||||
@@ -174,6 +167,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Action",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Actions",
|
||||
"translation": "",
|
||||
@@ -251,6 +251,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Add a border around the dock",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Adjust the number of columns in grid view mode.",
|
||||
"translation": "",
|
||||
@@ -258,6 +265,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Afternoon",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "All",
|
||||
"translation": "",
|
||||
@@ -713,6 +727,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Binds Include Missing",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Binds include added",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Bluetooth",
|
||||
"translation": "",
|
||||
@@ -1077,6 +1105,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Click any shortcut to edit. Changes save to dms/binds.kdl",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Click to capture",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Clipboard History",
|
||||
"translation": "",
|
||||
@@ -1154,6 +1196,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Command or script to run instead of the standard hibernate procedure",
|
||||
"translation": "",
|
||||
@@ -1273,6 +1322,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Conflicts with: %1",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Connect",
|
||||
"translation": "",
|
||||
@@ -1518,6 +1574,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "DMS shell actions (launcher, clipboard, etc.)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "DMS_SOCKET not available",
|
||||
"translation": "",
|
||||
@@ -1532,6 +1595,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Daily Forecast",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Daily at:",
|
||||
"translation": "",
|
||||
@@ -1588,6 +1658,27 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dawn (Astronomical Twilight)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dawn (Civil Twilight)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dawn (Nautical Twilight)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Day Temperature",
|
||||
"translation": "",
|
||||
@@ -1931,6 +2022,27 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dusk (Astronomical Twilight)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dusk (Civil Twighlight)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dusk (Nautical Twilight)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Dynamic Theming",
|
||||
"translation": "",
|
||||
@@ -1980,6 +2092,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Enable Overview Overlay",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Enable System Sounds",
|
||||
"translation": "",
|
||||
@@ -2176,6 +2295,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Failed to add binds include",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Failed to add printer to class",
|
||||
"translation": "",
|
||||
@@ -2330,6 +2456,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Failed to remove keybind",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Failed to remove printer from class",
|
||||
"translation": "",
|
||||
@@ -2351,6 +2484,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Failed to save keybind",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Failed to set profile image",
|
||||
"translation": "",
|
||||
@@ -2449,6 +2589,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Fix Now",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Fixing...",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Focused Window",
|
||||
"translation": "",
|
||||
@@ -2505,6 +2659,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Forecast Not Available",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Forget",
|
||||
"translation": "",
|
||||
@@ -2603,6 +2764,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Golden Hour",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Good",
|
||||
"translation": "",
|
||||
@@ -2757,6 +2925,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Hotkey overlay title (optional)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Hour",
|
||||
"translation": "",
|
||||
@@ -2764,6 +2939,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Hourly Forecast",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "How often to change wallpaper",
|
||||
"translation": "",
|
||||
@@ -2995,6 +3177,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Key",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Keyboard Layout Name",
|
||||
"translation": "",
|
||||
@@ -3002,6 +3191,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Keyboard Shortcuts",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Keys",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Kill Process",
|
||||
"translation": "",
|
||||
@@ -3128,6 +3331,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Loading keybinds...",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Loading plugins...",
|
||||
"translation": "",
|
||||
@@ -3513,6 +3723,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Morning",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Mount",
|
||||
"translation": "",
|
||||
@@ -3618,6 +3835,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "New Key",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "New Keybind",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "New Notification",
|
||||
"translation": "",
|
||||
@@ -3632,6 +3863,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Night",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Night Mode",
|
||||
"translation": "",
|
||||
@@ -3646,6 +3884,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Niri compositor actions (focus, move, etc.)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No",
|
||||
"translation": "",
|
||||
@@ -3695,6 +3940,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No action",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No adapters",
|
||||
"translation": "",
|
||||
@@ -3702,6 +3954,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No changes",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No clipboard entries found",
|
||||
"translation": "",
|
||||
@@ -3737,6 +3996,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No keybinds found",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "No matches",
|
||||
"translation": "",
|
||||
@@ -3968,6 +4234,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Open with...",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Optional description",
|
||||
"translation": "",
|
||||
@@ -4031,6 +4304,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Override",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Overrides",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Overview",
|
||||
"translation": "",
|
||||
@@ -4339,6 +4626,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Precipitation Chance",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Preference",
|
||||
"translation": "",
|
||||
@@ -4346,6 +4640,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Press key...",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Pressure",
|
||||
"translation": "",
|
||||
@@ -4570,6 +4871,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Refresh Weather",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Reject Jobs",
|
||||
"translation": "",
|
||||
@@ -4696,6 +5004,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Run a program (e.g., firefox, kitty)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Run a shell command (e.g., notify-send)",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Running Apps",
|
||||
"translation": "",
|
||||
@@ -4794,6 +5116,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Scroll song title",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Scrolling",
|
||||
"translation": "",
|
||||
@@ -4822,6 +5151,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Search keybinds...",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Search plugins...",
|
||||
"translation": "",
|
||||
@@ -4864,6 +5200,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Select Application",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Select Custom Theme",
|
||||
"translation": "",
|
||||
@@ -4990,6 +5333,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Select...",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Selected image file not found.",
|
||||
"translation": "",
|
||||
@@ -5025,6 +5375,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Set key and action to save",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Settings",
|
||||
"translation": "",
|
||||
@@ -5032,6 +5389,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Shell",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Shift+Del: Clear All • Esc: Close",
|
||||
"translation": "",
|
||||
@@ -5039,6 +5403,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Shortcuts",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Show All Tags",
|
||||
"translation": "",
|
||||
@@ -5438,6 +5809,20 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Sunrise",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Sunset",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Support Development",
|
||||
"translation": "",
|
||||
@@ -5718,6 +6103,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Title",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "To Full",
|
||||
"translation": "",
|
||||
@@ -5830,6 +6222,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Type",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Unavailable",
|
||||
"translation": "",
|
||||
@@ -6236,6 +6635,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "When enabled, shows the launcher overlay when typing in Niri overview mode. Disable this if you prefer to not have the launcher when typing on Niri overview or want to use other launcher in the overview.",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Wi-Fi Password",
|
||||
"translation": "",
|
||||
@@ -6334,6 +6740,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Wind Speed",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Workspace",
|
||||
"translation": "",
|
||||
@@ -6404,6 +6817,34 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "dms/binds.kdl is not included in config.kdl. Custom keybinds will not work until this is fixed.",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "dms/binds.kdl is now included in config.kdl",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "e.g., firefox, kitty --title foo",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "e.g., focus-workspace 3, resize-column -10",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "events",
|
||||
"translation": "",
|
||||
|
||||
Reference in New Issue
Block a user