diff --git a/net/server/internal/api_status.go b/net/server/internal/api_status.go index ae52b0cf..f41bddf2 100644 --- a/net/server/internal/api_status.go +++ b/net/server/internal/api_status.go @@ -113,7 +113,7 @@ func getRevision(account *store.Account) Activity { r.Card = account.CardRevision var a Activity - a.Revision = r + a.Revision = &r return a } @@ -131,7 +131,7 @@ func SetRing(card *store.Card, ring Ring) { phone.CalleeToken = ring.CalleeToken phone.CardID = card.CardSlot.CardSlotID var a Activity - a.Phone = phone; + a.Phone = ☎ msg, err := json.Marshal(a) if err != nil { ErrMsg(err); diff --git a/net/server/internal/models.go b/net/server/internal/models.go index f0ab4ab9..0642ce58 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -395,9 +395,9 @@ type ProfileData struct { //Activity listener for account type Activity struct { - Revision Revision `json:"revision,emitempty"` + Revision *Revision `json:"revision,emitempty"` - Phone Phone `json:"ring",omitempty"` + Phone *Phone `json:"ring",omitempty"` } //Revision revision of each account module diff --git a/net/web/src/App.js b/net/web/src/App.js index 5e8c23c7..2ef1e566 100644 --- a/net/web/src/App.js +++ b/net/web/src/App.js @@ -12,6 +12,7 @@ import { StoreContextProvider } from 'context/StoreContext'; import { UploadContextProvider } from 'context/UploadContext'; import { ViewportContextProvider } from 'context/ViewportContext'; import { ConversationContextProvider } from 'context/ConversationContext'; +import { RingContextProvider } from 'context/RingContext'; import { AppWrapper } from 'App.styled'; import { Root } from './root/Root'; @@ -30,33 +31,35 @@ function App() { - - - - - - - } /> - } /> - } /> - } /> - } /> - - - - }> - - - - - - - + + + + + + + + } /> + } /> + } /> + } /> + } /> + + + + }> + + + + + + + + diff --git a/net/web/src/api/addContactRing.js b/net/web/src/api/addContactRing.js new file mode 100644 index 00000000..fd387762 --- /dev/null +++ b/net/web/src/api/addContactRing.js @@ -0,0 +1,12 @@ +import { checkResponse, fetchWithTimeout } from './fetchUtil'; + +export async function addContactRing(server, token, call) { + let host = ""; + if (server) { + host = `https://${server}` + } + + let ring = await fetchWithTimeout(`${host}/talk/ring?contact=${token}`, { method: 'POST', body: JSON.stringify(call) }); + checkResponse(ring); +} + diff --git a/net/web/src/context/RingContext.js b/net/web/src/context/RingContext.js new file mode 100644 index 00000000..1ec9e7ca --- /dev/null +++ b/net/web/src/context/RingContext.js @@ -0,0 +1,14 @@ +import { createContext } from 'react'; +import { useRingContext } from './useRingContext.hook'; + +export const RingContext = createContext({}); + +export function RingContextProvider({ children }) { + const { state, actions } = useRingContext(); + return ( + + {children} + + ); +} + diff --git a/net/web/src/context/useAppContext.hook.js b/net/web/src/context/useAppContext.hook.js index 2d281a09..eff405bb 100644 --- a/net/web/src/context/useAppContext.hook.js +++ b/net/web/src/context/useAppContext.hook.js @@ -9,6 +9,7 @@ import { CardContext } from './CardContext'; import { ChannelContext } from './ChannelContext'; import { StoreContext } from './StoreContext'; import { UploadContext } from './UploadContext'; +import { RingContext } from './RingContext'; import { createWebsocket } from 'api/fetchUtil'; export function useAppContext(websocket) { @@ -30,6 +31,7 @@ export function useAppContext(websocket) { setState((s) => ({ ...s, ...value })) } + const ringContext = useContext(RingContext); const uploadContext = useContext(UploadContext); const storeContext = useContext(StoreContext); const accountContext = useContext(AccountContext); @@ -57,6 +59,7 @@ export function useAppContext(websocket) { const clearSession = () => { uploadContext.actions.clear(); storeContext.actions.clear(); + ringContext.actions.clear(); accountContext.actions.clearToken(); profileContext.actions.clearToken(); @@ -173,8 +176,14 @@ export function useAppContext(websocket) { let activity = JSON.parse(ev.data); updateState({ status: 'connected' }); if (activity.revision) { +console.log("GOR REVISION"); setAppRevision(activity.revision); } + if (activity.ring) { +console.log("GOT PHONE!"); + const { cardId, callId, calleeToken } = activity.ring; + ringContext.actions.ring(cardId, callId, calleeToken); + } } catch (err) { console.log(err); diff --git a/net/web/src/context/useRingContext.hook.js b/net/web/src/context/useRingContext.hook.js new file mode 100644 index 00000000..89a51cca --- /dev/null +++ b/net/web/src/context/useRingContext.hook.js @@ -0,0 +1,60 @@ +import { useEffect, useContext, useState, useRef } from 'react'; + +export function useRingContext() { + const [state, setState] = useState({ + ringing: new Map(), + }); + const access = useRef(null); + + const EXPIRE = 3000 + const ringing = useRef(new Map()); + + const updateState = (value) => { + setState((s) => ({ ...s, ...value })) + } + + const actions = { + clear: () => { + ringing.current = new Map(); + updateState({ ringing: ringing.current }); + }, + ring: (cardId, callId, calleeToken) => { + const key = `${cardId}:${callId}` + const call = ringing.current.get(key) || { calleeToken, callId } + call.expires = Date.now() + EXPIRE; + ringing.current.set(key, call); + updateState({ ringing: ringing.current }); + }, + ignore: (cardId, callId) => { + const key = `${cardId}:${callId}` + const call = ringing.current.get(key); + if (call) { + call.status = 'ignored' + ringing.current.set(key, call); + updateState({ ringing: ringing.current }); + } + }, + decline: (cardId, callId) => { + const key = `${cardId}:${callId}` + const call = ringing.current.get(key); + if (call) { + call.status = 'declined' + ringing.current.set(key, call); + updateState({ ringing: ringing.current }); + } + }, + accept: (cardId, callId) => { + const key = `${cardId}:${callId}` + const call = ringing.current.get(key); + if (call) { + call.status = 'accepted' + ringing.current.set(key, call); + updateState({ ringing: ringing.current }); + } + }, + } + + return { state, actions } +} + + diff --git a/net/web/src/session/contact/Contact.jsx b/net/web/src/session/contact/Contact.jsx index 98dfff28..fd410c53 100644 --- a/net/web/src/session/contact/Contact.jsx +++ b/net/web/src/session/contact/Contact.jsx @@ -9,6 +9,10 @@ export function Contact({ close, guid, listing }) { const [ modal, modalContext ] = Modal.useModal(); const { state, actions } = useContact(guid, listing, close); + const ring = async () => { + actions.ring(); + }; + const updateContact = async (action) => { try { await action(); @@ -132,6 +136,9 @@ export function Contact({ close, guid, listing }) {
updateContact(actions.saveConnect)}>Save and Request
)} + +
RING
+ diff --git a/net/web/src/session/contact/useContact.hook.js b/net/web/src/session/contact/useContact.hook.js index b7b9f146..6a41e5f9 100644 --- a/net/web/src/session/contact/useContact.hook.js +++ b/net/web/src/session/contact/useContact.hook.js @@ -3,6 +3,7 @@ import { CardContext } from 'context/CardContext'; import { ViewportContext } from 'context/ViewportContext'; import { getListingMessage } from 'api/getListingMessage'; import { getCardByGuid } from 'context/cardUtil'; +import { addContactRing } from 'api/addContactRing'; export function useContact(guid, listing, close) { @@ -155,6 +156,14 @@ export function useContact(guid, listing, close) { close(); }); }, + ring: async () => { + console.log("ringing!!"); + const contact = card.state.cards.get(state.cardId); + const { node, guid } = contact.data.cardProfile; + const { token } = contact.data.cardDetail; + await addContactRing(node, `${guid}.${token}`, { index: 0, callId: 'abc', calleeToken: '123' }); + console.log(contact); + }, }; return { state, actions }; diff --git a/net/web/src/session/useSession.hook.js b/net/web/src/session/useSession.hook.js index 7587193f..b9259346 100644 --- a/net/web/src/session/useSession.hook.js +++ b/net/web/src/session/useSession.hook.js @@ -5,6 +5,7 @@ import { CardContext } from 'context/CardContext'; import { StoreContext } from 'context/StoreContext'; import { ViewportContext } from 'context/ViewportContext'; import { ProfileContext } from 'context/ProfileContext'; +import { RingContext } from 'context/RingContext'; export function useSession() { @@ -27,6 +28,7 @@ export function useSession() { const app = useContext(AppContext); const card = useContext(CardContext); const store = useContext(StoreContext); + const ring = useContext(RingContext); const viewport = useContext(ViewportContext); const profile = useContext(ProfileContext); @@ -39,6 +41,10 @@ export function useSession() { setState((s) => ({ ...s, ...value })); } + useEffect(() => { + console.log(ring.state); + }, [ring.state]); + useEffect(() => { if (!profile.state.identity?.guid) { updateState({ loading: true });