Skip to content

Commit

Permalink
Merge branch 'main' into feat/calendar
Browse files Browse the repository at this point in the history
  • Loading branch information
snehmehta authored Oct 24, 2023
2 parents cf19495 + 610bbe7 commit 1b57183
Show file tree
Hide file tree
Showing 22 changed files with 675 additions and 346 deletions.
32 changes: 31 additions & 1 deletion assets/schema/ensemble_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2870,8 +2870,13 @@
"type": "boolean",
"description": "Moves the label on top of the Input Field. Default (False)."
},
"floatingLabelStyle": {
"$ref": "#/$defs/TextStyle",
"description": "Set the label's styles when it is in floating mode"
},
"labelStyle": {
"$ref": "#/$defs/TextStyle"
"$ref": "#/$defs/TextStyle",
"description": "Set the label's styles"
}
}
}
Expand Down Expand Up @@ -4257,6 +4262,10 @@
"items"
],
"properties": {
"reloadView": {
"type": "boolean",
"description": "It will reload the page each time when clicking the menu item"
},
"items": {
"type": "array",
"description": "List of menu items (minimum 2)",
Expand Down Expand Up @@ -4320,9 +4329,26 @@
"floatingIconColor": {
"$ref": "#/$defs/typeColors",
"description": "Floating item icon color, starting with '0xFF' for full opacity e.g 0xFFCCCCCC"
},
"height": {
"type": "integer",
"description": "Set the height of the BottomNavBar."
},
"padding": {
"$ref": "#/$defs/Padding-payload"
},
"margin": {
"$ref": "#/$defs/Margin-payload"
},
"borderRadius": {
"$ref": "#/$defs/borderRadius"
}
}
},
"reloadView": {
"type": "boolean",
"description": "It will reload the page each time when clicking the menu item"
},
"items": {
"type": "array",
"description": "List of menu items (minimum 2)",
Expand Down Expand Up @@ -4412,6 +4438,10 @@
},
{
"properties": {
"reloadView": {
"type": "boolean",
"description": "It will reload the page each time when clicking the menu item"
},
"styles": {
"properties": {
"borderColor": {
Expand Down
47 changes: 47 additions & 0 deletions lib/action/action_invokable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:ensemble/action/call_external_method.dart';
import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:ensemble/framework/scope.dart';
import 'package:ensemble/screen_controller.dart';
import 'package:ensemble_ts_interpreter/invokables/invokable.dart';
import 'package:flutter/cupertino.dart';

/// expose Ensemble Actions as Invokables
abstract class ActionInvokable with Invokable {
ActionInvokable(this.buildContext);
final BuildContext buildContext;

@override
Map<String, Function> methods() {
return _generateFromActionTypes([
ActionType.callExternalMethod,
ActionType.share,
ActionType.rateApp,
ActionType.copyToClipboard,
ActionType.getDeviceToken
]);
}

Map<String, Function> _generateFromActionTypes(List<ActionType> actionTypes) {
Map<String, Function> functions = {};
for (ActionType actionType in actionTypes) {
functions[actionType.name] = (payload) {
if (payload != null && payload is! Map) {
throw LanguageError("${actionType.name} has an invalid payload.");
}
EnsembleAction? action = EnsembleAction.fromActionType(
actionType, payload: payload);
return action?.execute(buildContext, _getScopeManager(buildContext));
};
}
return functions;
}

ScopeManager _getScopeManager(BuildContext context) {
ScopeManager? scopeManager = ScreenController().getScopeManager(context);
if (scopeManager == null) {
throw LanguageError("Cannot look up ScopeManager");
}
return scopeManager;
}
}
7 changes: 5 additions & 2 deletions lib/action/badge_action.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/data_context.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:ensemble/framework/scope.dart';
import 'package:ensemble/util/utils.dart';
Expand All @@ -19,7 +20,8 @@ class UpdateBadgeCount extends EnsembleAction {
}

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
int? count = Utils.optionalInt(scopeManager.dataContext.eval(_count));
if (count != null) {
return FlutterAppBadger.updateBadgeCount(count);
Expand All @@ -30,7 +32,8 @@ class UpdateBadgeCount extends EnsembleAction {

class ClearBadgeCount extends EnsembleAction {
@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
return FlutterAppBadger.removeBadge();
}
}
7 changes: 5 additions & 2 deletions lib/action/bottom_modal_action.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:ui';

import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/data_context.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:ensemble/framework/event.dart';
import 'package:ensemble/framework/scope.dart';
Expand Down Expand Up @@ -59,7 +60,8 @@ class ShowBottomModalAction extends EnsembleAction {
}

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
Widget? widget;
if (body != null) {
widget = scopeManager.buildWidgetFromDefinition(body);
Expand Down Expand Up @@ -96,7 +98,8 @@ class DismissBottomModalAction extends EnsembleAction {
DismissBottomModalAction(payload: payload?['payload']);

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
BuildContext? bottomModalContext =
ContextScopeWidget.getRootContext(context);
if (bottomModalContext != null) {
Expand Down
4 changes: 3 additions & 1 deletion lib/action/call_external_method.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:developer';

import 'package:ensemble/ensemble.dart';
import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/data_context.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:ensemble/framework/event.dart';
import 'package:ensemble/framework/scope.dart';
Expand Down Expand Up @@ -32,7 +33,8 @@ class CallExternalMethod extends EnsembleAction {
}

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) async {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) async {
String? name = Utils.optionalString(scopeManager.dataContext.eval(_name));

String? errorReason;
Expand Down
46 changes: 46 additions & 0 deletions lib/action/invoke_api_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,52 @@ import 'package:flutter/cupertino.dart';
import 'package:yaml/yaml.dart';
import 'package:http/http.dart' as http;

class InvokeAPIAction extends EnsembleAction {
InvokeAPIAction(
{Invokable? initiator,
required this.apiName,
this.id,
Map<String, dynamic>? inputs,
this.onResponse,
this.onError})
: super(initiator: initiator, inputs: inputs);

String? id;
final String apiName;
EnsembleAction? onResponse;
EnsembleAction? onError;

factory InvokeAPIAction.fromYaml({Invokable? initiator, Map? payload}) {
if (payload == null || payload['name'] == null) {
throw LanguageError(
"${ActionType.invokeAPI.name} requires the 'name' of the API.");
}

return InvokeAPIAction(
initiator: initiator,
apiName: payload['name'],
id: Utils.optionalString(payload['id']),
inputs: Utils.getMap(payload['inputs']),
onResponse: EnsembleAction.fromYaml(payload['onResponse'],
initiator: initiator),
onError:
EnsembleAction.fromYaml(payload['onError'], initiator: initiator));
}

@override
Future execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
DataContext realDataContext = dataContext ?? scopeManager.dataContext;
var evalApiName = realDataContext.eval(apiName);
var cloneAction = InvokeAPIAction(apiName: evalApiName, initiator: initiator, id: id, inputs: inputs, onResponse: onResponse, onError: onError);
return InvokeAPIController()
.execute(cloneAction, context, realDataContext, scopeManager,
scopeManager.pageData.apiMap);
}
}



class InvokeAPIController {
Future<Response?> executeWithContext(
BuildContext context, InvokeAPIAction action,
Expand Down
108 changes: 108 additions & 0 deletions lib/action/misc_action.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'dart:io';

import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/data_context.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:ensemble/framework/event.dart';
import 'package:ensemble/framework/scope.dart';
import 'package:ensemble/screen_controller.dart';
import 'package:ensemble/util/utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:rate_my_app/rate_my_app.dart';
import 'package:share_plus/share_plus.dart';

class CopyToClipboardAction extends EnsembleAction {
CopyToClipboardAction(this._value,
{super.initiator, this.onSuccess, this.onFailure});

dynamic _value;
EnsembleAction? onSuccess;
EnsembleAction? onFailure;

factory CopyToClipboardAction.from({Map? payload}) {
if (payload == null || payload['value'] == null) {
throw LanguageError(
'${ActionType.copyToClipboard.name} requires the value.');
}
return CopyToClipboardAction(
payload['value'],
onSuccess: EnsembleAction.fromYaml(payload['onSuccess']),
onFailure: EnsembleAction.fromYaml(payload['onFailure']),
);
}

@override
Future execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
String? value = Utils.optionalString(scopeManager.dataContext.eval(_value));
if (value != null) {
Clipboard.setData(ClipboardData(text: value)).then((_) {
if (onSuccess != null) {
ScreenController().executeAction(context, onSuccess!,
event: EnsembleEvent(initiator));
}
}).catchError((_) {
if (onFailure != null) {
ScreenController().executeAction(context, onFailure!,
event: EnsembleEvent(initiator));
}
});
} else {
if (onFailure != null) {
ScreenController().executeAction(context, onFailure!,
event: EnsembleEvent(initiator));
}
}
return Future.value(null);
}
}

/// Share a text (an optionally a title) to external Apps
class ShareAction extends EnsembleAction {
ShareAction(this._text, {String? title}) : _title = title;
String? _title;
dynamic _text;

factory ShareAction.from({Map? payload}) {
if (payload == null || payload['text'] == null) {
throw LanguageError("${ActionType.share.name} requires 'text'");
}
return ShareAction(payload['text'], title: payload['title']?.toString());
}

@override
Future execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
Share.share(scopeManager.dataContext.eval(_text),
subject: Utils.optionalString(scopeManager.dataContext.eval(_title)));
return Future.value(null);
}
}

/// Rate an App (currently only works for iOS)
class RateAppAction extends EnsembleAction {
RateAppAction({dynamic title, dynamic message})
: _title = title,
_message = message;

// not exposed yet
final dynamic _title;
final dynamic _message;

factory RateAppAction.from({Map? payload}) {
return RateAppAction(
title: payload?['title'], message: payload?['message']);
}

@override
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
// what a mess of options on Android. TODO: add them
if (Platform.isIOS) {
RateMyApp rateMyApp = RateMyApp(minDays: 0, minLaunches: 0);
rateMyApp.init().then((_) => rateMyApp.showStarRateDialog(context));
}
return Future.value(null);
}
}
7 changes: 5 additions & 2 deletions lib/action/navigation_action.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/data_context.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:ensemble/framework/scope.dart';
import 'package:ensemble/host_platform_manager.dart';
Expand All @@ -25,7 +26,8 @@ class NavigateExternalScreen extends BaseNavigateScreenAction {
}

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
// payload
Map<String, dynamic>? payload;
if (inputs != null) {
Expand Down Expand Up @@ -58,7 +60,8 @@ class NavigateBackAction extends EnsembleAction {
NavigateBackAction(payload: payload?['payload'] ?? payload?['data']);

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) {
Future<dynamic> execute(BuildContext context, ScopeManager scopeManager,
{DataContext? dataContext}) {
return Navigator.of(context)
.maybePop(scopeManager.dataContext.eval(payload));
}
Expand Down
Loading

0 comments on commit 1b57183

Please sign in to comment.