Skip to content

Commit fab65cc

Browse files
committed
status-bar: make visibility depend on runtime state
Change dependency on Bluetooth connection state to runtime state. This way it works for USB connection as well.
1 parent 3623f83 commit fab65cc

File tree

6 files changed

+177
-186
lines changed

6 files changed

+177
-186
lines changed

src/ble/reducers.test.ts

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22
// Copyright (c) 2021-2025 The Pybricks Authors
33

44
import { AnyAction } from 'redux';
5-
import {
6-
bleDIServiceDidReceiveFirmwareRevision,
7-
bleDIServiceDidReceivePnPId,
8-
} from '../ble-device-info-service/actions';
9-
import { PnpIdVendorIdSource } from '../ble-device-info-service/protocol';
10-
import { HubType, LegoCompanyId } from '../ble-lwp3-service/protocol';
11-
import { didReceiveStatusReport } from '../ble-pybricks-service/actions';
12-
import { Status, statusToFlag } from '../ble-pybricks-service/protocol';
135
import {
146
bleConnectPybricks,
157
bleDidConnectPybricks,
@@ -26,11 +18,6 @@ test('initial state', () => {
2618
expect(reducers(undefined, {} as AnyAction)).toMatchInlineSnapshot(`
2719
{
2820
"connection": "ble.connection.state.disconnected",
29-
"deviceBatteryCharging": false,
30-
"deviceFirmwareVersion": "",
31-
"deviceLowBatteryWarning": false,
32-
"deviceName": "",
33-
"deviceType": "",
3421
}
3522
`);
3623
});
@@ -73,87 +60,3 @@ test('connection', () => {
7360
).connection,
7461
).toBe(BleConnectionState.Connected);
7562
});
76-
77-
test('deviceName', () => {
78-
const testId = 'test-id';
79-
const testName = 'Test Name';
80-
81-
expect(
82-
reducers({ deviceName: '' } as State, bleDidConnectPybricks(testId, testName))
83-
.deviceName,
84-
).toBe(testName);
85-
86-
expect(
87-
reducers({ deviceName: testName } as State, bleDidDisconnectPybricks())
88-
.deviceName,
89-
).toBe('');
90-
});
91-
92-
test('deviceType', () => {
93-
expect(
94-
reducers(
95-
{ deviceType: '' } as State,
96-
bleDIServiceDidReceivePnPId({
97-
vendorIdSource: PnpIdVendorIdSource.BluetoothSig,
98-
vendorId: LegoCompanyId,
99-
productId: HubType.MoveHub,
100-
productVersion: 0,
101-
}),
102-
).deviceType,
103-
).toBe('Move hub');
104-
105-
expect(
106-
reducers({ deviceType: 'Move hub' } as State, bleDidDisconnectPybricks())
107-
.deviceType,
108-
).toBe('');
109-
});
110-
111-
test('deviceFirmwareVersion', () => {
112-
const testVersion = '3.0.0';
113-
114-
expect(
115-
reducers(
116-
{ deviceFirmwareVersion: '' } as State,
117-
bleDIServiceDidReceiveFirmwareRevision(testVersion),
118-
).deviceFirmwareVersion,
119-
).toBe(testVersion);
120-
121-
expect(
122-
reducers(
123-
{ deviceFirmwareVersion: testVersion } as State,
124-
bleDidDisconnectPybricks(),
125-
).deviceFirmwareVersion,
126-
).toBe('');
127-
});
128-
129-
test('deviceLowBatteryWarning', () => {
130-
expect(
131-
reducers(
132-
{ deviceLowBatteryWarning: false } as State,
133-
didReceiveStatusReport(statusToFlag(Status.BatteryLowVoltageWarning), 0, 0),
134-
).deviceLowBatteryWarning,
135-
).toBeTruthy();
136-
137-
expect(
138-
reducers(
139-
{ deviceLowBatteryWarning: true } as State,
140-
didReceiveStatusReport(
141-
~statusToFlag(Status.BatteryLowVoltageWarning),
142-
0,
143-
0,
144-
),
145-
).deviceLowBatteryWarning,
146-
).toBeFalsy();
147-
148-
expect(
149-
reducers({ deviceLowBatteryWarning: true } as State, bleDidDisconnectPybricks())
150-
.deviceLowBatteryWarning,
151-
).toBeFalsy();
152-
});
153-
154-
test('deviceBatteryCharging', () => {
155-
expect(
156-
reducers({ deviceBatteryCharging: true } as State, bleDidDisconnectPybricks())
157-
.deviceBatteryCharging,
158-
).toBeFalsy();
159-
});

