feat(auth): add Copy Workspace Key button on Next.js auth page for desktop SSO fallback
This commit is contained in:
@@ -22,6 +22,7 @@ function AuthPageInner() {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const [ssoProcessing, setSsoProcessing] = React.useState(false);
|
||||
const [ssoToken, setSsoToken] = React.useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (status === "authenticated" && session?.user?.email) {
|
||||
@@ -34,6 +35,7 @@ function AuthPageInner() {
|
||||
.then((r) => r.json())
|
||||
.then((data) => {
|
||||
if (data.token) {
|
||||
setSsoToken(data.token);
|
||||
// Deep-link redirect back to the VibnCode desktop app
|
||||
window.location.href = `vibncode://auth/callback?token=${data.token}`;
|
||||
} else {
|
||||
@@ -65,6 +67,8 @@ function AuthPageInner() {
|
||||
}, [status, session, router, searchParams]);
|
||||
|
||||
if (status === "loading" || ssoProcessing) {
|
||||
const deepLink = ssoToken ? `vibncode://auth/callback?token=${ssoToken}` : "";
|
||||
|
||||
return (
|
||||
<div
|
||||
className="new-site-wrapper"
|
||||
@@ -73,43 +77,133 @@ function AuthPageInner() {
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
minHeight: "100vh",
|
||||
background: "radial-gradient(circle at 20% 20%, #1c1c1f, #0b0b0f 60%)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: "16px",
|
||||
}}
|
||||
>
|
||||
{ssoToken ? (
|
||||
<div
|
||||
style={{
|
||||
width: "24px",
|
||||
height: "24px",
|
||||
borderRadius: "50%",
|
||||
border: "2px solid oklch(0.20 0.009 60)",
|
||||
borderTopColor: "var(--accent)",
|
||||
animation: "spin .9s linear infinite",
|
||||
}}
|
||||
/>
|
||||
<style>{`
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
`}</style>
|
||||
<div
|
||||
style={{
|
||||
color: "var(--fg-mute)",
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: "11px",
|
||||
letterSpacing: "0.1em",
|
||||
textTransform: "uppercase",
|
||||
border: "1px solid rgba(255, 255, 255, 0.08)",
|
||||
background: "rgba(12, 12, 16, 0.85)",
|
||||
borderRadius: "20px",
|
||||
padding: "32px",
|
||||
boxShadow: "0 18px 50px rgba(0, 0, 0, 0.35)",
|
||||
backdropFilter: "blur(16px)",
|
||||
textAlign: "center",
|
||||
width: "min(480px, 90vw)",
|
||||
color: "#f5f5f5",
|
||||
fontFamily: "-apple-system, sans-serif",
|
||||
}}
|
||||
>
|
||||
{ssoProcessing
|
||||
? "Authorizing VibnCode Desktop..."
|
||||
: "Checking session"}
|
||||
<div
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "56px",
|
||||
height: "56px",
|
||||
borderRadius: "50%",
|
||||
border: "1px solid rgba(255, 255, 255, 0.12)",
|
||||
background: "linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02))",
|
||||
fontSize: "28px",
|
||||
marginBottom: "20px",
|
||||
}}
|
||||
>
|
||||
✓
|
||||
</div>
|
||||
<h1 style={{ margin: "0 0 12px", fontSize: "24px", fontWeight: "600", color: "#f8f8f8" }}>
|
||||
Authentication Successful
|
||||
</h1>
|
||||
<p style={{ margin: "0 0 24px", color: "#cfcfd4", fontSize: "14px" }}>
|
||||
Signed in. Redirecting to VibnCode...
|
||||
</p>
|
||||
<div
|
||||
style={{
|
||||
margin: "0 auto 20px",
|
||||
width: "44px",
|
||||
height: "44px",
|
||||
borderRadius: "50%",
|
||||
border: "4px solid rgba(255, 255, 255, 0.15)",
|
||||
borderTopColor: "#ffffff",
|
||||
animation: "spin 1s linear infinite",
|
||||
}}
|
||||
/>
|
||||
<style>{`
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
`}</style>
|
||||
<p style={{ margin: "0 0 16px", color: "#b6b6bd", lineHeight: "1.6", fontSize: "13px" }}>
|
||||
If the app doesn't open automatically, copy your Workspace API Key below and paste it into the connection card.
|
||||
</p>
|
||||
<div style={{ display: "flex", gap: "10px", justifyContent: "center", marginBottom: "16px" }}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(ssoToken);
|
||||
alert("Workspace API Key copied!");
|
||||
}}
|
||||
style={{
|
||||
padding: "10px 16px",
|
||||
borderRadius: "999px",
|
||||
border: "1px solid rgba(255, 255, 255, 0.18)",
|
||||
background: "rgba(255, 255, 255, 0.12)",
|
||||
color: "#ffffff",
|
||||
cursor: "pointer",
|
||||
fontSize: "13px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Copy Workspace Key
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
padding: "12px",
|
||||
borderRadius: "12px",
|
||||
background: "rgba(255, 255, 255, 0.06)",
|
||||
fontFamily: "monospace",
|
||||
fontSize: "12px",
|
||||
wordBreak: "break-all",
|
||||
color: "#d8d8df",
|
||||
}}
|
||||
>
|
||||
{ssoToken}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: "16px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "24px",
|
||||
height: "24px",
|
||||
borderRadius: "50%",
|
||||
border: "2px solid oklch(0.20 0.009 60)",
|
||||
borderTopColor: "var(--accent)",
|
||||
animation: "spin .9s linear infinite",
|
||||
}}
|
||||
/>
|
||||
<style>{`
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
`}</style>
|
||||
<div
|
||||
style={{
|
||||
color: "var(--fg-mute)",
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: "11px",
|
||||
letterSpacing: "0.1em",
|
||||
textTransform: "uppercase",
|
||||
}}
|
||||
>
|
||||
Checking session
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user