UX improvements: inline undo banner, haptics, technical-details preference, sign-in toast#19
UX improvements: inline undo banner, haptics, technical-details preference, sign-in toast#19jameshaworthcs wants to merge 15 commits into
Conversation
Cancelling or dismissing the auth browser used to leave the modal in a silent or never-rendered error state. Now the modal closes cleanly and an info toast appears explaining the cancellation; tapping it opens the support page (authenticated transfer-token URL with an unauthenticated fallback). Toast component now wraps in TouchableOpacity when an onPress is supplied, and useToast forwards an optional onPress that hides the toast before invoking the handler.
- Report Code: selection haptic on changing the selected code; light impact + success/error around submit. - Undo: light impact on banner tap; medium impact on modal confirm + success/error on completion. - History: success haptic on copy; light impact + success/error on hide/restore. - Options sheet: selection haptic on non-push rows and the Session Info toggle. Push rows already get one from the sheet transition. - AutoCheckin: light impact + success/error on Join, Leave, and Open. - Settings: light impact + success on Log Out; warning on opening Delete Account; medium impact + success/error on delete submit.
Adds a Display section toggle in Settings that gates the live-update fetch timing in the checkout indicator, mirroring the web's "Show technical details" preference. The pref is persisted to local storage for instant first paint and synced to the user's account via /api/settings/technicalDetails when signed in. Live-classes poll responses include the server-authoritative value in userInfo, so changes made on the web propagate to the app within the next 2.5s poll without an extra request.
Tapping Undo now cross-fades the thank-you banner into a "Remove your code?" yes/no, then spinner, then a persistent "Code removed." with a dismiss — no modal hop, no toast-only error. Mirrors the web change in v1.9.122. useLiveClasses owns the interactive state machine (confirming/undoing/undone/error) and patches any buffered poll snapshot on success so a stale flush can't revert the card. The purge in applyDataToUI now stringifies keys before comparing — session.rejectID is the DB activityID and arrives as a number, which previously meant the undone entry was deleted on the very next refresh and never rendered.
Replace the opaque accessory bar above the keyboard with a transparent host and a 52pt circular Liquid Glass capsule (expo-glass-effect's GlassView) on iOS 26, with a systemChromeMaterial BlurView fallback for older iOS. The capsule contains a tinted checkmark SF Symbol so the control reads as a real iOS submit affordance rather than a "Done" label on a black slab. Pass accessibilityLabel="Submit code" from CodeInput so VoiceOver announces the action, not just "Done".
Two issues caused the report form to appear with either a large empty gap below the action buttons, or with the bottom of the buttons clipped behind the sheet's paddingBottom: 1. KeyboardAvoidingView (behavior="padding") already lifts the sheet above the keyboard, but automaticallyAdjustKeyboardInsets on the inner ScrollView was double-counting that by adding another keyboardHeight of contentInset, prompting iOS to over-scroll the focused field to the top of an inflated content area. 2. The sheet shrinks by keyboardHeight when the keyboard rises, but kept its full insets.bottom paddingBottom for the home indicator — which is hidden behind the keyboard and so unused. Reclaiming that inset in the maxHeight clamp lets the sheet grow upward by that amount, giving the ScrollView viewport enough room for the form.
On launch, sessions are hydrated synchronously from the persisted response cache, which can still hold a session that finished while the app was closed. The toast effect fired against that stale data — and the in-memory dedup set is reset on each mount, so it no longer suppressed the repeat — surfacing a "<session> has N codes" toast for a session that is no longer visible. Gate the toast on lastUpdateTime so it only runs once a live fetch has landed (by which point a finished session has already dropped out of the list), and prune the dismissed set to currently-active IDs so it stays bounded and a session that becomes active again can re-toast.
Apply npm audit fix to clear the critical and all high-severity advisories (46 -> 16). Remaining 16 moderate are dev/build-toolchain deps gated behind an Expo SDK 56 breaking upgrade (tracked on chore/expo-sdk-56-upgrade-wip).
* chore(deps): WIP Expo SDK 54->56 upgrade (npm audit --force) Upgrades expo to 56 and aligns native modules via 'expo install --fix'. INCOMPLETE - requires code migration before merge: - expo-router no longer compatible with @react-navigation (8 files) - expo-router/unstable-native-tabs API changed (Icon/Label/VectorIcon) - StyleSheet.absoluteFillObject removed - missing peer dep react-native-worklets - needs simulator/device testing Clears remaining audit moderates that are gated behind SDK 56. * chore(deps): complete Expo SDK 56 upgrade Finishes the SDK 54->56 migration started in the WIP commit and clears the npm audit. - npm audit: 0 vulnerabilities via a uuid>=11.1.1 override scoped to xcode (the only consumer; it uses uuid.v4() only) - native-tabs: migrate Icon/Label/VectorIcon to NativeTabs.Trigger.*, androidSrc -> src (SDK 56 API) - StyleSheet.absoluteFillObject (removed) -> absoluteFill - useColorScheme() now returns 'unspecified' (RN 0.85); normalize to 'dark' ? 'dark' : 'light' across themed lookups - register react-native-worklets jest resolver so the reanimated 4 mock loads (fixes 3 test suites) - IconSymbol: key the SF-symbol map by string (expo-symbols name type widened to a platform-object union) - tsconfig types:["jest"] (TS 6.0 no longer auto-includes ambient @types) - resolve all eslint-plugin-react-hooks v7 (React Compiler) findings: Animated.Value refs -> useState lazy init, Confetti particles -> state with shape baked in, scoped disables for Reanimated/worklet idioms tsc, expo lint, and prettier clean; npm audit clean; 87 tests pass. * style: apply prettier to KeyboardDoneAccessory Pre-existing formatting drift unrelated to the SDK upgrade; brings the repo to a clean prettier --check (CI prettier.yml). * fix(router): migrate @react-navigation imports to expo-router entry points SDK 56's Metro resolver rejects any @react-navigation/* import from app code, failing the bundle (and eas submit) at app/(tabs)/_layout.tsx. Repoint all such imports to expo-router's own entry points: - nav/theme hooks (useRoute, useFocusEffect, useNavigation, ThemeProvider, DarkTheme, DefaultTheme) -> 'expo-router' - BottomTabBarHeightContext -> 'expo-router/js-tabs' Runtime API is unchanged; only the module specifiers move.
- useLiveClasses: confirmUndo's error paths now unblock refresh, and the poll purge releases the 'undo' blocker when a session ends mid-confirm/ undoing. Previously an undo network error (or a class ending while the inline confirm was open) left 'undo' stranded in the blocker set and froze live updates until app restart. retryUndo re-blocks on return to the confirm step. - useShowTechnicalDetails: roll back the optimistic local/cache update when the save POST fails so storage, in-memory cache, and the Switch don't diverge from the server. - CheckOutIcon: pass the color (string | OpaqueColorValue) straight to the SVG fill instead of .toString(), which flattened PlatformColor handles to a non-renderable string.
Adds the repo's first hook tests (renderHook), covering the two fixes from the prior commit plus the surrounding logic: - useLiveClasses.undo: full begin/confirm/cancel/retry/dismiss state machine, applyUndoToPending buffered-snapshot patching, and the fix #1 regressions — confirmUndo error (rejected + thrown) unblocks refresh, retryUndo re-blocks, 'undone' survives the session ending while a stale 'error' is purged. The three error/purge tests fail against the pre-fix hook. - useShowTechnicalDetails: hydration, optimistic save, the fix #2 rollback on failure (transport + body-level), accountSync relay, listener broadcast, and server reconciliation on login. Module-singleton state is isolated via resetModules + the /pure entry so renderHook shares the hook's React. 110 tests pass (was 87).
- UndoBanner: renders every step (idle/confirming/undoing/undone/error) with correct copy, fallbacks, button wiring, the cross-fade step swap, and the polite live region. Reduced motion is forced so swaps are synchronous and the vector icon is stubbed to avoid an async font setState. - useAuth: native (WebBrowser) sign-in flow — the 'Sign-in cancelled' toast on cancel/dismiss/success-without-token, its contact-support onPress opening the support URL, and suppression of the toast when a token is returned. The web popup path (no DOM here) is documented as not covered. 127 tests pass (was 110).
The real @expo/vector-icons Icon loads its font asynchronously and setState()s after render, surfacing as "not wrapped in act(...)" warnings in every test that renders one (VerificationContent, ReportContent, and others). Mock the icon entrypoints once in jest.setup.ts with a host-element stub that preserves accessibility props, and drop the now-redundant local mock in UndoBanner.test. Test suite is now warning-free; 127 tests pass.
|
Warning Review limit reached
More reviews will be available in 55 minutes and 36 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (45)
✨ 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 |
Summary
UX-polish branch on top of the Expo SDK 56 upgrade:
Fixes & tests
Version bumped 1.2.15 → 1.2.16.