kitowall 3.5.13 → 3.5.16
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 +20 -38
- package/dist/core/init.js +3 -47
- package/dist/core/live.js +2 -4
- package/dist/core/systemd.js +1 -5
- package/dist/managers/swww.js +1 -4
- package/dist/utils/exec.js +2 -23
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<img src="https://github.com/KitotsuMolina/Kitowall/blob/
|
|
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
|
|
|
5
5
|
`Kitowall` is a wallpaper manager for Hyprland/Wayland using `swww`.
|
|
6
6
|
|
|
7
|
-
Current version: `
|
|
7
|
+
Current version: `3.5.15`.
|
|
8
8
|
|
|
9
9
|
## What You Can Do
|
|
10
10
|
- Rotate wallpapers with transitions.
|
|
@@ -43,11 +43,28 @@ If your system needs it on Wayland:
|
|
|
43
43
|
WEBKIT_DISABLE_DMABUF_RENDERER=1 npm run tauri:dev
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## AppImage (Recommended)
|
|
47
|
+
AppImage is now the primary desktop distribution for `kitowall-ui`.
|
|
48
|
+
|
|
49
|
+
1) Download the latest `Kitowall-<version>-x86_64.AppImage` from GitHub Releases.
|
|
50
|
+
2) Make it executable:
|
|
51
|
+
```bash
|
|
52
|
+
chmod +x ./Kitowall-*.AppImage
|
|
53
|
+
```
|
|
54
|
+
3) First-time host bootstrap (installs CLI/runtime dependencies on host):
|
|
55
|
+
```bash
|
|
56
|
+
./scripts/bootstrap-host.sh
|
|
57
|
+
```
|
|
58
|
+
4) Initialize services:
|
|
59
|
+
```bash
|
|
60
|
+
kitowall init --namespace kitowall --apply --force
|
|
61
|
+
```
|
|
62
|
+
|
|
46
63
|
## Package / Release
|
|
47
64
|
- Release checklist: `RELEASE_CHECKLIST.md`
|
|
48
65
|
- Release notes: `RELEASE_NOTES_1.0.0.md`
|
|
49
66
|
- Dependencies: `DEPENDENCIES.md`
|
|
50
|
-
-
|
|
67
|
+
- AppImage CI: `.github/workflows/build-appimage.yml`
|
|
51
68
|
|
|
52
69
|
Main commands:
|
|
53
70
|
```bash
|
|
@@ -64,46 +81,11 @@ npm run package:ui
|
|
|
64
81
|
npm run package:all
|
|
65
82
|
```
|
|
66
83
|
|
|
67
|
-
## Flatpak (Linux)
|
|
68
|
-
```bash
|
|
69
|
-
# 0) Install host deps (Arch Linux)
|
|
70
|
-
./BOOTSTRAP_FLATPAK_BUILD_DEPS.sh
|
|
71
|
-
|
|
72
|
-
# 1) Build desktop binary
|
|
73
|
-
cd ui
|
|
74
|
-
npm run tauri:build
|
|
75
|
-
cd ..
|
|
76
|
-
|
|
77
|
-
# 2) Prepare flatpak sources (binary + icon)
|
|
78
|
-
./flatpak/prepare.sh
|
|
79
|
-
|
|
80
|
-
# 3) Build and install flatpak
|
|
81
|
-
flatpak-builder flatpak/build-dir flatpak/io.kitotsu.KitoWall.yml --user --install --force-clean
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
For Flathub source pipeline:
|
|
85
|
-
```bash
|
|
86
|
-
./BOOTSTRAP_FLATPAK_BUILD_DEPS.sh
|
|
87
|
-
./GENERATE_FLATHUB_SOURCES.sh 2.1.0 && ./BUILD_FLATPAK_FROMSOURCE.sh
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Integrated local Flatpak (Kitowall + Kitsune + Kitsune-RenderCore in one app):
|
|
91
|
-
```bash
|
|
92
|
-
./BOOTSTRAP_FLATPAK_BUILD_DEPS.sh
|
|
93
|
-
./GENERATE_FLATHUB_SOURCES.sh 2.1.0
|
|
94
|
-
./BUILD_FLATPAK_INTEGRATED_LOCAL.sh
|
|
95
|
-
flatpak run io.kitotsu.KitoWall
|
|
96
|
-
```
|
|
97
|
-
|
|
98
84
|
## User Docs
|
|
99
85
|
- Current status: `STATUS.md`
|
|
100
86
|
- Config examples: `CONFIG_EXAMPLES.md`
|
|
101
87
|
- UI details: `ui/README.md`
|
|
102
88
|
|
|
103
|
-
## Known Issues
|
|
104
|
-
- Flatpak watch unit failing with `/app/bin/node` in user systemd:
|
|
105
|
-
- `issues/flatpak-watch-service-failed.md`
|
|
106
|
-
|
|
107
89
|
## Legal
|
|
108
90
|
- License: `LICENSE.md`
|
|
109
91
|
- Attribution notice: `NOTICE.md`
|
package/dist/core/init.js
CHANGED
|
@@ -17,9 +17,6 @@ function esc(a) {
|
|
|
17
17
|
return JSON.stringify(a);
|
|
18
18
|
}
|
|
19
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
20
|
return (0, exec_1.run)('sh', ['-lc', cmd]);
|
|
24
21
|
}
|
|
25
22
|
async function hostCmdExists(cmd) {
|
|
@@ -32,7 +29,7 @@ async function hostCmdExists(cmd) {
|
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
async function ensureHostDeps() {
|
|
35
|
-
const required = ['swww', 'swww-daemon', 'hyprctl'
|
|
32
|
+
const required = ['swww', 'swww-daemon', 'hyprctl'];
|
|
36
33
|
const missing = [];
|
|
37
34
|
for (const dep of required) {
|
|
38
35
|
if (!(await hostCmdExists(dep)))
|
|
@@ -45,8 +42,6 @@ async function ensureHostDeps() {
|
|
|
45
42
|
pkgSet.add('swww');
|
|
46
43
|
if (missing.includes('hyprctl'))
|
|
47
44
|
pkgSet.add('hyprland');
|
|
48
|
-
if (missing.includes('mpvpaper'))
|
|
49
|
-
pkgSet.add('mpvpaper');
|
|
50
45
|
const packages = Array.from(pkgSet);
|
|
51
46
|
// Best effort auto-install on Arch host; if it fails, we keep a clear actionable error.
|
|
52
47
|
if (packages.length > 0 && await hostCmdExists('pacman')) {
|
|
@@ -62,41 +57,9 @@ async function ensureHostDeps() {
|
|
|
62
57
|
}
|
|
63
58
|
if (stillMissing.length > 0) {
|
|
64
59
|
throw new Error(`Missing host dependencies: ${stillMissing.join(', ')}. ` +
|
|
65
|
-
`Install on host (Arch): sudo pacman -S --needed swww hyprland
|
|
60
|
+
`Install on host (Arch): sudo pacman -S --needed swww hyprland`);
|
|
66
61
|
}
|
|
67
62
|
}
|
|
68
|
-
async function ensureHostRendercoreBridge(appId) {
|
|
69
|
-
const home = (0, node_os_1.homedir)();
|
|
70
|
-
const localBinDir = (0, node_path_1.join)(home, '.local', 'bin');
|
|
71
|
-
ensureDir(localBinDir);
|
|
72
|
-
const bridgePath = (0, node_path_1.join)(localBinDir, 'kitsune-rendercore');
|
|
73
|
-
const bridgeScript = `#!/usr/bin/env bash
|
|
74
|
-
set -euo pipefail
|
|
75
|
-
exec /usr/bin/flatpak run --command=kitsune-rendercore ${appId} "$@"
|
|
76
|
-
`;
|
|
77
|
-
(0, node_fs_1.writeFileSync)(bridgePath, bridgeScript, { encoding: 'utf8', mode: 0o755 });
|
|
78
|
-
const userDir = (0, node_path_1.join)(home, '.config', 'systemd', 'user');
|
|
79
|
-
ensureDir(userDir);
|
|
80
|
-
const unitPath = (0, node_path_1.join)(userDir, 'kitsune-rendercore.service');
|
|
81
|
-
const unit = `
|
|
82
|
-
[Unit]
|
|
83
|
-
Description=Kitsune RenderCore Live Wallpaper (Flatpak bridge)
|
|
84
|
-
After=graphical-session.target
|
|
85
|
-
PartOf=graphical-session.target
|
|
86
|
-
|
|
87
|
-
[Service]
|
|
88
|
-
Type=simple
|
|
89
|
-
ExecStart=${bridgePath}
|
|
90
|
-
Restart=on-failure
|
|
91
|
-
RestartSec=1
|
|
92
|
-
|
|
93
|
-
[Install]
|
|
94
|
-
WantedBy=default.target
|
|
95
|
-
`.trimStart();
|
|
96
|
-
(0, node_fs_1.writeFileSync)(unitPath, unit, 'utf8');
|
|
97
|
-
await (0, exec_1.run)('systemctl', ['--user', 'daemon-reload']);
|
|
98
|
-
await (0, exec_1.run)('systemctl', ['--user', 'enable', '--now', 'kitsune-rendercore.service']).catch(() => { });
|
|
99
|
-
}
|
|
100
63
|
async function disableIfExists(unit) {
|
|
101
64
|
await (0, exec_1.run)('systemctl', ['--user', 'disable', '--now', unit]).catch(() => { });
|
|
102
65
|
await (0, exec_1.run)('systemctl', ['--user', 'reset-failed', unit]).catch(() => { });
|
|
@@ -124,22 +87,15 @@ async function initKitowall(opts) {
|
|
|
124
87
|
const state = (0, state_1.loadState)(); // crea/migra state si hace falta
|
|
125
88
|
const ns = (opts.namespace && opts.namespace.trim()) ? opts.namespace.trim() : 'kitowall';
|
|
126
89
|
const force = !!opts.force;
|
|
127
|
-
const isFlatpak = Boolean(process.env.FLATPAK_ID);
|
|
128
|
-
const flatpakAppId = (process.env.FLATPAK_ID || 'io.kitotsu.KitoWall').trim();
|
|
129
90
|
// Validaciones mínimas
|
|
130
91
|
await ensureHostDeps();
|
|
131
|
-
if (isFlatpak) {
|
|
132
|
-
await ensureHostRendercoreBridge(flatpakAppId);
|
|
133
|
-
}
|
|
134
92
|
// Apagar servicios que pisan el wallpaper
|
|
135
93
|
await detectAndHandleConflicts(force);
|
|
136
94
|
const userDir = (0, node_path_1.join)((0, node_os_1.homedir)(), '.config', 'systemd', 'user');
|
|
137
95
|
ensureDir(userDir);
|
|
138
96
|
const nodePath = process.execPath;
|
|
139
97
|
const cliPath = (0, node_path_1.resolve)(process.argv[1]); // dist/cli.js absoluto
|
|
140
|
-
const cliInvoke =
|
|
141
|
-
? `/usr/bin/flatpak run --command=kitowall ${flatpakAppId}`
|
|
142
|
-
: `${JSON.stringify(nodePath)} ${JSON.stringify(cliPath)}`;
|
|
98
|
+
const cliInvoke = `${JSON.stringify(nodePath)} ${JSON.stringify(cliPath)}`;
|
|
143
99
|
const xdgRuntimeDir = (process.env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR.trim())
|
|
144
100
|
? process.env.XDG_RUNTIME_DIR.trim()
|
|
145
101
|
: `/run/user/${process.getuid?.() ?? 1000}`;
|
package/dist/core/live.js
CHANGED
|
@@ -47,8 +47,8 @@ const LIVE_BROWSER_UA = process.env.KITOWALL_LIVE_UA ||
|
|
|
47
47
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
|
48
48
|
const LIVE_BROWSER_UA_FALLBACK = process.env.KITOWALL_LIVE_UA_FALLBACK ||
|
|
49
49
|
'insomnia/12.3.1';
|
|
50
|
-
const INTEGRATED_RENDERCORE_ENV = '
|
|
51
|
-
const INTEGRATED_RENDERCORE_BIN_FALLBACK = '
|
|
50
|
+
const INTEGRATED_RENDERCORE_ENV = 'KITOWALL_INTEGRATED_RENDERCORE';
|
|
51
|
+
const INTEGRATED_RENDERCORE_BIN_FALLBACK = 'kitsune-rendercore';
|
|
52
52
|
function nowUnix() {
|
|
53
53
|
return Math.floor(Date.now() / 1000);
|
|
54
54
|
}
|
|
@@ -871,8 +871,6 @@ function rendercoreEnvPath() {
|
|
|
871
871
|
return node_path_1.default.join(node_os_1.default.homedir(), '.config', 'kitsune-rendercore', 'env');
|
|
872
872
|
}
|
|
873
873
|
function integratedRendercoreMode() {
|
|
874
|
-
if (!process.env.FLATPAK_ID)
|
|
875
|
-
return false;
|
|
876
874
|
const v = clean(process.env[INTEGRATED_RENDERCORE_ENV]).toLowerCase();
|
|
877
875
|
return v === '1' || v === 'true' || v === 'yes' || v === 'on';
|
|
878
876
|
}
|
package/dist/core/systemd.js
CHANGED
|
@@ -37,8 +37,6 @@ async function installSystemd(opts) {
|
|
|
37
37
|
ensureDir(userDir);
|
|
38
38
|
const every = systemdInterval(opts.every);
|
|
39
39
|
const ns = (opts.namespace && opts.namespace.trim()) ? opts.namespace.trim() : 'kitowall';
|
|
40
|
-
const isFlatpak = Boolean(process.env.FLATPAK_ID);
|
|
41
|
-
const flatpakAppId = (process.env.FLATPAK_ID || 'io.kitotsu.KitoWall').trim();
|
|
42
40
|
const nodePath = process.execPath;
|
|
43
41
|
const cliPath = (0, node_path_1.resolve)(process.argv[1] || '');
|
|
44
42
|
const xdgRuntimeDir = (process.env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR.trim())
|
|
@@ -53,9 +51,7 @@ async function installSystemd(opts) {
|
|
|
53
51
|
const waylandBootstrap = 'WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-$(ls \\"$XDG_RUNTIME_DIR\\"/wayland-* 2>/dev/null | xargs -r -n1 basename | sort | tail -n1)}"; ' +
|
|
54
52
|
'if [ -z "$WAYLAND_DISPLAY" ]; then WAYLAND_DISPLAY=wayland-1; fi; ' +
|
|
55
53
|
'export WAYLAND_DISPLAY;';
|
|
56
|
-
const nextCmd =
|
|
57
|
-
? `${waylandBootstrap} exec /usr/bin/flatpak run --command=kitowall ${flatpakAppId} rotate-now --namespace ${ns} --force`
|
|
58
|
-
: `${waylandBootstrap} exec ${JSON.stringify(nodePath)} ${JSON.stringify(cliPath)} rotate-now --namespace ${JSON.stringify(ns)} --force`;
|
|
54
|
+
const nextCmd = `${waylandBootstrap} exec ${JSON.stringify(nodePath)} ${JSON.stringify(cliPath)} rotate-now --namespace ${JSON.stringify(ns)} --force`;
|
|
59
55
|
const kitowallNextService = `
|
|
60
56
|
[Unit]
|
|
61
57
|
Description=Kitowall apply next wallpapers
|
package/dist/managers/swww.js
CHANGED
|
@@ -8,10 +8,7 @@ function startSwwwDaemon(namespace) {
|
|
|
8
8
|
const args = [];
|
|
9
9
|
if (namespace)
|
|
10
10
|
args.push('--namespace', namespace);
|
|
11
|
-
const
|
|
12
|
-
const cmd = inFlatpak ? 'flatpak-spawn' : 'swww-daemon';
|
|
13
|
-
const spawnArgs = inFlatpak ? ['--host', 'swww-daemon', ...args] : args;
|
|
14
|
-
const child = (0, node_child_process_1.spawn)(cmd, spawnArgs, {
|
|
11
|
+
const child = (0, node_child_process_1.spawn)('swww-daemon', args, {
|
|
15
12
|
stdio: 'ignore',
|
|
16
13
|
detached: true
|
|
17
14
|
});
|
package/dist/utils/exec.js
CHANGED
|
@@ -5,29 +5,8 @@ exports.run = run;
|
|
|
5
5
|
const child_process_1 = require("child_process");
|
|
6
6
|
function run(cmd, args = [], options = {}) {
|
|
7
7
|
return new Promise((resolve, reject) => {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|| process.env.KITOWALL_FLATPAK_INTEGRATED_RENDERCORE === 'true');
|
|
11
|
-
const hostCommands = new Set([
|
|
12
|
-
'swww',
|
|
13
|
-
'swww-daemon',
|
|
14
|
-
'hyprctl',
|
|
15
|
-
'systemctl',
|
|
16
|
-
'xdg-open',
|
|
17
|
-
'steamcmd',
|
|
18
|
-
'ffmpeg',
|
|
19
|
-
'ffprobe',
|
|
20
|
-
'cargo',
|
|
21
|
-
'kitsune-livewallpaper',
|
|
22
|
-
'dd'
|
|
23
|
-
]);
|
|
24
|
-
if (!integratedRendercore) {
|
|
25
|
-
hostCommands.add('which');
|
|
26
|
-
hostCommands.add('kitsune-rendercore');
|
|
27
|
-
}
|
|
28
|
-
const useHost = isFlatpak && hostCommands.has(cmd);
|
|
29
|
-
const finalCmd = useHost ? 'flatpak-spawn' : cmd;
|
|
30
|
-
const finalArgs = useHost ? ['--host', cmd, ...args] : args;
|
|
8
|
+
const finalCmd = cmd;
|
|
9
|
+
const finalArgs = args;
|
|
31
10
|
const child = (0, child_process_1.spawn)(finalCmd, finalArgs, {
|
|
32
11
|
cwd: options.cwd,
|
|
33
12
|
env: options.env,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kitowall",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.16",
|
|
4
4
|
"description": "CLI/daemon for Hyprland wallpapers using swww with pack-based rotation.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"release:check": "npm run build && npm run test:e2e",
|
|
27
27
|
"package:cli": "npm pack",
|
|
28
28
|
"package:ui": "npm --prefix ui run tauri:build",
|
|
29
|
+
"package:appimage": "npm --prefix ui run tauri:build",
|
|
29
30
|
"package:all": "npm run release:check && npm run package:cli && npm run package:ui",
|
|
30
31
|
"test:smoke": "bash ./tests/smoke.e2e.sh",
|
|
31
32
|
"test:regression": "bash ./tests/regression.e2e.sh",
|