From 80dee5142a9f1514649ea5613b2f1022b6311c1a Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Mon, 21 Apr 2025 18:53:45 +0500 Subject: [PATCH 1/8] Implement GetLocationAction for location retrieval and update context with location data. Remove deprecated location handling from ScreenController. --- .../ensemble/lib/action/action_invokable.dart | 1 + modules/ensemble/lib/action/getLocation.dart | 102 ++++++++++++++++++ modules/ensemble/lib/framework/action.dart | 24 +---- modules/ensemble/lib/screen_controller.dart | 67 ------------ 4 files changed, 105 insertions(+), 89 deletions(-) create mode 100644 modules/ensemble/lib/action/getLocation.dart diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index 815c88051..0f6bec851 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -44,6 +44,7 @@ abstract class ActionInvokable with Invokable { ActionType.saveFile, ActionType.controlDeviceBackNavigation, ActionType.closeApp, + ActionType.getLocation, ]); } diff --git a/modules/ensemble/lib/action/getLocation.dart b/modules/ensemble/lib/action/getLocation.dart new file mode 100644 index 000000000..39d7f3ce9 --- /dev/null +++ b/modules/ensemble/lib/action/getLocation.dart @@ -0,0 +1,102 @@ +import 'dart:async'; +import 'package:ensemble/framework/action.dart'; +import 'package:ensemble/framework/device.dart'; +import 'package:ensemble/framework/error_handling.dart'; +import 'package:ensemble/framework/scope.dart'; +import 'package:ensemble/framework/stub/location_manager.dart'; +import 'package:ensemble/screen_controller.dart'; +import 'package:ensemble/util/utils.dart'; +import 'package:ensemble_ts_interpreter/invokables/invokable.dart'; +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; + +class GetLocationAction extends EnsembleAction { + GetLocationAction({ + super.initiator, + this.onLocationReceived, + this.onError, + this.recurring, + this.recurringDistanceFilter, + }); + + final EnsembleAction? onLocationReceived; + final EnsembleAction? onError; + final bool? recurring; + final int? recurringDistanceFilter; + + factory GetLocationAction.fromYaml({Invokable? initiator, Map? payload}) { + return GetLocationAction( + initiator: initiator, + onLocationReceived: EnsembleAction.from(payload?['onLocationReceived']), + onError: EnsembleAction.from(payload?['onError']), + recurring: Utils.optionalBool(payload?['options']?['recurring']), + recurringDistanceFilter: Utils.optionalInt( + payload?['options']?['recurringDistanceFilter'], + min: 50), + ); + } + + @override + Future execute(BuildContext context, ScopeManager scopeManager) async { + if (onLocationReceived == null) { + throw LanguageError( + '${ActionType.getLocation.name} requires onLocationReceived callback'); + } + + try { + final status = await GetIt.I().getLocationStatus(); + + if (status == LocationStatus.ready) { + // Handle recurring location updates + if (recurring == true) { + StreamSubscription streamSubscription = + GetIt.I() + .getPositionStream( + distanceFilter: recurringDistanceFilter ?? 1000) + .map((position) => LocationData( + latitude: position.latitude, + longitude: position.longitude)) + .listen((LocationData? location) { + if (location != null) { + // Update last known location + Device().updateLastLocation(location); + + // Add location data to context and execute callback + scopeManager.dataContext + .addDataContextById('latitude', location.latitude); + scopeManager.dataContext + .addDataContextById('longitude', location.longitude); + ScreenController().executeAction(context, onLocationReceived!); + } else if (onError != null) { + scopeManager.dataContext.addDataContextById('reason', 'unknown'); + ScreenController().executeAction(context, onError!); + } + }); + scopeManager.addLocationListener(streamSubscription); + } + // Handle one-time location request + else { + final location = await GetIt.I().simplyGetLocation(); + if (location != null) { + Device().updateLastLocation(location); + scopeManager.dataContext + .addDataContextById('latitude', location.latitude); + scopeManager.dataContext + .addDataContextById('longitude', location.longitude); + ScreenController().executeAction(context, onLocationReceived!); + } + } + } else if (onError != null) { + scopeManager.dataContext.addDataContextById('reason', status.name); + ScreenController().executeAction(context, onError!); + } + } catch (e) { + if (onError != null) { + scopeManager.dataContext.addDataContextById('reason', e.toString()); + ScreenController().executeAction(context, onError!); + } else { + rethrow; + } + } + } +} diff --git a/modules/ensemble/lib/framework/action.dart b/modules/ensemble/lib/framework/action.dart index 22c6dba08..74bca0f59 100644 --- a/modules/ensemble/lib/framework/action.dart +++ b/modules/ensemble/lib/framework/action.dart @@ -27,6 +27,7 @@ import 'package:ensemble/action/toast_actions.dart'; import 'package:ensemble/action/take_screenshot.dart'; import 'package:ensemble/action/disable_hardware_navigation.dart'; import 'package:ensemble/action/close_app.dart'; +import 'package:ensemble/action/getLocation.dart'; import 'package:ensemble/ensemble.dart'; import 'package:ensemble/framework/data_context.dart'; import 'package:ensemble/framework/error_handling.dart'; @@ -571,20 +572,6 @@ class OpenUrlAction extends EnsembleAction { OpenUrlAction.fromYaml(payload: Utils.getYamlMap(inputs)); } -class GetLocationAction extends EnsembleAction { - GetLocationAction( - {this.onLocationReceived, - this.onError, - this.recurring, - this.recurringDistanceFilter}); - - EnsembleAction? onLocationReceived; - EnsembleAction? onError; - - bool? recurring; - int? recurringDistanceFilter; -} - enum FileSource { gallery, files } class FilePickerAction extends EnsembleAction { @@ -1182,14 +1169,7 @@ abstract class EnsembleAction { } else if (actionType == ActionType.executeCode) { return ExecuteCodeAction.fromYaml(initiator: initiator, payload: payload); } else if (actionType == ActionType.getLocation) { - return GetLocationAction( - onLocationReceived: - EnsembleAction.from(payload?['onLocationReceived']), - onError: EnsembleAction.from(payload?['onError']), - recurring: Utils.optionalBool(payload?['options']?['recurring']), - recurringDistanceFilter: Utils.optionalInt( - payload?['options']?['recurringDistanceFilter'], - min: 50)); + return GetLocationAction.fromYaml(initiator: initiator, payload: payload); } else if (actionType == ActionType.pickFiles) { return FilePickerAction.fromYaml(payload: payload); } else if (actionType == ActionType.uploadFiles) { diff --git a/modules/ensemble/lib/screen_controller.dart b/modules/ensemble/lib/screen_controller.dart index 17e741c3b..b97436e17 100644 --- a/modules/ensemble/lib/screen_controller.dart +++ b/modules/ensemble/lib/screen_controller.dart @@ -367,9 +367,6 @@ class ScreenController { debugPrint( 'error when trying to stop timer with name ${action.id}. Error: ${e.toString()}'); } - } else if (action is GetLocationAction) { - executeGetLocationAction( - scopeManager, scopeManager.dataContext, context, action); } else if (action is ExecuteCodeAction) { action.inputs?.forEach((key, value) { dynamic val = scopeManager.dataContext.eval(value); @@ -697,70 +694,6 @@ class ScreenController { APIProviders.clone(Ensemble().getConfig()!.apiProviders ?? {})); } - void executeGetLocationAction(ScopeManager scopeManager, - DataContext dataContext, BuildContext context, GetLocationAction action) { - if (action.onLocationReceived != null) { - GetIt.I() - .getLocationStatus() - .then((LocationStatus status) async { - if (status == LocationStatus.ready) { - // if recurring - if (action.recurring == true) { - StreamSubscription streamSubscription = - GetIt.I() - .getPositionStream( - distanceFilter: action.recurringDistanceFilter ?? 1000) - .map((position) => LocationData( - latitude: position.latitude, - longitude: position.longitude)) - .listen((LocationData? location) { - if (location != null) { - // update last location. TODO: consolidate this - Device().updateLastLocation(location); - - _onLocationReceived(scopeManager, dataContext, context, - action.onLocationReceived!, location); - } else if (action.onError != null) { - DataContext localizedContext = dataContext.clone(); - localizedContext.addDataContextById('reason', 'unknown'); - nowExecuteAction(context, action.onError!, - scopeManager.pageData.apiMap, scopeManager); - } - }); - scopeManager.addLocationListener(streamSubscription); - } - // one-time get location - else { - _onLocationReceived( - scopeManager, - dataContext, - context, - action.onLocationReceived!, - await GetIt.I().simplyGetLocation()); - } - } else if (action.onError != null) { - DataContext localizedContext = dataContext.clone(); - localizedContext.addDataContextById('reason', status.name); - nowExecuteAction(context, action.onError!, - scopeManager.pageData.apiMap, scopeManager); - } - }); - } - } - - void _onLocationReceived( - ScopeManager scopeManager, - DataContext dataContext, - BuildContext context, - EnsembleAction onLocationReceived, - LocationData location) { - scopeManager.dataContext.addDataContextById('latitude', location.latitude); - scopeManager.dataContext - .addDataContextById('longitude', location.longitude); - nowExecuteAction(context, onLocationReceived, scopeManager.pageData.apiMap, - scopeManager); - } - /// return a wrapper for the screen widget /// with custom animation for different pageType PageRouteBuilder getScreenBuilder( From a0eaa1de5f46ec116fb98283819acd26098658c8 Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Mon, 21 Apr 2025 23:44:49 +0500 Subject: [PATCH 2/8] Add FilePickerAction for file selection functionality - Introduced FilePickerAction to handle file selection from gallery or files. - Updated ScreenController to remove deprecated file manager references. - Registered FilePickerAction in ActionInvokable for action handling. - Adjusted imports in relevant files to integrate the new action. --- .../ensemble/lib/action/action_invokable.dart | 1 + .../lib/action/file_picker_action.dart | 72 +++++++++++++++++++ modules/ensemble/lib/framework/action.dart | 50 +------------ .../lib/framework/stub/file_manager.dart | 2 +- modules/ensemble/lib/screen_controller.dart | 4 -- modules/file_manager/lib/file_manager.dart | 2 +- 6 files changed, 76 insertions(+), 55 deletions(-) create mode 100644 modules/ensemble/lib/action/file_picker_action.dart diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index 0f6bec851..a330acc45 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -45,6 +45,7 @@ abstract class ActionInvokable with Invokable { ActionType.controlDeviceBackNavigation, ActionType.closeApp, ActionType.getLocation, + ActionType.pickFiles, ]); } diff --git a/modules/ensemble/lib/action/file_picker_action.dart b/modules/ensemble/lib/action/file_picker_action.dart new file mode 100644 index 000000000..a094a3adc --- /dev/null +++ b/modules/ensemble/lib/action/file_picker_action.dart @@ -0,0 +1,72 @@ +import 'package:ensemble/framework/action.dart'; +import 'package:ensemble/framework/error_handling.dart'; +import 'package:ensemble/framework/scope.dart'; +import 'package:ensemble/framework/stub/file_manager.dart'; +import 'package:ensemble/screen_controller.dart'; +import 'package:ensemble/util/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:yaml/yaml.dart'; +import 'package:ensemble/framework/event.dart'; +import 'package:flutter/cupertino.dart'; + +enum FileSource { gallery, files } + +class FilePickerAction extends EnsembleAction { + FilePickerAction({ + required this.id, + this.allowedExtensions, + this.allowMultiple, + this.allowCompression, + this.onComplete, + this.onError, + this.source, + }); + + String id; + List? allowedExtensions; + bool? allowMultiple; + bool? allowCompression; + EnsembleAction? onComplete; + EnsembleAction? onError; + FileSource? source; + + factory FilePickerAction.fromYaml({Map? payload}) { + if (payload == null || payload['id'] == null) { + throw LanguageError("${ActionType.pickFiles.name} requires 'id'."); + } + + FileSource? getSource(String? source) { + if (source == 'gallery') { + return FileSource.gallery; + } + if (source == 'files') { + return FileSource.files; + } + return null; + } + + return FilePickerAction( + id: Utils.getString(payload['id'], fallback: ''), + allowedExtensions: + (payload['allowedExtensions'] as YamlList?)?.cast().toList(), + allowMultiple: Utils.optionalBool(payload['allowMultiple']), + allowCompression: Utils.optionalBool(payload['allowCompression']), + onComplete: EnsembleAction.from(payload['onComplete']), + onError: EnsembleAction.from(payload['onError']), + source: getSource(payload['source']), + ); + } + + @override + Future execute(BuildContext context, ScopeManager scopeManager) async { + try { + await GetIt.I().pickFiles(context, this, scopeManager); + } catch (e) { + if (onError != null) { + await ScreenController().executeAction(context, onError!, + event: EnsembleEvent(null, error: e.toString())); + } + } + } +} diff --git a/modules/ensemble/lib/framework/action.dart b/modules/ensemble/lib/framework/action.dart index 74bca0f59..65afab1c2 100644 --- a/modules/ensemble/lib/framework/action.dart +++ b/modules/ensemble/lib/framework/action.dart @@ -10,6 +10,7 @@ import 'package:ensemble/action/device_security.dart'; import 'package:ensemble/action/dialog_actions.dart'; import 'package:ensemble/action/drawer_actions.dart'; import 'package:ensemble/action/execute_action_group_action.dart'; +import 'package:ensemble/action/file_picker_action.dart'; import 'package:ensemble/action/get_network_info_action.dart'; import 'package:ensemble/action/haptic_action.dart'; import 'package:ensemble/action/call_native_method.dart'; @@ -572,55 +573,6 @@ class OpenUrlAction extends EnsembleAction { OpenUrlAction.fromYaml(payload: Utils.getYamlMap(inputs)); } -enum FileSource { gallery, files } - -class FilePickerAction extends EnsembleAction { - FilePickerAction({ - required this.id, - this.allowedExtensions, - this.allowMultiple, - this.allowCompression, - this.onComplete, - this.onError, - this.source, - }); - - String id; - List? allowedExtensions; - bool? allowMultiple; - bool? allowCompression; - EnsembleAction? onComplete; - EnsembleAction? onError; - FileSource? source; - - factory FilePickerAction.fromYaml({Map? payload}) { - if (payload == null || payload['id'] == null) { - throw LanguageError("${ActionType.pickFiles.name} requires 'id'."); - } - - FileSource? getSource(String? source) { - if (source == 'gallery') { - return FileSource.gallery; - } - if (source == 'files') { - return FileSource.files; - } - return null; - } - - return FilePickerAction( - id: Utils.getString(payload['id'], fallback: ''), - allowedExtensions: - (payload['allowedExtensions'] as YamlList?)?.cast().toList(), - allowMultiple: Utils.optionalBool(payload['allowMultiple']), - allowCompression: Utils.optionalBool(payload['allowCompression']), - onComplete: EnsembleAction.from(payload['onComplete']), - onError: EnsembleAction.from(payload['onError']), - source: getSource(payload['source']), - ); - } -} - class FileUploadAction extends EnsembleAction { FileUploadAction({ super.inputs, diff --git a/modules/ensemble/lib/framework/stub/file_manager.dart b/modules/ensemble/lib/framework/stub/file_manager.dart index 459262a08..e6bedc8c8 100644 --- a/modules/ensemble/lib/framework/stub/file_manager.dart +++ b/modules/ensemble/lib/framework/stub/file_manager.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; -import 'package:ensemble/framework/action.dart'; +import 'package:ensemble/action/file_picker_action.dart'; import 'package:ensemble/framework/error_handling.dart'; import 'package:ensemble/framework/scope.dart'; import 'package:flutter/cupertino.dart'; diff --git a/modules/ensemble/lib/screen_controller.dart b/modules/ensemble/lib/screen_controller.dart index b97436e17..cdb1aa192 100644 --- a/modules/ensemble/lib/screen_controller.dart +++ b/modules/ensemble/lib/screen_controller.dart @@ -21,8 +21,6 @@ import 'package:ensemble/framework/permissions_manager.dart'; import 'package:ensemble/framework/scope.dart'; import 'package:ensemble/framework/stub/camera_manager.dart'; import 'package:ensemble/framework/stub/contacts_manager.dart'; -import 'package:ensemble/framework/stub/file_manager.dart'; -import 'package:ensemble/framework/stub/location_manager.dart'; import 'package:ensemble/framework/stub/plaid_link_manager.dart'; import 'package:ensemble/framework/theme/theme_loader.dart'; import 'package:ensemble/framework/view/data_scope_widget.dart'; @@ -398,8 +396,6 @@ class ScreenController { dataContext: scopeManager.dataContext, apiMap: apiMap, scopeManager: scopeManager); - } else if (action is FilePickerAction) { - GetIt.I().pickFiles(context, action, scopeManager); } else if (action is SignInAnonymousAction) { GetIt.I().signInAnonymously(context, action: action); } else if (action is SignInWithCustomTokenAction) { diff --git a/modules/file_manager/lib/file_manager.dart b/modules/file_manager/lib/file_manager.dart index 1877cf2c2..92d7d945a 100644 --- a/modules/file_manager/lib/file_manager.dart +++ b/modules/file_manager/lib/file_manager.dart @@ -2,7 +2,7 @@ library ensemble_file_manager; import 'dart:typed_data'; -import 'package:ensemble/framework/action.dart'; +import 'package:ensemble/action/file_picker_action.dart'; import 'package:ensemble/framework/bindings.dart'; import 'package:ensemble/framework/data_context.dart'; import 'package:ensemble/framework/stub/file_manager.dart'; From 0db8e85af03ec8275b1d30137789230518a2dedd Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Thu, 24 Apr 2025 21:17:59 +0500 Subject: [PATCH 3/8] feat: implement PlaidLinkAction execution logic - Added execution logic for PlaidLinkAction in the action framework. - Removed deprecated PlaidLink handling from ScreenController. - Updated ActionInvokable to include ActionType.openPlaidLink. - Introduced error handling for Plaid link opening process. --- .../ensemble/lib/action/action_invokable.dart | 1 + modules/ensemble/lib/framework/action.dart | 58 +++++++++++++++++++ modules/ensemble/lib/screen_controller.dart | 49 ---------------- 3 files changed, 59 insertions(+), 49 deletions(-) diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index a330acc45..ece3bb56c 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -46,6 +46,7 @@ abstract class ActionInvokable with Invokable { ActionType.closeApp, ActionType.getLocation, ActionType.pickFiles, + ActionType.openPlaidLink, ]); } diff --git a/modules/ensemble/lib/framework/action.dart b/modules/ensemble/lib/framework/action.dart index 65afab1c2..b967070fb 100644 --- a/modules/ensemble/lib/framework/action.dart +++ b/modules/ensemble/lib/framework/action.dart @@ -37,6 +37,7 @@ import 'package:ensemble/framework/extensions.dart'; import 'package:ensemble/framework/keychain_manager.dart'; import 'package:ensemble/framework/permissions_manager.dart'; import 'package:ensemble/framework/scope.dart'; +import 'package:ensemble/framework/stub/plaid_link_manager.dart'; import 'package:ensemble/framework/view/page_group.dart'; import 'package:ensemble/framework/widget/view_util.dart'; import 'package:ensemble/receive_intent_manager.dart'; @@ -48,6 +49,7 @@ import 'package:ensemble_ts_interpreter/invokables/invokable.dart'; import 'package:flutter/material.dart'; import 'package:source_span/source_span.dart'; import 'package:yaml/yaml.dart'; +import 'package:get_it/get_it.dart'; class ShowCameraAction extends EnsembleAction { ShowCameraAction({ @@ -256,6 +258,62 @@ class PlaidLinkAction extends EnsembleAction { onExit: EnsembleAction.from(payload['onExit']), ); } + + @override + Future execute(BuildContext context, ScopeManager scopeManager) async { + final linkToken = getLinkToken(scopeManager.dataContext).trim(); + if (linkToken.isNotEmpty) { + try { + GetIt.I().openPlaidLink( + linkToken, + (linkSuccess) { + if (onSuccess != null) { + ScreenController().executeActionWithScope( + context, + scopeManager, + onSuccess!, + event: EnsembleEvent( + initiator, + data: linkSuccess, + ), + ); + } + }, + (linkEvent) { + if (onEvent != null) { + ScreenController().executeActionWithScope( + context, + scopeManager, + onEvent!, + event: EnsembleEvent( + initiator, + data: linkEvent, + ), + ); + } + }, + (linkExit) { + if (onExit != null) { + ScreenController().executeActionWithScope( + context, + scopeManager, + onExit!, + event: EnsembleEvent( + initiator, + data: linkExit, + ), + ); + } + }, + ); + } catch (e) { + throw ConfigError("Error opening Plaid link: $e"); + } + } else { + throw RuntimeError( + "openPlaidLink action requires the plaid's link_token."); + } + } } class ReceiveIntentAction extends EnsembleAction { diff --git a/modules/ensemble/lib/screen_controller.dart b/modules/ensemble/lib/screen_controller.dart index cdb1aa192..a2c5bbc3a 100644 --- a/modules/ensemble/lib/screen_controller.dart +++ b/modules/ensemble/lib/screen_controller.dart @@ -252,55 +252,6 @@ class ScreenController { executeActionWithScope(context, scopeManager, action.onModalDismiss!); }); } - } else if (action is PlaidLinkAction) { - final linkToken = action.getLinkToken(scopeManager.dataContext).trim(); - if (linkToken.isNotEmpty) { - GetIt.I().openPlaidLink( - linkToken, - (linkSuccess) { - if (action.onSuccess != null) { - executeActionWithScope( - context, - scopeManager, - action.onSuccess!, - event: EnsembleEvent( - action.initiator, - data: linkSuccess, - ), - ); - } - }, - (linkEvent) { - if (action.onEvent != null) { - executeActionWithScope( - context, - scopeManager, - action.onEvent!, - event: EnsembleEvent( - action.initiator, - data: linkEvent, - ), - ); - } - }, - (linkExit) { - if (action.onExit != null) { - executeActionWithScope( - context, - scopeManager, - action.onExit!, - event: EnsembleEvent( - action.initiator, - data: linkExit, - ), - ); - } - }, - ); - } else { - throw RuntimeError( - "openPlaidLink action requires the plaid's link_token."); - } } else if (action is ShowCameraAction) { GetIt.I().openCamera(context, action, scopeManager); } else if (action is StartTimerAction) { From 71c987631dbc0d82f1f206e8607cc9abc5a5df34 Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Fri, 25 Apr 2025 18:00:05 +0500 Subject: [PATCH 4/8] feat: add new action types for badge management - Updated ActionInvokable to include ActionType.updateBadgeCount and ActionType.clearBadgeCount. - These additions enhance the action framework's capabilities for managing badge counts. --- modules/ensemble/lib/action/action_invokable.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index ece3bb56c..90c007377 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -47,6 +47,8 @@ abstract class ActionInvokable with Invokable { ActionType.getLocation, ActionType.pickFiles, ActionType.openPlaidLink, + ActionType.updateBadgeCount, + ActionType.clearBadgeCount, ]); } From c7091665da2b933cab6aca8161c46ca16760c621 Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Tue, 29 Apr 2025 16:35:38 +0500 Subject: [PATCH 5/8] fix: add ActionType.getNetworkInfo to ActionInvokable --- modules/ensemble/lib/action/action_invokable.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index 90c007377..2eef4eff9 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -49,6 +49,7 @@ abstract class ActionInvokable with Invokable { ActionType.openPlaidLink, ActionType.updateBadgeCount, ActionType.clearBadgeCount, + ActionType.getNetworkInfo, ]); } From b0af7e406e5504dc45443091a9657723242f363c Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Tue, 29 Apr 2025 16:56:51 +0500 Subject: [PATCH 6/8] fix: CheckPermission action execution logic - Added execution logic for CheckPermission in the action framework. - Updated ScreenController to remove deprecated permission handling. - Included CheckPermission in ActionType within ActionInvokable. --- .../ensemble/lib/action/action_invokable.dart | 1 + modules/ensemble/lib/framework/action.dart | 29 +++++++++++++++++++ modules/ensemble/lib/screen_controller.dart | 19 ------------ 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index 2eef4eff9..04f1db49c 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -50,6 +50,7 @@ abstract class ActionInvokable with Invokable { ActionType.updateBadgeCount, ActionType.clearBadgeCount, ActionType.getNetworkInfo, + ActionType.checkPermission, ]); } diff --git a/modules/ensemble/lib/framework/action.dart b/modules/ensemble/lib/framework/action.dart index b967070fb..168bdf178 100644 --- a/modules/ensemble/lib/framework/action.dart +++ b/modules/ensemble/lib/framework/action.dart @@ -854,6 +854,35 @@ class CheckPermission extends EnsembleAction { onNotDetermined: EnsembleAction.from(payload['onNotDetermined']), ); } + + @override + Future execute(BuildContext context, ScopeManager scopeManager) async { + Permission? type = getType(scopeManager.dataContext); + if (type == null) { + throw RuntimeError('checkPermission requires a type.'); + } + + bool? result = await PermissionsManager().hasPermission(type); + + if (result == true) { + if (onAuthorized != null) { + return ScreenController() + .executeActionWithScope(context, scopeManager, onAuthorized!); + } + } else if (result == false) { + if (onDenied != null) { + return ScreenController() + .executeActionWithScope(context, scopeManager, onDenied!); + } + } else { + if (onNotDetermined != null) { + return ScreenController() + .executeActionWithScope(context, scopeManager, onNotDetermined!); + } + } + + return Future.value(null); + } } class SaveKeychain extends EnsembleAction { diff --git a/modules/ensemble/lib/screen_controller.dart b/modules/ensemble/lib/screen_controller.dart index a2c5bbc3a..e1cb217ce 100644 --- a/modules/ensemble/lib/screen_controller.dart +++ b/modules/ensemble/lib/screen_controller.dart @@ -417,25 +417,6 @@ class ScreenController { notificationUtils.onRemoteNotificationOpened = action.onTap; } else if (action is AuthorizeOAuthAction) { // TODO - } else if (action is CheckPermission) { - Permission? type = action.getType(scopeManager.dataContext); - if (type == null) { - throw RuntimeError('checkPermission requires a type.'); - } - bool? result = await PermissionsManager().hasPermission(type); - if (result == true) { - if (action.onAuthorized != null) { - executeAction(context, action.onAuthorized!); - } - } else if (result == false) { - if (action.onDenied != null) { - executeAction(context, action.onDenied!); - } - } else { - if (action.onNotDetermined != null) { - executeAction(context, action.onNotDetermined!); - } - } } else if (action is ConnectSocketAction) { dynamic resolveURI(String uri) { final result = scopeManager.dataContext.eval(uri); From fe94ae21627c8460028860a8452b71dd99c18cf6 Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Tue, 29 Apr 2025 17:07:14 +0500 Subject: [PATCH 7/8] fix: firebase phone auth actions invokable - Included ActionType.sendVerificationCode, ActionType.validateVerificationCode, and ActionType.resendVerificationCode in ActionInvokable. - These additions enhance the action framework's capabilities for user verification. --- modules/ensemble/lib/action/action_invokable.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index 04f1db49c..cf2117c3c 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -51,6 +51,9 @@ abstract class ActionInvokable with Invokable { ActionType.clearBadgeCount, ActionType.getNetworkInfo, ActionType.checkPermission, + ActionType.sendVerificationCode, + ActionType.validateVerificationCode, + ActionType.resendVerificationCode, ]); } From 8e662847ced9033b8cdbffebfec14dcb98e55f18 Mon Sep 17 00:00:00 2001 From: Sharjeel Yunus Date: Tue, 29 Apr 2025 17:14:14 +0500 Subject: [PATCH 8/8] fix: add Bluetooth action types to ActionInvokable - Included ActionType.bluetoothStartScan, ActionType.bluetoothConnect, ActionType.bluetoothDisconnect, ActionType.bluetoothSubscribeCharacteristic, and ActionType.bluetoothUnsubscribeCharacteristic in ActionInvokable. - These additions enhance the action framework's capabilities for Bluetooth interactions. --- modules/ensemble/lib/action/action_invokable.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/ensemble/lib/action/action_invokable.dart b/modules/ensemble/lib/action/action_invokable.dart index cf2117c3c..c9e901176 100644 --- a/modules/ensemble/lib/action/action_invokable.dart +++ b/modules/ensemble/lib/action/action_invokable.dart @@ -54,6 +54,11 @@ abstract class ActionInvokable with Invokable { ActionType.sendVerificationCode, ActionType.validateVerificationCode, ActionType.resendVerificationCode, + ActionType.bluetoothStartScan, + ActionType.bluetoothConnect, + ActionType.bluetoothDisconnect, + ActionType.bluetoothSubscribeCharacteristic, + ActionType.bluetoothUnsubscribeCharacteristic, ]); }