Add macOS support (#23)

* Add macOS support

* Update README

* Update to v0.2.0

* Document breaking changes

* Delete widget tests
This commit is contained in:
Ben Hagen
2025-05-13 16:24:58 +02:00
committed by GitHub
parent c391cc5f26
commit abe519dae7
103 changed files with 3444 additions and 169 deletions
+28 -28
View File
@@ -18,7 +18,7 @@ export 'src/interface/interface.dart';
/// The main tool for working with a P2P network.
/// Implementations:
/// * for Android - [NearbyAndroidService]
/// * for IOS - [NearbyIOSService]
/// * for Darwin - [NearbyDarwinService]
///
/// **The plugin is not supported for other platforms yet**
///
@@ -37,9 +37,9 @@ abstract class NearbyService {
if (Platform.isAndroid) {
Logger.debug('Created Nearby Android Service');
return NearbyAndroidService();
} else if (Platform.isIOS) {
Logger.debug('Created Nearby IOS Service');
return NearbyIOSService();
} else if (Platform.isIOS || Platform.isMacOS) {
Logger.debug('Created Nearby Darwin Service');
return NearbyDarwinService();
} else {
throw NearbyServiceException.unsupportedPlatform(
caller: 'getInstance()',
@@ -48,11 +48,11 @@ abstract class NearbyService {
}
///
/// Returns [NearbyService] cast as [NearbyIOSService] if the current
/// platform is IOS. Otherwise, returns null.
/// Returns [NearbyService] cast as [NearbyDarwinService] if the current
/// platform is IOS or MacOS. Otherwise, returns null.
///
late final NearbyIOSService? ios = get(
onIOS: (e) => e,
late final NearbyDarwinService? darwin = get(
onDarwin: (e) => e,
);
///
@@ -193,8 +193,8 @@ abstract class NearbyService {
///
/// Starts searching for devices using a platform-specific service.
///
/// Note that the [NearbyIOSService] implementation starts **browsing** or
/// **advertising** depending on the [NearbyIOSService.isBrowserValue].
/// Note that the [NearbyDarwinService] implementation starts **browsing** or
/// **advertising** depending on the [NearbyDarwinService.isBrowserValue].
///
/// On Android can throw mapped from native platform exceptions:
/// 1. [NearbyServiceBusyException]
@@ -208,8 +208,8 @@ abstract class NearbyService {
///
/// Stops searching for devices using a platform-specific service.
///
/// Note that the [NearbyIOSService] implementation stops **browsing** or
/// **advertising** depending on the [NearbyIOSService.isBrowserValue].
/// Note that the [NearbyDarwinService] implementation stops **browsing** or
/// **advertising** depending on the [NearbyDarwinService.isBrowserValue].
///
/// On Android can throw mapped from native platform exceptions:
/// 1. [NearbyServiceBusyException]
@@ -223,10 +223,10 @@ abstract class NearbyService {
///
/// Connects to passed [device] using a platform-specific service.
///
/// Note that the [NearbyIOSService] implementation **invites** or
/// **accepts invite** depending on the [NearbyIOSService.isBrowser].
/// Note that the [NearbyDarwinService] implementation **invites** or
/// **accepts invite** depending on the [NearbyDarwinService.isBrowser].
///
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
/// Note that if [Platform.isIOS] == true, [NearbyDarwinDevice] should be passed.
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
///
/// On Android can throw mapped from native platform exceptions:
@@ -242,10 +242,10 @@ abstract class NearbyService {
///
/// Connects to passed [deviceId] using a platform-specific service.
///
/// Note that the [NearbyIOSService] implementation **invites** or
/// **accepts invite** depending on the [NearbyIOSService.isBrowserValue].
/// Note that the [NearbyDarwinService] implementation **invites** or
/// **accepts invite** depending on the [NearbyDarwinService.isBrowserValue].
///
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
/// Note that if [Platform.isIOS] == true, [NearbyDarwinDevice] should be passed.
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
///
/// On Android can throw mapped from native platform exceptions:
@@ -260,7 +260,7 @@ abstract class NearbyService {
///
/// Disconnects from passed [device] using a platform-specific service.
///
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
/// Note that if [Platform.isIOS] == true, [NearbyDarwinDevice] should be passed.
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
///
/// On Android can throw mapped from native platform exceptions:
@@ -277,7 +277,7 @@ abstract class NearbyService {
///
/// Disconnects from passed [deviceId] using a platform-specific service.
///
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
/// Note that if [Platform.isIOS] or [Platform.isMacOS] == true, [NearbyDarwinDevice] should be passed.
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
///
/// On Android can throw mapped from native platform exceptions:
@@ -338,28 +338,28 @@ extension NearbyServiceGetterExtension on NearbyService {
/// * The [onAndroid] callback returns this instance of [NearbyService],
/// cast as [NearbyAndroidService] if [Platform.isAndroid] is true.
///
/// * The [onIOS] callback returns this instance of [NearbyService],
/// cast as [NearbyIOSService] if [Platform.isIOS] is true.
/// * The [onDarwin] callback returns this instance of [NearbyService],
/// cast as [NearbyDarwinService] if [Platform.isIOS] or [Platform.isMacOS] is true.
///
/// * The [onAny] callback returns this instance of [NearbyService] with
/// no casting if both [Platform.isAndroid] and [Platform.isIOS] are false.
/// no casting if both [Platform.isAndroid] and [Platform.isIOS] or [Platform.isMacOS] are false.
///
/// **Note: any of the callbacks must not be null!**
///
T? get<T>({
T Function(NearbyAndroidService)? onAndroid,
T Function(NearbyIOSService)? onIOS,
T Function(NearbyDarwinService)? onDarwin,
T Function(NearbyService)? onAny,
}) {
assert(
onAndroid != null || onIOS != null || onAny != null,
'You should provide at least one of (onAndroid, onIOS, onAny)',
onAndroid != null || onDarwin != null || onAny != null,
'You should provide at least one of (onAndroid, onDarwin, onAny)',
);
if (this is NearbyAndroidService && onAndroid != null) {
return onAndroid(this as NearbyAndroidService);
}
if (this is NearbyIOSService && onIOS != null) {
return onIOS(this as NearbyIOSService);
if (this is NearbyDarwinService && onDarwin != null) {
return onDarwin(this as NearbyDarwinService);
}
if (onAny != null) {
return onAny(this);
+6 -6
View File
@@ -46,19 +46,19 @@ abstract base class NearbyDevice {
/// * The [onAndroid] callback returns this instance of [NearbyDevice],
/// cast as [NearbyAndroidDevice] if [Platform.isAndroid] is true.
///
/// * The [onIOS] callback returns this instance of [NearbyDevice],
/// cast as [NearbyIOSDevice] if [Platform.isIOS] is true.
/// * The [onDarwin] callback returns this instance of [NearbyDevice],
/// cast as [NearbyDarwinDevice] if [Platform.isIOS] or [Platform.isMacOS] is true.
///
/// * The [onAny] callback returns this instance of [NearbyDevice] with
/// no casting if both [Platform.isAndroid] and [Platform.isIOS] are false.
/// no casting if both [Platform.isAndroid] and [Platform.isIOS] or [Platform.isMacOS] are false.
///
T? byPlatform<T>({
T Function(NearbyDevice)? onAny,
T Function(NearbyAndroidDevice)? onAndroid,
T Function(NearbyIOSDevice)? onIOS,
T Function(NearbyDarwinDevice)? onDarwin,
}) {
if (this is NearbyIOSDevice && onIOS != null) {
return onIOS(this as NearbyIOSDevice);
if (this is NearbyDarwinDevice && onDarwin != null) {
return onDarwin(this as NearbyDarwinDevice);
} else if (this is NearbyAndroidDevice && onAndroid != null) {
return onAndroid(this as NearbyAndroidDevice);
} else {
+1 -1
View File
@@ -13,7 +13,7 @@ abstract interface class NearbyDeviceMapper {
if (Platform.isAndroid) {
return NearbyAndroidMapper();
}
if (Platform.isIOS) {
if (Platform.isIOS || Platform.isMacOS) {
return NearbyIOSMapper();
}
@@ -8,8 +8,8 @@ abstract class NearbyServiceExceptionMapper {
static NearbyServiceExceptionMapper get instance {
if (Platform.isAndroid) {
return NearbyServiceAndroidExceptionMapper();
} else if (Platform.isIOS) {
return NearbyServiceIOSExceptionMapper();
} else if (Platform.isIOS || Platform.isMacOS) {
return NearbyServiceDarwinExceptionMapper();
}
throw NearbyServiceException.unsupportedPlatform(
caller: 'NearbyServiceExceptionMapper',
@@ -4,7 +4,7 @@ import 'package:nearby_service/src/utils/json_decoder.dart';
///
/// A device on a P2P network obtained from the IOS platform.
///
final class NearbyIOSDevice extends NearbyDevice {
final class NearbyDarwinDevice extends NearbyDevice {
///
/// A class representing an IOS device on a P2P network.
///
@@ -13,7 +13,7 @@ final class NearbyIOSDevice extends NearbyDevice {
///
/// [MCPeerID](https://developer.apple.com/documentation/multipeerconnectivity/mcpeerid) is an identifier on the local network for IOS.
///
NearbyIOSDevice({
NearbyDarwinDevice({
required super.info,
required super.status,
this.os,
@@ -22,10 +22,10 @@ final class NearbyIOSDevice extends NearbyDevice {
});
///
/// Gets [NearbyIOSDevice] from [Map].
/// Gets [NearbyDarwinDevice] from [Map].
///
factory NearbyIOSDevice.fromJson(Map<String, dynamic>? json) {
return NearbyIOSDevice(
factory NearbyDarwinDevice.fromJson(Map<String, dynamic>? json) {
return NearbyDarwinDevice(
info: NearbyDeviceInfo.fromJson(json),
deviceType: json?["deviceType"],
os: json?["os"],
@@ -53,7 +53,7 @@ final class NearbyIOSDevice extends NearbyDevice {
bool operator ==(Object other) =>
identical(this, other) ||
super == other &&
other is NearbyIOSDevice &&
other is NearbyDarwinDevice &&
runtimeType == other.runtimeType &&
os == other.os &&
osVersion == other.osVersion &&
@@ -78,7 +78,7 @@ class NearbyIOSMapper implements NearbyDeviceMapper {
final decoded = JSONDecoder.decodeList(value);
return [
...?decoded?.map(
(e) => NearbyIOSDevice.fromJson(JSONDecoder.decodeMap(e)),
(e) => NearbyDarwinDevice.fromJson(JSONDecoder.decodeMap(e)),
),
];
}
@@ -88,6 +88,6 @@ class NearbyIOSMapper implements NearbyDeviceMapper {
final decoded = JSONDecoder.decodeMap(value);
if (decoded == null) return null;
return NearbyIOSDevice.fromJson(decoded);
return NearbyDarwinDevice.fromJson(decoded);
}
}
+10 -10
View File
@@ -13,7 +13,7 @@ import 'package:nearby_service/src/utils/stream_mapper.dart';
/// Connects to the device by subscribing to messages from the selected
/// device by identifier.
///
class NearbyIOSService extends NearbyService {
class NearbyDarwinService extends NearbyService {
final _isBrowser = NearbyServiceListenable<bool>(initialValue: true);
final _communicationChannelState =
@@ -68,7 +68,7 @@ class NearbyIOSService extends NearbyService {
/// The name of the device on the network can be
/// specified on initialization via the parameter [data].
///
/// [NearbyInitializeData.iosDeviceName] will be passed to the platform as initial
/// [NearbyInitializeData.darwinDeviceName] will be passed to the platform as initial
/// name. If a new name is not passed, the previous name stored
/// in [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults)
/// will be used. If there is no saved name, `UIDevice.current.name` will be used.
@@ -78,13 +78,13 @@ class NearbyIOSService extends NearbyService {
NearbyInitializeData data = const NearbyInitializeData(),
}) async {
final result = await NearbyServiceIOSPlatform.instance.initialize(
data.iosDeviceName,
data.darwinDeviceName,
);
_logResult(
result,
onSuccess: 'Initialized ${data.iosDeviceName}',
onError: 'Failed to initialize ${data.iosDeviceName}',
onSuccess: 'Initialized ${data.darwinDeviceName}',
onError: 'Failed to initialize ${data.darwinDeviceName}',
);
return result;
}
@@ -134,7 +134,7 @@ class NearbyIOSService extends NearbyService {
/// Invites [device] if [isBrowserValue] is true.
/// Accepts invite from [device] if [isBrowserValue] is false.
///
/// Note! Requires [NearbyIOSDevice] to be passed.
/// Note! Requires [NearbyDarwinDevice] to be passed.
@Deprecated('Use connectById instead')
@override
Future<bool> connect(NearbyDevice device) async {
@@ -167,7 +167,7 @@ class NearbyIOSService extends NearbyService {
///
/// Disconnects from the [device] on the P2P network.
///
/// Note! Requires [NearbyIOSDevice] to be passed.
/// Note! Requires [NearbyDarwinDevice] to be passed.
///
@Deprecated('Use disconnectById instead')
@override
@@ -290,7 +290,7 @@ class NearbyIOSService extends NearbyService {
/// [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) using this method.
///
/// Changing the name on the network is only available for IOS,
/// so the [NearbyIOSService] only can be used for that.
/// so the [NearbyDarwinService] only can be used for that.
///
Future<String?> getSavedDeviceName() {
return NearbyServiceIOSPlatform.instance.getSavedDeviceName();
@@ -322,8 +322,8 @@ class NearbyIOSService extends NearbyService {
void _requireIOSDevice(NearbyDevice device) {
assert(
device is NearbyIOSDevice,
'The Nearby IOS Service can only work with the NearbyIOSDevice and not with ${device.runtimeType}',
device is NearbyDarwinDevice,
'The Nearby IOS Service can only work with the NearbyDarwinDevice and not with ${device.runtimeType}',
);
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
import 'package:nearby_service/nearby_service.dart';
import 'package:nearby_service/src/interface/nearby_service_exception_mapper.dart';
class NearbyServiceIOSExceptionMapper extends NearbyServiceExceptionMapper {
class NearbyServiceDarwinExceptionMapper extends NearbyServiceExceptionMapper {
@override
bool canMap(String error) {
return IOSFailureCodes.values.any((element) => element.name == error);
+2 -2
View File
@@ -8,10 +8,10 @@ class NearbyInitializeData {
/// There is an option to pass the device name to IOS [iosDeviceName].
/// For Android platform changing device name in P2P network is not supported.
///
const NearbyInitializeData({this.iosDeviceName});
const NearbyInitializeData({this.darwinDeviceName});
///
/// The device name for IOS on the P2P network.
///
final String? iosDeviceName;
final String? darwinDeviceName;
}