- Add real-time chat between customers and staff via WebSocket - Add HTTP polling fallback when WebSocket unavailable - Chat auto-closes when worker ends conversation with dialog notification - Add user search API for group order invites (phone/email/name) - Store group order invites in app state - Add login check before starting chat with sign-in prompt - Remove table change button (not allowed currently) - Fix About screen to show dynamic version from pubspec - Update snackbar styling to green with black text Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
150 lines
5.7 KiB
Dart
150 lines
5.7 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
import 'package:dchs_flutter_beacon/dchs_flutter_beacon.dart';
|
|
|
|
class BeaconPermissions {
|
|
static Future<bool> requestPermissions() async {
|
|
try {
|
|
// Request location permission (required for Bluetooth scanning)
|
|
final locationStatus = await Permission.locationWhenInUse.request();
|
|
debugPrint('[BeaconPermissions] Location: $locationStatus');
|
|
|
|
bool bluetoothGranted = true;
|
|
|
|
if (Platform.isIOS) {
|
|
// iOS uses a single Bluetooth permission
|
|
final bluetoothStatus = await Permission.bluetooth.request();
|
|
debugPrint('[BeaconPermissions] Bluetooth (iOS): $bluetoothStatus');
|
|
bluetoothGranted = bluetoothStatus.isGranted;
|
|
} else {
|
|
// Android 12+ requires separate scan/connect permissions
|
|
final bluetoothScan = await Permission.bluetoothScan.request();
|
|
final bluetoothConnect = await Permission.bluetoothConnect.request();
|
|
debugPrint('[BeaconPermissions] BluetoothScan: $bluetoothScan, BluetoothConnect: $bluetoothConnect');
|
|
bluetoothGranted = bluetoothScan.isGranted && bluetoothConnect.isGranted;
|
|
}
|
|
|
|
final allGranted = locationStatus.isGranted && bluetoothGranted;
|
|
|
|
if (allGranted) {
|
|
debugPrint('[BeaconPermissions] ✅ All permissions granted');
|
|
} else {
|
|
debugPrint('[BeaconPermissions] ❌ Permissions denied');
|
|
}
|
|
|
|
return allGranted;
|
|
} catch (e) {
|
|
debugPrint('[BeaconPermissions] Error requesting permissions: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Check if Bluetooth is enabled - returns current state without prompting
|
|
static Future<bool> isBluetoothEnabled() async {
|
|
try {
|
|
final bluetoothState = await flutterBeacon.bluetoothState;
|
|
return bluetoothState == BluetoothState.stateOn;
|
|
} catch (e) {
|
|
debugPrint('[BeaconPermissions] Error checking Bluetooth state: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Request to enable Bluetooth via system prompt (Android only)
|
|
static Future<bool> requestEnableBluetooth() async {
|
|
try {
|
|
debugPrint('[BeaconPermissions] 📶 Requesting Bluetooth enable...');
|
|
// This opens a system dialog on Android asking user to turn on Bluetooth
|
|
final result = await flutterBeacon.requestAuthorization;
|
|
debugPrint('[BeaconPermissions] Request authorization result: $result');
|
|
return result;
|
|
} catch (e) {
|
|
debugPrint('[BeaconPermissions] Error requesting Bluetooth enable: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Open Bluetooth settings
|
|
static Future<bool> openBluetoothSettings() async {
|
|
try {
|
|
debugPrint('[BeaconPermissions] Opening Bluetooth settings...');
|
|
final opened = await flutterBeacon.openBluetoothSettings;
|
|
debugPrint('[BeaconPermissions] Open Bluetooth settings result: $opened');
|
|
return opened;
|
|
} catch (e) {
|
|
debugPrint('[BeaconPermissions] Error opening Bluetooth settings: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Check if Bluetooth is enabled, and try to enable it if not
|
|
static Future<bool> ensureBluetoothEnabled() async {
|
|
try {
|
|
// Check current Bluetooth state
|
|
final bluetoothState = await flutterBeacon.bluetoothState;
|
|
debugPrint('[BeaconPermissions] 📶 Bluetooth state: $bluetoothState');
|
|
|
|
if (bluetoothState == BluetoothState.stateOn) {
|
|
debugPrint('[BeaconPermissions] ✅ Bluetooth is ON');
|
|
return true;
|
|
}
|
|
|
|
// Request to enable Bluetooth via system prompt
|
|
debugPrint('[BeaconPermissions] ⚠️ Bluetooth is OFF, requesting enable...');
|
|
await requestEnableBluetooth();
|
|
|
|
// Poll for Bluetooth state change - short wait first
|
|
for (int i = 0; i < 6; i++) {
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
final newState = await flutterBeacon.bluetoothState;
|
|
debugPrint('[BeaconPermissions] 📶 Polling Bluetooth state ($i): $newState');
|
|
if (newState == BluetoothState.stateOn) {
|
|
debugPrint('[BeaconPermissions] ✅ Bluetooth is now ON');
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// If still off after 3 seconds, try opening Bluetooth settings directly
|
|
debugPrint('[BeaconPermissions] ⚠️ Bluetooth still OFF, opening settings...');
|
|
await openBluetoothSettings();
|
|
|
|
// Poll again for up to 15 seconds (user needs time to toggle in settings)
|
|
for (int i = 0; i < 30; i++) {
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
final newState = await flutterBeacon.bluetoothState;
|
|
debugPrint('[BeaconPermissions] 📶 Polling Bluetooth state after settings ($i): $newState');
|
|
if (newState == BluetoothState.stateOn) {
|
|
debugPrint('[BeaconPermissions] ✅ Bluetooth is now ON');
|
|
return true;
|
|
}
|
|
}
|
|
|
|
debugPrint('[BeaconPermissions] ❌ Bluetooth still OFF after waiting');
|
|
return false;
|
|
} catch (e) {
|
|
debugPrint('[BeaconPermissions] Error checking Bluetooth state: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static Future<bool> checkPermissions() async {
|
|
final locationStatus = await Permission.locationWhenInUse.status;
|
|
|
|
bool bluetoothGranted = true;
|
|
if (Platform.isIOS) {
|
|
final bluetoothStatus = await Permission.bluetooth.status;
|
|
bluetoothGranted = bluetoothStatus.isGranted;
|
|
} else {
|
|
final bluetoothScan = await Permission.bluetoothScan.status;
|
|
final bluetoothConnect = await Permission.bluetoothConnect.status;
|
|
bluetoothGranted = bluetoothScan.isGranted && bluetoothConnect.isGranted;
|
|
}
|
|
|
|
return locationStatus.isGranted && bluetoothGranted;
|
|
}
|
|
|
|
static Future<void> openSettings() async {
|
|
await openAppSettings();
|
|
}
|
|
}
|