Skip to content

Commit

Permalink
Merge branch 'main' into 1771-screenshot
Browse files Browse the repository at this point in the history
  • Loading branch information
mehsaandev authored Jan 7, 2025
2 parents bc99b17 + efa3fa9 commit cd257f0
Show file tree
Hide file tree
Showing 21 changed files with 278 additions and 16 deletions.
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## 2025-01-07

### Changes

---

Packages with breaking changes:

- There are no breaking changes in this release.

Packages with other changes:

- [`ensemble` - `v1.1.14`](#ensemble---v1114)
- [`ensemble_auth` - `v1.0.1`](#ensemble_auth---v101)
- [`ensemble_camera` - `v0.0.1+1`](#ensemble_camera---v0011)
- [`ensemble_chat` - `v0.0.1+1`](#ensemble_chat---v0011)
- [`ensemble_connect` - `v0.0.1+1`](#ensemble_connect---v0011)
- [`ensemble_contacts` - `v0.0.1+1`](#ensemble_contacts---v0011)
- [`ensemble_deeplink` - `v0.0.1+1`](#ensemble_deeplink---v0011)
- [`ensemble_bluetooth` - `v0.0.1+1`](#ensemble_bluetooth---v0011)
- [`ensemble_network_info` - `v0.0.1+1`](#ensemble_network_info---v0011)
- [`ensemble_file_manager` - `v0.0.1+1`](#ensemble_file_manager---v0011)
- [`ensemble_location` - `v0.0.1+1`](#ensemble_location---v0011)

Packages with dependency updates only:

> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `ensemble_auth` - `v1.0.1`
- `ensemble_camera` - `v0.0.1+1`
- `ensemble_chat` - `v0.0.1+1`
- `ensemble_connect` - `v0.0.1+1`
- `ensemble_contacts` - `v0.0.1+1`
- `ensemble_deeplink` - `v0.0.1+1`
- `ensemble_bluetooth` - `v0.0.1+1`
- `ensemble_network_info` - `v0.0.1+1`
- `ensemble_file_manager` - `v0.0.1+1`
- `ensemble_location` - `v0.0.1+1`

---

#### `ensemble` - `v1.1.14`

# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## 2025-01-03

### Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/auth/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble

ensemble_ts_interpreter:
Expand Down
2 changes: 1 addition & 1 deletion modules/bracket/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble

dev_dependencies:
Expand Down
2 changes: 1 addition & 1 deletion modules/camera/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble
ensemble_ts_interpreter:
git:
Expand Down
2 changes: 1 addition & 1 deletion modules/chat/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble

ensemble_ts_interpreter:
Expand Down
2 changes: 1 addition & 1 deletion modules/connect/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble

plaid_flutter: ^3.1.2
Expand Down
2 changes: 1 addition & 1 deletion modules/contacts/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble

flutter_contacts: ^1.1.7+1
Expand Down
2 changes: 1 addition & 1 deletion modules/deeplink/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
ensemble:
git:
url: https://github.com/EnsembleUI/ensemble.git
ref: ensemble-v1.1.13
ref: ensemble-v1.1.14
path: modules/ensemble

flutter_branch_sdk: ^7.0.1
Expand Down
2 changes: 2 additions & 0 deletions modules/ensemble/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## 1.1.14

## 1.1.13

- Moengage Module Release
Expand Down
2 changes: 2 additions & 0 deletions modules/ensemble/lib/action/action_invokable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ abstract class ActionInvokable with Invokable {
ActionType.closeAllDialogs,
ActionType.executeActionGroup,
ActionType.takeScreenshot
ActionType.saveFile,
ActionType.controlDeviceBackNavigation,
ActionType.closeApp,
]);
}

Expand Down
24 changes: 24 additions & 0 deletions modules/ensemble/lib/action/close_app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/scope.dart';
import 'package:ensemble/util/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ensemble_ts_interpreter/invokables/invokable.dart';

class CloseAppAction extends EnsembleAction {
CloseAppAction({
super.initiator,
});

factory CloseAppAction.from({Invokable? initiator, Map? payload}) {
return CloseAppAction(
initiator: initiator,
);
}

@override
Future execute(BuildContext context, ScopeManager scopeManager) {
SystemNavigator.pop();
return Future.value(null);
}
}
177 changes: 177 additions & 0 deletions modules/ensemble/lib/action/save_file.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import 'dart:convert';
import 'dart:typed_data';
import 'dart:io';

import 'package:ensemble/framework/action.dart';
import 'package:ensemble/framework/scope.dart';
import 'package:flutter/material.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:ensemble/framework/error_handling.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'dart:html' as html;

/// Custom action to save files (images and documents) in platform-specific accessible directories
class SaveToFileSystemAction extends EnsembleAction {
final String? fileName;
final dynamic blobData;
final String? source; // Optional source for URL if blobData is not available
final String? type; // file type

SaveToFileSystemAction({
required this.fileName,
this.blobData,
this.source,
this.type,
});

factory SaveToFileSystemAction.from({Map? payload}) {
if (payload == null || payload['fileName'] == null) {
throw LanguageError('${ActionType.saveFile.name} requires fileName.');
}

return SaveToFileSystemAction(
fileName: payload['fileName'],
blobData: payload['blobData'],
source: payload['source'],
type: payload['type'],
);
}

@override
Future<void> execute(BuildContext context, ScopeManager scopeManager) async {
try {
if (fileName == null) {
throw Exception('Missing required parameter: fileName.');
}

Uint8List? fileBytes;

// If blobData is provided, process it
if (blobData != null) {
// Handle base64 blob or binary data
if (blobData is String) {
fileBytes = base64Decode(blobData); // Decode base64
} else if (blobData is List<int>) {
fileBytes = Uint8List.fromList(blobData);
} else {
throw Exception(
'Invalid blob data format. Must be base64 or List<int>.');
}
} else if (source != null) {
// If blobData is not available, check for source (network URL)
final response = await http.get(Uri.parse(source!));
if (response.statusCode == 200) {
fileBytes = Uint8List.fromList(response.bodyBytes);
} else {
throw Exception(
'Failed to download file: HTTP ${response.statusCode}');
}
} else {
throw Exception('Missing blobData and source.');
}

if (type == 'image') {
// Save images to Default Image Path
await _saveImageToDCIM(fileName!, fileBytes);
} else if (type == 'document') {
// Save documents to Documents folder
await _saveDocumentToDocumentsFolder(fileName!, fileBytes);
}
} catch (e) {
throw Exception('Failed to save file: $e');
}
}

Future<void> _saveImageToDCIM(String fileName, Uint8List fileBytes) async {
try {
if (kIsWeb) {
_downloadFileOnWeb(fileName, fileBytes);
} else {
final result = await ImageGallerySaver.saveImage(
fileBytes,
name: fileName,
);
if (result['isSuccess']) {
debugPrint('Image saved to gallery: $result');
} else {
throw Exception('Failed to save image to gallery.');
}
}
} catch (e) {
throw Exception('Failed to save image: $e');
}
}

/// Save documents to the default "Documents" directory
Future<void> _saveDocumentToDocumentsFolder(
String fileName, Uint8List fileBytes) async {
try {
String filePath;

if (Platform.isAndroid) {
// Get the default "Documents" directory on Android
Directory? directory = Directory('/storage/emulated/0/Documents');
if (!directory.existsSync()) {
directory.createSync(
recursive: true); // Create the directory if it doesn't exist
}
filePath = '${directory.path}/$fileName';
} else if (Platform.isIOS) {
// On iOS, use the app-specific Documents directory
final directory = await getApplicationDocumentsDirectory();
filePath = '${directory.path}/$fileName';

// Optionally, use a share intent to let users save the file to their desired location
} else if (kIsWeb) {
_downloadFileOnWeb(fileName, fileBytes);
return;
} else {
throw UnsupportedError('Platform not supported');
}

// Write the file to the determined path
final file = File(filePath);
await file.writeAsBytes(fileBytes);

debugPrint('Document saved to: $filePath');
} catch (e) {
throw Exception('Failed to save document: $e');
}
}

Future<void> _downloadFileOnWeb(String fileName, Uint8List fileBytes) async {
try {
// Convert Uint8List to a Blob
final blob = html.Blob([fileBytes]);

// Create an object URL for the Blob
final url = html.Url.createObjectUrlFromBlob(blob);

// Create a download anchor element
final anchor = html.AnchorElement(href: url)
..target = 'blank' // Open in a new tab if needed
..download = fileName; // Set the download file name

// Trigger the download
anchor.click();

// Revoke the object URL to free resources
html.Url.revokeObjectUrl(url);

debugPrint('File downloaded: $fileName');
} catch (e) {
throw Exception('Failed to download file: $e');
}
}

/// Factory method to construct the action from JSON
static SaveToFileSystemAction fromJson(Map<String, dynamic> json) {
return SaveToFileSystemAction(
fileName: json['fileName'],
blobData: json['blobData'],
source: json['source'],
);
}
}
10 changes: 9 additions & 1 deletion modules/ensemble/lib/framework/action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import 'package:ensemble/action/change_locale_actions.dart';
import 'package:ensemble/action/misc_action.dart';
import 'package:ensemble/action/navigation_action.dart';
import 'package:ensemble/action/notification_actions.dart';
import 'package:ensemble/action/save_file.dart';
import 'package:ensemble/action/phone_contact_action.dart';
import 'package:ensemble/action/sign_in_out_action.dart';
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/ensemble.dart';
import 'package:ensemble/framework/data_context.dart';
import 'package:ensemble/framework/error_handling.dart';
Expand Down Expand Up @@ -1057,7 +1059,9 @@ enum ActionType {
bluetoothDisconnect,
bluetoothSubscribeCharacteristic,
bluetoothUnsubscribeCharacteristic,
controlDeviceBackNavigation
controlDeviceBackNavigation,
closeApp
saveFile
}

/// payload representing an Action to do (navigateToScreen, InvokeAPI, ..)
Expand Down Expand Up @@ -1179,12 +1183,16 @@ abstract class EnsembleAction {
return CopyToClipboardAction.from(payload: payload);
} else if (actionType == ActionType.share) {
return ShareAction.from(payload: payload);
} else if (actionType == ActionType.saveFile) {
return SaveToFileSystemAction.from(payload: payload);
} else if (actionType == ActionType.controlDeviceBackNavigation) {
return ControlBackNavigation.from(payload: payload);
} else if (actionType == ActionType.rateApp) {
return RateAppAction.from(payload: payload);
} else if (actionType == ActionType.getDeviceToken) {
return GetDeviceTokenAction.fromMap(payload: payload);
} else if (actionType == ActionType.closeApp) {
return CloseAppAction();
} else if (actionType == ActionType.openPlaidLink) {
return PlaidLinkAction.fromYaml(initiator: initiator, payload: payload);
} else if (actionType == ActionType.openAppSettings) {
Expand Down
3 changes: 2 additions & 1 deletion modules/ensemble/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ description: Ensemble Runtime
# This version is used _only_ for the Runner app, which is used if you just do
# a `flutter run` or a `flutter make-host-app-editable`. It has no impact
# on any other native host app that you embed your Flutter project into.
version: 1.1.13
version: 1.1.14

environment:
sdk: ">=3.5.0"
Expand Down Expand Up @@ -93,6 +93,7 @@ dependencies:
shared_preferences: ^2.1.1
workmanager: ^0.5.1
flutter_local_notifications: ^17.2.3
image_gallery_saver: ^2.0.3
flutter_i18n: ^0.35.1
pointer_interceptor: ^0.9.3+4
flutter_secure_storage: ^9.2.2
Expand Down
Loading

0 comments on commit cd257f0

Please sign in to comment.