fix: give Explore its own /explore route so PiP navigates back to voice correctly
The Explore page shared /channels/@me with Friends, differentiated by a showExplore UI flag. When PiP navigated to a voice channel, the stale flag caused MainContent to render text chat instead of the voice grid. Replace the flag with a dedicated /explore route so the URL is the single source of truth.
This commit is contained in:
@@ -52,6 +52,14 @@ export function App() {
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/explore"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppLayout />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="/" element={<Navigate to="/channels/@me" replace />} />
|
||||
<Route path="*" element={<Navigate to="/channels/@me" replace />} />
|
||||
</Routes>
|
||||
|
||||
@@ -2,14 +2,12 @@ import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react'
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useExploreStore, type TaggedExploreServer } from '../../stores/exploreStore';
|
||||
import { useServerStore } from '../../stores/serverStore';
|
||||
import { useUIStore } from '../../stores/uiStore';
|
||||
import { LoadingSpinner } from '../ui/LoadingSpinner';
|
||||
import { getServerGradient } from '../../utils/gradients';
|
||||
|
||||
export function ExplorePage() {
|
||||
const navigate = useNavigate();
|
||||
const setCurrentServer = useServerStore((s) => s.setCurrentServer);
|
||||
const setShowExplore = useUIStore((s) => s.setShowExplore);
|
||||
|
||||
const servers = useExploreStore((s) => s.servers);
|
||||
const myRequests = useExploreStore((s) => s.myRequests);
|
||||
@@ -47,7 +45,6 @@ export function ExplorePage() {
|
||||
}, []);
|
||||
|
||||
const handleJoinSuccess = (serverId: string) => {
|
||||
setShowExplore(false);
|
||||
setCurrentServer(serverId);
|
||||
navigate(`/channels/${serverId}`);
|
||||
};
|
||||
|
||||
@@ -183,14 +183,15 @@ export function AppLayout() {
|
||||
// Handle route params
|
||||
useEffect(() => {
|
||||
if (serverId === '@me') {
|
||||
if (!useUIStore.getState().showExplore) {
|
||||
setShowDms(true);
|
||||
}
|
||||
setShowDms(true);
|
||||
setCurrentServer(null);
|
||||
} else if (serverId) {
|
||||
setShowDms(false);
|
||||
setCurrentServer(serverId);
|
||||
loadServerDetail(serverId);
|
||||
} else {
|
||||
setShowDms(false);
|
||||
setCurrentServer(null);
|
||||
}
|
||||
}, [serverId, setCurrentServer, loadServerDetail, setShowDms]);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useServerStore, getChannelOrigin } from '../../stores/serverStore';
|
||||
import { useChatStore } from '../../stores/chatStore';
|
||||
import { useUIStore } from '../../stores/uiStore';
|
||||
@@ -35,6 +35,7 @@ export function ChannelSidebar() {
|
||||
const toggleMic = useVoiceStore((s) => s.toggleMic);
|
||||
const toggleDeafen = useVoiceStore((s) => s.toggleDeafen);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const handleMicToggle = async () => {
|
||||
toggleMic();
|
||||
@@ -142,7 +143,7 @@ export function ChannelSidebar() {
|
||||
<div
|
||||
onClick={handleHomeClick}
|
||||
className={`flex items-center gap-3 px-2 h-[42px] rounded-[4px] cursor-pointer mb-[2px] transition-colors group ${
|
||||
!currentChannelId
|
||||
!currentChannelId && location.pathname !== '/explore'
|
||||
? 'bg-interactive-selected text-white'
|
||||
: 'text-txt-tertiary hover:bg-interactive-hover hover:text-txt-secondary'
|
||||
}`}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useServerStore } from '../../stores/serverStore';
|
||||
import { useChatStore } from '../../stores/chatStore';
|
||||
import { useUIStore } from '../../stores/uiStore';
|
||||
@@ -30,7 +31,8 @@ export function MainContent() {
|
||||
const isLiveKitConnected = useVoiceStore((s) => s.isLiveKitConnected);
|
||||
const connectionError = useVoiceStore((s) => s.connectionError);
|
||||
const showDms = useUIStore((s) => s.showDms);
|
||||
const showExplore = useUIStore((s) => s.showExplore);
|
||||
const location = useLocation();
|
||||
const isExplorePage = location.pathname === '/explore';
|
||||
const activeDmCall = useVoiceStore((s) => s.activeDmCall);
|
||||
const outgoingCall = useVoiceStore((s) => s.outgoingCall);
|
||||
const dmChannels = useServerStore((s) => s.dmChannels);
|
||||
@@ -62,9 +64,9 @@ export function MainContent() {
|
||||
const channel = channels.find(c => c.id === currentChannelId);
|
||||
const isVoiceChannel = channel?.type === 'voice' || channel?.type === 'video';
|
||||
|
||||
if (showDms || showExplore || !currentServerId) {
|
||||
if (showDms || isExplorePage || !currentServerId) {
|
||||
if (!currentChannelId) {
|
||||
if (showExplore) return <ExplorePage />;
|
||||
if (isExplorePage) return <ExplorePage />;
|
||||
return <FriendsPage />;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useServerStore } from '../../stores/serverStore';
|
||||
import { useChatStore } from '../../stores/chatStore';
|
||||
import { useUIStore } from '../../stores/uiStore';
|
||||
@@ -120,14 +120,13 @@ export function ServerSidebar() {
|
||||
const dmChannels = useServerStore((s) => s.dmChannels);
|
||||
const showDms = useUIStore((s) => s.showDms);
|
||||
const setShowDms = useUIStore((s) => s.setShowDms);
|
||||
const showExplore = useUIStore((s) => s.showExplore);
|
||||
const setShowExplore = useUIStore((s) => s.setShowExplore);
|
||||
const openModal = useUIStore((s) => s.openModal);
|
||||
const addToast = useUIStore((s) => s.addToast);
|
||||
const setCurrentChannel = useChatStore((s) => s.setCurrentChannel);
|
||||
const unreadChannels = useChatStore((s) => s.unreadChannels);
|
||||
const instances = useInstanceStore((s) => s.instances);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
// Group servers by origin
|
||||
const groupedServers = useMemo(() => {
|
||||
@@ -182,7 +181,6 @@ export function ServerSidebar() {
|
||||
}
|
||||
setCurrentServer(serverId);
|
||||
setShowDms(false);
|
||||
setShowExplore(false);
|
||||
navigate(`/channels/${serverId}`);
|
||||
};
|
||||
|
||||
@@ -194,10 +192,9 @@ export function ServerSidebar() {
|
||||
};
|
||||
|
||||
const handleExploreClick = () => {
|
||||
setShowExplore(true);
|
||||
setCurrentServer(null);
|
||||
setCurrentChannel(null);
|
||||
navigate('/channels/@me');
|
||||
navigate('/explore');
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -276,7 +273,7 @@ export function ServerSidebar() {
|
||||
<SidebarItem
|
||||
id="explore"
|
||||
name="Explore Servers"
|
||||
active={showExplore}
|
||||
active={location.pathname === '/explore'}
|
||||
onClick={handleExploreClick}
|
||||
type="action"
|
||||
actionType="explore"
|
||||
|
||||
@@ -28,7 +28,6 @@ interface UIState {
|
||||
modalData: Record<string, unknown>;
|
||||
isMobile: boolean;
|
||||
showDms: boolean;
|
||||
showExplore: boolean;
|
||||
imagePreviewUrl: string | null;
|
||||
userProfilePopout: {
|
||||
user: User | null;
|
||||
@@ -41,7 +40,6 @@ interface UIState {
|
||||
closeModal: () => void;
|
||||
setIsMobile: (isMobile: boolean) => void;
|
||||
setShowDms: (show: boolean) => void;
|
||||
setShowExplore: (show: boolean) => void;
|
||||
openImagePreview: (url: string) => void;
|
||||
closeImagePreview: () => void;
|
||||
openUserProfile: (user: User, position: { top: number; left: number }) => void;
|
||||
@@ -66,7 +64,6 @@ export const useUIStore = create<UIState>()(
|
||||
modalData: {},
|
||||
isMobile: false,
|
||||
showDms: false,
|
||||
showExplore: false,
|
||||
imagePreviewUrl: null,
|
||||
userProfilePopout: {
|
||||
user: null,
|
||||
@@ -92,8 +89,7 @@ export const useUIStore = create<UIState>()(
|
||||
}
|
||||
},
|
||||
|
||||
setShowDms: (show) => set({ showDms: show, ...(show ? { showExplore: false } : {}) }),
|
||||
setShowExplore: (show) => set({ showExplore: show, ...(show ? { showDms: false } : {}) }),
|
||||
setShowDms: (show) => set({ showDms: show }),
|
||||
|
||||
openImagePreview: (url) => set({ activeModal: 'imagePreview', imagePreviewUrl: url }),
|
||||
closeImagePreview: () => set({ activeModal: null, imagePreviewUrl: null }),
|
||||
|
||||
Reference in New Issue
Block a user