Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[quick_actions] add localizedSubtitle for iOS #6973

Closed
Closed
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
1 change: 1 addition & 0 deletions packages/quick_actions/quick_actions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT

* Add localizedSubtitle field for iOS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the CHANGELOG style guide linked from the PR checklist.

* Updates minimum supported SDK version to Flutter 3.16/Dart 3.2.

## 1.0.7
Expand Down
2 changes: 1 addition & 1 deletion packages/quick_actions/quick_actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Finally, manage the app's quick actions, for instance:
```dart
quickActions.setShortcutItems(<ShortcutItem>[
const ShortcutItem(type: 'action_main', localizedTitle: 'Main view', icon: 'icon_main'),
const ShortcutItem(type: 'action_help', localizedTitle: 'Help', icon: 'icon_help')
const ShortcutItem(type: 'action_help', localizedTitle: 'Help', localizedSubtitle: 'Tap to get help', icon: 'icon_help')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that this is a common enough option that we actually need to update the README and example app to demonstrate it.

]);
```

Expand Down
10 changes: 6 additions & 4 deletions packages/quick_actions/quick_actions/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,16 @@ class _MyHomePageState extends State<MyHomePage> {
const ShortcutItem(
type: 'action_one',
localizedTitle: 'Action one',
icon: 'AppIcon',
localizedSubtitle: 'Action one subtitle',
icon: 'icon_help',
),
// NOTE: This second action icon will only work on Android.
// In a real world project keep the same file name for both platforms.
const ShortcutItem(
type: 'action_two',
localizedTitle: 'Action two',
icon: 'ic_launcher'),
type: 'action_two',
localizedTitle: 'Action two',
icon: 'ic_launcher',
),
]).then((void _) {
setState(() {
if (shortcut == 'no action set') {
Expand Down
10 changes: 10 additions & 0 deletions packages/quick_actions/quick_actions/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ dependencies:
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../


# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:

quick_actions_platform_interface:
path: ../../../quick_actions/quick_actions_platform_interface
quick_actions_ios:
path: ../../../quick_actions/quick_actions_ios

dev_dependencies:
espresso: ^0.2.0
Expand Down
5 changes: 5 additions & 0 deletions packages/quick_actions/quick_actions/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ dev_dependencies:
topics:
- quick-actions
- os-integration

# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:
{quick_actions_ios: {path: ../../quick_actions/quick_actions_ios}, quick_actions_platform_interface: {path: ../../quick_actions/quick_actions_platform_interface}}
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ dev_dependencies:

flutter:
uses-material-design: true

# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all of the quick_actions_android override entries since the package won't need any changes.

# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:
{quick_actions_platform_interface: {path: ../../../quick_actions/quick_actions_platform_interface}}
5 changes: 5 additions & 0 deletions packages/quick_actions/quick_actions_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ dev_dependencies:
topics:
- quick-actions
- os-integration

# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:
{quick_actions_platform_interface: {path: ../../quick_actions/quick_actions_platform_interface}}
4 changes: 4 additions & 0 deletions packages/quick_actions/quick_actions_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## NEXT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the versioning policy linked in from the PR checklist.


* Add localizedSubtitle field

## 1.1.1

* Updates to a newer version of Pigeon.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ dev_dependencies:

flutter:
uses-material-design: true

# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:
{quick_actions_ios: {path: ../../../quick_actions/quick_actions_ios}, quick_actions_platform_interface: {path: ../../../quick_actions/quick_actions_platform_interface}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should have corresponding native testing.

Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA

let type = shortcut.type
let localizedTitle = shortcut.localizedTitle
let localizedSubtitle = shortcut.localizedSubtitle
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be inlined below, as it doesn't seem like the local variables are adding any value here. (The ones above may well be left over from a direct Pigeon conversion, as they would have been more useful prior to Pigeon.)


let icon = (shortcut.icon).map {
UIApplicationShortcutIcon(templateImageName: $0)
Expand All @@ -101,7 +102,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA
return UIApplicationShortcutItem(
type: type,
localizedTitle: localizedTitle,
localizedSubtitle: nil,
localizedSubtitle: localizedSubtitle,
icon: icon,
userInfo: nil)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class PigeonError: Error {
var localizedDescription: String {
return
"PigeonError(code: \(code), message: \(message ?? "<nil>"), details: \(details ?? "<nil>")"
}
}
}

private func wrapResult(_ result: Any?) -> [Any?] {
Expand Down Expand Up @@ -59,9 +59,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}

private func createConnectionError(withChannelName channelName: String) -> PigeonError {
return PigeonError(
code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.",
details: "")
return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "")
}

private func isNullish(_ value: Any?) -> Bool {
Expand All @@ -81,25 +79,30 @@ struct ShortcutItemMessage {
var type: String
/// Localized title of the item.
var localizedTitle: String
/// Localized subtitle of the item.
var localizedSubtitle: String? = nil
/// Name of native resource to be displayed as the icon for this item.
var icon: String? = nil

// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ __pigeon_list: [Any?]) -> ShortcutItemMessage? {
let type = __pigeon_list[0] as! String
let localizedTitle = __pigeon_list[1] as! String
let icon: String? = nilOrValue(__pigeon_list[2])
let localizedSubtitle: String? = nilOrValue(__pigeon_list[2])
let icon: String? = nilOrValue(__pigeon_list[3])

return ShortcutItemMessage(
type: type,
localizedTitle: localizedTitle,
localizedSubtitle: localizedSubtitle,
icon: icon
)
}
func toList() -> [Any?] {
return [
type,
localizedTitle,
localizedSubtitle,
icon,
]
}
Expand Down Expand Up @@ -152,16 +155,10 @@ protocol IOSQuickActionsApi {
class IOSQuickActionsApiSetup {
static var codec: FlutterStandardMessageCodec { messagesPigeonCodec.shared }
/// Sets up an instance of `IOSQuickActionsApi` to handle messages through the `binaryMessenger`.
static func setUp(
binaryMessenger: FlutterBinaryMessenger, api: IOSQuickActionsApi?,
messageChannelSuffix: String = ""
) {
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: IOSQuickActionsApi?, messageChannelSuffix: String = "") {
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
/// Sets the dynamic shortcuts for the app.
let setShortcutItemsChannel = FlutterBasicMessageChannel(
name:
"dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.setShortcutItems\(channelSuffix)",
binaryMessenger: binaryMessenger, codec: codec)
let setShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.setShortcutItems\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
setShortcutItemsChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
Expand All @@ -177,10 +174,7 @@ class IOSQuickActionsApiSetup {
setShortcutItemsChannel.setMessageHandler(nil)
}
/// Removes all dynamic shortcuts.
let clearShortcutItemsChannel = FlutterBasicMessageChannel(
name:
"dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.clearShortcutItems\(channelSuffix)",
binaryMessenger: binaryMessenger, codec: codec)
let clearShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.clearShortcutItems\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
clearShortcutItemsChannel.setMessageHandler { _, reply in
do {
Expand All @@ -198,8 +192,7 @@ class IOSQuickActionsApiSetup {
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
protocol IOSQuickActionsFlutterApiProtocol {
/// Sends a string representing a shortcut from the native platform to the app.
func launchAction(
action actionArg: String, completion: @escaping (Result<Void, PigeonError>) -> Void)
func launchAction(action actionArg: String, completion: @escaping (Result<Void, PigeonError>) -> Void)
}
class IOSQuickActionsFlutterApi: IOSQuickActionsFlutterApiProtocol {
private let binaryMessenger: FlutterBinaryMessenger
Expand All @@ -212,13 +205,9 @@ class IOSQuickActionsFlutterApi: IOSQuickActionsFlutterApiProtocol {
return messagesPigeonCodec.shared
}
/// Sends a string representing a shortcut from the native platform to the app.
func launchAction(
action actionArg: String, completion: @escaping (Result<Void, PigeonError>) -> Void
) {
let channelName: String =
"dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(
name: channelName, binaryMessenger: binaryMessenger, codec: codec)
func launchAction(action actionArg: String, completion: @escaping (Result<Void, PigeonError>) -> Void) {
let channelName: String = "dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([actionArg] as [Any?]) { response in
guard let listResponse = response as? [Any?] else {
completion(.failure(createConnectionError(withChannelName: channelName)))
Expand Down
54 changes: 23 additions & 31 deletions packages/quick_actions/quick_actions_ios/lib/messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ PlatformException _createConnectionError(String channelName) {
);
}

List<Object?> wrapResponse(
{Object? result, PlatformException? error, bool empty = false}) {
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
}
Expand All @@ -34,6 +33,7 @@ class ShortcutItemMessage {
ShortcutItemMessage({
required this.type,
required this.localizedTitle,
this.localizedSubtitle,
this.icon,
});

Expand All @@ -43,13 +43,17 @@ class ShortcutItemMessage {
/// Localized title of the item.
String localizedTitle;

/// Localized subtitle of the item.
String? localizedSubtitle;

/// Name of native resource to be displayed as the icon for this item.
String? icon;

Object encode() {
return <Object?>[
type,
localizedTitle,
localizedSubtitle,
icon,
];
}
Expand All @@ -59,11 +63,13 @@ class ShortcutItemMessage {
return ShortcutItemMessage(
type: result[0]! as String,
localizedTitle: result[1]! as String,
icon: result[2] as String?,
localizedSubtitle: result[2] as String?,
icon: result[3] as String?,
);
}
}


class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
Expand All @@ -79,7 +85,7 @@ class _PigeonCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
case 129:
return ShortcutItemMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
Expand All @@ -91,11 +97,9 @@ class IOSQuickActionsApi {
/// Constructor for [IOSQuickActionsApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
IOSQuickActionsApi(
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
IOSQuickActionsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: __pigeon_binaryMessenger = binaryMessenger,
__pigeon_messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
__pigeon_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? __pigeon_binaryMessenger;

static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
Expand All @@ -104,10 +108,8 @@ class IOSQuickActionsApi {

/// Sets the dynamic shortcuts for the app.
Future<void> setShortcutItems(List<ShortcutItemMessage?> itemsList) async {
final String __pigeon_channelName =
'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.setShortcutItems$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.setShortcutItems$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
Expand All @@ -129,10 +131,8 @@ class IOSQuickActionsApi {

/// Removes all dynamic shortcuts.
Future<void> clearShortcutItems() async {
final String __pigeon_channelName =
'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.clearShortcutItems$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel =
BasicMessageChannel<Object?>(
final String __pigeon_channelName = 'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.clearShortcutItems$__pigeon_messageChannelSuffix';
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
__pigeon_channelName,
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
Expand All @@ -159,25 +159,18 @@ abstract class IOSQuickActionsFlutterApi {
/// Sends a string representing a shortcut from the native platform to the app.
void launchAction(String action);

static void setUp(
IOSQuickActionsFlutterApi? api, {
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) {
messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
static void setUp(IOSQuickActionsFlutterApi? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
Object?>(
'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction$messageChannelSuffix',
pigeonChannelCodec,
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
__pigeon_channel.setMessageHandler(null);
} else {
__pigeon_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction was null.');
'Argument for dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_action = (args[0] as String?);
assert(arg_action != null,
Expand All @@ -187,9 +180,8 @@ abstract class IOSQuickActionsFlutterApi {
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()));
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class QuickActionsIos extends QuickActionsPlatform {
return ShortcutItemMessage(
type: item.type,
localizedTitle: item.localizedTitle,
localizedSubtitle: item.localizedSubtitle,
icon: item.icon,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ShortcutItemMessage {
ShortcutItemMessage(
this.type,
this.localizedTitle,
this.localizedSubtitle,
this.icon,
);

Expand All @@ -24,6 +25,9 @@ class ShortcutItemMessage {
/// Localized title of the item.
String localizedTitle;

/// Localized subtitle of the item.
String? localizedSubtitle;

/// Name of native resource to be displayed as the icon for this item.
String? icon;
}
Expand Down
Loading