diff --git a/installer/README.md b/installer/README.md index 098363a..4349463 100644 --- a/installer/README.md +++ b/installer/README.md @@ -66,6 +66,8 @@ Actions builds Linux x64/ARM64, Windows x64, and macOS Intel/Apple Silicon. macO The titlebar and application icons share the pixel logo. Windows builds embed the ICO in the EXE; macOS packaging uses the system `iconutil` to generate and configure `.icns`. On Linux, run `bash install-desktop-entry.sh` from the extracted archive to register an icon-bearing entry in the current user's application menu. The entry points to that directory; rerun the script after moving it. +Installer archives do not include a separate `assets` directory. The UI logo is embedded in the executable; the Linux registration script embeds its menu icon, while macOS keeps its application icon inside the `.app` bundle. + Automated tests and Actions builds validate software and artifacts. Discovery, login, permissions, update, rollback, and uninstall still need acceptance testing on actual computers and Frame hardware. Discovery queries `frame.local` mDNS address records directly. It does not require an advertised SSH service or system DNS support for `.local`. Run the same discovery logic independently for diagnosis: diff --git a/installer/README.zh-CN.md b/installer/README.zh-CN.md index af1bc2c..a5a2a85 100644 --- a/installer/README.zh-CN.md +++ b/installer/README.zh-CN.md @@ -66,6 +66,8 @@ Actions 构建 Linux x64/ARM64、Windows x64、macOS Intel/Apple Silicon。macOS 安装器标题栏和应用图标使用统一的像素 Logo。Windows 构建将 ICO 嵌入 EXE,macOS 打包使用系统 `iconutil` 生成并配置 `.icns`。Linux 解压后可在解压目录执行 `bash install-desktop-entry.sh`,把带图标的入口注册到当前用户的应用菜单;入口指向该目录,移动后需重新执行脚本。 +安装器压缩包不包含独立的 `assets` 目录。界面 Logo 内嵌在可执行文件中,Linux 注册脚本内嵌菜单图标,macOS 的应用图标保存在 `.app` 内部。 + 所有自动测试和 Actions 构建只能验证软件及产物;仍需在真实电脑和 Frame 上完成扫描、登录、权限、升级回滚及卸载验收。 扫描会直接查询 `frame.local` 的 mDNS 地址记录,不要求设备广播 SSH 服务,也不依赖电脑的系统 DNS 支持 `.local`。可单独运行与界面相同的发现逻辑进行诊断: diff --git a/installer/install-desktop-entry.sh b/installer/install-desktop-entry.sh index ff738b8..956cf79 100644 --- a/installer/install-desktop-entry.sh +++ b/installer/install-desktop-entry.sh @@ -3,7 +3,7 @@ set -euo pipefail base=$(cd -- "$(dirname -- "$0")" && pwd) python3 - "$base" <<'PY' -import os, pathlib, shutil +import os, pathlib base = pathlib.Path(__import__('sys').argv[1]) binary = base / 'framely-installer' if not binary.is_file(): @@ -13,7 +13,10 @@ apps = data / 'applications' icons = data / 'icons/hicolor/scalable/apps' apps.mkdir(parents=True, exist_ok=True) icons.mkdir(parents=True, exist_ok=True) -shutil.copy2(base / 'assets/branding/framely-app-icon.svg', icons / 'org.framely.installer.svg') +icon = None # Embedded by tools/package-installer.py. +if icon is None: + icon = (base.parent / 'assets/branding/framely-app-icon.svg').read_bytes() +(icons / 'org.framely.installer.svg').write_bytes(icon) # Desktop entries parse backslash escapes before parsing the quoted Exec value. quoted = str(binary).replace('%', '%%').replace('\\', '\\\\') for character in ('"', '`', '$'): diff --git a/tools/package-installer.py b/tools/package-installer.py index 695802e..0eb7935 100644 --- a/tools/package-installer.py +++ b/tools/package-installer.py @@ -39,11 +39,13 @@ with __import__('tempfile').TemporaryDirectory() as temp: shutil.copy2(binary, stage / exe) if not platform.startswith('windows'): (stage / exe).chmod(0o755) - shutil.copy2(root / 'installer/install-desktop-entry.sh', stage / 'install-desktop-entry.sh') + desktop_script = (root / 'installer/install-desktop-entry.sh').read_text() + marker = 'icon = None # Embedded by tools/package-installer.py.' + if desktop_script.count(marker) != 1: + raise ValueError('Desktop registration script is missing its icon marker') + icon = (root / 'assets/branding/framely-app-icon.svg').read_bytes() + (stage / 'install-desktop-entry.sh').write_text(desktop_script.replace(marker, f'icon = {icon!r}')) (stage / 'install-desktop-entry.sh').chmod(0o755) - (stage / 'assets/branding').mkdir(parents=True) - for asset in ('framely-logo.svg', 'framely-logo-light.svg', 'framely-app-icon.svg', 'framely-app-icon.png', 'framely.ico'): - shutil.copy2(root / 'assets/branding' / asset, stage / 'assets/branding' / asset) shutil.copy2(root / 'installer/README.md', stage / 'README.md') shutil.copy2(root / 'installer/README.zh-CN.md', stage / 'README.zh-CN.md') shutil.copy2(root / 'LICENSE', stage / 'LICENSE')