mirror of
https://github.com/balzack/databag.git
synced 2025-04-23 01:55:17 +00:00
preparing for updated call screen in webapp
This commit is contained in:
parent
fc0ba2a187
commit
a717a6d88e
@ -34,7 +34,7 @@ export function useRingContext() {
|
||||
const peerUpdate = useRef([] as {type: string, data?: any}[]);
|
||||
const connecting = useRef(false);
|
||||
const passive = useRef(false);
|
||||
const passiveTrack = useRef([] as MediaStreamTrack);
|
||||
const passiveTracks = useRef([] as MediaStreamTrack[]);
|
||||
const closing = useRef(false);
|
||||
const [ringing, setRinging] = useState([] as { cardId: string, callId: string }[]);
|
||||
const [cards, setCards] = useState([] as Card[]);
|
||||
@ -131,9 +131,10 @@ export function useRingContext() {
|
||||
if (remoteStream.current) {
|
||||
remoteStream.current.addTrack(data);
|
||||
passive.current = false;
|
||||
passiveTrack.current.forEach(track => {
|
||||
passiveTracks.current.forEach(track => {
|
||||
peer.addTrack(track, sourceStream.current);
|
||||
});
|
||||
passiveTracks.current = [];
|
||||
if (data.kind === 'video') {
|
||||
InCallManager.setForceSpeakerphoneOn(true);
|
||||
updateState({ remoteVideo: true });
|
||||
@ -142,7 +143,7 @@ export function useRingContext() {
|
||||
break;
|
||||
case 'local_track':
|
||||
if (passive.current) {
|
||||
passiveTrack.push(data);
|
||||
passiveTracks.push(data);
|
||||
} else {
|
||||
peer.addTrack(data, sourceStream.current);
|
||||
}
|
||||
@ -167,7 +168,7 @@ export function useRingContext() {
|
||||
const setup = async (link: Link, card: Card, polite: boolean) => {
|
||||
|
||||
passive.current = polite;
|
||||
passiveTrack.current = [];
|
||||
passiveTracks.current = [];
|
||||
remoteStream.current = new MediaStream();
|
||||
localStream.current = new MediaStream();
|
||||
sourceStream.current = await mediaDevices.getUserMedia({
|
||||
|
66
app/client/web/src/call/Call.module.css
Normal file
66
app/client/web/src/call/Call.module.css
Normal file
@ -0,0 +1,66 @@
|
||||
.active {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
.inactive {
|
||||
display: none;
|
||||
}
|
||||
.call {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
bottom: 10%;
|
||||
padding: 8;
|
||||
gap: 12;
|
||||
border-radius: 8;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.full {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.box {
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
right: 10%;
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
}
|
||||
.titleView {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
paddingTop: 92;
|
||||
}
|
||||
.titleName {
|
||||
font-size: 24;
|
||||
padding-bottom: 32;
|
||||
}
|
||||
.titleImage {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 8;
|
||||
}
|
||||
.duration {
|
||||
padding-top: 16;
|
||||
font-size: 20;
|
||||
}
|
||||
.logoView {
|
||||
height: 100%;
|
||||
width: auto;
|
||||
aspect-ratio: 1;
|
||||
}
|
82
app/client/web/src/call/Call.tsx
Normal file
82
app/client/web/src/call/Call.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import React, { 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'
|
||||
|
||||
export function Call() {
|
||||
const { state, actions } = useCall();
|
||||
const [ending, setEnding] = useState(false);
|
||||
const [applyingAudio, setApplyingAudio] = useState(false);
|
||||
const [applyingVideo, setApplyingVideo] = useState(false);
|
||||
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 showError = () => {
|
||||
modals.openConfirmModal({
|
||||
title: state.strings.operationFailed,
|
||||
withCloseButton: true,
|
||||
overlayProps: {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: <Text>{state.strings.tryAgain}</Text>,
|
||||
cancelProps: { display: 'none' },
|
||||
confirmProps: { display: 'none' },
|
||||
})
|
||||
}
|
||||
|
||||
const toggleAudio = async () => {
|
||||
if (!applyingAudio) {
|
||||
setApplyingAudio(true);
|
||||
try {
|
||||
if (state.audioEnabled) {
|
||||
await actions.disableAudio();
|
||||
} else if (!state.audioEnabled) {
|
||||
await actions.enableAudio();
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setApplyingAudio(false);
|
||||
}
|
||||
}
|
||||
|
||||
const toggleVideo = async () => {
|
||||
if (!applyingVideo) {
|
||||
setApplyingVideo(true);
|
||||
try {
|
||||
if (state.videoEnabled) {
|
||||
await actions.disableVideo();
|
||||
} else if (!state.videoEnabled) {
|
||||
await actions.enableVideo();
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setApplyingVideo(false);
|
||||
}
|
||||
}
|
||||
|
||||
const end = async () => {
|
||||
if (!ending) {
|
||||
setEnding(true);
|
||||
try {
|
||||
await actions.end();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setEnding(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div />
|
||||
);
|
||||
}
|
||||
|
63
app/client/web/src/call/useCall.hook.ts
Normal file
63
app/client/web/src/call/useCall.hook.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { useState, useContext, useEffect, useRef } from 'react'
|
||||
import { RingContext } from '../context/RingContext'
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import { Card } from 'databag-client-sdk';
|
||||
|
||||
export function useCall() {
|
||||
const ring = useContext(RingContext) as ContextType;
|
||||
const display = useContext(DisplayContext) as ContextType;
|
||||
const offsetTime = useRef(0);
|
||||
const offset = useRef(false);
|
||||
|
||||
const [state, setState] = useState({
|
||||
strings: display.state.strings,
|
||||
calls: [] as { callId: string, card: Card }[],
|
||||
calling: null as null | Card,
|
||||
localStream: null as null|MediaStream,
|
||||
remoteStream: null as null|MediaStream,
|
||||
remoteVideo: false,
|
||||
localVideo: false,
|
||||
audioEnabled: false,
|
||||
videoEnabled: false,
|
||||
connected: false,
|
||||
duration: 0,
|
||||
failed: false,
|
||||
width: 0,
|
||||
height: 0,
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const updateState = (value: any) => {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { width, height, strings } = display.state;
|
||||
updateState({ width, height, strings });
|
||||
}, [display.state]);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (offset.current) {
|
||||
const now = new Date();
|
||||
const duration = Math.floor((now.getTime() / 1000) - offsetTime.current);
|
||||
updateState({ duration });
|
||||
}
|
||||
}, 1000);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const { calls, calling, fullscreen, localStream, remoteStream, remoteVideo, localVideo, audioEnabled, videoEnabled, connected, connectedTime, failed } = ring.state;
|
||||
offsetTime.current = connectedTime;
|
||||
offset.current = connected;
|
||||
const duration = connected ? Math.floor(((new Date()).getTime() / 1000) - connectedTime) : 0;
|
||||
updateState({ calls, calling, fullscreen, duration, localStream, remoteStream, remoteVideo, localVideo, audioEnabled, videoEnabled, connected, failed });
|
||||
}, [ring.state]);
|
||||
|
||||
const actions = ring.actions;
|
||||
return { state, actions };
|
||||
}
|
@ -38,7 +38,7 @@ function Action({ icon, color, strings, select }: { icon: ReactNode; color: stri
|
||||
)
|
||||
}
|
||||
|
||||
export function Contacts({ openRegistry, openContact, textContact, callContact }: { openRegistry: ()=>void; openContact: (params: ProfileParams)=>void, textContact: (cardId: string)=>void, callContact: (card: Card)=>void }) {
|
||||
export function Contacts({ openRegistry, openContact, textContact }: { openRegistry: ()=>void; openContact: (params: ProfileParams)=>void, textContact: (cardId: string)=>void }) {
|
||||
const { state, actions } = useContacts()
|
||||
|
||||
const cards = state.filtered.map((card, idx) => {
|
||||
@ -48,7 +48,7 @@ export function Contacts({ openRegistry, openContact, textContact, callContact }
|
||||
const phone = <IconPhone size={24} />
|
||||
const text = <IconMessage2 size={24} />
|
||||
return [
|
||||
<Action key="phone" icon={phone} color={Colors.connected} select={async () => callContact(card)} strings={state.strings} />,
|
||||
<Action key="phone" icon={phone} color={Colors.connected} select={async () => actions.call(card)} strings={state.strings} />,
|
||||
<Action key="text" icon={text} color={Colors.connected} select={async () => textContact(card.cardId)} strings={state.strings} />,
|
||||
]
|
||||
} else if (status === 'offsync') {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useState, useContext, useEffect } from 'react'
|
||||
import { AppContext } from '../context/AppContext'
|
||||
import { RingContext } from '../context/RingContext'
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import { Card } from 'databag-client-sdk'
|
||||
@ -7,6 +8,7 @@ import { Card } from 'databag-client-sdk'
|
||||
export function useContacts() {
|
||||
const app = useContext(AppContext) as ContextType
|
||||
const display = useContext(DisplayContext) as ContextType
|
||||
const ring = useContext(RingContext) as ContextType
|
||||
const [state, setState] = useState({
|
||||
strings: display.state.strings,
|
||||
cards: [] as Card[],
|
||||
@ -64,6 +66,9 @@ export function useContacts() {
|
||||
}, [state.sortAsc, state.filter, state.cards])
|
||||
|
||||
const actions = {
|
||||
call: async (card: Card) => {
|
||||
await ring.actions.call(card);
|
||||
},
|
||||
toggleSort: () => {
|
||||
const sortAsc = !state.sortAsc
|
||||
updateState({ sortAsc })
|
||||
|
@ -18,6 +18,8 @@ export function useRingContext() {
|
||||
const peerUpdate = useRef([] as {type: string, data?: any}[]);
|
||||
const connecting = useRef(false);
|
||||
const closing = useRef(false);
|
||||
const passive = useRef(false);
|
||||
const passiveTracks = useRef([] as { track: MediaStreamTrack, stream: MediaStream }[]);
|
||||
const [ringing, setRinging] = useState([] as { cardId: string, callId: string }[]);
|
||||
const [cards, setCards] = useState([] as Card[]);
|
||||
|
||||
@ -32,6 +34,7 @@ export function useRingContext() {
|
||||
videoEnabled: false,
|
||||
connected: false,
|
||||
failed: false,
|
||||
fullscreen: false,
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@ -124,13 +127,22 @@ export function useRingContext() {
|
||||
case 'remote_track':
|
||||
if (remoteStream.current) {
|
||||
remoteStream.current.addTrack(data);
|
||||
passive.current = false;
|
||||
passiveTracks.current.forEach(data => {
|
||||
peer.addTrack(data.track, data.stream);
|
||||
});
|
||||
passiveTracks.current = [];
|
||||
if (data.kind === 'video') {
|
||||
updateState({ remoteVideo: true });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'local_track':
|
||||
peer.addTrack(data.track, data.stream);
|
||||
if (passive.current) {
|
||||
passiveTracks.current.push(data);
|
||||
} else {
|
||||
peer.addTrack(data.track, data.stream);
|
||||
}
|
||||
if (data.track.kind === 'audio') {
|
||||
localAudio.current = data.track;
|
||||
}
|
||||
@ -153,7 +165,8 @@ export function useRingContext() {
|
||||
}
|
||||
}
|
||||
|
||||
const setup = async (link: Link, card: Card) => {
|
||||
const setup = async (link: Link, card: Card, polite: boolean) => {
|
||||
passive.current = polite;
|
||||
localAudio.current = null;
|
||||
localVideo.current = null;
|
||||
localStream.current = null;
|
||||
@ -242,6 +255,9 @@ export function useRingContext() {
|
||||
}, [app.state.session]);
|
||||
|
||||
const actions = {
|
||||
setFullscreen: (fullscreen: boolean) => {
|
||||
updateState({ fullscreen });
|
||||
},
|
||||
ignore: async (callId: string, card: Card) => {
|
||||
const ring = app.state.session.getRing();
|
||||
await ring.ignore(card.cardId, callId);
|
||||
@ -262,7 +278,7 @@ export function useRingContext() {
|
||||
const { cardId, node } = card;
|
||||
const ring = app.state.session.getRing();
|
||||
const link = await ring.accept(cardId, callId, node);
|
||||
await setup(link, card);
|
||||
await setup(link, card, true);
|
||||
connecting.current = false;
|
||||
} catch (err) {
|
||||
connecting.current = false;
|
||||
@ -277,7 +293,7 @@ export function useRingContext() {
|
||||
connecting.current = true;
|
||||
const contact = app.state.session.getContact();
|
||||
const link = await contact.callCard(card.cardId);
|
||||
await setup(link, card);
|
||||
await setup(link, card, false);
|
||||
connecting.current = false;
|
||||
} catch (err) {
|
||||
connecting.current = false;
|
||||
|
57
app/client/web/src/ring/Ring.module.css
Normal file
57
app/client/web/src/ring/Ring.module.css
Normal file
@ -0,0 +1,57 @@
|
||||
active {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
max-width: 500px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
inactive {
|
||||
display: none;
|
||||
}
|
||||
ring {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16px;
|
||||
padding-left: 16px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
card {
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
circleIcon {
|
||||
}
|
||||
flipIcon {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
end {
|
||||
}
|
||||
name {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-left: 8px;
|
||||
}
|
||||
nameSet {
|
||||
font-size: 20px;
|
||||
}
|
||||
nameUnset {
|
||||
font-size: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
status {
|
||||
width: 64px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
duration {
|
||||
color: Colors.primary;
|
||||
font-size: 20px;
|
||||
}
|
118
app/client/web/src/ring/Ring.tsx
Normal file
118
app/client/web/src/ring/Ring.tsx
Normal file
@ -0,0 +1,118 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useRing } from './useRing.hook';
|
||||
import classes from './Ring.module.css';
|
||||
import { Card as Contact } from '../card/Card';
|
||||
import { Colors } from '../constants/Colors';
|
||||
import { modals } from '@mantine/modals'
|
||||
import { Loader, Image, Text, ActionIcon } from '@mantine/core'
|
||||
import { IconEyeX, IconPhone, IconPhoneOff, IconMicrophone, IconMicrophoneOff } from '@tabler/icons-react'
|
||||
|
||||
export function Ring() {
|
||||
const { state, actions } = useRing();
|
||||
const [ending, setEnding] = useState(false);
|
||||
const [applyingAudio, setApplyingAudio] = useState(false);
|
||||
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 showError = () => {
|
||||
modals.openConfirmModal({
|
||||
title: state.strings.operationFailed,
|
||||
withCloseButton: true,
|
||||
overlayProps: {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: <Text>{state.strings.tryAgain}</Text>,
|
||||
cancelProps: { display: 'none' },
|
||||
confirmProps: { display: 'none' },
|
||||
})
|
||||
}
|
||||
|
||||
const toggleAudio = async () => {
|
||||
if (!applyingAudio) {
|
||||
setApplyingAudio(true);
|
||||
try {
|
||||
if (state.audioEnabled) {
|
||||
await actions.disableAudio();
|
||||
} else if (!state.audioEnabled) {
|
||||
await actions.enableAudio();
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setApplyingAudio(false);
|
||||
}
|
||||
}
|
||||
|
||||
const end = async () => {
|
||||
if (!ending) {
|
||||
setEnding(true);
|
||||
try {
|
||||
await actions.end();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setEnding(false);
|
||||
}
|
||||
}
|
||||
|
||||
const accept = async (callId, card) => {
|
||||
if (!accepting) {
|
||||
setAccepting(callId);
|
||||
try {
|
||||
await actions.accept(callId, card);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setAccepting(null);
|
||||
}
|
||||
}
|
||||
|
||||
const ignore = async (callId, card) => {
|
||||
if (!ignoring) {
|
||||
setIgnoring(callId);
|
||||
try {
|
||||
await actions.ignore(callId, card);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setIgnoring(null);
|
||||
}
|
||||
}
|
||||
|
||||
const decline = async (callId, card) => {
|
||||
if (!declining) {
|
||||
setDeclining(callId);
|
||||
try {
|
||||
await actions.decline(callId, card);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setDeclining(null);
|
||||
}
|
||||
}
|
||||
|
||||
const calls = state.calls.map((ring, index) => {
|
||||
const { name, handle, node, imageUrl } = ring.card;
|
||||
const ignoreButton = <ActionIcon key="ignore" variant="subtle" loading={ignoring===ring.callId} onClick={()=>ignore(ring)} color={Colors.pending}><IconEyeX /></ActionIcon>
|
||||
const declineButton = <div key="decline" className={classes.space}><ActionIcon variant="subtle" loading={declining===ring.callId} onClick={()=>decline(ring)} color={Colors.offsync}><IconPhone className={classes.off} /></ActionIcon></div>
|
||||
const acceptButton = <ActionIcon key="accept" variant="subtle" loading={accepting===ring.callId} onClick={()=>accept(ring)} color={Colors.primary}><IconPhone /></ActionIcon>
|
||||
|
||||
return (
|
||||
<div key={index} className={classes.caller}>
|
||||
<Contact className={classes.card} placeholder={''} imageUrl={imageUrl} name={name} node={node} handle={handle} actions={[ignoreButton, declineButton, acceptButton]} />
|
||||
</div>
|
||||
)
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%', height: 14, backgroundColor: 'yellow' }} />
|
||||
);
|
||||
}
|
||||
|
53
app/client/web/src/ring/useRing.hook.ts
Normal file
53
app/client/web/src/ring/useRing.hook.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { useState, useContext, useEffect, useRef } from 'react'
|
||||
import { RingContext } from '../context/RingContext'
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import { Card } from 'databag-client-sdk';
|
||||
|
||||
export function useRing() {
|
||||
const ring = useContext(RingContext) as ContextType;
|
||||
const display = useContext(DisplayContext) as ContextType;
|
||||
const offsetTime = useRef(0);
|
||||
const offset = useRef(false);
|
||||
|
||||
const [state, setState] = useState({
|
||||
strings: display.state.strings,
|
||||
calls: [] as { callId: string, card: Card }[],
|
||||
calling: null as null | Card,
|
||||
remoteVideo: false,
|
||||
localVideo: false,
|
||||
audioEnabled: false,
|
||||
connected: false,
|
||||
duration: 0,
|
||||
failed: false,
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const updateState = (value: any) => {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (offset.current) {
|
||||
const now = new Date();
|
||||
const duration = Math.floor((now.getTime() / 1000) - offsetTime.current);
|
||||
updateState({ duration });
|
||||
}
|
||||
}, 1000);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const { calls, calling, localVideo, remoteVideo, audioEnabled, connected, connectedTime, failed } = ring.state;
|
||||
offsetTime.current = connectedTime;
|
||||
offset.current = connected;
|
||||
const duration = connected ? Math.floor(((new Date()).getTime() / 1000) - connectedTime) : 0;
|
||||
updateState({ calls, calling, duration, localVideo, remoteVideo, audioEnabled, connected, failed });
|
||||
}, [ring.state]);
|
||||
|
||||
const actions = ring.actions;
|
||||
return { state, actions };
|
||||
}
|
@ -26,13 +26,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
.show {
|
||||
.body {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: calc(100% - 48px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.show {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
height: 10%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hide {
|
||||
@ -63,10 +71,18 @@
|
||||
|
||||
.right {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
background: var(--mantine-color-surface-3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.conversation {
|
||||
display: flex;
|
||||
height: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,8 @@ import { Conversation } from '../conversation/Conversation'
|
||||
import { Focus, Card } from 'databag-client-sdk'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { IconAlertCircle } from '@tabler/icons-react'
|
||||
import { Calling } from '../calling/Calling';
|
||||
import { Ring } from '../ring/Ring';
|
||||
import { Call } from '../call/Call';
|
||||
|
||||
export function Session() {
|
||||
const { state } = useSession();
|
||||
@ -29,7 +30,6 @@ export function Session() {
|
||||
const [details, { open: openDetails, close: closeDetails }] = useDisclosure(false)
|
||||
const [profile, { open: openProfile, close: closeProfile }] = useDisclosure(false)
|
||||
const [textCard, setTextCard] = useState({ cardId: null} as {cardId: null|string});
|
||||
const [callCard, setCallCard] = useState({ card: null} as {card: null|Card});
|
||||
|
||||
const textContact = (cardId: string) => {
|
||||
console.log("MESSAGE: ", cardId);
|
||||
@ -38,63 +38,61 @@ export function Session() {
|
||||
setTab('content');
|
||||
}
|
||||
|
||||
const callContact = (card: Card) => {
|
||||
setCallCard({ card });
|
||||
}
|
||||
|
||||
return (
|
||||
<RingContextProvider>
|
||||
<div className={classes.session}>
|
||||
{state.layout === 'small' && (
|
||||
<>
|
||||
<div className={tab === 'content' ? classes.show : classes.hide}>
|
||||
<div className={classes.screen}>
|
||||
<Content textCard={textCard} />
|
||||
</div>
|
||||
{state.focus && (
|
||||
<div className={classes.body}>
|
||||
<Ring />
|
||||
<div className={tab === 'content' ? classes.show : classes.hide}>
|
||||
<div className={classes.screen}>
|
||||
<Conversation openDetails={openDetails} />
|
||||
<Content textCard={textCard} />
|
||||
</div>
|
||||
)}
|
||||
{details && (
|
||||
{state.focus && (
|
||||
<div className={classes.screen}>
|
||||
<Conversation openDetails={openDetails} />
|
||||
</div>
|
||||
)}
|
||||
{details && (
|
||||
<div className={classes.screen}>
|
||||
<Details showClose={true} close={closeDetails} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={tab === 'settings' ? classes.show : classes.hide}>
|
||||
<div className={classes.screen}>
|
||||
<Details showClose={true} close={closeDetails} />
|
||||
<Settings showLogout={true} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={tab === 'settings' ? classes.show : classes.hide}>
|
||||
<div className={classes.screen}>
|
||||
<Settings showLogout={true} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={tab === 'contacts' ? classes.show : classes.hide}>
|
||||
<div className={classes.screen}>
|
||||
<Contacts
|
||||
callContact={callContact}
|
||||
textContact={textContact}
|
||||
openRegistry={openRegistry}
|
||||
openContact={(params) => {
|
||||
setProfileParams(params)
|
||||
openProfile()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{registry && (
|
||||
<div className={tab === 'contacts' ? classes.show : classes.hide}>
|
||||
<div className={classes.screen}>
|
||||
<Registry
|
||||
close={closeRegistry}
|
||||
<Contacts
|
||||
textContact={textContact}
|
||||
openRegistry={openRegistry}
|
||||
openContact={(params) => {
|
||||
setProfileParams(params)
|
||||
openProfile()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{profile && (
|
||||
<div className={classes.screen}>
|
||||
<Profile params={profileParams} showClose={true} close={closeProfile} />
|
||||
</div>
|
||||
)}
|
||||
{registry && (
|
||||
<div className={classes.screen}>
|
||||
<Registry
|
||||
close={closeRegistry}
|
||||
openContact={(params) => {
|
||||
setProfileParams(params)
|
||||
openProfile()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{profile && (
|
||||
<div className={classes.screen}>
|
||||
<Profile params={profileParams} showClose={true} close={closeProfile} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.tabs}>
|
||||
{tab === 'content' && (
|
||||
@ -140,11 +138,15 @@ export function Session() {
|
||||
<Content textCard={textCard} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.right}>{state.focus && <Conversation openDetails={openDetails} />}</div>
|
||||
<div className={classes.right}>
|
||||
<Ring />
|
||||
<div className={classes.conversation}>
|
||||
{state.focus && <Conversation openDetails={openDetails} />}
|
||||
</div>
|
||||
</div>
|
||||
<Drawer opened={contacts} onClose={closeContacts} withCloseButton={false} size="md" padding="0" position="right">
|
||||
<div style={{ height: '100vh' }}>
|
||||
<Contacts
|
||||
callContact={callContact}
|
||||
textContact={textContact}
|
||||
openRegistry={openRegistry}
|
||||
openContact={(params) => {
|
||||
@ -189,7 +191,7 @@ export function Session() {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Calling callCard={callCard} />
|
||||
<Call />
|
||||
</div>
|
||||
</RingContextProvider>
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user