-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into Media-Support-for-shareAction
- Loading branch information
Showing
6 changed files
with
210 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:flutter/foundation.dart'; | ||
import 'package:image_gallery_saver/image_gallery_saver.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
// Conditionally import the file that has `dart:html` vs. the stub: | ||
import 'download_stub.dart' if (dart.library.html) 'download_web.dart'; | ||
|
||
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'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import 'dart:typed_data'; | ||
import 'package:ensemble/framework/action.dart'; | ||
import 'package:ensemble/framework/error_handling.dart'; | ||
import 'package:ensemble/framework/event.dart'; | ||
import 'package:ensemble/framework/view/data_scope_widget.dart'; | ||
import 'package:ensemble/screen_controller.dart'; | ||
import 'package:ensemble/framework/scope.dart'; | ||
import 'package:ensemble/util/utils.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:intl/intl.dart'; | ||
import 'package:screenshot/screenshot.dart'; | ||
import 'saveFile/save_mobile.dart'; | ||
|
||
class TakeScreenshotAction extends EnsembleAction { | ||
TakeScreenshotAction({ | ||
super.initiator, | ||
required this.widgetId, | ||
this.pixelRatio, | ||
this.onSuccess, | ||
this.onError, | ||
}); | ||
|
||
final dynamic widgetId; | ||
final double? pixelRatio; | ||
final EnsembleAction? onSuccess; | ||
final EnsembleAction? onError; | ||
|
||
factory TakeScreenshotAction.fromYaml({Map? payload}) { | ||
if (payload == null || payload['widgetId'] == null) { | ||
throw LanguageError( | ||
"${ActionType.takeScreenshot.name} requires 'widgetId'"); | ||
} | ||
return TakeScreenshotAction( | ||
widgetId: payload['widgetId'], | ||
pixelRatio: Utils.optionalDouble(payload['pixelRatio']), | ||
onSuccess: payload['onSuccess'] != null | ||
? EnsembleAction.from(payload['onSuccess']) | ||
: null, | ||
onError: payload['onError'] != null | ||
? EnsembleAction.from(payload['onError']) | ||
: null, | ||
); | ||
} | ||
|
||
@override | ||
Future<void> execute(BuildContext context, ScopeManager scopeManager) async { | ||
final screenshotController = ScreenshotController(); | ||
|
||
try { | ||
final resolvedWidget = scopeManager.dataContext.eval(widgetId); | ||
if (resolvedWidget == null) { | ||
throw LanguageError("Widget not found: '$widgetId'"); | ||
} | ||
|
||
final widget = Screenshot( | ||
controller: screenshotController, | ||
child: DataScopeWidget( | ||
scopeManager: scopeManager, | ||
child: resolvedWidget, | ||
), | ||
); | ||
|
||
final Uint8List? capturedImage = | ||
// It will only capture readonly widgets | ||
await screenshotController.captureFromLongWidget( | ||
InheritedTheme.captureAll( | ||
context, | ||
Material( | ||
type: MaterialType.transparency, | ||
child: widget, | ||
), | ||
), | ||
pixelRatio: pixelRatio ?? MediaQuery.of(context).devicePixelRatio, | ||
context: context, | ||
); | ||
|
||
if (capturedImage == null) { | ||
throw LanguageError("Failed to capture screenshot"); | ||
} | ||
|
||
final dimensions = await _getImageDimensions(capturedImage); | ||
// Save screenshot to gallery and download on web | ||
await _saveScreenshot(capturedImage); | ||
|
||
if (onSuccess != null) { | ||
await ScreenController().executeAction( | ||
context, | ||
onSuccess!, | ||
event: EnsembleEvent(initiator, data: { | ||
'imageBytes': capturedImage, // capturedImage contains Image Bytes | ||
'size': capturedImage.length, | ||
'dimensions': dimensions, | ||
}), | ||
); | ||
} | ||
} catch (e) { | ||
if (onError != null) { | ||
await ScreenController().executeAction( | ||
context, | ||
onError!, | ||
event: EnsembleEvent(initiator, data: {'error': e.toString()}), | ||
); | ||
} | ||
} | ||
} | ||
|
||
Future<void> _saveScreenshot(Uint8List fileBytes) async { | ||
// Screenshot name of current date | ||
// Get the current date and time | ||
DateTime now = DateTime.now(); | ||
|
||
// Format the date and time | ||
String formattedDateTime = DateFormat('yyyyMMdd_HHmmss').format(now); | ||
|
||
// Combine the prefix with the formatted date and time | ||
String screenshotName = 'screenshot_$formattedDateTime'; | ||
|
||
await saveImageToDCIM(screenshotName, fileBytes); | ||
} | ||
|
||
Future<Map<String, int>> _getImageDimensions(Uint8List imageData) async { | ||
final image = await decodeImageFromList(imageData); | ||
return { | ||
'width': image.width, | ||
'height': image.height, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters