补齐移动壳启动视觉配置

复用真实品牌图标配置 Expo 启动页

复用透明品牌图标配置 Android adaptive icon

校验启动页、adaptive icon 与品牌底色不漂移

更新原生壳方案和团队决策记录
This commit is contained in:
2026-06-18 08:46:35 +08:00
parent 01a346a9b0
commit 1ced5f2a0e
4 changed files with 51 additions and 0 deletions

View File

@@ -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",

View File

@@ -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) =>

View File

@@ -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 iconExpo 移动壳启动页和 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固定玩法在各宿主中读取同一作品数据和运行态 snapshotAI sandbox 无法直接调用 HostBridgeTauri release 不允许任意远端页面调用桌面命令。
- 关联文档:`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md``docs/【前端架构】宿主壳能力统一协议-2026-06-17.md`

View File

@@ -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宿主能力扩展
- 移动端接入系统分享、推送、原生登录和渠道支付。