1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Marcus Ramberg
0df47d2ce3 core: add dynamic completion for more commands (#889) 2025-12-02 18:35:51 -05:00
purian23
e24b548b54 fix: dms-cli & about versioning in all builds 2025-12-02 18:12:13 -05:00
Lucas
75af444cee niri: add option to disable overview launcher (#887) 2025-12-02 18:04:04 -05:00
bbedward
02dd19962f matugen: backup and add to vscode extensions json when present 2025-12-02 17:32:48 -05:00
purian23
f552b8ef7b Update Debian version format 2025-12-02 16:51:58 -05:00
Marcus Ramberg
9162e31489 core: add dynamic completion for ipc command (#885) 2025-12-02 15:51:26 -05:00
bbedward
01b28e3ee8 spotlight: optimize to keep loaded 2025-12-02 15:01:23 -05:00
bbedward
f5aa855125 network: eth device speed is not exposed 2025-12-02 14:45:28 -05:00
Guilherme Pagano
db3610fcdb feat: add support for geometric centering (#856)
Introduces a configurable centering mode.
- Adds 'geometric' option.
- Retains 'index' as the default value to preserve existing behavior.
2025-12-02 14:43:51 -05:00
bbedward
2e3f330058 theme: uncomment niri alt-tab colors 2025-12-02 14:41:09 -05:00
Marcus Ramberg
1617a7f2c1 dankbar: allow disabling title scrolling in the music display (#882) 2025-12-02 13:39:19 -05:00
25 changed files with 517 additions and 66 deletions

View File

@@ -172,6 +172,51 @@ jobs:
CHANGELOG_ENTRY="* $DATE_STR Avenge Media <AvengeMedia.US@gmail.com> - ${NEW_VERSION}-1\n- Git snapshot (commit $COMMIT_COUNT: $COMMIT_HASH)"
sed -i "/%changelog/a\\$CHANGELOG_ENTRY" distro/opensuse/dms-git.spec
- name: Update Debian dms-git changelog version
if: contains(steps.packages.outputs.packages, 'dms-git') || steps.packages.outputs.packages == 'all'
run: |
# Get commit info for dms-git versioning
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
COMMIT_COUNT=$(git rev-list --count HEAD)
BASE_VERSION=$(grep -oP '^Version:\s+\K[0-9.]+' distro/opensuse/dms.spec | head -1 || echo "0.6.2")
# Debian version format: 0.6.2+git2256.9162e314
NEW_VERSION="${BASE_VERSION}+git${COMMIT_COUNT}.${COMMIT_HASH}"
echo "📦 Updating Debian dms-git changelog to version: $NEW_VERSION"
CHANGELOG_DATE=$(date -R)
CHANGELOG_FILE="distro/debian/dms-git/debian/changelog"
# Get current version from changelog
CURRENT_VERSION=$(head -1 "$CHANGELOG_FILE" | sed 's/.*(\([^)]*\)).*/\1/')
echo "Current Debian version: $CURRENT_VERSION"
echo "New version: $NEW_VERSION"
# Only update if version changed
if [ "$CURRENT_VERSION" != "$NEW_VERSION" ]; then
# Create new changelog entry at top
TEMP_CHANGELOG=$(mktemp)
cat > "$TEMP_CHANGELOG" << EOF
dms-git ($NEW_VERSION) nightly; urgency=medium
* Git snapshot (commit $COMMIT_COUNT: $COMMIT_HASH)
-- Avenge Media <AvengeMedia.US@gmail.com> $CHANGELOG_DATE
EOF
# Prepend to existing changelog
cat "$CHANGELOG_FILE" >> "$TEMP_CHANGELOG"
mv "$TEMP_CHANGELOG" "$CHANGELOG_FILE"
echo "✓ Updated Debian changelog: $CURRENT_VERSION → $NEW_VERSION"
else
echo "✓ Debian changelog already at version $NEW_VERSION"
fi
- name: Update dms stable version
if: steps.packages.outputs.version != ''
run: |

View File

@@ -43,6 +43,7 @@ install-shell:
@mkdir -p $(SHELL_INSTALL_DIR)
@cp -r $(SHELL_DIR)/* $(SHELL_INSTALL_DIR)/
@rm -rf $(SHELL_INSTALL_DIR)/.git* $(SHELL_INSTALL_DIR)/.github
@$(MAKE) --no-print-directory -C $(CORE_DIR) print-version > $(SHELL_INSTALL_DIR)/VERSION
@echo "Shell files installed"
install-completions:
@@ -80,8 +81,7 @@ install: build install-bin install-shell install-completions install-systemd ins
@echo ""
@echo "Installation complete!"
@echo ""
@echo "To enable and start DMS:"
@echo " systemctl --user enable --now dms"
@echo "=== The DMS Team! ==="
# Uninstallation targets
uninstall-bin:

View File

@@ -10,16 +10,19 @@ GO=go
GOFLAGS=-ldflags="-s -w"
# Version and build info
VERSION=$(shell git describe --tags --always 2>/dev/null || echo "dev")
BUILD_TIME=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
COMMIT=$(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BASE_VERSION=$(shell git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo "0.0.0")
COMMIT_COUNT=$(shell git rev-list --count HEAD 2>/dev/null || echo "0")
COMMIT_HASH=$(shell git rev-parse --short=8 HEAD 2>/dev/null || echo "unknown")
VERSION?=$(BASE_VERSION)+git$(COMMIT_COUNT).$(COMMIT_HASH)
BUILD_TIME?=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
COMMIT?=$(COMMIT_HASH)
BUILD_LDFLAGS=-ldflags='-s -w -X main.Version=$(VERSION) -X main.buildTime=$(BUILD_TIME) -X main.commit=$(COMMIT)'
# Architecture to build for dist target (amd64, arm64, or all)
ARCH ?= all
.PHONY: all build dankinstall dist clean install install-all install-dankinstall uninstall uninstall-all uninstall-dankinstall install-config uninstall-config test fmt vet deps help
.PHONY: all build dankinstall dist clean install install-all install-dankinstall uninstall uninstall-all uninstall-dankinstall install-config uninstall-config test fmt vet deps print-version help
# Default target
all: build
@@ -132,6 +135,9 @@ version: check-go
@echo "Build Time: $(BUILD_TIME)"
@echo "Commit: $(COMMIT)"
print-version:
@echo "$(VERSION)"
help:
@echo "Available targets:"
@echo " all - Build the main binary (dms) (default)"

View File

@@ -28,6 +28,13 @@ var brightnessSetCmd = &cobra.Command{
Short: "Set brightness for a device",
Long: "Set brightness percentage (0-100) for a specific device",
Args: cobra.ExactArgs(2),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
includeDDC, _ := cmd.Flags().GetBool("ddc")
return getBrightnessDevices(includeDDC), cobra.ShellCompDirectiveNoFileComp
},
Run: runBrightnessSet,
}
@@ -36,6 +43,13 @@ var brightnessGetCmd = &cobra.Command{
Short: "Get brightness for a device",
Long: "Get current brightness percentage for a specific device",
Args: cobra.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
includeDDC, _ := cmd.Flags().GetBool("ddc")
return getBrightnessDevices(includeDDC), cobra.ShellCompDirectiveNoFileComp
},
Run: runBrightnessGet,
}
@@ -105,9 +119,7 @@ Global Flags:
brightnessCmd.AddCommand(brightnessListCmd, brightnessSetCmd, brightnessGetCmd)
}
func runBrightnessList(cmd *cobra.Command, args []string) {
includeDDC, _ := cmd.Flags().GetBool("ddc")
func getAllBrightnessDevices(includeDDC bool) []brightness.Device {
allDevices := []brightness.Device{}
sysfs, err := brightness.NewSysfsBackend()
@@ -138,6 +150,13 @@ func runBrightnessList(cmd *cobra.Command, args []string) {
}
}
return allDevices
}
func runBrightnessList(cmd *cobra.Command, args []string) {
includeDDC, _ := cmd.Flags().GetBool("ddc")
allDevices := getAllBrightnessDevices(includeDDC)
if len(allDevices) == 0 {
fmt.Println("No brightness devices found")
return
@@ -261,31 +280,20 @@ func runBrightnessSet(cmd *cobra.Command, args []string) {
log.Fatalf("Failed to set brightness for device: %s", deviceID)
}
func getBrightnessDevices(includeDDC bool) []string {
allDevices := getAllBrightnessDevices(includeDDC)
var deviceIDs []string
for _, device := range allDevices {
deviceIDs = append(deviceIDs, device.ID)
}
return deviceIDs
}
func runBrightnessGet(cmd *cobra.Command, args []string) {
deviceID := args[0]
includeDDC, _ := cmd.Flags().GetBool("ddc")
allDevices := []brightness.Device{}
sysfs, err := brightness.NewSysfsBackend()
if err == nil {
devices, err := sysfs.GetDevices()
if err == nil {
allDevices = append(allDevices, devices...)
}
}
if includeDDC {
ddc, err := brightness.NewDDCBackend()
if err == nil {
defer ddc.Close()
time.Sleep(100 * time.Millisecond)
devices, err := ddc.GetDevices()
if err == nil {
allDevices = append(allDevices, devices...)
}
}
}
allDevices := getAllBrightnessDevices(includeDDC)
for _, device := range allDevices {
if device.ID == deviceID {

View File

@@ -66,6 +66,10 @@ var ipcCmd = &cobra.Command{
Short: "Send IPC commands to running DMS shell",
Long: "Send IPC commands to running DMS shell (qs -c dms ipc <args>)",
PreRunE: findConfig,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
_ = findConfig(cmd, args)
return getShellIPCCompletions(args, toComplete), cobra.ShellCompDirectiveNoFileComp
},
Run: func(cmd *cobra.Command, args []string) {
runShellIPCCommand(args)
},
@@ -115,6 +119,12 @@ var pluginsInstallCmd = &cobra.Command{
Short: "Install a plugin by ID",
Long: "Install a DMS plugin from the registry using its ID (e.g., 'myPlugin'). Plugin names with spaces are also supported for backward compatibility.",
Args: cobra.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getAvailablePluginIDs(), cobra.ShellCompDirectiveNoFileComp
},
Run: func(cmd *cobra.Command, args []string) {
if err := installPluginCLI(args[0]); err != nil {
log.Fatalf("Error installing plugin: %v", err)
@@ -127,6 +137,12 @@ var pluginsUninstallCmd = &cobra.Command{
Short: "Uninstall a plugin by ID",
Long: "Uninstall a DMS plugin using its ID (e.g., 'myPlugin'). Plugin names with spaces are also supported for backward compatibility.",
Args: cobra.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getInstalledPluginIDs(), cobra.ShellCompDirectiveNoFileComp
},
Run: func(cmd *cobra.Command, args []string) {
if err := uninstallPluginCLI(args[0]); err != nil {
log.Fatalf("Error uninstalling plugin: %v", err)
@@ -299,6 +315,38 @@ func installPluginCLI(idOrName string) error {
return nil
}
func getAvailablePluginIDs() []string {
registry, err := plugins.NewRegistry()
if err != nil {
return nil
}
pluginList, err := registry.List()
if err != nil {
return nil
}
var ids []string
for _, p := range pluginList {
ids = append(ids, p.ID)
}
return ids
}
func getInstalledPluginIDs() []string {
manager, err := plugins.NewManager()
if err != nil {
return nil
}
installed, err := manager.ListInstalled()
if err != nil {
return nil
}
return installed
}
func uninstallPluginCLI(idOrName string) error {
manager, err := plugins.NewManager()
if err != nil {

View File

@@ -27,6 +27,9 @@ func init() {
dank16Cmd.Flags().Bool("wezterm", false, "Output in Wezterm terminal format")
dank16Cmd.Flags().String("background", "", "Custom background color")
dank16Cmd.Flags().String("contrast", "dps", "Contrast algorithm: dps (Delta Phi Star, default) or wcag")
_ = dank16Cmd.RegisterFlagCompletionFunc("contrast", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"dps", "wcag"}, cobra.ShellCompDirectiveNoFileComp
})
}
func runDank16(cmd *cobra.Command, args []string) {

View File

@@ -16,6 +16,12 @@ var dpmsOnCmd = &cobra.Command{
Use: "on [output]",
Short: "Turn display(s) on",
Args: cobra.MaximumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getDPMSOutputs(), cobra.ShellCompDirectiveNoFileComp
},
Run: runDPMSOn,
}
@@ -23,6 +29,12 @@ var dpmsOffCmd = &cobra.Command{
Use: "off [output]",
Short: "Turn display(s) off",
Args: cobra.MaximumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getDPMSOutputs(), cobra.ShellCompDirectiveNoFileComp
},
Run: runDPMSOff,
}
@@ -71,6 +83,15 @@ func runDPMSOff(cmd *cobra.Command, args []string) {
}
}
func getDPMSOutputs() []string {
client, err := newDPMSClient()
if err != nil {
return nil
}
defer client.Close()
return client.ListOutputs()
}
func runDPMSList(cmd *cobra.Command, args []string) {
client, err := newDPMSClient()
if err != nil {

View File

@@ -30,6 +30,13 @@ var keybindsShowCmd = &cobra.Command{
Short: "Show keybinds for a provider",
Long: "Display keybinds/cheatsheet for the specified provider",
Args: cobra.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
registry := keybinds.GetDefaultRegistry()
return registry.List(), cobra.ShellCompDirectiveNoFileComp
},
Run: runKeybindsShow,
}

View File

@@ -45,6 +45,9 @@ func init() {
openCmd.Flags().StringVar(&openMimeType, "mime", "", "MIME type for filtering applications")
openCmd.Flags().StringSliceVar(&openCategories, "category", []string{}, "Application categories to filter (e.g., WebBrowser, Office, Graphics)")
openCmd.Flags().StringVar(&openRequestType, "type", "url", "Request type (url, file, or custom)")
_ = openCmd.RegisterFlagCompletionFunc("type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"url", "file", "custom"}, cobra.ShellCompDirectiveNoFileComp
})
}
// mimeTypeToCategories maps MIME types to desktop file categories

View File

@@ -16,6 +16,8 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/internal/server"
)
type ipcTargets map[string][]string
var isSessionManaged bool
func execDetachedRestart(targetPID int) {
@@ -68,7 +70,7 @@ func getPIDFilePath() string {
func writePIDFile(childPID int) error {
pidFile := getPIDFilePath()
return os.WriteFile(pidFile, []byte(strconv.Itoa(childPID)), 0644)
return os.WriteFile(pidFile, []byte(strconv.Itoa(childPID)), 0o644)
}
func removePIDFile() {
@@ -144,7 +146,7 @@ func runShellInteractive(session bool) {
socketPath := server.GetSocketPath()
configStateFile := filepath.Join(getRuntimeDir(), "danklinux.path")
if err := os.WriteFile(configStateFile, []byte(configPath), 0644); err != nil {
if err := os.WriteFile(configStateFile, []byte(configPath), 0o644); err != nil {
log.Warnf("Failed to write config state file: %v", err)
}
defer os.Remove(configStateFile)
@@ -370,7 +372,7 @@ func runShellDaemon(session bool) {
socketPath := server.GetSocketPath()
configStateFile := filepath.Join(getRuntimeDir(), "danklinux.path")
if err := os.WriteFile(configStateFile, []byte(configPath), 0644); err != nil {
if err := os.WriteFile(configStateFile, []byte(configPath), 0o644); err != nil {
log.Warnf("Failed to write config state file: %v", err)
}
defer os.Remove(configStateFile)
@@ -473,6 +475,51 @@ func runShellDaemon(session bool) {
}
}
func parseTargetsFromIPCShowOutput(output string) ipcTargets {
targets := map[string][]string{}
var currentTarget string
for _, line := range strings.Split(output, "\n") {
if strings.HasPrefix(line, "target ") {
currentTarget = strings.TrimSpace(strings.TrimPrefix(line, "target "))
}
if strings.HasPrefix(line, " function") && currentTarget != "" {
currentFunc := strings.TrimPrefix(line, " function ")
currentFunc = strings.SplitN(currentFunc, "(", 2)[0]
targets[currentTarget] = append(targets[currentTarget], currentFunc)
}
}
return targets
}
func getShellIPCCompletions(args []string, toComplete string) []string {
cmdArgs := []string{"-p", configPath, "ipc", "show"}
cmd := exec.Command("qs", cmdArgs...)
var targets ipcTargets
if output, err := cmd.Output(); err == nil {
log.Debugf("IPC show output: %s", string(output))
targets = parseTargetsFromIPCShowOutput(string(output))
} else {
log.Debugf("Error getting IPC show output for completions: %v", err)
return nil
}
if len(args) > 0 && args[0] == "call" {
args = args[1:]
}
if len(args) == 0 {
targetNames := make([]string, 0)
targetNames = append(targetNames, "call")
for k := range targets {
targetNames = append(targetNames, k)
}
return targetNames
}
return targets[args[0]]
}
func runShellIPCCommand(args []string) {
if len(args) == 0 {
log.Error("IPC command requires arguments")

View File

@@ -169,6 +169,7 @@ fi
CHANGELOG_VERSION=""
if [[ -d "distro/debian/$PACKAGE/debian" ]]; then
# Format: 0.6.2+git{COMMIT_COUNT}.{COMMIT_HASH} (e.g., 0.6.2+git2256.9162e314)
CHANGELOG_VERSION=$(grep -m1 "^$PACKAGE" "distro/debian/$PACKAGE/debian/changelog" 2>/dev/null | sed 's/.*(\([^)]*\)).*/\1/' || echo "")
if [[ -n "$CHANGELOG_VERSION" ]] && [[ "$CHANGELOG_VERSION" == *"-"* ]]; then
SOURCE_FORMAT_CHECK=$(cat "distro/debian/$PACKAGE/debian/source/format" 2>/dev/null || echo "3.0 (quilt)")

View File

@@ -14,8 +14,31 @@ Singleton {
property var activeModal: null
property bool windowsVisible: false
property var targetScreen: null
property var persistentModal: 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
onPersistentModalChanged: {
if (!persistentModal)
return;
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;
}
}
readonly property var screen: backgroundWindow.screen
readonly property real dpr: screen ? CompositorService.getScreenScale(screen) : 1
readonly property real shadowBuffer: 5
@@ -161,7 +184,7 @@ Singleton {
PanelWindow {
id: backgroundWindow
visible: root.windowsVisible
visible: root.windowsVisible || root.shouldKeepWindowsAlive
screen: root.targetScreen
color: "transparent"
@@ -223,7 +246,7 @@ Singleton {
PanelWindow {
id: contentWindow
visible: root.windowsVisible
visible: root.windowsVisible || root.shouldKeepWindowsAlive
screen: root.targetScreen
color: "transparent"

View File

@@ -168,12 +168,14 @@ Singleton {
property bool dwlShowAllTags: false
property var workspaceNameIcons: ({})
property bool waveProgressEnabled: true
property bool scrollTitleEnabled: true
property bool clockCompactMode: false
property bool focusedWindowCompactMode: false
property bool runningAppsCompactMode: true
property bool keyboardLayoutNameCompactMode: false
property bool runningAppsCurrentWorkspace: false
property bool runningAppsGroupByApp: false
property string centeringMode: "index"
property string clockDateFormat: ""
property string lockDateFormat: ""
property int mediaSize: 1
@@ -185,6 +187,7 @@ Singleton {
property bool sortAppsAlphabetically: false
property int appLauncherGridColumns: 4
property bool spotlightCloseNiriOverview: true
property bool niriOverviewOverlayEnabled: true
property string weatherLocation: "New York, NY"
property string weatherCoordinates: "40.7128,-74.0060"
@@ -226,6 +229,7 @@ Singleton {
onNotepadFontFamilyChanged: saveSettings()
onNotepadFontSizeChanged: saveSettings()
onNotepadShowLineNumbersChanged: saveSettings()
// onCenteringModeChanged: saveSettings()
onNotepadTransparencyOverrideChanged: {
if (notepadTransparencyOverride > 0) {
notepadLastCustomTransparency = notepadTransparencyOverride;

View File

@@ -83,12 +83,14 @@ var SPEC = {
dwlShowAllTags: { def: false },
workspaceNameIcons: { def: {} },
waveProgressEnabled: { def: true },
scrollTitleEnabled: {def: true},
clockCompactMode: { def: false },
focusedWindowCompactMode: { def: false },
runningAppsCompactMode: { def: true },
keyboardLayoutNameCompactMode: { def: false },
runningAppsCurrentWorkspace: { def: false },
runningAppsGroupByApp: { def: false },
centeringMode: { def: "index" },
clockDateFormat: { def: "" },
lockDateFormat: { def: "" },
mediaSize: { def: 1 },
@@ -98,6 +100,7 @@ var SPEC = {
sortAppsAlphabetically: { def: false },
appLauncherGridColumns: { def: 4 },
spotlightCloseNiriOverview: { def: true },
niriOverviewOverlayEnabled: { def: true },
weatherLocation: { def: "New York, NY" },
weatherCoordinates: { def: "40.7128,-74.0060" },

View File

@@ -712,7 +712,7 @@ Item {
LazyLoader {
id: niriOverviewOverlayLoader
active: CompositorService.isNiri
active: CompositorService.isNiri && SettingsData.niriOverviewOverlayEnabled
component: NiriOverviewOverlay {
id: niriOverviewOverlay
}

View File

@@ -130,6 +130,10 @@ DankModal {
target: "spotlight"
}
Component.onCompleted: {
DankModalWindow.persistentModal = spotlightModal;
}
SpotlightContent {
id: spotlightContentInstance

View File

@@ -30,6 +30,64 @@ Item {
property real totalSize: 0
function updateLayout() {
if (SettingsData.centeringMode === "geometric") {
applyGeometricLayout();
} else {
// Default to index layout or if value is not 'geometric'
applyIndexLayout();
}
}
function applyGeometricLayout() {
if ((isVertical ? height : width) <= 0 || !visible) {
return;
}
centerWidgets = [];
totalWidgets = 0;
totalSize = 0;
for (var i = 0; i < centerRepeater.count; i++) {
const item = centerRepeater.itemAt(i);
if (item && item.active && item.item && getWidgetVisible(item.widgetId)) {
centerWidgets.push(item.item);
totalWidgets++;
totalSize += isVertical ? item.item.height : item.item.width;
}
}
if (totalWidgets === 0) {
return;
}
if (totalWidgets > 1) {
totalSize += spacing * (totalWidgets - 1);
}
positionWidgetsGeometric();
}
function positionWidgetsGeometric() {
const parentLength = isVertical ? height : width;
const parentCenter = parentLength / 2;
let currentPos = parentCenter - (totalSize / 2);
centerWidgets.forEach(widget => {
if (isVertical) {
widget.anchors.verticalCenter = undefined;
widget.y = currentPos;
} else {
widget.anchors.horizontalCenter = undefined;
widget.x = currentPos;
}
const widgetSize = isVertical ? widget.height : widget.width;
currentPos += widgetSize + spacing;
});
}
function applyIndexLayout() {
if ((isVertical ? height : width) <= 0 || !visible) {
return;
}
@@ -85,10 +143,10 @@ Item {
totalSize += spacing * (totalWidgets - 1);
}
positionWidgets(configuredWidgets, configuredMiddleWidget, configuredLeftWidget, configuredRightWidget);
positionWidgetsByIndex(configuredWidgets, configuredMiddleWidget, configuredLeftWidget, configuredRightWidget);
}
function positionWidgets(configuredWidgets, configuredMiddleWidget, configuredLeftWidget, configuredRightWidget) {
function positionWidgetsByIndex(configuredWidgets, configuredMiddleWidget, configuredLeftWidget, configuredRightWidget) {
const parentCenter = (isVertical ? height : width) / 2;
const isOddConfigured = configuredWidgets % 2 === 1;
@@ -508,4 +566,11 @@ Item {
}
}
}
Connections {
target: SettingsData
function onCenteringModeChanged() {
layoutTimer.restart();
}
}
}

View File

@@ -232,7 +232,7 @@ BasePill {
StyledText {
id: mediaText
property bool needsScrolling: implicitWidth > textContainer.width
property bool needsScrolling: implicitWidth > textContainer.width && SettingsData.scrollTitleEnabled
property real scrollOffset: 0
anchors.verticalCenter: parent.verticalCenter

View File

@@ -162,7 +162,19 @@ Item {
}
StyledText {
text: SystemUpdateService.shellVersion ? `dms ${SystemUpdateService.shellVersion}` : "dms"
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+)\./);
if (match) {
return `dms v${match[1]}-${match[2]}`;
}
return `dms ${version}`;
}
font.pixelSize: Theme.fontSizeXLarge
font.weight: Font.Bold
color: Theme.surfaceText

View File

@@ -655,6 +655,69 @@ Item {
}
}
StyledRect {
width: parent.width
height: niriOverlayEnabledSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0
visible: CompositorService.isNiri
Column {
id: niriOverlayEnabledSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "layers"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Enable Overview Overlay")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - parent.children[0].width - parent.children[1].width - niriOverlayToggle.width - Theme.spacingM * 3
height: 1
}
DankToggle {
id: niriOverlayToggle
width: 32
height: 18
checked: SettingsData.niriOverviewOverlayEnabled
anchors.verticalCenter: parent.verticalCenter
onToggled: checked => {
SettingsData.set("niriOverviewOverlayEnabled", checked);
}
}
}
StyledText {
width: parent.width
text: I18n.tr("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.")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
}
}
}
StyledRect {
width: parent.width
height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2

View File

@@ -407,20 +407,6 @@ Item {
color: Theme.surfaceVariantText
visible: modelData.ip && modelData.ip.length > 0
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
visible: modelData.speed && modelData.speed > 0
}
StyledText {
text: modelData.speed ? modelData.speed + " Mbps" : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
visible: modelData.speed && modelData.speed > 0
}
}
}
}

View File

@@ -203,6 +203,15 @@ Item {
return SettingsData.set("waveProgressEnabled", checked);
}
}
DankToggle {
width: parent.width
text: I18n.tr("Scroll song title")
description: I18n.tr("Scroll title if it doesn't fit in widget")
checked: SettingsData.scrollTitleEnabled
onToggled: checked => {
return SettingsData.set("scrollTitleEnabled", checked);
}
}
}
}

View File

@@ -1,5 +1,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Common
import qs.Widgets
import qs.Services
@@ -34,7 +35,7 @@ Column {
height: implicitHeight
spacing: Theme.spacingM
Row {
RowLayout {
width: parent.width
spacing: Theme.spacingM
@@ -42,7 +43,7 @@ Column {
name: root.titleIcon
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Layout.alignment: Qt.AlignVCenter
}
StyledText {
@@ -50,12 +51,54 @@ Column {
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
Layout.alignment: Qt.AlignVCenter
}
Item {
width: parent.width - 60
height: 1
Layout.fillWidth: true
}
RowLayout {
spacing: Theme.spacingXS
Layout.alignment: Qt.AlignVCenter
visible: root.sectionId === "center"
DankActionButton {
id: indexCenterButton
buttonSize: 28
iconName: "format_list_numbered"
iconSize: 16
iconColor: SettingsData.centeringMode === "index" ? Theme.primary : Theme.outline
onClicked: {
console.log("Centering mode changed to: index");
SettingsData.set("centeringMode", "index");
}
onEntered: {
sharedTooltip.show("Index Centering", indexCenterButton, 0, 0, "bottom");
}
onExited: {
sharedTooltip.hide();
}
}
DankActionButton {
id: geometricCenterButton
buttonSize: 28
iconName: "center_focus_weak"
iconSize: 16
iconColor: SettingsData.centeringMode === "geometric" ? Theme.primary : Theme.outline
onClicked: {
console.log("Centering mode changed to: geometric");
SettingsData.set("centeringMode", "geometric");
}
onEntered: {
sharedTooltip.show("Geometric Centering", geometricCenterButton, 0, 0, "bottom");
}
onExited: {
sharedTooltip.hide();
}
}
}
}

View File

@@ -28,7 +28,7 @@ layout {
}
}
/-recent-windows {
recent-windows {
highlight {
active-color "{{colors.primary_container.dark.hex}}"
urgent-color "{{colors.error.default.hex}}"

View File

@@ -175,6 +175,56 @@ setup_vscode_extension() {
mkdir -p "$theme_dir"
cp "$SHELL_DIR/matugen/templates/vscode-package.json" "$ext_dir/package.json" 2>/dev/null || true
cp "$SHELL_DIR/matugen/templates/vscode-vsixmanifest.xml" "$ext_dir/.vsixmanifest" 2>/dev/null || true
update_vscode_extensions_json "$config_dir/extensions" "$ext_dir"
}
update_vscode_extensions_json() {
local ext_list_dir="$1" ext_dir="$2"
local ext_json="$ext_list_dir/extensions.json"
[[ ! -f "$ext_json" ]] && return
grep -q "dynamic-base16-dankshell" "$ext_json" && return
cp "$ext_json" "$ext_json.bak"
local entry
entry=$(cat <<EOF
{
"identifier": {
"id": "local.dynamic-base16-dankshell",
"uuid": "00000000-0000-0000-0000-000000000000"
},
"version": "0.0.1",
"location": {
"\$mid": 1,
"path": "$ext_dir",
"scheme": "file"
},
"relativeLocation": "local.dynamic-base16-dankshell-0.0.1",
"metadata": {
"isApplicationScoped": false,
"isMachineScoped": false,
"isBuiltin": false,
"installedTimestamp": $(date +%s)000,
"pinned": false,
"source": "local",
"id": "00000000-0000-0000-0000-000000000000",
"publisherId": "local",
"publisherDisplayName": "Dank Linux",
"targetPlatform": "undefined",
"updated": true,
"private": false,
"isPreReleaseVersion": false,
"hasPreReleaseVersion": false,
"preRelease": false
}
}
EOF
)
local content
content=$(cat "$ext_json")
if [[ "$content" == "[]" ]]; then
echo "[$entry]" > "$ext_json"
else
echo "${content%]}, $entry]" > "$ext_json"
fi
}
signal_terminals() {