Simplify embedded mode navigation to stay within iframe
Remove the complex token-passing logic for new tabs in embedded mode. Instead, navigation now stays within the iframe for a simpler UX. - Remove handleNewWindowClick auth handler from sidebar items - Simplify useNewWindow hook to navigate within iframe when embedded - Fix authenticate route to use saveResponse instead of saveToken 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,26 +36,10 @@ export type SidebarItemType = {
|
|||||||
export const ApSidebarItem = (item: SidebarItemType) => {
|
export const ApSidebarItem = (item: SidebarItemType) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { state } = useSidebar();
|
const { state } = useSidebar();
|
||||||
const { embedState } = useEmbedding();
|
|
||||||
const isLinkActive =
|
const isLinkActive =
|
||||||
location.pathname.startsWith(item.to) || item.isActive?.(location.pathname);
|
location.pathname.startsWith(item.to) || item.isActive?.(location.pathname);
|
||||||
const isCollapsed = state === 'collapsed';
|
const isCollapsed = state === 'collapsed';
|
||||||
|
|
||||||
// Handle new window clicks with authentication in embedded mode
|
|
||||||
const handleNewWindowClick = (e: React.MouseEvent) => {
|
|
||||||
if (item.newWindow && embedState.isEmbedded) {
|
|
||||||
e.preventDefault();
|
|
||||||
const token = authenticationSession.getToken();
|
|
||||||
if (token) {
|
|
||||||
const encodedRedirect = encodeURIComponent(item.to);
|
|
||||||
const authUrl = `/authenticate?token=${encodeURIComponent(token)}&redirect=${encodedRedirect}`;
|
|
||||||
window.open(authUrl, '_blank', 'noopener');
|
|
||||||
} else {
|
|
||||||
window.open(item.to, '_blank', 'noopener noreferrer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarMenuItem
|
<SidebarMenuItem
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
@@ -69,7 +53,6 @@ export const ApSidebarItem = (item: SidebarItemType) => {
|
|||||||
to={item.to}
|
to={item.to}
|
||||||
target={item.newWindow ? '_blank' : ''}
|
target={item.newWindow ? '_blank' : ''}
|
||||||
rel={item.newWindow ? 'noopener noreferrer' : undefined}
|
rel={item.newWindow ? 'noopener noreferrer' : undefined}
|
||||||
onClick={handleNewWindowClick}
|
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({ variant: 'ghost', size: 'icon' }),
|
buttonVariants({ variant: 'ghost', size: 'icon' }),
|
||||||
isLinkActive && 'bg-sidebar-accent hover:!bg-sidebar-accent',
|
isLinkActive && 'bg-sidebar-accent hover:!bg-sidebar-accent',
|
||||||
@@ -102,7 +85,6 @@ export const ApSidebarItem = (item: SidebarItemType) => {
|
|||||||
to={item.to}
|
to={item.to}
|
||||||
target={item.newWindow ? '_blank' : ''}
|
target={item.newWindow ? '_blank' : ''}
|
||||||
rel={item.newWindow ? 'noopener noreferrer' : undefined}
|
rel={item.newWindow ? 'noopener noreferrer' : undefined}
|
||||||
onClick={handleNewWindowClick}
|
|
||||||
>
|
>
|
||||||
<div className="w-full flex items-center justify-between gap-2">
|
<div className="w-full flex items-center justify-between gap-2">
|
||||||
<div className="flex items-center gap-2 w-full">
|
<div className="flex items-center gap-2 w-full">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const AuthenticatePage = () => {
|
|||||||
} else if (token) {
|
} else if (token) {
|
||||||
// Handle standalone JWT token (from embedded mode new tab)
|
// Handle standalone JWT token (from embedded mode new tab)
|
||||||
// Save token directly to localStorage for persistence in new tabs
|
// Save token directly to localStorage for persistence in new tabs
|
||||||
authenticationSession.saveToken(token);
|
authenticationSession.saveResponse({ token }, false);
|
||||||
navigate(redirectTo);
|
navigate(redirectTo);
|
||||||
}
|
}
|
||||||
}, [response, token, redirectTo, navigate]);
|
}, [response, token, redirectTo, navigate]);
|
||||||
|
|||||||
@@ -8,24 +8,12 @@ export const useNewWindow = () => {
|
|||||||
const { embedState } = useEmbedding();
|
const { embedState } = useEmbedding();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
if (embedState.isEmbedded) {
|
if (embedState.isEmbedded) {
|
||||||
// In embedded mode, open new tab with authentication token
|
// In embedded mode, navigate within the iframe (don't open new tabs)
|
||||||
return (route: string, searchParams?: string) => {
|
return (route: string, searchParams?: string) =>
|
||||||
const token = authenticationSession.getToken();
|
|
||||||
const fullRoute = `${route}${searchParams ? '?' + searchParams : ''}`;
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
// Pass token for auto-authentication in new tab
|
|
||||||
const encodedRedirect = encodeURIComponent(fullRoute);
|
|
||||||
const authUrl = `/authenticate?token=${encodeURIComponent(token)}&redirect=${encodedRedirect}`;
|
|
||||||
window.open(authUrl, '_blank', 'noopener');
|
|
||||||
} else {
|
|
||||||
// Fallback to in-iframe navigation if no token
|
|
||||||
navigate({
|
navigate({
|
||||||
pathname: route,
|
pathname: route,
|
||||||
search: searchParams,
|
search: searchParams,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return (route: string, searchParams?: string) =>
|
return (route: string, searchParams?: string) =>
|
||||||
window.open(
|
window.open(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { Bot, RefreshCw, AlertTriangle, Loader2, Sparkles, RotateCcw, ChevronDown } from 'lucide-react';
|
import { Bot, RefreshCw, AlertTriangle, Loader2, ExternalLink, Sparkles, RotateCcw, ChevronDown } from 'lucide-react';
|
||||||
import api from '../api/client';
|
import api from '../api/client';
|
||||||
import { usePlanFeatures } from '../hooks/usePlanFeatures';
|
import { usePlanFeatures } from '../hooks/usePlanFeatures';
|
||||||
import { UpgradePrompt } from '../components/UpgradePrompt';
|
import { UpgradePrompt } from '../components/UpgradePrompt';
|
||||||
|
|||||||
Reference in New Issue
Block a user