diff --git a/lib/screens/SiteLogsScreen.dart b/lib/screens/SiteLogsScreen.dart index 44d95ff..7634152 100644 --- a/lib/screens/SiteLogsScreen.dart +++ b/lib/screens/SiteLogsScreen.dart @@ -84,32 +84,28 @@ class _SiteLogsScreenState extends State { ), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( - child: PlatformIconButton( - padding: padding, - icon: Icon(context.platformIcons.share, size: 30), - onPressed: () { - Share.shareFile( - title: '${widget.site.name} logs', - filePath: widget.site.logFile, - filename: '${widget.site.name}.log'); - }, + child: Builder( + builder: (BuildContext context) { + return PlatformIconButton( + padding: padding, + icon: Icon(context.platformIcons.share, size: 30), + onPressed: () { + Share.shareFile(context, + title: '${widget.site.name} logs', + filePath: widget.site.logFile, + filename: '${widget.site.name}.log'); + }, + ); + } )), Expanded( child: PlatformIconButton( - padding: padding, - icon: Icon(context.platformIcons.delete, size: Platform.isIOS ? 38 : 30), - onPressed: () { - Utils.confirmDelete(context, 'Are you sure you want to clear all logs?', () => deleteLogs()); - }, - )), - Expanded( - child: PlatformIconButton( - padding: padding, - icon: Icon(context.platformIcons.downArrow, size: 30), - onPressed: () async { - controller.animateTo(controller.position.maxScrollExtent, - duration: const Duration(milliseconds: 500), curve: Curves.linearToEaseOut); - }, + padding: padding, + icon: Icon(context.platformIcons.downArrow, size: 30), + onPressed: () async { + controller.animateTo(controller.position.maxScrollExtent, + duration: const Duration(milliseconds: 500), curve: Curves.linearToEaseOut); + }, )), ])); } diff --git a/lib/screens/siteConfig/AddCertificateScreen.dart b/lib/screens/siteConfig/AddCertificateScreen.dart index 6653514..ae90a8c 100644 --- a/lib/screens/siteConfig/AddCertificateScreen.dart +++ b/lib/screens/siteConfig/AddCertificateScreen.dart @@ -92,11 +92,18 @@ class _AddCertificateScreenState extends State { labelWidth: 0, content: SelectableText(pubKey, style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14)), ), - ConfigButtonItem( - content: Text('Share Public Key'), - onPressed: () async { - await Share.share(title: 'Please sign and return a certificate', text: pubKey, filename: 'device.pub'); - }, + Builder( + builder: (BuildContext context) { + return ConfigButtonItem( + content: Text('Share Public Key'), + onPressed: () async { + await Share.share(context, + title: 'Please sign and return a certificate', + text: pubKey, + filename: 'device.pub'); + }, + ); + }, ), ]) ]; diff --git a/lib/screens/siteConfig/RenderedConfigScreen.dart b/lib/screens/siteConfig/RenderedConfigScreen.dart index a5328f3..16d6fbf 100644 --- a/lib/screens/siteConfig/RenderedConfigScreen.dart +++ b/lib/screens/siteConfig/RenderedConfigScreen.dart @@ -19,11 +19,17 @@ class RenderedConfigScreen extends StatelessWidget { title: Text('Rendered Site Config'), scrollable: SimpleScrollable.both, trailingActions: [ - PlatformIconButton( - padding: EdgeInsets.zero, - icon: Icon(context.platformIcons.share, size: 28.0), - onPressed: () => Share.share(title: '$name.yaml', text: config, filename: '$name.yaml'), - ) + Builder( + builder: (BuildContext context) { + return PlatformIconButton( + padding: EdgeInsets.zero, + icon: Icon(context.platformIcons.share, size: 28.0), + onPressed: () => + Share.share(context, + title: '$name.yaml', text: config, filename: '$name.yaml'), + ); + } + ), ], child: Container( padding: EdgeInsets.all(5), diff --git a/lib/services/share.dart b/lib/services/share.dart index 3f7d0bb..7707aa3 100644 --- a/lib/services/share.dart +++ b/lib/services/share.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/widgets.dart'; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart' as sp; import 'package:path/path.dart' as p; @@ -10,7 +11,8 @@ class Share { /// - title: Title of message or subject if sending an email /// - text: The text to share /// - filename: The filename to use if sending over airdrop for example - static Future share({ + static Future share( + BuildContext context, { required String title, required String text, required String filename, @@ -25,7 +27,7 @@ class Share { try { file.writeAsStringSync(text, flush: true); - res = await Share.shareFile(title: title, filePath: file.path); + res = await Share.shareFile(context, title: title, filePath: file.path); } catch (err) { // Ignoring file write errors } @@ -38,19 +40,22 @@ class Share { /// - title: Title of message or subject if sending an email /// - filePath: Path to the file to share /// - filename: An optional filename to override the existing file - static Future shareFile({ - required String title, - required String filePath, - String? filename - }) async { + static Future shareFile(BuildContext context, + {required String title, + required String filePath, + String? filename}) async { assert(title.isNotEmpty); assert(filePath.isNotEmpty); + final box = context.findRenderObject() as RenderBox?; + //NOTE: the filename used to specify the name of the file in gmail/slack/etc but no longer works that way // If we want to support that again we will need to save the file to a temporary directory, share that, // and then delete it final xFile = sp.XFile(filePath, name: filename); - final result = await sp.Share.shareXFiles([xFile], subject: title); + final result = await sp.Share.shareXFiles([xFile], + subject: title, + sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size); return result.status == sp.ShareResultStatus.success; } }