Improve profile management and account switching UX#2
Improve profile management and account switching UX#2TanjimReza wants to merge 6 commits intokitze:mainfrom
Conversation
…ements. Implemented guard clauses to prevent actions when account switching is in progress. Updated menu rendering logic and adjusted layout for better usability.
…e accounts in CodexMaxx
feat: profile modification, switching state enhancement
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdded profile deletion with a two-phase account switching model featuring identity-matching to prevent inadvertent file overwrites. UsageController is now an ObservableObject with concurrency guards. Storage layer supports profile deletion with safe conditional file copying based on matching identities between accounts. Menu UI expanded with delete buttons, loading indicators, and state feedback. ChangesProfile Deletion & Account Switching Safety
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
Sources/CodexMaxx/main.swift (1)
1076-1086: 💤 Low valueDuplicated JWT id_token email decoding.
This helper duplicates the logic in
CodexReconciledState.email(from:)at lines 1523–1533 (same base64url normalization, padding loop, andhttps://api.openai.com/profilefallback). Consider extracting a single shared helper (e.g.,CodexIDToken.email(from:)) so both call sites stay in sync if the token shape ever changes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Sources/CodexMaxx/main.swift` around lines 1076 - 1086, The JWT email decoding logic is duplicated between private static func email(fromIDToken:) and CodexReconciledState.email(from:); extract that shared logic into a single helper (e.g., a new static method CodexIDToken.email(from: String?) or similar) that performs base64url normalization, padding, JSON decoding, and the "https://api.openai.com/profile" fallback, then replace both email(fromIDToken:) and CodexReconciledState.email(from:) to call the new helper so both call sites use the same implementation and keep behavior in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/CodexMaxx/main.swift`:
- Around line 1048-1054: The current profilesHaveMatchingIdentity(_:_:) returns
true when either profileIdentity(at:) fails, which lets a corrupt/unreadable
live ~/.codex trigger copySwitchedFiles(from: liveCodexHome, to: currentHome);
change the guard so that if either lhsIdentity or rhsIdentity is nil the
function returns false (i.e., only return lhsIdentity == rhsIdentity when both
identities are present). Update the implementation of
profilesHaveMatchingIdentity to treat missing/unreadable identities as
non-matching to prevent the copy-back in ambiguous cases.
- Around line 821-832: The success statusMessage set in finishSwitching(to:) is
never cleared, causing a stale "Switched to ..." message to linger; fix it by
(1) resetting statusMessage = nil at the start of refresh() (and/or
startSwitching(to:)) to ensure refreshes clear stale state, and (2) in
finishSwitching(to:) schedule an asynchronous auto-clear (e.g. spawn a Task that
awaits a short delay then on the MainActor sets self.statusMessage = nil) so the
success message is visible briefly then removed automatically.
---
Nitpick comments:
In `@Sources/CodexMaxx/main.swift`:
- Around line 1076-1086: The JWT email decoding logic is duplicated between
private static func email(fromIDToken:) and CodexReconciledState.email(from:);
extract that shared logic into a single helper (e.g., a new static method
CodexIDToken.email(from: String?) or similar) that performs base64url
normalization, padding, JSON decoding, and the "https://api.openai.com/profile"
fallback, then replace both email(fromIDToken:) and
CodexReconciledState.email(from:) to call the new helper so both call sites use
the same implementation and keep behavior in sync.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0681015e-c925-44ba-97b6-0d1bb8d84bdd
📒 Files selected for processing (2)
README.mdSources/CodexMaxx/main.swift
| func finishSwitching(to name: String) async { | ||
| do { | ||
| try CodexProfileStore.switchToProfile(named: name) | ||
| await self.refresh() | ||
| self.statusMessage = "Switched to \(self.displayName(for: name))" | ||
| } catch { | ||
| await self.refresh() | ||
| self.lastError = error.localizedDescription | ||
| self.statusMessage = nil | ||
| } | ||
| self.switchingAccountName = nil | ||
| } |
There was a problem hiding this comment.
Success statusMessage lingers indefinitely.
statusMessage is set to "Switched to ..." on success and is never cleared by refresh() or any timer, so the green checkmark + message keeps showing in the menu across subsequent refreshes (and even hours later) until another switch starts or the app restarts. Consider clearing it after a short delay, or resetting it at the top of refresh() / startSwitching(to:) so stale state doesn't accumulate.
🧹 One possible fix — auto-clear after a short delay
func finishSwitching(to name: String) async {
do {
try CodexProfileStore.switchToProfile(named: name)
await self.refresh()
- self.statusMessage = "Switched to \(self.displayName(for: name))"
+ let message = "Switched to \(self.displayName(for: name))"
+ self.statusMessage = message
+ Task { [weak self] in
+ try? await Task.sleep(nanoseconds: 4_000_000_000)
+ await MainActor.run {
+ if self?.statusMessage == message { self?.statusMessage = nil }
+ }
+ }
} catch {
await self.refresh()
self.lastError = error.localizedDescription
self.statusMessage = nil
}
self.switchingAccountName = nil
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Sources/CodexMaxx/main.swift` around lines 821 - 832, The success
statusMessage set in finishSwitching(to:) is never cleared, causing a stale
"Switched to ..." message to linger; fix it by (1) resetting statusMessage = nil
at the start of refresh() (and/or startSwitching(to:)) to ensure refreshes clear
stale state, and (2) in finishSwitching(to:) schedule an asynchronous auto-clear
(e.g. spawn a Task that awaits a short delay then on the MainActor sets
self.statusMessage = nil) so the success message is visible briefly then removed
automatically.
# Conflicts: # README.md # Sources/CodexMaxx/main.swift
~/.codexlogin changes from overwriting the wrong saved profilecodex loginScreenshot_.2026-05-09.at.00.46.38.mp4
Summary by CodeRabbit
New Features
Documentation