mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
Compare commits
11 Commits
69a5566bf9
...
0df47d2ce3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0df47d2ce3 | ||
|
|
e24b548b54 | ||
|
|
75af444cee | ||
|
|
02dd19962f | ||
|
|
f552b8ef7b | ||
|
|
9162e31489 | ||
|
|
01b28e3ee8 | ||
|
|
f5aa855125 | ||
|
|
db3610fcdb | ||
|
|
2e3f330058 | ||
|
|
1617a7f2c1 |
45
.github/workflows/run-obs.yml
vendored
45
.github/workflows/run-obs.yml
vendored
@@ -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: |
|
||||
|
||||
4
Makefile
4
Makefile
@@ -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:
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -28,7 +28,14 @@ var brightnessSetCmd = &cobra.Command{
|
||||
Short: "Set brightness for a device",
|
||||
Long: "Set brightness percentage (0-100) for a specific device",
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: runBrightnessSet,
|
||||
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,
|
||||
}
|
||||
|
||||
var brightnessGetCmd = &cobra.Command{
|
||||
@@ -36,7 +43,14 @@ var brightnessGetCmd = &cobra.Command{
|
||||
Short: "Get brightness for a device",
|
||||
Long: "Get current brightness percentage for a specific device",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: runBrightnessGet,
|
||||
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,
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -16,14 +16,26 @@ var dpmsOnCmd = &cobra.Command{
|
||||
Use: "on [output]",
|
||||
Short: "Turn display(s) on",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Run: runDPMSOn,
|
||||
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,
|
||||
}
|
||||
|
||||
var dpmsOffCmd = &cobra.Command{
|
||||
Use: "off [output]",
|
||||
Short: "Turn display(s) off",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Run: runDPMSOff,
|
||||
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,
|
||||
}
|
||||
|
||||
var dpmsListCmd = &cobra.Command{
|
||||
@@ -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 {
|
||||
|
||||
@@ -30,7 +30,14 @@ var keybindsShowCmd = &cobra.Command{
|
||||
Short: "Show keybinds for a provider",
|
||||
Long: "Display keybinds/cheatsheet for the specified provider",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: runKeybindsShow,
|
||||
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,
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -712,7 +712,7 @@ Item {
|
||||
|
||||
LazyLoader {
|
||||
id: niriOverviewOverlayLoader
|
||||
active: CompositorService.isNiri
|
||||
active: CompositorService.isNiri && SettingsData.niriOverviewOverlayEnabled
|
||||
component: NiriOverviewOverlay {
|
||||
id: niriOverviewOverlay
|
||||
}
|
||||
|
||||
@@ -130,6 +130,10 @@ DankModal {
|
||||
target: "spotlight"
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
DankModalWindow.persistentModal = spotlightModal;
|
||||
}
|
||||
|
||||
SpotlightContent {
|
||||
id: spotlightContentInstance
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ layout {
|
||||
}
|
||||
}
|
||||
|
||||
/-recent-windows {
|
||||
recent-windows {
|
||||
highlight {
|
||||
active-color "{{colors.primary_container.dark.hex}}"
|
||||
urgent-color "{{colors.error.default.hex}}"
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user