src/ble/reducers.ts

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2020-2022 The Pybricks Authors
2+
// Copyright (c) 2020-2025 The Pybricks Authors
33
//
44
// Manages state for the Bluetooth Low Energy connection.
55
// This assumes that there is only one global connection to a single device.
66

77
import { Reducer, combineReducers } from 'redux';
8-
import {
9-
bleDIServiceDidReceiveFirmwareRevision,
10-
bleDIServiceDidReceivePnPId,
11-
} from '../ble-device-info-service/actions';
12-
import { getHubTypeName } from '../ble-device-info-service/protocol';
13-
import { didReceiveStatusReport } from '../ble-pybricks-service/actions';
14-
import { Status, statusToFlag } from '../ble-pybricks-service/protocol';
158
import {
169
bleConnectPybricks,
1710
bleDidConnectPybricks,
@@ -72,71 +65,6 @@ const connection: Reducer<BleConnectionState> = (
7265
return state;
7366
};
7467

75-
const deviceName: Reducer<string> = (state = '', action) => {
76-
if (bleDidDisconnectPybricks.matches(action)) {
77-
return '';
78-
}
79-
80-
if (bleDidConnectPybricks.matches(action)) {
81-
return action.name;
82-
}
83-
84-
return state;
85-
};
86-
87-
const deviceType: Reducer<string> = (state = '', action) => {
88-
if (bleDidDisconnectPybricks.matches(action)) {
89-
return '';
90-
}
91-
92-
if (bleDIServiceDidReceivePnPId.matches(action)) {
93-
return getHubTypeName(action.pnpId);
94-
}
95-
96-
return state;
97-
};
98-
99-
const deviceFirmwareVersion: Reducer<string> = (state = '', action) => {
100-
if (bleDidDisconnectPybricks.matches(action)) {
101-
return '';
102-
}
103-
104-
if (bleDIServiceDidReceiveFirmwareRevision.matches(action)) {
105-
return action.version;
106-
}
107-
108-
return state;
109-
};
110-
111-
const deviceLowBatteryWarning: Reducer<boolean> = (state = false, action) => {
112-
if (bleDidDisconnectPybricks.matches(action)) {
113-
return false;
114-
}
115-
116-
if (didReceiveStatusReport.matches(action)) {
117-
return Boolean(
118-
action.statusFlags & statusToFlag(Status.BatteryLowVoltageWarning),
119-
);
120-
}
121-
122-
return state;
123-
};
124-
125-
const deviceBatteryCharging: Reducer<boolean> = (state = false, action) => {
126-
if (bleDidDisconnectPybricks.matches(action)) {
127-
return false;
128-
}
129-
130-
// TODO: hub does not currently have a status flag for this
131-
132-
return state;
133-
};
134-
13568
export default combineReducers({
13669
connection,
137-
deviceName,
138-
deviceType,
139-
deviceFirmwareVersion,
140-
deviceLowBatteryWarning,
141-
deviceBatteryCharging,
14270
});

src/hub/reducers.test.ts

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ import {
77
bleDidDisconnectPybricks,
88
bleDisconnectPybricks,
99
} from '../ble/actions';
10-
import { bleDIServiceDidReceiveSoftwareRevision } from '../ble-device-info-service/actions';
11-
import { PnpId } from '../ble-device-info-service/protocol';
12-
import { HubType } from '../ble-lwp3-service/protocol';
10+
import {
11+
bleDIServiceDidReceiveFirmwareRevision,
12+
bleDIServiceDidReceivePnPId,
13+
bleDIServiceDidReceiveSoftwareRevision,
14+
} from '../ble-device-info-service/actions';
15+
import { PnpId, PnpIdVendorIdSource } from '../ble-device-info-service/protocol';
16+
import { HubType, LegoCompanyId } from '../ble-lwp3-service/protocol';
1317
import {
1418
blePybricksServiceDidNotReceiveHubCapabilities,
1519
blePybricksServiceDidReceiveHubCapabilities,
@@ -40,6 +44,11 @@ type State = ReturnType<typeof reducers>;
4044
test('initial state', () => {
4145
expect(reducers(undefined, {} as AnyAction)).toMatchInlineSnapshot(`
4246
{
47+
"deviceBatteryCharging": false,
48+
"deviceFirmwareVersion": "",
49+
"deviceLowBatteryWarning": false,
50+
"deviceName": "",
51+
"deviceType": "",
4352
"downloadProgress": null,
4453
"hasRepl": false,
4554
"maxBleWriteSize": 0,
@@ -298,6 +307,90 @@ describe('runtime', () => {
298307
});
299308
});
300309

310+
test('deviceName', () => {
311+
const testId = 'test-id';
312+
const testName = 'Test Name';
313+
314+
expect(
315+
reducers({ deviceName: '' } as State, bleDidConnectPybricks(testId, testName))
316+
.deviceName,
317+
).toBe(testName);
318+
319+
expect(
320+
reducers({ deviceName: testName } as State, bleDidDisconnectPybricks())
321+
.deviceName,
322+
).toBe('');
323+
});
324+
325+
test('deviceType', () => {
326+
expect(
327+
reducers(
328+
{ deviceType: '' } as State,
329+
bleDIServiceDidReceivePnPId({
330+
vendorIdSource: PnpIdVendorIdSource.BluetoothSig,
331+
vendorId: LegoCompanyId,
332+
productId: HubType.MoveHub,
333+
productVersion: 0,
334+
}),
335+
).deviceType,
336+
).toBe('Move hub');
337+
338+
expect(
339+
reducers({ deviceType: 'Move hub' } as State, bleDidDisconnectPybricks())
340+
.deviceType,
341+
).toBe('');
342+
});
343+
344+
test('deviceFirmwareVersion', () => {
345+
const testVersion = '3.0.0';
346+
347+
expect(
348+
reducers(
349+
{ deviceFirmwareVersion: '' } as State,
350+
bleDIServiceDidReceiveFirmwareRevision(testVersion),
351+
).deviceFirmwareVersion,
352+
).toBe(testVersion);
353+
354+
expect(
355+
reducers(
356+
{ deviceFirmwareVersion: testVersion } as State,
357+
bleDidDisconnectPybricks(),
358+
).deviceFirmwareVersion,
359+
).toBe('');
360+
});
361+
362+
test('deviceLowBatteryWarning', () => {
363+
expect(
364+
reducers(
365+
{ deviceLowBatteryWarning: false } as State,
366+
didReceiveStatusReport(statusToFlag(Status.BatteryLowVoltageWarning), 0, 0),
367+
).deviceLowBatteryWarning,
368+
).toBeTruthy();
369+
370+
expect(
371+
reducers(
372+
{ deviceLowBatteryWarning: true } as State,
373+
didReceiveStatusReport(
374+
~statusToFlag(Status.BatteryLowVoltageWarning),
375+
0,
376+
0,
377+
),
378+
).deviceLowBatteryWarning,
379+
).toBeFalsy();
380+
381+
expect(
382+
reducers({ deviceLowBatteryWarning: true } as State, bleDidDisconnectPybricks())
383+
.deviceLowBatteryWarning,
384+
).toBeFalsy();
385+
});
386+
387+
test('deviceBatteryCharging', () => {
388+
expect(
389+
reducers({ deviceBatteryCharging: true } as State, bleDidDisconnectPybricks())
390+
.deviceBatteryCharging,
391+
).toBeFalsy();
392+
});
393+
301394
describe('maxBleWriteSize', () => {
302395
test.each([100, 1000])('Pybricks Profile >= v1.2.0: %s', (size) => {
303396
expect(

0 commit comments

Comments
 (0)