diff --git a/scripts/gen-icon.sh b/scripts/gen-icon.sh new file mode 100644 index 0000000..ba6293b --- /dev/null +++ b/scripts/gen-icon.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Erzeugt alle Icon-Groessen fuer Tauri aus scripts/icon.svg. +# Braucht ImageMagick (auf Nix: via nix-shell automatisch verfuegbar). +# +# Aufruf: ./scripts/gen-icon.sh +# Ergebnis: src-tauri/icons/{icon.png, 32x32.png, 128x128.png, 128x128@2x.png} + +set -euo pipefail + +cd "$(dirname "$0")/.." +SVG="scripts/icon.svg" +OUT="src-tauri/icons" + +if [ ! -f "$SVG" ]; then + echo "❌ $SVG nicht gefunden" >&2; exit 1 +fi +mkdir -p "$OUT" + +# ImageMagick aus Nix ziehen falls nicht vorhanden +if ! command -v magick >/dev/null && ! command -v convert >/dev/null; then + echo "ℹ️ ImageMagick fehlt — ziehe aus nixpkgs" + IM=$(nix-build '' -A imagemagick --no-out-link 2>/dev/null || true) + [ -n "$IM" ] && export PATH="$IM/bin:$PATH" || { echo "❌ ImageMagick nicht bezogen"; exit 1; } +fi + +# Moderne ImageMagick nutzt `magick`, aeltere `convert` +if command -v magick >/dev/null; then IM_CMD="magick"; else IM_CMD="convert"; fi + +echo "Generiere Icons aus $SVG mit $IM_CMD..." + +# WICHTIG: -depth 8 erzwingen — sonst erzeugt ImageMagick aus hoher SVG-Density +# 16-bit-RGBA-PNGs. Tauris Tray-Icon-Crate erwartet 8-bit RGBA (4 Byte/Pixel). +for size in 32 64 128 256 512; do + $IM_CMD -background none -density 400 "$SVG" -resize "${size}x${size}" -depth 8 "$OUT/${size}x${size}.png" + echo " ✓ $OUT/${size}x${size}.png" +done + +# Retina-Variante (Tauri-Konvention) +$IM_CMD -background none -density 400 "$SVG" -resize 256x256 -depth 8 "$OUT/128x128@2x.png" +echo " ✓ $OUT/128x128@2x.png" + +# Haupt-Icon +cp "$OUT/512x512.png" "$OUT/icon.png" +echo " ✓ $OUT/icon.png (Haupt-Icon 512x512)" + +echo +echo "✅ Fertig. Icons in $OUT/:" +ls -l "$OUT"/*.png diff --git a/scripts/icon.svg b/scripts/icon.svg new file mode 100644 index 0000000..1cfdd58 --- /dev/null +++ b/scripts/icon.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png new file mode 100644 index 0000000..1439542 Binary files /dev/null and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png new file mode 100644 index 0000000..afc3573 Binary files /dev/null and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/256x256.png b/src-tauri/icons/256x256.png new file mode 100644 index 0000000..1119e97 Binary files /dev/null and b/src-tauri/icons/256x256.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png new file mode 100644 index 0000000..fb859d3 Binary files /dev/null and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/512x512.png b/src-tauri/icons/512x512.png new file mode 100644 index 0000000..23e2701 Binary files /dev/null and b/src-tauri/icons/512x512.png differ diff --git a/src-tauri/icons/64x64.png b/src-tauri/icons/64x64.png new file mode 100644 index 0000000..d95c523 Binary files /dev/null and b/src-tauri/icons/64x64.png differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index 19ce3de..23e2701 100644 Binary files a/src-tauri/icons/icon.png and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/src/update.rs b/src-tauri/src/update.rs index 4fb3593..fbbbfcb 100644 --- a/src-tauri/src/update.rs +++ b/src-tauri/src/update.rs @@ -269,6 +269,10 @@ pub async fn download_update( /// 2. Nix-Wrapper-Modus → `$CLAUDE_DESKTOP_NIX_WRAPPER=1` + `$CLAUDE_DESKTOP_BIN` zeigt /// auf ~/.local/share/claude-desktop/bin/claude-desktop (writable, siehe nix/default.nix) /// 3. Entwicklungs-Build → Fehlerhinweis mit Build-Anleitung +/// +/// Vor dem Rename wird ein Smoke-Test durchgeführt: Die heruntergeladene Datei +/// muss ein valides ELF-Binary sein (Magic-Bytes 0x7F 'ELF'). Das fängt korrupte +/// Downloads und falsche Architekturen ab, bevor das funktionsfähige Binary ersetzt wird. #[tauri::command] pub async fn apply_update(app: AppHandle, update_path: PathBuf) -> Result<(), String> { // Modus bestimmen: AppImage > Nix-Wrapper > Dev @@ -289,7 +293,34 @@ pub async fn apply_update(app: AppHandle, update_path: PathBuf) -> Result<(), St .to_string() })?; - // Backup-Pfad: gleiches Verzeichnis, Suffix .backup + // === Smoke-Test: Ist die neue Datei ein valides ELF-Binary? === + // ELF-Magic: 0x7F 'E' 'L' 'F' (gilt auch fuer AppImages, die self-extracting ELFs sind) + let meta = std::fs::metadata(&update_path) + .map_err(|e| format!("Update-Datei nicht zugreifbar: {}", e))?; + if !meta.is_file() { + return Err("Update-Datei ist keine regulaere Datei — Abbruch, bestehende Installation unveraendert.".into()); + } + if meta.len() < 4 { + return Err(format!( + "Update-Datei ist zu klein ({} Bytes) — vermutlich abgebrochener Download. Bestehende Installation unveraendert.", + meta.len() + )); + } + { + use std::io::Read; + let mut magic = [0u8; 4]; + std::fs::File::open(&update_path) + .and_then(|mut f| f.read_exact(&mut magic)) + .map_err(|e| format!("Update-Datei nicht lesbar: {} — bestehende Installation unveraendert.", e))?; + if magic != [0x7F, 0x45, 0x4C, 0x46] { + return Err(format!( + "Update-Datei ist kein ausfuehrbares ELF-Binary (Magic: {:02X} {:02X} {:02X} {:02X}). Bestehende Installation unveraendert.", + magic[0], magic[1], magic[2], magic[3] + )); + } + } + + // === Backup + Rename === let backup_path = { let mut p = target.clone(); let file_name = target @@ -306,7 +337,7 @@ pub async fn apply_update(app: AppHandle, update_path: PathBuf) -> Result<(), St std::fs::rename(&update_path, &target).map_err(|e| { // Rollback std::fs::rename(&backup_path, &target).ok(); - format!("Update-Installation fehlgeschlagen ({}): {}", mode_label, e) + format!("Update-Installation fehlgeschlagen ({}): {} — Backup wiederhergestellt.", mode_label, e) })?; std::fs::remove_file(&backup_path).ok(); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4e310aa..8f4d7e7 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -33,6 +33,9 @@ "active": true, "targets": ["appimage", "deb"], "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", "icons/icon.png" ] }, diff --git a/src/lib/components/ChatPanel.svelte b/src/lib/components/ChatPanel.svelte index f7625e8..3b147bf 100644 --- a/src/lib/components/ChatPanel.svelte +++ b/src/lib/components/ChatPanel.svelte @@ -1,7 +1,7 @@