diff --git a/src/App.tsx b/src/App.tsx index 4e291e6..942fc86 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import { Logo } from "@components/Icons" import { Idle, Ringing, InCall } from "@screens/index" import dayjs from "dayjs" import React, { useState, useEffect, useRef } from "react" -import { UserAgent, Registerer, SessionState, RegistererState } from "sip.js" +import { UserAgent, Registerer, SessionState, RegistererState, Inviter } from "sip.js" import config from "@root/config" @@ -27,6 +27,7 @@ const App = () => { const [loading, setLoading] = useState(false) const [registered, setRegistered] = useState(false) const [muted, setMuted] = useState(false) + const [nextRequest, setNextRequest] = useState(false) const [stats, setStats] = useState({ contacts: 0 }) const eventListener = useRef() @@ -88,13 +89,37 @@ const App = () => { registerer.unregister() } + const outboundCall = () => { + if (!ua) return + + const target = UserAgent.makeURI(`sip:${config.dst}@${config.host}`) + if (!target) { + throw new Error("Failed to create target URI.") + } + + const outboundSession = new Inviter(ua, target, { + sessionDescriptionHandlerOptions: { + constraints: { audio: true, video: false } + } + }) + + outboundSession.invite() + setSession(outboundSession) + setLoading(true) + setInvite({ ...invite, startedAt: dayjs().toDate() }) + + logger.log("send invite => ") + } + const hangup = () => { + logger.log("hangup", nextRequest) setLoading(false) if (!session) return - if (invite.answeredAt) return session.bye() + if (invite.answeredAt) return session.bye().catch(e => logger.error(e)) // @ts-ignore session.cancel() + logger.log("hangup", nextRequest) } const handleMute = () => { @@ -104,16 +129,31 @@ const App = () => { } + const next = () => { + setNextRequest(true) + hangup() + } + const sessionListener = (newState: SessionState) => { if (!session) return const terminate = () => { + logger.log("terminate", nextRequest) + cleanupMedia() - setLoading(false) + setMuted(false) toggleMicro(session, false) setInvite({ startedAt: null, answeredAt: null }) - logger.log("terminate") + logger.log("terminate", nextRequest) + if(nextRequest) { + outboundCall() + setLoading(true) + setNextRequest(false) + return + } + + setLoading(false) } switch (newState) { @@ -158,18 +198,8 @@ const App = () => { const getScreen = () => { if (loading) return - - if (invite.answeredAt) return - - return ( - setInvite({ ...invite, startedAt })} - /> - ) + if (invite.answeredAt) return + return } return ( diff --git a/src/screens/Idle/index.tsx b/src/screens/Idle/index.tsx index 95c00af..d4f2796 100644 --- a/src/screens/Idle/index.tsx +++ b/src/screens/Idle/index.tsx @@ -1,43 +1,13 @@ -import dayjs from "dayjs" import React from "react" -import { UserAgent, Inviter, Session } from "sip.js" - -import config from "@root/config" import styles from "../style.m.scss" -import logger from "@helpers/logger" type Props = { - ua: UserAgent | null registered: boolean - setSession: (session: Session) => void - setLoading: (loading: boolean) => void - setStartedAt: (startedAt: Date) => void + outboundCall: () => void } -const Idle: React.FC = ({ ua, registered, setSession, setLoading, setStartedAt }) => { - const outboundCall = () => { - if (!ua) return - - const target = UserAgent.makeURI(`sip:${config.dst}@${config.host}`) - if (!target) { - throw new Error("Failed to create target URI.") - } - - const outboundSession = new Inviter(ua, target, { - sessionDescriptionHandlerOptions: { - constraints: { audio: true, video: false } - } - }) - - outboundSession.invite() - setSession(outboundSession) - setLoading(true) - setStartedAt(dayjs().toDate()) - - logger.log("send invite => ") - } - +const Idle: React.FC = ({ registered, outboundCall }) => { return ( <>
diff --git a/src/screens/InCall/index.tsx b/src/screens/InCall/index.tsx index 0342ea7..805c2ed 100644 --- a/src/screens/InCall/index.tsx +++ b/src/screens/InCall/index.tsx @@ -1,7 +1,7 @@ import React from "react" -import {CallDurationTimer} from '@root/components/CallDurationTimer'; -import {Mic, MicOff} from '@root/components/Icons'; +import { CallDurationTimer } from "@root/components/CallDurationTimer" +import { Mic, MicOff } from "@root/components/Icons" import styles from "../style.m.scss" @@ -10,14 +10,14 @@ type Props = { muted: boolean handleMute: () => void hangup: () => void - } + next: () => void +} -const InCall: React.FC = ({ answeredAt, muted, handleMute, hangup }) => { +const InCall: React.FC = ({ answeredAt, muted, handleMute, hangup, next }) => { return ( <>
- - +
@@ -27,9 +27,14 @@ const InCall: React.FC = ({ answeredAt, muted, handleMute, hangup }) => {
)} - +
+ + +
) diff --git a/src/screens/Ringing/index.tsx b/src/screens/Ringing/index.tsx index 910f517..b9256f2 100644 --- a/src/screens/Ringing/index.tsx +++ b/src/screens/Ringing/index.tsx @@ -23,8 +23,8 @@ const Ringing: React.FC = ({ loading, hangup }) => {
-
diff --git a/src/screens/style.m.scss b/src/screens/style.m.scss index eba3ef2..d50c008 100644 --- a/src/screens/style.m.scss +++ b/src/screens/style.m.scss @@ -57,6 +57,11 @@ } } + .buttons { + display: flex; + gap: 12px + } + button { outline: none; border: none; @@ -78,7 +83,7 @@ } } - &.cancelButton { + &.darkButton { background-color: rgba(255, 255, 255, 0.10); &:hover { background-color: rgba(255, 255, 255, 0.07);