账号漏斗的第一屏(TAPD #1003129),三个入口:Google(全平台)、Apple(仅 iOS,App Store 4.8 条款要求提供 Apple 登录、但 Android 没有原生 Apple 认证)、邮箱(跳 邮箱登录注册)。三个入口共享一个"请先勾选用户协议/隐私协议"的同意闸——未勾选时点任意一个都只会弹提示对话框,不会真的发起登录。
lib/features/auth/presentation/sign_in_landing_page.dart(237 行)authControllerProvider(signInWithProvider 用于 Google/Apple;邮箱按钮只做路由跳转,不直接调用)AuthScaffold / ProviderButton / finishAuthFunnel(lib/features/auth/presentation/widgets/auth_widgets.dart)deviceId(可空)——非空时是从 WiFi 配网漏斗中途触发(连接模式 或 设备配置 的 WiFi 选项),登录成功后继续该漏斗;为空时是账号入口独立触发(如 Settings 的 account-only 入口),登录成功只回到发起页/sign-in(SignInLandingPage.routeName)lib/app.dart 的 onGenerateRoute(arguments 是可空 String?)顶部标题/副标题(AuthScaffold 外壳);若 deviceId 非空,标题下方先出现一个绿点 + deviceId 的小胶囊(表明这是为哪台设备配网触发的登录);接着从上到下三个provider 按钮:白底 Google(google_g.svg)、黑底 Apple(apple_logo.svg,仅 iOS,Android 完全不渲染这一行)、邮件图标的 "Continue with email";底部是协议同意行——一个 checkbox + "已阅读并同意《用户协议》和《隐私协议》",两个协议名是可点的下划线链接(openPolicy,打开外部 URL)。
_ConsentRow 的 Checkbox.onChangedsetState,不持久化——每次进本页都要重新勾选_guard(action) 检测到 _agreed == false_showConsentDialog),不执行 action,用户点确定后关闭对话框,仍需手动去勾选_guard(() => _oauth(AuthProvider.google))_oauth(AuthProvider.google)
→ authControllerProvider.notifier.signInWithProvider(AuthProvider.google)
→ SupabaseAuthService.signInWithProvider() → GoTrue signInWithOAuth(...)
(PKCE 浏览器回跳,culinatech://login-callback)
→ 成功 → finishAuthFunnel(context, deviceId)
AuthController 状态翻到 signedIn_oauth(AuthProvider.apple),仅在 Platform.isIOS 时渲染这个按钮AuthProvider.apple_guard(() => Navigator.pushNamed(context, '/email-auth', arguments: deviceId))deviceId 原样透传watch authControllerProvider 只为了读 state.busy(驱动 provider 按钮的 loading 态);ref.listen 监听 state.error 变化统一弹 SnackBar。_agreed 是纯本地 setState 状态。
| 项 | iOS | Android |
|---|---|---|
| Apple 登录按钮 | 渲染(Platform.isIOS 分支) |
不渲染——没有原生 Apple 认证,硬做会是别扭的 web OAuth 绕行,不如干脆不提供 |