feat: add call management features with useCall and useRoomCallMembers hooks

- Implemented useCall hook for managing call state and actions.
- Created useRoomCallMembers hook to track active call members in a room.
- Added useRtcConfig for fetching RTC configurations and LiveKit JWT.
- Developed Audio settings component for managing audio devices and settings.
- Introduced device selection and screen sharing options in the Audio settings.
- Persisted audio settings in localStorage for user preferences.
This commit is contained in:
2026-01-23 19:35:25 +11:00
parent c88cb4bca9
commit 94f8466d1c
19 changed files with 3270 additions and 14 deletions

View File

@@ -0,0 +1,142 @@
import { style } from '@vanilla-extract/css';
import { config, DefaultReset, color } from 'folds';
export const CallOverlayContainer = style([
DefaultReset,
{
position: 'fixed',
bottom: config.space.S400,
right: config.space.S400,
zIndex: 9999,
backgroundColor: color.Surface.Container,
borderRadius: config.radii.R400,
padding: config.space.S300,
boxShadow: `0 4px 12px ${color.Other.Shadow}`,
minWidth: '280px',
maxWidth: '400px',
transition: 'box-shadow 0.2s ease',
userSelect: 'none',
},
]);
export const CallOverlayDragging = style({
boxShadow: `0 8px 24px ${color.Other.Shadow}`,
opacity: 0.95,
});
export const CallOverlayFullscreen = style({
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
width: '100vw',
height: '100vh',
maxWidth: 'none',
borderRadius: 0,
display: 'flex',
flexDirection: 'column',
transform: 'none !important',
});
export const CallOverlayHeader = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: config.space.S200,
});
export const CallOverlayControls = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: config.space.S200,
});
export const CallDuration = style({
fontVariantNumeric: 'tabular-nums',
});
export const VideoContainer = style({
position: 'relative',
width: '100%',
aspectRatio: '16 / 9',
backgroundColor: color.Surface.ContainerActive,
borderRadius: config.radii.R300,
marginBottom: config.space.S200,
overflow: 'hidden',
selectors: {
[`${CallOverlayFullscreen} &`]: {
flex: 1,
aspectRatio: 'unset',
borderRadius: 0,
marginBottom: 0,
},
},
});
export const LocalVideo = style({
position: 'absolute',
bottom: config.space.S200,
right: config.space.S200,
width: '80px',
aspectRatio: '4 / 3',
backgroundColor: color.Surface.ContainerLine,
borderRadius: config.radii.R300,
overflow: 'hidden',
});
export const VideoElement = style({
width: '100%',
height: '100%',
objectFit: 'cover',
});
export const ScreenShareContainer = style({
position: 'relative',
width: '100%',
aspectRatio: '16 / 9',
backgroundColor: color.Surface.ContainerActive,
borderRadius: config.radii.R300,
marginBottom: config.space.S200,
overflow: 'hidden',
border: `2px solid ${color.Primary.Main}`,
selectors: {
[`${CallOverlayFullscreen} &`]: {
flex: 1,
aspectRatio: 'unset',
borderRadius: 0,
marginBottom: 0,
},
},
});
export const ScreenShareLabel = style({
position: 'absolute',
top: config.space.S100,
left: config.space.S100,
backgroundColor: 'rgba(0, 0, 0, 0.7)',
color: 'white',
padding: `${config.space.S100} ${config.space.S200}`,
borderRadius: config.radii.R300,
fontSize: '0.75rem',
display: 'flex',
alignItems: 'center',
gap: config.space.S100,
zIndex: 1,
});
export const ScreenShareVideoContainer = style({
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#000',
});
export const ScreenShareVideo = style({
width: '100%',
height: '100%',
objectFit: 'contain',
});