From 8ff0443aeae9850054ce827ed43e2a29b552fed9 Mon Sep 17 00:00:00 2001 From: balzack Date: Sun, 26 Jan 2025 22:31:26 -0800 Subject: [PATCH] implementing call gui --- app/client/mobile/ios/Podfile.lock | 6 ++ app/client/mobile/package.json | 1 + .../mobile/src/calling/Calling.styled.ts | 33 ++++++++++- app/client/mobile/src/calling/Calling.tsx | 57 ++++++++++++++++++- .../mobile/src/calling/useCalling.hook.ts | 35 ++++++++---- app/client/mobile/src/constants/Colors.ts | 2 +- app/client/mobile/yarn.lock | 11 ++++ 7 files changed, 128 insertions(+), 17 deletions(-) diff --git a/app/client/mobile/ios/Podfile.lock b/app/client/mobile/ios/Podfile.lock index ba51b721..fd02926f 100644 --- a/app/client/mobile/ios/Podfile.lock +++ b/app/client/mobile/ios/Podfile.lock @@ -1,5 +1,7 @@ PODS: - boost (1.84.0) + - BVLinearGradient (2.8.3): + - React-Core - DoubleConversion (1.1.6) - FBLazyVector (0.75.4) - Firebase/CoreOnly (11.5.0): @@ -1862,6 +1864,7 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) @@ -1970,6 +1973,8 @@ SPEC REPOS: EXTERNAL SOURCES: boost: :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + BVLinearGradient: + :path: "../node_modules/react-native-linear-gradient" DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" FBLazyVector: @@ -2140,6 +2145,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 4cb898d0bf20404aab1850c656dcea009429d6c1 + BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3 DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 FBLazyVector: 430e10366de01d1e3d57374500b1b150fe482e6d Firebase: 7a56fe4f56b5ab81b86a6822f5b8f909ae6fc7e2 diff --git a/app/client/mobile/package.json b/app/client/mobile/package.json index d06b751e..a6319b68 100644 --- a/app/client/mobile/package.json +++ b/app/client/mobile/package.json @@ -39,6 +39,7 @@ "react-native-gesture-handler": "^2.19.0", "react-native-image-crop-picker": "^0.41.2", "react-native-keyboard-aware-scroll-view": "^0.9.5", + "react-native-linear-gradient": "^2.8.3", "react-native-paper": "^5.12.5", "react-native-reanimated": "^3.15.2", "react-native-rsa-native": "^2.0.5", diff --git a/app/client/mobile/src/calling/Calling.styled.ts b/app/client/mobile/src/calling/Calling.styled.ts index 9c979dd7..2ee4eefd 100644 --- a/app/client/mobile/src/calling/Calling.styled.ts +++ b/app/client/mobile/src/calling/Calling.styled.ts @@ -25,6 +25,11 @@ export const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, + call: { + width: '100%', + height: '100%', + display: 'flex', + }, image: { width: '100%', height: '100%', @@ -32,8 +37,32 @@ export const styles = StyleSheet.create({ }, frame: { display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 8, + overflow: 'hidden', + padding: 2, + position: 'relative', + }, + closeIcon: { + borderRadius: 8, + }, + name: { + fontSize: 28, + minWidth: '50%', + color: '#aaaaaa', + paddingLeft: 16, width: '100%', - height: '100%', - padding: 16, + }, + overlap: { + display: 'flex', + flexDirection: 'row', + position: 'absolute', + alignItems: 'center', + width: '100%', + justifyContent: 'center', + paddingBottom: 8, + paddingTop: 8, + gap: 32, }, }); diff --git a/app/client/mobile/src/calling/Calling.tsx b/app/client/mobile/src/calling/Calling.tsx index cb95c4b6..d0f60cbf 100644 --- a/app/client/mobile/src/calling/Calling.tsx +++ b/app/client/mobile/src/calling/Calling.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { Image, SafeAreaView, Modal, ScrollView, View } from 'react-native'; +import { useWindowDimensions, Image, SafeAreaView, Modal, ScrollView, View } from 'react-native'; import { Surface, Icon, Divider, Button, IconButton, Text, TextInput} from 'react-native-paper'; import {styles} from './Calling.styled'; import {useCalling} from './useCalling.hook'; @@ -7,11 +7,28 @@ import {BlurView} from '@react-native-community/blur'; import { Confirm } from '../confirm/Confirm'; import { ActivityIndicator } from 'react-native-paper'; import FastImage from 'react-native-fast-image' +import LinearGradient from 'react-native-linear-gradient'; +import { Colors } from '../constants/Colors'; export function Calling({ callCard }: { callCard: string }) { const { state, actions } = useCalling(); const [alert, setAlert] = useState(false); const [connecting, setConnecting] = useState(false); + const [ending, setEnding] = useState(false); + const {height, width} = useWindowDimensions(); + + const end = async () => { + if (!ending) { + setEnding(true); + try { + await actions.end(); + } catch (err) { + console.log(err); + setAlert(true); + } + setEnding(false); + } + } const call = async (cardId: string) => { if (!connecting) { @@ -44,6 +61,10 @@ export function Calling({ callCard }: { callCard: string }) { } }, [callCard]); + const overlap = (width + 128) > height; + const frameWidth = width > height ? height : width - 16; + const frameHeight = frameWidth; + //const frameHeight = overlap ? frameWidth : frameWidth + 128; return ( 0 || alert) ? styles.active : styles.inactive}> @@ -51,13 +72,43 @@ export function Calling({ callCard }: { callCard: string }) { )} { state.calling && ( - + - + { state.loaded && ( + + + + + )} + { state.loaded && ( + + + + + )} + { state.loaded && ( + + { state.calling.name && ( + { state.calling.name } + )} + { !state.calling.name && ( + { `${state.calling.handle}/${state.calling.node}` } + )} + + )} + { state.loaded && ( + + + + + + )} + )} diff --git a/app/client/mobile/src/calling/useCalling.hook.ts b/app/client/mobile/src/calling/useCalling.hook.ts index aa55fa47..87c6edab 100644 --- a/app/client/mobile/src/calling/useCalling.hook.ts +++ b/app/client/mobile/src/calling/useCalling.hook.ts @@ -27,6 +27,8 @@ export function useCalling() { cards: [], calling: null as null | Card, failed: false, + loaded: false, + panelOffset: 0, }) // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -55,8 +57,6 @@ export function useCalling() { }; const linkStatus = async (status: string) => { -console.log("LINK STATUS: ", status); - if (call.current) { const { policy, peer, link } = call.current; if (status === 'connected') { @@ -84,8 +84,6 @@ console.log("LINK STATUS: ", status); try { peer.close(); link.close(); - link.clearStatusListener(); - link.clearMessageListener(); } catch (err) { console.log(err); } @@ -96,8 +94,6 @@ console.log("LINK STATUS: ", status); } const linkMessage = async (message: any) => { -console.log("LINK MSG: ", message); - if (call.current) { const { peer, link, candidates, policy } = call.current; try { @@ -135,13 +131,9 @@ console.log("LINK MSG: ", message); updateState({ failed: true }); } } - -console.log("LINK MSG: done"); - } const peerCandidate = async (candidate) => { -console.log("PEER CANDIDATE"); if (call.current && candidate) { const { link } = call.current; await link.sendMessage({ candidate }); @@ -149,7 +141,6 @@ console.log("PEER CANDIDATE"); } const peerNegotiate = async () => { -console.log("PEER NEGOTIATE"); if (call.current) { const { peer, link } = call.current; const description = await peer.createOffer(constraints); @@ -204,6 +195,20 @@ console.log("PEER NEGOTIATE"); }, [app.state.session]); const actions = { + end: async () => { + if (!call.current) { + throw new Error('no active call'); + } + const { link, peer } = call.current; + try { + peer.close(); + link.close(); + } catch (err) { + console.log(err); + } + call.current = null; + updateState({ calling: null }); + }, accept: async (callId: string, call: Call) => { if (call.current) { throw new Error('active call in progress'); @@ -239,6 +244,14 @@ console.log("PEER NEGOTIATE"); link.setMessageListener(linkMessage); updateState({ calling: card }); }, + loaded: (e) => { + const { width, height } = e.nativeEvent.layout; + if (width > (height + 80)) { + updateState({ panelOffset: 0, loaded: true }); + } else { + updateState({ panelOffset: ((height - width) - 80) / 2, loaded: true }); + } + } } return { state, actions } diff --git a/app/client/mobile/src/constants/Colors.ts b/app/client/mobile/src/constants/Colors.ts index daed6531..3d29437e 100644 --- a/app/client/mobile/src/constants/Colors.ts +++ b/app/client/mobile/src/constants/Colors.ts @@ -1,6 +1,6 @@ export const Colors = { primary: '#408060', - danger: '#ff8888', + danger: '#ff6666', placeholder: '#888888', unsaved: '#555555', confirmed: '#aaaaaa', diff --git a/app/client/mobile/yarn.lock b/app/client/mobile/yarn.lock index a7fafc99..76ec2bbf 100644 --- a/app/client/mobile/yarn.lock +++ b/app/client/mobile/yarn.lock @@ -4461,6 +4461,7 @@ __metadata: react-native-gesture-handler: ^2.19.0 react-native-image-crop-picker: ^0.41.2 react-native-keyboard-aware-scroll-view: ^0.9.5 + react-native-linear-gradient: ^2.8.3 react-native-paper: ^5.12.5 react-native-reanimated: ^3.15.2 react-native-rsa-native: ^2.0.5 @@ -10705,6 +10706,16 @@ __metadata: languageName: node linkType: hard +"react-native-linear-gradient@npm:^2.8.3": + version: 2.8.3 + resolution: "react-native-linear-gradient@npm:2.8.3" + peerDependencies: + react: "*" + react-native: "*" + checksum: f980d324e551bbc475c6406bdc5250a08242020cbe653412fa169bbdf51e28a502e225de105b4d696d6a1a1b733d44782469020f4936d8b3ce0e2c78e51cf58f + languageName: node + linkType: hard + "react-native-paper@npm:^5.12.5": version: 5.13.1 resolution: "react-native-paper@npm:5.13.1"