Skip to content

Commit e8d2677

Browse files
Merge pull request #25 from SARDONYX-sard/feature/fix-update-connected-event
Feature/fix update connected event
2 parents bfa5bb9 + bd52b25 commit e8d2677

File tree

8 files changed

+89
-29
lines changed

8 files changed

+89
-29
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bluetooth/src/device/windows/device_info/mod.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,31 @@ impl BluetoothDeviceInfo {
108108
/// - is_connected
109109
/// - last_used
110110
/// - last_updated
111-
pub(crate) fn update_info(
112-
&mut self,
113-
is_connected: bool,
114-
) -> Result<(), BluetoothDeviceInfoError> {
111+
pub(crate) fn update_info(&mut self) -> Result<(), BluetoothDeviceInfoError> {
115112
let device = DeviceInstance::new(self.device_instance);
116113

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

120117
// NOTE: `is_connected` & `last_used` must be taken by device_search to get a decent value, so the information is merged.
121-
self.is_connected = is_connected;
122-
if is_connected {
123-
self.last_used = LocalTime::now();
124-
}
118+
let sys_device = {
119+
let mut devices = match super::device_searcher::get_bluetooth_devices() {
120+
Ok(devices) => devices,
121+
Err(err) => {
122+
tracing::error!("{err}");
123+
return Ok(());
124+
}
125+
};
126+
devices.remove(&self.address)
127+
};
128+
// NOTE: `is_connected` & `last_used` must be taken by device_search to get a decent value, so the information is merged.
129+
self.is_connected = sys_device
130+
.as_ref()
131+
.map(|device| device.is_connected)
132+
.unwrap_or_default();
133+
self.last_used = sys_device
134+
.map(|device| device.last_used)
135+
.unwrap_or_default();
125136

126137
Ok(())
127138
}

crates/bluetooth/src/device/windows/watch.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,21 @@ impl Watcher {
9797

9898
match DEVICES.get_mut(&address) {
9999
Some(mut dev) => {
100-
let map = device.Properties()?;
101-
102100
// for prop in &map {
103101
// dbg!(address);
104102
// type_to_value(prop)?;
105103
// }
106104

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

112-
match dev.value_mut().update_info(is_connected) {
114+
match dev.value_mut().update_info() {
113115
Ok(()) => update_fn(dev.value()),
114116
Err(err) => tracing::error!("{err}"),
115117
}

gui/backend/src/cmd/interval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub async fn restart_interval(app: AppHandle) {
6161
err_log!(update_tray_inner(dev_name, battery_level, dev.is_connected));
6262
};
6363

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

6666
// Replace all
6767
for (address, device) in devices {

gui/frontend/src/components/organisms/BluetoothGrid/DevicesProvider.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { NOTIFY } from '@/lib/notify';
1515
import { PRIVATE_CACHE_OBJ } from '@/lib/storage/cacheKeys';
1616
import { numberSchema } from '@/lib/zod/schema-utils';
1717
import { BluetoothDeviceInfoSchema, type Devices } from '@/services/api/bluetooth_finder';
18-
import { deviceListener } from '@/services/api/device_listener';
18+
import { deviceListener, devicesListener } from '@/services/api/device_listener';
1919

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

33-
let unlisten: (() => void) | undefined;
33+
let unlistenUpdate: (() => void) | undefined;
34+
let unlistenRestart: (() => void) | undefined;
3435

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

41+
// Update a device information
4042
useEffect(() => {
4143
NOTIFY.asyncTry(async () => {
42-
unlisten = await deviceListener({
44+
unlistenUpdate = await deviceListener({
4345
setDev: (newDevice) => {
4446
setDevices((prev) => {
4547
if (prev) {
@@ -52,8 +54,25 @@ export const DevicesProvider: FC<Props> = ({ children }) => {
5254
});
5355

5456
return () => {
55-
if (unlisten) {
56-
unlisten();
57+
if (unlistenUpdate) {
58+
unlistenUpdate();
59+
}
60+
};
61+
}, [setDevices]);
62+
63+
// Restart(Replace all devices)
64+
useEffect(() => {
65+
NOTIFY.asyncTry(async () => {
66+
unlistenRestart = await devicesListener({
67+
setDev: (newDevices) => {
68+
setDevices(newDevices);
69+
},
70+
});
71+
});
72+
73+
return () => {
74+
if (unlistenRestart) {
75+
unlistenRestart();
5776
}
5877
};
5978
}, [setDevices]);

gui/frontend/src/components/organisms/BluetoothGrid/RestartButton.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { useCallback } from 'react';
44
import { useTranslation } from '@/components/hooks/useTranslation';
55
import { LoadingButtonWithToolTip } from '@/components/molecules/LoadingButtonWithToolTip';
66
import { NOTIFY } from '@/lib/notify';
7-
import { getDevices, restartDeviceWatcher } from '@/services/api/bluetooth_finder';
8-
import { defaultTrayIcon } from '@/services/api/sys_tray';
7+
import { getDevices, restartDeviceWatcher, restartInterval } from '@/services/api/bluetooth_finder';
98

109
import { useDevicesContext } from './DevicesProvider';
1110

@@ -23,8 +22,8 @@ export function RestartButton() {
2322
(async () => {
2423
try {
2524
setLoading(true);
26-
await defaultTrayIcon();
27-
await restartDeviceWatcher();
25+
await restartInterval();
26+
await restartDeviceWatcher(); // set loading icon(by backend) & set device icon
2827
setDevices(await getDevices());
2928
setLoading(false);
3029
} catch (err) {

gui/frontend/src/services/api/device_listener.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { listen } from '@tauri-apps/api/event';
22

33
import { NOTIFY } from '@/lib/notify';
4-
import type { BluetoothDeviceInfo } from '@/services/api/bluetooth_finder';
4+
import type { BluetoothDeviceInfo, Devices } from '@/services/api/bluetooth_finder';
55

66
import type { EventCallback } from '@tauri-apps/api/event';
77
import type { JSX } from 'react/jsx-runtime';
@@ -31,3 +31,30 @@ export async function deviceListener({ setDev, error }: ListenerProps) {
3131
}
3232
}
3333
}
34+
35+
export async function devicesListener({
36+
setDev,
37+
error,
38+
}: {
39+
setDev: (devices: Devices) => void;
40+
/** @default Error */
41+
error?: string | JSX.Element;
42+
}) {
43+
let unlisten: (() => void) | null = null;
44+
const eventHandler: EventCallback<Devices> = (event) => {
45+
if (event.payload) {
46+
setDev(event.payload);
47+
}
48+
};
49+
50+
try {
51+
// Setup before run Promise(For event hook)
52+
unlisten = await listen<Devices>('bt_monitor://restart_devices', eventHandler);
53+
return unlisten;
54+
} catch (err) {
55+
NOTIFY.error(error ?? `${err}`);
56+
if (unlisten) {
57+
unlisten();
58+
}
59+
}
60+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { invoke } from '@tauri-apps/api/core';
22

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

8+
/** set Loading tray icon */
79
export async function defaultTrayIcon() {
810
await invoke('default_tray');
911
}

0 commit comments

Comments
 (0)