From 526df92374ea9682008c89df07b1236ef3aa51df Mon Sep 17 00:00:00 2001 From: Marcelo Milhomem Date: Wed, 23 Sep 2026 14:25:25 +1000 Subject: [PATCH] feat(share_plus_platform_interface): add ShareAirDropAs for titled URI shares Let callers choose whether iOS AirDrop delivers a URI as a URL, as text, or keeps the current inherit behaviour. Co-authored-by: Cursor --- .../method_channel/method_channel_share.dart | 2 ++ .../share_plus_platform.dart | 28 +++++++++++++++++++ .../lib/share_plus_platform_interface.dart | 1 + .../share_plus_platform_interface_test.dart | 9 ++++-- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart b/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart index 80d6c97e51..822a9acec2 100644 --- a/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart +++ b/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart @@ -43,6 +43,8 @@ class MethodChannelShare extends SharePlatform { if (params.subject != null) 'subject': params.subject, if (params.title != null) 'title': params.title, if (params.uri != null) 'uri': params.uri.toString(), + if (params.airDrop != ShareAirDropAs.inherit) + 'airDrop': params.airDrop.name, }; if (params.sharePositionOrigin != null) { diff --git a/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart b/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart index c5e8f0b934..cc2bd07c13 100644 --- a/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart +++ b/packages/share_plus/share_plus_platform_interface/lib/platform_interface/share_plus_platform.dart @@ -145,6 +145,21 @@ class ShareParams { /// Parameter ignored on other platforms. final List? excludedCupertinoActivities; + /// How AirDrop should deliver [uri] on iOS. + /// + /// * [ShareAirDropAs.inherit] keeps the current URI share (raw `NSURL`, + /// Safari / page preview on the sheet). + /// * [ShareAirDropAs.url] wraps the URI like a text share so the host app + /// icon stays in the header, and AirDrop / Messages receive the URL. + /// * [ShareAirDropAs.text] sends the URI string as plain text (Notes). + /// + /// Android has no AirDrop. [uri] + [title] already go out as EXTRA_TEXT / + /// EXTRA_TITLE (Nearby Share equivalent). This parameter is ignored there. + /// + /// * Supported platforms: iOS + /// Parameter ignored on other platforms. + final ShareAirDropAs airDrop; + ShareParams({ this.text, this.subject, @@ -157,6 +172,7 @@ class ShareParams { this.downloadFallbackEnabled = true, this.mailToFallbackEnabled = true, this.excludedCupertinoActivities, + this.airDrop = ShareAirDropAs.inherit, }); } @@ -222,6 +238,18 @@ enum ShareResultStatus { /// /// See also: /// [UIActivity.ActivityType](https://developer.apple.com/documentation/uikit/uiactivity/activitytype) +/// How iOS AirDrop should deliver a shared [ShareParams.uri]. +enum ShareAirDropAs { + /// Keep the current URI-share behaviour (raw URL item). + inherit, + + /// Deliver the URI as a URL (opens the link instead of Notes). + url, + + /// Deliver the URI string as plain text. + text, +} + enum CupertinoActivityType { postToFacebook, postToTwitter, diff --git a/packages/share_plus/share_plus_platform_interface/lib/share_plus_platform_interface.dart b/packages/share_plus/share_plus_platform_interface/lib/share_plus_platform_interface.dart index f1e38b83bc..3ee169f9a1 100644 --- a/packages/share_plus/share_plus_platform_interface/lib/share_plus_platform_interface.dart +++ b/packages/share_plus/share_plus_platform_interface/lib/share_plus_platform_interface.dart @@ -3,4 +3,5 @@ // found in the LICENSE file. export 'package:cross_file/cross_file.dart'; + export 'platform_interface/share_plus_platform.dart'; diff --git a/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart b/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart index 67c8bff9a9..598d80217e 100644 --- a/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart +++ b/packages/share_plus/share_plus_platform_interface/test/share_plus_platform_interface_test.dart @@ -58,6 +58,8 @@ void main() { await sharePlatform.share( ShareParams( uri: Uri.parse('https://pub.dev/packages/share_plus'), + title: 'Join this circle', + airDrop: ShareAirDropAs.url, sharePositionOrigin: const Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), excludedCupertinoActivities: [CupertinoActivityType.airDrop], ), @@ -65,6 +67,8 @@ void main() { verify( mockChannel.invokeMethod('share', { 'uri': 'https://pub.dev/packages/share_plus', + 'title': 'Join this circle', + 'airDrop': 'url', 'originX': 1.0, 'originY': 2.0, 'originWidth': 3.0, @@ -223,8 +227,7 @@ class MockMethodChannel extends Mock implements MethodChannel { @override Future invokeMethod(String method, [dynamic arguments]) async { return super.noSuchMethod( - Invocation.method(#invokeMethod, [method, arguments]), - ) - as dynamic; + Invocation.method(#invokeMethod, [method, arguments]), + ) as dynamic; } }