Skip to content

Commit

Permalink
Merge pull request #25 from SARDONYX-sard/feature/fix-update-connecte…
Browse files Browse the repository at this point in the history
…d-event

Feature/fix update connected event
  • Loading branch information
SARDONYX-sard authored Jan 21, 2025
2 parents bfa5bb9 + bd52b25 commit e8d2677
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 29 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 19 additions & 8 deletions crates/bluetooth/src/device/windows/device_info/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,31 @@ impl BluetoothDeviceInfo {
/// - is_connected
/// - last_used
/// - last_updated
pub(crate) fn update_info(
&mut self,
is_connected: bool,
) -> Result<(), BluetoothDeviceInfoError> {
pub(crate) fn update_info(&mut self) -> Result<(), BluetoothDeviceInfoError> {
let device = DeviceInstance::new(self.device_instance);

self.battery_level = device.get_device_property(&DEVPKEY_Bluetooth_Battery)?;
self.last_updated = LocalTime::now();

// NOTE: `is_connected` & `last_used` must be taken by device_search to get a decent value, so the information is merged.
self.is_connected = is_connected;
if is_connected {
self.last_used = LocalTime::now();
}
let sys_device = {
let mut devices = match super::device_searcher::get_bluetooth_devices() {
Ok(devices) => devices,
Err(err) => {
tracing::error!("{err}");
return Ok(());
}
};
devices.remove(&self.address)
};
// NOTE: `is_connected` & `last_used` must be taken by device_search to get a decent value, so the information is merged.
self.is_connected = sys_device
.as_ref()
.map(|device| device.is_connected)
.unwrap_or_default();
self.last_used = sys_device
.map(|device| device.last_used)
.unwrap_or_default();

Ok(())
}
Expand Down
16 changes: 9 additions & 7 deletions crates/bluetooth/src/device/windows/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,21 @@ impl Watcher {

match DEVICES.get_mut(&address) {
Some(mut dev) => {
let map = device.Properties()?;

// for prop in &map {
// dbg!(address);
// type_to_value(prop)?;
// }

// In my tests, the only properties selected by kind that exist are the ones the device was able to get via pnp.
// Therefore, any device that exists in DashMap should be able to retrieve it.
let is_connected =
map.HasKey(&HSTRING::from(IS_CONNECTED)).unwrap_or_default();
// Not use this pattern
// ```
// let map = device.Properties()?;
// let is_connected = map.HasKey(&HSTRING::from(IS_CONNECTED)).unwrap_or_default();
// ```
// Why?
// There were times when the information from props was unreliable.
// The information is obtained when connected, but for some reason this value may not be obtained when not connected.

match dev.value_mut().update_info(is_connected) {
match dev.value_mut().update_info() {
Ok(()) => update_fn(dev.value()),
Err(err) => tracing::error!("{err}"),
}
Expand Down
2 changes: 1 addition & 1 deletion gui/backend/src/cmd/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub async fn restart_interval(app: AppHandle) {
err_log!(update_tray_inner(dev_name, battery_level, dev.is_connected));
};

err_log!(window.emit("bt_monitor://update_devices", &devices));
err_log!(window.emit("bt_monitor://restart_devices", &devices));

// Replace all
for (address, device) in devices {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { NOTIFY } from '@/lib/notify';
import { PRIVATE_CACHE_OBJ } from '@/lib/storage/cacheKeys';
import { numberSchema } from '@/lib/zod/schema-utils';
import { BluetoothDeviceInfoSchema, type Devices } from '@/services/api/bluetooth_finder';
import { deviceListener } from '@/services/api/device_listener';
import { deviceListener, devicesListener } from '@/services/api/device_listener';

type ContextType = {
devices: Devices | undefined;
Expand All @@ -30,16 +30,18 @@ export const OptBluetoothDeviceInfoSchema = z
.union([z.record(numberSchema, BluetoothDeviceInfoSchema), z.undefined()])
.catch(undefined);

let unlisten: (() => void) | undefined;
let unlistenUpdate: (() => void) | undefined;
let unlistenRestart: (() => void) | undefined;

type Props = { children: ReactNode };
export const DevicesProvider: FC<Props> = ({ children }) => {
const [devices, setDevices] = useStorageState(PRIVATE_CACHE_OBJ.devices, OptBluetoothDeviceInfoSchema);
const [loading, setLoading] = useState<boolean>(false);

// Update a device information
useEffect(() => {
NOTIFY.asyncTry(async () => {
unlisten = await deviceListener({
unlistenUpdate = await deviceListener({
setDev: (newDevice) => {
setDevices((prev) => {
if (prev) {
Expand All @@ -52,8 +54,25 @@ export const DevicesProvider: FC<Props> = ({ children }) => {
});

return () => {
if (unlisten) {
unlisten();
if (unlistenUpdate) {
unlistenUpdate();
}
};
}, [setDevices]);

// Restart(Replace all devices)
useEffect(() => {
NOTIFY.asyncTry(async () => {
unlistenRestart = await devicesListener({
setDev: (newDevices) => {
setDevices(newDevices);
},
});
});

return () => {
if (unlistenRestart) {
unlistenRestart();
}
};
}, [setDevices]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { useCallback } from 'react';
import { useTranslation } from '@/components/hooks/useTranslation';
import { LoadingButtonWithToolTip } from '@/components/molecules/LoadingButtonWithToolTip';
import { NOTIFY } from '@/lib/notify';
import { getDevices, restartDeviceWatcher } from '@/services/api/bluetooth_finder';
import { defaultTrayIcon } from '@/services/api/sys_tray';
import { getDevices, restartDeviceWatcher, restartInterval } from '@/services/api/bluetooth_finder';

import { useDevicesContext } from './DevicesProvider';

Expand All @@ -23,8 +22,8 @@ export function RestartButton() {
(async () => {
try {
setLoading(true);
await defaultTrayIcon();
await restartDeviceWatcher();
await restartInterval();
await restartDeviceWatcher(); // set loading icon(by backend) & set device icon
setDevices(await getDevices());
setLoading(false);
} catch (err) {
Expand Down
29 changes: 28 additions & 1 deletion gui/frontend/src/services/api/device_listener.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { listen } from '@tauri-apps/api/event';

import { NOTIFY } from '@/lib/notify';
import type { BluetoothDeviceInfo } from '@/services/api/bluetooth_finder';
import type { BluetoothDeviceInfo, Devices } from '@/services/api/bluetooth_finder';

import type { EventCallback } from '@tauri-apps/api/event';
import type { JSX } from 'react/jsx-runtime';
Expand Down Expand Up @@ -31,3 +31,30 @@ export async function deviceListener({ setDev, error }: ListenerProps) {
}
}
}

export async function devicesListener({
setDev,
error,
}: {
setDev: (devices: Devices) => void;
/** @default Error */
error?: string | JSX.Element;
}) {
let unlisten: (() => void) | null = null;
const eventHandler: EventCallback<Devices> = (event) => {
if (event.payload) {
setDev(event.payload);
}
};

try {
// Setup before run Promise(For event hook)
unlisten = await listen<Devices>('bt_monitor://restart_devices', eventHandler);
return unlisten;
} catch (err) {
NOTIFY.error(error ?? `${err}`);
if (unlisten) {
unlisten();
}
}
}
2 changes: 2 additions & 0 deletions gui/frontend/src/services/api/sys_tray.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { invoke } from '@tauri-apps/api/core';

/** set device info icon */
export async function updateTrayIcon(deviceName: string, batteryLevel: number, isConnected: boolean) {
await invoke('update_tray', { deviceName, batteryLevel, isConnected });
}

/** set Loading tray icon */
export async function defaultTrayIcon() {
await invoke('default_tray');
}

0 comments on commit e8d2677

Please sign in to comment.