CM4 机型配对成功后立即弹出的二选一页面:选 WiFi + 云端 → 进 sign-in 漏斗(已恢复 session 时跳过)→ /wifi-select 网络选择页(TAPD #1003130,Android 自动扫附近 2.4 GHz AP / iOS manual fallback)→ /wifi-setup 密码+配对页;选 BLE-only → 清栈到 Dashboard + 顶部叠 设备指南(TAPD #1003087 / 88e3ad7,与 scan-page 非 CM4 / WiFi 成功 / WiFi→BT fallback 三条收尾路径统一)。CM1/CM2/CM3 跳过此页(legacy 全家族无 cloud / account 概念,per PLAN_ACCOUNT_SYSTEM.md 的 "guest mode" 划分)。
lib/features/thermometer/presentation/pages/connection_mode_page.dart(ConsumerStatefulWidget——72151239 / TAPD #1003129 起从 StatelessWidget 升级以读 authControllerProvider,并维护 _committed 状态用于 dispose 时的 setup 清理)authControllerProvider(仅 read.isSignedIn,决定 WiFi 选项跳 sign-in 漏斗还是直入 WiFi 配置)AppPermissions.requestCM4LocalNetwork(iOS 本地网络权限)deviceId(路由 arguments,由 Scan 页传过来)/connection-mode(ConnectionModePage.routeName)lib/app.dart 的 onGenerateRoute(line 86)—— 因为需要 deviceId arguments,不在静态 routes map顶部仅一个返回 chevron_left 按钮。中段是大号粗体标题 + 灰色 deviceId 副标题。下方两张等宽选项卡片:第一张是云图标 "WiFi(推荐)"(蓝色 accent),WiFi 卡片下方夹一条蓝色 info banner(蓝牙图标 + l.connectionModeWifiBluetoothHint,fff9dba / TAPD #1003235:提示用户在配对完成前保持手机蓝牙开启,否则 WiFi 配网会持续失败——WiFi 流程全程跑在 BLE 上,详见 WiFi 配置 §Per Liang 2026-06-10),第二张是蓝牙图标 "Bluetooth-only"(绿色 accent)。每张卡片右侧带 chevron_right 暗示可点。整体居中布局,上下大量空白。
IconButton.onPressed → Navigator.pop(context)pushReplacementNamed 打开本页,pop 不会回到 Scan 页。dispose,因 _committed 为 false,会调用 deviceSetupProvider.notifier.complete(deviceId) 解除该设备的 alarm suppression(BLE 连接已建立,不会被 pop 撤销)⚠️ 72151239 / TAPD #1003129 起前置 sign-in 漏斗 + 242ec8c / TAPD #1003130 起拆 WiFi 两步:CM4 WiFi 路径先经账户登录漏斗(sign-in landing → email + password / Google / Apple 仅 iOS(caa7e95:App Store guideline 4.8 要求 iOS 提供 Apple sign-in,但 Android 无原生 Apple auth、Apple 按钮经 Platform.isIOS 闸;Android 只显 Google + email) → 6-digit code),有持久化 session 时直接跳过;漏斗终点不再是 /wifi-setup,而是新增的 /wifi-select 网络选择页(Android 扫附近 2.4 GHz AP 列出、auth_widgets.finishAuthFunnel(context, deviceId) push /wifi-select 同时把 auth-stack 全部 pop 掉——c5b09e4 / TAPD #1003149 起原 goToWifiSetup 改名为 finishAuthFunnel,deviceId 改为可空:携 deviceId 仍走「WiFi-onboarding」路径 push /wifi-select,为 null 则只 popUntil auth 路由、返回 sign-in 入口页(如 Settings 的 account-only 入口),不进 WiFi 流程),用户选中 SSID 或走 Skip / 手动输入后再 push /wifi-setup 完成密码 + 配对。后端目前是 StubAuthService,UI 不变就可以后续 swap 到 Cognito(详见 PLAN_ACCOUNT_SYSTEM.md)。BLE-only 路径不经登录、与 legacy guest-mode 一致。
_ConnectionOption.onTap(第一张卡片,Icons.cloud_outlined)authControllerProvider.isSignedIn 跳目标——已登录直入 /wifi-select(跳过登录漏斗)、未登录跳 /sign-in(sign-in landing 页,创建账号后才进入 email-code;已有账号登录成功则直接调用 finishAuthFunnel(context, deviceId) 进入后续流程。)。两种目标都带 deviceId arguments。GestureDetector.onTap (in _ConnectionOption)
→ if (Platform.isIOS):
showDialog<bool>(...) // CM4 权限解释
→ 用户取消 → return(留在本页)
→ 用户继续 → AppPermissions.requestCM4LocalNetwork()
→ signedIn = ref.read(authControllerProvider).isSignedIn
→ Navigator.pushReplacementNamed(
signedIn ? '/wifi-select' : '/sign-in',
arguments: deviceId)
pushReplacement 替换本页(防止用户用返回键回到 ConnectionMode);sign-in 漏斗持久化 session 通过 SharedPreferences,App 重启后 authControllerProvider.restore() 灌回,下次 WiFi 选项 skip 漏斗。_ConnectionOption.onTap(第二张卡片,Icons.bluetooth)GestureDetector.onTap
→ _committed = true
→ DeviceGuidePage.showAfterDeviceAdd(context)
≡ ProviderScope.containerOf(context, listen: false)
.read(deviceSetupProvider.notifier)
.completeAll();
Navigator.of(context)
..pushNamedAndRemoveUntil('/dashboard', (route) => false)
..pushNamed('/device-guide')
showAfterDeviceAdd helper,保证「Settings → Operation Guide」与「设备 add 完成后」看到的指南内容完全一致无 Provider 订阅。本页是纯静态导航选择 —— 不需要重建。
| 项 | iOS | Android |
|---|---|---|
| WiFi 选项点击行为 | 先弹 cm4PermissionDialogTitle 对话框,确认后调 AppPermissions.requestCM4LocalNetwork() 申请「本地网络」权限 |
跳过权限解释对话框,直接跳到 /wifi-select(或 /sign-in 若未登录) |
Platform.isIOS 分支在 _ConnectionOption.onTap 内(line 86)。理由:iOS 14+ 要求 App 显式请求本地网络权限才能扫到同 WiFi 的 CM4,而 Android 没有此要求。