kitowall 3.5.12 → 3.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <img src="https://github.com/KitotsuMolina/Kitowall/blob/master/assets/kitowall.png?raw=true" alt="Kitowall" width="420" />
1
+ <img src="https://github.com/KitotsuMolina/Kitowall/blob/main/assets/kitowall.png?raw=true" alt="Kitowall" width="420" />
2
2
 
3
3
  # Kitowall
4
4
 
package/dist/core/init.js CHANGED
@@ -16,6 +16,91 @@ function esc(a) {
16
16
  // ExecStart=... necesita escapado simple. JSON.stringify funciona bien para espacios/comillas.
17
17
  return JSON.stringify(a);
18
18
  }
19
+ async function runHostShell(cmd) {
20
+ if (process.env.FLATPAK_ID) {
21
+ return (0, exec_1.run)('flatpak-spawn', ['--host', 'sh', '-lc', cmd]);
22
+ }
23
+ return (0, exec_1.run)('sh', ['-lc', cmd]);
24
+ }
25
+ async function hostCmdExists(cmd) {
26
+ try {
27
+ await runHostShell(`command -v ${cmd} >/dev/null 2>&1`);
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ async function ensureHostDeps() {
35
+ const required = ['swww', 'swww-daemon', 'hyprctl'];
36
+ const missing = [];
37
+ for (const dep of required) {
38
+ if (!(await hostCmdExists(dep)))
39
+ missing.push(dep);
40
+ }
41
+ if (missing.length === 0)
42
+ return;
43
+ const pkgSet = new Set();
44
+ if (missing.includes('swww') || missing.includes('swww-daemon'))
45
+ pkgSet.add('swww');
46
+ if (missing.includes('hyprctl'))
47
+ pkgSet.add('hyprland');
48
+ const packages = Array.from(pkgSet);
49
+ // Best effort auto-install on Arch host; if it fails, we keep a clear actionable error.
50
+ if (packages.length > 0 && await hostCmdExists('pacman')) {
51
+ const pkgArgs = packages.join(' ');
52
+ await runHostShell(`if command -v sudo >/dev/null 2>&1; then ` +
53
+ `(sudo -n pacman -S --needed --noconfirm ${pkgArgs} || sudo pacman -S --needed ${pkgArgs}); ` +
54
+ `else pacman -S --needed ${pkgArgs}; fi`).catch(() => { });
55
+ }
56
+ const stillMissing = [];
57
+ for (const dep of required) {
58
+ if (!(await hostCmdExists(dep)))
59
+ stillMissing.push(dep);
60
+ }
61
+ if (stillMissing.length > 0) {
62
+ throw new Error(`Missing host dependencies: ${stillMissing.join(', ')}. ` +
63
+ `Install on host (Arch): sudo pacman -S --needed swww hyprland`);
64
+ }
65
+ }
66
+ async function ensureHostFlatpakBridges(appId) {
67
+ const home = (0, node_os_1.homedir)();
68
+ const localBinDir = (0, node_path_1.join)(home, '.local', 'bin');
69
+ ensureDir(localBinDir);
70
+ const writeBridge = (name, command) => {
71
+ const bridgePath = (0, node_path_1.join)(localBinDir, name);
72
+ const bridgeScript = `#!/usr/bin/env bash
73
+ set -euo pipefail
74
+ exec /usr/bin/flatpak run --command=${command} ${appId} "$@"
75
+ `;
76
+ (0, node_fs_1.writeFileSync)(bridgePath, bridgeScript, { encoding: 'utf8', mode: 0o755 });
77
+ return bridgePath;
78
+ };
79
+ writeBridge('kitowall', 'kitowall');
80
+ writeBridge('kitsune', 'kitsune');
81
+ const rendercoreBridgePath = writeBridge('kitsune-rendercore', 'kitsune-rendercore');
82
+ const userDir = (0, node_path_1.join)(home, '.config', 'systemd', 'user');
83
+ ensureDir(userDir);
84
+ const unitPath = (0, node_path_1.join)(userDir, 'kitsune-rendercore.service');
85
+ const unit = `
86
+ [Unit]
87
+ Description=Kitsune RenderCore Live Wallpaper (Flatpak bridge)
88
+ After=graphical-session.target
89
+ PartOf=graphical-session.target
90
+
91
+ [Service]
92
+ Type=simple
93
+ ExecStart=${rendercoreBridgePath}
94
+ Restart=on-failure
95
+ RestartSec=1
96
+
97
+ [Install]
98
+ WantedBy=default.target
99
+ `.trimStart();
100
+ (0, node_fs_1.writeFileSync)(unitPath, unit, 'utf8');
101
+ await (0, exec_1.run)('systemctl', ['--user', 'daemon-reload']);
102
+ await (0, exec_1.run)('systemctl', ['--user', 'enable', '--now', 'kitsune-rendercore.service']).catch(() => { });
103
+ }
19
104
  async function disableIfExists(unit) {
20
105
  await (0, exec_1.run)('systemctl', ['--user', 'disable', '--now', unit]).catch(() => { });
21
106
  await (0, exec_1.run)('systemctl', ['--user', 'reset-failed', unit]).catch(() => { });
@@ -39,24 +124,26 @@ async function detectAndHandleConflicts(force) {
39
124
  }
40
125
  }
41
126
  async function initKitowall(opts) {
42
- if (process.env.FLATPAK_ID) {
43
- throw new Error('init/repair cannot be executed from Flatpak UI because it would generate host systemd units with sandbox paths. ' +
44
- 'Run on host shell: kitowall init --namespace kitowall --apply --force (or, in local dev, node dist/cli.js init --namespace kitowall --apply --force)');
45
- }
46
127
  const config = (0, config_1.loadConfig)(); // crea/migra config si hace falta
47
128
  const state = (0, state_1.loadState)(); // crea/migra state si hace falta
48
129
  const ns = (opts.namespace && opts.namespace.trim()) ? opts.namespace.trim() : 'kitowall';
49
130
  const force = !!opts.force;
131
+ const isFlatpak = Boolean(process.env.FLATPAK_ID);
132
+ const flatpakAppId = (process.env.FLATPAK_ID || 'io.kitotsu.KitoWall').trim();
50
133
  // Validaciones mínimas
51
- await (0, exec_1.run)('which', ['swww']).catch(() => { throw new Error('Missing dependency: swww'); });
52
- await (0, exec_1.run)('which', ['swww-daemon']).catch(() => { throw new Error('Missing dependency: swww-daemon'); });
53
- await (0, exec_1.run)('which', ['hyprctl']).catch(() => { throw new Error('Missing dependency: hyprctl'); });
134
+ await ensureHostDeps();
135
+ if (isFlatpak) {
136
+ await ensureHostFlatpakBridges(flatpakAppId);
137
+ }
54
138
  // Apagar servicios que pisan el wallpaper
55
139
  await detectAndHandleConflicts(force);
56
140
  const userDir = (0, node_path_1.join)((0, node_os_1.homedir)(), '.config', 'systemd', 'user');
57
141
  ensureDir(userDir);
58
142
  const nodePath = process.execPath;
59
143
  const cliPath = (0, node_path_1.resolve)(process.argv[1]); // dist/cli.js absoluto
144
+ const cliInvoke = isFlatpak
145
+ ? `/usr/bin/flatpak run --command=kitowall ${flatpakAppId}`
146
+ : `${JSON.stringify(nodePath)} ${JSON.stringify(cliPath)}`;
60
147
  const xdgRuntimeDir = (process.env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR.trim())
61
148
  ? process.env.XDG_RUNTIME_DIR.trim()
62
149
  : `/run/user/${process.getuid?.() ?? 1000}`;
@@ -92,7 +179,7 @@ WantedBy=graphical-session.target
92
179
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(userDir, 'swww-daemon@.service'), swwwDaemonTemplate, 'utf8');
93
180
  // 2) kitowall-next.service (oneshot)
94
181
  // OJO: aunque CLI ignore --namespace en algunos comandos, aquí lo dejamos por compatibilidad.
95
- const nextExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${nodePath} ${esc(cliPath)} ${esc('next')} ${esc('--namespace')} ${esc(ns)}`)}`;
182
+ const nextExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${cliInvoke} next --namespace ${JSON.stringify(ns)}`)}`;
96
183
  const kitowallNextService = `
97
184
  [Unit]
98
185
  Description=Kitowall apply next wallpapers
@@ -107,7 +194,7 @@ ExecStart=${nextExec}
107
194
  `.trimStart();
108
195
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(userDir, 'kitowall-next.service'), kitowallNextService, 'utf8');
109
196
  // 3) kitowall-watch.service (hotplug watcher)
110
- const watchExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${nodePath} ${esc(cliPath)} ${esc('watch')} ${esc('--namespace')} ${esc(ns)}`)}`;
197
+ const watchExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${cliInvoke} watch --namespace ${JSON.stringify(ns)}`)}`;
111
198
  const kitowallWatchService = `
112
199
  [Unit]
113
200
  Description=Kitowall watcher (monitor hotplug)
@@ -128,7 +215,7 @@ WantedBy=graphical-session.target
128
215
  `.trimStart();
129
216
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(userDir, 'kitowall-watch.service'), kitowallWatchService, 'utf8');
130
217
  // 4) kitowall-login-apply.service (apply once on login to avoid gray background)
131
- const loginApplyExec = `/bin/sh -lc ${esc(`sleep 2; ${waylandBootstrap} exec ${nodePath} ${esc(cliPath)} ${esc('rotate-now')} ${esc('--namespace')} ${esc(ns)} ${esc('--force')}`)}`;
218
+ const loginApplyExec = `/bin/sh -lc ${esc(`sleep 2; ${waylandBootstrap} exec ${cliInvoke} rotate-now --namespace ${JSON.stringify(ns)} --force`)}`;
132
219
  const kitowallLoginApplyService = `
133
220
  [Unit]
134
221
  Description=Kitowall apply wallpapers on session start
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitowall",
3
- "version": "3.5.12",
3
+ "version": "3.5.14",
4
4
  "description": "CLI/daemon for Hyprland wallpapers using swww with pack-based rotation.",
5
5
  "repository": {
6
6
  "type": "git",