import { differenceWith, unionWith } from 'lodash' import { createEffect, createMemo, createResource, createSignal, untrack, } from 'solid-js' import { Connection, ConnectionWithSpeed } from '~/types' import { selectedEndpoint, useWsRequest } from './request' type WsMsg = { connections: Connection[] uploadTotal: number downloadTotal: number } | null // we make allconnections global so we can keep track of connections when user in proxy page // when user selects proxy and close some connections they can back and check connections // they closed const [allConnectionsWithSpeed, setAllConnectionsWithSpeed] = createSignal< ConnectionWithSpeed[] >([]) const [latestConnectionWsMessage] = createResource(async () => { await new Promise((resolve) => { createEffect(() => { if (selectedEndpoint()) { resolve() } }) }) return useWsRequest('connections') }) export const connections = createMemo(() => latestConnectionWsMessage()?.()) export const useConnections = () => { const [closedConnectionsWithSpeed, setClosedConnectionsWithSpeed] = createSignal([]) const [activeConnectionsWithSpeed, setActiveConnectionsWithSpeed] = createSignal([]) const [paused, setPaused] = createSignal(false) const updateConnectionsWithSpeed = (connections: Connection[]) => { const prevActiveConnections = activeConnectionsWithSpeed() const prevMap = new Map() prevActiveConnections.forEach((prev) => prevMap.set(prev.id, prev)) const activeConnnections: ConnectionWithSpeed[] = connections.map( (connection) => { const prevConn = prevMap.get(connection.id) if (!prevConn) { return { ...connection, downloadSpeed: 0, uploadSpeed: 0 } } return { ...connection, downloadSpeed: connection.download - (prevConn.download ?? connection.download), uploadSpeed: connection.upload - (prevConn.upload ?? connection.upload), } }, ) const allConnections = unionWith( allConnectionsWithSpeed(), activeConnnections, (a, b) => a.id === b.id, ) const closedConnections = differenceWith( allConnections, activeConnnections, (a, b) => a.id === b.id, ) return { activeConns: activeConnnections.slice(-200), closedConns: closedConnections.slice(-200), allConns: allConnections.slice(-400), } } createEffect(() => { const connection = connections()?.connections if (!connection) { return } untrack(() => { const { activeConns, closedConns, allConns } = updateConnectionsWithSpeed(connection) if (!paused()) { setActiveConnectionsWithSpeed(activeConns) setClosedConnectionsWithSpeed(closedConns) } setAllConnectionsWithSpeed(allConns) }) }) return { closedConnectionsWithSpeed, activeConnectionsWithSpeed, paused, setPaused, } }