Skip to content

Commit

Permalink
Merge branch 'main' into fix/db-common-cmake-collision
Browse files Browse the repository at this point in the history
  • Loading branch information
Equartey authored Oct 23, 2024
2 parents 8dfbdcd + 25fe3f0 commit 3b9cc90
Show file tree
Hide file tree
Showing 42 changed files with 474 additions and 58 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions packages/amplify_core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 2.4.2

### Features
- feat(api): move App Sync subscription headers to protocol ([#5301](https://github.com/aws-amplify/amplify-flutter/pull/5301))

### Fixes
- fix(api): Reconnect WebSocket when resuming app from a paused state ([#5567](https://github.com/aws-amplify/amplify-flutter/pull/5567))

## 2.4.1

### Fixes
Expand Down
2 changes: 1 addition & 1 deletion packages/amplify_core/lib/src/version.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/amplify_core/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: amplify_core
description: The base package containing common types and utilities that are shared across the Amplify Flutter packages.
version: 2.4.1
version: 2.4.2
homepage: https://docs.amplify.aws/lib/q/platform/flutter/
repository: https://github.com/aws-amplify/amplify-flutter/tree/main/packages/amplify_core
issue_tracker: https://github.com/aws-amplify/amplify-flutter/issues
Expand All @@ -10,7 +10,7 @@ environment:

dependencies:
async: ^2.10.0
aws_common: ">=0.7.3 <0.8.0"
aws_common: ">=0.7.4 <0.8.0"
aws_signature_v4: ">=0.6.3 <0.7.0"
collection: ^1.15.0
graphs: ^2.1.0
Expand Down
4 changes: 4 additions & 0 deletions packages/amplify_datastore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.4.2

- Minor bug fixes and improvements

## 2.4.1

### Fixes
Expand Down
4 changes: 2 additions & 2 deletions packages/amplify_datastore/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: amplify_datastore
description: The Amplify Flutter DataStore category plugin, providing a queryable, on-device data store.
version: 2.4.1
version: 2.4.2
homepage: https://docs.amplify.aws/lib/q/platform/flutter/
repository: https://github.com/aws-amplify/amplify-flutter/tree/main/packages/amplify_datastore
issue_tracker: https://github.com/aws-amplify/amplify-flutter/issues
Expand All @@ -13,7 +13,7 @@ dependencies:
flutter:
sdk: flutter
amplify_datastore_plugin_interface: ">=2.4.1 <2.5.0"
amplify_core: ">=2.4.1 <2.5.0"
amplify_core: ">=2.4.2 <2.5.0"
plugin_platform_interface: ^2.0.0
meta: ^1.7.0
collection: ^1.14.13
Expand Down
5 changes: 5 additions & 0 deletions packages/api/amplify_api/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.4.2

### Fixes
- fix(api): Reconnect WebSocket when resuming app from a paused state ([#5567](https://github.com/aws-amplify/amplify-flutter/pull/5567))

## 2.4.1

- Minor bug fixes and improvements
Expand Down
6 changes: 5 additions & 1 deletion packages/api/amplify_api/lib/amplify_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ library amplify_api;

export 'package:amplify_api/src/api_plugin_impl.dart';
export 'package:amplify_api_dart/amplify_api_dart.dart'
hide AmplifyAPIDart, ConnectivityPlatform, ConnectivityStatus;
hide
AmplifyAPIDart,
ConnectivityPlatform,
ProcessLifeCycle,
ConnectivityStatus;
2 changes: 2 additions & 0 deletions packages/api/amplify_api/lib/src/api_plugin_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_api/src/connectivity_plus_platform.dart';
import 'package:amplify_api/src/flutter_life_cycle.dart';
import 'package:amplify_api_dart/amplify_api_dart.dart';
import 'package:amplify_core/amplify_core.dart';

Expand All @@ -14,6 +15,7 @@ class AmplifyAPI extends AmplifyAPIDart with AWSDebuggable {
super.options,
}) : super(
connectivity: const ConnectivityPlusPlatform(),
processLifeCycle: FlutterLifeCycle(),
);

@override
Expand Down
42 changes: 42 additions & 0 deletions packages/api/amplify_api/lib/src/flutter_life_cycle.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'dart:async';

import 'package:amplify_api_dart/amplify_api_dart.dart';
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';

/// {@template amplify_api.flutter_life_cycle}
/// Creates a stream of [ProcessStatus] mapped from [AppLifecycleListener](https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html).
/// {@endtemplate}
@internal
class FlutterLifeCycle extends ProcessLifeCycle {
/// {@macro amplify_api.flutter_life_cycle}
FlutterLifeCycle() {
AppLifecycleListener(
onStateChange: _onStateChange,
);
}

final _stateController =
StreamController<ProcessStatus>.broadcast(sync: true);

@override
Stream<ProcessStatus> get onStateChanged => _stateController.stream;

void _onStateChange(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.detached:
_stateController.add(ProcessStatus.detached);
case AppLifecycleState.paused:
_stateController.add(ProcessStatus.paused);
case AppLifecycleState.hidden:
_stateController.add(ProcessStatus.hidden);
case AppLifecycleState.inactive:
_stateController.add(ProcessStatus.inactive);
case AppLifecycleState.resumed:
_stateController.add(ProcessStatus.resumed);
}
}
}
6 changes: 3 additions & 3 deletions packages/api/amplify_api/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: amplify_api
description: The Amplify Flutter API category plugin, supporting GraphQL and REST operations.
version: 2.4.1
version: 2.4.2
homepage: https://docs.amplify.aws/lib/q/platform/flutter/
repository: https://github.com/aws-amplify/amplify-flutter/tree/main/packages/api/amplify_api
issue_tracker: https://github.com/aws-amplify/amplify-flutter/issues
Expand All @@ -19,8 +19,8 @@ platforms:
web:

dependencies:
amplify_api_dart: ">=0.5.5 <0.6.0"
amplify_core: ">=2.4.1 <2.5.0"
amplify_api_dart: ">=0.5.6 <0.6.0"
amplify_core: ">=2.4.2 <2.5.0"
amplify_flutter: ">=2.4.1 <2.5.0"
connectivity_plus: ^6.0.1
flutter:
Expand Down
8 changes: 8 additions & 0 deletions packages/api/amplify_api_dart/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 0.5.6

### Features
- feat(api): move App Sync subscription headers to protocol ([#5301](https://github.com/aws-amplify/amplify-flutter/pull/5301))

### Fixes
- fix(api): Reconnect WebSocket when resuming app from a paused state ([#5567](https://github.com/aws-amplify/amplify-flutter/pull/5567))

## 0.5.5

### Fixes
Expand Down
1 change: 1 addition & 0 deletions packages/api/amplify_api_dart/lib/amplify_api_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export 'src/graphql/model_helpers/model_subscriptions.dart';

/// Network connectivity util not needed by consumers of Flutter package amplify_api.
export 'src/graphql/web_socket/types/connectivity_platform.dart';
export 'src/graphql/web_socket/types/process_life_cycle.dart';
9 changes: 8 additions & 1 deletion packages/api/amplify_api_dart/lib/src/api_plugin_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:amplify_api_dart/src/graphql/web_socket/blocs/web_socket_bloc.da
import 'package:amplify_api_dart/src/graphql/web_socket/services/web_socket_service.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/state/web_socket_state.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/types/connectivity_platform.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/types/process_life_cycle.dart';
import 'package:amplify_api_dart/src/util/amplify_api_config.dart';
import 'package:amplify_api_dart/src/util/amplify_authorization_rest_client.dart';
import 'package:amplify_core/amplify_core.dart';
Expand All @@ -30,8 +31,10 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable {
AmplifyAPIDart({
APIPluginOptions options = const APIPluginOptions(),
ConnectivityPlatform connectivity = const ConnectivityPlatform(),
ProcessLifeCycle processLifeCycle = const ProcessLifeCycle(),
}) : _options = options,
_connectivity = connectivity {
_connectivity = connectivity,
_processLifeCycle = processLifeCycle {
_options.authProviders.forEach(registerAuthProvider);
}

Expand All @@ -43,6 +46,9 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable {
/// Creates a stream representing network connectivity at the hardware level.
final ConnectivityPlatform _connectivity;

/// Creates a stream representing the process life cycle state.
final ProcessLifeCycle _processLifeCycle;

/// A map of the keys from the Amplify API config with auth modes to HTTP clients
/// to use for requests to that endpoint/auth mode. e.g. { "myEndpoint.AWS_IAM": AWSHttpClient}
final Map<String, AWSHttpClient> _clientPool = {};
Expand Down Expand Up @@ -277,6 +283,7 @@ class AmplifyAPIDart extends APIPluginInterface with AWSDebuggable {
wsService: AmplifyWebSocketService(),
subscriptionOptions: _options.subscriptionOptions,
connectivity: _connectivity,
processLifeCycle: _processLifeCycle,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:amplify_api_dart/src/graphql/web_socket/services/web_socket_serv
import 'package:amplify_api_dart/src/graphql/web_socket/state/web_socket_state.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/state/ws_subscriptions_state.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/types/connectivity_platform.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/types/process_life_cycle.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/types/subscriptions_event.dart';
import 'package:amplify_api_dart/src/graphql/web_socket/types/web_socket_types.dart';
import 'package:amplify_core/amplify_core.dart' hide SubscriptionEvent;
Expand All @@ -33,8 +34,10 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
required WebSocketService wsService,
required GraphQLSubscriptionOptions subscriptionOptions,
required ConnectivityPlatform connectivity,
required ProcessLifeCycle processLifeCycle,
AWSHttpClient? pollClientOverride,
}) : _connectivity = connectivity,
_processLifeCycle = processLifeCycle,
_pollClient = pollClientOverride ?? AWSHttpClient() {
final subBlocs = <String, SubscriptionBloc<Object?>>{};

Expand All @@ -49,6 +52,7 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
);
final blocStream = _wsEventStream.asyncExpand(_eventTransformer);
_networkSubscription = _getConnectivityStream();
_processLifeCycleSubscription = _getProcessLifecycleStream();
_stateSubscription = blocStream.listen(_emit);
add(const InitEvent());
}
Expand Down Expand Up @@ -81,10 +85,14 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
late final Stream<WebSocketEvent> _wsEventStream = _wsEventController.stream;
late final StreamSubscription<WebSocketState> _stateSubscription;
late final StreamSubscription<ConnectivityStatus> _networkSubscription;
late final StreamSubscription<ProcessStatus> _processLifeCycleSubscription;

/// Creates a stream representing network connectivity at the hardware level.
final ConnectivityPlatform _connectivity;

/// Creates a stream representing the process life cycle state.
final ProcessLifeCycle _processLifeCycle;

/// The underlying event stream, used only in testing.
@visibleForTesting
Stream<WebSocketEvent> get wsEventStream => _wsEventStream;
Expand Down Expand Up @@ -164,6 +172,8 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
yield* _networkLoss();
} else if (event is NetworkFoundEvent) {
yield* _networkFound();
} else if (event is ProcessResumeEvent) {
yield* _processResumed();
} else if (event is PollSuccessEvent) {
yield* _pollSuccess();
} else if (event is PollFailedEvent) {
Expand Down Expand Up @@ -328,6 +338,16 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
yield* const Stream.empty();
}

Stream<WebSocketState> _processResumed() async* {
final state = _currentState;
if (state is ConnectedState) {
yield state.reconnecting(networkState: NetworkState.disconnected);
add(const ReconnectEvent());
}
// TODO(dnys1): Yield broken on web debug build.
yield* const Stream.empty();
}

/// Handle successful polls
Stream<WebSocketState> _pollSuccess() async* {
// TODO(dnys1): Yield broken on web debug build.
Expand Down Expand Up @@ -467,6 +487,7 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
await Future.wait<void>([
// TODO(equartey): https://github.com/fluttercommunity/plus_plugins/issues/1382
if (!isWindows()) _networkSubscription.cancel(),
_processLifeCycleSubscription.cancel(),
Future.value(_pollClient.close()),
_stateSubscription.cancel(),
_wsEventController.close(),
Expand Down Expand Up @@ -507,6 +528,41 @@ class WebSocketBloc with AWSDebuggable, AmplifyLoggerMixin {
);
}

/// Process life cycle stream monitors when the process resumes from a paused state.
StreamSubscription<ProcessStatus> _getProcessLifecycleStream() {
var prev = ProcessStatus.detached;
return _processLifeCycle.onStateChanged.listen(
(state) {
if (_isResuming(state, prev)) {
// ignore: invalid_use_of_internal_member
if (!WebSocketOptions.autoReconnect) {
_shutdownWithException(
const NetworkException(
'Unable to recover network connection, web socket will close.',
recoverySuggestion: 'Avoid pausing the process.',
),
StackTrace.current,
);
} else {
add(const ProcessResumeEvent());
}
}

prev = state;
},
onError: (Object e, StackTrace st) =>
logger.error('Error in process life cycle stream $e, $st'),
);
}

bool _isResuming(ProcessStatus current, ProcessStatus previous) {
if (previous != ProcessStatus.paused) return false;

return current == ProcessStatus.hidden ||
current == ProcessStatus.inactive ||
current == ProcessStatus.resumed;
}

Future<void> _poll() async {
try {
final res = await _sendPollRequest();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

/// Possible process life cycle states
enum ProcessStatus {
/// Engine is running without a view.
detached,

/// Application is not visible to the user or responding to user input.
paused,

/// All views of an application are hidden.
hidden,

/// A view of the application is visible, but none have input.
inactive,

/// Default running mode.
resumed,
}

/// {@template amplify_api_dart.process_life_cycle}
/// Used to create a stream representing the process life cycle state.
///
/// The generated stream is empty.
/// {@endtemplate}
class ProcessLifeCycle {
/// {@macro amplify_api_dart.process_life_cycle}
const ProcessLifeCycle();

/// Generates a new stream of [ProcessStatus].
Stream<ProcessStatus> get onStateChanged => const Stream.empty();
}
Loading

0 comments on commit 3b9cc90

Please sign in to comment.