(feat): improve mobile
Some checks failed
/ release (push) Has been cancelled
/ build-web (push) Has been cancelled
/ build-desktop (linux) (push) Has been cancelled
/ build-mobile (push) Has been cancelled

(feat): add camera sharing
(fix): vite tauri connection
(fix): methanium/ui theme not applied to call popout
This commit is contained in:
Alois 2026-08-01 01:25:41 +02:00
commit 62aaa7c01d
Signed by: alois
SSH key fingerprint: SHA256:GBzT2DXvAuGV9XIV5W3WrzVpjU54FThmxHXdbz95J24
31 changed files with 1915 additions and 859 deletions

View file

@ -178,6 +178,13 @@ export default function Base({
Track.Source.ScreenShare,
);
const screenSharePreview = participant?.attributes["screenSharePreview"];
const cameraPublication = getTrackPublicationBySource(
participant,
Track.Source.Camera,
);
const cameraDisabled = useCall((state) =>
user ? state.disabledCameraParticipantIds.includes(user.UserId) : false,
);
const [ownId, setOwnId] = useState(0);
useEffect(() => {
@ -271,7 +278,7 @@ export default function Base({
flush && !fill && "border-x-0!",
type === "user" &&
isSpeaking &&
"border-4 border-(--primary-foreground-alt)/75!",
"border-4 border-(--primary-foreground-alt)/75! rounded-lg",
)}
>
<div className="z-20 absolute bottom-0 left-0 w-full h-full flex justify-start items-end p-2">
@ -341,23 +348,31 @@ export default function Base({
</div>
) : null)}
{type === "user" && (
<Avatar
style={{
width: "32cqh",
height: "32cqh",
}}
>
<AvatarImage src={user.Avatar} />
<AvatarFallback
{type === "user" &&
(cameraPublication?.track && !cameraDisabled ? (
<VideoViewer
fill={fill}
flush={flush}
participantId={participant.identity}
publication={cameraPublication}
/>
) : (
<Avatar
style={{
fontSize: "11cqh",
width: "32cqh",
height: "32cqh",
}}
>
{user.Display.slice(0, 2).toUpperCase()}
</AvatarFallback>
</Avatar>
)}
<AvatarImage src={user.Avatar} />
<AvatarFallback
style={{
fontSize: "11cqh",
}}
>
{user.Display.slice(0, 2).toUpperCase()}
</AvatarFallback>
</Avatar>
))}
</div>
</div>
}

View file

@ -6,7 +6,7 @@ import {
Slider,
} from "@methanium/ui";
import type { User } from "@tensamin/user/context";
import { useCall } from "../../store";
import { setParticipantCameraDisabled, useCall } from "../../store";
import { useState } from "react";
function EmptyCheckboxIndicator({ checked }: { checked: boolean }) {
@ -33,6 +33,9 @@ export default function ContextMenu({
const watchedStreamParticipantIds = useCall(
(state) => state.watchedStreamParticipantIds,
);
const cameraDisabled = useCall((state) =>
state.disabledCameraParticipantIds.includes(user.UserId),
);
return (
<ContextMenuContent className="p-1">
@ -71,6 +74,19 @@ export default function ContextMenu({
<p>Mute Soundboard</p>
<EmptyCheckboxIndicator checked={soundboardMuted} />
</ContextMenuCheckboxItem>
{user.UserId !== ownId ? (
<ContextMenuCheckboxItem
checked={cameraDisabled}
onCheckedChange={(checked) =>
setParticipantCameraDisabled(user.UserId, checked)
}
onSelect={(e) => e.preventDefault()}
className="flex justify-between"
>
<p>Disable camera</p>
<EmptyCheckboxIndicator checked={cameraDisabled} />
</ContextMenuCheckboxItem>
) : null}
<ContextMenuCheckboxItem
checked={serverDeafened}
onCheckedChange={setServerDeafened}