mirror of
https://github.com/jambonz/chrome-extension-dialer.git
synced 2026-01-25 02:08:05 +00:00
wip
This commit is contained in:
42
src/components/outline-box/index.tsx
Normal file
42
src/components/outline-box/index.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { VStack, Text } from "@chakra-ui/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
const OutlineBox = ({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
h,
|
||||||
|
borderColor,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
children: ReactNode;
|
||||||
|
h?: string;
|
||||||
|
borderColor?: string;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<VStack align="stretch" h={h || ""} w="full">
|
||||||
|
<VStack
|
||||||
|
border="1px"
|
||||||
|
borderColor={borderColor || ""}
|
||||||
|
position="relative"
|
||||||
|
borderRadius={5}
|
||||||
|
p={4}
|
||||||
|
h={h || ""}
|
||||||
|
align="start"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
position="absolute"
|
||||||
|
top={-3}
|
||||||
|
left={2}
|
||||||
|
bg="white"
|
||||||
|
color={borderColor || ""}
|
||||||
|
px={2}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
{children}
|
||||||
|
</VStack>
|
||||||
|
</VStack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OutlineBox;
|
||||||
@@ -59,9 +59,10 @@ import {
|
|||||||
faPhoneSlash,
|
faPhoneSlash,
|
||||||
faPlay,
|
faPlay,
|
||||||
faUserGroup,
|
faUserGroup,
|
||||||
faUsers,
|
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import NewConference from "./new-conference";
|
||||||
|
import JoinConference from "./join-conference";
|
||||||
|
|
||||||
type PhoneProbs = {
|
type PhoneProbs = {
|
||||||
sipDomain: string;
|
sipDomain: string;
|
||||||
@@ -74,6 +75,14 @@ type PhoneProbs = {
|
|||||||
advancedSettings: AdvancedAppSettings;
|
advancedSettings: AdvancedAppSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum PAGE_VIEW {
|
||||||
|
DIAL_PAD,
|
||||||
|
INCOMING_CALL,
|
||||||
|
OUTGOING_CALL,
|
||||||
|
START_NEW_CONFERENCE,
|
||||||
|
JOIN_CONFERENCE,
|
||||||
|
}
|
||||||
|
|
||||||
export const Phone = ({
|
export const Phone = ({
|
||||||
sipDomain,
|
sipDomain,
|
||||||
sipServerAddress,
|
sipServerAddress,
|
||||||
@@ -109,6 +118,7 @@ export const Phone = ({
|
|||||||
const [isOnline, setIsOnline] = useState(false);
|
const [isOnline, setIsOnline] = useState(false);
|
||||||
const unregisteredReasonRef = useRef("");
|
const unregisteredReasonRef = useRef("");
|
||||||
const isInputNumberFocusRef = useRef(false);
|
const isInputNumberFocusRef = useRef(false);
|
||||||
|
const [pageView, setPageView] = useState<PAGE_VIEW>(PAGE_VIEW.DIAL_PAD);
|
||||||
const [registeredUser, setRegisteredUser] = useState<Partial<RegisteredUser>>(
|
const [registeredUser, setRegisteredUser] = useState<Partial<RegisteredUser>>(
|
||||||
{
|
{
|
||||||
allow_direct_app_calling: false,
|
allow_direct_app_calling: false,
|
||||||
@@ -158,6 +168,15 @@ export const Phone = ({
|
|||||||
if (isSipClientIdle(callStatus) && isCallButtonLoading) {
|
if (isSipClientIdle(callStatus) && isCallButtonLoading) {
|
||||||
setIsCallButtonLoading(false);
|
setIsCallButtonLoading(false);
|
||||||
}
|
}
|
||||||
|
if (isSipClientRinging(callStatus)) {
|
||||||
|
if (sessionDirection === "incoming") {
|
||||||
|
setPageView(PAGE_VIEW.INCOMING_CALL);
|
||||||
|
} else {
|
||||||
|
setPageView(PAGE_VIEW.OUTGOING_CALL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setPageView(PAGE_VIEW.DIAL_PAD);
|
||||||
|
}
|
||||||
}, [callStatus]);
|
}, [callStatus]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -190,29 +209,6 @@ export const Phone = ({
|
|||||||
}, 10_000);
|
}, 10_000);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// chrome.runtime.onMessage.addListener(function (request) {
|
|
||||||
// const msg = request as Message<any>;
|
|
||||||
// switch (msg.event) {
|
|
||||||
// case MessageEvent.Call:
|
|
||||||
// handleCallEvent(msg.data as Call);
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// const handleCallEvent = (call: Call) => {
|
|
||||||
// if (!call.number) return;
|
|
||||||
|
|
||||||
// if (isSipClientIdle(callStatus)) {
|
|
||||||
// setIsCallButtonLoading(true);
|
|
||||||
// setInputNumber(call.number);
|
|
||||||
// sipUA.current?.call(call.number);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const fetchRegisterUser = () => {
|
const fetchRegisterUser = () => {
|
||||||
getSelfRegisteredUser(sipUsernameRef.current)
|
getSelfRegisteredUser(sipUsernameRef.current)
|
||||||
.then(({ json }) => {
|
.then(({ json }) => {
|
||||||
@@ -516,21 +512,7 @@ export const Phone = ({
|
|||||||
Go to Settings to configure your account
|
Go to Settings to configure your account
|
||||||
</Heading>
|
</Heading>
|
||||||
)}
|
)}
|
||||||
|
{pageView === PAGE_VIEW.DIAL_PAD && (
|
||||||
{isSipClientRinging(callStatus) ? (
|
|
||||||
sessionDirection === "incoming" ? (
|
|
||||||
<IncommingCall
|
|
||||||
number={inputNumber}
|
|
||||||
answer={handleAnswer}
|
|
||||||
decline={handleDecline}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<OutGoingCall
|
|
||||||
number={inputNumber || appName}
|
|
||||||
cancelCall={handleDecline}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<VStack
|
<VStack
|
||||||
spacing={2}
|
spacing={2}
|
||||||
w="full"
|
w="full"
|
||||||
@@ -643,32 +625,20 @@ export const Phone = ({
|
|||||||
|
|
||||||
<IconButtonMenu
|
<IconButtonMenu
|
||||||
icon={<FontAwesomeIcon icon={faPeopleGroup} />}
|
icon={<FontAwesomeIcon icon={faPeopleGroup} />}
|
||||||
tooltip="Call an application"
|
tooltip="Join a conference"
|
||||||
noResultLabel="No applications"
|
noResultLabel="No conference"
|
||||||
onClick={(name, value) => {
|
onClick={(name, value) => {
|
||||||
setAppName(`App ${name}`);
|
setPageView(PAGE_VIEW.START_NEW_CONFERENCE);
|
||||||
const calledAppId = `app-${value}`;
|
|
||||||
setInputNumber("");
|
|
||||||
makeOutboundCall(calledAppId, `App ${name}`);
|
|
||||||
}}
|
}}
|
||||||
onOpen={() => {
|
onOpen={() => {
|
||||||
return new Promise<IconButtonMenuItems[]>(
|
return new Promise<IconButtonMenuItems[]>((resolve) => {
|
||||||
(resolve, reject) => {
|
resolve([
|
||||||
getApplications()
|
{
|
||||||
.then(({ json }) => {
|
name: "Start New Conference",
|
||||||
const sortedApps = json.sort((a, b) =>
|
value: "start_new_conference",
|
||||||
a.name.localeCompare(b.name)
|
},
|
||||||
);
|
]);
|
||||||
resolve(
|
});
|
||||||
sortedApps.map((a) => ({
|
|
||||||
name: a.name,
|
|
||||||
value: a.application_sid,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch((err) => reject(err));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
@@ -771,6 +741,33 @@ export const Phone = ({
|
|||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
)}
|
)}
|
||||||
|
{pageView === PAGE_VIEW.INCOMING_CALL && (
|
||||||
|
<IncommingCall
|
||||||
|
number={inputNumber}
|
||||||
|
answer={handleAnswer}
|
||||||
|
decline={handleDecline}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{pageView === PAGE_VIEW.OUTGOING_CALL && (
|
||||||
|
<OutGoingCall
|
||||||
|
number={inputNumber || appName}
|
||||||
|
cancelCall={handleDecline}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{pageView === PAGE_VIEW.JOIN_CONFERENCE && (
|
||||||
|
<JoinConference
|
||||||
|
handleCancel={() => {
|
||||||
|
setPageView(PAGE_VIEW.DIAL_PAD);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{pageView === PAGE_VIEW.START_NEW_CONFERENCE && (
|
||||||
|
<NewConference
|
||||||
|
handleCancel={() => {
|
||||||
|
setPageView(PAGE_VIEW.DIAL_PAD);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Center>
|
</Center>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
66
src/window/phone/join-conference.tsx
Normal file
66
src/window/phone/join-conference.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
VStack,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { FormEvent } from "react";
|
||||||
|
import OutlineBox from "src/components/outline-box";
|
||||||
|
|
||||||
|
type JoinConferenceProbs = {
|
||||||
|
handleCancel: () => void;
|
||||||
|
};
|
||||||
|
export const JoinConference = ({ handleCancel }: JoinConferenceProbs) => {
|
||||||
|
const handleSubmit = (e: FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Box as="form" onSubmit={handleSubmit} w="full">
|
||||||
|
<VStack spacing={4} mt="20px" w="full">
|
||||||
|
<Text fontWeight="bold">Joining conference</Text>
|
||||||
|
<FormControl id="conference_name">
|
||||||
|
<FormLabel>Conference name</FormLabel>
|
||||||
|
<Input type="text" placeholder="Name" isRequired />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<OutlineBox title="Join as">
|
||||||
|
<Checkbox colorScheme="jambonz">Full participant</Checkbox>
|
||||||
|
<Checkbox colorScheme="jambonz">Muted</Checkbox>
|
||||||
|
<Checkbox colorScheme="jambonz">Coach mode</Checkbox>
|
||||||
|
|
||||||
|
<FormControl id="speak_only_to">
|
||||||
|
<FormLabel>Speak only to</FormLabel>
|
||||||
|
<Input type="text" placeholder="agent" isRequired />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl id="tag">
|
||||||
|
<FormLabel>Tag</FormLabel>
|
||||||
|
<Input type="text" placeholder="tags" isRequired />
|
||||||
|
</FormControl>
|
||||||
|
</OutlineBox>
|
||||||
|
<HStack w="full">
|
||||||
|
<Button colorScheme="jambonz" type="submit" w="full">
|
||||||
|
Start Conference
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
colorScheme="grey"
|
||||||
|
type="button"
|
||||||
|
w="full"
|
||||||
|
textColor="black"
|
||||||
|
onClick={handleCancel}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default JoinConference;
|
||||||
69
src/window/phone/new-conference.tsx
Normal file
69
src/window/phone/new-conference.tsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
VStack,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { FormEvent } from "react";
|
||||||
|
import OutlineBox from "src/components/outline-box";
|
||||||
|
|
||||||
|
type NewConferenceProbs = {
|
||||||
|
handleCancel: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NewConference = ({ handleCancel }: NewConferenceProbs) => {
|
||||||
|
const handleSubmit = (e: FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Box as="form" onSubmit={handleSubmit} w="full">
|
||||||
|
<VStack spacing={4} mt="20px" w="full">
|
||||||
|
<Text fontWeight="bold" fontSize="2xl">
|
||||||
|
Start new conference
|
||||||
|
</Text>
|
||||||
|
<FormControl id="conference_name">
|
||||||
|
<FormLabel>Conference name</FormLabel>
|
||||||
|
<Input type="text" placeholder="Name" isRequired />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<OutlineBox title="Join as">
|
||||||
|
<Checkbox colorScheme="jambonz">Full participant</Checkbox>
|
||||||
|
<Checkbox colorScheme="jambonz">Muted</Checkbox>
|
||||||
|
<Checkbox colorScheme="jambonz">Coach mode</Checkbox>
|
||||||
|
|
||||||
|
<FormControl id="speak_only_to">
|
||||||
|
<FormLabel>Speak only to</FormLabel>
|
||||||
|
<Input type="text" placeholder="agent" isRequired />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl id="tag">
|
||||||
|
<FormLabel>Tag</FormLabel>
|
||||||
|
<Input type="text" placeholder="tags" isRequired />
|
||||||
|
</FormControl>
|
||||||
|
</OutlineBox>
|
||||||
|
<HStack w="full">
|
||||||
|
<Button colorScheme="jambonz" type="submit" w="full">
|
||||||
|
Start Conference
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
colorScheme="grey"
|
||||||
|
type="button"
|
||||||
|
w="full"
|
||||||
|
textColor="black"
|
||||||
|
onClick={handleCancel}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewConference;
|
||||||
Reference in New Issue
Block a user