From ea8ec923fdeb18431e64752d1866f8c89d1aca14 Mon Sep 17 00:00:00 2001 From: tmgrask Date: Tue, 1 Oct 2024 14:16:29 -0400 Subject: [PATCH] render Lights so they can be faded out when a connection drops; update the mock to match module behaviour around being turned off andnot emitting a zeroed ActivityStats struct, reset data to zeros when status !== RUNNING is received --- src/components/ConduitOrbToggle.tsx | 35 +++++++++++-------- .../canvas/ConduitConnectionLight.tsx | 24 ++++++++++--- src/inproxy/context.tsx | 16 ++++++--- src/inproxy/mockModule.ts | 9 +++-- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/components/ConduitOrbToggle.tsx b/src/components/ConduitOrbToggle.tsx index f850a81..db4c989 100644 --- a/src/components/ConduitOrbToggle.tsx +++ b/src/components/ConduitOrbToggle.tsx @@ -36,7 +36,10 @@ import { z } from "zod"; import { useAnimatedImageValue } from "@/src/animationHooks"; import { timedLog } from "@/src/common/utils"; import { ConduitConnectionLight } from "@/src/components/canvas/ConduitConnectionLight"; -import { PARTICLE_VIDEO_DELAY_MS } from "@/src/constants"; +import { + INPROXY_MAX_CLIENTS_MAX, + PARTICLE_VIDEO_DELAY_MS, +} from "@/src/constants"; import { useInProxyContext } from "@/src/inproxy/context"; import { useInProxyCurrentConnectedClients, @@ -409,19 +412,23 @@ export function ConduitOrbToggle({ /> {/* 1 flying light per connected client */} - {[ - ...Array(inProxyCurrentConnectedClients).keys(), - ].map((i) => { - return ( - - ); - })} + {[...Array(INPROXY_MAX_CLIENTS_MAX).keys()].map( + (i) => { + return ( + + i + } + canvasWidth={width} + orbRadius={finalOrbRadius} + orbCenterY={orbCenterY} + psiphonLogoSize={psiphonLogoSize} + /> + ); + }, + )} {/* Turn ON text displayed when Conduit is off */} diff --git a/src/components/canvas/ConduitConnectionLight.tsx b/src/components/canvas/ConduitConnectionLight.tsx index d2724fb..f945512 100644 --- a/src/components/canvas/ConduitConnectionLight.tsx +++ b/src/components/canvas/ConduitConnectionLight.tsx @@ -24,11 +24,13 @@ import { palette } from "@/src/styles"; * up to the top of the canvas. Must be rendered within a Canvas. **/ export function ConduitConnectionLight({ + active, canvasWidth, orbRadius, orbCenterY, psiphonLogoSize, }: { + active: boolean; canvasWidth: number; orbRadius: number; orbCenterY: number; @@ -81,6 +83,9 @@ export function ConduitConnectionLight({ ); }); + // use opacity to fade out when a connection is dropped + const lightOpacity = useSharedValue(0); + function randomizeXYSpin() { "worklet"; x0.value = (Math.random() > 0.5 ? 1 : -1) * canvasWidth; @@ -93,16 +98,26 @@ export function ConduitConnectionLight({ withTiming(1, { duration: periodMs, }), - 2, + -1, true, - randomizeXYSpin, ), ); } React.useEffect(() => { - randomizeXYSpin(); - () => { + if (active) { + lfo.current.value = -1; + lightOpacity.value = withTiming(1, { duration: 1000 }); + randomizeXYSpin(); + } else { + lightOpacity.value = withTiming(0, { duration: 1000 }, () => { + cancelAnimation(lfo.current); + }); + } + }, [active]); + + React.useEffect(() => { + return () => { cancelAnimation(lfo.current); lfo.current.value = -1; }; @@ -114,6 +129,7 @@ export function ConduitConnectionLight({ c={trajectory} r={orbRadius / 10} color={lightColor} + opacity={lightOpacity} > diff --git a/src/inproxy/context.tsx b/src/inproxy/context.tsx index 571e7a2..2c1ccc9 100644 --- a/src/inproxy/context.tsx +++ b/src/inproxy/context.tsx @@ -25,7 +25,10 @@ import { ProxyState, ProxyStateSchema, } from "@/src/inproxy/types"; -import { getDefaultInProxyParameters } from "@/src/inproxy/utils"; +import { + getDefaultInProxyParameters, + getZeroedInProxyActivityStats, +} from "@/src/inproxy/utils"; const InProxyContext = React.createContext(null); @@ -116,10 +119,13 @@ export function InProxyProvider({ children }: { children: React.ReactNode }) { function handleProxyState(proxyState: ProxyState): void { timedLog(`handleProxyState: ${JSON.stringify(proxyState)}`); - queryClient.setQueryData( - ["inProxyStatus"], - InProxyStatusEnumSchema.parse(proxyState.status), - ); + const inProxyStatus = InProxyStatusEnumSchema.parse(proxyState.status); + queryClient.setQueryData(["inProxyStatus"], inProxyStatus); + // The module does not send an update for ActivityData when the InProxy + // is stopped, so reset it when we receive a non-running status. + if (inProxyStatus !== "RUNNING") { + handleInProxyActivityStats(getZeroedInProxyActivityStats()); + } // NOTE: proxyState.networkState is currently ignored } diff --git a/src/inproxy/mockModule.ts b/src/inproxy/mockModule.ts index 189df58..d1c8303 100644 --- a/src/inproxy/mockModule.ts +++ b/src/inproxy/mockModule.ts @@ -22,8 +22,8 @@ async function* generateMockData( data.dataByPeriod["1000ms"].bytesUp.shift(); data.dataByPeriod["1000ms"].bytesDown.shift(); - // 5% chance to drop a connected client - if (Math.random() > 0.95 && data.currentConnectedClients > 0) { + // 25% chance to drop a connected client + if (Math.random() > 0.75 && data.currentConnectedClients > 0) { data.currentConnectedClients--; } @@ -150,9 +150,8 @@ class ConduitModuleMock { private async stopMockData() { if (this.mockDataGenerator) { timedLog("MOCK: Stopping mock data generation"); - await this.mockDataGenerator.return( - getZeroedInProxyActivityStats(), - ); + const lastData = (await this.mockDataGenerator.next()).value; + await this.mockDataGenerator.return(lastData); } }