Phase 2 frontend: voice store, VoiceChannel, VoicePanel, VoiceControls
Frontend:
- stores/voice.ts: Zustand store for voice state (join, leave, mute, deafen, video, screen share)
- VoiceChannel.tsx: sidebar item showing 🔊 channel name with participant count
- VoicePanel.tsx: box-drawn frame with participant list and controls
- VoiceControls.tsx: [m] mute, [d] deafen, [cam] video, [share] screen, [x] disconnect
- ChannelList.tsx: integrated VoiceChannel for voice-type channels
- Layout.tsx: added VoicePanel above chat area
Deps:
- Added livekit-client, @livekit/components-react
- NODE_ENV fix for dev deps installation
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useServerStore } from '../stores/server.ts';
|
||||
import { useChannelStore } from '../stores/channel.ts';
|
||||
import { VoiceChannel } from './VoiceChannel.tsx';
|
||||
|
||||
export function ChannelList() {
|
||||
const activeServerId = useServerStore((state) => state.activeServerId);
|
||||
@@ -44,22 +45,26 @@ export function ChannelList() {
|
||||
<div key={category} className="mb-3">
|
||||
<div className="text-gb-fg-t text-xs uppercase mb-1">{category}</div>
|
||||
<div className="text-gb-fg-f text-xs mb-1">---</div>
|
||||
{list.map((channel) => (
|
||||
<button
|
||||
key={channel.id}
|
||||
onClick={() => setActiveChannel(channel.id)}
|
||||
className={`w-full text-left px-2 py-1 rounded-sm flex items-center gap-2 ${
|
||||
channel.id === activeChannelId ? 'terminal-active' : 'hover:bg-gb-bg-t text-gb-fg-s'
|
||||
}`}
|
||||
>
|
||||
{channel.type === 'voice' ? (
|
||||
<span className="text-gb-fg-f">♫</span>
|
||||
) : (
|
||||
{list.map((channel) =>
|
||||
channel.type === 'voice' ? (
|
||||
<VoiceChannel
|
||||
key={channel.id}
|
||||
channelId={channel.id}
|
||||
channelName={channel.name}
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
key={channel.id}
|
||||
onClick={() => setActiveChannel(channel.id)}
|
||||
className={`w-full text-left px-2 py-1 rounded-sm flex items-center gap-2 ${
|
||||
channel.id === activeChannelId ? 'terminal-active' : 'hover:bg-gb-bg-t text-gb-fg-s'
|
||||
}`}
|
||||
>
|
||||
<span className="text-gb-fg-f">#</span>
|
||||
)}
|
||||
<span className="truncate">{channel.name}</span>
|
||||
</button>
|
||||
))}
|
||||
<span className="truncate">{channel.name}</span>
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user