diff --git a/app/mobile/src/context/useAppContext.hook.js b/app/mobile/src/context/useAppContext.hook.js
index ee900bc3..07fb6a12 100644
--- a/app/mobile/src/context/useAppContext.hook.js
+++ b/app/mobile/src/context/useAppContext.hook.js
@@ -181,8 +181,8 @@ export function useAppContext() {
card.actions.setRevision(cardRev);
}
if (activity.ring) {
- const { cardId, callId, calleeToken } = activity.ring;
- ring.actions.ring(cardId, callId, calleeToken);
+ const { cardId, callId, calleeToken, iceUrl, iceUsername, icePassword } = activity.ring;
+ ring.actions.ring(cardId, callId, calleeToken, iceUrl, iceUsername, icePassword);
}
}
catch (err) {
diff --git a/app/mobile/src/context/useRingContext.hook.js b/app/mobile/src/context/useRingContext.hook.js
index cc0b8b8c..647bf6b8 100644
--- a/app/mobile/src/context/useRingContext.hook.js
+++ b/app/mobile/src/context/useRingContext.hook.js
@@ -49,14 +49,6 @@ export function useRingContext() {
const connected = useRef(false);
const candidates = useRef([]);
- const iceServers = [
- {
- urls: 'turn:44.238.207.157:3478?transport=udp',
- username: 'user',
- credential: 'pass'
- },
- ];
-
const constraints = {
mandatory: {
OfferToReceiveAudio: true,
@@ -168,9 +160,9 @@ export function useRingContext() {
processing.current = false;
}
- const transmit = async (policy) => {
+ const transmit = async (policy, ice) => {
- pc.current = new RTCPeerConnection({ iceServers });
+ pc.current = new RTCPeerConnection({ iceServers: ice });
pc.current.addEventListener( 'connectionstatechange', event => {
console.log("CONNECTION STATE", event);
} );
@@ -234,7 +226,7 @@ export function useRingContext() {
}
}
- const connect = async (policy, node, token, clearRing, clearAlive) => {
+ const connect = async (policy, node, token, clearRing, clearAlive, ice) => {
// connect signal socket
connected.current = false;
@@ -256,7 +248,7 @@ export function useRingContext() {
if (policy === 'polite') {
connected.current = true;
InCallManager.start({media: 'audio'});
- transmit('polite');
+ transmit('polite', ice);
polite();
}
}
@@ -311,7 +303,7 @@ export function useRingContext() {
if (policy === 'impolite') {
connected.current = true;
InCallManager.start({media: 'audio'});
- transmit('impolite');
+ transmit('impolite', ice);
impolite();
}
}
@@ -335,9 +327,9 @@ export function useRingContext() {
clearSession: () => {
access.current = null;
},
- ring: (cardId, callId, calleeToken) => {
+ ring: (cardId, callId, calleeToken, iceUrl, iceUsername, icePassword) => {
const key = `${cardId}:${callId}`
- const call = ringing.current.get(key) || { cardId, calleeToken, callId }
+ const call = ringing.current.get(key) || { cardId, calleeToken, callId, iceUrl, iceUsername, icePassword }
call.expires = Date.now() + EXPIRE;
ringing.current.set(key, call);
updateState({ ringing: ringing.current });
@@ -369,7 +361,7 @@ export function useRingContext() {
}
}
},
- accept: async (cardId, callId, contactNode, contactToken, calleeToken) => {
+ accept: async (cardId, callId, contactNode, contactToken, calleeToken, iceUrl, iceUsername, icePassword) => {
if (calling.current) {
throw new Error("active session");
}
@@ -382,7 +374,8 @@ export function useRingContext() {
updateState({ ringing: ringing.current, callStatus: "connecting", cardId });
calling.current = { callId, contactNode, contactToken, host: false };
- await connect('impolite', contactNode, calleeToken, () => {}, () => {});
+ const ice = [{ urls: iceUrl, username: iceUsername, credential: icePassword }];
+ await connect('impolite', contactNode, calleeToken, () => {}, () => {}, ice);
}
},
end: async () => {
@@ -412,9 +405,9 @@ export function useRingContext() {
// create call
const { server, token } = access.current;
const call = await addCall(server, token, cardId);
- const { id, keepAlive, callerToken, calleeToken } = call;
+ const { id, keepAlive, callerToken, calleeToken, iceUrl, iceUsername, icePassword } = call;
try {
- await addContactRing(contactNode, contactToken, { index, callId: id, calleeToken });
+ await addContactRing(contactNode, contactToken, { index, callId: id, calleeToken, iceUrl, iceUsername, icePassword });
}
catch (err) {
console.log(err);
@@ -436,7 +429,7 @@ export function useRingContext() {
}
}
else {
- await addContactRing(contactNode, contactToken, { index, callId: id, calleeToken });
+ await addContactRing(contactNode, contactToken, { index, callId: id, calleeToken, iceUrl, iceUsername, icePassword });
index += 1;
}
}
@@ -447,7 +440,8 @@ export function useRingContext() {
updateState({ callStatus: "ringing", cardId });
calling.current = { callId: id, host: true };
- await connect('polite', server, callerToken, () => clearInterval(ringInterval), () => clearInterval(aliveInterval));
+ const ice = [{ urls: iceUrl, username: iceUsername, credential: icePassword }];
+ await connect('polite', server, callerToken, () => clearInterval(ringInterval), () => clearInterval(aliveInterval), ice);
},
enableVideo: async () => {
if (!videoTrack.current) {
diff --git a/app/mobile/src/dashboard/Dashboard.jsx b/app/mobile/src/dashboard/Dashboard.jsx
index 7d891ab5..7168386b 100644
--- a/app/mobile/src/dashboard/Dashboard.jsx
+++ b/app/mobile/src/dashboard/Dashboard.jsx
@@ -191,6 +191,8 @@ export function Dashboard(props) {
onValueChange={actions.setPushSupported} trackColor={styles.track}/>
+
+
actions.setEnableImage(!state.enableImage)}>
Enable Image Queue:
@@ -209,6 +211,21 @@ export function Dashboard(props) {
+
+
+ actions.setEnableIce(!state.enableIce)}>
+ Enable WebRTC Calls:
+
+
+
+
+
+
diff --git a/app/mobile/src/dashboard/Dashboard.styled.js b/app/mobile/src/dashboard/Dashboard.styled.js
index e8c37d98..820410a4 100644
--- a/app/mobile/src/dashboard/Dashboard.styled.js
+++ b/app/mobile/src/dashboard/Dashboard.styled.js
@@ -194,7 +194,7 @@ export const styles = StyleSheet.create({
padding: 4,
borderRadius: 4,
marginBottom: 16,
- fontSize: 16,
+ fontSize: 12,
color: Colors.text,
},
switch: {
@@ -224,4 +224,20 @@ export const styles = StyleSheet.create({
borderRadius: 4,
borderColor: Colors.divider,
},
+ label: {
+ borderTopWidth: 1,
+ borderColor: Colors.divider,
+ marginTop: 12,
+ },
+ labelText: {
+ fontSize: 14,
+ color: Colors.text,
+ },
+ ice: {
+ display: 'flex',
+ flexDirection: 'row',
+ marginTop: 8,
+ alignItems: 'center',
+ paddingBottom: 8,
+ }
});
diff --git a/app/mobile/src/dashboard/useDashboard.hook.js b/app/mobile/src/dashboard/useDashboard.hook.js
index 37628826..99063fa7 100644
--- a/app/mobile/src/dashboard/useDashboard.hook.js
+++ b/app/mobile/src/dashboard/useDashboard.hook.js
@@ -28,6 +28,10 @@ export function useDashboard(config, server, token) {
enableAudio: true,
enableVideo: true,
createToken: null,
+ enableIce: false,
+ iceUrl: null,
+ iceUsername: null,
+ icePassword: null,
});
const navigate = useNavigate();
@@ -55,8 +59,8 @@ export function useDashboard(config, server, token) {
};
useEffect(() => {
- const { keyType, accountStorage, domain, enableImage, enableAudio, enableVideo, pushSupported } = config;
- updateState({ keyType, storage: accountStorage.toString(), domain, enableImage, enableAudio, enableVideo, pushSupported });
+ const { keyType, accountStorage, domain, enableImage, enableAudio, enableVideo, pushSupported, enableIce, iceUrl, iceUsername, icePassword } = config;
+ updateState({ keyType, storage: accountStorage.toString(), domain, enableImage, enableAudio, enableVideo, pushSupported, enableIce, iceUrl, iceUsername, icePassword });
}, [config]);
useEffect(() => {
@@ -111,9 +115,21 @@ export function useDashboard(config, server, token) {
setKeyType: (keyType) => {
updateState({ keyType });
},
+ setEnableIce: (enableIce) => {
+ updateState({ enableIce });
+ },
+ setIceUrl: (iceUrl) => {
+ updateState({ iceUrl });
+ },
+ setIceUsername: (iceUsername) => {
+ updateState({ iceUsername });
+ },
+ setIcePassword: (icePassword) => {
+ updateState({ icePassword });
+ },
saveConfig: async () => {
- const { storage, domain, keyType, enableImage, enableAudio, enableVideo } = state;
- const config = { accountStorage: Number(storage), domain, keyType, enableImage, enableAudio, enableVideo };
+ const { storage, domain, keyType, enableImage, enableAudio, enableVideo, enableIce, iceUrl, iceUsername, icePassword } = state;
+ const config = { accountStorage: Number(storage), domain, keyType, enableImage, enableAudio, enableVideo, enableIce, iceUrl, iceUsername, icePassword };
await setNodeConfig(server, token, config);
},
enableUser: async (accountId, enabled) => {
diff --git a/app/mobile/src/session/Session.jsx b/app/mobile/src/session/Session.jsx
index 5bb95d62..ce6ed02b 100644
--- a/app/mobile/src/session/Session.jsx
+++ b/app/mobile/src/session/Session.jsx
@@ -329,7 +329,8 @@ export function Session() {
useEffect(() => {
let incoming = [];
for (let i = 0; i < state.ringing.length; i++) {
- const { img, name, handle, callId, cardId, contactNode, contactToken, calleeToken } = state.ringing[i];
+ const call = state.ringing[i];
+ const { img, cardId, callId, name, handle, contactNode } = call || {};
const label = name ? name : `${handle}@${contactNode}`;
const key = `${cardId}:${callId}`
incoming.push(
@@ -339,10 +340,10 @@ export function Session() {
actions.ignore({ cardId, callId })}>
- actions.decline({ cardId, contactNode, contactToken, callId })}>
+ actions.decline(call)}>
- actions.accept({ cardId, callId, contactNode, contactToken, calleeToken })}>
+ actions.accept(call)}>
diff --git a/app/mobile/src/session/cards/Cards.jsx b/app/mobile/src/session/cards/Cards.jsx
index 61fbf851..c5fcc952 100644
--- a/app/mobile/src/session/cards/Cards.jsx
+++ b/app/mobile/src/session/cards/Cards.jsx
@@ -66,7 +66,7 @@ export function CardsBody({ filter, sort, openContact, addChannel }) {
data={state.cards}
initialNumToRender={25}
renderItem={({ item }) => call(item)} message={() => addChannel(item.cardId)} />}
+ enableIce={state.enableIce} call={() => call(item)} message={() => addChannel(item.cardId)} />}
keyExtractor={item => item.cardId}
/>
)}
diff --git a/app/mobile/src/session/cards/cardItem/CardItem.jsx b/app/mobile/src/session/cards/cardItem/CardItem.jsx
index b4c51c68..89701683 100644
--- a/app/mobile/src/session/cards/cardItem/CardItem.jsx
+++ b/app/mobile/src/session/cards/cardItem/CardItem.jsx
@@ -4,7 +4,7 @@ import { styles } from './CardItem.styled';
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import Colors from 'constants/Colors';
-export function CardItem({ item, openContact, call, message }) {
+export function CardItem({ item, openContact, enableIce, call, message }) {
const select = () => {
const { guid, name, handle, node, location, description, imageSet } = item;
@@ -26,9 +26,11 @@ export function CardItem({ item, openContact, call, message }) {
-
-
-
+ { enableIce && (
+
+
+
+ )}
)}
{ item.status === 'connected' && item.offsync === 1 && (
diff --git a/app/mobile/src/session/cards/useCards.hook.js b/app/mobile/src/session/cards/useCards.hook.js
index 4d53bba8..6fb03c62 100644
--- a/app/mobile/src/session/cards/useCards.hook.js
+++ b/app/mobile/src/session/cards/useCards.hook.js
@@ -1,13 +1,16 @@
import { useState, useEffect, useRef, useContext } from 'react';
import { CardContext } from 'context/CardContext';
import { RingContext } from 'context/RingContext';
+import { AccountContext } from 'context/AccountContext';
export function useCards(filter, sort) {
const [state, setState] = useState({
cards: [],
+ enableIce: false,
});
+ const account = useContext(AccountContext);
const card = useContext(CardContext);
const ring = useContext(RingContext);
@@ -15,6 +18,11 @@ export function useCards(filter, sort) {
setState((s) => ({ ...s, ...value }));
}
+ useEffect(() => {
+ const { enableIce } = account.state.status || {};
+ updateState({ enableIce });
+ }, [account.state]);
+
const setCardItem = (item) => {
const { profile, detail, cardId } = item.card || { profile: {}, detail: {} }
const { name, handle, node, guid, location, description, imageSet } = profile;
diff --git a/app/mobile/src/session/useSession.hook.js b/app/mobile/src/session/useSession.hook.js
index 80578343..4f0687a1 100644
--- a/app/mobile/src/session/useSession.hook.js
+++ b/app/mobile/src/session/useSession.hook.js
@@ -44,14 +44,14 @@ export function useSession() {
const expired = Date.now();
ring.state.ringing.forEach(call => {
if (call.expires > expired && !call.status) {
- const { callId, cardId, calleeToken } = call;
+ const { callId, cardId, calleeToken, iceUrl, iceUsername, icePassword } = call;
const contact = card.state.cards.get(cardId);
if (contact) {
const { imageSet, name, handle, node, guid } = contact.card?.profile || {};
const { token } = contact.card?.detail || {};
const contactToken = `${guid}.${token}`;
const img = imageSet ? card.actions.getCardImageUrl(cardId) : null;
- ringing.push({ cardId, img, name, handle, contactNode: node, callId, contactToken, calleeToken });
+ ringing.push({ cardId, img, name, handle, contactNode: node, callId, contactToken, calleeToken, iceUrl, iceUsername, icePassword });
}
}
});
@@ -106,8 +106,8 @@ export function useSession() {
await ring.actions.decline(cardId, contactNode, contactToken, callId);
},
accept: async (call) => {
- const { cardId, callId, contactNode, contactToken, calleeToken } = call;
- await ring.actions.accept(cardId, callId, contactNode, contactToken, calleeToken);
+ const { cardId, callId, contactNode, contactToken, calleeToken, iceUrl, iceUsername, icePassword } = call;
+ await ring.actions.accept(cardId, callId, contactNode, contactToken, calleeToken, iceUrl, iceUsername, icePassword);
},
end: async () => {
await ring.actions.end();