Skip to content

Commit e5c2f7d

Browse files
committed
feat: add support for sould studio
1 parent 0aba53d commit e5c2f7d

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use client'
2+
3+
import { useEffect, useState } from 'react'
4+
5+
/**
6+
* Relays OAuth callback codes to the Soul Studio desktop app via deep-link.
7+
*
8+
* When the URL contains `?source=desktop&code=...`, this component redirects
9+
* to `soulstudio://auth-callback?code=...` so the desktop app can complete
10+
* the Convex Auth flow using its locally stored verifier.
11+
*/
12+
export function DesktopAuthRelay() {
13+
const [relaying, setRelaying] = useState(false)
14+
15+
useEffect(() => {
16+
const params = new URLSearchParams(window.location.search)
17+
const source = params.get('source')
18+
const code = params.get('code')
19+
20+
if (source !== 'desktop' || !code) return
21+
22+
setRelaying(true)
23+
24+
// Redirect to the desktop app via deep-link
25+
window.location.href = `soulstudio://auth-callback?code=${encodeURIComponent(code)}`
26+
}, [])
27+
28+
if (!relaying) return null
29+
30+
return (
31+
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-bg/95">
32+
<div className="text-center space-y-3">
33+
<p className="text-lg font-medium text-text">Returning to Soul Studio...</p>
34+
<p className="text-sm text-text-secondary">
35+
If the app doesn&apos;t open automatically,{' '}
36+
<button
37+
type="button"
38+
className="underline hover:text-text"
39+
onClick={() => {
40+
const params = new URLSearchParams(window.location.search)
41+
const code = params.get('code')
42+
if (code) {
43+
window.location.href = `soulstudio://auth-callback?code=${encodeURIComponent(code)}`
44+
}
45+
}}
46+
>
47+
click here
48+
</button>
49+
.
50+
</p>
51+
</div>
52+
</div>
53+
)
54+
}

apps/web/components/layout/providers.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'use client'
22

3+
import { DesktopAuthRelay } from '@/components/auth/desktop-auth-relay'
34
import { KeyboardShortcutsProvider } from '@/components/shortcuts/keyboard-shortcuts-provider'
45
import { OpenPanelIdentify } from '@/components/user/openpanel-identify'
56
import { UserBootstrap } from '@/components/user/user-bootstrap'
67
import { ConvexAuthProvider } from '@convex-dev/auth/react'
78
import { ConvexReactClient } from 'convex/react'
89
import { ThemeProvider as NextThemesProvider } from 'next-themes'
910
import { NuqsAdapter } from 'nuqs/adapters/next/app'
10-
import type { ReactNode } from 'react'
11+
import { type ReactNode, useCallback } from 'react'
1112
import { Toaster } from 'sonner'
1213

1314
// Convex client: use real URL when set; otherwise placeholder so ConvexProvider is always present
@@ -29,6 +30,14 @@ interface ProvidersProps {
2930
* - Keyboard shortcuts (power users)
3031
*/
3132
export function Providers({ children }: ProvidersProps) {
33+
// Skip automatic code handling when the OAuth callback is for the desktop app.
34+
// The DesktopAuthRelay component will relay the code via deep-link instead.
35+
const shouldHandleCode = useCallback(() => {
36+
if (typeof window === 'undefined') return true
37+
const params = new URLSearchParams(window.location.search)
38+
return params.get('source') !== 'desktop'
39+
}, [])
40+
3241
const content = (
3342
<NuqsAdapter>
3443
<NextThemesProvider
@@ -55,7 +64,8 @@ export function Providers({ children }: ProvidersProps) {
5564
)
5665

5766
return (
58-
<ConvexAuthProvider client={convex}>
67+
<ConvexAuthProvider client={convex} shouldHandleCode={shouldHandleCode}>
68+
<DesktopAuthRelay />
5969
<UserBootstrap />
6070
<OpenPanelIdentify />
6171
{content}

0 commit comments

Comments
 (0)