1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-31 08:52:49 -05:00

Compare commits

..

19 Commits

Author SHA1 Message Date
bbedward
119b5df6df gamma: fix initial night mode enablement 2025-12-12 10:15:38 -05:00
bbedward
8ede810d32 settings: make default height screen-aware 2025-12-12 10:14:33 -05:00
bbedward
830dd93af5 chore: bump version to v1.0.1 2025-12-12 10:04:47 -05:00
bbedward
75f28c5ea7 ci: switch to dispatch-based release flow 2025-12-12 10:04:20 -05:00
bbedward
6c9b8c590e dankinstall: call add-wants for niri/hyprland with dms service 2025-12-12 10:04:20 -05:00
bbedward
24d9b77307 niri: fix keybind handling of cooldown-ms parameter 2025-12-12 10:04:20 -05:00
bbedward
d4be68912c workspaces: make icons scale with bar size, fixi valign of numbers fixes #990 2025-12-12 10:04:20 -05:00
bbedward
a443721000 core: fix socket reported CLI version 2025-12-12 10:03:32 -05:00
bbedward
786b097187 plugins: hide uninstall and update buttons for system plugins 2025-12-12 10:03:18 -05:00
bbedward
8ca60c7d2a dwl: fix layout popout not opening fixes #980 2025-12-12 10:03:04 -05:00
bbedward
406dc64aba wf: disable update-versions job 2025-12-10 10:50:47 -05:00
dms-ci[bot]
af5d6a2015 chore: bump version to v1.0.0 2025-12-10 15:43:36 +00:00
bbedward
61c6f509ae i18n: update translations 2025-12-10 09:32:57 -05:00
Marcus Ramberg
98769ecd88 nix: switch to standard nixpkgs rfc formatting (#962) 2025-12-10 04:55:45 -03:00
bbedward
8615950bd6 cc: allow 75 width sliders 2025-12-10 00:48:27 -05:00
bbedward
1bec8dfc48 vpn: make import modal floating variant 2025-12-10 00:30:45 -05:00
bbedward
460486fe25 media: fix media player updates 2025-12-09 23:59:04 -05:00
bbedward
318c50bc6c media: block scrolling media volume in widget when no player vol avail 2025-12-09 23:45:01 -05:00
purian23
3e08bac7f3 distros: Prep dms-git build versioning 2025-12-09 23:25:34 -05:00
37 changed files with 969 additions and 716 deletions

View File

@@ -1,16 +1,19 @@
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to release (e.g., v1.0.1)'
required: true
type: string
permissions:
contents: write
actions: write
concurrency:
group: release-${{ github.ref_name }}
group: release-${{ inputs.tag }}
cancel-in-progress: true
jobs:
@@ -24,10 +27,14 @@ jobs:
run:
working-directory: core
env:
TAG: ${{ inputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
fetch-depth: 0
- name: Set up Go
@@ -54,7 +61,7 @@ jobs:
run: |
set -eux
cd cmd/dankinstall
go build -trimpath -ldflags "-s -w -X main.Version=${GITHUB_REF#refs/tags/}" \
go build -trimpath -ldflags "-s -w -X main.Version=${TAG}" \
-o ../../dankinstall-${{ matrix.arch }}
cd ../..
gzip -9 -k dankinstall-${{ matrix.arch }}
@@ -68,7 +75,7 @@ jobs:
run: |
set -eux
cd cmd/dms
go build -trimpath -ldflags "-s -w -X main.Version=${GITHUB_REF#refs/tags/}" \
go build -trimpath -ldflags "-s -w -X main.Version=${TAG}" \
-o ../../dms-${{ matrix.arch }}
cd ../..
gzip -9 -k dms-${{ matrix.arch }}
@@ -91,7 +98,7 @@ jobs:
run: |
set -eux
cd cmd/dms
go build -trimpath -tags distro_binary -ldflags "-s -w -X main.Version=${GITHUB_REF#refs/tags/}" \
go build -trimpath -tags distro_binary -ldflags "-s -w -X main.Version=${TAG}" \
-o ../../dms-distropkg-${{ matrix.arch }}
cd ../..
gzip -9 -k dms-distropkg-${{ matrix.arch }}
@@ -128,60 +135,61 @@ jobs:
core/completion.zsh
if-no-files-found: error
update-versions:
runs-on: ubuntu-latest
needs: build-core
steps:
- name: Create GitHub App token
id: app_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
# update-versions:
# runs-on: ubuntu-latest
# needs: build-core
# steps:
# - name: Create GitHub App token
# id: app_token
# uses: actions/create-github-app-token@v1
# with:
# app-id: ${{ secrets.APP_ID }}
# private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ steps.app_token.outputs.token }}
fetch-depth: 0
# - name: Checkout
# uses: actions/checkout@v4
# with:
# token: ${{ steps.app_token.outputs.token }}
# fetch-depth: 0
- name: Update VERSION
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
run: |
set -euo pipefail
git config user.name "dms-ci[bot]"
git config user.email "dms-ci[bot]@users.noreply.github.com"
# - name: Update VERSION
# env:
# GH_TOKEN: ${{ steps.app_token.outputs.token }}
# run: |
# set -euo pipefail
# git config user.name "dms-ci[bot]"
# git config user.email "dms-ci[bot]@users.noreply.github.com"
version="${GITHUB_REF#refs/tags/}"
echo "Updating to version: $version"
echo "${version}" > quickshell/VERSION
git add quickshell/VERSION
# version="${GITHUB_REF#refs/tags/}"
# echo "Updating to version: $version"
# echo "${version}" > quickshell/VERSION
# git add quickshell/VERSION
if ! git diff --cached --quiet; then
git commit -m "chore: bump version to $version"
git pull --rebase origin master
git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:master
fi
# if ! git diff --cached --quiet; then
# git commit -m "chore: bump version to $version"
# git pull --rebase origin master
# git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:master
# fi
git tag -f "${version}"
git push -f https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git "${version}"
# git tag -f "${version}"
# git push -f https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git "${version}"
release:
runs-on: ubuntu-24.04
needs: [build-core, update-versions]
needs: [build-core] #, update-versions]
env:
TAG: ${{ github.ref_name }}
TAG: ${{ inputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
fetch-depth: 0
- name: Fetch updated tag after version bump
run: |
git fetch origin --force tag ${{ github.ref_name }}
git checkout ${{ github.ref_name }}
git fetch origin --force tag ${TAG}
git checkout ${TAG}
- name: Download core artifacts
uses: actions/download-artifact@v4
@@ -391,9 +399,13 @@ jobs:
trigger-obs-update:
runs-on: ubuntu-latest
needs: release
env:
TAG: ${{ inputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Install OSC
run: |
@@ -413,16 +425,19 @@ jobs:
- name: Update OBS packages
run: |
VERSION="${{ github.ref_name }}"
cd distro
bash scripts/obs-upload.sh dms "Update to $VERSION"
bash scripts/obs-upload.sh dms "Update to ${TAG}"
trigger-ppa-update:
runs-on: ubuntu-latest
needs: release
env:
TAG: ${{ inputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Install build dependencies
run: |
@@ -446,7 +461,6 @@ jobs:
- name: Upload to PPA
run: |
VERSION="${{ github.ref_name }}"
cd distro/ubuntu/ppa
bash create-and-upload.sh ../dms dms questing
@@ -454,11 +468,13 @@ jobs:
runs-on: ubuntu-latest
needs: release
env:
TAG: ${{ github.ref_name }}
TAG: ${{ inputs.tag }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}
- name: Determine version
id: version

View File

@@ -1 +0,0 @@
indentation = "FourSpaces"

View File

@@ -155,6 +155,7 @@ func runShellInteractive(session bool) {
errChan <- fmt.Errorf("server panic: %v", r)
}
}()
server.CLIVersion = Version
if err := server.Start(false); err != nil {
errChan <- fmt.Errorf("server error: %w", err)
}

View File

@@ -344,7 +344,7 @@ func (a *ArchDistribution) InstallPackages(ctx context.Context, dependencies []d
a.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
}
if err := a.EnableDMSService(ctx); err != nil {
if err := a.EnableDMSService(ctx, wm); err != nil {
a.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
}

View File

@@ -597,12 +597,24 @@ TERMINAL=%s
return nil
}
func (b *BaseDistribution) EnableDMSService(ctx context.Context) error {
func (b *BaseDistribution) EnableDMSService(ctx context.Context, wm deps.WindowManager) error {
cmd := exec.CommandContext(ctx, "systemctl", "--user", "enable", "--now", "dms")
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to enable dms service: %w", err)
}
b.log("Enabled dms systemd user service")
switch wm {
case deps.WindowManagerNiri:
if err := exec.CommandContext(ctx, "systemctl", "--user", "add-wants", "niri.service", "dms").Run(); err != nil {
b.log("Warning: failed to add dms as a want for niri.service")
}
case deps.WindowManagerHyprland:
if err := exec.CommandContext(ctx, "systemctl", "--user", "add-wants", "hyprland-session.target", "dms").Run(); err != nil {
b.log("Warning: failed to add dms as a want for hyprland-session.target")
}
}
return nil
}

View File

@@ -312,7 +312,7 @@ func (d *DebianDistribution) InstallPackages(ctx context.Context, dependencies [
d.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
}
if err := d.EnableDMSService(ctx); err != nil {
if err := d.EnableDMSService(ctx, wm); err != nil {
d.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
}

View File

@@ -353,7 +353,7 @@ func (f *FedoraDistribution) InstallPackages(ctx context.Context, dependencies [
f.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
}
if err := f.EnableDMSService(ctx); err != nil {
if err := f.EnableDMSService(ctx, wm); err != nil {
f.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
}

View File

@@ -410,7 +410,7 @@ func (g *GentooDistribution) InstallPackages(ctx context.Context, dependencies [
g.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
}
if err := g.EnableDMSService(ctx); err != nil {
if err := g.EnableDMSService(ctx, wm); err != nil {
g.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
}

View File

@@ -371,7 +371,7 @@ func (o *OpenSUSEDistribution) InstallPackages(ctx context.Context, dependencies
o.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
}
if err := o.EnableDMSService(ctx); err != nil {
if err := o.EnableDMSService(ctx, wm); err != nil {
o.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
}

View File

@@ -331,7 +331,7 @@ func (u *UbuntuDistribution) InstallPackages(ctx context.Context, dependencies [
u.log(fmt.Sprintf("Warning: failed to write window manager config: %v", err))
}
if err := u.EnableDMSService(ctx); err != nil {
if err := u.EnableDMSService(ctx, wm); err != nil {
u.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err))
}

View File

@@ -6,6 +6,7 @@ import (
"os/exec"
"path/filepath"
"sort"
"strconv"
"strings"
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
@@ -153,6 +154,7 @@ func (n *NiriProvider) convertKeybind(kb *NiriKeyBinding, subcategory string, co
Subcategory: subcategory,
Source: source,
HideOnOverlay: kb.HideOnOverlay,
CooldownMs: kb.CooldownMs,
}
if source == "dms" && conflicts != nil {
@@ -310,7 +312,9 @@ func (n *NiriProvider) extractOptions(node *document.Node) map[string]any {
opts["repeat"] = val.String() == "true"
}
if val, ok := node.Properties.Get("cooldown-ms"); ok {
opts["cooldown-ms"] = val.String()
if ms, err := strconv.Atoi(val.String()); err == nil {
opts["cooldown-ms"] = ms
}
}
if val, ok := node.Properties.Get("allow-when-locked"); ok {
opts["allow-when-locked"] = val.String() == "true"
@@ -336,7 +340,14 @@ func (n *NiriProvider) buildBindNode(bind *overrideBind) *document.Node {
node.AddProperty("repeat", false, "")
}
if v, ok := bind.Options["cooldown-ms"]; ok {
node.AddProperty("cooldown-ms", v, "")
switch val := v.(type) {
case int:
node.AddProperty("cooldown-ms", val, "")
case string:
if ms, err := strconv.Atoi(val); err == nil {
node.AddProperty("cooldown-ms", ms, "")
}
}
}
if v, ok := bind.Options["allow-when-locked"]; ok && v == true {
node.AddProperty("allow-when-locked", true, "")

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/sblinch/kdl-go"
@@ -17,6 +18,7 @@ type NiriKeyBinding struct {
Args []string
Description string
HideOnOverlay bool
CooldownMs int
Source string
}
@@ -275,6 +277,7 @@ func (p *NiriParser) parseKeybindNode(node *document.Node, _ string) *NiriKeyBin
var description string
var hideOnOverlay bool
var cooldownMs int
if node.Properties != nil {
if val, ok := node.Properties.Get("hotkey-overlay-title"); ok {
switch val.ValueString() {
@@ -284,6 +287,9 @@ func (p *NiriParser) parseKeybindNode(node *document.Node, _ string) *NiriKeyBin
description = val.ValueString()
}
}
if val, ok := node.Properties.Get("cooldown-ms"); ok {
cooldownMs, _ = strconv.Atoi(val.String())
}
}
return &NiriKeyBinding{
@@ -293,6 +299,7 @@ func (p *NiriParser) parseKeybindNode(node *document.Node, _ string) *NiriKeyBin
Args: args,
Description: description,
HideOnOverlay: hideOnOverlay,
CooldownMs: cooldownMs,
Source: p.currentSource,
}
}

View File

@@ -7,6 +7,7 @@ type Keybind struct {
Subcategory string `json:"subcat,omitempty"`
Source string `json:"source,omitempty"`
HideOnOverlay bool `json:"hideOnOverlay,omitempty"`
CooldownMs int `json:"cooldownMs,omitempty"`
Conflict *Keybind `json:"conflict,omitempty"`
}

View File

@@ -643,6 +643,16 @@ func (m *Manager) applyCurrentTemp() {
return
}
m.configMutex.RLock()
low, high := m.config.LowTemp, m.config.HighTemp
m.configMutex.RUnlock()
if low == high {
m.applyGamma(low)
m.updateStateFromSchedule()
return
}
if !m.hasValidSchedule() {
m.updateStateFromSchedule()
return

View File

@@ -5,7 +5,7 @@
%global pkg_summary DankMaterialShell - Material 3 inspired shell for Wayland compositors
Name: dms
Epoch: 1
Epoch: 2
Version: %{version}
Release: 1%{?dist}
Summary: %{pkg_summary}

View File

@@ -4,13 +4,14 @@
pkgs,
dmsPkgs,
...
}: let
}:
let
cfg = config.programs.dankMaterialShell;
in {
in
{
qmlPath = "${dmsPkgs.dms-shell}/share/quickshell/dms";
packages =
[
packages = [
pkgs.material-symbols
pkgs.inter
pkgs.fira-code
@@ -22,8 +23,14 @@ in {
dmsPkgs.dms-shell
]
++ lib.optional cfg.enableSystemMonitoring dmsPkgs.dgop
++ lib.optionals cfg.enableClipboard [pkgs.cliphist pkgs.wl-clipboard]
++ lib.optionals cfg.enableVPN [pkgs.glib pkgs.networkmanager]
++ lib.optionals cfg.enableClipboard [
pkgs.cliphist
pkgs.wl-clipboard
]
++ lib.optionals cfg.enableVPN [
pkgs.glib
pkgs.networkmanager
]
++ lib.optional cfg.enableBrightnessControl pkgs.brightnessctl
++ lib.optional cfg.enableColorPicker pkgs.hyprpicker
++ lib.optional cfg.enableDynamicTheming pkgs.matugen

View File

@@ -4,16 +4,24 @@
pkgs,
dmsPkgs,
...
}: let
}:
let
inherit (lib) types;
cfg = config.programs.dankMaterialShell.greeter;
user = config.services.greetd.settings.default_session.user;
inherit (config.services.greetd.settings.default_session) user;
cacheDir = "/var/lib/dms-greeter";
greeterScript = pkgs.writeShellScriptBin "dms-greeter" ''
export PATH=$PATH:${lib.makeBinPath [cfg.quickshell.package config.programs.${cfg.compositor.name}.package]}
${lib.escapeShellArgs ([
export PATH=$PATH:${
lib.makeBinPath [
cfg.quickshell.package
config.programs.${cfg.compositor.name}.package
]
}
${
lib.escapeShellArgs (
[
"sh"
"${../../quickshell/Modules/Greetd/assets/dms-greeter}"
"--cache-dir"
@@ -26,19 +34,36 @@
++ lib.optionals (cfg.compositor.customConfig != "") [
"-C"
"${pkgs.writeText "dmsgreeter-compositor-config" cfg.compositor.customConfig}"
])} ${lib.optionalString cfg.logs.save "> ${cfg.logs.path} 2>&1"}
]
)
} ${lib.optionalString cfg.logs.save "> ${cfg.logs.path} 2>&1"}
'';
jq = lib.getExe pkgs.jq;
in {
imports = let
in
{
imports =
let
msg = "The option 'programs.dankMaterialShell.greeter.compositor.extraConfig' is deprecated. Please use 'programs.dankMaterialShell.greeter.compositor.customConfig' instead.";
in [(lib.mkRemovedOptionModule ["programs" "dankMaterialShell" "greeter" "compositor" "extraConfig"] msg)];
in
[
(lib.mkRemovedOptionModule [
"programs"
"dankMaterialShell"
"greeter"
"compositor"
"extraConfig"
] msg)
];
options.programs.dankMaterialShell.greeter = {
enable = lib.mkEnableOption "DankMaterialShell greeter";
compositor.name = lib.mkOption {
type = types.enum ["niri" "hyprland" "sway" "scroll"];
type = types.enum [
"niri"
"hyprland"
"sway"
];
description = "Compositor to run greeter in";
};
compositor.customConfig = lib.mkOption {
@@ -97,22 +122,21 @@ in {
];
systemd.tmpfiles.settings."10-dmsgreeter" = {
${cacheDir}.d = {
user = user;
inherit user;
group =
if config.users.users.${user}.group != ""
then config.users.users.${user}.group
else "greeter";
if config.users.users.${user}.group != "" then config.users.users.${user}.group else "greeter";
mode = "0750";
};
};
systemd.services.greetd.preStart = ''
cd ${cacheDir}
${lib.concatStringsSep "\n" (lib.map (f: ''
${lib.concatStringsSep "\n" (
lib.map (f: ''
if [ -f "${f}" ]; then
cp "${f}" .
fi
'')
cfg.configFiles)}
'') cfg.configFiles
)}
if [ -f session.json ]; then
if cp "$(${jq} -r '.wallpaperPath' session.json)" wallpaper.jpg; then

View File

@@ -4,15 +4,31 @@
lib,
dmsPkgs,
...
} @ args: let
}@args:
let
cfg = config.programs.dankMaterialShell;
jsonFormat = pkgs.formats.json { };
common = import ./common.nix {inherit config pkgs lib dmsPkgs;};
in {
common = import ./common.nix {
inherit
config
pkgs
lib
dmsPkgs
;
};
in
{
imports = [
(import ./options.nix args)
(lib.mkRemovedOptionModule ["programs" "dankMaterialShell" "enableNightMode"] "Night mode is now always available.")
(lib.mkRenamedOptionModule ["programs" "dankMaterialShell" "enableSystemd"] ["programs" "dankMaterialShell" "systemd" "enable"])
(lib.mkRemovedOptionModule [
"programs"
"dankMaterialShell"
"enableNightMode"
] "Night mode is now always available.")
(lib.mkRenamedOptionModule
[ "programs" "dankMaterialShell" "enableSystemd" ]
[ "programs" "dankMaterialShell" "systemd" "enable" ]
)
];
options.programs.dankMaterialShell = with lib.types; {
@@ -30,7 +46,10 @@ in {
};
plugins = lib.mkOption {
type = attrsOf (types.submodule ({config, ...}: {
type = attrsOf (
types.submodule (
{ config, ... }:
{
options = {
enable = lib.mkOption {
type = types.bool;
@@ -42,17 +61,18 @@ in {
description = "Source to link to DMS plugins directory";
};
};
}));
}
)
);
default = { };
description = "DMS Plugins to install";
};
};
config = lib.mkIf cfg.enable
{
config = lib.mkIf cfg.enable {
programs.quickshell = {
enable = true;
package = cfg.quickshell.package;
inherit (cfg.quickshell) package;
configs.dms = common.qmlPath;
};

View File

@@ -2,9 +2,11 @@
config,
lib,
...
}: let
}:
let
cfg = config.programs.dankMaterialShell;
in {
in
{
options.programs.dankMaterialShell = {
niri = {
enableKeybinds = lib.mkEnableOption "DankMaterialShell niri keybinds";
@@ -15,7 +17,9 @@ in {
config = lib.mkIf cfg.enable {
programs.niri.settings = lib.mkMerge [
(lib.mkIf cfg.niri.enableKeybinds {
binds = with config.lib.niri.actions; let
binds =
with config.lib.niri.actions;
let
dms-ipc = spawn "dms" "ipc";
in
{
@@ -90,13 +94,22 @@ in {
})
(lib.mkIf cfg.niri.enableSpawn {
spawn-at-startup =
[
{command = ["dms" "run"];}
spawn-at-startup = [
{
command = [
"dms"
"run"
];
}
]
++ lib.optionals cfg.enableClipboard [
{
command = ["wl-paste" "--watch" "cliphist" "store"];
command = [
"wl-paste"
"--watch"
"cliphist"
"store"
];
}
];
})

View File

@@ -4,16 +4,24 @@
lib,
dmsPkgs,
...
} @ args: let
}@args:
let
cfg = config.programs.dankMaterialShell;
common = import ./common.nix {inherit config pkgs lib dmsPkgs;};
in {
common = import ./common.nix {
inherit
config
pkgs
lib
dmsPkgs
;
};
in
{
imports = [
(import ./options.nix args)
];
config = lib.mkIf cfg.enable
{
config = lib.mkIf cfg.enable {
environment.etc."xdg/quickshell/dms".source = "${dmsPkgs.dms-shell}/share/quickshell/dms";
systemd.user.services.dms = lib.mkIf cfg.systemd.enable {

View File

@@ -2,9 +2,11 @@
lib,
dmsPkgs,
...
}: let
}:
let
inherit (lib) types;
in {
in
{
options.programs.dankMaterialShell = {
enable = lib.mkEnableOption "DankMaterialShell";

View File

@@ -2,8 +2,8 @@
Name: dms-git
Version: 0.6.2+git2147.03073f68
Release: 5%{?dist}
Epoch: 1
Release: 1%{?dist}
Epoch: 2
Summary: DankMaterialShell - Material 3 inspired shell (git nightly)
License: MIT

View File

@@ -13,33 +13,40 @@
};
};
outputs = {
outputs =
{
self,
nixpkgs,
dgop,
quickshell,
...
}: let
forEachSystem = fn:
}:
let
forEachSystem =
fn:
nixpkgs.lib.genAttrs [ "aarch64-darwin" "aarch64-linux" "x86_64-darwin" "x86_64-linux" ] (
system: fn system nixpkgs.legacyPackages.${system}
);
buildDmsPkgs = pkgs: {
dms-shell = self.packages.${pkgs.stdenv.hostPlatform.system}.default;
dgop = dgop.packages.${pkgs.stdenv.hostPlatform.system}.dgop;
inherit (dgop.packages.${pkgs.stdenv.hostPlatform.system}) dgop;
quickshell = quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default;
};
mkModuleWithDmsPkgs = path: args @ {pkgs, ...}: {
mkModuleWithDmsPkgs =
path:
args@{ pkgs, ... }:
{
imports = [
(import path (args // { dmsPkgs = buildDmsPkgs pkgs; }))
];
};
in {
formatter = forEachSystem (_: pkgs: pkgs.alejandra);
in
{
packages = forEachSystem (
system: pkgs: let
mkDate = longDate:
system: pkgs:
let
mkDate =
longDate:
pkgs.lib.concatStringsSep "-" [
(builtins.substring 0 4 longDate)
(builtins.substring 4 2 longDate)
@@ -51,11 +58,13 @@
+ mkDate (self.lastModifiedDate or "19700101")
+ "_"
+ (self.shortRev or "dirty");
in {
in
{
dms-shell = pkgs.buildGoModule (
let
rootSrc = ./.;
in {
in
{
inherit version;
pname = "dms-shell";
src = ./core;
@@ -132,9 +141,9 @@
nixosModules.greeter = mkModuleWithDmsPkgs ./distro/nix/greeter.nix;
devShells = forEachSystem (
system: pkgs: let
qmlPkgs =
[
system: pkgs:
let
qmlPkgs = [
quickshell.packages.${system}.default
]
++ (with pkgs.kdePackages; [
@@ -143,9 +152,11 @@
sonnet
qtmultimedia
]);
in {
in
{
default = pkgs.mkShell {
buildInputs = with pkgs;
buildInputs =
with pkgs;
[
go_1_24
gopls

View File

@@ -59,7 +59,7 @@ FloatingWindow {
title: I18n.tr("Settings", "settings window title")
minimumSize: Qt.size(500, 400)
implicitWidth: 800
implicitHeight: 940
implicitHeight: screen ? Math.min(940, screen.height - 100) : 940
color: Theme.surfaceContainer
visible: false

View File

@@ -12,7 +12,7 @@ Row {
signal sizeChanged(int newSize)
readonly property var availableSizes: isSlider ? [50, 100] : [25, 50, 75, 100]
readonly property var availableSizes: isSlider ? [50, 75, 100] : [25, 50, 75, 100]
spacing: 2

View File

@@ -1088,6 +1088,7 @@ Item {
id: layoutComponent
DWLLayout {
id: layoutWidget
layoutPopupVisible: layoutPopoutLoader.item ? layoutPopoutLoader.item.shouldBeVisible : false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
@@ -1100,17 +1101,22 @@ Item {
parentScreen: barWindow.screen
onToggleLayoutPopup: {
layoutPopoutLoader.active = true;
if (!layoutPopoutLoader.item)
return;
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (layoutPopoutLoader.item && layoutPopoutLoader.item.setBarContext) {
layoutPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
if (layoutPopoutLoader.item.setTriggerPosition) {
const globalPos = layoutWidget.mapToGlobal(0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, layoutWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "center";
layoutPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
if (layoutPopoutLoader.item) {
PopoutManager.requestPopout(layoutPopoutLoader.item, undefined, "layout");
}
}
}
}
Component {
id: vpnComponent

View File

@@ -49,15 +49,12 @@ BasePill {
}
onWheel: function (wheelEvent) {
if (!activePlayer) {
wheelEvent.accepted = false;
return;
}
wheelEvent.accepted = true;
if (!usePlayerVolume)
return;
const delta = wheelEvent.angleDelta.y;
const currentVolume = usePlayerVolume ? (activePlayer.volume * 100) : ((AudioService.sink?.audio?.volume ?? 0) * 100);
const currentVolume = activePlayer.volume * 100;
let newVolume;
if (delta > 0) {
@@ -66,11 +63,7 @@ BasePill {
newVolume = Math.max(0, currentVolume - 5);
}
if (usePlayerVolume) {
activePlayer.volume = newVolume / 100;
} else if (AudioService.sink?.audio) {
AudioService.sink.audio.volume = newVolume / 100;
}
}
content: Component {

View File

@@ -1,4 +1,5 @@
import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Widgets
import Quickshell.Hyprland
@@ -245,11 +246,14 @@ Item {
if (!byApp[key]) {
const moddedId = Paths.moddedAppId(keyBase);
const isSteamApp = moddedId.toLowerCase().includes("steam_app");
const icon = isSteamApp ? "" : DesktopService.resolveIconPath(moddedId);
const isQuickshell = keyBase === "org.quickshell";
const desktopEntry = DesktopEntries.heuristicLookup(keyBase);
const icon = isSteamApp ? "" : Paths.getAppIcon(keyBase, desktopEntry);
byApp[key] = {
"type": "icon",
"icon": icon,
"isSteamApp": isSteamApp,
"isQuickshell": isQuickshell,
"active": !!((w.activated || w.is_focused) || (CompositorService.isNiri && w.is_focused)),
"count": 1,
"windowId": w.address || w.id,
@@ -446,6 +450,7 @@ Item {
readonly property real padding: Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
readonly property real visualWidth: isVertical ? widgetHeight : (workspaceRow.implicitWidth + padding * 2)
readonly property real visualHeight: isVertical ? (workspaceRow.implicitHeight + padding * 2) : widgetHeight
readonly property real appIconSize: Theme.barIconSize(barThickness, -6)
function getRealWorkspaces() {
return root.workspaceList.filter(ws => {
@@ -719,14 +724,14 @@ Item {
readonly property real iconsExtraWidth: {
if (!root.isVertical && SettingsData.showWorkspaceApps && loadedIcons.length > 0) {
const numIcons = Math.min(loadedIcons.length, SettingsData.maxWorkspaceIcons);
return numIcons * 18 + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0) + (isActive ? Theme.spacingXS : 0);
return numIcons * root.appIconSize + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0) + (isActive ? Theme.spacingXS : 0);
}
return 0;
}
readonly property real iconsExtraHeight: {
if (root.isVertical && SettingsData.showWorkspaceApps && loadedIcons.length > 0) {
const numIcons = Math.min(loadedIcons.length, SettingsData.maxWorkspaceIcons);
return numIcons * 18 + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0) + (isActive ? Theme.spacingXS : 0);
return numIcons * root.appIconSize + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0) + (isActive ? Theme.spacingXS : 0);
}
return 0;
}
@@ -897,7 +902,7 @@ Item {
Item {
visible: loadedHasIcon && loadedIconData?.type === "icon"
width: wsIcon.width + (isActive && loadedIcons.length > 0 ? 4 : 0)
height: 18
height: root.appIconSize
DankIcon {
id: wsIcon
@@ -912,7 +917,7 @@ Item {
Item {
visible: loadedHasIcon && loadedIconData?.type === "text"
width: wsText.implicitWidth + (isActive && loadedIcons.length > 0 ? 4 : 0)
height: 18
height: root.appIconSize
StyledText {
id: wsText
@@ -927,7 +932,7 @@ Item {
Item {
visible: SettingsData.showWorkspaceIndex && !loadedHasIcon
width: wsIndexText.implicitWidth + (isActive && loadedIcons.length > 0 ? 4 : 0)
height: 18
height: root.appIconSize
StyledText {
id: wsIndexText
@@ -944,48 +949,61 @@ Item {
values: loadedIcons.slice(0, SettingsData.maxWorkspaceIcons)
}
delegate: Item {
width: 18
height: 18
width: root.appIconSize
height: root.appIconSize
IconImage {
id: appIcon
property var windowId: modelData.windowId
id: rowAppIcon
anchors.fill: parent
source: modelData.icon
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
visible: !modelData.isSteamApp
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
visible: !modelData.isSteamApp && !modelData.isQuickshell
}
IconImage {
anchors.fill: parent
source: modelData.icon
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isQuickshell
layer.enabled: true
layer.effect: MultiEffect {
saturation: 0
colorization: 1
colorizationColor: isActive ? Theme.primaryContainer : Theme.primary
}
}
DankIcon {
anchors.centerIn: parent
size: 18
size: root.appIconSize
name: "sports_esports"
color: Theme.widgetTextColor
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
opacity: modelData.active ? 1.0 : rowAppMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isSteamApp
}
MouseArea {
id: appMouseArea
id: rowAppMouseArea
anchors.fill: parent
enabled: isActive
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!appIcon.windowId)
const winId = modelData.windowId;
if (!winId)
return;
if (CompositorService.isHyprland) {
Hyprland.dispatch(`focuswindow address:${appIcon.windowId}`);
Hyprland.dispatch(`focuswindow address:${winId}`);
} else if (CompositorService.isNiri) {
NiriService.focusWindow(appIcon.windowId);
NiriService.focusWindow(winId);
}
}
}
Rectangle {
visible: modelData.count > 1 && !isActive
width: 12
height: 12
radius: 6
width: root.appIconSize * 0.67
height: root.appIconSize * 0.67
radius: root.appIconSize * 0.33
color: "black"
border.color: "white"
border.width: 1
@@ -996,7 +1014,7 @@ Item {
Text {
anchors.centerIn: parent
text: modelData.count
font.pixelSize: 8
font.pixelSize: root.appIconSize * 0.44
color: "white"
}
}
@@ -1034,48 +1052,61 @@ Item {
values: loadedIcons.slice(0, SettingsData.maxWorkspaceIcons)
}
delegate: Item {
width: 18
height: 18
width: root.appIconSize
height: root.appIconSize
IconImage {
id: appIcon
property var windowId: modelData.windowId
id: colAppIcon
anchors.fill: parent
source: modelData.icon
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
visible: !modelData.isSteamApp
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
visible: !modelData.isSteamApp && !modelData.isQuickshell
}
IconImage {
anchors.fill: parent
source: modelData.icon
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isQuickshell
layer.enabled: true
layer.effect: MultiEffect {
saturation: 0
colorization: 1
colorizationColor: isActive ? Theme.primaryContainer : Theme.primary
}
}
DankIcon {
anchors.centerIn: parent
size: 18
size: root.appIconSize
name: "sports_esports"
color: Theme.widgetTextColor
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
opacity: modelData.active ? 1.0 : colAppMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isSteamApp
}
MouseArea {
id: appMouseArea
id: colAppMouseArea
anchors.fill: parent
enabled: isActive
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!appIcon.windowId)
const winId = modelData.windowId;
if (!winId)
return;
if (CompositorService.isHyprland) {
Hyprland.dispatch(`focuswindow address:${appIcon.windowId}`);
Hyprland.dispatch(`focuswindow address:${winId}`);
} else if (CompositorService.isNiri) {
NiriService.focusWindow(appIcon.windowId);
NiriService.focusWindow(winId);
}
}
}
Rectangle {
visible: modelData.count > 1 && !isActive
width: 12
height: 12
radius: 6
width: root.appIconSize * 0.67
height: root.appIconSize * 0.67
radius: root.appIconSize * 0.33
color: "black"
border.color: "white"
border.width: 1
@@ -1086,7 +1117,7 @@ Item {
Text {
anchors.centerIn: parent
text: modelData.count
font.pixelSize: 8
font.pixelSize: root.appIconSize * 0.44
color: "white"
}
}

View File

@@ -227,6 +227,13 @@ Item {
property bool isSeeking: false
Timer {
interval: 1000
running: activePlayer?.playbackState === MprisPlaybackState.Playing && !isSeeking
repeat: true
onTriggered: activePlayer?.positionChanged()
}
Item {
id: bgContainer
anchors.fill: parent

View File

@@ -157,6 +157,8 @@ Item {
anchors.fill: parent
screenName: root.screenName
visible: {
var _ = SessionData.perMonitorWallpaper
var __ = SessionData.monitorWallpapers
var currentWallpaper = SessionData.getMonitorWallpaper(screenName)
return !currentWallpaper || currentWallpaper === "" || (currentWallpaper && currentWallpaper.startsWith("#"))
}
@@ -167,6 +169,8 @@ Item {
anchors.fill: parent
source: {
var _ = SessionData.perMonitorWallpaper
var __ = SessionData.monitorWallpapers
var currentWallpaper = SessionData.getMonitorWallpaper(screenName)
return (currentWallpaper && !currentWallpaper.startsWith("#")) ? currentWallpaper : ""
}

View File

@@ -23,7 +23,7 @@ Item {
NetworkService.removeRef();
}
FileBrowserSurfaceModal {
FileBrowserModal {
id: vpnFileBrowser
browserTitle: I18n.tr("Import VPN")
browserIcon: "vpn_key"

View File

@@ -28,6 +28,7 @@ StyledRect {
property string pluginSettingsPath: pluginData ? (pluginData.settingsPath || "") : ""
property var pluginPermissions: pluginData ? (pluginData.permissions || []) : []
property bool hasSettings: pluginData && pluginData.settings !== undefined && pluginData.settings !== ""
property bool isSystemPlugin: pluginData ? (pluginData.source === "system") : false
property bool isExpanded: expandedPluginId === pluginId
property bool isLoaded: {
PluginService.loadedPlugins;
@@ -116,7 +117,7 @@ StyledRect {
height: 28
radius: 14
color: updateArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : "transparent"
visible: DMSService.dmsAvailable && root.isLoaded && root.hasUpdate
visible: DMSService.dmsAvailable && root.isLoaded && root.hasUpdate && !root.isSystemPlugin
DankIcon {
anchors.centerIn: parent
@@ -160,7 +161,7 @@ StyledRect {
height: 28
radius: 14
color: uninstallArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : "transparent"
visible: DMSService.dmsAvailable
visible: DMSService.dmsAvailable && !root.isSystemPlugin
DankIcon {
anchors.centerIn: parent

View File

@@ -314,7 +314,8 @@ Singleton {
const keyData = {
key: bind.key || "",
source: bind.source || "config",
isOverride: bind.source === "dms"
isOverride: bind.source === "dms",
cooldownMs: bind.cooldownMs || 0
};
if (actionMap[action]) {
actionMap[action].keys.push(keyData);
@@ -378,6 +379,8 @@ Singleton {
const cmd = ["dms", "keybinds", "set", currentProvider, bindData.key, bindData.action, "--desc", bindData.desc || ""];
if (originalKey && originalKey !== bindData.key)
cmd.push("--replace-key", originalKey);
if (bindData.cooldownMs > 0)
cmd.push("--cooldown-ms", String(bindData.cooldownMs));
saveProcess.command = cmd;
saveProcess.running = true;
bindSaved(bindData.key);

View File

@@ -1 +1 @@
v0.6.2
v1.0.1

View File

@@ -23,6 +23,8 @@ Item {
property string editKey: ""
property string editAction: ""
property string editDesc: ""
property int editCooldownMs: 0
property int _savedCooldownMs: -1
property bool hasChanges: false
property string _actionType: ""
property bool addingNewKey: false
@@ -90,6 +92,12 @@ Item {
editKey = keyToFind;
editAction = bindData.action || "";
editDesc = bindData.desc || "";
if (_savedCooldownMs >= 0) {
editCooldownMs = _savedCooldownMs;
_savedCooldownMs = -1;
} else {
editCooldownMs = keys[i].cooldownMs || 0;
}
hasChanges = false;
_actionType = Actions.getActionType(editAction);
useCustomCompositor = _actionType === "compositor" && editAction && !Actions.isKnownCompositorAction(editAction);
@@ -109,6 +117,7 @@ Item {
editKey = editingKeyIndex >= 0 ? keys[editingKeyIndex].key : "";
editAction = bindData.action || "";
editDesc = bindData.desc || "";
editCooldownMs = editingKeyIndex >= 0 ? (keys[editingKeyIndex].cooldownMs || 0) : 0;
hasChanges = false;
_actionType = Actions.getActionType(editAction);
useCustomCompositor = _actionType === "compositor" && editAction && !Actions.isKnownCompositorAction(editAction);
@@ -127,6 +136,7 @@ Item {
addingNewKey = false;
editingKeyIndex = index;
editKey = keys[index].key;
editCooldownMs = keys[index].cooldownMs || 0;
hasChanges = false;
}
@@ -137,8 +147,11 @@ Item {
editAction = changes.action;
if (changes.desc !== undefined)
editDesc = changes.desc;
if (changes.cooldownMs !== undefined)
editCooldownMs = changes.cooldownMs;
const origKey = editingKeyIndex >= 0 && editingKeyIndex < keys.length ? keys[editingKeyIndex].key : "";
hasChanges = editKey !== origKey || editAction !== (bindData.action || "") || editDesc !== (bindData.desc || "");
const origCooldown = editingKeyIndex >= 0 && editingKeyIndex < keys.length ? (keys[editingKeyIndex].cooldownMs || 0) : 0;
hasChanges = editKey !== origKey || editAction !== (bindData.action || "") || editDesc !== (bindData.desc || "") || editCooldownMs !== origCooldown;
}
function canSave() {
@@ -156,10 +169,12 @@ Item {
let desc = editDesc;
if (expandedLoader.item?.currentTitle !== undefined)
desc = expandedLoader.item.currentTitle;
_savedCooldownMs = editCooldownMs;
saveBind(origKey, {
key: editKey,
action: editAction,
desc: desc
desc: desc,
cooldownMs: editCooldownMs
});
hasChanges = false;
addingNewKey = false;
@@ -1431,6 +1446,57 @@ Item {
}
}
RowLayout {
Layout.fillWidth: true
spacing: Theme.spacingM
StyledText {
text: I18n.tr("Cooldown")
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceVariantText
Layout.preferredWidth: 60
}
DankTextField {
id: cooldownField
Layout.preferredWidth: 100
Layout.preferredHeight: 40
placeholderText: "0"
Connections {
target: root
function onEditCooldownMsChanged() {
const newText = root.editCooldownMs > 0 ? String(root.editCooldownMs) : "";
if (cooldownField.text !== newText)
cooldownField.text = newText;
}
}
Component.onCompleted: {
text = root.editCooldownMs > 0 ? String(root.editCooldownMs) : "";
}
onTextChanged: {
const val = parseInt(text) || 0;
if (val !== root.editCooldownMs)
root.updateEdit({
cooldownMs: val
});
}
}
StyledText {
text: I18n.tr("ms")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
Item {
Layout.fillWidth: true
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1

View File

@@ -3554,7 +3554,7 @@
{
"term": "No Active Players",
"context": "No Active Players",
"reference": "Modules/DankDash/MediaPlayerTab.qml:308",
"reference": "Modules/DankDash/MediaPlayerTab.qml:315",
"comment": ""
},
{
@@ -5300,7 +5300,7 @@
{
"term": "Switch User",
"context": "Switch User",
"reference": "Modules/Greetd/GreeterContent.qml:662",
"reference": "Modules/Greetd/GreeterContent.qml:666",
"comment": ""
},
{

View File

@@ -1926,7 +1926,7 @@
"None": "Nulla"
},
"Normal Font": {
"Normal Font": "Carattere Normale"
"Normal Font": "Font Normale"
},
"Normal Priority": {
"Normal Priority": "Priorità Normale"
@@ -2481,7 +2481,7 @@
"Select driver...": "Seleziona un driver..."
},
"Select font weight for UI text": {
"Select font weight for UI text": "Seleziona lo spessore del carattere per il testo dell'interfaccia utente"
"Select font weight for UI text": "Seleziona lo spessore del font per il testo dell'interfaccia utente"
},
"Select monitor to configure wallpaper": {
"Select monitor to configure wallpaper": "Selezionare il monitor per configurare lo sconto"
@@ -2493,7 +2493,7 @@
"Select system sound theme": "Seleziona tema suoni di sistema"
},
"Select the font family for UI text": {
"Select the font family for UI text": "Seleziona la famiglia di caratteri per il testo dell'interfaccia utente"
"Select the font family for UI text": "Seleziona la famiglia di font per il testo dell'interfaccia utente"
},
"Select the palette algorithm used for wallpaper-based colors": {
"Select the palette algorithm used for wallpaper-based colors": "Seleziona l'algoritmo tavolozza usato per i colori basati sullo sfondo"
@@ -2946,7 +2946,7 @@
"Typography": "Tipografia"
},
"Typography & Motion": {
"Typography & Motion": "Tipografia e Movimento"
"Typography & Motion": "Tipografia e Animazioni"
},
"Unavailable": {
"Unavailable": "Non disponibile"