diff --git a/app/client/mobile/src/call/Call.styled.ts b/app/client/mobile/src/call/Call.styled.ts
new file mode 100644
index 00000000..f0df1d78
--- /dev/null
+++ b/app/client/mobile/src/call/Call.styled.ts
@@ -0,0 +1,20 @@
+import {StyleSheet} from 'react-native';
+import { Colors } from '../constants/Colors';
+
+export const styles = StyleSheet.create({
+ active: {
+ width: '100%',
+ height: '100%',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ position: 'absolute',
+ },
+ inactive: {
+ display: 'none',
+ },
+ call: {
+ width: '100%',
+ height: '100%',
+ },
+});
diff --git a/app/client/mobile/src/call/Call.tsx b/app/client/mobile/src/call/Call.tsx
new file mode 100644
index 00000000..8d5f2a4b
--- /dev/null
+++ b/app/client/mobile/src/call/Call.tsx
@@ -0,0 +1,85 @@
+import React, { useEffect, useState } from 'react';
+import { View } from 'react-native';
+import { useCall } from './useCall.hook';
+import { styles } from './Call.styled'
+import { Card as Contact } from '../card/Card';
+import { Text, Surface, IconButton, ActivityIndicator } from 'react-native-paper';
+import { Confirm } from '../confirm/Confirm';
+import { Colors } from '../constants/Colors';
+
+export function Call() {
+ const { state, actions } = useCall();
+ const [alert, setAlert] = useState(false);
+ 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 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);
+ setAlert(true);
+ }
+ 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);
+ setAlert(true);
+ }
+ setApplyingVideo(false);
+ }
+ }
+
+ const end = async () => {
+ if (!ending) {
+ setEnding(true);
+ try {
+ await actions.end();
+ } catch (err) {
+ console.log(err);
+ setAlert(true);
+ }
+ setEnding(false);
+ }
+ }
+
+ const alertParams = {
+ title: state.strings.operationFailed,
+ prompt: state.strings.tryAgain,
+ cancel: {
+ label: state.strings.close,
+ action: () => {
+ setAlert(false);
+ },
+ },
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
diff --git a/app/client/mobile/src/call/useCall.hook.ts b/app/client/mobile/src/call/useCall.hook.ts
new file mode 100644
index 00000000..8aeeb4bf
--- /dev/null
+++ b/app/client/mobile/src/call/useCall.hook.ts
@@ -0,0 +1,54 @@
+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,
+ remoteVideo: false,
+ localVideo: false,
+ audioEnabled: false,
+ videoEnabled: 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, fullscreen, 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, remoteVideo, localVideo, audioEnabled, videoEnabled, connected, failed });
+ }, [ring.state]);
+
+ const actions = ring.actions;
+ return { state, actions };
+}
diff --git a/app/client/mobile/src/context/useRingContext.hook.ts b/app/client/mobile/src/context/useRingContext.hook.ts
index 4884162f..ea977681 100644
--- a/app/client/mobile/src/context/useRingContext.hook.ts
+++ b/app/client/mobile/src/context/useRingContext.hook.ts
@@ -49,6 +49,7 @@ export function useRingContext() {
connected: false,
connectedTime: 0,
failed: false,
+ fullscreen: false,
})
// eslint-disable-next-line @typescript-eslint/no-explicit-any
diff --git a/app/client/mobile/src/ring/Ring.tsx b/app/client/mobile/src/ring/Ring.tsx
index 49752ed0..0ec33ff2 100644
--- a/app/client/mobile/src/ring/Ring.tsx
+++ b/app/client/mobile/src/ring/Ring.tsx
@@ -121,11 +121,11 @@ export function Ring() {
)}
{ state.calling && (
-
-
+
+ actions.setFullscreen(true)} />
{ state.calling.name && (
- asuperlongnamehere asuperlongnamehere
+ { state.calling.name }
)}
{ !state.calling.name && (
{ state.strings.name }
diff --git a/app/client/mobile/src/ring/useRing.hook.ts b/app/client/mobile/src/ring/useRing.hook.ts
index 49b95c08..47aca1e2 100644
--- a/app/client/mobile/src/ring/useRing.hook.ts
+++ b/app/client/mobile/src/ring/useRing.hook.ts
@@ -15,6 +15,7 @@ export function useRing() {
calls: [] as { callId: string, card: Card }[],
calling: null as null | Card,
remoteVideo: false,
+ localVideo: false,
audioEnabled: false,
connected: false,
duration: 0,
@@ -40,11 +41,11 @@ export function useRing() {
}, []);
useEffect(() => {
- const { calls, calling, remoteVideo, audioEnabled, connected, connectedTime, failed } = ring.state;
+ 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, remoteVideo, audioEnabled, connected, failed });
+ updateState({ calls, calling, duration, localVideo, remoteVideo, audioEnabled, connected, failed });
}, [ring.state]);
const actions = ring.actions;
diff --git a/app/client/mobile/src/session/Session.tsx b/app/client/mobile/src/session/Session.tsx
index 7421677c..eb061342 100644
--- a/app/client/mobile/src/session/Session.tsx
+++ b/app/client/mobile/src/session/Session.tsx
@@ -19,6 +19,7 @@ import {createDrawerNavigator} from '@react-navigation/drawer';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {Colors} from '../constants/Colors';
import {Ring} from '../ring/Ring';
+import {Call} from '../call/Call';
const SettingsDrawer = createDrawerNavigator();
const ContactsDrawer = createDrawerNavigator();
@@ -198,6 +199,7 @@ export function Session() {
)}
+
);