mirror of
https://github.com/balzack/databag.git
synced 2025-04-23 18:15:19 +00:00
fix webrtc video position
This commit is contained in:
parent
35f2c7d58d
commit
1b73422ab0
@ -45,10 +45,32 @@
|
||||
padding-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.fullFrame {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.boxFrame {
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
right: 5%;
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
}
|
||||
|
||||
.full {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.buttons {
|
||||
background-color: var(--mantine-color-surface-2);
|
||||
position: absolute;
|
||||
bottom: 92px;
|
||||
bottom: 10%;
|
||||
opacity: 0.8;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import { useCall } from './useCall.hook';
|
||||
import classes from './Call.module.css'
|
||||
import { Card as Contact } from '../card/Card';
|
||||
import { Colors } from '../constants/Colors';
|
||||
import { modals } from '@mantine/modals'
|
||||
import { Image, Text, ActionIcon } from '@mantine/core'
|
||||
import { IconPhone, IconMicrophone, IconMicrophoneOff, IconVideo, IconVideoOff } from '@tabler/icons-react'
|
||||
import { IconPhone, IconMicrophone, IconMicrophoneOff, IconVideo, IconVideoOff, IconArrowsMinimize } from '@tabler/icons-react'
|
||||
|
||||
export function Call() {
|
||||
const { state, actions } = useCall();
|
||||
@ -15,6 +15,8 @@ export function Call() {
|
||||
const [accepting, setAccepting] = useState(null as null|string);
|
||||
const [ignoring, setIgnoring] = useState(null as null|string);
|
||||
const [declining, setDeclining] = useState(null as null|string);
|
||||
const remote = useRef(null as null|HTMLVideoElement);
|
||||
const local = useRef(null as null|HTMLVideoElement);
|
||||
|
||||
const showError = () => {
|
||||
modals.openConfirmModal({
|
||||
@ -77,27 +79,53 @@ export function Call() {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (local.current) {
|
||||
local.current.srcObject = state.localStream;
|
||||
local.current.load();
|
||||
local.current.play();
|
||||
}
|
||||
}, [state.localStream]);
|
||||
|
||||
useEffect(() => {
|
||||
if (remote.current) {
|
||||
remote.current.srcObject = state.remoteStream;
|
||||
remote.current.load();
|
||||
remote.current.play();
|
||||
}
|
||||
}, [state.remoteStream]);
|
||||
|
||||
return (
|
||||
<div className={(state.calling && state.fullscreen) ? classes.active : classes.inactive}>
|
||||
{ state.calling && (
|
||||
<div className={classes.call}>
|
||||
|
||||
<div className={classes.titleView}>
|
||||
{ state.calling.name && (
|
||||
<Text className={classes.titleName}>{ state.calling.name }</Text>
|
||||
)}
|
||||
{ !state.calling.name && (
|
||||
<Text className={classes.titleName}>{ `${state.calling.handle}/${state.calling.node}` }</Text>
|
||||
)}
|
||||
<div className={classes.image}>
|
||||
<div className={classes.frame}>
|
||||
<Image radius="lg" fit="contain" className={classes.logo} src={state.calling.imageUrl} />
|
||||
{ !state.remoteVideo && !state.localVideo && (
|
||||
<div className={classes.titleView}>
|
||||
{ state.calling.name && (
|
||||
<Text className={classes.titleName}>{ state.calling.name }</Text>
|
||||
)}
|
||||
{ !state.calling.name && (
|
||||
<Text className={classes.titleName}>{ `${state.calling.handle}/${state.calling.node}` }</Text>
|
||||
)}
|
||||
<div className={classes.image}>
|
||||
<div className={classes.frame}>
|
||||
<Image radius="lg" fit="contain" className={classes.logo} src={state.calling.imageUrl} />
|
||||
</div>
|
||||
</div>
|
||||
<Text className={classes.titleStatus}>{ `${Math.floor(state.duration/60)}:${(state.duration % 60).toString().padStart(2, '0')}` }</Text>
|
||||
</div>
|
||||
<Text className={classes.titleStatus}>{ `${Math.floor(state.duration/60)}:${(state.duration % 60).toString().padStart(2, '0')}` }</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={classes.fullFrame} style={{ display: state.remoteVideo ? 'flex' : 'none' }}>
|
||||
<video ref={remote} disablePictureInPicture playsInline autoPlay className={classes.full} />
|
||||
</div>
|
||||
<div className={state.remoteVideo ? classes.boxFrame : classes.fulLFrame} style={{ display: state.localVideo ? 'flex' : 'none' }}>
|
||||
<video ref={local} disablePictureInPicture playsInline autoPlay className={classes.full} />
|
||||
</div>
|
||||
|
||||
<div className={classes.buttons}>
|
||||
<ActionIcon onClick={()=>actions.setFullscreen(false)} color={Colors.confirmed} size="xl"><IconArrowsMinimize /></ActionIcon>
|
||||
<ActionIcon onClick={toggleAudio} disabled={!state.connected} loading={applyingAudio} color={Colors.primary} size="xl">
|
||||
{ state.audioEnabled && (
|
||||
<IconMicrophone />
|
||||
|
@ -38,7 +38,7 @@ function Action({ icon, color, strings, select }: { icon: ReactNode; color: stri
|
||||
)
|
||||
}
|
||||
|
||||
export function Contacts({ openRegistry, openContact, textContact }: { openRegistry: ()=>void; openContact: (params: ProfileParams)=>void, textContact: (cardId: string)=>void }) {
|
||||
export function Contacts({ openRegistry, openContact, textContact, closeContacts }: { openRegistry: ()=>void; openContact: (params: ProfileParams)=>void, textContact: (cardId: string)=>void, closeContacts: ()=>void }) {
|
||||
const { state, actions } = useContacts()
|
||||
|
||||
const cards = state.filtered.map((card, idx) => {
|
||||
@ -48,7 +48,7 @@ export function Contacts({ openRegistry, openContact, textContact }: { openRegis
|
||||
const phone = <IconPhone size={24} />
|
||||
const text = <IconMessage2 size={24} />
|
||||
return [
|
||||
<Action key="phone" icon={phone} color={Colors.connected} select={async () => actions.call(card)} strings={state.strings} />,
|
||||
<Action key="phone" icon={phone} color={Colors.connected} select={async () => { await actions.call(card), closeContacts() }} strings={state.strings} />,
|
||||
<Action key="text" icon={text} color={Colors.connected} select={async () => textContact(card.cardId)} strings={state.strings} />,
|
||||
]
|
||||
} else if (status === 'offsync') {
|
||||
|
@ -190,7 +190,6 @@ export function useRingContext() {
|
||||
}
|
||||
|
||||
const cleanup = async () => {
|
||||
console.log("CLEANUP!");
|
||||
closing.current = true;
|
||||
while (updatingPeer.current || connecting.current) {
|
||||
await new Promise((r) => setTimeout(r, CLOSE_POLL_MS));
|
||||
@ -214,7 +213,6 @@ console.log("CLEANUP!");
|
||||
peerUpdate.current = [];
|
||||
updateState({ calling: null, connected: false, connectedTime: 0, failed: false, localStream: null, remoteStream: null, localVideo: false, remoteVideo: false });
|
||||
closing.current = false;
|
||||
console.log("!!");
|
||||
}
|
||||
|
||||
const transmit = (ice: { urls: string; username: string; credential: string }[]) => {
|
||||
|
@ -6,7 +6,7 @@ import { Card } from 'databag-client-sdk';
|
||||
import { Colors } from '../constants/Colors';
|
||||
import { modals } from '@mantine/modals'
|
||||
import { Loader, Image, Text, ActionIcon } from '@mantine/core'
|
||||
import { IconEyeX, IconPhone, IconPhoneOff, IconArrowsMaximize, IconMicrophone, IconMicrophoneOff } from '@tabler/icons-react'
|
||||
import { IconVideoPlus, IconEyeX, IconPhone, IconPhoneOff, IconArrowsMaximize, IconMicrophone, IconMicrophoneOff } from '@tabler/icons-react'
|
||||
|
||||
export function Ring() {
|
||||
const { state, actions } = useRing();
|
||||
@ -134,7 +134,12 @@ export function Ring() {
|
||||
)}
|
||||
</ActionIcon>
|
||||
<ActionIcon variant="subtle" disabled={!state.connected} className={classes.circleIcon} color={Colors.confirmed} onClick={()=>actions.setFullscreen(true)}>
|
||||
<IconArrowsMaximize />
|
||||
{ (state.localVideo || state.remoteVideo) && (
|
||||
<IconVideoPlus />
|
||||
)}
|
||||
{ !state.localVideo && !state.remoteVideo && (
|
||||
<IconArrowsMaximize />
|
||||
)}
|
||||
</ActionIcon>
|
||||
<div className={classes.name}>
|
||||
{ state.calling.name && (
|
||||
|
@ -32,7 +32,6 @@ export function Session() {
|
||||
const [textCard, setTextCard] = useState({ cardId: null} as {cardId: null|string});
|
||||
|
||||
const textContact = (cardId: string) => {
|
||||
console.log("MESSAGE: ", cardId);
|
||||
setTextCard({ cardId });
|
||||
closeContacts();
|
||||
setTab('content');
|
||||
@ -70,6 +69,7 @@ export function Session() {
|
||||
<Contacts
|
||||
textContact={textContact}
|
||||
openRegistry={openRegistry}
|
||||
closeContacts={()=>{}}
|
||||
openContact={(params) => {
|
||||
setProfileParams(params)
|
||||
openProfile()
|
||||
@ -149,6 +149,7 @@ export function Session() {
|
||||
<Contacts
|
||||
textContact={textContact}
|
||||
openRegistry={openRegistry}
|
||||
closeContacts={closeContacts}
|
||||
openContact={(params) => {
|
||||
setProfileParams(params)
|
||||
openProfile()
|
||||
|
13510
app/client/web/yarn.lock
13510
app/client/web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user