diff --git a/packages/renderer/src/lib/api.ts b/packages/renderer/src/lib/api.ts index 4f0590b..232f90d 100644 --- a/packages/renderer/src/lib/api.ts +++ b/packages/renderer/src/lib/api.ts @@ -32,8 +32,13 @@ const connect = async () => { socket.addEventListener('message', (event) => { const {action, data} = JSON.parse(event.data); console.log('[IN]', action, data); - for(const router of routers) { - router(action, data); + const routeFound = routers + .map(router => router(action, data)) + .reduce((a, b) => a + b, 0); + if(routeFound === 0) { + console.warn(`route <${action}> not found`); + } else { + console.log(`routed to ${routeFound} elements`); } }); @@ -63,21 +68,12 @@ export async function send(action: string, data?: any) { } export function router(routes: any) { - for(const routeName in routes) { - const route = routes[routeName]; - if(typeof route === 'object') { - for(const suffix in route) { - const combinedRouteName = routeName + ':' + suffix; - routes[combinedRouteName] = route[suffix]; - } - delete routes[routeName]; - } - } return function(route: string, data: any) { if(route in routes) { routes[route](data); + return true; } else { - console.warn(`route <${route}> not found`); + return false; } }; } diff --git a/packages/renderer/src/lib/useRouter.tsx b/packages/renderer/src/lib/useRouter.tsx new file mode 100644 index 0000000..e5deed3 --- /dev/null +++ b/packages/renderer/src/lib/useRouter.tsx @@ -0,0 +1,16 @@ +import { useEffect } from 'react'; +import { registerRouter, router, send, unregisterRouter } from './api'; + +export function useAPI(actions: Function | object, deps: any[]) { + const _router = typeof actions === 'object' ? router(actions) : actions; + useEffect(() => { + registerRouter(_router); + return () => { + unregisterRouter(_router); + }; + }, deps); + + return { + send: send, + }; +} diff --git a/packages/renderer/src/pages/Channels.tsx b/packages/renderer/src/pages/Channels.tsx index 96e3fc9..d6ecbc8 100644 --- a/packages/renderer/src/pages/Channels.tsx +++ b/packages/renderer/src/pages/Channels.tsx @@ -1,20 +1,7 @@ import { useCallback, useContext, useEffect, useRef, useState } from 'react'; -import { registerRouter, router, send, unregisterRouter } from '../lib/api'; import { channelContext } from './App'; - -function useRouter(actions: Function | object, deps: any[]) { - const _router = typeof actions === 'object' ? router(actions) : actions; - useEffect(() => { - registerRouter(_router); - return () => { - unregisterRouter(_router); - }; - }, deps); - - return { - send: send, - }; -} +import { useAPI } from '../lib/useRouter'; +import type { IMessage } from './Message'; interface IChannel { uid: string; @@ -29,12 +16,19 @@ function Hashmark() { }}>#; } +interface IUnreads { + [uid: string]: number +} + export default function Channels() { const [channels, setChannels] = useState([]); const {channel, setChannel} = useContext(channelContext); - const { send } = useRouter({ + const [unreads, setUnreads] = useState({}); + + + const { send } = useAPI({ 'channels:list'(data: IChannel[]) { // console.log(data) setChannels(data); @@ -42,7 +36,18 @@ export default function Channels() { 'channel:add'(channel: IChannel) { setChannels([...channels, channel]); }, - }, [channels]); + 'message:message'(message: IMessage) { + if(channel === message.channel) return; + setUnreads({ + ...unreads, + [message.channel]: (unreads[message.channel] ?? 0) + 1, + }); + }, + }, [channels, unreads]); + + useEffect(() => { + console.log('unreads', unreads); + }, [unreads]); useEffect(() => { if(channels.length === 0) { @@ -56,6 +61,14 @@ export default function Channels() { setChannel(channels[0].uid); }, [channel, channels]); + useEffect(() => { + if(!channel) return; + setUnreads({ + ...unreads, + [channel]: 0, + }); + }, [channel]); + const textbox = useRef(null); const add = useCallback(() => { if(textbox.current === null) return; @@ -75,8 +88,20 @@ export default function Channels() { }} onClick={() => { setChannel(c.uid); }}> - {c.name} - {}}>Delete + + {(c.uid in unreads) && (unreads[c.uid] > 0) && ( + ({unreads[c.uid]}) + )} + 0 ? 'bold' : '300', + }}> + {c.name} + + {}}>Delete ))} { const textBoxRef = useRef(null); const { channel, setChannel } = useContext(channelContext); - useEffect(() => { - const actions = router({ - 'message:message'(data: IMessage) { - setMessages([...messages, data]); - }, - 'message:recent'(data: { messages: IMessage[] }) { - setMessages(data.messages); - }, - }); - registerRouter(actions); - return () => { - unregisterRouter(actions); - }; + const { send } = useAPI({ + 'message:message'(data: IMessage) { + if(data.channel !== channel) return; + + setMessages([...messages, data]); + }, + 'message:recent'(data: { messages: IMessage[] }) { + setMessages(data.messages); + }, }, [messages]); useEffect(() => { @@ -46,12 +42,18 @@ export default () => { const sendMessage = useCallback(() => { if(textBoxRef.current === null) return; if(channel === null) return; - send('message:message', createMessage('Val', textBoxRef.current.innerText, channel)); + send( + 'message:message', + createMessage( + 'Val', + textBoxRef.current.innerText, + channel, + ), + ); textBoxRef.current.innerText = ''; }, [channel]); const keyDown = useCallback((evt: any) => { - console.log(evt); if(evt.key === 'Enter') { sendMessage(); } diff --git a/packages/server/src/routers/message.ts b/packages/server/src/routers/message.ts index 35c4a3a..371b34b 100644 --- a/packages/server/src/routers/message.ts +++ b/packages/server/src/routers/message.ts @@ -25,7 +25,7 @@ export default router({ messages: messages.map(v => ({ from: v.from, uid: v.uid, - timestamp: v.t_sent * 1000, + timestamp: v.t_sent, text: v.text, })), });