Skip to content
This repository was archived by the owner on Jul 21, 2022. It is now read-only.

fix iPadOS share screen and allow to specify point of origin #54

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## 1.0.3

* update example app
* null safety

## 1.0.2

Expand Down
1 change: 1 addition & 0 deletions example/.flutter-plugins-dependencies
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"esys_flutter_share","path":"E:\\\\Devs\\\\dart\\\\esys-flutter-share\\\\","dependencies":["path_provider"]},{"name":"path_provider","path":"C:\\\\homeware\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]}],"android":[{"name":"esys_flutter_share","path":"E:\\\\Devs\\\\dart\\\\esys-flutter-share\\\\","dependencies":["path_provider"]},{"name":"path_provider","path":"C:\\\\homeware\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\homeware\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.0\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\homeware\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.0.0\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\homeware\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.0\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"esys_flutter_share","dependencies":["path_provider"]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2021-03-09 15:55:10.945587","version":"2.0.1"}
13 changes: 13 additions & 0 deletions example/ios/Flutter/flutter_export_environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=C:\homeware\flutter"
export "FLUTTER_APPLICATION_PATH=E:\Devs\dart\esys-flutter-share\example"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build\ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"
202 changes: 142 additions & 60 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,52 +27,114 @@ class _MyHomePageState extends State<MyHomePage> {
appBar: AppBar(
title: Text('Share Example'),
),
body: Container(
padding: const EdgeInsets.all(20.0),
child: ListView(
children: <Widget>[
MaterialButton(
child: Text('Share text'),
onPressed: () async => await _shareText(),
),
MaterialButton(
child: Text('Share image'),
onPressed: () async => await _shareImage(),
),
MaterialButton(
child: Text('Share images'),
onPressed: () async => await _shareImages(),
),
MaterialButton(
child: Text('Share CSV'),
onPressed: () async => await _shareCSV(),
),
MaterialButton(
child: Text('Share mixed'),
onPressed: () async => await _shareMixed(),
),
MaterialButton(
child: Text('Share image from url'),
onPressed: () async => await _shareImageFromUrl(),
),
MaterialButton(
child: Text('Share sound'),
onPressed: () async => await _shareSound(),
),
],
)));
floatingActionButton: Builder(
builder: (BuildContext context) => IconButton(
icon: Icon(Icons.file_download),
onPressed: () => _shareImage(context),
)),
body: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
padding: const EdgeInsets.all(20.0),
child: ListView(
children: <Widget>[
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share text'),
onPressed: () async => await _shareText(context),
),
),
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share image'),
onPressed: () async => await _shareImage(context),
),
),
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share images'),
onPressed: () async => await _shareImages(context),
),
),
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share CSV'),
onPressed: () async => await _shareCSV(context),
),
),
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share mixed'),
onPressed: () async => await _shareMixed(context),
),
),
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share image from url'),
onPressed: () async =>
await _shareImageFromUrl(context),
),
),
Builder(
builder: (BuildContext context) => MaterialButton(
child: Text('Share sound'),
onPressed: () async => await _shareSound(context),
),
),
MaterialButton(
child: Text('Share not bounded'),
onPressed: () async => await _shareImageNotBounded(),
),
MaterialButton(
child: Text('Share bounded to window'),
onPressed: () async => await _shareImage(context),
),
],
)),
),
Positioned(
child: Builder(
builder: (BuildContext context) => IconButton(
icon: Icon(Icons.file_download),
onPressed: () => _shareImage(context),
)),
bottom: 0,
left: 0)
],
));
}

