From 3ca730a82b1090684e9da8310990c30a26724acb Mon Sep 17 00:00:00 2001 From: Vixalie Date: Thu, 27 Feb 2025 22:19:25 +0800 Subject: [PATCH] refactor state refresh. --- src/context/EstimContext.tsx | 179 +++++++++++++++++++++++++++-------- 1 file changed, 137 insertions(+), 42 deletions(-) diff --git a/src/context/EstimContext.tsx b/src/context/EstimContext.tsx index ef84a4d..b1417db 100644 --- a/src/context/EstimContext.tsx +++ b/src/context/EstimContext.tsx @@ -1,9 +1,9 @@ import { invoke } from '@tauri-apps/api/core'; -import { Event, listen, UnlistenFn } from '@tauri-apps/api/event'; +import { listen, UnlistenFn } from '@tauri-apps/api/event'; import { message } from '@tauri-apps/plugin-dialog'; import { atom, PrimitiveAtom, useSetAtom } from 'jotai'; -import { atomFamily } from 'jotai/utils'; -import { FC, ReactNode, useCallback, useEffect, useRef } from 'react'; +import { atomFamily, atomWithRefresh } from 'jotai/utils'; +import { FC, ReactNode, useEffect, useRef } from 'react'; export type Channels = 'a' | 'b'; type ChannelState = { @@ -15,7 +15,19 @@ type ChannelState = { boostLevel: number; maxBoostLevel: number; }; +type PeripheralItem = { + id: string; + address: string; + represent: string; + isConnected: boolean; + rssi: number | null; + battery: number | null; +}; type DeviceState = { + id: string | null; + address: string | null; + represent: string | null; + isConnected: boolean | null; rssi: number | null; battery: number | null; }; @@ -25,57 +37,136 @@ type BluetoothState = { connected: string | null; }; -export const BleState = atom({ - ready: null, - searching: null, - connected: null, +export const BleState = atomWithRefresh(async (get) => { + try { + const state = await invoke('central_device_state'); + return { + ready: state.isReady, + searching: state.isScanning, + connected: state.connected, + }; + } catch (e) { + console.error('[refresh central]', e); + } + return { + ready: null, + searching: null, + connected: null, + }; }); -export const DeviceState = atom({ - rssi: null, - battery: null, +export const DeviceState = atomWithRefresh(async (get) => { + try { + const state = await invoke('connected_peripheral_state'); + return { + id: state?.id, + address: state?.address, + represent: state?.represent, + isConnected: state?.isConnected, + rssi: state?.rssi, + battery: state?.battery, + }; + } catch (e) { + console.error('[refresh connected]', e); + } + return { + id: null, + address: null, + represent: null, + isConnected: null, + rssi: null, + battery: null, + }; +}); +export const FoundPeripherals = atomWithRefresh(async (get) => { + try { + const peripherals = await invoke('found_peripherals'); + return peripherals.map((peripheral: PeripheralItem) => ({ + id: peripheral.id, + address: peripheral.address, + represent: peripheral.represent, + isConnected: peripheral.isConnected, + rssi: peripheral.rssi, + battery: peripheral.battery, + })); + } catch (e) { + console.error('[refresh found]', e); + } + return []; }); const Channels: Record> = { - a: atom({ - playing: false, - playMode: 'repeat-one', - strength: 0, - maxStrength: 100, - boosting: false, - boostLevel: 0, - maxBoostLevel: 100, + a: atomWithRefresh(async (get) => { + try { + const state = await invoke('channel_a_state'); + return { + playing: state.isPlaying, + playMode: state.playMode, + strength: state.strength, + maxStrength: state.maxStrength, + boosting: state.isBoosting, + boostLevel: state.boostLevel, + maxBoostLevel: state.maxBoostLevel, + }; + } catch (e) { + console.error('[refresh channel a]', e); + } + return { + playing: false, + playMode: 'repeat-one', + strength: 0, + maxStrength: 100, + boosting: false, + boostLevel: 0, + maxBoostLevel: 100, + }; }), - b: atom({ - playing: false, - playMode: 'repeat-one', - strength: 0, - maxStrength: 100, - boosting: false, - boostLevel: 0, - maxBoostLevel: 100, + b: atom(async (get) => { + try { + const state = await invoke('channel_b_state'); + return { + playing: state.isPlaying, + playMode: state.playMode, + strength: state.strength, + maxStrength: state.maxStrength, + boosting: state.isBoosting, + boostLevel: state.boostLevel, + maxBoostLevel: state.maxBoostLevel, + }; + } catch (e) { + console.error('[refresh channel b]', e); + } + return { + playing: false, + playMode: 'repeat-one', + strength: 0, + maxStrength: 100, + boosting: false, + boostLevel: 0, + maxBoostLevel: 100, + }; }), }; export const ChannelState = atomFamily((channel: Channels) => Channels[channel]); const EstimWatchProvider: FC<{ children?: ReactNode }> = ({ children }) => { - const unlisten = useRef(null); - const setBleState = useSetAtom(BleState); - const handleAppStateRefresh = useCallback(async (event: Event) => { - try { - const newState = await invoke('refresh_application_state'); - setBleState({ - ready: newState.central.is_ready, - searching: newState.central.is_scanning, - connected: newState.central.connected, - }); - } catch (e) { - console.error('[Answer refresh state]', e); - } - }, []); + const unlistenBle = useRef(null); + const unlistenDevice = useRef(null); + const unlistenPreipherals = useRef(null); + const unlistenChannelA = useRef(null); + const unlistenChannelB = useRef(null); + const refreshBle = useSetAtom(BleState); + const refreshDevice = useSetAtom(DeviceState); + const refreshPeripherals = useSetAtom(FoundPeripherals); + const refreshChannelA = useSetAtom(ChannelState('a')); + const refreshChannelB = useSetAtom(ChannelState('b')); useEffect(() => { (async function () { try { - unlisten.current = await listen('app_state_updated', handleAppStateRefresh); + unlistenBle.current = await listen('central_state_updated', () => refreshBle()); + unlistenDevice.current = await listen('peripheral_connected', () => refreshDevice()); + unlistenPreipherals.current = await listen('peripherals_found', () => refreshPeripherals()); + unlistenChannelA.current = await listen('channel_a_updated', () => refreshChannelA()); + unlistenChannelB.current = await listen('channel_b_updated', () => refreshChannelB()); await invoke('activate_central_adapter'); } catch (e) { console.error('[Activate Adapter]', e); @@ -87,7 +178,11 @@ const EstimWatchProvider: FC<{ children?: ReactNode }> = ({ children }) => { })(); return () => { - unlisten.current?.(); + unlistenBle.current?.(); + unlistenDevice.current?.(); + unlistenPreipherals.current?.(); + unlistenChannelA.current?.(); + unlistenChannelB.current?.(); }; }, []); return <>{children};