Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1ec829a
feat(installer): enable selectable install directory and branded setup
Strudelcode Oct 13, 2026
758f528
feat(desktop): show branded startup splash immediately
Strudelcode Oct 13, 2026
21e56fb
feat(desktop): add minimal branded startup splash
Strudelcode Oct 13, 2026
87d2f34
chore(release): bump SOCDOF to 24.10.0
Strudelcode Oct 13, 2026
993c17d
chore(version): document 24.10.0 installer improvements
Strudelcode Oct 13, 2026
58a02cf
docs(changelog): document selectable installer and startup splash
Strudelcode Oct 13, 2026
69dc74d
docs(release): add SOCDOF v24.10.0 overview
Strudelcode Oct 13, 2026
d45e05d
docs(todo): track Windows installer verification
Strudelcode Oct 13, 2026
fc86a4e
docs(changelog): note installer and startup feedback improvements
Strudelcode Oct 13, 2026
6b4b10c
feat(installer): add standalone Windows bootstrapper project
Strudelcode Oct 13, 2026
d6d2840
feat(installer): add immediate dark setup window with download progress
Strudelcode Oct 13, 2026
1727c26
ci: validate desktop build and Windows installer bootstrapper
Strudelcode Oct 13, 2026
3d1aa49
build(release): publish instant-launch installer bootstrapper
Strudelcode Oct 13, 2026
ca72c83
feat(download): offer immediate-launch SOCDOF installer
Strudelcode Oct 13, 2026
6a4b83e
feat(installer): add lightweight framework-based bootstrapper project
Strudelcode Oct 13, 2026
60081c7
feat(installer): add immediate-start Windows setup UI with download p…
Strudelcode Oct 13, 2026
5c4dcbc
ci: compile lightweight framework bootstrapper on pull requests
Strudelcode Oct 13, 2026
647f988
build(release): use instant-start .NET Framework bootstrapper
Strudelcode Oct 13, 2026
98de924
docs(installer): document instant-launch bootstrapper
Strudelcode Oct 13, 2026
613631f
docs(installer): document instant-launch bootstrapper
Strudelcode Oct 13, 2026
b33cb5b
docs(installer): document instant-launch bootstrapper
Strudelcode Oct 13, 2026
563d10c
docs(installer): document instant-launch bootstrapper
Strudelcode Oct 13, 2026
b3feafa
docs(version): describe instant-launch Windows bootstrapper
Strudelcode Oct 13, 2026
8dbf190
ci: remove redundant bootstrapper workflow without lockfile
Strudelcode Oct 13, 2026
3cd1b34
refactor(installer): keep only lightweight framework bootstrapper
Strudelcode Oct 13, 2026
c3d16e7
refactor(installer): keep only lightweight framework bootstrapper
Strudelcode Oct 13, 2026
75d9527
ci: validate SOCDOF app and instant-launch installer
Strudelcode Oct 13, 2026
c953362
fix(installer): correct rounded window region arguments
Strudelcode Oct 13, 2026
6231328
test(installer): validate full Windows NSIS packaging
Strudelcode Oct 13, 2026
47ed7fd
fix(updater): select NSIS setup instead of bootstrapper
Strudelcode Oct 13, 2026
fd13581
fix(download): prefer instant-launch installer asset
Strudelcode Oct 13, 2026
5f9019e
docs(download): show correct installer filename
Strudelcode Oct 13, 2026
f2b8b3f
test(installer): prepare NSIS assets and Electron tooling
Strudelcode Oct 13, 2026
a6add10
test(installer): smoke-test fresh install and upgrade
Strudelcode Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/build-windows-exe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Build lightweight instant-launch bootstrapper
shell: powershell
run: |
$msbuild = Get-ChildItem "C:\Program Files\Microsoft Visual Studio" -Filter MSBuild.exe -Recurse | Where-Object { $_.FullName -match "Current\\Bin\\MSBuild.exe$" } | Select-Object -First 1
if (-not $msbuild) { throw "MSBuild.exe was not found on the Windows runner." }
& $msbuild.FullName installer-bootstrapper\SOCDOF.Bootstrapper.Framework.csproj /p:Configuration=Release /p:Platform=AnyCPU /m
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Copy-Item release\bootstrapper\SOCDOF-Installer.exe release\SOCDOF-Installer.exe -Force
if (-not (Test-Path release\SOCDOF-Installer.exe)) { throw "SOCDOF-Installer.exe was not produced." }

- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/installer-bootstrapper-framework-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Validate SOCDOF Installer Bootstrapper (.NET Framework)

on:
pull_request:
branches: [main, master]
workflow_dispatch:

permissions:
contents: read

jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Build native-startup Windows bootstrapper
shell: powershell
run: |
$msbuild = Get-ChildItem "C:\Program Files\Microsoft Visual Studio" -Filter MSBuild.exe -Recurse | Where-Object { $_.FullName -match "Current\\Bin\\MSBuild.exe$" } | Select-Object -First 1
if (-not $msbuild) { throw "MSBuild.exe was not found on the Windows runner." }
& $msbuild.FullName installer-bootstrapper\SOCDOF.Bootstrapper.Framework.csproj /p:Configuration=Release /p:Platform=AnyCPU /m
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
if (-not (Test-Path release\bootstrapper\SOCDOF-Installer.exe)) { throw "Bootstrapper executable was not produced." }
74 changes: 74 additions & 0 deletions .github/workflows/socdof-installer-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Validate SOCDOF App and Installer

on:
pull_request:
branches: [main, master]
workflow_dispatch:

permissions:
contents: read

jobs:
validate:
runs-on: windows-latest
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Install dependencies
run: npm install --no-package-lock

- name: TypeScript validation
run: npm run lint

- name: Build web application
run: npm run build

- name: Prepare NSIS artwork
run: node scripts/generate_nsis_bitmaps.js

- name: Install Electron packaging tools
run: npm install --no-save --no-package-lock electron electron-builder

- name: Package Windows NSIS installer
run: npx --yes electron-builder --win --x64 --config electron-builder.json --publish never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Verify Windows installer artifact
shell: powershell
run: |
$setup = Get-ChildItem release -Filter 'SOCDOF-Setup-*.exe' -File | Select-Object -First 1
if (-not $setup) { throw "Electron Builder did not produce the expected SOCDOF-Setup-*.exe artifact." }
Write-Host "Verified installer artifact: $($setup.FullName) ($($setup.Length) bytes)"

- name: Smoke-test fresh install and in-place upgrade
shell: powershell
run: |
$setup = Get-ChildItem release -Filter 'SOCDOF-Setup-*.exe' -File | Select-Object -First 1
if (-not $setup) { throw "No SOCDOF NSIS installer is available for smoke testing." }
$installPath = Join-Path $env:RUNNER_TEMP 'SOCDOF-SmokeInstall'
$firstInstall = Start-Process -FilePath $setup.FullName -ArgumentList @('/S', "/D=$installPath") -Wait -PassThru
if ($firstInstall.ExitCode -ne 0) { throw "Fresh install failed with exit code $($firstInstall.ExitCode)." }
$appExe = Join-Path $installPath 'SOCDOF.exe'
if (-not (Test-Path $appExe)) { throw "Fresh install did not produce SOCDOF.exe at the selected install path." }
Get-Process -Name 'SOCDOF' -ErrorAction SilentlyContinue | Stop-Process -Force
$upgrade = Start-Process -FilePath $setup.FullName -ArgumentList @('/S', "/D=$installPath") -Wait -PassThru
if ($upgrade.ExitCode -ne 0) { throw "In-place upgrade failed with exit code $($upgrade.ExitCode)." }
if (-not (Test-Path $appExe)) { throw "In-place upgrade removed or failed to preserve SOCDOF.exe." }
Get-Process -Name 'SOCDOF' -ErrorAction SilentlyContinue | Stop-Process -Force
Write-Host "Fresh install and in-place upgrade passed at $installPath."

- name: Compile instant-launch bootstrapper
shell: powershell
run: |
$msbuild = Get-ChildItem "C:\Program Files\Microsoft Visual Studio" -Filter MSBuild.exe -Recurse | Where-Object { $_.FullName -match "Current\\Bin\\MSBuild.exe$" } | Select-Object -First 1
if (-not $msbuild) { throw "MSBuild.exe was not found on the Windows runner." }
& $msbuild.FullName installer-bootstrapper\SOCDOF.Bootstrapper.Framework.csproj /p:Configuration=Release /p:Platform=AnyCPU /m
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
if (-not (Test-Path release\bootstrapper\SOCDOF-Installer.exe)) { throw "Bootstrapper executable was not produced." }
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ Format guidelines:
- Keep it concise: what is new, what changed/improved, what was fixed.
- Avoid exhaustive UI/visual layout breakdowns.
-->

- **Changed:** Windows setup now allows choosing the installation directory while defaulting to a per-user Local AppData location.
- **Improved:** Added a minimal branded startup splash while the SOCDOF desktop workspace initializes.

