diff --git a/assets/logos/farmcontroluninstaller.png b/assets/logos/farmcontroluninstaller.png new file mode 100644 index 0000000..9168a7d Binary files /dev/null and b/assets/logos/farmcontroluninstaller.png differ diff --git a/assets/uninstaller.ico b/assets/uninstaller.ico new file mode 100644 index 0000000..a2f4302 Binary files /dev/null and b/assets/uninstaller.ico differ diff --git a/packaging/windows/farmcontrol.nsi b/packaging/windows/farmcontrol.nsi index c2174ff..100882a 100644 --- a/packaging/windows/farmcontrol.nsi +++ b/packaging/windows/farmcontrol.nsi @@ -31,11 +31,15 @@ SilentInstall normal !define INSTALLER_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico" !endif +!ifndef UNINSTALLER_ICON + !define UNINSTALLER_ICON "${INSTALLER_ICON}" +!endif + !define MUI_ICON "${INSTALLER_ICON}" -!define MUI_UNICON "${INSTALLER_ICON}" +!define MUI_UNICON "${UNINSTALLER_ICON}" Icon "${INSTALLER_ICON}" -UninstallIcon "${INSTALLER_ICON}" +UninstallIcon "${UNINSTALLER_ICON}" BrandingText "Farm Control v${VERSION}-b${BUILD_NUMBER} Installer" diff --git a/scripts/build-windows-nsis.ps1 b/scripts/build-windows-nsis.ps1 index fdcf0ec..259a449 100644 --- a/scripts/build-windows-nsis.ps1 +++ b/scripts/build-windows-nsis.ps1 @@ -87,6 +87,12 @@ if (Test-Path $iconPath) { Write-Host "Using installer icon from $iconPath" } +$uninstallerIconPath = Join-Path $rootDir "assets\uninstaller.ico" +if (Test-Path $uninstallerIconPath) { + Copy-Item -LiteralPath $uninstallerIconPath -Destination (Join-Path $workDir "uninstaller.ico") -Force + Write-Host "Using uninstaller icon from $uninstallerIconPath" +} + $makensis = Find-Makensis $outputExePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputExe) $outputDir = Split-Path $outputExePath -Parent @@ -107,6 +113,10 @@ if (Test-Path (Join-Path $workDir "icon.ico")) { $makensisArgs += "/DINSTALLER_ICON=icon.ico" } +if (Test-Path (Join-Path $workDir "uninstaller.ico")) { + $makensisArgs += "/DUNINSTALLER_ICON=uninstaller.ico" +} + $makensisArgs += (Join-Path $workDir "farmcontrol.nsi") Push-Location $workDir diff --git a/scripts/pre-build.mjs b/scripts/pre-build.mjs index 0ed4382..c756a7a 100644 --- a/scripts/pre-build.mjs +++ b/scripts/pre-build.mjs @@ -66,6 +66,7 @@ const requiredIconPaths = [ path.join(rootDir, "assets/icon.png"), path.join(rootDir, "assets/icon.iconset/icon_256x256.png"), path.join(rootDir, "assets/installer.ico"), + path.join(rootDir, "assets/uninstaller.ico"), ]; if (buildEnv === "stable") { diff --git a/scripts/prepare-installer-icons.mjs b/scripts/prepare-installer-icons.mjs index 0dc2adb..503481d 100644 --- a/scripts/prepare-installer-icons.mjs +++ b/scripts/prepare-installer-icons.mjs @@ -9,6 +9,10 @@ const INSTALLER_SOURCE = path.join( rootDir, 'assets/logos/farmcontrolinstaller.png' ) +const UNINSTALLER_SOURCE = path.join( + rootDir, + 'assets/logos/farmcontroluninstaller.png' +) const MAC_ICONSET_ENTRIES = [ { name: 'icon_16x16.png', size: 16 }, @@ -38,6 +42,16 @@ async function writePng(filePath, sourceImage, size) { return png } +async function writeWindowsIco(sourceImage, icoPath) { + const icoPngs = [] + for (const size of WIN_ICO_SIZES) { + icoPngs.push(await resizePng(sourceImage, size)) + } + + await Bun.write(icoPath, await pngToIco(icoPngs)) + console.log(`prepare-installer-icons: wrote ${icoPath}`) +} + async function main() { if (!existsSync(INSTALLER_SOURCE)) { console.error( @@ -46,10 +60,24 @@ async function main() { process.exit(1) } - const sourceImage = await Jimp.read(INSTALLER_SOURCE) - if (sourceImage.width < 256 || sourceImage.height < 256) { + if (!existsSync(UNINSTALLER_SOURCE)) { + console.error( + `prepare-installer-icons: source image not found: ${UNINSTALLER_SOURCE}` + ) + process.exit(1) + } + + const installerImage = await Jimp.read(INSTALLER_SOURCE) + if (installerImage.width < 256 || installerImage.height < 256) { console.warn( - `prepare-installer-icons: source image is ${sourceImage.width}x${sourceImage.height}; recommend at least 256x256` + `prepare-installer-icons: installer source is ${installerImage.width}x${installerImage.height}; recommend at least 256x256` + ) + } + + const uninstallerImage = await Jimp.read(UNINSTALLER_SOURCE) + if (uninstallerImage.width < 256 || uninstallerImage.height < 256) { + console.warn( + `prepare-installer-icons: uninstaller source is ${uninstallerImage.width}x${uninstallerImage.height}; recommend at least 256x256` ) } @@ -63,21 +91,17 @@ async function main() { for (const entry of MAC_ICONSET_ENTRIES) { await writePng( path.join(iconsetDir, entry.name), - sourceImage, + installerImage, entry.size ) } - const icoPngs = [] - for (const size of WIN_ICO_SIZES) { - icoPngs.push(await resizePng(sourceImage, size)) - } - - const icoPath = path.join(assetsDir, 'installer.ico') - await Bun.write(icoPath, await pngToIco(icoPngs)) - console.log(`prepare-installer-icons: wrote ${iconsetDir}`) - console.log(`prepare-installer-icons: wrote ${icoPath}`) + await writeWindowsIco(installerImage, path.join(assetsDir, 'installer.ico')) + await writeWindowsIco( + uninstallerImage, + path.join(assetsDir, 'uninstaller.ico') + ) } main().catch((error) => {