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 +1 -1
- package/dist/core/init.js +97 -10
- package/package.json +1 -1
package/README.md
CHANGED
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 (
|
|
52
|
-
|
|
53
|
-
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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
|