-
Notifications
You must be signed in to change notification settings - Fork 4k
Fix blank background when copiloting into an agent from the agent-DM RHP #97869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6a3a2a2
7757050
15f43a8
7bec3bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,8 @@ import Navigation from '@libs/Navigation/Navigation'; | |
|
|
||
| import ROUTES from '@src/ROUTES'; | ||
|
|
||
| import {useFocusEffect} from '@react-navigation/native'; | ||
| import React, {useCallback} from 'react'; | ||
| import {useFocusEffect, useIsFocused} from '@react-navigation/native'; | ||
| import React, {useCallback, useEffect} from 'react'; | ||
|
|
||
| function withAgentAccessDenied(getComponent: () => React.ComponentType): () => React.ComponentType { | ||
| let ProtectedComponent: React.ComponentType | undefined; | ||
|
|
@@ -16,47 +16,62 @@ function withAgentAccessDenied(getComponent: () => React.ComponentType): () => R | |
| const Component = getComponent(); | ||
| ProtectedComponent = (props) => { | ||
| const isAgent = useIsAgentAccount(); | ||
| const isFocused = useIsFocused(); | ||
| const isAlreadyOnRedirectTarget = Navigation.isActiveRoute(ROUTES.SETTINGS_PROFILE.route); | ||
| const shouldRedirect = isAgent === true && !isAlreadyOnRedirectTarget; | ||
|
|
||
| // Redirect on every focus (not just the initial false->true transition) so navigating back | ||
| // onto a guarded screen that the split navigator keeps mounted (e.g. a stale agents route | ||
| // left over from the owner session) bounces the agent to a page they can access instead of | ||
| // rendering a blank pane. | ||
| useFocusEffect( | ||
| useCallback(() => { | ||
| if (isAgent !== true) { | ||
| const redirectAgentAway = useCallback(() => { | ||
| if (isAgent !== true) { | ||
| return; | ||
| } | ||
|
|
||
| // On a cold deep-link the effect can run before the NavigationContainer is ready, so the | ||
| // redirect is silently dropped and leaves a blank central pane. Wait for readiness before | ||
| // reading navigation state or dispatching. | ||
| Navigation.isNavigationReady().then(() => { | ||
| if (Navigation.isActiveRoute(ROUTES.SETTINGS_PROFILE.route)) { | ||
| return; | ||
| } | ||
|
|
||
| // On a cold deep-link the effect can run before the NavigationContainer is ready, so the | ||
| // redirect is silently dropped and leaves a blank central pane. Wait for readiness before | ||
| // reading navigation state or dispatching. | ||
| Navigation.isNavigationReady().then(() => { | ||
| if (Navigation.isActiveRoute(ROUTES.SETTINGS_PROFILE.route)) { | ||
| return; | ||
| } | ||
| // forceReplace REPLACEs the stale guarded central-pane route instead of PUSHing Profile on | ||
| // top of it, so back from Profile pops to the unguarded Account sidebar rather than the | ||
| // guarded route that would re-fire this redirect. | ||
| const redirectToProfile = () => Navigation.navigate(ROUTES.SETTINGS_PROFILE.getRoute(), {forceReplace: true}); | ||
|
|
||
| // The guarded screen can be open inside a modal/RHP (e.g. the agent-edit page the owner was | ||
| // on when they tapped "Copilot into account"), or an unguarded RHP (e.g. the agent DM) can be | ||
| // sitting on top of this guarded central pane. Navigating straight to the tab-nested Profile | ||
| // route while an RHP is focused gets forced to PUSH (see linkTo), stacking Profile on top of | ||
| // the still-guarded route and trapping the user in a Profile <-> Profile loop on back. Dismiss | ||
| // the modal first, then redirect once it's closed (the underlying pane may be unguarded, so we | ||
| // can't rely on its guard to redirect). | ||
| if (Navigation.isTopmostRouteModalScreen()) { | ||
| Navigation.dismissModal({afterTransition: redirectToProfile}); | ||
| return; | ||
| } | ||
|
|
||
| // forceReplace REPLACEs the stale guarded central-pane route instead of PUSHing Profile on | ||
| // top of it, so back from Profile pops to the unguarded Account sidebar rather than the | ||
| // guarded route that would re-fire this redirect. | ||
| const redirectToProfile = () => Navigation.navigate(ROUTES.SETTINGS_PROFILE.getRoute(), {forceReplace: true}); | ||
| redirectToProfile(); | ||
| }); | ||
| }, [isAgent]); | ||
|
|
||
| // The guarded screen can be open inside a modal/RHP (e.g. the agent-edit page the owner was | ||
| // on when they tapped "Copilot into account"). Navigating straight to the tab-nested Profile | ||
| // route while an RHP is focused gets forced to PUSH (see linkTo), stacking Profile on top of | ||
| // the still-guarded route and trapping the user in a Profile <-> Profile loop on back. Dismiss | ||
| // the modal first, then redirect once it's closed (the underlying pane may be unguarded, so we | ||
| // can't rely on its guard to redirect). | ||
| if (Navigation.isTopmostRouteModalScreen()) { | ||
| Navigation.dismissModal({afterTransition: redirectToProfile}); | ||
| return; | ||
| } | ||
| // Redirect on every focus (not just the initial transition from false to true) so navigating back | ||
| // onto a guarded screen that the split navigator keeps mounted (e.g. a stale agents route | ||
| // left over from the owner session) bounces the agent to a page they can access instead of | ||
| // rendering a blank pane. | ||
| useFocusEffect(redirectAgentAway); | ||
|
|
||
| redirectToProfile(); | ||
| }); | ||
| }, [isAgent]), | ||
| ); | ||
| // useFocusEffect only fires while this screen is focused. When the session flips to an agent while | ||
| // this guarded screen is mounted but NOT focused, for example the owner taps "Copilot into account" from | ||
| // an unguarded RHP (the agent DM) sitting over this guarded central pane, useFocusEffect never runs, | ||
| // so the pane renders null (blank background) until the RHP is closed. Drive the redirect off the | ||
| // isAgent transition here too so the background is corrected immediately. Skip when focused since | ||
| // useFocusEffect already covers that case. | ||
| useEffect(() => { | ||
| if (isFocused) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ CONSISTENCY-16 (docs)This newly added comment uses em dashes (—) to set off clauses in its own sentences (lines: Rewrite using ordinary punctuation, for example: // useFocusEffect only fires while this screen is focused. When the session flips to an agent while
// this guarded screen is mounted but NOT focused, for example the owner taps "Copilot into account" from
// an unguarded RHP (the agent DM) sitting over this guarded central pane, useFocusEffect never runs,
// so the pane renders null (blank background) until the RHP is closed. Drive the redirect off the
// isAgent transition here too so the background is corrected immediately. Skip when focused since
// useFocusEffect already covers that case.Reviewed at: 15f43a8 | Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in |
||
| return; | ||
| } | ||
| redirectAgentAway(); | ||
| }, [isFocused, redirectAgentAway]); | ||
|
|
||
| if (isAgent === undefined || shouldRedirect) { | ||
| return null; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❌ CONSISTENCY-16 (docs)
This comment uses an arrow (
->) in its own sentence (the initial false->true transition) instead of writing the relationship in words. Comments should express the relationship in plain English.Rewrite, for example:
// Redirect on every focus (not just the initial transition from false to true) so navigating backReviewed at: 15f43a8 | Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in
7bec3bc— rewrotefalse->trueastransition from false to true.