Skip to content

[quick_actions] add localizedSubtitle for iOS #8038

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

Merged
merged 24 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
929fdea
[quick_actions] add localizedSubtitle for iOS
GiacomoPignoni Jun 23, 2024
4bea2bc
test and changelog
GiacomoPignoni Jun 23, 2024
fd8a73a
add deps override
GiacomoPignoni Jun 26, 2024
4cba4da
update ios changelog
GiacomoPignoni Jun 26, 2024
1886a75
update platform interface changelog
GiacomoPignoni Jun 26, 2024
3dd729f
Merge branch 'main' into quick_action/subtitle
sinyu1012 Nov 8, 2024
bf72048
update changelog
sinyu1012 Nov 8, 2024
a0ac67e
revert quick_actions_android changes
sinyu1012 Nov 8, 2024
ce569d9
opt QuickActionsPlugin
sinyu1012 Nov 8, 2024
2bf8256
update notes
sinyu1012 Nov 8, 2024
f644114
update quick_actions_ios example & UITests
sinyu1012 Nov 13, 2024
4b38b32
format quick_actions_ios/messages.g.swift
sinyu1012 Nov 13, 2024
54e0a39
format swift
sinyu1012 Nov 13, 2024
550dfe3
Update packages/quick_actions/quick_actions_android/example/pubspec.yaml
sinyu1012 Nov 15, 2024
977992e
Update packages/quick_actions/quick_actions_android/pubspec.yaml
sinyu1012 Nov 15, 2024
3568750
update quick_actions example code
sinyu1012 Nov 15, 2024
9fca7cf
Merge branch 'main' into quick_action/subtitle
sinyu1012 Nov 22, 2024
ee8dc3f
update dependencies
sinyu1012 Nov 22, 2024
efb9975
format code
sinyu1012 Nov 22, 2024
8782df8
format code
sinyu1012 Nov 22, 2024
52eb23b
update version
sinyu1012 Nov 22, 2024
4783ff8
Merge branch 'main' into quick_action/subtitle
sinyu1012 Dec 10, 2024
8d663b7
Merge branch 'main' into quick_action/subtitle
sinyu1012 Dec 11, 2024
f42fb39
update dependencies
sinyu1012 Dec 11, 2024
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
4 changes: 4 additions & 0 deletions packages/quick_actions/quick_actions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.9

* Adds localizedSubtitle field for iOS quick actions.

## 1.0.8

* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.
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')
]);
```

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.4.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,4 @@ dev_dependencies:

flutter:
uses-material-design: true

1 change: 1 addition & 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,4 @@ dev_dependencies:
topics:
- quick-actions
- os-integration

3 changes: 2 additions & 1 deletion packages/quick_actions/quick_actions_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 1.1.2

* Adds localizedSubtitle field for iOS quick actions.
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.

## 1.1.1
Expand Down
5 changes: 5 additions & 0 deletions packages/quick_actions/quick_actions_ios/example/pubspec.yaml
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}}
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,15 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA
-> UIApplicationShortcutItem?
{

let type = shortcut.type
let localizedTitle = shortcut.localizedTitle

let icon = (shortcut.icon).map {
UIApplicationShortcutIcon(templateImageName: $0)
}

// type and localizedTitle are required.
return UIApplicationShortcutItem(
type: type,
localizedTitle: localizedTitle,
localizedSubtitle: nil,
type: shortcut.type,
localizedTitle: shortcut.localizedTitle,
localizedSubtitle: shortcut.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