feat(example_full, lib, android): optimisation improving, current device data
This commit is contained in:
@@ -97,8 +97,9 @@ class NearbyServiceManager(private var context: Context) {
|
|||||||
}
|
}
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
if (!permissionsHandler.checkPermissions()) {
|
if (!permissionsHandler.checkPermissions()) {
|
||||||
Logger.e("No permission to call 'discover'")
|
Logger.e("No permission to call 'getCurrentDevice'")
|
||||||
permissionsHandler.requestPermissions()
|
permissionsHandler.requestPermissions()
|
||||||
|
result.success(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ android {
|
|||||||
applicationId "com.example.nearby_service_example_full"
|
applicationId "com.example.nearby_service_example_full"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion 24
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
|
||||||
|
android:usesPermissionFlags="neverForLocation" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
<application
|
<application
|
||||||
android:label="nearby_service_example_full"
|
android:label="nearby_service_example_full"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ class AppService extends ChangeNotifier {
|
|||||||
await _nearbyService.initialize(
|
await _nearbyService.initialize(
|
||||||
data: NearbyInitializeData(iosDeviceName: iosDeviceName),
|
data: NearbyInitializeData(iosDeviceName: iosDeviceName),
|
||||||
);
|
);
|
||||||
await getCurrentDeviceInfo();
|
|
||||||
updateState(
|
updateState(
|
||||||
Platform.isAndroid ? AppState.permissions : AppState.selectClientType,
|
Platform.isAndroid ? AppState.permissions : AppState.selectClientType,
|
||||||
);
|
);
|
||||||
@@ -86,6 +85,7 @@ class AppService extends ChangeNotifier {
|
|||||||
if (result ?? false) {
|
if (result ?? false) {
|
||||||
updateState(AppState.readyToDiscover);
|
updateState(AppState.readyToDiscover);
|
||||||
startListeningConnectionInfo();
|
startListeningConnectionInfo();
|
||||||
|
await getCurrentDeviceInfo();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -37,46 +37,60 @@ class App extends StatelessWidget {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Consumer<AppService>(builder: (context, service, _) {
|
body: const _AppBody(),
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(16, 12, 16, 10),
|
|
||||||
child: InfoPanel(),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: MediaQuery.removePadding(
|
|
||||||
context: context,
|
|
||||||
removeLeft: true,
|
|
||||||
child: Stepper(
|
|
||||||
controlsBuilder: (context, _) => const SizedBox.shrink(),
|
|
||||||
currentStep: service.state.step,
|
|
||||||
steps: [
|
|
||||||
...AppState.steps.map((e) {
|
|
||||||
final builder = AppStepViewBuilder(state: e);
|
|
||||||
final isActive = e == service.state;
|
|
||||||
return Step(
|
|
||||||
state: isActive
|
|
||||||
? StepState.indexed
|
|
||||||
: e.step < service.state.step
|
|
||||||
? StepState.complete
|
|
||||||
: StepState.disabled,
|
|
||||||
title: builder.buildTitle(),
|
|
||||||
subtitle: builder.buildSubtitle(),
|
|
||||||
content: builder.buildContent(),
|
|
||||||
isActive: isActive,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AppBody extends StatelessWidget {
|
||||||
|
const _AppBody();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Selector<AppService, AppState>(
|
||||||
|
selector: (context, service) => service.state,
|
||||||
|
builder: (context, state, _) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(16, 12, 16, 10),
|
||||||
|
child: InfoPanel(),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: MediaQuery.removePadding(
|
||||||
|
context: context,
|
||||||
|
removeLeft: true,
|
||||||
|
child: Stepper(
|
||||||
|
controlsBuilder: (context, _) => const SizedBox.shrink(),
|
||||||
|
currentStep: state.step,
|
||||||
|
steps: [
|
||||||
|
...AppState.steps.map(
|
||||||
|
(e) {
|
||||||
|
final builder = AppStepViewBuilder(state: e);
|
||||||
|
final isActive = e == state;
|
||||||
|
return Step(
|
||||||
|
state: isActive
|
||||||
|
? StepState.indexed
|
||||||
|
: e.step < state.step
|
||||||
|
? StepState.complete
|
||||||
|
: StepState.disabled,
|
||||||
|
title: builder.buildTitle(),
|
||||||
|
subtitle: builder.buildSubtitle(),
|
||||||
|
content: builder.buildContent(),
|
||||||
|
isActive: isActive,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nearby_service/nearby_service.dart';
|
||||||
import 'package:nearby_service_example_full/domain/app_service.dart';
|
import 'package:nearby_service_example_full/domain/app_service.dart';
|
||||||
import 'package:nearby_service_example_full/presentation/app.dart';
|
import 'package:nearby_service_example_full/presentation/app.dart';
|
||||||
import 'package:nearby_service_example_full/uikit/uikit.dart';
|
import 'package:nearby_service_example_full/uikit/uikit.dart';
|
||||||
|
import 'package:nearby_service_example_full/utils/files_saver.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../components/device_preview.dart';
|
import '../components/device_preview.dart';
|
||||||
@@ -22,13 +24,13 @@ class _CommunicationViewState extends State<CommunicationView> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<AppService>(
|
return Selector<AppService, NearbyDevice?>(
|
||||||
builder: (context, service, _) {
|
selector: (context, service) => service.connectedDevice,
|
||||||
final device = service.connectedDevice;
|
builder: (context, device, _) {
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
return Center(
|
return Center(
|
||||||
child: ActionButton(
|
child: ActionButton(
|
||||||
onTap: service.stopListeningAll,
|
onTap: context.read<AppService>().stopListeningAll,
|
||||||
title: 'Restart',
|
title: 'Restart',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -69,7 +71,9 @@ class _CommunicationViewState extends State<CommunicationView> {
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: ActionButton(
|
child: ActionButton(
|
||||||
title: 'Send',
|
title: 'Send',
|
||||||
onTap: () => service.sendTextRequest(message),
|
onTap: () => context.read<AppService>().sendTextRequest(
|
||||||
|
message,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -100,7 +104,7 @@ class _CommunicationViewState extends State<CommunicationView> {
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: ActionButton(
|
child: ActionButton(
|
||||||
title: 'Send',
|
title: 'Send',
|
||||||
onTap: () => service.sendFilesRequest([
|
onTap: () => context.read<AppService>().sendFilesRequest([
|
||||||
...files
|
...files
|
||||||
.map((e) => e.path)
|
.map((e) => e.path)
|
||||||
.where((element) => element != null)
|
.where((element) => element != null)
|
||||||
@@ -122,11 +126,57 @@ class _CommunicationViewState extends State<CommunicationView> {
|
|||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
children: [
|
children: [
|
||||||
...files.where((element) => element.path != null).map(
|
...files.where((element) => element.path != null).map(
|
||||||
(e) => Image.file(
|
(e) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: kGreenColor),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(11),
|
||||||
|
child: FilesSaver.isImage(e.extension)
|
||||||
|
? Image.file(
|
||||||
|
File(e.path!),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
e.name,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: kGreenColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (FilesSaver.isImage(e.extension)) {
|
||||||
|
return Image.file(
|
||||||
File(e.path!),
|
File(e.path!),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
);
|
||||||
),
|
} else {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: kBlueColor),
|
||||||
|
borderRadius: BorderRadius.circular(16)),
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
e.name,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: kBlueColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -13,63 +13,68 @@ class ConnectedView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<AppService>(
|
final device = context.select<AppService, NearbyDevice?>(
|
||||||
builder: (context, service, _) {
|
(service) => service.connectedDevice,
|
||||||
final device = service.connectedDevice;
|
|
||||||
return device != null
|
|
||||||
? Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
if (!device.status.isConnected)
|
|
||||||
const Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.all(8.0),
|
|
||||||
child: Text('Connection lost'),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else if (!device.status.isConnected)
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Text('Connection lost'),
|
|
||||||
ActionButton(
|
|
||||||
onTap: () {
|
|
||||||
service.connect(device);
|
|
||||||
},
|
|
||||||
title: 'Reconnect',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else
|
|
||||||
DevicePreview(device: device, largeView: true),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
if (service.communicationChannelState !=
|
|
||||||
CommunicationChannelState.loading)
|
|
||||||
ActionButton(
|
|
||||||
title: 'Start communicate',
|
|
||||||
onTap: () => service.startCommunicationChannel(
|
|
||||||
listener: (event) => MessagesListener.call(
|
|
||||||
context,
|
|
||||||
event,
|
|
||||||
),
|
|
||||||
onFilesSaved: (files) => FilesListener.call(
|
|
||||||
context,
|
|
||||||
files,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
Text(
|
|
||||||
'Connecting socket.. '
|
|
||||||
'${service.isAndroidGroupOwner != null ? service.isAndroidGroupOwner! ? "Waiting a client for connect" : "Waiting a server for connect" : "Waiting a connection"}',
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const SizedBox();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
final isAndroidGroupOwner = context.select<AppService, bool?>(
|
||||||
|
(service) => service.isAndroidGroupOwner,
|
||||||
|
);
|
||||||
|
final communicationChannelState =
|
||||||
|
context.select<AppService, CommunicationChannelState>(
|
||||||
|
(service) => service.communicationChannelState,
|
||||||
|
);
|
||||||
|
return device != null
|
||||||
|
? Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
if (!device.status.isConnected)
|
||||||
|
const Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: Text('Connection lost'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else if (!device.status.isConnected)
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Text('Connection lost'),
|
||||||
|
ActionButton(
|
||||||
|
onTap: () {
|
||||||
|
context.read<AppService>().connect(device);
|
||||||
|
},
|
||||||
|
title: 'Reconnect',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
DevicePreview(device: device, largeView: true),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
if (!communicationChannelState.isLoading)
|
||||||
|
ActionButton(
|
||||||
|
title: 'Start communicate',
|
||||||
|
onTap: () =>
|
||||||
|
context.read<AppService>().startCommunicationChannel(
|
||||||
|
listener: (event) => MessagesListener.call(
|
||||||
|
context,
|
||||||
|
event,
|
||||||
|
),
|
||||||
|
onFilesSaved: (files) => FilesListener.call(
|
||||||
|
context,
|
||||||
|
files,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Text(
|
||||||
|
'Connecting socket.. '
|
||||||
|
'${isAndroidGroupOwner != null ? isAndroidGroupOwner ? "Waiting a client for connect" : "Waiting a server for connect" : "Waiting a connection"}',
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,14 @@ class PermissionsView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<AppService>(builder: (context, service, _) {
|
return Column(
|
||||||
return Column(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
children: [
|
||||||
children: [
|
ActionButton(
|
||||||
ActionButton(
|
onTap: context.read<AppService>().requestPermissions,
|
||||||
onTap: service.requestPermissions,
|
title: 'Request permissions',
|
||||||
title: 'Request permissions',
|
),
|
||||||
),
|
],
|
||||||
],
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nearby_service/nearby_service.dart';
|
||||||
import 'package:nearby_service_example_full/domain/app_service.dart';
|
import 'package:nearby_service_example_full/domain/app_service.dart';
|
||||||
import 'package:nearby_service_example_full/uikit/uikit.dart';
|
import 'package:nearby_service_example_full/uikit/uikit.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -32,29 +33,35 @@ class _PeersBody extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<AppService>(
|
return Selector<AppService, bool>(
|
||||||
builder: (context, service, _) {
|
selector: (context, service) => service.isIOSBrowser,
|
||||||
return (service.peers != null && service.peers!.isNotEmpty)
|
builder: (context, isIOSBrowser, _) {
|
||||||
? Column(
|
return Selector<AppService, List<NearbyDevice>?>(
|
||||||
mainAxisSize: MainAxisSize.min,
|
selector: (context, service) => service.peers,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
builder: (context, peers, _) {
|
||||||
children: [
|
return (peers != null && peers.isNotEmpty)
|
||||||
...service.peers!.map(
|
? Column(
|
||||||
(e) {
|
mainAxisSize: MainAxisSize.min,
|
||||||
return Container(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
padding: const EdgeInsets.only(bottom: 8.0),
|
children: [
|
||||||
child: DevicePreview(device: e),
|
...peers.map(
|
||||||
);
|
(e) {
|
||||||
},
|
return Container(
|
||||||
),
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
],
|
child: DevicePreview(device: e),
|
||||||
)
|
);
|
||||||
: Text(
|
},
|
||||||
Platform.isAndroid || service.isIOSBrowser
|
),
|
||||||
? 'No one here ('
|
],
|
||||||
: "Wait until someone invites you!",
|
)
|
||||||
textAlign: TextAlign.center,
|
: Text(
|
||||||
);
|
Platform.isAndroid || isIOSBrowser
|
||||||
|
? 'No one here ('
|
||||||
|
: "Wait until someone invites you!",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,19 @@ import 'package:path_provider/path_provider.dart';
|
|||||||
class FilesSaver {
|
class FilesSaver {
|
||||||
FilesSaver._();
|
FilesSaver._();
|
||||||
|
|
||||||
|
static bool isImage(String? extension) {
|
||||||
|
return _imageExtensions.contains(extension?.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
static const _imageExtensions = [
|
||||||
|
'jpg',
|
||||||
|
'jpeg',
|
||||||
|
'png',
|
||||||
|
'gif',
|
||||||
|
'webp',
|
||||||
|
'bmp',
|
||||||
|
];
|
||||||
|
|
||||||
static Future<List<NearbyFileInfo>> savePack(
|
static Future<List<NearbyFileInfo>> savePack(
|
||||||
ReceivedNearbyFilesPack pack) async {
|
ReceivedNearbyFilesPack pack) async {
|
||||||
final files = <NearbyFileInfo>[];
|
final files = <NearbyFileInfo>[];
|
||||||
|
|||||||
@@ -2,4 +2,14 @@
|
|||||||
/// The status of the communication channel for data exchange.
|
/// The status of the communication channel for data exchange.
|
||||||
/// Use it to determine if you can send data over the communication channel or not.
|
/// Use it to determine if you can send data over the communication channel or not.
|
||||||
///
|
///
|
||||||
enum CommunicationChannelState { notConnected, loading, connected }
|
enum CommunicationChannelState {
|
||||||
|
notConnected,
|
||||||
|
loading,
|
||||||
|
connected;
|
||||||
|
|
||||||
|
bool get isNotConnected => this == CommunicationChannelState.notConnected;
|
||||||
|
|
||||||
|
bool get isLoading => this == CommunicationChannelState.loading;
|
||||||
|
|
||||||
|
bool get isConnected => this == CommunicationChannelState.connected;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user