mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-02 10:32:07 -04:00
Compare commits
17 Commits
e86227f05f
...
bb08e1233a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb08e1233a | ||
|
|
5343e97ab2 | ||
|
|
edc544df7a | ||
|
|
a880edd9fb | ||
|
|
7e1d808d70 | ||
|
|
ce93f22669 | ||
|
|
a58037b968 | ||
|
|
ccf0b60935 | ||
|
|
aad7011b1c | ||
|
|
3bde7ef4d3 | ||
|
|
04555dbfa7 | ||
|
|
3b494aa591 | ||
|
|
365387c3cd | ||
|
|
bb74a0ca4d | ||
|
|
9cf2ef84b7 | ||
|
|
46aaf5ff77 | ||
|
|
c544bda5df |
6
.github/workflows/update-vendor-hash.yml
vendored
6
.github/workflows/update-vendor-hash.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
|||||||
echo "Build succeeded, no hash update needed"
|
echo "Build succeeded, no hash update needed"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
new_hash=$(echo "$output" | grep -oP "got:\s+\K\S+" | head -n1)
|
new_hash=$(echo "$output" | grep -oP "got:\s+\K\S+" | head -n1 || true)
|
||||||
[ -n "$new_hash" ] || { echo "Could not extract new vendorHash"; echo "$output"; exit 1; }
|
[ -n "$new_hash" ] || { echo "Could not extract new vendorHash"; echo "$output"; exit 1; }
|
||||||
current_hash=$(grep -oP 'vendorHash = "\K[^"]+' flake.nix)
|
current_hash=$(grep -oP 'vendorHash = "\K[^"]+' flake.nix)
|
||||||
[ "$current_hash" = "$new_hash" ] && { echo "vendorHash already up to date"; exit 0; }
|
[ "$current_hash" = "$new_hash" ] && { echo "vendorHash already up to date"; exit 0; }
|
||||||
@@ -59,8 +59,8 @@ jobs:
|
|||||||
git config user.email "dms-ci[bot]@users.noreply.github.com"
|
git config user.email "dms-ci[bot]@users.noreply.github.com"
|
||||||
git add flake.nix
|
git add flake.nix
|
||||||
git commit -m "nix: update vendorHash for go.mod changes" || exit 0
|
git commit -m "nix: update vendorHash for go.mod changes" || exit 0
|
||||||
git pull --rebase origin master
|
git pull --rebase origin ${{ github.ref_name }}
|
||||||
git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:master
|
git push https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git HEAD:${{ github.ref_name }}
|
||||||
else
|
else
|
||||||
echo "No changes to flake.nix"
|
echo "No changes to flake.nix"
|
||||||
fi
|
fi
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -79,7 +79,7 @@ install-desktop:
|
|||||||
@update-desktop-database -q $(APPLICATIONS_DIR) 2>/dev/null || true
|
@update-desktop-database -q $(APPLICATIONS_DIR) 2>/dev/null || true
|
||||||
@echo "Desktop entry installed"
|
@echo "Desktop entry installed"
|
||||||
|
|
||||||
install: build install-bin install-shell install-completions install-systemd install-icon install-desktop
|
install: install-bin install-shell install-completions install-systemd install-icon install-desktop
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Installation complete!"
|
@echo "Installation complete!"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|||||||
@@ -1,13 +1,26 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/golangci/golangci-lint
|
|
||||||
rev: v2.9.0
|
|
||||||
hooks:
|
|
||||||
- id: golangci-lint-fmt
|
|
||||||
require_serial: true
|
|
||||||
- id: golangci-lint-full
|
|
||||||
- id: golangci-lint-config-verify
|
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
|
- id: golangci-lint-fmt
|
||||||
|
name: golangci-lint-fmt
|
||||||
|
entry: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.3 fmt
|
||||||
|
language: system
|
||||||
|
require_serial: true
|
||||||
|
types: [go]
|
||||||
|
pass_filenames: false
|
||||||
|
- id: golangci-lint-full
|
||||||
|
name: golangci-lint-full
|
||||||
|
entry: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.3 run --fix
|
||||||
|
language: system
|
||||||
|
require_serial: true
|
||||||
|
types: [go]
|
||||||
|
pass_filenames: false
|
||||||
|
- id: golangci-lint-config-verify
|
||||||
|
name: golangci-lint-config-verify
|
||||||
|
entry: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.3 config verify
|
||||||
|
language: system
|
||||||
|
files: \.golangci\.(?:yml|yaml|toml|json)
|
||||||
|
pass_filenames: false
|
||||||
- id: go-test
|
- id: go-test
|
||||||
name: go test
|
name: go test
|
||||||
entry: go test ./...
|
entry: go test ./...
|
||||||
|
|||||||
@@ -63,19 +63,19 @@ endif
|
|||||||
|
|
||||||
build-all: build dankinstall
|
build-all: build dankinstall
|
||||||
|
|
||||||
install: build
|
install:
|
||||||
@echo "Installing $(BINARY_NAME) to $(INSTALL_DIR)..."
|
@echo "Installing $(BINARY_NAME) to $(INSTALL_DIR)..."
|
||||||
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME) $(INSTALL_DIR)/$(BINARY_NAME)
|
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME) $(INSTALL_DIR)/$(BINARY_NAME)
|
||||||
@echo "Installation complete"
|
@echo "Installation complete"
|
||||||
|
|
||||||
install-all: build-all
|
install-all:
|
||||||
@echo "Installing $(BINARY_NAME) to $(INSTALL_DIR)..."
|
@echo "Installing $(BINARY_NAME) to $(INSTALL_DIR)..."
|
||||||
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME) $(INSTALL_DIR)/$(BINARY_NAME)
|
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME) $(INSTALL_DIR)/$(BINARY_NAME)
|
||||||
@echo "Installing $(BINARY_NAME_INSTALL) to $(INSTALL_DIR)..."
|
@echo "Installing $(BINARY_NAME_INSTALL) to $(INSTALL_DIR)..."
|
||||||
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME_INSTALL) $(INSTALL_DIR)/$(BINARY_NAME_INSTALL)
|
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME_INSTALL) $(INSTALL_DIR)/$(BINARY_NAME_INSTALL)
|
||||||
@echo "Installation complete"
|
@echo "Installation complete"
|
||||||
|
|
||||||
install-dankinstall: dankinstall
|
install-dankinstall:
|
||||||
@echo "Installing $(BINARY_NAME_INSTALL) to $(INSTALL_DIR)..."
|
@echo "Installing $(BINARY_NAME_INSTALL) to $(INSTALL_DIR)..."
|
||||||
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME_INSTALL) $(INSTALL_DIR)/$(BINARY_NAME_INSTALL)
|
@install -D -m 755 $(BUILD_DIR)/$(BINARY_NAME_INSTALL) $(INSTALL_DIR)/$(BINARY_NAME_INSTALL)
|
||||||
@echo "Installation complete"
|
@echo "Installation complete"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"blocked_commands": [
|
"blocked_commands": [
|
||||||
"greeter install",
|
"greeter install",
|
||||||
"greeter enable",
|
"greeter enable",
|
||||||
"greeter sync",
|
|
||||||
"greeter uninstall",
|
"greeter uninstall",
|
||||||
"setup"
|
"setup"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1079,14 +1079,14 @@ func formatResultsPlain(results []checkResult) string {
|
|||||||
if currentCategory != -1 {
|
if currentCategory != -1 {
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
}
|
}
|
||||||
sb.WriteString(fmt.Sprintf("**%s**\n", r.category.String()))
|
fmt.Fprintf(&sb, "**%s**\n", r.category.String())
|
||||||
currentCategory = r.category
|
currentCategory = r.category
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.WriteString(fmt.Sprintf("- [%s] %s: %s\n", r.status, r.name, r.message))
|
fmt.Fprintf(&sb, "- [%s] %s: %s\n", r.status, r.name, r.message)
|
||||||
|
|
||||||
if doctorVerbose && r.details != "" {
|
if doctorVerbose && r.details != "" {
|
||||||
sb.WriteString(fmt.Sprintf(" - %s\n", r.details))
|
fmt.Fprintf(&sb, " - %s\n", r.details)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1096,8 +1096,8 @@ func formatResultsPlain(results []checkResult) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sb.WriteString("\n---\n")
|
sb.WriteString("\n---\n")
|
||||||
sb.WriteString(fmt.Sprintf("**Summary:** %d error(s), %d warning(s), %d ok\n",
|
fmt.Fprintf(&sb, "**Summary:** %d error(s), %d warning(s), %d ok\n",
|
||||||
ds.ErrorCount(), ds.WarningCount(), ds.OKCount()))
|
ds.ErrorCount(), ds.WarningCount(), ds.OKCount())
|
||||||
|
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,9 @@ var greeterInstallCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var greeterSyncCmd = &cobra.Command{
|
var greeterSyncCmd = &cobra.Command{
|
||||||
Use: "sync",
|
Use: "sync",
|
||||||
Short: "Sync DMS theme and settings with greeter",
|
Short: "Sync DMS theme and settings with greeter",
|
||||||
Long: "Synchronize your current user's DMS theme, settings, and wallpaper configuration with the login greeter screen",
|
Long: "Synchronize your current user's DMS theme, settings, and wallpaper configuration with the login greeter screen",
|
||||||
PreRunE: requireMutableSystemCommand,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
yes, _ := cmd.Flags().GetBool("yes")
|
yes, _ := cmd.Flags().GetBool("yes")
|
||||||
auth, _ := cmd.Flags().GetBool("auth")
|
auth, _ := cmd.Flags().GetBool("auth")
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
matugenQueueCmd.Flags().Bool("wait", true, "Wait for completion")
|
matugenQueueCmd.Flags().Bool("wait", true, "Wait for completion")
|
||||||
matugenQueueCmd.Flags().Duration("timeout", 30*time.Second, "Timeout for waiting")
|
matugenQueueCmd.Flags().Duration("timeout", 90*time.Second, "Timeout for waiting")
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildMatugenOptions(cmd *cobra.Command) matugen.Options {
|
func buildMatugenOptions(cmd *cobra.Command) matugen.Options {
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ func getImmutablePolicy() (*immutableCommandPolicy, error) {
|
|||||||
immutablePolicy = immutableCommandPolicy{
|
immutablePolicy = immutableCommandPolicy{
|
||||||
ImmutableSystem: detectedImmutable,
|
ImmutableSystem: detectedImmutable,
|
||||||
ImmutableReason: reason,
|
ImmutableReason: reason,
|
||||||
BlockedCommands: []string{"greeter install", "greeter enable", "greeter sync", "setup"},
|
BlockedCommands: []string{"greeter install", "greeter enable", "setup"},
|
||||||
Message: "This command is disabled on immutable/image-based systems. Use your distro-native workflow for system-level changes.",
|
Message: "This command is disabled on immutable/image-based systems. Use your distro-native workflow for system-level changes.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
module github.com/AvengeMedia/DankMaterialShell/core
|
module github.com/AvengeMedia/DankMaterialShell/core
|
||||||
|
|
||||||
go 1.25.0
|
go 1.26.0
|
||||||
|
|
||||||
|
toolchain go1.26.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Wifx/gonetworkmanager/v2 v2.2.0
|
github.com/Wifx/gonetworkmanager/v2 v2.2.0
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ var templateRegistry = []TemplateDef{
|
|||||||
{ID: "kcolorscheme", ConfigFile: "kcolorscheme.toml", RunUnconditionally: true},
|
{ID: "kcolorscheme", ConfigFile: "kcolorscheme.toml", RunUnconditionally: true},
|
||||||
{ID: "vscode", Kind: TemplateKindVSCode},
|
{ID: "vscode", Kind: TemplateKindVSCode},
|
||||||
{ID: "emacs", Commands: []string{"emacs"}, ConfigFile: "emacs.toml", Kind: TemplateKindEmacs},
|
{ID: "emacs", Commands: []string{"emacs"}, ConfigFile: "emacs.toml", Kind: TemplateKindEmacs},
|
||||||
{ID: "zed", Commands: []string{"zed"}, ConfigFile: "zed.toml"},
|
{ID: "zed", Commands: []string{"zed", "zeditor", "zedit"}, ConfigFile: "zed.toml"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorMode) GTKTheme() string {
|
func (c *ColorMode) GTKTheme() string {
|
||||||
|
|||||||
@@ -6,12 +6,20 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
"github.com/pilebones/go-udev/netlink"
|
"github.com/pilebones/go-udev/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
udevRecvBufSize = 8 * 1024 * 1024
|
||||||
|
udevMaxRetries = 5
|
||||||
|
udevBaseDelay = 2 * time.Second
|
||||||
|
udevMaxDelay = 60 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
type UdevMonitor struct {
|
type UdevMonitor struct {
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
rescanMutex sync.Mutex
|
rescanMutex sync.Mutex
|
||||||
@@ -29,13 +37,6 @@ func NewUdevMonitor(manager *Manager) *UdevMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *UdevMonitor) run(manager *Manager) {
|
func (m *UdevMonitor) run(manager *Manager) {
|
||||||
conn := &netlink.UEventConn{}
|
|
||||||
if err := conn.Connect(netlink.UdevEvent); err != nil {
|
|
||||||
log.Errorf("Failed to connect to udev netlink: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
matcher := &netlink.RuleDefinitions{
|
matcher := &netlink.RuleDefinitions{
|
||||||
Rules: []netlink.RuleDefinition{
|
Rules: []netlink.RuleDefinition{
|
||||||
{Env: map[string]string{"SUBSYSTEM": "backlight"}},
|
{Env: map[string]string{"SUBSYSTEM": "backlight"}},
|
||||||
@@ -48,6 +49,46 @@ func (m *UdevMonitor) run(manager *Manager) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
failures := 0
|
||||||
|
for {
|
||||||
|
if err := m.monitorLoop(manager, matcher); err != nil {
|
||||||
|
log.Errorf("Udev monitor error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-m.stop:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
failures++
|
||||||
|
if failures > udevMaxRetries {
|
||||||
|
log.Errorf("Udev monitor exceeded %d retries, giving up", udevMaxRetries)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delay := min(udevBaseDelay*time.Duration(1<<(failures-1)), udevMaxDelay)
|
||||||
|
log.Infof("Udev monitor reconnecting in %v (attempt %d/%d)", delay, failures, udevMaxRetries)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-m.stop:
|
||||||
|
return
|
||||||
|
case <-time.After(delay):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UdevMonitor) monitorLoop(manager *Manager, matcher *netlink.RuleDefinitions) error {
|
||||||
|
conn := &netlink.UEventConn{}
|
||||||
|
if err := conn.Connect(netlink.UdevEvent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
if err := syscall.SetsockoptInt(conn.Fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, udevRecvBufSize); err != nil {
|
||||||
|
log.Warnf("Failed to set udev socket receive buffer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
events := make(chan netlink.UEvent)
|
events := make(chan netlink.UEvent)
|
||||||
errs := make(chan error)
|
errs := make(chan error)
|
||||||
conn.Monitor(events, errs, matcher)
|
conn.Monitor(events, errs, matcher)
|
||||||
@@ -57,10 +98,9 @@ func (m *UdevMonitor) run(manager *Manager) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-m.stop:
|
case <-m.stop:
|
||||||
return
|
return nil
|
||||||
case err := <-errs:
|
case err := <-errs:
|
||||||
log.Errorf("Udev monitor error: %v", err)
|
return err
|
||||||
return
|
|
||||||
case event := <-events:
|
case event := <-events:
|
||||||
m.handleEvent(manager, event)
|
m.handleEvent(manager, event)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ var dbusManager *serverDbus.Manager
|
|||||||
var wlContext *wlcontext.SharedContext
|
var wlContext *wlcontext.SharedContext
|
||||||
var themeModeManager *thememode.Manager
|
var themeModeManager *thememode.Manager
|
||||||
var locationManager *location.Manager
|
var locationManager *location.Manager
|
||||||
|
var geoClientInstance geolocation.Client
|
||||||
|
|
||||||
const dbusClientID = "dms-dbus-client"
|
const dbusClientID = "dms-dbus-client"
|
||||||
|
|
||||||
@@ -191,7 +192,7 @@ func InitializeFreedeskManager() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitializeWaylandManager(geoClient geolocation.Client) error {
|
func InitializeWaylandManager() error {
|
||||||
log.Info("Attempting to initialize Wayland gamma control...")
|
log.Info("Attempting to initialize Wayland gamma control...")
|
||||||
|
|
||||||
if wlContext == nil {
|
if wlContext == nil {
|
||||||
@@ -204,7 +205,7 @@ func InitializeWaylandManager(geoClient geolocation.Client) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := wayland.DefaultConfig()
|
config := wayland.DefaultConfig()
|
||||||
manager, err := wayland.NewManager(wlContext.Display(), geoClient, config)
|
manager, err := wayland.NewManager(wlContext.Display(), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to initialize wayland manager: %v", err)
|
log.Errorf("Failed to initialize wayland manager: %v", err)
|
||||||
return err
|
return err
|
||||||
@@ -385,8 +386,8 @@ func InitializeDbusManager() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitializeThemeModeManager(geoClient geolocation.Client) error {
|
func InitializeThemeModeManager() error {
|
||||||
manager := thememode.NewManager(geoClient)
|
manager := thememode.NewManager()
|
||||||
themeModeManager = manager
|
themeModeManager = manager
|
||||||
|
|
||||||
log.Info("Theme mode automation manager initialized")
|
log.Info("Theme mode automation manager initialized")
|
||||||
@@ -1330,6 +1331,9 @@ func cleanupManagers() {
|
|||||||
if locationManager != nil {
|
if locationManager != nil {
|
||||||
locationManager.Close()
|
locationManager.Close()
|
||||||
}
|
}
|
||||||
|
if geoClientInstance != nil {
|
||||||
|
geoClientInstance.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(printDocs bool) error {
|
func Start(printDocs bool) error {
|
||||||
@@ -1545,9 +1549,6 @@ func Start(printDocs bool) error {
|
|||||||
loginctlReady := make(chan struct{})
|
loginctlReady := make(chan struct{})
|
||||||
freedesktopReady := make(chan struct{})
|
freedesktopReady := make(chan struct{})
|
||||||
|
|
||||||
geoClient := geolocation.NewClient()
|
|
||||||
defer geoClient.Close()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(loginctlReady)
|
defer close(loginctlReady)
|
||||||
if err := InitializeLoginctlManager(); err != nil {
|
if err := InitializeLoginctlManager(); err != nil {
|
||||||
@@ -1592,10 +1593,41 @@ func Start(printDocs bool) error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := InitializeWaylandManager(geoClient); err != nil {
|
if err := InitializeWaylandManager(); err != nil {
|
||||||
log.Warnf("Wayland manager unavailable: %v", err)
|
log.Warnf("Wayland manager unavailable: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := InitializeThemeModeManager(); err != nil {
|
||||||
|
log.Warnf("Theme mode manager unavailable: %v", err)
|
||||||
|
} else {
|
||||||
|
notifyCapabilityChange()
|
||||||
|
go func() {
|
||||||
|
<-loginctlReady
|
||||||
|
if loginctlManager == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
themeModeManager.WatchLoginctl(loginctlManager)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
geoClient := geolocation.NewClient()
|
||||||
|
geoClientInstance = geoClient
|
||||||
|
|
||||||
|
if waylandManager != nil {
|
||||||
|
waylandManager.SetGeoClient(geoClient)
|
||||||
|
}
|
||||||
|
if themeModeManager != nil {
|
||||||
|
themeModeManager.SetGeoClient(geoClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := InitializeLocationManager(geoClient); err != nil {
|
||||||
|
log.Warnf("Location manager unavailable: %v", err)
|
||||||
|
} else {
|
||||||
|
notifyCapabilityChange()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := InitializeBluezManager(); err != nil {
|
if err := InitializeBluezManager(); err != nil {
|
||||||
log.Warnf("Bluez manager unavailable: %v", err)
|
log.Warnf("Bluez manager unavailable: %v", err)
|
||||||
@@ -1624,25 +1656,6 @@ func Start(printDocs bool) error {
|
|||||||
log.Debugf("WlrOutput manager unavailable: %v", err)
|
log.Debugf("WlrOutput manager unavailable: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := InitializeThemeModeManager(geoClient); err != nil {
|
|
||||||
log.Warnf("Theme mode manager unavailable: %v", err)
|
|
||||||
} else {
|
|
||||||
notifyCapabilityChange()
|
|
||||||
go func() {
|
|
||||||
<-loginctlReady
|
|
||||||
if loginctlManager == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
themeModeManager.WatchLoginctl(loginctlManager)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := InitializeLocationManager(geoClient); err != nil {
|
|
||||||
log.Warnf("Location manager unavailable: %v", err)
|
|
||||||
} else {
|
|
||||||
notifyCapabilityChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
fatalErrChan := make(chan error, 1)
|
fatalErrChan := make(chan error, 1)
|
||||||
if wlrOutputManager != nil {
|
if wlrOutputManager != nil {
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ type Manager struct {
|
|||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(geoClient geolocation.Client) *Manager {
|
func NewManager() *Manager {
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
config: Config{
|
config: Config{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
@@ -54,7 +54,6 @@ func NewManager(geoClient geolocation.Client) *Manager {
|
|||||||
},
|
},
|
||||||
stopChan: make(chan struct{}),
|
stopChan: make(chan struct{}),
|
||||||
updateTrigger: make(chan struct{}, 1),
|
updateTrigger: make(chan struct{}, 1),
|
||||||
geoClient: geoClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m.updateState(time.Now())
|
m.updateState(time.Now())
|
||||||
@@ -315,6 +314,10 @@ func (m *Manager) getConfig() Config {
|
|||||||
return m.config
|
return m.config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) SetGeoClient(client geolocation.Client) {
|
||||||
|
m.geoClient = client
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) getLocation(config Config) (*float64, *float64) {
|
func (m *Manager) getLocation(config Config) (*float64, *float64) {
|
||||||
if config.Latitude != nil && config.Longitude != nil {
|
if config.Latitude != nil && config.Longitude != nil {
|
||||||
return config.Latitude, config.Longitude
|
return config.Latitude, config.Longitude
|
||||||
@@ -322,6 +325,9 @@ func (m *Manager) getLocation(config Config) (*float64, *float64) {
|
|||||||
if !config.UseIPLocation {
|
if !config.UseIPLocation {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
if m.geoClient == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
m.locationMutex.RLock()
|
m.locationMutex.RLock()
|
||||||
if m.cachedIPLat != nil && m.cachedIPLon != nil {
|
if m.cachedIPLat != nil && m.cachedIPLon != nil {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
|
|
||||||
const animKelvinStep = 25
|
const animKelvinStep = 25
|
||||||
|
|
||||||
func NewManager(display wlclient.WaylandDisplay, geoClient geolocation.Client, config Config) (*Manager, error) {
|
func NewManager(display wlclient.WaylandDisplay, config Config) (*Manager, error) {
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,6 @@ func NewManager(display wlclient.WaylandDisplay, geoClient geolocation.Client, c
|
|||||||
updateTrigger: make(chan struct{}, 1),
|
updateTrigger: make(chan struct{}, 1),
|
||||||
dirty: make(chan struct{}, 1),
|
dirty: make(chan struct{}, 1),
|
||||||
dbusSignal: make(chan *dbus.Signal, 16),
|
dbusSignal: make(chan *dbus.Signal, 16),
|
||||||
geoClient: geoClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.setupRegistry(); err != nil {
|
if err := m.setupRegistry(); err != nil {
|
||||||
@@ -422,6 +421,10 @@ func (m *Manager) recalcSchedule(now time.Time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) SetGeoClient(client geolocation.Client) {
|
||||||
|
m.geoClient = client
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) getLocation() (*float64, *float64) {
|
func (m *Manager) getLocation() (*float64, *float64) {
|
||||||
m.configMutex.RLock()
|
m.configMutex.RLock()
|
||||||
config := m.config
|
config := m.config
|
||||||
@@ -430,27 +433,31 @@ func (m *Manager) getLocation() (*float64, *float64) {
|
|||||||
if config.Latitude != nil && config.Longitude != nil {
|
if config.Latitude != nil && config.Longitude != nil {
|
||||||
return config.Latitude, config.Longitude
|
return config.Latitude, config.Longitude
|
||||||
}
|
}
|
||||||
if config.UseIPLocation {
|
if !config.UseIPLocation {
|
||||||
m.locationMutex.RLock()
|
return nil, nil
|
||||||
if m.cachedIPLat != nil && m.cachedIPLon != nil {
|
|
||||||
lat, lon := m.cachedIPLat, m.cachedIPLon
|
|
||||||
m.locationMutex.RUnlock()
|
|
||||||
return lat, lon
|
|
||||||
}
|
|
||||||
m.locationMutex.RUnlock()
|
|
||||||
|
|
||||||
location, err := m.geoClient.GetLocation()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.locationMutex.Lock()
|
|
||||||
m.cachedIPLat = &location.Latitude
|
|
||||||
m.cachedIPLon = &location.Longitude
|
|
||||||
m.locationMutex.Unlock()
|
|
||||||
return m.cachedIPLat, m.cachedIPLon
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
if m.geoClient == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.locationMutex.RLock()
|
||||||
|
if m.cachedIPLat != nil && m.cachedIPLon != nil {
|
||||||
|
lat, lon := m.cachedIPLat, m.cachedIPLon
|
||||||
|
m.locationMutex.RUnlock()
|
||||||
|
return lat, lon
|
||||||
|
}
|
||||||
|
m.locationMutex.RUnlock()
|
||||||
|
|
||||||
|
location, err := m.geoClient.GetLocation()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.locationMutex.Lock()
|
||||||
|
m.cachedIPLat = &location.Latitude
|
||||||
|
m.cachedIPLon = &location.Longitude
|
||||||
|
m.locationMutex.Unlock()
|
||||||
|
return m.cachedIPLat, m.cachedIPLon
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) hasValidSchedule() bool {
|
func (m *Manager) hasValidSchedule() bool {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
mocks_geolocation "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/geolocation"
|
|
||||||
mocks_wlclient "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlclient"
|
mocks_wlclient "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -391,20 +390,18 @@ func TestNotifySubscribers_NonBlocking(t *testing.T) {
|
|||||||
|
|
||||||
func TestNewManager_GetRegistryError(t *testing.T) {
|
func TestNewManager_GetRegistryError(t *testing.T) {
|
||||||
mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t)
|
mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t)
|
||||||
mockGeoclient := mocks_geolocation.NewMockClient(t)
|
|
||||||
|
|
||||||
mockDisplay.EXPECT().Context().Return(nil)
|
mockDisplay.EXPECT().Context().Return(nil)
|
||||||
mockDisplay.EXPECT().GetRegistry().Return(nil, errors.New("failed to get registry"))
|
mockDisplay.EXPECT().GetRegistry().Return(nil, errors.New("failed to get registry"))
|
||||||
|
|
||||||
config := DefaultConfig()
|
config := DefaultConfig()
|
||||||
_, err := NewManager(mockDisplay, mockGeoclient, config)
|
_, err := NewManager(mockDisplay, config)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "get registry")
|
assert.Contains(t, err.Error(), "get registry")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewManager_InvalidConfig(t *testing.T) {
|
func TestNewManager_InvalidConfig(t *testing.T) {
|
||||||
mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t)
|
mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t)
|
||||||
mockGeoclient := mocks_geolocation.NewMockClient(t)
|
|
||||||
|
|
||||||
config := Config{
|
config := Config{
|
||||||
LowTemp: 500,
|
LowTemp: 500,
|
||||||
@@ -412,6 +409,6 @@ func TestNewManager_InvalidConfig(t *testing.T) {
|
|||||||
Gamma: 1.0,
|
Gamma: 1.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := NewManager(mockDisplay, mockGeoclient, config)
|
_, err := NewManager(mockDisplay, config)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package wlcontext
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/errdefs"
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
@@ -123,6 +123,9 @@ func (sc *SharedContext) eventDispatcher() {
|
|||||||
{Fd: int32(sc.wakeR), Events: unix.POLLIN},
|
{Fd: int32(sc.wakeR), Events: unix.POLLIN},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consecutiveErrors := 0
|
||||||
|
const maxConsecutiveErrors = 20
|
||||||
|
|
||||||
for {
|
for {
|
||||||
sc.drainCmdQueue()
|
sc.drainCmdQueue()
|
||||||
|
|
||||||
@@ -153,9 +156,19 @@ func (sc *SharedContext) eventDispatcher() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Dispatch(); err != nil && !os.IsTimeout(err) {
|
if err := ctx.Dispatch(); err != nil && !os.IsTimeout(err) {
|
||||||
log.Errorf("Wayland connection error: %v", err)
|
consecutiveErrors++
|
||||||
return
|
log.Warnf("Wayland connection error (%d/%d): %v", consecutiveErrors, maxConsecutiveErrors, err)
|
||||||
|
|
||||||
|
if consecutiveErrors >= maxConsecutiveErrors {
|
||||||
|
log.Errorf("Fatal: Wayland connection unrecoverable after %d attempts. Exiting dispatcher.", maxConsecutiveErrors)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(100 * time.Millisecond * time.Duration(consecutiveErrors))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consecutiveErrors = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func (m Model) viewDeployingConfigs() string {
|
|||||||
|
|
||||||
spinner := m.spinner.View()
|
spinner := m.spinner.View()
|
||||||
status := m.styles.Normal.Render("Setting up configuration files...")
|
status := m.styles.Normal.Render("Setting up configuration files...")
|
||||||
b.WriteString(fmt.Sprintf("%s %s", spinner, status))
|
fmt.Fprintf(&b, "%s %s", spinner, status)
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
|
|
||||||
// Show progress information
|
// Show progress information
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func (m Model) viewDetectingDeps() string {
|
|||||||
|
|
||||||
spinner := m.spinner.View()
|
spinner := m.spinner.View()
|
||||||
status := m.styles.Normal.Render("Scanning system for existing packages and configurations...")
|
status := m.styles.Normal.Render("Scanning system for existing packages and configurations...")
|
||||||
b.WriteString(fmt.Sprintf("%s %s", spinner, status))
|
fmt.Fprintf(&b, "%s %s", spinner, status)
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (m Model) viewInstallingPackages() string {
|
|||||||
if !m.packageProgress.isComplete {
|
if !m.packageProgress.isComplete {
|
||||||
spinner := m.spinner.View()
|
spinner := m.spinner.View()
|
||||||
status := m.styles.Normal.Render(m.packageProgress.step)
|
status := m.styles.Normal.Render(m.packageProgress.step)
|
||||||
b.WriteString(fmt.Sprintf("%s %s", spinner, status))
|
fmt.Fprintf(&b, "%s %s", spinner, status)
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
|
|
||||||
// Show progress bar
|
// Show progress bar
|
||||||
@@ -387,7 +387,7 @@ func (m Model) viewDebugLogs() string {
|
|||||||
|
|
||||||
for i := startIdx; i < len(allLogs); i++ {
|
for i := startIdx; i < len(allLogs); i++ {
|
||||||
if allLogs[i] != "" {
|
if allLogs[i] != "" {
|
||||||
b.WriteString(fmt.Sprintf("%d: %s\n", i, allLogs[i]))
|
fmt.Fprintf(&b, "%d: %s\n", i, allLogs[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func (m Model) viewFingerprintAuth() string {
|
|||||||
|
|
||||||
spinner := m.spinner.View()
|
spinner := m.spinner.View()
|
||||||
status := m.styles.Normal.Render("Waiting for fingerprint...")
|
status := m.styles.Normal.Render("Waiting for fingerprint...")
|
||||||
b.WriteString(fmt.Sprintf("%s %s", spinner, status))
|
fmt.Fprintf(&b, "%s %s", spinner, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ func (m Model) viewWelcome() string {
|
|||||||
contentStyle = contentStyle.Bold(true)
|
contentStyle = contentStyle.Bold(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString(fmt.Sprintf(" %s %s\n",
|
fmt.Fprintf(&b, " %s %s\n",
|
||||||
prefixStyle.Render(prefix),
|
prefixStyle.Render(prefix),
|
||||||
contentStyle.Render(content)))
|
contentStyle.Render(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
@@ -158,7 +158,7 @@ func (m Model) viewWelcome() string {
|
|||||||
} else if m.isLoading {
|
} else if m.isLoading {
|
||||||
spinner := m.spinner.View()
|
spinner := m.spinner.View()
|
||||||
loading := m.styles.Normal.Render("Detecting system...")
|
loading := m.styles.Normal.Render("Detecting system...")
|
||||||
b.WriteString(fmt.Sprintf("%s %s\n\n", spinner, loading))
|
fmt.Fprintf(&b, "%s %s\n\n", spinner, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Footer with better visual separation
|
// Footer with better visual separation
|
||||||
|
|||||||
23
flake.nix
23
flake.nix
@@ -17,6 +17,25 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
goModVersion =
|
||||||
|
let
|
||||||
|
content = builtins.readFile ./core/go.mod;
|
||||||
|
lines = builtins.filter builtins.isString (builtins.split "\n" content);
|
||||||
|
goLines = builtins.filter (l: builtins.match "go [0-9]+\\..*" l != null) lines;
|
||||||
|
matched =
|
||||||
|
if goLines != [ ] then builtins.match "go ([0-9]+)\\.([0-9]+).*" (builtins.head goLines) else null;
|
||||||
|
in
|
||||||
|
if matched != null then
|
||||||
|
{
|
||||||
|
major = builtins.elemAt matched 0;
|
||||||
|
minor = builtins.elemAt matched 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
major = "1";
|
||||||
|
minor = "25";
|
||||||
|
};
|
||||||
|
goForPkgs = pkgs: pkgs.${"go_${goModVersion.major}_${goModVersion.minor}"};
|
||||||
forEachSystem =
|
forEachSystem =
|
||||||
fn:
|
fn:
|
||||||
nixpkgs.lib.genAttrs [ "aarch64-darwin" "aarch64-linux" "x86_64-darwin" "x86_64-linux" ] (
|
nixpkgs.lib.genAttrs [ "aarch64-darwin" "aarch64-linux" "x86_64-darwin" "x86_64-linux" ] (
|
||||||
@@ -76,7 +95,7 @@
|
|||||||
{
|
{
|
||||||
extraQtPackages ? [ ],
|
extraQtPackages ? [ ],
|
||||||
}:
|
}:
|
||||||
pkgs.buildGoModule (
|
(pkgs.buildGoModule.override { go = goForPkgs pkgs; }) (
|
||||||
let
|
let
|
||||||
rootSrc = ./.;
|
rootSrc = ./.;
|
||||||
qtPackages = (qmlPkgs pkgs) ++ extraQtPackages;
|
qtPackages = (qmlPkgs pkgs) ++ extraQtPackages;
|
||||||
@@ -187,7 +206,7 @@
|
|||||||
buildInputs =
|
buildInputs =
|
||||||
with pkgs;
|
with pkgs;
|
||||||
[
|
[
|
||||||
go_1_25
|
(goForPkgs pkgs)
|
||||||
go-mockery_2
|
go-mockery_2
|
||||||
gopls
|
gopls
|
||||||
delve
|
delve
|
||||||
|
|||||||
@@ -580,14 +580,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newSettings[identifier]) {
|
newSettings[identifier] = getMonitorCyclingSettings(screenName);
|
||||||
newSettings[identifier] = {
|
|
||||||
"enabled": false,
|
|
||||||
"mode": "interval",
|
|
||||||
"interval": 300,
|
|
||||||
"time": "06:00"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
newSettings[identifier].enabled = enabled;
|
newSettings[identifier].enabled = enabled;
|
||||||
monitorCyclingSettings = newSettings;
|
monitorCyclingSettings = newSettings;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@@ -618,14 +611,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newSettings[identifier]) {
|
newSettings[identifier] = getMonitorCyclingSettings(screenName);
|
||||||
newSettings[identifier] = {
|
|
||||||
"enabled": false,
|
|
||||||
"mode": "interval",
|
|
||||||
"interval": 300,
|
|
||||||
"time": "06:00"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
newSettings[identifier].mode = mode;
|
newSettings[identifier].mode = mode;
|
||||||
monitorCyclingSettings = newSettings;
|
monitorCyclingSettings = newSettings;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@@ -656,14 +642,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newSettings[identifier]) {
|
newSettings[identifier] = getMonitorCyclingSettings(screenName);
|
||||||
newSettings[identifier] = {
|
|
||||||
"enabled": false,
|
|
||||||
"mode": "interval",
|
|
||||||
"interval": 300,
|
|
||||||
"time": "06:00"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
newSettings[identifier].interval = interval;
|
newSettings[identifier].interval = interval;
|
||||||
monitorCyclingSettings = newSettings;
|
monitorCyclingSettings = newSettings;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@@ -694,14 +673,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newSettings[identifier]) {
|
newSettings[identifier] = getMonitorCyclingSettings(screenName);
|
||||||
newSettings[identifier] = {
|
|
||||||
"enabled": false,
|
|
||||||
"mode": "interval",
|
|
||||||
"interval": 300,
|
|
||||||
"time": "06:00"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
newSettings[identifier].time = time;
|
newSettings[identifier].time = time;
|
||||||
monitorCyclingSettings = newSettings;
|
monitorCyclingSettings = newSettings;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@@ -1218,7 +1190,7 @@ Singleton {
|
|||||||
"time": "06:00"
|
"time": "06:00"
|
||||||
};
|
};
|
||||||
var value = _findMonitorValue(monitorCyclingSettings, screenName);
|
var value = _findMonitorValue(monitorCyclingSettings, screenName);
|
||||||
return value !== undefined ? value : defaults;
|
return Object.assign({}, defaults, value !== undefined ? value : {});
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
|
|||||||
@@ -477,6 +477,11 @@ Singleton {
|
|||||||
property bool matugenTemplateEmacs: true
|
property bool matugenTemplateEmacs: true
|
||||||
property bool matugenTemplateZed: true
|
property bool matugenTemplateZed: true
|
||||||
|
|
||||||
|
property var matugenTemplateNeovimSettings: ({
|
||||||
|
"dark": { "baseTheme": "github_dark", "harmony": 0.5 },
|
||||||
|
"light": { "baseTheme": "github_light", "harmony": 0.5 }
|
||||||
|
})
|
||||||
|
|
||||||
property bool showDock: false
|
property bool showDock: false
|
||||||
property bool dockAutoHide: false
|
property bool dockAutoHide: false
|
||||||
property bool dockSmartAutoHide: false
|
property bool dockSmartAutoHide: false
|
||||||
|
|||||||
@@ -292,6 +292,13 @@ var SPEC = {
|
|||||||
matugenTemplateEmacs: { def: true },
|
matugenTemplateEmacs: { def: true },
|
||||||
matugenTemplateZed: { def: true },
|
matugenTemplateZed: { def: true },
|
||||||
|
|
||||||
|
matugenTemplateNeovimSettings: {
|
||||||
|
def: {
|
||||||
|
dark: { baseTheme: "github_dark", harmony: 0.5 },
|
||||||
|
light: { baseTheme: "github_light", harmony: 0.5 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
showDock: { def: false },
|
showDock: { def: false },
|
||||||
dockAutoHide: { def: false },
|
dockAutoHide: { def: false },
|
||||||
dockSmartAutoHide: { def: false },
|
dockSmartAutoHide: { def: false },
|
||||||
|
|||||||
@@ -2568,18 +2568,96 @@ Item {
|
|||||||
onToggled: checked => SettingsData.set("matugenTemplateFoot", checked)
|
onToggled: checked => SettingsData.set("matugenTemplateFoot", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsDivider {
|
||||||
|
visible: neovimThemeToggle.visible && neovimThemeToggle.checked
|
||||||
|
}
|
||||||
|
|
||||||
SettingsToggleRow {
|
SettingsToggleRow {
|
||||||
|
id: neovimThemeToggle
|
||||||
tab: "theme"
|
tab: "theme"
|
||||||
tags: ["matugen", "neovim", "terminal", "template"]
|
tags: ["matugen", "neovim", "terminal", "template"]
|
||||||
settingKey: "matugenTemplateNeovim"
|
settingKey: "matugenTemplateNeovim"
|
||||||
text: "neovim"
|
text: "neovim"
|
||||||
description: getTemplateDescription("nvim", I18n.tr("Requires lazy plugin manager", "neovim template description"))
|
description: getTemplateDescription("nvim", I18n.tr("Required plugin: ") + "https://github.com/AvengeMedia/base46")
|
||||||
descriptionColor: getTemplateDescriptionColor("nvim")
|
descriptionColor: getTemplateDescriptionColor("nvim")
|
||||||
visible: SettingsData.runDmsMatugenTemplates
|
visible: SettingsData.runDmsMatugenTemplates
|
||||||
checked: SettingsData.matugenTemplateNeovim
|
checked: SettingsData.matugenTemplateNeovim
|
||||||
onToggled: checked => SettingsData.set("matugenTemplateNeovim", checked)
|
onToggled: checked => SettingsData.set("matugenTemplateNeovim", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
text: I18n.tr("Dark mode base")
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["matugen", "neovim", "terminal", "template"]
|
||||||
|
settingKey: "matugenTemplateNeovimSettings"
|
||||||
|
description: "Base to derive dark theme from"
|
||||||
|
visible: neovimThemeToggle.visible && neovimThemeToggle.checked
|
||||||
|
currentValue: SettingsData.matugenTemplateNeovimSettings?.dark?.baseTheme ?? "github_dark"
|
||||||
|
options: ["aquarium", "ashes", "aylin", "ayu_dark", "bearded-arc", "carbonfox", "catppuccin", "chadracula", "chadracula-evondev", "chadtain", "chocolate", "darcula-dark", "dark_horizon", "decay", "default-dark", "doomchad", "eldritch", "embark", "everblush", "everforest", "falcon", "flexoki", "flouromachine", "gatekeeper", "github_dark", "gruvbox", "gruvchad", "hiberbee", "horizon", "jabuti", "jellybeans", "kanagawa", "kanagawa-dragon", "material-darker", "material-deep-ocean", "melange", "midnight_breeze", "mito-laser", "monekai", "monochrome", "mountain", "neofusion", "nightfox", "nightlamp", "nightowl", "nord", "obsidian-ember", "oceanic-next", "onedark", "onenord", "oxocarbon", "palenight", "pastelDark", "pastelbeans", "penumbra_dark", "poimandres", "radium", "rosepine", "rxyhn", "scaryforest", "seoul256_dark", "solarized_dark", "solarized_osaka", "starlight", "sweetpastel", "tokyodark", "tokyonight", "tomorrow_night", "tundra", "vesper", "vscode_dark", "wombat", "yoru", "zenburn"]
|
||||||
|
enableFuzzySearch: true
|
||||||
|
onValueChanged: value => {
|
||||||
|
const settings = SettingsData.matugenTemplateNeovimSettings;
|
||||||
|
settings.dark.baseTheme = value;
|
||||||
|
SettingsData.set("matugenTemplateNeovimSettings", settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
text: I18n.tr("Light mode base")
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["matugen", "neovim", "terminal", "template"]
|
||||||
|
settingKey: "matugenTemplateNeovimSettings"
|
||||||
|
description: "Base to derive light theme from"
|
||||||
|
visible: neovimThemeToggle.visible && neovimThemeToggle.checked
|
||||||
|
currentValue: SettingsData.matugenTemplateNeovimSettings?.light?.baseTheme ?? "github_light"
|
||||||
|
options: ["ayu_light", "blossom_light", "catppuccin-latte", "default-light", "everforest_light", "flex-light", "flexoki-light", "github_light", "gruvbox_light", "material-lighter", "nano-light", "oceanic-light", "one_light", "onenord_light", "penumbra_light", "rosepine-dawn", "seoul256_light", "solarized_light", "sunrise_breeze", "vscode_light"]
|
||||||
|
enableFuzzySearch: true
|
||||||
|
onValueChanged: value => {
|
||||||
|
const settings = SettingsData.matugenTemplateNeovimSettings;
|
||||||
|
settings.light.baseTheme = value;
|
||||||
|
SettingsData.set("matugenTemplateNeovimSettings", settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
text: I18n.tr("Dark mode harmony")
|
||||||
|
tags: ["matugen", "neovim", "terminal", "template"]
|
||||||
|
settingKey: "matugenTemplateNeovimSettings"
|
||||||
|
description: "How much should the base dark theme be tinted"
|
||||||
|
visible: neovimThemeToggle.visible && neovimThemeToggle.checked
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
value: (SettingsData.matugenTemplateNeovimSettings?.dark?.harmony ?? 0.5) * 100
|
||||||
|
defaultValue: 50
|
||||||
|
onSliderValueChanged: value => {
|
||||||
|
const settings = SettingsData.matugenTemplateNeovimSettings;
|
||||||
|
settings.dark.harmony = value / 100;
|
||||||
|
SettingsData.set("matugenTemplateNeovimSettings", settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
text: I18n.tr("Light mode harmony")
|
||||||
|
tags: ["matugen", "neovim", "terminal", "template"]
|
||||||
|
settingKey: "matugenTemplateNeovimSettings"
|
||||||
|
description: "How much should the base light theme be tinted"
|
||||||
|
visible: neovimThemeToggle.visible && neovimThemeToggle.checked
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
value: (SettingsData.matugenTemplateNeovimSettings?.light?.harmony ?? 0.5) * 100
|
||||||
|
defaultValue: 50
|
||||||
|
onSliderValueChanged: value => {
|
||||||
|
const settings = SettingsData.matugenTemplateNeovimSettings;
|
||||||
|
settings.light.harmony = value / 100;
|
||||||
|
SettingsData.set("matugenTemplateNeovimSettings", settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDivider {
|
||||||
|
visible: neovimThemeToggle.visible && neovimThemeToggle.checked
|
||||||
|
}
|
||||||
|
|
||||||
SettingsToggleRow {
|
SettingsToggleRow {
|
||||||
tab: "theme"
|
tab: "theme"
|
||||||
tags: ["matugen", "alacritty", "terminal", "template"]
|
tags: ["matugen", "alacritty", "terminal", "template"]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ pragma ComponentBehavior: Bound
|
|||||||
import QtCore
|
import QtCore
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
[templates.dmsneovim]
|
[templates.dmsneovim]
|
||||||
input_path = 'SHELL_DIR/matugen/templates/neovim.lua'
|
input_path = 'SHELL_DIR/matugen/templates/neovim.lua'
|
||||||
output_path = 'CONFIG_DIR/nvim/lua/plugins/dankcolors.lua'
|
output_path = 'CONFIG_DIR/nvim/colors/dms.lua'
|
||||||
|
|||||||
@@ -1,40 +1,83 @@
|
|||||||
return {
|
local present, base46 = pcall(require, "base46")
|
||||||
{
|
if not present or not base46._DMS_SUPPORT then
|
||||||
"RRethy/base16-nvim",
|
vim.notify(
|
||||||
priority = 1000,
|
"base46 plugin not found or incorrect, make sure to install AvengeMedia/base46",
|
||||||
config = function()
|
vim.log.levels.ERROR,
|
||||||
require('base16-colorscheme').setup({
|
{ title = "dms integration" }
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
base00 = '{{colors.background.dark.hex}}',
|
local config_home = vim.env.XDG_CONFIG_HOME
|
||||||
base01 = '{{colors.surface_container_low.dark.hex}}',
|
if config_home == nil or #config_home == 0 then
|
||||||
base02 = '{{colors.surface_container.dark.hex}}',
|
config_home = vim.fs.joinpath(vim.env.HOME, ".config")
|
||||||
base03 = '{{dank16.color8.dark.hex}}',
|
end
|
||||||
base0B = '{{dank16.color3.dark.hex}}',
|
local settings_file_path = vim.fs.joinpath(config_home, "DankMaterialShell", "settings.json")
|
||||||
base04 = '{{dank16.color7.default.hex}}',
|
local settings_file = io.open(settings_file_path, "r")
|
||||||
base05 = '{{dank16.color15.default.hex}}',
|
if settings_file == nil then
|
||||||
base06 = '{{dank16.color15.default.hex}}',
|
vim.notify(
|
||||||
base07 = '{{dank16.color15.default.hex}}',
|
"cannnot read dms settings file at '" .. settings_file_path .. "'",
|
||||||
base08 = '{{dank16.color9.default.hex}}',
|
vim.log.levels.ERROR,
|
||||||
base09 = '{{dank16.color9.default.hex}}',
|
{ title = "dms integration" }
|
||||||
base0A = '{{dank16.color12.default.hex}}',
|
)
|
||||||
base0C = '{{dank16.color14.default.hex}}',
|
return
|
||||||
base0D = '{{dank16.color12.default.hex}}',
|
end
|
||||||
base0E = '{{dank16.color13.default.hex}}',
|
local settings = vim.json.decode(settings_file:read("*a"))
|
||||||
base0F = '{{dank16.color13.default.hex}}',
|
settings_file:close()
|
||||||
})
|
|
||||||
|
|
||||||
local current_file_path = vim.fn.stdpath("config") .. "/lua/plugins/dankcolors.lua"
|
local function deepGet(t, k)
|
||||||
if not _G._matugen_theme_watcher then
|
for _, s in ipairs(k) do
|
||||||
local uv = vim.uv or vim.loop
|
if type(t) ~= "table" then
|
||||||
_G._matugen_theme_watcher = uv.new_fs_event()
|
return
|
||||||
_G._matugen_theme_watcher:start(current_file_path, {}, vim.schedule_wrap(function()
|
|
||||||
local new_spec = dofile(current_file_path)
|
|
||||||
if new_spec and new_spec[1] and new_spec[1].config then
|
|
||||||
new_spec[1].config()
|
|
||||||
print("Theme reload")
|
|
||||||
end
|
|
||||||
end))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
}
|
t = t[s]
|
||||||
}
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
local current_file_path = debug.getinfo(1, "S").source:sub(2)
|
||||||
|
local theme_base = deepGet(settings, { "matugenTemplateNeovimSettings", vim.o.background, "baseTheme" })
|
||||||
|
or ("github_" .. vim.o.background)
|
||||||
|
local harmony = deepGet(settings, { "matugenTemplateNeovimSettings", vim.o.background, "harmony" }) or 0.5
|
||||||
|
local theme_name = "dms"
|
||||||
|
|
||||||
|
if not _G._matugen_theme_watcher then
|
||||||
|
local uv = vim.uv or vim.loop
|
||||||
|
_G._matugen_theme_watcher = { uv.new_fs_event(), uv.new_fs_event(), reload_timer = uv.new_timer() }
|
||||||
|
|
||||||
|
local debounce_time = 100 -- ms
|
||||||
|
local function handler()
|
||||||
|
_G._matugen_theme_watcher.reload_timer:stop()
|
||||||
|
_G._matugen_theme_watcher.reload_timer:start(
|
||||||
|
debounce_time,
|
||||||
|
0,
|
||||||
|
vim.schedule_wrap(function()
|
||||||
|
base46.theme_tables[theme_name] = nil
|
||||||
|
if vim.g.colors_name == theme_name then
|
||||||
|
vim.cmd.colorscheme(theme_name)
|
||||||
|
vim.notify("Theme reload", vim.log.levels.INFO, { title = "dms integration" })
|
||||||
|
end
|
||||||
|
-- NOTE: contrary to what the documentation says, uv fs events usually do not manage to react to more than one edit.
|
||||||
|
-- I understand that this is not intended: some edit processes in a typical system (e.g. the one neovim uses with
|
||||||
|
-- multiple renames and changes) make things hard to follow for libuv. Therefore, a restart is the best option.
|
||||||
|
_G._matugen_theme_watcher[1]:stop()
|
||||||
|
_G._matugen_theme_watcher[2]:stop()
|
||||||
|
_G._matugen_theme_watcher[1]:start(current_file_path, {}, handler)
|
||||||
|
_G._matugen_theme_watcher[2]:start(settings_file_path, {}, handler)
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
_G._matugen_theme_watcher[1]:start(current_file_path, {}, handler)
|
||||||
|
_G._matugen_theme_watcher[2]:start(settings_file_path, {}, handler)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not base46.theme_tables[theme_name] or base46.theme_tables[theme_name].type ~= vim.o.background then
|
||||||
|
local builtin = vim.deepcopy(assert(base46.get_builtin_theme(theme_base)))
|
||||||
|
local harmonized = base46.theme_harmonize(builtin, "{{colors.source_color.default.hex}}", harmony)
|
||||||
|
harmonized = base46.theme_set_bg(harmonized, "{{colors.background.default.hex}}")
|
||||||
|
|
||||||
|
base46.theme_tables[theme_name] = harmonized
|
||||||
|
end
|
||||||
|
|
||||||
|
base46.load(theme_name)
|
||||||
|
vim.g.colors_name = theme_name
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2583,6 +2583,29 @@
|
|||||||
"description": "Mouse pointer appearance",
|
"description": "Mouse pointer appearance",
|
||||||
"conditionKey": "isNiri"
|
"conditionKey": "isNiri"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "matugenTemplateNeovimSettings",
|
||||||
|
"label": "Dark mode base",
|
||||||
|
"tabIndex": 10,
|
||||||
|
"category": "Theme & Colors",
|
||||||
|
"keywords": [
|
||||||
|
"appearance",
|
||||||
|
"base",
|
||||||
|
"colors",
|
||||||
|
"dark",
|
||||||
|
"dark mode",
|
||||||
|
"look",
|
||||||
|
"matugen",
|
||||||
|
"mode",
|
||||||
|
"neovim",
|
||||||
|
"night",
|
||||||
|
"scheme",
|
||||||
|
"style",
|
||||||
|
"template",
|
||||||
|
"terminal",
|
||||||
|
"theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "modalDarkenBackground",
|
"section": "modalDarkenBackground",
|
||||||
"label": "Darken Modal Background",
|
"label": "Darken Modal Background",
|
||||||
@@ -3948,20 +3971,17 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"appearance",
|
"appearance",
|
||||||
"colors",
|
"colors",
|
||||||
"lazy",
|
|
||||||
"look",
|
"look",
|
||||||
"manager",
|
|
||||||
"matugen",
|
"matugen",
|
||||||
"neovim",
|
"neovim",
|
||||||
"plugin",
|
"required",
|
||||||
"requires",
|
|
||||||
"scheme",
|
"scheme",
|
||||||
"style",
|
"style",
|
||||||
"template",
|
"template",
|
||||||
"terminal",
|
"terminal",
|
||||||
"theme"
|
"theme"
|
||||||
],
|
],
|
||||||
"description": "Requires lazy plugin manager"
|
"description": "Required plugin: "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"section": "matugenTemplateNiri",
|
"section": "matugenTemplateNiri",
|
||||||
@@ -4138,18 +4158,14 @@
|
|||||||
"authentication",
|
"authentication",
|
||||||
"biometric",
|
"biometric",
|
||||||
"enable",
|
"enable",
|
||||||
"enrolled",
|
|
||||||
"fingerprint",
|
"fingerprint",
|
||||||
"fprint",
|
"fprint",
|
||||||
"lock",
|
"lock",
|
||||||
"lockscreen",
|
|
||||||
"login",
|
"login",
|
||||||
"password",
|
"password",
|
||||||
"reader",
|
|
||||||
"screen",
|
"screen",
|
||||||
"security"
|
"security"
|
||||||
],
|
]
|
||||||
"description": "Use fingerprint reader for lock screen authentication (requires enrolled fingerprints)"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"section": "loginctlLockIntegration",
|
"section": "loginctlLockIntegration",
|
||||||
@@ -4182,20 +4198,17 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"authentication",
|
"authentication",
|
||||||
"enable",
|
"enable",
|
||||||
"enrolled",
|
|
||||||
"fido",
|
"fido",
|
||||||
"hardware",
|
"hardware",
|
||||||
"key",
|
"key",
|
||||||
"lock",
|
"lock",
|
||||||
"lockscreen",
|
|
||||||
"login",
|
"login",
|
||||||
"password",
|
"password",
|
||||||
"screen",
|
"screen",
|
||||||
"security",
|
"security",
|
||||||
"u2f",
|
"u2f",
|
||||||
"yubikey"
|
"yubikey"
|
||||||
],
|
]
|
||||||
"description": "Use a FIDO2/U2F security key (e.g. YubiKey) for lock screen authentication (requires enrolled keys)"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"section": "lockDisplay",
|
"section": "lockDisplay",
|
||||||
@@ -4286,6 +4299,27 @@
|
|||||||
],
|
],
|
||||||
"description": "Automatically lock the screen when DMS starts"
|
"description": "Automatically lock the screen when DMS starts"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "lockBeforeSuspend",
|
||||||
|
"label": "Lock before suspend",
|
||||||
|
"tabIndex": 11,
|
||||||
|
"category": "Lock Screen",
|
||||||
|
"keywords": [
|
||||||
|
"automatic",
|
||||||
|
"automatically",
|
||||||
|
"before",
|
||||||
|
"lock",
|
||||||
|
"login",
|
||||||
|
"password",
|
||||||
|
"prepares",
|
||||||
|
"screen",
|
||||||
|
"security",
|
||||||
|
"sleep",
|
||||||
|
"suspend",
|
||||||
|
"system"
|
||||||
|
],
|
||||||
|
"description": "Automatically lock the screen when the system prepares to suspend"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "lockScreenNotificationMode",
|
"section": "lockScreenNotificationMode",
|
||||||
"label": "Notification Display",
|
"label": "Notification Display",
|
||||||
@@ -6288,27 +6322,6 @@
|
|||||||
"icon": "schedule",
|
"icon": "schedule",
|
||||||
"description": "Gradually fade the screen before locking with a configurable grace period"
|
"description": "Gradually fade the screen before locking with a configurable grace period"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"section": "lockBeforeSuspend",
|
|
||||||
"label": "Lock before suspend",
|
|
||||||
"tabIndex": 21,
|
|
||||||
"category": "Power & Sleep",
|
|
||||||
"keywords": [
|
|
||||||
"automatically",
|
|
||||||
"before",
|
|
||||||
"energy",
|
|
||||||
"lock",
|
|
||||||
"power",
|
|
||||||
"prepares",
|
|
||||||
"screen",
|
|
||||||
"security",
|
|
||||||
"shutdown",
|
|
||||||
"sleep",
|
|
||||||
"suspend",
|
|
||||||
"system"
|
|
||||||
],
|
|
||||||
"description": "Automatically lock the screen when the system prepares to suspend"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"section": "fadeToLockGracePeriod",
|
"section": "fadeToLockGracePeriod",
|
||||||
"label": "Lock fade grace period",
|
"label": "Lock fade grace period",
|
||||||
|
|||||||
@@ -1518,6 +1518,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Available.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "BSSID",
|
"term": "BSSID",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -3653,6 +3660,20 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Dark mode base",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Dark mode harmony",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Darken Modal Background",
|
"term": "Darken Modal Background",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -4003,13 +4024,6 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"term": "Disabled.",
|
|
||||||
"translation": "",
|
|
||||||
"context": "",
|
|
||||||
"reference": "",
|
|
||||||
"comment": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"term": "Disabling WiFi...",
|
"term": "Disabling WiFi...",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -4647,6 +4661,76 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but fingerprint availability could not be confirmed.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but no fingerprint reader was detected.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but no prints are enrolled yet. Enroll fingerprints and run Sync.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but no prints are enrolled yet. Enroll fingerprints to use it.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but no registered security key was found yet. Register a key and run Sync.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but no registered security key was found yet. Register a key or update your U2F config.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled, but security-key availability could not be confirmed.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled. PAM already provides fingerprint auth.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled. PAM already provides security-key auth.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Enabled. PAM provides fingerprint auth, but no prints are enrolled yet.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Enabling WiFi...",
|
"term": "Enabling WiFi...",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -5529,6 +5613,27 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Fingerprint availability could not be confirmed.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Fingerprint reader detected, but no prints are enrolled yet. You can enable this now and enroll later.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Fingerprint reader detected, but no prints are enrolled yet. You can enable this now and run Sync later.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Finish",
|
"term": "Finish",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -5641,6 +5746,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Focused Monitor Only",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Focused Window",
|
"term": "Focused Window",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -5648,6 +5760,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Focused monitor only",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Fog",
|
"term": "Fog",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -6425,6 +6544,20 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Highlight Active Workspace App",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Highlight the currently focused app inside workspace indicators",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "History",
|
"term": "History",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -7321,6 +7454,20 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Light mode base",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Light mode harmony",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Line",
|
"term": "Line",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -8826,6 +8973,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "No fingerprint reader detected.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "No folders found",
|
"term": "No folders found",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -9121,14 +9275,28 @@
|
|||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"term": "Not available — install fprintd and enroll fingerprints.",
|
"term": "Not available — install fprintd and pam_fprintd, or configure greetd PAM.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
"context": "",
|
"context": "",
|
||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"term": "Not available — install pam_u2f and enroll keys.",
|
"term": "Not available — install fprintd and pam_fprintd.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Not available — install or configure pam_u2f, or configure greetd PAM.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Not available — install or configure pam_u2f.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
"context": "",
|
"context": "",
|
||||||
"reference": "",
|
"reference": "",
|
||||||
@@ -9148,13 +9316,6 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"term": "Not enrolled",
|
|
||||||
"translation": "",
|
|
||||||
"context": "fingerprint not detected status | security key not detected status",
|
|
||||||
"reference": "",
|
|
||||||
"comment": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"term": "Not paired",
|
"term": "Not paired",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -9394,7 +9555,7 @@
|
|||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"term": "Only off for DMS-managed PAM lines. If greetd includes system-auth/common-auth/password-auth with pam_fprintd, fingerprint still stays enabled.",
|
"term": "Only affects DMS-managed PAM. If greetd already includes pam_fprintd, fingerprint stays enabled.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
"context": "",
|
"context": "",
|
||||||
"reference": "",
|
"reference": "",
|
||||||
@@ -9715,6 +9876,41 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "PAM already provides fingerprint auth. Enable this to show it at login.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "PAM already provides security-key auth. Enable this to show it at login.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "PAM provides fingerprint auth, but availability could not be confirmed.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "PAM provides fingerprint auth, but no prints are enrolled yet.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "PAM provides fingerprint auth, but no reader was detected.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "PIN",
|
"term": "PIN",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -10940,6 +11136,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Required plugin: ",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Requires %1",
|
"term": "Requires %1",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -10968,13 +11171,6 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"term": "Requires lazy plugin manager",
|
|
||||||
"translation": "",
|
|
||||||
"context": "neovim template description",
|
|
||||||
"reference": "",
|
|
||||||
"comment": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"term": "Requires night mode support",
|
"term": "Requires night mode support",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -11052,6 +11248,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Restore Special Workspace Windows",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Resume",
|
"term": "Resume",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -11640,6 +11843,20 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Security-key availability could not be confirmed.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Security-key support was detected, but no registered key was found yet. You can enable this now and register one later.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Select",
|
"term": "Select",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -12585,6 +12802,20 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Show notification popups only on the currently focused monitor",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"term": "Show notifications only on the currently focused monitor",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Show on Last Display",
|
"term": "Show on Last Display",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -14307,13 +14538,6 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"term": "Use a FIDO2/U2F security key (e.g. YubiKey) for lock screen authentication (requires enrolled keys)",
|
|
||||||
"translation": "",
|
|
||||||
"context": "lock screen U2F security key setting",
|
|
||||||
"reference": "",
|
|
||||||
"comment": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"term": "Use a custom image for the login screen, or leave empty to use your desktop wallpaper.",
|
"term": "Use a custom image for the login screen, or leave empty to use your desktop wallpaper.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -14328,6 +14552,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "Use a security key for lock screen authentication.",
|
||||||
|
"translation": "",
|
||||||
|
"context": "lock screen U2F security key setting",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "Use an external wallpaper manager like swww, hyprpaper, or swaybg.",
|
"term": "Use an external wallpaper manager like swww, hyprpaper, or swaybg.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
@@ -14392,7 +14623,7 @@
|
|||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"term": "Use fingerprint reader for lock screen authentication (requires enrolled fingerprints)",
|
"term": "Use fingerprint authentication for the lock screen.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
"context": "",
|
"context": "",
|
||||||
"reference": "",
|
"reference": "",
|
||||||
@@ -14832,6 +15063,13 @@
|
|||||||
"reference": "",
|
"reference": "",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"term": "When clicking a dock window in a Hyprland special workspace, bring that special workspace back before focusing the window",
|
||||||
|
"translation": "",
|
||||||
|
"context": "",
|
||||||
|
"reference": "",
|
||||||
|
"comment": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"term": "When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.",
|
"term": "When enabled, apps are sorted alphabetically. When disabled, apps are sorted by usage frequency.",
|
||||||
"translation": "",
|
"translation": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user