- **Added:** A lightweight Windows bootstrapper opens immediately, downloads the latest setup with real progress, and lets users select the installation directory.
13 changes: 9 additions & 4 deletions electron-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
{
"from": "languages",
"to": "languages",
"filter": ["**/*"]
"filter": [
"**/*"
]
}
],
"win": {
Expand All @@ -31,9 +33,9 @@
]
},
"nsis": {
"oneClick": true,
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "SOCDOF Desktop",
Expand All @@ -43,6 +45,9 @@
"installerIcon": "public/socdof_icon.ico",
"uninstallerIcon": "public/socdof_icon.ico",
"installerHeaderIcon": "public/socdof_icon.ico",
"uninstallerSidebar": "public/uninstallerSidebar.bmp"
"uninstallerSidebar": "public/uninstallerSidebar.bmp",
"installerSidebar": "public/installerSidebar.bmp",
"installerHeader": "public/installerHeader.bmp",
"displayLanguageSelector": false
}
}
38 changes: 38 additions & 0 deletions electron/main.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,42 @@ if (!gotSingleInstanceLock) {
}

let mainWindow;
let splashWindow = null;

// Show a lightweight branded window while the main workspace initializes.
function createSplashWindow() {
if (splashWindow && !splashWindow.isDestroyed()) return;
splashWindow = new BrowserWindow({
width: 390,
height: 300,
frame: false,
transparent: false,
resizable: false,
movable: true,
center: true,
show: false,
skipTaskbar: false,
backgroundColor: '#101116',
title: 'SOCDOF wird gestartet',
icon: process.platform === 'win32'
? path.join(__dirname, '../public/socdof_icon.ico')
: path.join(__dirname, '../public/socdof_icon.png'),
webPreferences: { contextIsolation: true, nodeIntegration: false, sandbox: true }
});
splashWindow.once('ready-to-show', () => {
if (splashWindow && !splashWindow.isDestroyed()) splashWindow.show();
});
splashWindow.on('closed', () => { splashWindow = null; });
splashWindow.loadFile(path.join(__dirname, 'splash.html'));
}

function closeSplashWindow() {
if (splashWindow && !splashWindow.isDestroyed()) {
const current = splashWindow;
splashWindow = null;
current.close();
}
}
let mobileSyncHttpServer = null;
const mobileSyncStore = new Map();

Expand Down Expand Up @@ -461,6 +497,7 @@ function createWindow() {
// Reveal window once first paint is completed and DOM is ready
mainWindow.once('ready-to-show', () => {
if (mainWindow) {
closeSplashWindow();
mainWindow.setFullScreen(true);
mainWindow.show();
mainWindow.focus();
Expand Down Expand Up @@ -1565,6 +1602,7 @@ app.on('second-instance', () => {
});

app.whenReady().then(() => {
createSplashWindow();
createWindow();

// Defer background language seed & backup folder readiness so the UI thread renders immediately
Expand Down
33 changes: 33 additions & 0 deletions electron/splash.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SOCDOF</title>
<style>
:root{color-scheme:dark;font-family:Inter,"Segoe UI",system-ui,sans-serif;background:#101116;color:#f5f6fa}
*{box-sizing:border-box}
html,body{width:100%;height:100%;margin:0;overflow:hidden}
body{display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at 50% 110%,rgba(74,87,190,.22),transparent 60%),#101116}
main{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:30px 34px;position:relative}
.logo{width:64px;height:64px;object-fit:contain;filter:drop-shadow(0 8px 24px rgba(90,120,255,.24));animation:breathe 2.8s ease-in-out infinite}
h1{font-size:22px;letter-spacing:.02em;font-weight:650;margin:17px 0 6px}
p{font-size:12px;color:#a5a9b8;margin:0 0 25px;letter-spacing:.015em}
.track{height:3px;width:100%;max-width:280px;border-radius:99px;background:#2b2d36;overflow:hidden}
.bar{height:100%;width:38%;border-radius:99px;background:linear-gradient(90deg,#6677f6,#9c8aff,#6caeff);animation:travel 1.5s cubic-bezier(.4,0,.2,1) infinite}
.footer{position:absolute;bottom:17px;font-size:10px;color:#646979;letter-spacing:.09em;text-transform:uppercase}
@keyframes travel{0%{transform:translateX(-115%)}100%{transform:translateX(370%)}}
@keyframes breathe{0%,100%{transform:scale(1);filter:drop-shadow(0 8px 20px rgba(90,120,255,.18))}50%{transform:scale(1.035);filter:drop-shadow(0 8px 27px rgba(110,120,255,.35))}}
@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important}.bar{width:65%}}
</style>
</head>
<body>
<main>
<img class="logo" src="../public/socdof_icon.png" alt="">
<h1>SOCDOF</h1>
<p>Der Arbeitsbereich wird vorbereitet …</p>
<div class="track" role="progressbar" aria-label="SOCDOF wird gestartet"><div class="bar"></div></div>
<div class="footer">Strudelcode · Yuri / Strudel</div>
</main>
</body>
</html>
Loading
Loading