mirror of
https://github.com/storytold/craft-launcher.git
synced 2026-10-22 18:22:10 +00:00
A native Rust/egui launcher for the 12 Craft Apps (7 classic + 5 new). - Grid (icon cards) or sortable table view, filters and search - Status per app: available, installed and up to date, or update available with version and release date - Installs where each OS keeps apps, from the official release packages: /Applications (DMG), Program Files (MSI), deb/rpm via the system package manager (Flatpak/AppImage fallback), /usr/local on FreeBSD - Detects apps installed by hand; updates keep the installed format - Every download verified against its published SHA-256; running apps are never replaced - Tray/menu-bar mode, start at login, one notification per new version - GitHub API with ETag cache, falling back to release pages when rate-limited; release source is pluggable for a future catalog API - Web build lists latest releases with per-platform downloads - Packaging and release workflows for macOS, Windows (x64/x86/arm64), Linux (x86_64/aarch64), FreeBSD and web Co-Authored-By: Claude Opus 5.5 <[email protected]>
48 lines
2.0 KiB
PowerShell
48 lines
2.0 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Check MSI icon references without building or installing ArtCraft Launcher.
|
|
|
|
.DESCRIPTION
|
|
Windows Installer caches each <Icon> under its Id as a file name, so a shortcut icon Id needs an
|
|
.exe or .ico extension (ICE50 for advertised shortcuts; extensionless identifiers can display a
|
|
generic document icon even when the ICO data and application are valid). Also checks that every
|
|
shortcut and ARPPRODUCTICON reference an <Icon> that exists, and that the Start Menu shortcut
|
|
carries the app's AppUserModelID (toast notifications need it).
|
|
#>
|
|
param(
|
|
[string] $WxsPath = (Join-Path $PSScriptRoot 'artcraft-launcher.wxs')
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
$AppId = 'ai.storyteller.artcraft-launcher'
|
|
[xml] $Wxs = Get-Content -LiteralPath $WxsPath -Raw
|
|
$Ns = [Xml.XmlNamespaceManager]::new($Wxs.NameTable)
|
|
$Ns.AddNamespace('w', 'http://wixtoolset.org/schemas/v4/wxs')
|
|
$Icons = @{}
|
|
foreach ($icon in $Wxs.SelectNodes('//w:Icon', $Ns)) {
|
|
$Icons[$icon.GetAttribute('Id')] = $icon
|
|
}
|
|
|
|
$shortcuts = $Wxs.SelectNodes('//w:Shortcut', $Ns)
|
|
if ($shortcuts.Count -eq 0) { throw 'No <Shortcut> in the MSI.' }
|
|
foreach ($shortcut in $shortcuts) {
|
|
$id = $shortcut.GetAttribute('Id')
|
|
$iconId = $shortcut.GetAttribute('Icon')
|
|
if (-not $Icons.ContainsKey($iconId)) {
|
|
throw "Shortcut '$id' references missing icon '$iconId'."
|
|
}
|
|
$iconExtension = [IO.Path]::GetExtension($iconId)
|
|
if ($iconExtension -notin '.exe', '.ico') {
|
|
throw "Shortcut '$id' icon '$iconId' must have an .exe or .ico extension (ICE50)."
|
|
}
|
|
$aumid = $shortcut.SelectSingleNode('w:ShortcutProperty[@Key="System.AppUserModel.ID"]', $Ns)
|
|
if (-not $aumid -or $aumid.GetAttribute('Value') -ne $AppId) {
|
|
throw "Shortcut '$id' must set System.AppUserModel.ID to $AppId."
|
|
}
|
|
}
|
|
|
|
$arpIcon = $Wxs.SelectSingleNode('//w:Property[@Id="ARPPRODUCTICON"]', $Ns)
|
|
if ($arpIcon -and -not $Icons.ContainsKey($arpIcon.GetAttribute('Value'))) {
|
|
throw "ARPPRODUCTICON references missing icon '$($arpIcon.GetAttribute('Value'))'."
|
|
}
|
|
Write-Output 'Windows shortcut icon references ok'
|