412 lines
13 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/services.dart';
import 'package:flutter_beacon/flutter_beacon.dart';
import 'package:get/get.dart';
import 'package:manager_api/api.dart';
import 'package:mymuseum_visitapp/Components/CustomAppBar.dart';
import 'package:mymuseum_visitapp/Components/Loading.dart';
import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart';
import 'package:mymuseum_visitapp/Helpers/networkCheck.dart';
import 'package:mymuseum_visitapp/Helpers/requirement_state_controller.dart';
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
import 'package:mymuseum_visitapp/Models/visitContext.dart';
import 'package:mymuseum_visitapp/Screens/Visit/visit.dart';
import 'package:mymuseum_visitapp/Services/apiService.dart';
import 'package:mymuseum_visitapp/Services/downloadConfiguration.dart';
import 'package:mymuseum_visitapp/app_context.dart';
import 'package:mymuseum_visitapp/client.dart';
import 'package:mymuseum_visitapp/constants.dart';
import 'package:provider/provider.dart';
import 'configurations_list.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
final controller = Get.find<RequirementStateController>();
StreamSubscription<BluetoothState>? _streamBluetooth;
int currentIndex = 0;
List<ConfigurationDTO> configurations = [];
List<String?> alreadyDownloaded = [];
VisitAppContext? visitAppContext;
StreamSubscription<RangingResult>? _streamRanging;
final _regionBeacons = <Region, List<Beacon>>{};
final _beacons = <Beacon>[];
//final controller = Get.find<RequirementStateController>();
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
listeningState();
}
listeningState() async {
print('Listening to bluetooth state');
_streamBluetooth = flutterBeacon
.bluetoothStateChanged()
.listen((BluetoothState state) async {
controller.updateBluetoothState(state);
await checkAllRequirements();
});
}
checkAllRequirements() async {
final bluetoothState = await flutterBeacon.bluetoothState;
controller.updateBluetoothState(bluetoothState);
print('BLUETOOTH $bluetoothState');
final authorizationStatus = await flutterBeacon.authorizationStatus;
controller.updateAuthorizationStatus(authorizationStatus);
print('AUTHORIZATION $authorizationStatus');
final locationServiceEnabled =
await flutterBeacon.checkLocationServicesIfEnabled;
controller.updateLocationService(locationServiceEnabled);
print('LOCATION SERVICE $locationServiceEnabled');
if (controller.bluetoothEnabled &&
controller.authorizationStatusOk &&
controller.locationServiceEnabled) {
print('STATE READY');
if (currentIndex == 0) {
print('SCANNING');
controller.startScanning();
controller.startStream.listen((flag) {
if (flag == true) {
initScanBeacon();
}
});
} else {
print('BROADCASTING');
controller.startBroadcasting();
}
} else {
print('STATE NOT READY');
controller.pauseScanning();
}
}
initScanBeacon() async {
await flutterBeacon.initializeScanning;
if (!controller.authorizationStatusOk ||
!controller.locationServiceEnabled ||
!controller.bluetoothEnabled) {
print(
'RETURNED, authorizationStatusOk=${controller.authorizationStatusOk}, '
'locationServiceEnabled=${controller.locationServiceEnabled}, '
'bluetoothEnabled=${controller.bluetoothEnabled}');
return;
}
final regions = <Region>[
Region(
identifier: 'Cubeacon',
proximityUUID: 'CB10023F-A318-3394-4199-A8730C7C1AEC',
),
Region(
identifier: 'BeaconType2',
proximityUUID: '6a84c716-0f2a-1ce9-f210-6a63bd873dd9',
),
];
if (_streamRanging != null) {
if (_streamRanging!.isPaused) {
_streamRanging?.resume();
return;
}
}
_streamRanging =
flutterBeacon.ranging(regions).listen((RangingResult result) {
print(result);
if (mounted) {
setState(() {
_regionBeacons[result.region] = result.beacons;
_beacons.clear();
_regionBeacons.values.forEach((list) {
_beacons.addAll(list);
});
_beacons.sort(_compareParameters);
});
}
});
}
pauseScanBeacon() async {
_streamRanging?.pause();
if (_beacons.isNotEmpty) {
setState(() {
_beacons.clear();
});
}
}
int _compareParameters(Beacon a, Beacon b) {
int compare = a.proximityUUID.compareTo(b.proximityUUID);
if (compare == 0) {
compare = a.major.compareTo(b.major);
}
if (compare == 0) {
compare = a.minor.compareTo(b.minor);
}
return compare;
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
print('AppLifecycleState = $state');
if (state == AppLifecycleState.resumed) {
if (_streamBluetooth != null) {
if (_streamBluetooth!.isPaused) {
_streamBluetooth?.resume();
}
}
await checkAllRequirements();
} else if (state == AppLifecycleState.paused) {
_streamBluetooth?.pause();
}
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context);
visitAppContext = appContext.getContext();
return Scaffold(
appBar: /*CustomAppBar(
title: TranslationHelper.getFromLocale("visitTitle", appContext),
isHomeButton: false,
),*/
AppBar(
title: const Text('Flutter Beacon'),
centerTitle: false,
actions: <Widget>[
Obx(() {
if (!controller.locationServiceEnabled)
return IconButton(
tooltip: 'Not Determined',
icon: Icon(Icons.portable_wifi_off),
color: Colors.grey,
onPressed: () {},
);
if (!controller.authorizationStatusOk)
return IconButton(
tooltip: 'Not Authorized',
icon: Icon(Icons.portable_wifi_off),
color: Colors.red,
onPressed: () async {
await flutterBeacon.requestAuthorization;
},
);
return IconButton(
tooltip: 'Authorized',
icon: Icon(Icons.wifi_tethering),
color: Colors.blue,
onPressed: () async {
await flutterBeacon.requestAuthorization;
},
);
}),
Obx(() {
return IconButton(
tooltip: controller.locationServiceEnabled
? 'Location Service ON'
: 'Location Service OFF',
icon: Icon(
controller.locationServiceEnabled
? Icons.location_on
: Icons.location_off,
),
color:
controller.locationServiceEnabled ? Colors.blue : Colors.red,
onPressed: controller.locationServiceEnabled
? () {}
: handleOpenLocationSettings,
);
}),
Obx(() {
final state = controller.bluetoothState.value;
if (state == BluetoothState.stateOn) {
return IconButton(
tooltip: 'Bluetooth ON',
icon: Icon(Icons.bluetooth_connected),
onPressed: () {},
color: Colors.lightBlueAccent,
);
}
if (state == BluetoothState.stateOff) {
return IconButton(
tooltip: 'Bluetooth OFF',
icon: Icon(Icons.bluetooth),
onPressed: handleOpenBluetooth,
color: Colors.red,
);
}
return IconButton(
icon: Icon(Icons.bluetooth_disabled),
tooltip: 'Bluetooth State Unknown',
onPressed: () {},
color: Colors.grey,
);
}),
],
),
body: SingleChildScrollView(
child: SizedBox(
width: size.width,
height: size.height,
child: FutureBuilder(
future: getConfigurationsCall(appContext.clientAPI, appContext),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
configurations = List<ConfigurationDTO>.from(snapshot.data).where((configuration) => configuration.isMobile!).toList();
return RefreshIndicator (
onRefresh: () {
setState(() {});
return Future(() => null);
},
color: kSecondColor,
child: ConfigurationsList(
alreadyDownloaded: alreadyDownloaded,
configurations: configurations,
requestRefresh: () {
setState(() {}); // For refresh
},
),
);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text(TranslationHelper.getFromLocale("noData", appContext));
} else {
return Center(
child: Container(
height: size.height * 0.15,
child: Loading()
)
);
}
}
),
)
),
//floatingActionButton: ScannerBouton(appContext: appContext),
//floatingActionButtonLocation: FloatingActionButtonLocation.miniCenterFloat,
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (index) {
setState(() {
currentIndex = index;
});
if (currentIndex == 0) {
controller.startScanning();
} else {
controller.pauseScanning();
controller.startBroadcasting();
}
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.list),
label: 'Scan',
),
BottomNavigationBarItem(
icon: Icon(Icons.bluetooth_audio),
label: 'Broadcast',
),
],
),
);
}
handleOpenLocationSettings() async {
if (Platform.isAndroid) {
await flutterBeacon.openLocationSettings;
} else if (Platform.isIOS) {
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Location Services Off'),
content: Text(
'Please enable Location Services on Settings > Privacy > Location Services.',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
);
},
);
}
}
handleOpenBluetooth() async {
if (Platform.isAndroid) {
try {
await flutterBeacon.openBluetoothSettings;
} on PlatformException catch (e) {
print(e);
}
} else if (Platform.isIOS) {
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Bluetooth is Off'),
content: Text('Please enable Bluetooth on Settings > Bluetooth.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
);
},
);
}
}
Future<List<ConfigurationDTO>?> getConfigurationsCall(Client client, AppContext appContext) async {
bool isOnline = await hasNetwork();
if(!isOnline) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(TranslationHelper.getFromLocale("noInternet", appContext)), backgroundColor: kBlue2),
);
VisitAppContext visitAppContext = appContext.getContext();
List<ConfigurationDTO>? configurations;
configurations = List<ConfigurationDTO>.from(await DatabaseHelper.instance.getData(DatabaseTableType.configurations));
alreadyDownloaded = configurations.map((c) => c.id).toList();
return configurations;
}
return await ApiService.getConfigurations(client, visitAppContext);
}
}