T3 Code 移动应用
NOTE
要从 App Store 或 Google Play 安装已发布的应用,请参阅移动应用。本指南介绍如何从源码构建。
快速开始
NOTE
它使用原生模块,因此不支持 Expo Go。你需要使用 Expo Dev Client。
此应用有三种变体:
development:Expo 开发客户端,可作为T3 Code Dev并行安装preview:持久的内部预览构建,可作为T3 Code Preview并行安装production:商店/发布构建,名称为T3 Code
请从 apps/mobile 运行命令。
T3 Connect 是可选的,在全新克隆中处于禁用状态。公共配置应放在仓库根目录的 .env 或 .env.local 中,而不是 apps/mobile/.env 文件。参见 ../../.env.example。
开发
进行模拟器、仿真器或 Android 手机开发时,先启动或连接一台设备,然后在启动 Metro 之前安装与此次检出匹配的原生客户端:
vp run mobile:install ios [simulator-udid]
# Or: vp run mobile:install android [emulator-or-phone-serial]
vp run dev:client当恰好有一台设备已启动或已连接时,可以省略设备参数。该辅助工具会将此次检出的 Expo 指纹及已安装的二进制文件与它上一次的安装记录比较,并复用匹配的客户端。否则,它会依次从 ~/.cache/t3code/native-clients/artifacts、再从共享任务缓存安装该指纹对应的构建,只有两者都没有时才进行构建。构建会在 Mobile Dev Client 工作流中运行(Blacksmith 运行器带有已预热的 Gradle 与 ccache 状态,iOS 使用 macOS 运行器),条件是 gh 可以在 pingdotgg/t3code 上分派工作流且 HEAD 已经推送;辅助工具会等待共享缓存中的客户端。否则,或者当 HEAD 缺少你的原生修改,或设置了 T3_NATIVE_CLIENT_BUILD=local 时,它会在本机构建。main 的客户端会在每次原生更改时于该处构建,因此大多数检出都能命中。一份 iOS 模拟器构建可供所有 iPhone 和 iPad 模拟器使用;每个 ABI(x86_64 或 arm64-v8a)一份 APK 可供该 ABI 的所有仿真器和手机使用。构建输出写入它打印出的日志文件(T3_NATIVE_CLIENT_VERBOSE=1 则会改为流式输出)。当你的任务缓存登录(bash infra/task-cache/install.sh)具有写入权限时,构建会再共享回去。T3_NATIVE_CLIENT_CACHE=read 会跳过上传,off 会跳过共享缓存。实体 iPhone 仍使用 vp run ios:dev。
--session <name> 会安装到在别处打开的智能体设备会话中,例如设备池或云端模拟器,而不是本地设备:vp run mobile:install android --session pool-1 --metro http://<this-machine>:8081. It uses only the cached build (x86_64 by default; --abi 用于 ARM),当还没有任何机器构建过此指纹时,会失败并给出下一步。
若只需只读判断,运行 node ../../scripts/mobile-native-client.ts check <ios|android> [device]:退出码 0 表示兼容,2 表示需要安装,1 表示操作错误。外部安装的客户端在辅助工具安装过它一次之前,都视为未经验证。
为已经验证的开发客户端启动 Metro:
vp run dev:clientMetro 会在普通启动之间保留转换缓存。如果缓存本身导致输出过期或无效,可以在一次开发客户端启动时清除它:
vp run dev:client:reset安装或更改 Uniwind 依赖补丁之后,运行一次该重置。否则,缓存的转换可能仍会引用它先前的 pnpm 包路径。普通的 Metro 启动仍会保留缓存。
组件编辑使用 Fast Refresh。在更改运行时所有权或刷新行为之前,请参阅移动开发生命周期。
构建并运行本地 iOS 开发客户端:
vp run ios:dev更改原生依赖补丁之后,在重新构建现有 iOS 项目之前重新运行 CocoaPods。pnpm 会给每个补丁哈希一个新的包路径;否则 Pods 可能继续编译先前的目录。
如果你的 Xcode 账户只有 Personal Team,请使用一个由你控制的 bundle identifier,并选择加入能力缩减的本地构建。Personal Team 构建会省略小组件和共享扩展、推送授权,以及原生的 Sign in with Apple 授权;未作此选择的构建保持不变。
T3CODE_IOS_PERSONAL_TEAM=1 \
T3CODE_IOS_PERSONAL_TEAM_BUNDLE_ID=com.example.t3code.dev \
vp run ios:dev构建并安装一个不需要 Metro 的自包含 Release 应用:
vp run ios:releasePersonal Team 的对应做法同样需要一个唯一的 bundle identifier:
T3CODE_IOS_PERSONAL_TEAM=1 \
T3CODE_IOS_PERSONAL_TEAM_BUNDLE_ID=com.example.t3code \
vp run ios:release构建并运行本地 iOS 预览应用:
vp run ios:preview查看某个变体解析后的 Expo 配置:
vp run config:dev
vp run config:preview对移动端原生代码运行静态检查:
node ../../scripts/mobile-native-static-check.ts原生 lint 任务会为 Swift 运行 SwiftLint,并为 Kotlin 运行 ktlint 和 detekt。缺少的原生工具会作为警告报告,并在本地跳过。CI 会在运行原生检查之前,从 apps/mobile/Brewfile 安装默认工具集。
EAS 构建
预览与生产变体使用 Expo 指纹识别,因此 OTA 更新只会送达原生依赖、配置插件和补丁都匹配的二进制文件。CI 使用 preview:dev 配置文件,以便在可能时复用兼容的原生构建。
开发变体使用 appVersion,以避免在每次 Metro 启动清单时重新计算原生指纹。MOBILE_VERSION_POLICY 可以覆盖这两种默认值中的任意一种。如果你分发一份使用开发身份的自定义 Release 构建,并向它发布 OTA 更新,请在其构建和更新两侧都设置 MOBILE_VERSION_POLICY=fingerprint。更改运行时策略后,需要重新进行原生构建才能匹配 OTA;现有的开发客户端仍可加载本地 Metro 包。
对于预览或生产 EAS 环境,将 T3CODE_CLERK_PUBLISHABLE_KEY、 T3CODE_CLERK_JWT_TEMPLATE 和 T3CODE_RELAY_URL 设为 EAS 环境变量。Expo 配置会把这些规范值映射到移动构建中。
手动创建拉取请求(PR)预览的开发客户端构建:
vp run eas:ios:preview:dev创建云端开发客户端构建:
vp run eas:ios:dev创建持久的预览构建:
vp run eas:ios:previewAndroid 对应命令:
vp run eas:android:dev
vp run eas:android:preview:dev
vp run eas:android:preview