Future<void> _shareText() async {
Rect rect(BuildContext context) {
final RenderBox box = context.findRenderObject() as RenderBox;
return box.localToGlobal(Offset.zero) & box.size;
}

Future<void> _shareText(BuildContext context) async {
try {
Share.text('my text title',
'This is my text to share with other applications.', 'text/plain');
Share.text(
'my text title',
'This is my text to share with other applications.',
'text/plain',
sharePositionOrigin: rect(context),
);
} catch (e) {
print('error: $e');
}
}

Future<void> _shareImage() async {
Future<void> _shareImage(BuildContext context) async {
try {
final ByteData bytes = await rootBundle.load('assets/image1.png');
await Share.file(
'esys image', 'esys.png', bytes.buffer.asUint8List(), 'image/png',
text: 'My optional text.', sharePositionOrigin: rect(context));
} catch (e) {
print('error: $e');
}
}

Future<void> _shareImageNotBounded() async {
try {
final ByteData bytes = await rootBundle.load('assets/image1.png');
await Share.file(
Expand All @@ -83,70 +145,90 @@ class _MyHomePageState extends State<MyHomePage> {
}
}

Future<void> _shareImages() async {
Future<void> _shareImages(BuildContext context) async {
try {
final ByteData bytes1 = await rootBundle.load('assets/image1.png');
final ByteData bytes2 = await rootBundle.load('assets/image2.png');

await Share.files(
'esys images',
{
'esys.png': bytes1.buffer.asUint8List(),
'bluedan.png': bytes2.buffer.asUint8List(),
},
'image/png');
'esys images',
{
'esys.png': bytes1.buffer.asUint8List(),
'bluedan.png': bytes2.buffer.asUint8List(),
},
'image/png',
sharePositionOrigin: rect(context),
);
} catch (e) {
print('error: $e');
}
}

Future<void> _shareCSV() async {
Future<void> _shareCSV(BuildContext context) async {
try {
final ByteData bytes = await rootBundle.load('assets/addresses.csv');
await Share.file(
'addresses', 'addresses.csv', bytes.buffer.asUint8List(), 'text/csv');
'addresses',
'addresses.csv',
bytes.buffer.asUint8List(),
'text/csv',
sharePositionOrigin: rect(context),
);
} catch (e) {
print('error: $e');
}
}

Future<void> _shareMixed() async {
Future<void> _shareMixed(BuildContext context) async {
try {
final ByteData bytes1 = await rootBundle.load('assets/image1.png');
final ByteData bytes2 = await rootBundle.load('assets/image2.png');
final ByteData bytes3 = await rootBundle.load('assets/addresses.csv');

await Share.files(
'esys images',
{
'esys.png': bytes1.buffer.asUint8List(),
'bluedan.png': bytes2.buffer.asUint8List(),
'addresses.csv': bytes3.buffer.asUint8List(),
},
'*/*',
text: 'My optional text.');
'esys images',
{
'esys.png': bytes1.buffer.asUint8List(),
'bluedan.png': bytes2.buffer.asUint8List(),
'addresses.csv': bytes3.buffer.asUint8List(),
},
'*/*',
text: 'My optional text.',
sharePositionOrigin: rect(context),
);
} catch (e) {
print('error: $e');
}
}

Future<void> _shareImageFromUrl() async {
Future<void> _shareImageFromUrl(BuildContext context) async {
try {
var request = await HttpClient().getUrl(Uri.parse(
'https://shop.esys.eu/media/image/6f/8f/af/amlog_transport-berwachung.jpg'));
var response = await request.close();
Uint8List bytes = await consolidateHttpClientResponseBytes(response);
await Share.file('ESYS AMLOG', 'amlog.jpg', bytes, 'image/jpg');
await Share.file(
'ESYS AMLOG',
'amlog.jpg',
bytes,
'image/jpg',
sharePositionOrigin: rect(context),
);
} catch (e) {
print('error: $e');
}
}

Future<void> _shareSound() async {
Future<void> _shareSound(BuildContext context) async {
try {
final ByteData bytes = await rootBundle.load('assets/cat.mp3');
await Share.file(
'Sound', 'cat.mp3', bytes.buffer.asUint8List(), 'audio/*');
'Sound',
'cat.mp3',
bytes.buffer.asUint8List(),
'audio/*',
sharePositionOrigin: rect(context),
);
} catch (e) {
print('error: $e');
}
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
cupertino_icons: ^1.0.2

dev_dependencies:
flutter_test:
Expand Down
77 changes: 53 additions & 24 deletions ios/Classes/SwiftEsysFlutterSharePlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,7 @@ public class SwiftEsysFlutterSharePlugin: NSObject, FlutterPlugin {
let argsMap = arguments as! NSDictionary
let text:String = argsMap.value(forKey: "text") as! String

// set up activity view controller
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: [text], applicationActivities: nil)

// present the view controller
let controller = UIApplication.shared.keyWindow!.rootViewController as! FlutterViewController
activityViewController.popoverPresentationController?.sourceView = controller.view

controller.show(activityViewController, sender: self)
setupAndShow(activityItems: [text], argsMap: argsMap)
}

func file(arguments:Any?) -> Void {
Expand All @@ -56,15 +49,18 @@ public class SwiftEsysFlutterSharePlugin: NSObject, FlutterPlugin {
// add optional text
activityItems.append(text);
}
if(UIDevice.current.userInterfaceIdiom == .pad){
setupAndShow(activityItems: activityItems, argsMap: argsMap)
} else {
// set up activity view controller
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

// present the view controller
let controller = UIApplication.shared.keyWindow!.rootViewController as! FlutterViewController
activityViewController.popoverPresentationController?.sourceView = controller.view
controller.show(activityViewController, sender: self)
}

// set up activity view controller
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

// present the view controller
let controller = UIApplication.shared.keyWindow!.rootViewController as! FlutterViewController
activityViewController.popoverPresentationController?.sourceView = controller.view

controller.show(activityViewController, sender: self)
}

func files(arguments:Any?) -> Void {
Expand All @@ -88,14 +84,47 @@ public class SwiftEsysFlutterSharePlugin: NSObject, FlutterPlugin {
// add optional text
activityItems.append(text);
}

// set up activity view controller
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

// present the view controller
if(UIDevice.current.userInterfaceIdiom == .pad){
setupAndShow(activityItems: activityItems, argsMap: argsMap)
} else {
// set up activity view controller
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

// present the view controller
let controller = UIApplication.shared.keyWindow!.rootViewController as! FlutterViewController
activityViewController.popoverPresentationController?.sourceView = controller.view
controller.show(activityViewController, sender: self)
}
}

private func setupAndShow(activityItems: [Any], argsMap: NSDictionary) {


let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
let controller = UIApplication.shared.keyWindow!.rootViewController as! FlutterViewController
activityViewController.popoverPresentationController?.sourceView = controller.view

controller.show(activityViewController, sender: self)
if let popover = activityViewController.popoverPresentationController {
popover.sourceView = controller.view
let bounds = controller.view.bounds

if (UIDevice.current.userInterfaceIdiom == .pad) {
let originX:NSNumber = argsMap.value(forKey: "originX") as? NSNumber ?? NSNumber(value: Float(bounds.midX))
let originY:NSNumber = argsMap.value(forKey: "originY") as? NSNumber ?? NSNumber(value: Float(bounds.midY))
var originWidth:NSNumber = argsMap.value(forKey: "originWidth") as? NSNumber ?? 0
var originHeight:NSNumber = argsMap.value(forKey: "originHeight") as? NSNumber ?? 0

if (originWidth.intValue > (bounds.width - 96 as NSNumber).intValue) {
originWidth = NSNumber(value: Float((bounds.width - 96)))
}
if (originHeight.intValue > (bounds.height - 96 as NSNumber).intValue) {
originHeight = NSNumber(value: Float((bounds.height - 96)))
}

popover.sourceRect = CGRect(x:originX.doubleValue,
y:originY.doubleValue,
width:originWidth.doubleValue,
height:originHeight.doubleValue);
}
controller.show(activityViewController, sender: self)
}
}
}
Loading