Skip to content

Commit 51b439b

Browse files
committed
feat: Add blePermissionList method to DeviceDiscoveryViewModel for platform-specific BLE permissions
1 parent fa40352 commit 51b439b

2 files changed

Lines changed: 46 additions & 5 deletions

File tree

client/lib/features/devices/view_models/device_discovery_view_model.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,31 @@ class DeviceDiscoveryViewModel extends AbstractScreenViewModel {
202202
/// public so that tests can supply a fake implementation.
203203
Future<bool> Function()? requestBlePermissions;
204204

205+
@visibleForTesting
206+
List<Permission> blePermissionList() {
207+
// iOS only has a single Bluetooth permission; Android requires location +
208+
// separate scan/connect permissions. The list is kept in a method so tests
209+
// can verify the behaviour without mocking the plugin itself.
210+
if (_platformService.isIOS) {
211+
return [
212+
Permission.bluetooth,
213+
// location may also be required when scanning on iOS
214+
Permission.locationWhenInUse,
215+
];
216+
} else {
217+
return [Permission.locationWhenInUse, Permission.bluetoothScan, Permission.bluetoothConnect];
218+
}
219+
}
220+
205221
Future<bool> _ensureBlePermissions() async {
206222
// allow injection for tests
207223
if (requestBlePermissions != null) {
208224
return await requestBlePermissions!();
209225
}
210226

211-
final statuses = await [
212-
Permission.locationWhenInUse,
213-
Permission.bluetoothScan,
214-
Permission.bluetoothConnect,
215-
].request();
227+
final permissions = blePermissionList();
228+
final statuses = await permissions.request();
229+
_logger.d('BLE permission statuses: $statuses');
216230

217231
// if any permission is not granted, treat as failure
218232
for (var status in statuses.values) {

client/test/view_models/device_discovery_view_model_test.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:flutter/services.dart';
88
import 'package:event_bus/event_bus.dart';
99
import 'package:logger/logger.dart';
1010
import 'package:sembast/sembast.dart';
11+
import 'package:permission_handler/permission_handler.dart';
1112

1213
import 'package:borneo_app/features/devices/view_models/device_discovery_view_model.dart';
1314
import 'package:borneo_app/core/services/devices/device_manager.dart';
@@ -227,6 +228,32 @@ void main() {
227228
);
228229
}
229230

231+
test('blePermissionList returns Android permissions on Android', () {
232+
vm = makeVm(mobile: true);
233+
final perms = vm.blePermissionList();
234+
expect(perms, containsAll([Permission.locationWhenInUse, Permission.bluetoothScan, Permission.bluetoothConnect]));
235+
expect(perms.length, 3);
236+
});
237+
238+
test('blePermissionList returns iOS permissions on iOS', () {
239+
// manual iOS platform service, bypassing makeVm helper
240+
bleProv = FakeBleProvisioner();
241+
vm = DeviceDiscoveryViewModel(
242+
Logger(),
243+
FakeDeviceManager(),
244+
bleProv,
245+
FakeDeviceModuleRegistry(),
246+
FakePlatformService(isIOS: true),
247+
globalEventBus: EventBus(),
248+
gt: FakeGettext(),
249+
logger: Logger(),
250+
requestBlePermissions: () async => true,
251+
);
252+
final perms = vm.blePermissionList();
253+
expect(perms, containsAll([Permission.bluetooth, Permission.locationWhenInUse]));
254+
expect(perms.length, 2);
255+
});
256+
230257
test('startDiscovery does not call BLE scan when permissions denied', () async {
231258
vm = makeVm(mobile: true, permissions: () async => false);
232259
expect(bleProv.scanCalled, isFalse);

0 commit comments

Comments
 (0)