From 1ced5f2a0ea2b9dd092304ad8f200b7f0c2006b6 Mon Sep 17 00:00:00 2001 From: kdletters Date: Thu, 18 Jun 2026 08:46:35 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E9=BD=90=E7=A7=BB=E5=8A=A8=E5=A3=B3?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E8=A7=86=E8=A7=89=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 复用真实品牌图标配置 Expo 启动页 复用透明品牌图标配置 Android adaptive icon 校验启动页、adaptive icon 与品牌底色不漂移 更新原生壳方案和团队决策记录 --- apps/mobile-shell/app.json | 9 +++++ apps/mobile-shell/scripts/check-config.mjs | 39 +++++++++++++++++++ .../shared-memory/decision-log.md | 1 + ...ExpoReactNative与Tauri宿主壳方案-2026-06-17.md | 2 + 4 files changed, 51 insertions(+) diff --git a/apps/mobile-shell/app.json b/apps/mobile-shell/app.json index bc5cc22a..3c49c05d 100644 --- a/apps/mobile-shell/app.json +++ b/apps/mobile-shell/app.json @@ -7,6 +7,11 @@ "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "automatic", + "splash": { + "image": "./assets/icon.png", + "resizeMode": "contain", + "backgroundColor": "#fffdf9" + }, "assetBundlePatterns": [ "**/*" ], @@ -37,6 +42,10 @@ "android": { "package": "world.genarrative.mobile", "versionCode": 1, + "adaptiveIcon": { + "foregroundImage": "./assets/icon.png", + "backgroundColor": "#fffdf9" + }, "intentFilters": [ { "action": "VIEW", diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs index 00d9f918..eebd4d29 100644 --- a/apps/mobile-shell/scripts/check-config.mjs +++ b/apps/mobile-shell/scripts/check-config.mjs @@ -19,6 +19,7 @@ const packagePath = new URL('../package.json', import.meta.url); const packageConfig = JSON.parse(fs.readFileSync(packagePath, 'utf8')); const iconPath = new URL('../assets/icon.png', import.meta.url); const icon = PNG.sync.read(fs.readFileSync(iconPath)); +const brandBackgroundColor = '#fffdf9'; const productionSourceRoots = [ new URL('../App.tsx', import.meta.url), new URL('../app.json', import.meta.url), @@ -107,6 +108,24 @@ function assertNoDevScaffoldTerms(files) { } } +function countAlphaPixels(png) { + let transparent = 0; + let translucent = 0; + let opaque = 0; + for (let index = 3; index < png.data.length; index += 4) { + const alpha = png.data[index]; + if (alpha === 0) { + transparent += 1; + } else if (alpha === 255) { + opaque += 1; + } else { + translucent += 1; + } + } + + return { transparent, translucent, opaque }; +} + assertNoDevScaffoldTerms( productionSourceRoots.flatMap((root) => collectProductionSourceFiles(root)), ); @@ -177,6 +196,19 @@ if (icon.width < 512 || icon.height < 512) { throw new Error('mobile shell icon must be a production-size brand asset'); } +const iconAlpha = countAlphaPixels(icon); +if (iconAlpha.transparent === 0 || iconAlpha.opaque === 0) { + throw new Error('mobile shell adaptive icon foreground must use the real transparent brand asset'); +} + +if ( + appConfig.splash?.image !== './assets/icon.png' || + appConfig.splash?.resizeMode !== 'contain' || + appConfig.splash?.backgroundColor !== brandBackgroundColor +) { + throw new Error('mobile shell splash must use the real brand icon and brand background'); +} + if (!appConfig.ios?.associatedDomains?.includes('applinks:app.genarrative.world')) { throw new Error('mobile shell iOS associated domain is missing'); } @@ -197,6 +229,13 @@ if (appConfig.android?.versionCode !== 1) { throw new Error('mobile shell Android versionCode must start at 1'); } +if ( + appConfig.android?.adaptiveIcon?.foregroundImage !== './assets/icon.png' || + appConfig.android?.adaptiveIcon?.backgroundColor !== brandBackgroundColor +) { + throw new Error('mobile shell Android adaptive icon must use the real brand icon and brand background'); +} + const androidFilter = appConfig.android?.intentFilters?.find((filter) => filter?.data?.some( (entry) => diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 34efa681..613743c5 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -53,6 +53,7 @@ - 2026-06-18 Tauri 单实例:桌面壳启用 `tauri-plugin-single-instance` 并要求该插件最先注册;重复启动 App 时第二实例退出,只唤醒、取消最小化并聚焦已有主窗口,不把第二实例 argv / cwd / 深链内容作为事件透传给 H5。桌面深链后续如需接入,必须先定义受控 URL 归一和宿主边界,不能借单实例回调直接开放任意启动参数。 - 2026-06-18 桌面壳安装包身份:Tauri 桌面壳的产品名固定为 `Genarrative`,应用 identifier 固定为 `world.genarrative.desktop`,Tauri 配置、`apps/desktop-shell/package.json` 与 Cargo package 版本统一为 `0.1.0`;Release 主窗口只加载打包的 `index.html` 和根 `dist` H5 资产,dev URL 只指向本机 Vite 调试入口。桌面壳 CSP 保持 `script-src 'self'`,不得加入 `unsafe-eval`、`tauri:` 或 `file:`,也不得在没有真实端点、签名密钥和发布流程前配置 updater;检查脚本会拒绝包身份、版本、CSP 或 updater 约束漂移。 - 2026-06-18 壳生产代码禁用临时替身:Expo 与 Tauri 壳的生产源码和配置不得出现 mock / fake / placeholder / stub / TODO / FIXME 以及对应中文脚手架词;测试文件仍可使用 mock。两端壳配置检查会扫描生产入口、配置和壳实现,防止把临时替身、占位文案或伪实现带进可分发壳。 +- 2026-06-18 移动壳启动页与 adaptive icon:Expo 移动壳启动页和 Android adaptive icon 复用现有真实品牌图标 `apps/mobile-shell/assets/icon.png`,背景色固定为 H5 壳根背景 `#fffdf9`。该 PNG 是 1024x1024 RGBA 透明前景品牌资产,不新增占位图;配置检查会校验图标尺寸、透明像素、splash 和 adaptive icon 指向,避免后续换成非品牌或占位素材。 - 影响范围:`src/services/host-bridge/`、未来 `apps/mobile-shell/`、未来 `apps/desktop-shell/`、移动端支付 / 分享 / 深链 / 推送、桌面端系统能力、AI H5 sandbox 的 GameBridge 边界。 - 验证方式:普通浏览器、小程序、Expo 壳、Tauri 壳都能返回正确 `getHostRuntime()`;未支持能力能回退 H5;固定玩法在各宿主中读取同一作品数据和运行态 snapshot;AI sandbox 无法直接调用 HostBridge;Tauri release 不允许任意远端页面调用桌面命令。 - 关联文档:`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`、`docs/【前端架构】宿主壳能力统一协议-2026-06-17.md`。 diff --git a/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md b/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md index 68d2fc31..6b8c7f76 100644 --- a/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md +++ b/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md @@ -309,6 +309,8 @@ GameBridge 禁止: 2026-06-18 追加:两端壳的生产源码和配置禁止出现 mock / fake / placeholder / stub / TODO / FIXME 以及对应中文脚手架词;测试文件仍可使用 `vi.mock` 或等价测试替身。`apps/mobile-shell/scripts/check-config.mjs` 与 `apps/desktop-shell/scripts/check-config.mjs` 会扫描各自生产入口、配置和壳实现,防止把临时替身或占位文案带进可分发壳。 +2026-06-18 追加:移动壳启动页与 Android adaptive icon 复用现有真实品牌图标 `apps/mobile-shell/assets/icon.png`,背景色固定为 H5 壳根背景 `#fffdf9`。该 PNG 是 1024x1024 RGBA 透明前景品牌资产,不新增占位图;Expo `splash` 使用同一图标 `contain` 展示,Android `adaptiveIcon.foregroundImage` 使用同一透明前景图,`check-config.mjs` 会校验图标尺寸、透明像素、启动页和 adaptive icon 配置。 + ### Phase 4:宿主能力扩展 - 移动端接入系统分享、推送、原生登录和渠道支付。