Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend public member documentation #381

Merged
merged 6 commits into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/src/authentication/src/token_params.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class TokenParams {
this.ttl,
});

/// converts to a map of objects
Map<String, dynamic> toMap() {
final jsonMap = <String, dynamic>{};
if (capability != null) jsonMap['capability'] = capability;
Expand Down
26 changes: 19 additions & 7 deletions lib/src/crypto/src/crypto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@ import 'package:ably_flutter/src/platform/platform_internal.dart';
/// Utility methods for creating keys ([generateRandomKey]) and configuration
/// objects ([CipherParams]) for symmetric encryption.
class Crypto {
/// Default algorithm used of encryption
/// Currently only AES is supported
static const defaultAlgorithm = 'aes';
static const defaultBlockLengthInBytes = 16;
static const defaultKeyLengthInBits = 256;

/// Default length of the key in bits
/// Equals to [keyLength256bits]
static const defaultKeyLengthInBits = keyLength256bits;

/// Length of 256-bit key
static const keyLength256bits = 256;

/// Length of 128-bit key
static const keyLength128bits = 128;

/// Default mode used of encryption
/// Currently only CBC is supported
static const defaultMode = 'cbc';
static const keyTypeErrorMessage = 'key must be a String or Uint8List.';
static const keyLengthErrorMessage = 'key must be 256 bits or 128 bits long.';

/// Gets the CipherParams which can be used to with [RestChannelOptions] or
/// [RealtimeChannelOptions] to specify encryption.
Expand All @@ -30,7 +40,7 @@ class Crypto {
ensureSupportedKeyLength(key);
} else {
throw AblyException(
message: keyTypeErrorMessage,
message: 'key must be a String or Uint8List.',
);
}

Expand All @@ -43,11 +53,13 @@ class Crypto {
);
}

/// Validates the length of provided [key]
/// Throws [AblyException] if key length is different than 128 or 256 bits
static void ensureSupportedKeyLength(Uint8List key) {
if (key.length != defaultKeyLengthInBits / 8 &&
if (key.length != keyLength256bits / 8 &&
key.length != keyLength128bits / 8) {
throw AblyException(
message: keyLengthErrorMessage,
message: 'Key must be 256 bits or 128 bits long.',
);
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/src/logging/src/log_level.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import 'package:ably_flutter/ably_flutter.dart';
/// Can be used for [ClientOptions.logLevel]
///
/// https://docs.ably.com/client-lib-development-guide/features/#TO3b
// ignore: public_member_api_docs
enum LogLevel { none, verbose, debug, info, warn, error }
3 changes: 3 additions & 0 deletions lib/src/platform/src/background_android_isolate_platform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class BackgroundIsolateAndroidPlatform {
Future<void> _onPushBackgroundMessage(RemoteMessage remoteMessage) async =>
_pushNotificationEvents.handleBackgroundMessage(remoteMessage);

/// Equivalent of [Platform.invokePlatformMethod] which cannot be used here
/// because we may not be able to acquire [Platform] instance here, so we
/// need to use a raw [MethodChannel] communication
Future<T?> invokeMethod<T>(String method, [dynamic arguments]) async =>
_methodChannel.invokeMethod<T>(method, arguments);
}
21 changes: 14 additions & 7 deletions lib/src/platform/src/cipher_params_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@ import 'package:ably_flutter/ably_flutter.dart';
/// needing to store instances on the Android side and pass references/handles
/// to the dart side.
class CipherParamsInternal implements CipherParams {
/// Android only
/// Handle value read from platform implementation
int? androidHandle;

/// iOS only
/// Encryption key returned by platform implementation
Uint8List? key;

/// iOS only
/// Encryption algorithm returned by platform implementation
String? algorithm;

String? mode = 'cbc';

/// Create a Dart side representation of CipherParams
/// Create a Dart side representation of CipherParams for iOS devices
CipherParamsInternal.forIOS({
required this.algorithm,
required this.key,
Expand All @@ -41,6 +46,7 @@ class CipherParamsInternal implements CipherParams {
}
}

/// Create a Dart side representation of CipherParams for Android devices
CipherParamsInternal.forAndroid({
required this.androidHandle,
}) {
Expand All @@ -56,10 +62,11 @@ class CipherParamsInternal implements CipherParams {
}
}

/// Explicitly cast the [CipherParams] to [CipherParamsInternal] so
/// it's possible to access the internal implementation details
///
/// This method is actually package-private, because [CipherParamsInternal]
/// is not exposed outside of the package
static CipherParamsInternal fromCipherParams(CipherParams cipherParams) =>
cipherParams as CipherParamsInternal;

/// Explicitly cast the [CipherParamsInternal] to [CipherParams] so
/// users do not see implementation details (e.g. [androidHandle]).
CipherParams toCipherParams() => this;
}
8 changes: 4 additions & 4 deletions lib/src/platform/src/method_call_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ class AblyMethodCallHandler {
return _pushNotificationEvents
.showNotificationInForeground(call.arguments as RemoteMessage);
case PlatformMethod.pushOnNotificationTap:
return onNotificationTap(call.arguments as RemoteMessage);
return _onNotificationTap(call.arguments as RemoteMessage);
case PlatformMethod.pushOpenSettingsFor:
return onOpenSettingsFor();
return _onOpenSettingsFor();
default:
throw PlatformException(
code: 'Received invalid method channel call from Platform side',
Expand Down Expand Up @@ -94,13 +94,13 @@ class AblyMethodCallHandler {
return null;
}

Future<Object?> onNotificationTap(RemoteMessage remoteMessage) async {
Future<Object?> _onNotificationTap(RemoteMessage remoteMessage) async {
_pushNotificationEvents.onNotificationTapStreamController
.add(remoteMessage);
return null;
}

Future<Object?> onOpenSettingsFor() async {
Future<Object?> _onOpenSettingsFor() async {
if (_pushNotificationEvents.onOpenSettingsHandler != null) {
_pushNotificationEvents.onOpenSettingsHandler!();
}
Expand Down
8 changes: 7 additions & 1 deletion lib/src/platform/src/platform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import 'package:ably_flutter/ably_flutter.dart';
import 'package:ably_flutter/src/platform/platform_internal.dart';
import 'package:flutter/services.dart';

/// Used to communicate between Dart and native platforms
/// holds reference to [MethodChannel] and exposes methods used to invoke
/// platform calls and listen to platform data streams
class Platform {
Platform._internal({MethodChannel? methodChannel}) {
_methodChannel = methodChannel;
Expand Down Expand Up @@ -33,6 +36,7 @@ class Platform {
/// instance of method channel to listen to android/ios events
late final StreamsChannel? _streamsChannel;

/// Call a platform method which may return null/void as a result
Future<T?> invokePlatformMethod<T>(String method,
[AblyMessage<Map<String, dynamic>>? arguments]) async {
try {
Expand All @@ -50,7 +54,7 @@ class Platform {
}
}

/// Call a platform method which always provides a result.
/// Call a platform method which always provides a non-null result
Future<T> invokePlatformMethodNonNull<T>(String method,
[AblyMessage<Map<String, dynamic>>? arguments]) async {
final result = await invokePlatformMethod<T>(method, arguments);
Expand All @@ -63,6 +67,8 @@ class Platform {
}
}

/// Call a platform method which always provides an observable stream
/// of data as a result
Stream<T> receiveBroadcastStream<T>(String methodName, int handle,
[final Object? payload]) =>
_streamsChannel!.receiveBroadcastStream<T>(
Expand Down
9 changes: 9 additions & 0 deletions lib/src/platform/src/push_activation_events_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@ import 'dart:async';

import 'package:ably_flutter/ably_flutter.dart';

/// package-private implementation of [PushActivationEvents]
/// used internally by [Push] instances
// FIXME: StreamControllers here may leak, we should add a `close()` method
KacperKluka marked this conversation as resolved.
Show resolved Hide resolved
// See: https://github.com/ably/ably-flutter/issues/382
class PushActivationEventsInternal extends PushActivationEvents {
/// [StreamController] used to handle onActivate events
StreamController<ErrorInfo?> onActivateStreamController = StreamController();

/// [StreamController] used to handle onDeactivate events
StreamController<ErrorInfo?> onDeactivateStreamController =
StreamController();

/// [StreamController] used to handle onUpdateFailed events
StreamController<ErrorInfo> onUpdateFailedStreamController =
StreamController();

Expand Down
14 changes: 12 additions & 2 deletions lib/src/platform/src/push_notification_events_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@ import 'dart:ui';
import 'package:ably_flutter/ably_flutter.dart';
import 'package:ably_flutter/src/platform/platform_internal.dart';

/// package-private implementation of [PushNotificationEvents]
class PushNotificationEventsInternal implements PushNotificationEvents {
/// Invoked when pushOpenSettingsFor platform method is called
VoidCallback? onOpenSettingsHandler;

/// Invoked when pushOnShowNotificationInForeground platform method is called
Future<bool> Function(RemoteMessage message)?
onShowNotificationInForegroundHandler;

/// Exposes stream of received [RemoteMessage] objects
/// New message is emitted after pushOnMessage platform method is called
StreamController<RemoteMessage> onMessageStreamController =
StreamController();

/// Controller used to indicate notification was tapped
StreamController<RemoteMessage> onNotificationTapStreamController =
StreamController();

BackgroundMessageHandler? _onBackgroundMessage;

@override
Future<RemoteMessage?> get notificationTapLaunchedAppFromTerminated =>
Platform().invokePlatformMethod<RemoteMessage>(
Expand Down Expand Up @@ -48,8 +57,6 @@ class PushNotificationEventsInternal implements PushNotificationEvents {
return onShowNotificationInForegroundHandler!(message);
}

BackgroundMessageHandler? _onBackgroundMessage;

/// Implementation of setOnBackgroundMessage. For more documentation,
/// see [PushNotificationEvents.setOnBackgroundMessage]
@override
Expand Down Expand Up @@ -77,6 +84,9 @@ class PushNotificationEventsInternal implements PushNotificationEvents {
}
}

/// Used to close internal [StreamController] instances
// FIXME: This method is not called anywhere
// See: https://github.com/ably/ably-flutter/issues/382
void close() {
onMessageStreamController.close();
onNotificationTapStreamController.close();
Expand Down
1 change: 1 addition & 0 deletions lib/src/platform/src/realtime/connection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class Connection extends PlatformObject {
/// https://docs.ably.com/client-lib-development-guide/features/#connection-states-operations
ConnectionState get state => _state;

/// stream of connection events with specified [ConnectionEvent] type
Stream<ConnectionStateChange> on([ConnectionEvent? connectionEvent]) =>
listen<ConnectionStateChange>(
PlatformMethod.onRealtimeConnectionStateChanged,
Expand Down
4 changes: 4 additions & 0 deletions lib/src/platform/src/realtime/realtime_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class RealtimeChannel extends PlatformObject {
/// (see IDL for more details)
late PushChannel push;

/// Current state of the channel
///
KacperKluka marked this conversation as resolved.
Show resolved Hide resolved
/// https://docs.ably.com/client-lib-development-guide/features/#RTL2b
ChannelState state;

/// Attaches the realtime client to this channel.
Expand All @@ -124,6 +127,7 @@ class RealtimeChannel extends PlatformObject {
TxTransportKeys.options: options,
});

/// stream of channel events with specified [ChannelEvent] type
Stream<ChannelStateChange> on([ChannelEvent? channelEvent]) =>
listen<ChannelStateChange>(
PlatformMethod.onRealtimeChannelStateChanged,
Expand Down
6 changes: 3 additions & 3 deletions lib/src/platform/src/rest/rest_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ class RestChannel extends PlatformObject {
/// name of the channel
String name;

late RestPresence _presence;

/// presence interface for this channel
///
/// can only query presence on the channel and presence history
/// https://docs.ably.com/client-lib-development-guide/features/#RSL3
late RestPresence _presence;
RestPresence get presence => _presence;

/// instantiates with [Rest], [name] and [RestChannelOptions]
RestChannel(this.rest, this.push, this.name) {
_presence = RestPresence(this);
}

RestPresence get presence => _presence;

/// createPlatformInstance will return restPlatformObject's handle
/// as that is what will be required in platforms end to find rest instance
/// and send message to channel
Expand Down
2 changes: 2 additions & 0 deletions lib/src/push_notifications/src/ios_notification_settings.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: public_member_api_docs

import 'package:ably_flutter/ably_flutter.dart';

/// This file contains push notification types specific to iOS. All types begin
Expand Down
1 change: 1 addition & 0 deletions lib/src/push_notifications/src/notification.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Notification {
this.body,
});

/// Creates an instance from the map
factory Notification.fromMap(Map<String, dynamic> map) => Notification(
body: map[TxNotification.body] as String?,
title: map[TxNotification.title] as String,
Expand Down
2 changes: 2 additions & 0 deletions lib/src/push_notifications/src/push_notification_events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'dart:ui';

import 'package:ably_flutter/ably_flutter.dart';

/// type definition for a callback invoked when background push message
/// is received
typedef BackgroundMessageHandler = void Function(RemoteMessage message);

/// Push Notification events, such as message arriving or notification tap.
Expand Down
1 change: 1 addition & 0 deletions lib/src/push_notifications/src/remote_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class RemoteMessage {
this.notification,
}) : data = data ??= {};

/// create instance from a map
factory RemoteMessage.fromMap(Map<String, dynamic> map) => RemoteMessage(
data: (map[TxRemoteMessage.data] == null)
? <String, dynamic>{}
Expand Down