add outgoing page and fix bugs

This commit is contained in:
Quan HL
2023-10-17 15:04:56 +07:00
parent 0914da166a
commit a12a0cc751
8 changed files with 134 additions and 55 deletions

9
package-lock.json generated
View File

@@ -14,6 +14,7 @@
"@testing-library/user-event": "^13.5.0",
"buffer": "^6.0.3",
"dayjs": "^1.11.10",
"fuse.js": "^6.6.2",
"google-libphonenumber": "^3.2.33",
"jssip": "^3.2.17",
"react": "^18.2.0",
@@ -10153,6 +10154,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/fuse.js": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz",
"integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==",
"engines": {
"node": ">=10"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",

View File

@@ -9,6 +9,7 @@
"@testing-library/user-event": "^13.5.0",
"buffer": "^6.0.3",
"dayjs": "^1.11.10",
"fuse.js": "^6.6.2",
"google-libphonenumber": "^3.2.33",
"jssip": "^3.2.17",
"react": "^18.2.0",

View File

@@ -62,24 +62,11 @@ export const WindowApp = () => {
const loadSettings = () => {
const settings = getSettings();
if (settings.sipDomain && settings.sipDomain !== sipDomain) {
setSipDomain(settings.sipDomain);
}
if (
settings.sipServerAddress &&
settings.sipServerAddress !== sipServerAddress
) {
setSipServerAddress(settings.sipServerAddress);
}
if (settings.sipUsername && settings.sipUsername !== sipUsername) {
setSipUsername(settings.sipUsername);
}
if (settings.sipPassword && settings.sipPassword !== sipPassword) {
setSipPassword(settings.sipPassword);
}
if (settings.sipDisplayName && settings.sipDisplayName !== sipDisplayName) {
setSipDisplayName(settings.sipDisplayName);
}
setSipDomain(settings.sipDomain);
setSipServerAddress(settings.sipServerAddress);
setSipUsername(settings.sipUsername);
setSipPassword(settings.sipPassword);
setSipDisplayName(settings.sipDisplayName);
};
return (
<Grid h="100vh" templateRows="1fr auto">

View File

@@ -10,10 +10,11 @@ import {
Spacer,
UnorderedList,
} from "@chakra-ui/react";
import { useState } from "react";
import { useEffect, useState } from "react";
import { Search, Sliders } from "react-feather";
import { CallHistory } from "src/common/types";
import CallHistoryItem from "./call-history-item";
import Fuse from "fuse.js";
type CallHistoriesProbs = {
calls: CallHistory[];
@@ -21,6 +22,25 @@ type CallHistoriesProbs = {
export const CallHistories = ({ calls }: CallHistoriesProbs) => {
const [searchText, setSearchText] = useState("");
const [callHistories, setCallHistories] = useState<CallHistory[]>(calls);
useEffect(() => {
if (searchText) {
setCallHistories(
new Fuse(calls, {
keys: ["number"],
})
.search(searchText)
.map(({ item }) => item)
);
} else {
setCallHistories(calls);
}
}, [searchText]);
useEffect(() => {
setCallHistories(calls);
}, [calls]);
return (
<VStack spacing={2}>
@@ -46,7 +66,7 @@ export const CallHistories = ({ calls }: CallHistoriesProbs) => {
</Text>
</HStack>
</Grid>
{calls.length > 0 ? (
{callHistories.length > 0 ? (
<UnorderedList
w="full"
spacing={2}
@@ -54,7 +74,7 @@ export const CallHistories = ({ calls }: CallHistoriesProbs) => {
overflowY="auto"
mt={2}
>
{calls.map((c) => (
{callHistories.map((c) => (
<CallHistoryItem call={c} />
))}
</UnorderedList>

View File

@@ -27,6 +27,9 @@ export const DialPad = ({ handleDigitPress }: DialPadProbs) => {
height="70px"
variant="unstyled"
bg="white"
_hover={{
bg: "gray.100",
}}
borderRadius={0}
>
{num}

View File

@@ -41,7 +41,7 @@ import {
saveCallHistory,
saveCurrentCall,
} from "src/storage";
import dayjs from "dayjs";
import { OutGoingCall } from "./outgoing-call";
type PhoneProbs = {
sipDomain: string;
@@ -75,9 +75,12 @@ export const Phone = ({
const [isCallButtonLoading, setIsCallButtonLoading] = useState(false);
useEffect(() => {
if (sipDomain && sipUsername && sipPassword) {
if (sipDomain && sipUsername && sipPassword && sipServerAddress) {
createSipClient();
setIsConfigured(true);
} else {
setIsConfigured(false);
clientGoOffline();
}
}, [sipDomain, sipUsername, sipPassword, sipServerAddress, sipDisplayName]);
@@ -99,18 +102,18 @@ export const Phone = ({
}
}, [callStatus]);
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;
}
});
}, []);
// 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;
@@ -166,17 +169,24 @@ export const Phone = ({
});
// Call Status
sipClient.on(SipConstants.SESSION_RINGING, (args) => {
saveCurrentCall({
number: args.session.user,
direction: args.session.direction,
timeStamp: Date.now(),
duration: "0",
});
if (args.session.direction === "incoming") {
saveCurrentCall({
number: args.session.user,
direction: args.session.direction,
timeStamp: Date.now(),
duration: "0",
});
}
setCallStatus(SipConstants.SESSION_RINGING);
setSessionDirection(args.session.direction);
setInputNumber(args.session.user);
});
sipClient.on(SipConstants.SESSION_ANSWERED, (args) => {
const currentCall = getCurrentCall();
if (currentCall) {
currentCall.timeStamp = Date.now();
saveCurrentCall(currentCall);
}
setCallStatus(SipConstants.SESSION_ANSWERED);
startCallDurationCounter();
});
@@ -203,15 +213,28 @@ export const Phone = ({
saveCallHistory(sipUsername, {
number: call.number,
direction: call.direction,
duration: new Date((Date.now() - call.timeStamp) / 1000)
.toISOString()
.substr(11, 8),
duration: transform(Date.now(), call.timeStamp),
timeStamp: call.timeStamp,
});
}
deleteCurrentCall();
};
function transform(t1: number, t2: number) {
const diff = Math.abs(t1 - t2) / 1000; // Get the difference in seconds
const hours = Math.floor(diff / 3600);
const minutes = Math.floor((diff % 3600) / 60);
const seconds = Math.floor(diff % 60);
// Pad the values with a leading zero if they are less than 10
const hours1 = hours < 10 ? "0" + hours : hours;
const minutes1 = minutes < 10 ? "0" + minutes : minutes;
const seconds1 = seconds < 10 ? "0" + seconds : seconds;
return `${hours1}:${minutes1}:${seconds1}`;
}
const handleDialPadClick = (value: string) => {
if (isSipClientIdle(callStatus)) {
setInputNumber((prev) => prev + value);
@@ -221,8 +244,16 @@ export const Phone = ({
};
const handleCallButtion = () => {
if (sipUA.current) {
if (sipUA.current && inputNumber) {
setIsCallButtonLoading(true);
setCallStatus(SipConstants.SESSION_RINGING);
setSessionDirection("outgoing");
saveCurrentCall({
number: inputNumber,
direction: "outgoing",
timeStamp: Date.now(),
duration: "0",
});
sipUA.current.call(inputNumber);
}
};
@@ -326,12 +357,16 @@ export const Phone = ({
</Heading>
)}
{isSipClientRinging(callStatus) && sessionDirection === "incoming" ? (
<IncommingCall
number={inputNumber}
answer={handleAnswer}
decline={handleDecline}
/>
{isSipClientRinging(callStatus) ? (
sessionDirection === "incoming" ? (
<IncommingCall
number={inputNumber}
answer={handleAnswer}
decline={handleDecline}
/>
) : (
<OutGoingCall number={inputNumber} cancelCall={handleDecline} />
)
) : (
<VStack
spacing={4}

View File

@@ -0,0 +1,26 @@
import { Button, Icon, Text, VStack } from "@chakra-ui/react";
import { PhoneCall } from "react-feather";
import { formatPhoneNumber } from "src/utils";
type OutGoingCallProbs = {
number: string;
cancelCall: () => void;
};
export const OutGoingCall = ({ number, cancelCall }: OutGoingCallProbs) => {
return (
<VStack alignItems="center" spacing={4} mt="130px" w="full">
<Icon as={PhoneCall} color="jambonz.500" w="60px" h="60px" />
<Text fontSize="15px">Dialing</Text>
<Text fontSize="24px" fontWeight="bold">
{formatPhoneNumber(number)}
</Text>
<Button w="full" colorScheme="jambonz" onClick={cancelCall}>
Cancel
</Button>
</VStack>
);
};
export default OutGoingCall;

View File

@@ -23,9 +23,7 @@ import ResetIcon from "src/imgs/icons/Reset.svg";
export const Settings = () => {
const [sipDomain, setSipDomain] = useState("");
const [sipServerAddress, setSipServerAddress] = useState(
"wss://sip.jambonz.cloud:8443/"
);
const [sipServerAddress, setSipServerAddress] = useState("");
const [sipUsername, setSipUsername] = useState("");
const [sipPassword, setSipPassword] = useState("");
const [sipDisplayName, setSipDisplayName] = useState("");
@@ -103,7 +101,7 @@ export const Settings = () => {
<FormLabel>Jambonz Server Address</FormLabel>
<Input
type="text"
placeholder="Server address"
placeholder="wss://sip.jambonz.cloud:8443/"
isRequired
value={sipServerAddress}
onChange={(e) => setSipServerAddress(e.target.value)}