mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-31 08:52:49 -05:00
Compare commits
15 Commits
6f3c4c89ab
...
bc27253cbf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc27253cbf | ||
|
|
0672b711f3 | ||
|
|
ed9ee6e347 | ||
|
|
7ad23ad4a2 | ||
|
|
8a83f03cc1 | ||
|
|
0be9ac4097 | ||
|
|
ba5be6b516 | ||
|
|
c4aea6d326 | ||
|
|
858c6407a9 | ||
|
|
c4313395b5 | ||
|
|
a32aec3d59 | ||
|
|
696bcfe8fa | ||
|
|
2f3a253c6a | ||
|
|
e41fbe0188 | ||
|
|
ef9d28597b |
@@ -127,7 +127,7 @@ dms plugins search # Browse plugin registry
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- **Website:** [danklinux.com](https://danklinux.com)
|
- **Website:** [danklinux.com](https://danklinux.com)
|
||||||
- **Docs:** [danklinux.com/docs](https://danklinux.com/docs)
|
- **Docs:** [danklinux.com/docs](https://danklinux.com/docs/)
|
||||||
- **Theming:** [Application themes](https://danklinux.com/docs/dankmaterialshell/application-themes) | [Custom themes](https://danklinux.com/docs/dankmaterialshell/custom-themes)
|
- **Theming:** [Application themes](https://danklinux.com/docs/dankmaterialshell/application-themes) | [Custom themes](https://danklinux.com/docs/dankmaterialshell/custom-themes)
|
||||||
- **Plugins:** [Development guide](https://danklinux.com/docs/dankmaterialshell/plugins-overview)
|
- **Plugins:** [Development guide](https://danklinux.com/docs/dankmaterialshell/plugins-overview)
|
||||||
- **Support:** [Ko-fi](https://ko-fi.com/avengemediallc)
|
- **Support:** [Ko-fi](https://ko-fi.com/avengemediallc)
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ func (d *DebianDistribution) InstallPrerequisites(ctx context.Context, sudoPassw
|
|||||||
|
|
||||||
checkCmd := exec.CommandContext(ctx, "dpkg", "-l", "build-essential")
|
checkCmd := exec.CommandContext(ctx, "dpkg", "-l", "build-essential")
|
||||||
if err := checkCmd.Run(); err != nil {
|
if err := checkCmd.Run(); err != nil {
|
||||||
cmd := ExecSudoCommand(ctx, sudoPassword, "apt-get install -y build-essential")
|
cmd := ExecSudoCommand(ctx, sudoPassword, "DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential")
|
||||||
if err := d.runWithProgress(cmd, progressChan, PhasePrerequisites, 0.08, 0.09); err != nil {
|
if err := d.runWithProgress(cmd, progressChan, PhasePrerequisites, 0.08, 0.09); err != nil {
|
||||||
return fmt.Errorf("failed to install build-essential: %w", err)
|
return fmt.Errorf("failed to install build-essential: %w", err)
|
||||||
}
|
}
|
||||||
@@ -225,7 +225,7 @@ func (d *DebianDistribution) InstallPrerequisites(ctx context.Context, sudoPassw
|
|||||||
}
|
}
|
||||||
|
|
||||||
devToolsCmd := ExecSudoCommand(ctx, sudoPassword,
|
devToolsCmd := ExecSudoCommand(ctx, sudoPassword,
|
||||||
"apt-get install -y curl wget git cmake ninja-build pkg-config libxcb-cursor-dev libglib2.0-dev libpolkit-agent-1-dev libjpeg-dev libpugixml-dev")
|
"DEBIAN_FRONTEND=noninteractive apt-get install -y curl wget git cmake ninja-build pkg-config libxcb-cursor-dev libglib2.0-dev libpolkit-agent-1-dev libjpeg-dev libpugixml-dev")
|
||||||
if err := d.runWithProgress(devToolsCmd, progressChan, PhasePrerequisites, 0.10, 0.12); err != nil {
|
if err := d.runWithProgress(devToolsCmd, progressChan, PhasePrerequisites, 0.10, 0.12); err != nil {
|
||||||
return fmt.Errorf("failed to install development tools: %w", err)
|
return fmt.Errorf("failed to install development tools: %w", err)
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ func (d *DebianDistribution) enableOBSRepos(ctx context.Context, obsPkgs []Packa
|
|||||||
CommandInfo: fmt.Sprintf("curl & gpg to add key for %s", pkg.RepoURL),
|
CommandInfo: fmt.Sprintf("curl & gpg to add key for %s", pkg.RepoURL),
|
||||||
}
|
}
|
||||||
|
|
||||||
keyCmd := fmt.Sprintf("curl -fsSL %s/Release.key | gpg --dearmor -o %s", baseURL, keyringPath)
|
keyCmd := fmt.Sprintf("bash -c 'rm -f %s && curl -fsSL %s/Release.key | gpg --batch --dearmor -o %s'", keyringPath, baseURL, keyringPath)
|
||||||
cmd := ExecSudoCommand(ctx, sudoPassword, keyCmd)
|
cmd := ExecSudoCommand(ctx, sudoPassword, keyCmd)
|
||||||
if err := d.runWithProgress(cmd, progressChan, PhaseSystemPackages, 0.18, 0.20); err != nil {
|
if err := d.runWithProgress(cmd, progressChan, PhaseSystemPackages, 0.18, 0.20); err != nil {
|
||||||
return fmt.Errorf("failed to add OBS GPG key for %s: %w", pkg.RepoURL, err)
|
return fmt.Errorf("failed to add OBS GPG key for %s: %w", pkg.RepoURL, err)
|
||||||
@@ -471,7 +471,7 @@ func (d *DebianDistribution) enableOBSRepos(ctx context.Context, obsPkgs []Packa
|
|||||||
}
|
}
|
||||||
|
|
||||||
addRepoCmd := ExecSudoCommand(ctx, sudoPassword,
|
addRepoCmd := ExecSudoCommand(ctx, sudoPassword,
|
||||||
fmt.Sprintf("echo '%s' | tee %s", repoLine, listFile))
|
fmt.Sprintf("bash -c \"echo '%s' | tee %s\"", repoLine, listFile))
|
||||||
if err := d.runWithProgress(addRepoCmd, progressChan, PhaseSystemPackages, 0.20, 0.22); err != nil {
|
if err := d.runWithProgress(addRepoCmd, progressChan, PhaseSystemPackages, 0.20, 0.22); err != nil {
|
||||||
return fmt.Errorf("failed to add OBS repo %s: %w", pkg.RepoURL, err)
|
return fmt.Errorf("failed to add OBS repo %s: %w", pkg.RepoURL, err)
|
||||||
}
|
}
|
||||||
@@ -506,7 +506,7 @@ func (d *DebianDistribution) installAPTPackages(ctx context.Context, packages []
|
|||||||
|
|
||||||
d.log(fmt.Sprintf("Installing APT packages: %s", strings.Join(packages, ", ")))
|
d.log(fmt.Sprintf("Installing APT packages: %s", strings.Join(packages, ", ")))
|
||||||
|
|
||||||
args := []string{"apt-get", "install", "-y"}
|
args := []string{"DEBIAN_FRONTEND=noninteractive", "apt-get", "install", "-y"}
|
||||||
args = append(args, packages...)
|
args = append(args, packages...)
|
||||||
|
|
||||||
progressChan <- InstallProgressMsg{
|
progressChan <- InstallProgressMsg{
|
||||||
@@ -616,7 +616,7 @@ func (d *DebianDistribution) installRust(ctx context.Context, sudoPassword strin
|
|||||||
CommandInfo: "sudo apt-get install rustup",
|
CommandInfo: "sudo apt-get install rustup",
|
||||||
}
|
}
|
||||||
|
|
||||||
rustupInstallCmd := ExecSudoCommand(ctx, sudoPassword, "apt-get install -y rustup")
|
rustupInstallCmd := ExecSudoCommand(ctx, sudoPassword, "DEBIAN_FRONTEND=noninteractive apt-get install -y rustup")
|
||||||
if err := d.runWithProgress(rustupInstallCmd, progressChan, PhaseSystemPackages, 0.82, 0.83); err != nil {
|
if err := d.runWithProgress(rustupInstallCmd, progressChan, PhaseSystemPackages, 0.82, 0.83); err != nil {
|
||||||
return fmt.Errorf("failed to install rustup: %w", err)
|
return fmt.Errorf("failed to install rustup: %w", err)
|
||||||
}
|
}
|
||||||
@@ -655,7 +655,7 @@ func (d *DebianDistribution) installGo(ctx context.Context, sudoPassword string,
|
|||||||
CommandInfo: "sudo apt-get install golang-go",
|
CommandInfo: "sudo apt-get install golang-go",
|
||||||
}
|
}
|
||||||
|
|
||||||
installCmd := ExecSudoCommand(ctx, sudoPassword, "apt-get install -y golang-go")
|
installCmd := ExecSudoCommand(ctx, sudoPassword, "DEBIAN_FRONTEND=noninteractive apt-get install -y golang-go")
|
||||||
return d.runWithProgress(installCmd, progressChan, PhaseSystemPackages, 0.87, 0.90)
|
return d.runWithProgress(installCmd, progressChan, PhaseSystemPackages, 0.87, 0.90)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ func (o *OpenSUSEDistribution) enableOBSRepos(ctx context.Context, obsPkgs []Pac
|
|||||||
cmd := ExecSudoCommand(ctx, sudoPassword,
|
cmd := ExecSudoCommand(ctx, sudoPassword,
|
||||||
fmt.Sprintf("zypper addrepo -f %s", repoURL))
|
fmt.Sprintf("zypper addrepo -f %s", repoURL))
|
||||||
if err := o.runWithProgress(cmd, progressChan, PhaseSystemPackages, 0.20, 0.22); err != nil {
|
if err := o.runWithProgress(cmd, progressChan, PhaseSystemPackages, 0.20, 0.22); err != nil {
|
||||||
return fmt.Errorf("failed to enable OBS repo %s: %w", pkg.RepoURL, err)
|
o.log(fmt.Sprintf("OBS repo %s add failed (may already exist): %v", pkg.RepoURL, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledRepos[pkg.RepoURL] = true
|
enabledRepos[pkg.RepoURL] = true
|
||||||
|
|||||||
@@ -562,53 +562,62 @@ func (m *Manager) transitionWorker() {
|
|||||||
case <-m.stopChan:
|
case <-m.stopChan:
|
||||||
return
|
return
|
||||||
case targetTemp := <-m.transitionChan:
|
case targetTemp := <-m.transitionChan:
|
||||||
|
m.runTransition(targetTemp, steps, stepDur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) runTransition(targetTemp int, steps int, stepDur time.Duration) {
|
||||||
|
for {
|
||||||
m.transitionMutex.Lock()
|
m.transitionMutex.Lock()
|
||||||
currentTemp := m.currentTemp
|
currentTemp := m.currentTemp
|
||||||
m.targetTemp = targetTemp
|
m.targetTemp = targetTemp
|
||||||
m.transitionMutex.Unlock()
|
m.transitionMutex.Unlock()
|
||||||
|
|
||||||
if currentTemp == targetTemp {
|
if currentTemp == targetTemp {
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Starting smooth transition: %dK -> %dK over %v", currentTemp, targetTemp, dur)
|
log.Debugf("Starting smooth transition: %dK -> %dK over %v", currentTemp, targetTemp, stepDur*time.Duration(steps))
|
||||||
|
|
||||||
stepLoop:
|
redirected := false
|
||||||
for i := 0; i <= steps; i++ {
|
for i := 0; i <= steps; i++ {
|
||||||
select {
|
select {
|
||||||
case newTarget := <-m.transitionChan:
|
case newTarget := <-m.transitionChan:
|
||||||
m.transitionMutex.Lock()
|
m.transitionMutex.Lock()
|
||||||
m.targetTemp = newTarget
|
m.targetTemp = newTarget
|
||||||
m.transitionMutex.Unlock()
|
m.transitionMutex.Unlock()
|
||||||
log.Debugf("Transition %dK -> %dK aborted (newer transition started)", currentTemp, targetTemp)
|
if newTarget != targetTemp {
|
||||||
break stepLoop
|
log.Debugf("Transition %dK -> %dK redirected to %dK", currentTemp, targetTemp, newTarget)
|
||||||
|
targetTemp = newTarget
|
||||||
|
redirected = true
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
m.transitionMutex.RLock()
|
if redirected {
|
||||||
if m.targetTemp != targetTemp {
|
|
||||||
m.transitionMutex.RUnlock()
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.transitionMutex.RLock()
|
||||||
|
currentTarget := m.targetTemp
|
||||||
m.transitionMutex.RUnlock()
|
m.transitionMutex.RUnlock()
|
||||||
|
|
||||||
|
if currentTarget != targetTemp {
|
||||||
|
targetTemp = currentTarget
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
progress := float64(i) / float64(steps)
|
progress := float64(i) / float64(steps)
|
||||||
temp := currentTemp + int(float64(targetTemp-currentTemp)*progress)
|
temp := currentTemp + int(float64(targetTemp-currentTemp)*progress)
|
||||||
|
|
||||||
m.post(func() { m.applyNowOnActor(temp) })
|
m.post(func() { m.applyNowOnActor(temp) })
|
||||||
|
|
||||||
if i < steps {
|
if i == steps {
|
||||||
time.Sleep(stepDur)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.transitionMutex.RLock()
|
|
||||||
finalTarget := m.targetTemp
|
|
||||||
m.transitionMutex.RUnlock()
|
|
||||||
|
|
||||||
if finalTarget == targetTemp {
|
|
||||||
log.Debugf("Transition complete: now at %dK", targetTemp)
|
log.Debugf("Transition complete: now at %dK", targetTemp)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time.Sleep(stepDur)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1206,11 +1215,18 @@ func (m *Manager) SetGamma(gamma float64) error {
|
|||||||
|
|
||||||
func (m *Manager) SetEnabled(enabled bool) {
|
func (m *Manager) SetEnabled(enabled bool) {
|
||||||
m.configMutex.Lock()
|
m.configMutex.Lock()
|
||||||
|
wasEnabled := m.config.Enabled
|
||||||
m.config.Enabled = enabled
|
m.config.Enabled = enabled
|
||||||
|
highTemp := m.config.HighTemp
|
||||||
m.configMutex.Unlock()
|
m.configMutex.Unlock()
|
||||||
|
|
||||||
if enabled {
|
if enabled {
|
||||||
if !m.controlsInitialized {
|
if !m.controlsInitialized {
|
||||||
|
m.transitionMutex.Lock()
|
||||||
|
m.currentTemp = highTemp
|
||||||
|
m.targetTemp = highTemp
|
||||||
|
m.transitionMutex.Unlock()
|
||||||
|
|
||||||
m.post(func() {
|
m.post(func() {
|
||||||
log.Info("Creating gamma controls")
|
log.Info("Creating gamma controls")
|
||||||
gammaMgr := m.gammaControl.(*wlr_gamma_control.ZwlrGammaControlManagerV1)
|
gammaMgr := m.gammaControl.(*wlr_gamma_control.ZwlrGammaControlManagerV1)
|
||||||
@@ -1221,9 +1237,10 @@ func (m *Manager) SetEnabled(enabled bool) {
|
|||||||
log.Errorf("Failed to create gamma controls: %v", err)
|
log.Errorf("Failed to create gamma controls: %v", err)
|
||||||
} else {
|
} else {
|
||||||
m.controlsInitialized = true
|
m.controlsInitialized = true
|
||||||
|
m.triggerUpdate()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else if !wasEnabled {
|
||||||
m.triggerUpdate()
|
m.triggerUpdate()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -10,13 +10,14 @@
|
|||||||
|
|
||||||
user = config.services.greetd.settings.default_session.user;
|
user = config.services.greetd.settings.default_session.user;
|
||||||
|
|
||||||
|
cacheDir = "/var/lib/dms-greeter";
|
||||||
greeterScript = pkgs.writeShellScriptBin "dms-greeter" ''
|
greeterScript = pkgs.writeShellScriptBin "dms-greeter" ''
|
||||||
export PATH=$PATH:${lib.makeBinPath [cfg.quickshell.package config.programs.${cfg.compositor.name}.package]}
|
export PATH=$PATH:${lib.makeBinPath [cfg.quickshell.package config.programs.${cfg.compositor.name}.package]}
|
||||||
${lib.escapeShellArgs ([
|
${lib.escapeShellArgs ([
|
||||||
"sh"
|
"sh"
|
||||||
"${../../quickshell/Modules/Greetd/assets/dms-greeter}"
|
"${../../quickshell/Modules/Greetd/assets/dms-greeter}"
|
||||||
"--cache-dir"
|
"--cache-dir"
|
||||||
"/var/lib/dmsgreeter"
|
cacheDir
|
||||||
"--command"
|
"--command"
|
||||||
cfg.compositor.name
|
cfg.compositor.name
|
||||||
"-p"
|
"-p"
|
||||||
@@ -27,6 +28,8 @@
|
|||||||
"${pkgs.writeText "dmsgreeter-compositor-config" cfg.compositor.customConfig}"
|
"${pkgs.writeText "dmsgreeter-compositor-config" cfg.compositor.customConfig}"
|
||||||
])} ${lib.optionalString cfg.logs.save "> ${cfg.logs.path} 2>&1"}
|
])} ${lib.optionalString cfg.logs.save "> ${cfg.logs.path} 2>&1"}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
jq = lib.getExe pkgs.jq;
|
||||||
in {
|
in {
|
||||||
imports = let
|
imports = let
|
||||||
msg = "The option 'programs.dankMaterialShell.greeter.compositor.extraConfig' is deprecated. Please use 'programs.dankMaterialShell.greeter.compositor.customConfig' instead.";
|
msg = "The option 'programs.dankMaterialShell.greeter.compositor.extraConfig' is deprecated. Please use 'programs.dankMaterialShell.greeter.compositor.customConfig' instead.";
|
||||||
@@ -93,17 +96,17 @@ in {
|
|||||||
material-symbols
|
material-symbols
|
||||||
];
|
];
|
||||||
systemd.tmpfiles.settings."10-dmsgreeter" = {
|
systemd.tmpfiles.settings."10-dmsgreeter" = {
|
||||||
"/var/lib/dmsgreeter".d = {
|
${cacheDir}.d = {
|
||||||
user = user;
|
user = user;
|
||||||
group =
|
group =
|
||||||
if config.users.users.${user}.group != ""
|
if config.users.users.${user}.group != ""
|
||||||
then config.users.users.${user}.group
|
then config.users.users.${user}.group
|
||||||
else "greeter";
|
else "greeter";
|
||||||
mode = "0755";
|
mode = "0750";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.services.greetd.preStart = ''
|
systemd.services.greetd.preStart = ''
|
||||||
cd /var/lib/dmsgreeter
|
cd ${cacheDir}
|
||||||
${lib.concatStringsSep "\n" (lib.map (f: ''
|
${lib.concatStringsSep "\n" (lib.map (f: ''
|
||||||
if [ -f "${f}" ]; then
|
if [ -f "${f}" ]; then
|
||||||
cp "${f}" .
|
cp "${f}" .
|
||||||
@@ -112,9 +115,16 @@ in {
|
|||||||
cfg.configFiles)}
|
cfg.configFiles)}
|
||||||
|
|
||||||
if [ -f session.json ]; then
|
if [ -f session.json ]; then
|
||||||
if cp "$(${lib.getExe pkgs.jq} -r '.wallpaperPath' session.json)" wallpaper.jpg; then
|
if cp "$(${jq} -r '.wallpaperPath' session.json)" wallpaper.jpg; then
|
||||||
mv session.json session.orig.json
|
mv session.json session.orig.json
|
||||||
${lib.getExe pkgs.jq} '.wallpaperPath = "/var/lib/dmsgreeter/wallpaper.jpg"' session.orig.json > session.json
|
${jq} '.wallpaperPath = "${cacheDir}/wallpaper.jpg"' session.orig.json > session.json
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f settings.json ]; then
|
||||||
|
if cp "$(${jq} -r '.customThemeFile' settings.json)" custom-theme.json; then
|
||||||
|
mv settings.json settings.orig.json
|
||||||
|
${jq} '.customThemeFile = "${cacheDir}/custom-theme.json"' settings.orig.json > settings.json
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
1
quickshell/CODENAME
Normal file
1
quickshell/CODENAME
Normal file
@@ -0,0 +1 @@
|
|||||||
|
The Dark Knight
|
||||||
@@ -53,7 +53,7 @@ Singleton {
|
|||||||
if (appId === "home assistant desktop")
|
if (appId === "home assistant desktop")
|
||||||
return "homeassistant-desktop";
|
return "homeassistant-desktop";
|
||||||
if (appId.includes("com.transmissionbt.transmission"))
|
if (appId.includes("com.transmissionbt.transmission"))
|
||||||
return "transmission-gtk";
|
return "transmission";
|
||||||
return appId;
|
return appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,21 +128,13 @@ Singleton {
|
|||||||
setDesiredTheme("image", rawWallpaperPath, isLight, iconTheme, selectedMatugenType);
|
setDesiredTheme("image", rawWallpaperPath, isLight, iconTheme, selectedMatugenType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (currentTheme !== "custom") {
|
||||||
let primaryColor;
|
const darkTheme = StockThemes.getThemeByName(currentTheme, false);
|
||||||
let matugenType;
|
const lightTheme = StockThemes.getThemeByName(currentTheme, true);
|
||||||
if (currentTheme === "custom") {
|
if (darkTheme && darkTheme.primary) {
|
||||||
if (customThemeData && customThemeData.primary) {
|
const stockColors = buildMatugenColorsFromTheme(darkTheme, lightTheme);
|
||||||
primaryColor = customThemeData.primary;
|
const themeData = isLight ? lightTheme : darkTheme;
|
||||||
matugenType = customThemeData.matugen_type;
|
setDesiredTheme("hex", themeData.primary, isLight, iconTheme, themeData.matugen_type, stockColors);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
primaryColor = currentThemeData.primary;
|
|
||||||
matugenType = currentThemeData.matugen_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primaryColor) {
|
|
||||||
setDesiredTheme("hex", primaryColor, isLight, iconTheme, matugenType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|||||||
@@ -332,18 +332,16 @@ Item {
|
|||||||
if (!provider)
|
if (!provider)
|
||||||
return "ERROR: No provider specified";
|
return "ERROR: No provider specified";
|
||||||
|
|
||||||
KeybindsService.currentProvider = provider;
|
KeybindsService.loadCheatsheet(provider);
|
||||||
KeybindsService.loadBinds();
|
|
||||||
root.hyprKeybindsModalLoader.active = true;
|
root.hyprKeybindsModalLoader.active = true;
|
||||||
|
|
||||||
if (!root.hyprKeybindsModalLoader.item)
|
if (!root.hyprKeybindsModalLoader.item)
|
||||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||||
|
|
||||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
if (root.hyprKeybindsModalLoader.item.shouldBeVisible)
|
||||||
root.hyprKeybindsModalLoader.item.close();
|
root.hyprKeybindsModalLoader.item.close();
|
||||||
} else {
|
else
|
||||||
root.hyprKeybindsModalLoader.item.open();
|
root.hyprKeybindsModalLoader.item.open();
|
||||||
}
|
|
||||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider}`;
|
return `KEYBINDS_TOGGLE_SUCCESS: ${provider}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,18 +349,16 @@ Item {
|
|||||||
if (!provider)
|
if (!provider)
|
||||||
return "ERROR: No provider specified";
|
return "ERROR: No provider specified";
|
||||||
|
|
||||||
KeybindsService.currentProvider = provider;
|
KeybindsService.loadCheatsheet(provider);
|
||||||
KeybindsService.loadBinds();
|
|
||||||
root.hyprKeybindsModalLoader.active = true;
|
root.hyprKeybindsModalLoader.active = true;
|
||||||
|
|
||||||
if (!root.hyprKeybindsModalLoader.item)
|
if (!root.hyprKeybindsModalLoader.item)
|
||||||
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
return `KEYBINDS_TOGGLE_FAILED: ${provider}`;
|
||||||
|
|
||||||
if (root.hyprKeybindsModalLoader.item.shouldBeVisible) {
|
if (root.hyprKeybindsModalLoader.item.shouldBeVisible)
|
||||||
root.hyprKeybindsModalLoader.item.close();
|
root.hyprKeybindsModalLoader.item.close();
|
||||||
} else {
|
else
|
||||||
root.hyprKeybindsModalLoader.item.open();
|
root.hyprKeybindsModalLoader.item.open();
|
||||||
}
|
|
||||||
return `KEYBINDS_TOGGLE_SUCCESS: ${provider} (${path})`;
|
return `KEYBINDS_TOGGLE_SUCCESS: ${provider} (${path})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,8 +366,7 @@ Item {
|
|||||||
if (!provider)
|
if (!provider)
|
||||||
return "ERROR: No provider specified";
|
return "ERROR: No provider specified";
|
||||||
|
|
||||||
KeybindsService.currentProvider = provider;
|
KeybindsService.loadCheatsheet(provider);
|
||||||
KeybindsService.loadBinds();
|
|
||||||
root.hyprKeybindsModalLoader.active = true;
|
root.hyprKeybindsModalLoader.active = true;
|
||||||
|
|
||||||
if (!root.hyprKeybindsModalLoader.item)
|
if (!root.hyprKeybindsModalLoader.item)
|
||||||
@@ -385,8 +380,7 @@ Item {
|
|||||||
if (!provider)
|
if (!provider)
|
||||||
return "ERROR: No provider specified";
|
return "ERROR: No provider specified";
|
||||||
|
|
||||||
KeybindsService.currentProvider = provider;
|
KeybindsService.loadCheatsheet(provider);
|
||||||
KeybindsService.loadBinds();
|
|
||||||
root.hyprKeybindsModalLoader.active = true;
|
root.hyprKeybindsModalLoader.active = true;
|
||||||
|
|
||||||
if (!root.hyprKeybindsModalLoader.item)
|
if (!root.hyprKeybindsModalLoader.item)
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ DankModal {
|
|||||||
modalWidth: _maxW
|
modalWidth: _maxW
|
||||||
modalHeight: _maxH
|
modalHeight: _maxH
|
||||||
onBackgroundClicked: close()
|
onBackgroundClicked: close()
|
||||||
onOpened: () => Qt.callLater(() => modalFocusScope.forceActiveFocus())
|
onOpened: {
|
||||||
|
Qt.callLater(() => modalFocusScope.forceActiveFocus());
|
||||||
|
if (!Object.keys(KeybindsService.cheatsheet).length && KeybindsService.cheatsheetAvailable)
|
||||||
|
KeybindsService.loadCheatsheet();
|
||||||
|
}
|
||||||
|
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
windows: [root.contentWindow]
|
windows: [root.contentWindow]
|
||||||
@@ -66,7 +70,7 @@ DankModal {
|
|||||||
spacing: Theme.spacingL
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: KeybindsService.keybinds.title || "Keybinds"
|
text: KeybindsService.cheatsheet.title || "Keybinds"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
@@ -82,7 +86,7 @@ DankModal {
|
|||||||
|
|
||||||
Component.onCompleted: root.activeFlickable = mainFlickable
|
Component.onCompleted: root.activeFlickable = mainFlickable
|
||||||
|
|
||||||
property var rawBinds: KeybindsService.keybinds.binds || {}
|
property var rawBinds: KeybindsService.cheatsheet.binds || {}
|
||||||
property var categories: {
|
property var categories: {
|
||||||
const processed = {};
|
const processed = {};
|
||||||
for (const cat in rawBinds) {
|
for (const cat in rawBinds) {
|
||||||
@@ -114,12 +118,36 @@ DankModal {
|
|||||||
}
|
}
|
||||||
property var categoryKeys: Object.keys(categories)
|
property var categoryKeys: Object.keys(categories)
|
||||||
|
|
||||||
|
function estimateCategoryHeight(catName) {
|
||||||
|
const catData = categories[catName];
|
||||||
|
if (!catData)
|
||||||
|
return 0;
|
||||||
|
let bindCount = 0;
|
||||||
|
for (const key of catData.subcatKeys) {
|
||||||
|
bindCount += catData.subcats[key]?.length || 0;
|
||||||
|
if (key !== "_root")
|
||||||
|
bindCount += 1;
|
||||||
|
}
|
||||||
|
return 40 + bindCount * 28;
|
||||||
|
}
|
||||||
|
|
||||||
function distributeCategories(cols) {
|
function distributeCategories(cols) {
|
||||||
const columns = [];
|
const columns = [];
|
||||||
for (let i = 0; i < cols; i++)
|
const heights = [];
|
||||||
|
for (let i = 0; i < cols; i++) {
|
||||||
columns.push([]);
|
columns.push([]);
|
||||||
for (let i = 0; i < categoryKeys.length; i++)
|
heights.push(0);
|
||||||
columns[i % cols].push(categoryKeys[i]);
|
}
|
||||||
|
const sorted = [...categoryKeys].sort((a, b) => estimateCategoryHeight(b) - estimateCategoryHeight(a));
|
||||||
|
for (const cat of sorted) {
|
||||||
|
let minIdx = 0;
|
||||||
|
for (let i = 1; i < cols; i++) {
|
||||||
|
if (heights[i] < heights[minIdx])
|
||||||
|
minIdx = i;
|
||||||
|
}
|
||||||
|
columns[minIdx].push(cat);
|
||||||
|
heights[minIdx] += estimateCategoryHeight(cat);
|
||||||
|
}
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +165,7 @@ DankModal {
|
|||||||
Column {
|
Column {
|
||||||
id: masonryColumn
|
id: masonryColumn
|
||||||
width: (rowLayout.width - rowLayout.spacing * (rowLayout.numColumns - 1)) / rowLayout.numColumns
|
width: (rowLayout.width - rowLayout.spacing * (rowLayout.numColumns - 1)) / rowLayout.numColumns
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingXL
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: rowLayout.columnCategories[index] || []
|
model: rowLayout.columnCategories[index] || []
|
||||||
@@ -199,37 +227,37 @@ DankModal {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: parent.parent.subcatBinds
|
model: parent.parent.subcatBinds
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingS
|
height: 24
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
width: Math.min(140, parent.width * 0.42)
|
id: keyBadge
|
||||||
|
width: Math.min(keyText.implicitWidth + 12, 160)
|
||||||
height: 22
|
height: 22
|
||||||
radius: 4
|
radius: 4
|
||||||
opacity: 0.9
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
id: keyText
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.margins: 2
|
|
||||||
width: parent.width - 4
|
|
||||||
color: Theme.secondary
|
color: Theme.secondary
|
||||||
text: modelData.key || ""
|
text: modelData.key || ""
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
isMonospace: true
|
isMonospace: true
|
||||||
elide: Text.ElideRight
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
width: parent.width - 150
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 170
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: modelData.desc || modelData.action || ""
|
text: modelData.desc || modelData.action || ""
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
opacity: 0.9
|
opacity: 0.9
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ DankPopout {
|
|||||||
active: true
|
active: true
|
||||||
tabBarItem: tabBar
|
tabBarItem: tabBar
|
||||||
keyForwardTarget: mainContainer
|
keyForwardTarget: mainContainer
|
||||||
targetScreen: root.triggerScreen
|
targetScreen: root.screen
|
||||||
parentPopout: root
|
parentPopout: root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import QtQuick.Effects
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Modules.Settings.Widgets
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: aboutTab
|
id: aboutTab
|
||||||
@@ -200,6 +199,16 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
visible: SystemUpdateService.shellCodename.length > 0
|
||||||
|
text: `"${SystemUpdateService.shellCodename}"`
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
font.italic: true
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: resourceButtonsRow
|
id: resourceButtonsRow
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ Variants {
|
|||||||
readonly property bool transitioning: transitionAnimation.running
|
readonly property bool transitioning: transitionAnimation.running
|
||||||
property bool effectActive: false
|
property bool effectActive: false
|
||||||
property bool useNextForEffect: false
|
property bool useNextForEffect: false
|
||||||
|
property string pendingWallpaper: ""
|
||||||
|
|
||||||
function getFillMode(modeName) {
|
function getFillMode(modeName) {
|
||||||
switch (modeName) {
|
switch (modeName) {
|
||||||
@@ -162,12 +163,10 @@ Variants {
|
|||||||
return;
|
return;
|
||||||
if (!newPath || newPath.startsWith("#"))
|
if (!newPath || newPath.startsWith("#"))
|
||||||
return;
|
return;
|
||||||
if (root.transitioning) {
|
|
||||||
transitionAnimation.stop();
|
if (root.transitioning || root.effectActive) {
|
||||||
root.transitionProgress = 0;
|
root.pendingWallpaper = newPath;
|
||||||
root.effectActive = false;
|
return;
|
||||||
currentWallpaper.source = nextWallpaper.source;
|
|
||||||
nextWallpaper.source = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentWallpaper.source) {
|
if (!currentWallpaper.source) {
|
||||||
@@ -488,24 +487,28 @@ Variants {
|
|||||||
currentWallpaper.source = nextWallpaper.source;
|
currentWallpaper.source = nextWallpaper.source;
|
||||||
}
|
}
|
||||||
root.useNextForEffect = false;
|
root.useNextForEffect = false;
|
||||||
Qt.callLater(() => {
|
|
||||||
nextWallpaper.source = "";
|
nextWallpaper.source = "";
|
||||||
Qt.callLater(() => {
|
root.transitionProgress = 0.0;
|
||||||
root.effectActive = false;
|
|
||||||
currentWallpaper.layer.enabled = false;
|
currentWallpaper.layer.enabled = false;
|
||||||
nextWallpaper.layer.enabled = false;
|
nextWallpaper.layer.enabled = false;
|
||||||
currentWallpaper.cache = true;
|
currentWallpaper.cache = true;
|
||||||
nextWallpaper.cache = false;
|
nextWallpaper.cache = false;
|
||||||
root.transitionProgress = 0.0;
|
root.effectActive = false;
|
||||||
});
|
|
||||||
|
if (root.pendingWallpaper) {
|
||||||
|
var pending = root.pendingWallpaper;
|
||||||
|
root.pendingWallpaper = "";
|
||||||
|
Qt.callLater(() => {
|
||||||
|
root.changeWallpaper(pending, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MultiEffect {
|
MultiEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: effectLoader.active ? effectLoader.item : (root.actualTransitionType === "none" ? currentWallpaper : null)
|
source: effectLoader.active ? effectLoader.item : currentWallpaper
|
||||||
visible: CompositorService.isNiri && SettingsData.blurWallpaperOnOverview && NiriService.inOverview && source !== null
|
visible: CompositorService.isNiri && SettingsData.blurWallpaperOnOverview && NiriService.inOverview && currentWallpaper.source !== ""
|
||||||
blurEnabled: true
|
blurEnabled: true
|
||||||
blur: 0.8
|
blur: 0.8
|
||||||
blurMax: 75
|
blurMax: 75
|
||||||
|
|||||||
@@ -22,6 +22,18 @@ Singleton {
|
|||||||
|
|
||||||
property bool available: CompositorService.isNiri && shortcutInhibitorAvailable
|
property bool available: CompositorService.isNiri && shortcutInhibitorAvailable
|
||||||
property string currentProvider: "niri"
|
property string currentProvider: "niri"
|
||||||
|
|
||||||
|
readonly property string cheatsheetProvider: {
|
||||||
|
if (CompositorService.isNiri)
|
||||||
|
return "niri";
|
||||||
|
if (CompositorService.isHyprland)
|
||||||
|
return "hyprland";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
property bool cheatsheetAvailable: cheatsheetProvider !== ""
|
||||||
|
property bool cheatsheetLoading: false
|
||||||
|
property var cheatsheet: ({})
|
||||||
|
|
||||||
property bool loading: false
|
property bool loading: false
|
||||||
property bool saving: false
|
property bool saving: false
|
||||||
property bool fixing: false
|
property bool fixing: false
|
||||||
@@ -58,16 +70,13 @@ Singleton {
|
|||||||
signal bindSaveCompleted(bool success)
|
signal bindSaveCompleted(bool success)
|
||||||
signal bindRemoved(string key)
|
signal bindRemoved(string key)
|
||||||
signal dmsBindsFixed
|
signal dmsBindsFixed
|
||||||
|
signal cheatsheetLoaded
|
||||||
Component.onCompleted: {
|
|
||||||
if (available)
|
|
||||||
Qt.callLater(loadBinds);
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CompositorService
|
target: CompositorService
|
||||||
function onCompositorChanged() {
|
function onCompositorChanged() {
|
||||||
if (CompositorService.isNiri)
|
if (!CompositorService.isNiri)
|
||||||
|
return;
|
||||||
Qt.callLater(root.loadBinds);
|
Qt.callLater(root.loadBinds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,6 +89,31 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: cheatsheetProcess
|
||||||
|
running: false
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
try {
|
||||||
|
root.cheatsheet = JSON.parse(text);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[KeybindsService] Failed to parse cheatsheet:", e);
|
||||||
|
root.cheatsheet = {};
|
||||||
|
}
|
||||||
|
root.cheatsheetLoading = false;
|
||||||
|
root.cheatsheetLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: exitCode => {
|
||||||
|
if (exitCode === 0)
|
||||||
|
return;
|
||||||
|
console.warn("[KeybindsService] Cheatsheet load failed with code:", exitCode);
|
||||||
|
root.cheatsheetLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: loadProcess
|
id: loadProcess
|
||||||
running: false
|
running: false
|
||||||
@@ -199,6 +233,17 @@ Singleton {
|
|||||||
loadBinds(true);
|
loadBinds(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadCheatsheet(provider) {
|
||||||
|
if (cheatsheetProcess.running)
|
||||||
|
return;
|
||||||
|
const target = provider || cheatsheetProvider;
|
||||||
|
if (!target)
|
||||||
|
return;
|
||||||
|
cheatsheetLoading = true;
|
||||||
|
cheatsheetProcess.command = ["dms", "keybinds", "show", target];
|
||||||
|
cheatsheetProcess.running = true;
|
||||||
|
}
|
||||||
|
|
||||||
function loadBinds(showLoading) {
|
function loadBinds(showLoading) {
|
||||||
if (loadProcess.running || !available)
|
if (loadProcess.running || !available)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -20,6 +19,7 @@ Singleton {
|
|||||||
property string distribution: ""
|
property string distribution: ""
|
||||||
property bool distributionSupported: false
|
property bool distributionSupported: false
|
||||||
property string shellVersion: ""
|
property string shellVersion: ""
|
||||||
|
property string shellCodename: ""
|
||||||
|
|
||||||
readonly property var archBasedUCSettings: {
|
readonly property var archBasedUCSettings: {
|
||||||
"listUpdatesSettings": {
|
"listUpdatesSettings": {
|
||||||
@@ -34,7 +34,7 @@ Singleton {
|
|||||||
"currentVersion": match[2],
|
"currentVersion": match[2],
|
||||||
"newVersion": match[3],
|
"newVersion": match[3],
|
||||||
"description": `${match[1]} ${match[2]} → ${match[3]}`
|
"description": `${match[1]} ${match[2]} → ${match[3]}`
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ Singleton {
|
|||||||
"currentVersion": match[2],
|
"currentVersion": match[2],
|
||||||
"newVersion": match[3],
|
"newVersion": match[3],
|
||||||
"description": `${match[1]} ${match[2]} → ${match[3]}`
|
"description": `${match[1]} ${match[2]} → ${match[3]}`
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ Singleton {
|
|||||||
"currentVersion": "",
|
"currentVersion": "",
|
||||||
"newVersion": match[2],
|
"newVersion": match[2],
|
||||||
"description": `${match[1]} → ${match[2]}`
|
"description": `${match[1]} → ${match[2]}`
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,40 +100,49 @@ Singleton {
|
|||||||
command: ["sh", "-c", "cat /etc/os-release | grep '^ID=' | cut -d'=' -f2 | tr -d '\"'"]
|
command: ["sh", "-c", "cat /etc/os-release | grep '^ID=' | cut -d'=' -f2 | tr -d '\"'"]
|
||||||
running: true
|
running: true
|
||||||
|
|
||||||
onExited: (exitCode) => {
|
onExited: exitCode => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
distribution = stdout.text.trim().toLowerCase()
|
distribution = stdout.text.trim().toLowerCase();
|
||||||
distributionSupported = supportedDistributions.includes(distribution)
|
distributionSupported = supportedDistributions.includes(distribution);
|
||||||
|
|
||||||
if (distributionSupported) {
|
if (distributionSupported) {
|
||||||
updateFinderDetection.running = true
|
updateFinderDetection.running = true;
|
||||||
pkgManagerDetection.running = true
|
pkgManagerDetection.running = true;
|
||||||
checkForUpdates()
|
checkForUpdates();
|
||||||
} else {
|
} else {
|
||||||
console.warn("SystemUpdate: Unsupported distribution:", distribution)
|
console.warn("SystemUpdate: Unsupported distribution:", distribution);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn("SystemUpdate: Failed to detect distribution")
|
console.warn("SystemUpdate: Failed to detect distribution");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout: StdioCollector {}
|
stdout: StdioCollector {}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
versionDetection.running = true
|
versionDetection.running = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: versionDetection
|
id: versionDetection
|
||||||
command: [
|
command: ["sh", "-c", `cd "${Quickshell.shellDir}" && if [ -d .git ]; then echo "(git) $(git rev-parse --short HEAD)"; elif [ -f VERSION ]; then cat VERSION; fi`]
|
||||||
"sh", "-c",
|
|
||||||
`cd "${Quickshell.shellDir}" && if [ -d .git ]; then echo "(git) $(git rev-parse --short HEAD)"; elif [ -f VERSION ]; then cat VERSION; fi`
|
|
||||||
]
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
shellVersion = text.trim()
|
shellVersion = text.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: codenameDetection
|
||||||
|
command: ["sh", "-c", `cd "${Quickshell.shellDir}" && if [ -f CODENAME ]; then cat CODENAME; fi`]
|
||||||
|
running: true
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
shellCodename = text.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,12 +151,12 @@ Singleton {
|
|||||||
id: updateFinderDetection
|
id: updateFinderDetection
|
||||||
command: ["sh", "-c", "which checkupdates"]
|
command: ["sh", "-c", "which checkupdates"]
|
||||||
|
|
||||||
onExited: (exitCode) => {
|
onExited: exitCode => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
const exeFound = stdout.text.trim()
|
const exeFound = stdout.text.trim();
|
||||||
updChecker = exeFound.split('/').pop()
|
updChecker = exeFound.split('/').pop();
|
||||||
} else {
|
} else {
|
||||||
console.warn("SystemUpdate: No update checker found. Will use package manager.")
|
console.warn("SystemUpdate: No update checker found. Will use package manager.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,12 +167,12 @@ Singleton {
|
|||||||
id: pkgManagerDetection
|
id: pkgManagerDetection
|
||||||
command: ["sh", "-c", "which paru || which yay || which dnf"]
|
command: ["sh", "-c", "which paru || which yay || which dnf"]
|
||||||
|
|
||||||
onExited: (exitCode) => {
|
onExited: exitCode => {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
const exeFound = stdout.text.trim()
|
const exeFound = stdout.text.trim();
|
||||||
pkgManager = exeFound.split('/').pop()
|
pkgManager = exeFound.split('/').pop();
|
||||||
} else {
|
} else {
|
||||||
console.warn("SystemUpdate: No package manager found")
|
console.warn("SystemUpdate: No package manager found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,19 +182,17 @@ Singleton {
|
|||||||
Process {
|
Process {
|
||||||
id: updateChecker
|
id: updateChecker
|
||||||
|
|
||||||
onExited: (exitCode) => {
|
onExited: exitCode => {
|
||||||
isChecking = false
|
isChecking = false;
|
||||||
const correctExitCodes = updChecker.length > 0 ?
|
const correctExitCodes = updChecker.length > 0 ? [updChecker].concat(updateCheckerParams[updChecker].listUpdatesSettings.correctExitCodes) : [pkgManager].concat(packageManagerParams[pkgManager].listUpdatesSettings.correctExitCodes);
|
||||||
[updChecker].concat(updateCheckerParams[updChecker].listUpdatesSettings.correctExitCodes) :
|
|
||||||
[pkgManager].concat(packageManagerParams[pkgManager].listUpdatesSettings.correctExitCodes)
|
|
||||||
if (correctExitCodes.includes(exitCode)) {
|
if (correctExitCodes.includes(exitCode)) {
|
||||||
parseUpdates(stdout.text)
|
parseUpdates(stdout.text);
|
||||||
hasError = false
|
hasError = false;
|
||||||
errorMessage = ""
|
errorMessage = "";
|
||||||
} else {
|
} else {
|
||||||
hasError = true
|
hasError = true;
|
||||||
errorMessage = "Failed to check for updates"
|
errorMessage = "Failed to check for updates";
|
||||||
console.warn("SystemUpdate: Update check failed with code:", exitCode)
|
console.warn("SystemUpdate: Update check failed with code:", exitCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,67 +201,67 @@ Singleton {
|
|||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: updater
|
id: updater
|
||||||
onExited: (exitCode) => {
|
onExited: exitCode => {
|
||||||
checkForUpdates()
|
checkForUpdates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkForUpdates() {
|
function checkForUpdates() {
|
||||||
if (!distributionSupported || (!pkgManager && !updChecker) || isChecking) return
|
if (!distributionSupported || (!pkgManager && !updChecker) || isChecking)
|
||||||
|
return;
|
||||||
isChecking = true
|
isChecking = true;
|
||||||
hasError = false
|
hasError = false;
|
||||||
if (updChecker.length > 0) {
|
if (updChecker.length > 0) {
|
||||||
updateChecker.command = [updChecker].concat(updateCheckerParams[updChecker].listUpdatesSettings.params)
|
updateChecker.command = [updChecker].concat(updateCheckerParams[updChecker].listUpdatesSettings.params);
|
||||||
} else {
|
} else {
|
||||||
updateChecker.command = [pkgManager].concat(packageManagerParams[pkgManager].listUpdatesSettings.params)
|
updateChecker.command = [pkgManager].concat(packageManagerParams[pkgManager].listUpdatesSettings.params);
|
||||||
}
|
}
|
||||||
updateChecker.running = true
|
updateChecker.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseUpdates(output) {
|
function parseUpdates(output) {
|
||||||
const lines = output.trim().split('\n').filter(line => line.trim())
|
const lines = output.trim().split('\n').filter(line => line.trim());
|
||||||
const updates = []
|
const updates = [];
|
||||||
|
|
||||||
const regex = packageManagerParams[pkgManager].parserSettings.lineRegex
|
const regex = packageManagerParams[pkgManager].parserSettings.lineRegex;
|
||||||
const entryProducer = packageManagerParams[pkgManager].parserSettings.entryProducer
|
const entryProducer = packageManagerParams[pkgManager].parserSettings.entryProducer;
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const match = line.match(regex)
|
const match = line.match(regex);
|
||||||
if (match) {
|
if (match) {
|
||||||
updates.push(entryProducer(match))
|
updates.push(entryProducer(match));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
availableUpdates = updates
|
availableUpdates = updates;
|
||||||
}
|
}
|
||||||
|
|
||||||
function runUpdates() {
|
function runUpdates() {
|
||||||
if (!distributionSupported || !pkgManager || updateCount === 0) return
|
if (!distributionSupported || !pkgManager || updateCount === 0)
|
||||||
|
return;
|
||||||
const terminal = Quickshell.env("TERMINAL") || "xterm"
|
const terminal = Quickshell.env("TERMINAL") || "xterm";
|
||||||
|
|
||||||
if (SettingsData.updaterUseCustomCommand && SettingsData.updaterCustomCommand.length > 0) {
|
if (SettingsData.updaterUseCustomCommand && SettingsData.updaterCustomCommand.length > 0) {
|
||||||
const updateCommand = `${SettingsData.updaterCustomCommand} && echo "Updates complete! Press Enter to close..." && read`
|
const updateCommand = `${SettingsData.updaterCustomCommand} && echo "Updates complete! Press Enter to close..." && read`;
|
||||||
const termClass = SettingsData.updaterTerminalAdditionalParams
|
const termClass = SettingsData.updaterTerminalAdditionalParams;
|
||||||
|
|
||||||
var finalCommand = [terminal]
|
var finalCommand = [terminal];
|
||||||
if (termClass.length > 0) {
|
if (termClass.length > 0) {
|
||||||
finalCommand = finalCommand.concat(termClass.split(" "))
|
finalCommand = finalCommand.concat(termClass.split(" "));
|
||||||
}
|
}
|
||||||
finalCommand.push("-e")
|
finalCommand.push("-e");
|
||||||
finalCommand.push("sh")
|
finalCommand.push("sh");
|
||||||
finalCommand.push("-c")
|
finalCommand.push("-c");
|
||||||
finalCommand.push(updateCommand)
|
finalCommand.push(updateCommand);
|
||||||
updater.command = finalCommand
|
updater.command = finalCommand;
|
||||||
} else {
|
} else {
|
||||||
const params = packageManagerParams[pkgManager].upgradeSettings.params.join(" ")
|
const params = packageManagerParams[pkgManager].upgradeSettings.params.join(" ");
|
||||||
const sudo = packageManagerParams[pkgManager].upgradeSettings.requiresSudo ? "sudo" : ""
|
const sudo = packageManagerParams[pkgManager].upgradeSettings.requiresSudo ? "sudo" : "";
|
||||||
const updateCommand = `${sudo} ${pkgManager} ${params} && echo "Updates complete! Press Enter to close..." && read`
|
const updateCommand = `${sudo} ${pkgManager} ${params} && echo "Updates complete! Press Enter to close..." && read`;
|
||||||
|
|
||||||
updater.command = [terminal, "-e", "sh", "-c", updateCommand]
|
updater.command = [terminal, "-e", "sh", "-c", updateCommand];
|
||||||
}
|
}
|
||||||
updater.running = true
|
updater.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -269,16 +276,16 @@ Singleton {
|
|||||||
|
|
||||||
function updatestatus(): string {
|
function updatestatus(): string {
|
||||||
if (root.isChecking) {
|
if (root.isChecking) {
|
||||||
return "ERROR: already checking"
|
return "ERROR: already checking";
|
||||||
}
|
}
|
||||||
if (!distributionSupported) {
|
if (!distributionSupported) {
|
||||||
return "ERROR: distribution not supported"
|
return "ERROR: distribution not supported";
|
||||||
}
|
}
|
||||||
if (!pkgManager && !updChecker) {
|
if (!pkgManager && !updChecker) {
|
||||||
return "ERROR: update checker not available"
|
return "ERROR: update checker not available";
|
||||||
}
|
}
|
||||||
root.checkForUpdates()
|
root.checkForUpdates();
|
||||||
return "SUCCESS: Now checking..."
|
return "SUCCESS: Now checking...";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user