Improve the installer, fix context menu on Windows, add CI workflows

This commit is contained in:
2026-09-02 23:03:07 +03:00
Unverified
parent 529e090b25
commit 33f5ac1a1f
66 changed files with 3384 additions and 768 deletions
+31 -6
View File
@@ -8,12 +8,9 @@ if /I "%1"=="sync" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" arm64
if errorlevel 1 exit /b 1
set "JAVA_HOME_17=C:\Program Files\Eclipse Adoptium\jdk-17.0.20.8-hotspot"
set "JAVA_HOME_21=C:\Program Files\Eclipse Adoptium\jdk-21.0.10.7-hotspot"
for /d %%D in ("C:\Program Files\Eclipse Adoptium\jdk-17*") do set "JAVA_HOME_17=%%D"
for /d %%D in ("C:\Program Files\Eclipse Adoptium\jdk-21*") do set "JAVA_HOME_21=%%D"
set "JAVA_HOME=%JAVA_HOME_21%"
set "FROMCHAT_PACKAGING_JDK=%JAVA_HOME_17%"
call "%~dp0ensure-windows-arm64-jdk.cmd"
if errorlevel 1 exit /b 1
set "FROMCHAT_PACKAGING_JDK=%JAVA_HOME%"
set "PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32\config\systemprofile\.cargo\bin;%PATH%"
cd /d C:\FromChat\app
if exist gradle\gradle-daemon-jvm.properties del /f gradle\gradle-daemon-jvm.properties
@@ -26,6 +23,31 @@ if /I "%1"=="rust" (
exit /b %ERRORLEVEL%
)
if /I "%1"=="beta" (
call "%~dp0sync-windows-vm.cmd" all
if errorlevel 1 exit /b 1
if exist gradle\gradle-daemon-jvm.properties del /f gradle\gradle-daemon-jvm.properties
if /I "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
if exist app\desktop\build\compose\tmp\main\runtime rmdir /s /q app\desktop\build\compose\tmp\main\runtime
if exist app\desktop\build\compose\binaries\main\app rmdir /s /q app\desktop\build\compose\binaries\main\app
if not exist app\desktop\build\prebuilt\windows-x64\app\FromChat\FromChat.exe (
echo WARNING: No x64 prebuilt at app\desktop\build\prebuilt\windows-x64\app\FromChat
echo Installer will be ARM64-only. Run scripts\stage-windows-x64-prebuilt.cmd first.
)
)
gradlew.bat :app:desktop:packageBetaWindows -PbetaDesktop --no-daemon
if errorlevel 1 exit /b 1
call "%~dp0copy-installers-to-desktop.cmd" beta
exit /b %ERRORLEVEL%
)
if /I "%1"=="install" (
call "%~dp0build-windows-vm.cmd" beta
if errorlevel 1 exit /b 1
call "%~dp0run-beta-installer.cmd"
exit /b %ERRORLEVEL%
)
if /I "%1"=="pack" (
call "%~dp0sync-windows-vm.cmd" rust
if errorlevel 1 exit /b 1
@@ -48,6 +70,9 @@ if /I "%1"=="gradle" (
echo Usage: build-windows-vm.cmd sync [all^|rust^|scripts^|gradle]
echo build-windows-vm.cmd rust ^(sync windows-setup, then cargo build^)
echo build-windows-vm.cmd beta ^(debug app + beta setup EXE, no ProGuard^)
echo build-windows-vm.cmd install ^(beta build + upgrade install + launch^)
echo Place x64 app-image: scripts\stage-windows-x64-prebuilt.cmd ^<path^>
echo build-windows-vm.cmd pack ^(sync, rust, packSetupOnly — fast UI loop^)
echo build-windows-vm.cmd gradle ^(sync, full packageReleaseWindows, copy to Desktop^)
exit /b 1
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
VERSION="${1:?usage: ci-set-version.sh <version>}"
VERSION_CODE="$(printf '%s' "$VERSION" | sed 's/[^0-9]//g')"
if [[ -z "$VERSION_CODE" ]]; then
VERSION_CODE=1
fi
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
GRADLE_FILE="$ROOT/build.gradle.kts"
sed -i.bak "s/extra\\[\"versionName\"\\] = \"[^\"]*\"/extra[\"versionName\"] = \"$VERSION\"/" "$GRADLE_FILE"
sed -i.bak "s/extra\\[\"versionCode\"\\] = [0-9]*/extra[\"versionCode\"] = $VERSION_CODE/" "$GRADLE_FILE"
rm -f "$GRADLE_FILE.bak"
echo "versionName=$VERSION versionCode=$VERSION_CODE"
+47 -7
View File
@@ -3,10 +3,13 @@ setlocal EnableExtensions EnableDelayedExpansion
rem Copy packaged Windows installer to the logged-in user's Desktop.
rem prlctl exec runs as SYSTEM, so do not rely on %%USERPROFILE%%.
rem
rem copy-installers-to-desktop.cmd — release setup only
rem copy-installers-to-desktop.cmd beta — beta2 setup only (cleans desktop)
set "DIST=C:\FromChat\app\app\desktop\build\distributions\release"
set "WIN_DESKTOP="
set "COPIED=0"
set "MODE=%~1"
if not exist "%DIST%\" (
echo WARNING: Release output folder missing: %DIST%
@@ -34,6 +37,23 @@ if not defined WIN_DESKTOP (
call :kill_running_installers
if /I "%MODE%"=="beta" (
call :clean_desktop_installers
set "COPIED=0"
for %%F in ("%DIST%\FromChat-Setup-*-beta2.exe") do (
if exist "%%F" (
call :copy_installer "%%~fF" "%WIN_DESKTOP%"
if errorlevel 1 exit /b 1
set "COPIED=1"
)
)
if "!COPIED!"=="0" (
echo ERROR: No FromChat-Setup-*-beta2.exe found in %DIST%
exit /b 1
)
exit /b 0
)
for %%F in ("%DIST%\FromChat-Portable-*.exe") do (
if exist "%%F" (
del /F /Q "%%F" >nul 2>&1
@@ -48,24 +68,44 @@ for %%F in ("%WIN_DESKTOP%\FromChat-Portable-*.exe") do (
)
)
set "COPIED=0"
for %%F in ("%DIST%\FromChat-Setup-*.exe") do (
if exist "%%F" (
call :copy_installer "%%~fF" "%WIN_DESKTOP%"
if errorlevel 1 exit /b 1
set "COPIED=1"
echo %%~nxF | findstr /i /c:"beta" >nul
if errorlevel 1 (
if exist "%%F" (
call :copy_installer "%%~fF" "%WIN_DESKTOP%"
if errorlevel 1 exit /b 1
set "COPIED=1"
)
)
)
if "!COPIED!"=="0" (
echo WARNING: No FromChat-Setup-*.exe found in %DIST%
echo WARNING: No release FromChat-Setup-*.exe found in %DIST%
)
exit /b 0
:clean_desktop_installers
echo Cleaning Desktop installer clutter...
for %%F in ("%WIN_DESKTOP%\FromChat-Setup*.exe") do (
if exist "%%F" (
del /F /Q "%%F" >nul 2>&1
echo Removed %%~nxF
)
)
for %%F in ("%WIN_DESKTOP%\FromChat-Portable*.exe") do (
if exist "%%F" (
del /F /Q "%%F" >nul 2>&1
echo Removed %%~nxF
)
)
exit /b 0
:kill_running_installers
echo Stopping running FromChat installer processes...
powershell -NoProfile -Command ^
"$names = @('fromchat-setup','FromChat-Setup*','FromChat-Portable*');" ^
"$names = @('fromchat-setup','FromChat-Installer','FromChat-Setup*','FromChat-Portable*');" ^
"foreach ($n in $names) { Get-Process -Name $n -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue }" ^
2>nul
ping -n 2 127.0.0.1 >nul
+68
View File
@@ -0,0 +1,68 @@
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Ensure a native Windows ARM64 JDK is available for Gradle/jpackage builds.
rem x64 JDKs under emulation package x64 Skiko/JavaFX natives and break the desktop app.
if /I not "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
if /I not "%PROCESSOR_ARCHITEW6432%"=="ARM64" (
exit /b 0
)
)
set "JDK_ROOT=C:\Program Files\Eclipse Adoptium"
set "JDK_HOME="
set "JDK_FALLBACK=%LOCALAPPDATA%\Programs\Eclipse Adoptium\jdk-21-arm64"
for /d %%D in ("%JDK_ROOT%\jdk-*-arm64") do (
if exist "%%D\bin\java.exe" set "JDK_HOME=%%D"
)
for /d %%D in ("%JDK_ROOT%\jdk-*aarch64*") do (
if exist "%%D\bin\java.exe" set "JDK_HOME=%%D"
)
if not defined JDK_HOME (
for /d %%D in ("%JDK_ROOT%\jdk-*") do (
if not defined JDK_HOME if exist "%%D\bin\java.exe" (
"%%D\bin\java.exe" -XshowSettings:properties -version 2>&1 | findstr /i /c:"os.arch = aarch64" >nul
if not errorlevel 1 set "JDK_HOME=%%D"
)
)
)
if defined JDK_HOME goto :verify
echo Installing Temurin JDK 21 for Windows ARM64...
set "TMP_ZIP=%TEMP%\fromchat-temurin21-arm64.zip"
set "TMP_DIR=%TEMP%\fromchat-temurin21-arm64"
set "JDK_HOME=%JDK_ROOT%\jdk-21.0.12.101-hotspot-arm64"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$zip='%TMP_ZIP%'; $tmp='%TMP_DIR%'; $dest='%JDK_HOME%'; $fallback='%JDK_FALLBACK%';" ^
"try { New-Item -ItemType Directory -Force -Path $dest | Out-Null } catch { $dest = $fallback; New-Item -ItemType Directory -Force -Path $dest | Out-Null };" ^
"Invoke-WebRequest -Uri 'https://api.adoptium.net/v3/binary/latest/21/ga/windows/aarch64/jdk/hotspot/normal/eclipse?project=jdk' -OutFile $zip;" ^
"if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp };" ^
"Expand-Archive -Path $zip -DestinationPath $tmp -Force;" ^
"$inner = Get-ChildItem $tmp -Directory | Select-Object -First 1;" ^
"Copy-Item -Path (Join-Path $inner.FullName '*') -Destination $dest -Recurse -Force"
if not exist "%JDK_HOME%\bin\java.exe" set "JDK_HOME=%JDK_FALLBACK%"
if not exist "%JDK_HOME%\bin\java.exe" (
echo ERROR: Failed to install ARM64 JDK under %JDK_ROOT%
exit /b 1
)
:verify
"%JDK_HOME%\bin\java.exe" -XshowSettings:properties -version 2>&1 | findstr /i /c:"os.arch = aarch64" >nul
if errorlevel 1 (
echo ERROR: %JDK_HOME% is not an ARM64 JDK ^(os.arch must be aarch64^).
exit /b 1
)
set "JAVA_HOME=%JDK_HOME%"
set "FROMCHAT_PACKAGING_JDK=%JDK_HOME%"
set "PATH=%JDK_HOME%\bin;%PATH%"
echo Using ARM64 JDK: %JDK_HOME%
endlocal & set "JAVA_HOME=%JAVA_HOME%" & set "FROMCHAT_PACKAGING_JDK=%FROMCHAT_PACKAGING_JDK%" & set "PATH=%PATH%"
exit /b 0
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -euo pipefail
VERSION="${1:?usage: package-ios-ipa.sh <version> <output-dir>}"
OUT_DIR="${2:?usage: package-ios-ipa.sh <version> <output-dir>}"
VERSION_CODE="$(printf '%s' "$VERSION" | sed 's/[^0-9]//g')"
[[ -z "$VERSION_CODE" ]] && VERSION_CODE=1
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
IOS_PROJECT_DIR="$ROOT/app/ios"
BUILD_DIR="$ROOT/build/ios"
PLIST_PATH="$IOS_PROJECT_DIR/iosApp/Info.plist"
IPA_NAME="FromChat-$VERSION-ios.ipa"
IPA_PATH="$OUT_DIR/$IPA_NAME"
export DEVELOPER_DIR="${DEVELOPER_DIR:-/Applications/Xcode.app/Contents/Developer}"
if [[ ! -d "$DEVELOPER_DIR" ]]; then
DEVELOPER_DIR="$(xcode-select -p)"
export DEVELOPER_DIR
fi
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSION_CODE" "$PLIST_PATH" || true
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" "$PLIST_PATH" || true
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR" "$OUT_DIR"
xcodebuild \
-project "$IOS_PROJECT_DIR/iosApp.xcodeproj" \
-scheme iosApp \
-configuration Release \
-sdk iphoneos \
-destination 'generic/platform=iOS' \
-derivedDataPath "$BUILD_DIR" \
CODE_SIGNING_ALLOWED=NO \
CODE_SIGNING_REQUIRED=NO \
clean build
APP_BUNDLE_PATH="$(find "$BUILD_DIR/Build/Products/Release-iphoneos" -name '*.app' -type d | head -n 1)"
if [[ -z "$APP_BUNDLE_PATH" ]]; then
echo "iOS .app bundle not found" >&2
exit 1
fi
PAYLOAD_STAGE="$BUILD_DIR/ipa_stage"
rm -rf "$PAYLOAD_STAGE"
mkdir -p "$PAYLOAD_STAGE/Payload"
cp -R "$APP_BUNDLE_PATH" "$PAYLOAD_STAGE/Payload/"
( cd "$PAYLOAD_STAGE" && zip -qr "$IPA_PATH" Payload )
rm -rf "$PAYLOAD_STAGE"
git -C "$ROOT" checkout -- "$PLIST_PATH" >/dev/null 2>&1 || true
echo "Wrote $IPA_PATH"
+54
View File
@@ -0,0 +1,54 @@
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "WIN_DESKTOP="
for /f "skip=1 tokens=1" %%U in ('query user 2^>nul') do (
if not defined LOGON set "LOGON=%%U"
)
if defined LOGON set "WIN_DESKTOP=C:\Users\%LOGON%\Desktop"
if not exist "%WIN_DESKTOP%\" (
for /d %%D in ("C:\Users\*") do (
if not defined WIN_DESKTOP (
echo %%~nxD | findstr /i /x "Public Default DefaultAccount WsiAccount" >nul
if errorlevel 1 if exist "%%D\Desktop\" set "WIN_DESKTOP=%%D\Desktop"
)
)
)
if not defined WIN_DESKTOP (
echo ERROR: Could not resolve Desktop path
exit /b 1
)
set "INSTALLER="
for /f "delims=" %%F in ('dir /b /od "%WIN_DESKTOP%\FromChat-Setup-*-beta2.exe" 2^>nul') do set "INSTALLER=%WIN_DESKTOP%\%%F"
if not defined INSTALLER (
set "DIST=C:\FromChat\app\app\desktop\build\distributions\release"
for /f "delims=" %%F in ('dir /b /od "%DIST%\FromChat-Setup-*-beta2.exe" 2^>nul') do set "INSTALLER=%DIST%\%%F"
)
if not exist "%INSTALLER%" (
echo ERROR: No FromChat-Setup-*-beta2.exe on Desktop or in dist folder
exit /b 1
)
echo Launching installer: %INSTALLER%
set "TASK=FromChatBetaInstall"
schtasks /delete /tn "%TASK%" /f >nul 2>&1
for /f "tokens=1-2 delims=:" %%H in ("%TIME%") do set "ST=%%H:%%M"
set "ST=%ST: =0%"
if defined LOGON (
schtasks /create /tn "%TASK%" /tr "\"%INSTALLER%\" --upgrade --launch" /sc once /st %ST% /ru "%LOGON%" /it /f
) else (
schtasks /create /tn "%TASK%" /tr "\"%INSTALLER%\" --upgrade --launch" /sc once /st %ST% /f
)
schtasks /run /tn "%TASK%" >nul
ping -n 3 127.0.0.1 >nul
schtasks /delete /tn "%TASK%" /f >nul 2>&1
echo Installer started.
exit /b 0
+19
View File
@@ -0,0 +1,19 @@
@echo off
setlocal EnableExtensions
if "%~1"=="" (
echo Usage: stage-windows-x64-prebuilt.cmd ^<path-to-FromChat-app-image^>
echo Example: stage-windows-x64-prebuilt.cmd C:\Downloads\FromChat
exit /b 1
)
set "SRC=%~1"
if not exist "%SRC%\FromChat.exe" (
echo Expected FromChat.exe in %SRC%
exit /b 1
)
cd /d "%~dp0.."
set "DEST=app\desktop\build\prebuilt\windows-x64\app\FromChat"
if exist app\desktop\build\prebuilt\windows-x64 rmdir /s /q app\desktop\build\prebuilt\windows-x64
mkdir "%DEST%"
xcopy /E /I /Y "%SRC%\*" "%DEST%\"
echo Staged x64 app image at %DEST%
exit /b 0