Skip to content

Commit dafa4da

Browse files
authored
fix(settings): drop the settings return url when the workspace changed (#6847)
The settings Back button restores a return url captured on entry, but a workspace switch made from inside settings keeps the user in the new workspace without touching that stored path — so Back pushed them back into the workspace they had left, while the sidebar still read as the new one. Discard a stored return url that names a different workspace and fall back to the current workspace root.
1 parent 7dac31b commit dafa4da

3 files changed

Lines changed: 80 additions & 12 deletions

File tree

apps/sim/hooks/use-oauth-return.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import { getDesktopBridge } from '@/lib/desktop'
2626
import { oauthConnectionsKeys } from '@/hooks/queries/oauth/oauth-connections'
2727
import { workspaceCredentialKeys } from '@/hooks/queries/utils/credential-keys'
2828
import { requireWorkspaceCredentialListResponse } from '@/hooks/queries/utils/fetch-workspace-credentials'
29+
import { SETTINGS_RETURN_URL_KEY } from '@/hooks/use-settings-navigation'
2930

3031
const OAUTH_CREDENTIAL_UPDATED_EVENT = 'oauth-credentials-updated'
31-
const SETTINGS_RETURN_URL_KEY = 'settings-return-url'
3232
const CONTEXT_MAX_AGE_MS = 15 * 60 * 1000
3333

3434
export interface OAuthResultMessage {

apps/sim/hooks/use-settings-navigation.test.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ vi.mock('@/lib/auth/auth-client', () => ({
1515
useSession: vi.fn(() => ({ data: null, isPending: false })),
1616
}))
1717

18-
import { resolveSettingsHref } from '@/hooks/use-settings-navigation'
18+
import { resolveSettingsHref, resolveSettingsReturnUrl } from '@/hooks/use-settings-navigation'
1919

2020
const HOST_CONTEXT: WorkspaceHostContext = {
2121
workspace: {
@@ -107,3 +107,43 @@ describe('resolveSettingsHref unified settings navigation', () => {
107107
).toBe('/workspace/workspace-b/settings/billing')
108108
})
109109
})
110+
111+
describe('resolveSettingsReturnUrl', () => {
112+
const fallback = '/workspace/workspace-b'
113+
114+
it('returns the stored url when it belongs to the current workspace', () => {
115+
expect(
116+
resolveSettingsReturnUrl({
117+
storedUrl: '/workspace/workspace-b/w/workflow-a',
118+
workspaceId: 'workspace-b',
119+
fallback,
120+
})
121+
).toBe('/workspace/workspace-b/w/workflow-a')
122+
})
123+
124+
it('discards a stored url captured in a workspace the user has since left', () => {
125+
expect(
126+
resolveSettingsReturnUrl({
127+
storedUrl: '/workspace/workspace-a/w/workflow-a',
128+
workspaceId: 'workspace-b',
129+
fallback,
130+
})
131+
).toBe(fallback)
132+
})
133+
134+
it('keeps workspace-agnostic stored urls', () => {
135+
expect(
136+
resolveSettingsReturnUrl({
137+
storedUrl: '/account/settings/billing',
138+
workspaceId: 'workspace-b',
139+
fallback,
140+
})
141+
).toBe('/account/settings/billing')
142+
})
143+
144+
it('falls back when nothing was stored', () => {
145+
expect(
146+
resolveSettingsReturnUrl({ storedUrl: null, workspaceId: 'workspace-b', fallback })
147+
).toBe(fallback)
148+
})
149+
})

apps/sim/hooks/use-settings-navigation.ts

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { canManageWorkspaceBilling } from '@/lib/billing/workspace-permissions'
88
import { useOptionalWorkspaceHostContext } from '@/app/workspace/[workspaceId]/providers/workspace-host-provider'
99
import type { SettingsSection } from '@/app/workspace/[workspaceId]/settings/navigation'
1010

11-
const SETTINGS_RETURN_URL_KEY = 'settings-return-url'
11+
export const SETTINGS_RETURN_URL_KEY = 'settings-return-url'
1212

1313
interface SettingsNavigationOptions {
1414
section?: SettingsSection
@@ -57,6 +57,31 @@ export function resolveSettingsHref({
5757
return query ? `${pathname}?${query}` : pathname
5858
}
5959

60+
interface ResolveSettingsReturnUrlParams {
61+
storedUrl: string | null
62+
workspaceId?: string
63+
fallback: string
64+
}
65+
66+
/**
67+
* Resolves the stored settings return url, discarding it when it points at a
68+
* different workspace than the one currently open. Switching workspaces from
69+
* settings keeps the user on the new workspace, so a return url captured in the
70+
* old one would silently navigate them back out of it.
71+
*/
72+
export function resolveSettingsReturnUrl({
73+
storedUrl,
74+
workspaceId,
75+
fallback,
76+
}: ResolveSettingsReturnUrlParams): string {
77+
if (!storedUrl) return fallback
78+
const [, root, storedWorkspaceId] = storedUrl.split('/')
79+
if (root === 'workspace' && storedWorkspaceId && storedWorkspaceId !== workspaceId) {
80+
return fallback
81+
}
82+
return storedUrl
83+
}
84+
6085
export function useSettingsNavigation(): UseSettingsNavigationReturn {
6186
const router = useRouter()
6287
const params = useParams<{ workspaceId?: string }>()
@@ -77,15 +102,18 @@ export function useSettingsNavigation(): UseSettingsNavigationReturn {
77102
[hostContext, session?.user?.id, workspaceId]
78103
)
79104

80-
const popSettingsReturnUrl = useCallback((fallback: string): string => {
81-
try {
82-
const url = sessionStorage.getItem(SETTINGS_RETURN_URL_KEY)
83-
sessionStorage.removeItem(SETTINGS_RETURN_URL_KEY)
84-
return url ?? fallback
85-
} catch {
86-
return fallback
87-
}
88-
}, [])
105+
const popSettingsReturnUrl = useCallback(
106+
(fallback: string): string => {
107+
try {
108+
const storedUrl = sessionStorage.getItem(SETTINGS_RETURN_URL_KEY)
109+
sessionStorage.removeItem(SETTINGS_RETURN_URL_KEY)
110+
return resolveSettingsReturnUrl({ storedUrl, workspaceId, fallback })
111+
} catch {
112+
return fallback
113+
}
114+
},
115+
[workspaceId]
116+
)
89117

90118
const navigateToSettings = useCallback(
91119
(options?: SettingsNavigationOptions) => {

0 commit comments

Comments
 (0)