Block route rendering until auth and NSFW node classification are resolved
Hop-State: A_06FP9N1CECVZN3TAJZTJJ4R Hop-Proposal: R_06FP9N09YGWW0S9XV4S3XNG Hop-Task: T_06FP9MBVAVXP6ZRX0VG9RSG Hop-Attempt: AT_06FP9MBVARDT7GQQ58C9WG0
This commit is contained in:
@@ -10,6 +10,7 @@ import { Bot, Network, Server, EyeOff } from 'lucide-react';
|
|||||||
import { useAuth } from '@/lib/contexts/AuthContext';
|
import { useAuth } from '@/lib/contexts/AuthContext';
|
||||||
import { signedAPI } from '@/lib/api/signed-fetch';
|
import { signedAPI } from '@/lib/api/signed-fetch';
|
||||||
import { AvatarImage } from '@/components/AvatarImage';
|
import { AvatarImage } from '@/components/AvatarImage';
|
||||||
|
import { useRuntimeConfig } from '@/lib/contexts/ConfigContext';
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -85,6 +86,7 @@ interface SwarmPost {
|
|||||||
|
|
||||||
export default function ExplorePage() {
|
export default function ExplorePage() {
|
||||||
const { user, did, handle } = useAuth();
|
const { user, did, handle } = useAuth();
|
||||||
|
const { config } = useRuntimeConfig();
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [activeTab, setActiveTab] = useState<'node' | 'swarm' | 'users' | 'search'>('node');
|
const [activeTab, setActiveTab] = useState<'node' | 'swarm' | 'users' | 'search'>('node');
|
||||||
const [nodePosts, setNodePosts] = useState<Post[]>([]);
|
const [nodePosts, setNodePosts] = useState<Post[]>([]);
|
||||||
@@ -99,17 +101,7 @@ export default function ExplorePage() {
|
|||||||
const [loadingMore, setLoadingMore] = useState(false);
|
const [loadingMore, setLoadingMore] = useState(false);
|
||||||
const [hasMoreNode, setHasMoreNode] = useState(true);
|
const [hasMoreNode, setHasMoreNode] = useState(true);
|
||||||
const [hasMoreSwarm, setHasMoreSwarm] = useState(true);
|
const [hasMoreSwarm, setHasMoreSwarm] = useState(true);
|
||||||
const [isNsfwNode, setIsNsfwNode] = useState(false);
|
const isNsfwNode = config?.isNsfw === true;
|
||||||
|
|
||||||
// Fetch node info to check if NSFW
|
|
||||||
useEffect(() => {
|
|
||||||
fetch('/api/node')
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => {
|
|
||||||
setIsNsfwNode(data.isNsfw || false);
|
|
||||||
})
|
|
||||||
.catch(() => { });
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Load node posts (local only)
|
// Load node posts (local only)
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ import { usePathname } from 'next/navigation';
|
|||||||
import { Sidebar } from './Sidebar';
|
import { Sidebar } from './Sidebar';
|
||||||
import { RightSidebar } from './RightSidebar';
|
import { RightSidebar } from './RightSidebar';
|
||||||
import { useAuth } from '@/lib/contexts/AuthContext';
|
import { useAuth } from '@/lib/contexts/AuthContext';
|
||||||
|
import { useRuntimeConfig } from '@/lib/contexts/ConfigContext';
|
||||||
|
import { isAppBootstrapReady } from '@/lib/bootstrap/readiness';
|
||||||
|
|
||||||
export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
||||||
const { loading } = useAuth();
|
const { loading } = useAuth();
|
||||||
|
const { isLoading: configLoading } = useRuntimeConfig();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
||||||
// Paths that should NOT have the app layout
|
// Paths that should NOT have the app layout
|
||||||
@@ -17,7 +20,7 @@ export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
|||||||
// Hide right sidebar on chat page for more space
|
// Hide right sidebar on chat page for more space
|
||||||
const hideRightSidebar = false;
|
const hideRightSidebar = false;
|
||||||
|
|
||||||
if (loading) {
|
if (!isAppBootstrapReady({ authLoading: loading, configLoading })) {
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { isAppBootstrapReady } from './readiness';
|
||||||
|
|
||||||
|
describe('isAppBootstrapReady', () => {
|
||||||
|
it('blocks route rendering while authentication is unresolved', () => {
|
||||||
|
expect(isAppBootstrapReady({ authLoading: true, configLoading: false })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('blocks route rendering while node classification is unresolved', () => {
|
||||||
|
expect(isAppBootstrapReady({ authLoading: false, configLoading: true })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows route rendering only after both dependencies are resolved', () => {
|
||||||
|
expect(isAppBootstrapReady({ authLoading: false, configLoading: false })).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export function isAppBootstrapReady({
|
||||||
|
authLoading,
|
||||||
|
configLoading,
|
||||||
|
}: {
|
||||||
|
authLoading: boolean;
|
||||||
|
configLoading: boolean;
|
||||||
|
}): boolean {
|
||||||
|
return !authLoading && !configLoading;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user