feat: add drill-down navigation for Instance settings on mobile
Replace inline InstancePanel render with MobileInstancePanel that shows a navigation list for General, Streaming, Storage, and Users sub-panels. Each sub-panel pushes onto the mobile screen stack with MobileScreenHeader.
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useUIStore } from '../../stores/uiStore';
|
||||||
|
import { MobileScreenHeader } from './MobileScreenHeader';
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{
|
||||||
|
id: 'general',
|
||||||
|
label: 'General',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-5 h-5 text-txt-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 010 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.432l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.432l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 010-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 01-.26-1.43l1.297-2.248a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28z" />
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'streaming',
|
||||||
|
label: 'Streaming',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-5 h-5 text-txt-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 10.5l4.72-4.72a.75.75 0 011.28.53v11.38a.75.75 0 01-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25h-9A2.25 2.25 0 002.25 7.5v9a2.25 2.25 0 002.25 2.25z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'storage',
|
||||||
|
label: 'Storage',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-5 h-5 text-txt-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75m16.5 0c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'users',
|
||||||
|
label: 'Users',
|
||||||
|
icon: (
|
||||||
|
<svg className="w-5 h-5 text-txt-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function MobileInstancePanel() {
|
||||||
|
const pushMobileScreen = useUIStore((s) => s.pushMobileScreen);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col h-full bg-surface-base">
|
||||||
|
<MobileScreenHeader title="Instance" />
|
||||||
|
<div className="flex-1 overflow-y-auto">
|
||||||
|
{sections.map((section) => (
|
||||||
|
<button
|
||||||
|
key={section.id}
|
||||||
|
onClick={() => pushMobileScreen(`settings-instance-${section.id}`)}
|
||||||
|
className="w-full flex items-center gap-3 px-4 py-3.5 hover:bg-interactive-hover text-left transition-colors"
|
||||||
|
>
|
||||||
|
{section.icon}
|
||||||
|
<span className="text-sm text-txt-primary flex-1">{section.label}</span>
|
||||||
|
<svg className="w-4 h-4 text-txt-tertiary" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import { AccountPanel } from '../modals/settingsPanels/AccountPanel';
|
|||||||
import { VoicePanel } from '../modals/settingsPanels/VoicePanel';
|
import { VoicePanel } from '../modals/settingsPanels/VoicePanel';
|
||||||
import { ConnectionsPanel } from '../modals/settingsPanels/ConnectionsPanel';
|
import { ConnectionsPanel } from '../modals/settingsPanels/ConnectionsPanel';
|
||||||
import { PrivacyPanel } from '../modals/settingsPanels/PrivacyPanel';
|
import { PrivacyPanel } from '../modals/settingsPanels/PrivacyPanel';
|
||||||
import { InstancePanel } from '../modals/settingsPanels/InstancePanel';
|
|
||||||
|
|
||||||
interface MobileSettingsScreenProps {
|
interface MobileSettingsScreenProps {
|
||||||
initialPanel?: string;
|
initialPanel?: string;
|
||||||
@@ -16,7 +15,6 @@ const panelConfig: Record<string, { title: string; component: React.ReactNode }>
|
|||||||
voice: { title: 'Voice & Audio', component: <VoicePanel /> },
|
voice: { title: 'Voice & Audio', component: <VoicePanel /> },
|
||||||
privacy: { title: 'Privacy', component: <PrivacyPanel /> },
|
privacy: { title: 'Privacy', component: <PrivacyPanel /> },
|
||||||
connections: { title: 'Connections', component: <ConnectionsPanel /> },
|
connections: { title: 'Connections', component: <ConnectionsPanel /> },
|
||||||
instance: { title: 'Instance', component: <InstancePanel /> },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sectionIcons: Record<string, React.ReactNode> = {
|
const sectionIcons: Record<string, React.ReactNode> = {
|
||||||
|
|||||||
@@ -11,12 +11,18 @@ import { MobileDmsScreen } from './MobileDmsScreen';
|
|||||||
import { MobileYouScreen } from './MobileYouScreen';
|
import { MobileYouScreen } from './MobileYouScreen';
|
||||||
import { MobileChatScreen } from './MobileChatScreen';
|
import { MobileChatScreen } from './MobileChatScreen';
|
||||||
import { MobileSettingsScreen } from './MobileSettingsScreen';
|
import { MobileSettingsScreen } from './MobileSettingsScreen';
|
||||||
|
import { MobileInstancePanel } from './MobileInstancePanel';
|
||||||
|
import { MobileScreenHeader } from './MobileScreenHeader';
|
||||||
import { MobileVoiceMiniBar } from './MobileVoiceMiniBar';
|
import { MobileVoiceMiniBar } from './MobileVoiceMiniBar';
|
||||||
import { MobileVoiceFullScreen } from './MobileVoiceFullScreen';
|
import { MobileVoiceFullScreen } from './MobileVoiceFullScreen';
|
||||||
import { MemberSidebar } from './MemberSidebar';
|
import { MemberSidebar } from './MemberSidebar';
|
||||||
import { FriendsPage } from '../chat/FriendsPage';
|
import { FriendsPage } from '../chat/FriendsPage';
|
||||||
import { ExplorePage } from '../chat/ExplorePage';
|
import { ExplorePage } from '../chat/ExplorePage';
|
||||||
import { UserProfileModal } from '../modals/UserProfileModal';
|
import { UserProfileModal } from '../modals/UserProfileModal';
|
||||||
|
import { GeneralPanel } from '../modals/instanceSettingsPanels/GeneralPanel';
|
||||||
|
import { StreamingPanel } from '../modals/instanceSettingsPanels/StreamingPanel';
|
||||||
|
import { StoragePanel } from '../modals/instanceSettingsPanels/StoragePanel';
|
||||||
|
import { UsersPanel } from '../modals/instanceSettingsPanels/UsersPanel';
|
||||||
|
|
||||||
const screenMap: Record<string, (params?: Record<string, string>) => React.ReactNode> = {
|
const screenMap: Record<string, (params?: Record<string, string>) => React.ReactNode> = {
|
||||||
'channel-chat': (params) => <MobileChatScreen params={params} />,
|
'channel-chat': (params) => <MobileChatScreen params={params} />,
|
||||||
@@ -26,7 +32,31 @@ const screenMap: Record<string, (params?: Record<string, string>) => React.React
|
|||||||
'settings-voice': () => <MobileSettingsScreen initialPanel="voice" />,
|
'settings-voice': () => <MobileSettingsScreen initialPanel="voice" />,
|
||||||
'settings-privacy': () => <MobileSettingsScreen initialPanel="privacy" />,
|
'settings-privacy': () => <MobileSettingsScreen initialPanel="privacy" />,
|
||||||
'settings-connections': () => <MobileSettingsScreen initialPanel="connections" />,
|
'settings-connections': () => <MobileSettingsScreen initialPanel="connections" />,
|
||||||
'settings-instance': () => <MobileSettingsScreen initialPanel="instance" />,
|
'settings-instance': () => <MobileInstancePanel />,
|
||||||
|
'settings-instance-general': () => (
|
||||||
|
<div className="flex flex-col h-full bg-surface-base">
|
||||||
|
<MobileScreenHeader title="General" />
|
||||||
|
<div className="flex-1 overflow-y-auto p-4"><GeneralPanel /></div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
'settings-instance-streaming': () => (
|
||||||
|
<div className="flex flex-col h-full bg-surface-base">
|
||||||
|
<MobileScreenHeader title="Streaming" />
|
||||||
|
<div className="flex-1 overflow-y-auto p-4"><StreamingPanel /></div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
'settings-instance-storage': () => (
|
||||||
|
<div className="flex flex-col h-full bg-surface-base">
|
||||||
|
<MobileScreenHeader title="Storage" />
|
||||||
|
<div className="flex-1 overflow-y-auto p-4"><StoragePanel /></div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
'settings-instance-users': () => (
|
||||||
|
<div className="flex flex-col h-full bg-surface-base">
|
||||||
|
<MobileScreenHeader title="Users" />
|
||||||
|
<div className="flex-1 overflow-y-auto p-4"><UsersPanel /></div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
'members': () => <MemberSidebar />,
|
'members': () => <MemberSidebar />,
|
||||||
'voice-full': () => <MobileVoiceFullScreen />,
|
'voice-full': () => <MobileVoiceFullScreen />,
|
||||||
'explore': () => <ExplorePage />,
|
'explore': () => <ExplorePage />,
|
||||||
|
|||||||
Reference in New Issue
Block a user