Three related fixes after the notes feature landed: Config location: build_and_deploy.ps1 wipes its target directory before every deploy, and app_dir() had just been pointed at that same directory -- so every rebuild silently deleted the user's config and the app rebuilt it empty from the board, losing all notes. Config now lives in %APPDATA%\VersaPadViewer (roaming), separate from the install dir, and the build script additionally rescues any versapad_config*.json it finds in the target so legacy installs survive an upgrade. Window chrome: hide the title bar (plain Tk overrideredirect, no ctypes window manipulation) and move the mode checkboxes up next to the title, which reclaims two full rows of header height that the taller note cards had eaten. Removing the title bar also removes the resize borders, so add a grip -- anchored with place() to the window corner rather than packed after the content, which would push it out of view exactly when the window is too small and the grip is needed. Default geometry grown to fit the taller cards, and empty encoder note lines are no longer rendered at all. Note truncation: the note area was a fixed 34px and cut longer notes mid-word; it now takes the remaining card height.
120 lines
4.7 KiB
PowerShell
120 lines
4.7 KiB
PowerShell
# Baut VersaPadViewer.exe (PyInstaller --onedir) und kopiert das Ergebnis
|
|
# nach %LOCALAPPDATA%\VersaPadViewer (nicht $projectDir\dist wie im
|
|
# jappel-Upstream -- hier bereits die tatsaechlich installierte/genutzte
|
|
# Instanz, siehe Speicher-Notiz "VersaPad Viewer Tool"; ein Pfadwechsel
|
|
# wuerde bestehende Verknuepfungen/Autostart-Eintraege brechen).
|
|
#
|
|
# WICHTIG: Sowohl Bauen als auch Laufen muessen lokal passieren, NICHT auf
|
|
# dem Netzlaufwerk (Z:\Git\...):
|
|
# - Laufzeit: Windows blockiert das Nachladen der PyInstaller-_internal-
|
|
# DLLs von einem Netzwerkpfad (SMB-Share) ohne jede Fehlermeldung, der
|
|
# Prozess startet einfach nie.
|
|
# - Buildzeit: PyInstaller scheitert beim Kopieren von Tcl/Tk-tzdata (viele
|
|
# tief verschachtelte, lang benannte Zeitzonen-Ordner) mit
|
|
# "FileNotFoundError: [WinError 3]" -- Pfadlaengen-Problem auf dem
|
|
# SMB-Share, kombiniert mit dem eh schon langen Projektpfad.
|
|
#
|
|
# Deshalb: Quellcode zuerst nach lokal (%TEMP%) kopieren, dort bauen, danach
|
|
# das fertige Bundle nach $projectDir\dist kopieren. Z: wird nur zum Lesen
|
|
# der Quelldateien angefasst.
|
|
#
|
|
# Fehlerverhalten: Bei Doppelklick im Explorer schliesst sich das Fenster
|
|
# sofort nach Skriptende -- ohne Pause waeren Fehlermeldungen unsichtbar
|
|
# ("stirbt ohne jede Fehlermeldung"). Deshalb: alles in try/catch, im
|
|
# Fehlerfall UND am Ende eine Pause, ausser bei -NoPause (fuer CI/Automation).
|
|
|
|
param(
|
|
[switch]$NoPause
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$projectDir = $PSScriptRoot
|
|
$buildSrc = "$env:TEMP\versapad_build_src"
|
|
$localDir = "$env:LOCALAPPDATA\VersaPadViewer"
|
|
$requirementsFile = "$projectDir\requirements.txt"
|
|
|
|
function Assert-LastExitCode([string]$step) {
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "$step ist fehlgeschlagen (Exit-Code $LASTEXITCODE) -- Ausgabe oben pruefen."
|
|
}
|
|
}
|
|
|
|
function Wait-ForKeyIfInteractive {
|
|
if ($NoPause) { return }
|
|
try {
|
|
Read-Host "Taste druecken zum Schliessen"
|
|
} catch {
|
|
# z.B. nicht-interaktiver Aufruf (stdin nicht verfuegbar) -- einfach ignorieren
|
|
}
|
|
}
|
|
|
|
try {
|
|
Write-Host "Pruefe Python-Installation..."
|
|
py --version
|
|
Assert-LastExitCode "'py --version' (ist Python installiert und im PATH?)"
|
|
|
|
if (-not (Test-Path $requirementsFile)) {
|
|
throw "requirements.txt nicht gefunden unter $requirementsFile"
|
|
}
|
|
Write-Host "Installiere/aktualisiere benoetigte Pakete aus requirements.txt..."
|
|
py -m pip install --quiet --disable-pip-version-check -r $requirementsFile
|
|
Assert-LastExitCode "Paketinstallation (pip install -r requirements.txt)"
|
|
|
|
if (Test-Path $buildSrc) {
|
|
Remove-Item $buildSrc -Recurse -Force
|
|
}
|
|
New-Item -ItemType Directory -Path $buildSrc | Out-Null
|
|
Copy-Item "$projectDir\*.py" -Destination $buildSrc
|
|
Copy-Item "$projectDir\icon.ico" -Destination $buildSrc
|
|
Copy-Item "$projectDir\icon.png" -Destination $buildSrc
|
|
|
|
Push-Location $buildSrc
|
|
try {
|
|
Write-Host "Baue mit PyInstaller (--onedir --windowed)..."
|
|
py -m PyInstaller --windowed --onedir --name VersaPadViewer `
|
|
--icon icon.ico --add-data "icon.png;." --add-data "icon.ico;." `
|
|
desktop_viewer.py --noconfirm
|
|
Assert-LastExitCode "PyInstaller-Build"
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
|
|
if (-not (Test-Path "$buildSrc\dist\VersaPadViewer\VersaPadViewer.exe")) {
|
|
throw "PyInstaller hat keine VersaPadViewer.exe erzeugt, obwohl der Exit-Code 0 war -- Build-Ausgabe oben pruefen."
|
|
}
|
|
|
|
# Zielverzeichnis abraeumen, aber NIE Nutzerdaten mitloeschen: die Config
|
|
# liegt zwar inzwischen woanders (Roaming-AppData, siehe
|
|
# versapad_data.app_dir()), aeltere Installationen haben sie aber noch
|
|
# hier liegen -- ohne diese Sicherung loescht jeder Rebuild sie mit
|
|
# (am 2026-08-15 genau so passiert, alle Notizen weg).
|
|
$userData = Get-ChildItem $localDir -Filter "versapad_config*.json" -File -ErrorAction SilentlyContinue
|
|
$rescued = @()
|
|
foreach ($f in $userData) {
|
|
$tmp = Join-Path $env:TEMP $f.Name
|
|
Copy-Item $f.FullName $tmp -Force
|
|
$rescued += @{ Tmp = $tmp; Name = $f.Name }
|
|
Write-Host "Nutzerdatei gesichert: $($f.Name)" -ForegroundColor Yellow
|
|
}
|
|
|
|
if (Test-Path $localDir) {
|
|
Remove-Item $localDir -Recurse -Force
|
|
}
|
|
Copy-Item "$buildSrc\dist\VersaPadViewer" -Destination $localDir -Recurse
|
|
|
|
foreach ($r in $rescued) {
|
|
Copy-Item $r.Tmp (Join-Path $localDir $r.Name) -Force
|
|
Remove-Item $r.Tmp -Force
|
|
}
|
|
Remove-Item $buildSrc -Recurse -Force
|
|
|
|
Write-Host ""
|
|
Write-Host "Fertig: $localDir\VersaPadViewer.exe" -ForegroundColor Green
|
|
Wait-ForKeyIfInteractive
|
|
}
|
|
catch {
|
|
Write-Host ""
|
|
Write-Host "FEHLER: $($_.Exception.Message)" -ForegroundColor Red
|
|
Wait-ForKeyIfInteractive
|
|
exit 1
|
|
}
|