feat(ios): add onboarding welcome pager#45054
Conversation
Greptile SummaryThis PR introduces a first-run welcome pager ( Key changes:
Confidence Score: 4/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: apps/ios/Sources/Onboarding/OnboardingWizardView.swift
Line: 837-841
Comment:
**Redundant `statusLine` reset may mask `initializeState()` side-effect**
`initializeState()` (called from `.onAppear`) already overwrites `statusLine` to `"No saved pairing found. In your OpenClaw chat, run /pair qr, then scan the code here."` for any fresh install with no saved credentials. The re-assignment in `advanceFromIntro()` intentionally drops the `"No saved pairing found."` prefix for users who just tapped Continue on the intro screen — which is correct UX. However, there's no comment explaining why the override is needed, making it look like dead code. A short inline comment would clarify the intent:
```suggestion
private func advanceFromIntro() {
OnboardingStateStore.markFirstRunIntroSeen()
// Override the "No saved pairing found." prefix that initializeState() may have set,
// since first-run users haven't had a chance to pair yet and the prefix would be confusing.
self.statusLine = "In your OpenClaw chat, run /pair qr, then scan the code here."
self.step = .welcome
}
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: 6fcdda2 |
|
Addressed the review feedback in 881ea16.
@greptile-apps please re-review this PR |
881ea16 to
d5cd523
Compare
| @Test func resetClearsCompletionAndIntroSeen() { | ||
| let testDefaults = self.makeDefaults() | ||
| let defaults = testDefaults.defaults | ||
| defer { self.reset(testDefaults) } | ||
|
|
||
| OnboardingStateStore.markCompleted(mode: .homeNetwork, defaults: defaults) | ||
| OnboardingStateStore.markFirstRunIntroSeen(defaults: defaults) | ||
|
|
||
| OnboardingStateStore.reset(defaults: defaults) | ||
|
|
||
| #expect(OnboardingStateStore.shouldPresentFirstRunIntro(defaults: defaults)) | ||
| #expect(OnboardingStateStore.lastMode(defaults: defaults) == .homeNetwork) | ||
| } |
There was a problem hiding this comment.
Test name promises completion cleared but doesn't assert it
resetClearsCompletionAndIntroSeen verifies that shouldPresentFirstRunIntro becomes true again (intro-seen cleared ✓) and that lastMode is preserved ✓. However it never asserts that the completed flag was actually cleared — the "ClearsCompletion" half of the name is unverified.
Since shouldPresentOnLaunch requires @MainActor and an AppModel, the simplest addition is a dedicated @MainActor assertion:
// inside the existing test, add after reset():
let appModel = NodeAppModel()
appModel.gatewayServerName = nil
#expect(OnboardingStateStore.shouldPresentOnLaunch(appModel: appModel, defaults: defaults))Without this, a future regression that accidentally skips the completedDefaultsKey reset inside reset() would go undetected by this suite.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/ios/Tests/OnboardingStateStoreTests.swift
Line: 53-65
Comment:
**Test name promises completion cleared but doesn't assert it**
`resetClearsCompletionAndIntroSeen` verifies that `shouldPresentFirstRunIntro` becomes `true` again (intro-seen cleared ✓) and that `lastMode` is preserved ✓. However it never asserts that the `completed` flag was actually cleared — the "ClearsCompletion" half of the name is unverified.
Since `shouldPresentOnLaunch` requires `@MainActor` and an `AppModel`, the simplest addition is a dedicated `@MainActor` assertion:
```swift
// inside the existing test, add after reset():
let appModel = NodeAppModel()
appModel.gatewayServerName = nil
#expect(OnboardingStateStore.shouldPresentOnLaunch(appModel: appModel, defaults: defaults))
```
Without this, a future regression that accidentally skips the `completedDefaultsKey` reset inside `reset()` would go undetected by this suite.
How can I resolve this? If you propose a fix, please make it concise.d5cd523 to
6fcdda2
Compare
|
Addressed the latest follow-up review points in 6fcdda2.
@greptile-apps please re-review this PR |
| private func advanceFromIntro() { | ||
| OnboardingStateStore.markFirstRunIntroSeen() | ||
| self.statusLine = "In your OpenClaw chat, run /pair qr, then scan the code here." | ||
| self.step = .welcome | ||
| } |
There was a problem hiding this comment.
Redundant statusLine reset may mask initializeState() side-effect
initializeState() (called from .onAppear) already overwrites statusLine to "No saved pairing found. In your OpenClaw chat, run /pair qr, then scan the code here." for any fresh install with no saved credentials. The re-assignment in advanceFromIntro() intentionally drops the "No saved pairing found." prefix for users who just tapped Continue on the intro screen — which is correct UX. However, there's no comment explaining why the override is needed, making it look like dead code. A short inline comment would clarify the intent:
| private func advanceFromIntro() { | |
| OnboardingStateStore.markFirstRunIntroSeen() | |
| self.statusLine = "In your OpenClaw chat, run /pair qr, then scan the code here." | |
| self.step = .welcome | |
| } | |
| private func advanceFromIntro() { | |
| OnboardingStateStore.markFirstRunIntroSeen() | |
| // Override the "No saved pairing found." prefix that initializeState() may have set, | |
| // since first-run users haven't had a chance to pair yet and the prefix would be confusing. | |
| self.statusLine = "In your OpenClaw chat, run /pair qr, then scan the code here." | |
| self.step = .welcome | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/ios/Sources/Onboarding/OnboardingWizardView.swift
Line: 837-841
Comment:
**Redundant `statusLine` reset may mask `initializeState()` side-effect**
`initializeState()` (called from `.onAppear`) already overwrites `statusLine` to `"No saved pairing found. In your OpenClaw chat, run /pair qr, then scan the code here."` for any fresh install with no saved credentials. The re-assignment in `advanceFromIntro()` intentionally drops the `"No saved pairing found."` prefix for users who just tapped Continue on the intro screen — which is correct UX. However, there's no comment explaining why the override is needed, making it look like dead code. A short inline comment would clarify the intent:
```suggestion
private func advanceFromIntro() {
OnboardingStateStore.markFirstRunIntroSeen()
// Override the "No saved pairing found." prefix that initializeState() may have set,
// since first-run users haven't had a chance to pair yet and the prefix would be confusing.
self.statusLine = "In your OpenClaw chat, run /pair qr, then scan the code here."
self.step = .welcome
}
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
Codex Review: Didn't find any major issues. Chef's kiss. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
6fcdda2 to
b54815d
Compare
* main: (168 commits) fix: stabilize macos daemon onboarding fix(ui): keep shared auth on insecure control-ui connects (openclaw#45088) docs(plugins): clarify workspace shadowing fix(node-host): harden perl approval binding fix(node-host): harden pnpm approval binding fix(discovery): add missing domain to wideArea Zod config schema (openclaw#35615) chore(gitignore): add docker-compose override (openclaw#42879) feat(ios): add onboarding welcome pager (openclaw#45054) fix(signal): add groups config to Signal channel schema (openclaw#27199) fix: restore web fetch firecrawl config in runtime zod schema (openclaw#42583) fix: polish Android QR scanner onboarding (openclaw#45021) fix(android): use Google Code Scanner for onboarding QR fix(config): add missing params field to agents.list[] validation schema (openclaw#41171) docs(contributing): update Android app ownership fix(agents): rephrase session reset prompt to avoid Azure content filter (openclaw#43403) test(config): cover requiresOpenAiAnthropicToolPayload in compat schema fixture fix(agents): respect explicit user compat overrides for non-native openai-completions (openclaw#44432) Android: fix HttpURLConnection leak in TalkModeVoiceResolver (openclaw#43780) Docker: add OPENCLAW_TZ timezone support (openclaw#34119) fix(agents): avoid injecting memory file twice on case-insensitive mounts (openclaw#26054) ...
* feat(ios): add onboarding welcome pager * feat(ios): add onboarding welcome pager (openclaw#45054) (thanks @ngutman)
* feat(ios): add onboarding welcome pager * feat(ios): add onboarding welcome pager (openclaw#45054) (thanks @ngutman)
* feat(ios): add onboarding welcome pager * feat(ios): add onboarding welcome pager (openclaw#45054) (thanks @ngutman)
* feat(ios): add onboarding welcome pager * feat(ios): add onboarding welcome pager (openclaw#45054) (thanks @ngutman)
* feat(ios): add onboarding welcome pager * feat(ios): add onboarding welcome pager (openclaw#45054) (thanks @ngutman) (cherry picked from commit 496176d)
* feat(ios): add onboarding welcome pager * feat(ios): add onboarding welcome pager (openclaw#45054) (thanks @ngutman)
Summary
/pair qrinstructions on the connect gateway step so pairing can be initiated from chatVerification