From 409cd34f452015d5c5dd661aeb942da7c2dc60d0 Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Wed, 18 Oct 2023 03:31:53 -0700 Subject: [PATCH 01/10] swift --- .../quick_actions_ios/CHANGELOG.md | 4 + .../ios/Runner.xcodeproj/project.pbxproj | 11 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../DefaultShortcutItemParserTests.swift | 39 +--- .../Mocks/MockBinaryMessenger.swift | 40 ++++ .../RunnerTests/Mocks/MockMethodChannel.swift | 14 -- .../Mocks/MockShortcutItemParser.swift | 4 +- .../RunnerTests/QuickActionsPluginTests.swift | 135 +++-------- .../ios/Classes/MethodChannel.swift | 16 -- .../ios/Classes/QuickActionsPlugin.swift | 49 ++-- .../ios/Classes/ShortcutItemParser.swift | 18 +- .../ios/Classes/messages.g.swift | 169 ++++++++++++++ .../quick_actions_ios/lib/messages.g.dart | 160 +++++++++++++ .../lib/quick_actions_ios.dart | 60 ++--- .../quick_actions_ios/pigeons/copyright.txt | 3 + .../quick_actions_ios/pigeons/messages.dart | 45 ++++ .../quick_actions_ios/pubspec.yaml | 3 +- .../test/quick_actions_ios_test.dart | 214 ++++++------------ .../quick_actions_ios/test/test_api.g.dart | 14 ++ 19 files changed, 619 insertions(+), 381 deletions(-) create mode 100644 packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockBinaryMessenger.swift delete mode 100644 packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockMethodChannel.swift delete mode 100644 packages/quick_actions/quick_actions_ios/ios/Classes/MethodChannel.swift create mode 100644 packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift create mode 100644 packages/quick_actions/quick_actions_ios/lib/messages.g.dart create mode 100644 packages/quick_actions/quick_actions_ios/pigeons/copyright.txt create mode 100644 packages/quick_actions/quick_actions_ios/pigeons/messages.dart create mode 100644 packages/quick_actions/quick_actions_ios/test/test_api.g.dart diff --git a/packages/quick_actions/quick_actions_ios/CHANGELOG.md b/packages/quick_actions/quick_actions_ios/CHANGELOG.md index 5272ba930d5..e0321a6056a 100644 --- a/packages/quick_actions/quick_actions_ios/CHANGELOG.md +++ b/packages/quick_actions/quick_actions_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.8 + +* Changes method channels to pigeon. + ## 1.0.7 * Adds pub topics to package metadata. diff --git a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj index 395847ae2de..d471313d3e0 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -10,13 +10,13 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 2632072169FF635893D8EB4D /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 436668746754BEEA28B76E55 /* libPods-RunnerTests.a */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 47B0F9522ADE93E300947B4D /* MockBinaryMessenger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */; }; 6A841C2B6AED5CF8DB2A1894 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C35AD3650AB6BF850E016715 /* libPods-Runner.a */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - E092A7ED28D10802005C7F67 /* MockMethodChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7EA28D10801005C7F67 /* MockMethodChannel.swift */; }; E092A7EE28D10802005C7F67 /* QuickActionsPluginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7EB28D10802005C7F67 /* QuickActionsPluginTests.swift */; }; E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */; }; E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */; }; @@ -61,6 +61,7 @@ 33E20B3626EFCDFC00A4A191 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 436668746754BEEA28B76E55 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockBinaryMessenger.swift; sourceTree = ""; }; 5278439583922091276A37C9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 686BE82D25E58CCF00862533 /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 686BE83125E58CCF00862533 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -78,7 +79,6 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9D27FE1F0F21D4D47DDA16DE /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; C35AD3650AB6BF850E016715 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - E092A7EA28D10801005C7F67 /* MockMethodChannel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockMethodChannel.swift; sourceTree = ""; }; E092A7EB28D10802005C7F67 /* QuickActionsPluginTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickActionsPluginTests.swift; sourceTree = ""; }; E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShortcutItemProvider.swift; sourceTree = ""; }; E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultShortcutItemParserTests.swift; sourceTree = ""; }; @@ -215,7 +215,7 @@ E092A7F228D10908005C7F67 /* Mocks */ = { isa = PBXGroup; children = ( - E092A7EA28D10801005C7F67 /* MockMethodChannel.swift */, + 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */, E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */, E0A075D429147FE200329BAE /* MockShortcutItemParser.swift */, ); @@ -289,7 +289,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 33E20B3126EFCDFC00A4A191 = { @@ -364,6 +364,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -435,7 +436,7 @@ buildActionMask = 2147483647; files = ( E092A7EE28D10802005C7F67 /* QuickActionsPluginTests.swift in Sources */, - E092A7ED28D10802005C7F67 /* MockMethodChannel.swift in Sources */, + 47B0F9522ADE93E300947B4D /* MockBinaryMessenger.swift in Sources */, E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */, E0A075D529147FE200329BAE /* MockShortcutItemParser.swift in Sources */, E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */, diff --git a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1ba2b47c79f..2810c229f3a 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ FlutterBinaryMessengerConnection { + handlers[channel] = handler + return .init(handlers.count) + } + + func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) {} +} diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockMethodChannel.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockMethodChannel.swift deleted file mode 100644 index b52fa1daec9..00000000000 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockMethodChannel.swift +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - -@testable import quick_actions_ios - -final class MockMethodChannel: MethodChannel { - var invokeMethodStub: ((_ methods: String, _ arguments: Any?) -> Void)? = nil - func invokeMethod(_ method: String, arguments: Any?) { - invokeMethodStub?(method, arguments) - } -} diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift index 3b5a0965395..fd9032ff625 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift @@ -8,9 +8,9 @@ import Foundation final class MockShortcutItemParser: ShortcutItemParser { - var parseShortcutItemsStub: ((_ items: [[String: Any]]) -> [UIApplicationShortcutItem])? = nil + var parseShortcutItemsStub: ((_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem])? = nil - func parseShortcutItems(_ items: [[String: Any]]) -> [UIApplicationShortcutItem] { + func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { return parseShortcutItemsStub?(items) ?? [] } } diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift index 268a89ba5a5..d542bc85b24 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift @@ -10,11 +10,12 @@ import XCTest class QuickActionsPluginTests: XCTestCase { func testHandleMethodCall_setShortcutItems() { - let rawItem = [ - "type": "SearchTheThing", - "localizedTitle": "Search the thing", - "icon": "search_the_thing.png", - ] + let rawItem = ShortcutItemMessage( + type: "SearchTheThing", + localizedTitle: "Search the thing", + icon: "search_the_thing.png" + ) + let item = UIApplicationShortcutItem( type: "SearchTheThing", localizedTitle: "Search the thing", @@ -22,30 +23,26 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let call = FlutterMethodCall(methodName: "setShortcutItems", arguments: [rawItem]) - - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) let parseShortcutItemsExpectation = expectation( description: "parseShortcutItems must be called.") mockShortcutItemParser.parseShortcutItemsStub = { items in - XCTAssertEqual(items as? [[String: String]], [rawItem]) + XCTAssertEqual(items.first!.icon, rawItem.icon) + XCTAssertEqual(items.first!.localizedTitle, rawItem.localizedTitle) + XCTAssertEqual(items.first!.type, rawItem.type) parseShortcutItemsExpectation.fulfill() return [item] } - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertNil(result, "result block must be called with nil.") - resultExpectation.fulfill() - } + try? plugin.setShortcutItems(itemsList: [rawItem]) XCTAssertEqual(mockShortcutItemProvider.shortcutItems, [item], "Must set shortcut items.") waitForExpectations(timeout: 1) } @@ -58,80 +55,30 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let call = FlutterMethodCall(methodName: "clearShortcutItems", arguments: nil) - let mockChannel = MockMethodChannel() - let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() - - mockShortcutItemProvider.shortcutItems = [item] - - let plugin = QuickActionsPlugin( - channel: mockChannel, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertNil(result, "result block must be called with nil.") - resultExpectation.fulfill() - } - - XCTAssertEqual(mockShortcutItemProvider.shortcutItems, [], "Must clear shortcut items.") - waitForExpectations(timeout: 1) - } - - func testHandleMethodCall_getLaunchAction() { - let call = FlutterMethodCall(methodName: "getLaunchAction", arguments: nil) - - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertNil(result, "result block must be called with nil.") - resultExpectation.fulfill() - } - - waitForExpectations(timeout: 1) - } - - func testHandleMethodCall_nonExistMethods() { - let call = FlutterMethodCall(methodName: "nonExist", arguments: nil) - - let mockChannel = MockMethodChannel() - let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() - - let plugin = QuickActionsPlugin( - channel: mockChannel, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + mockShortcutItemProvider.shortcutItems = [item] - let resultExpectation = expectation(description: "result block must be called.") + try? plugin.clearShortcutItems() - plugin.handle(call) { result in - XCTAssertEqual( - result as? NSObject, FlutterMethodNotImplemented, - "result block must be called with FlutterMethodNotImplemented") - resultExpectation.fulfill() - } + XCTAssertEqual(mockShortcutItemProvider.shortcutItems, [], "Must clear shortcut items.") - waitForExpectations(timeout: 1) } func testApplicationPerformActionForShortcutItem() { - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) @@ -143,28 +90,28 @@ class QuickActionsPluginTests: XCTestCase { userInfo: nil) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - mockChannel.invokeMethodStub = { method, arguments in - XCTAssertEqual(method, "launch") - XCTAssertEqual(arguments as? String, item.type) + plugin.testStub = { invokeMethodExpectation.fulfill() } let actionResult = plugin.application( UIApplication.shared, performActionFor: item - ) { success in /* no-op */ } + ) { success in + // noop + } XCTAssert(actionResult, "performActionForShortcutItem must return true.") waitForExpectations(timeout: 1) } func testApplicationDidFinishLaunchingWithOptions_launchWithShortcut() { - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) @@ -183,12 +130,12 @@ class QuickActionsPluginTests: XCTestCase { } func testApplicationDidFinishLaunchingWithOptions_launchWithoutShortcut() { - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) @@ -198,19 +145,15 @@ class QuickActionsPluginTests: XCTestCase { } func testApplicationDidBecomeActive_launchWithoutShortcut() { - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) - mockChannel.invokeMethodStub = { _, _ in - XCTFail("invokeMethod should not be called if launch without shortcut.") - } - let launchResult = plugin.application(UIApplication.shared, didFinishLaunchingWithOptions: [:]) XCTAssert( launchResult, "didFinishLaunchingWithOptions must return true if not launched from shortcut.") @@ -226,19 +169,17 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - mockChannel.invokeMethodStub = { method, arguments in - XCTAssertEqual(method, "launch") - XCTAssertEqual(arguments as? String, item.type) + plugin.testStub = { invokeMethodExpectation.fulfill() } @@ -261,20 +202,20 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let mockChannel = MockMethodChannel() + let mockMessenger = MockBinaryMessenger() let mockShortcutItemProvider = MockShortcutItemProvider() let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - channel: mockChannel, + messenger: mockMessenger, shortcutItemProvider: mockShortcutItemProvider, shortcutItemParser: mockShortcutItemParser) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - var invokeMehtodCount = 0 - mockChannel.invokeMethodStub = { method, arguments in - invokeMehtodCount += 1 + var invokeMethodCount = 0 + plugin.testStub = { + invokeMethodCount += 1 invokeMethodExpectation.fulfill() } @@ -287,8 +228,6 @@ class QuickActionsPluginTests: XCTestCase { plugin.applicationDidBecomeActive(UIApplication.shared) waitForExpectations(timeout: 1) - - XCTAssertEqual(invokeMehtodCount, 1, "shortcut should only be handled once per launch.") } } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/MethodChannel.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/MethodChannel.swift deleted file mode 100644 index 5d52790dd4b..00000000000 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/MethodChannel.swift +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter - -/// A channel for platform code to communicate with the Dart code. -protocol MethodChannel { - /// Invokes a method in Dart code. - /// - Parameter method the method name. - /// - Parameter arguments the method arguments. - func invokeMethod(_ method: String, arguments: Any?) -} - -/// A default implementation of the `MethodChannel` protocol. -extension FlutterMethodChannel: MethodChannel {} diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 8522c5ff528..ec84cb51ac5 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -4,48 +4,39 @@ import Flutter -public final class QuickActionsPlugin: NSObject, FlutterPlugin { +public final class QuickActionsPlugin: NSObject, FlutterPlugin, IosQuickActionsApi { public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel( - name: "plugins.flutter.io/quick_actions_ios", - binaryMessenger: registrar.messenger()) - let instance = QuickActionsPlugin(channel: channel) - registrar.addMethodCallDelegate(instance, channel: channel) + let messenger = registrar.messenger() + let instance = QuickActionsPlugin(messenger: messenger) + IosQuickActionsApiSetup.setUp(binaryMessenger: messenger, api: instance) registrar.addApplicationDelegate(instance) } - private let channel: MethodChannel private let shortcutItemProvider: ShortcutItemProviding private let shortcutItemParser: ShortcutItemParser + private let flutterApi: IosQuickActionsFlutterApi /// The type of the shortcut item selected when launching the app. private var launchingShortcutType: String? = nil init( - channel: MethodChannel, + messenger: FlutterBinaryMessenger, shortcutItemProvider: ShortcutItemProviding = UIApplication.shared, shortcutItemParser: ShortcutItemParser = DefaultShortcutItemParser() ) { - self.channel = channel self.shortcutItemProvider = shortcutItemProvider self.shortcutItemParser = shortcutItemParser + self.flutterApi = IosQuickActionsFlutterApi(binaryMessenger: messenger) } - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "setShortcutItems": - // `arguments` must be an array of dictionaries - let items = call.arguments as! [[String: Any]] - shortcutItemProvider.shortcutItems = shortcutItemParser.parseShortcutItems(items) - result(nil) - case "clearShortcutItems": - shortcutItemProvider.shortcutItems = [] - result(nil) - case "getLaunchAction": - result(nil) - case _: - result(FlutterMethodNotImplemented) - } + var testStub: (() -> Void)? = nil + + func setShortcutItems(itemsList: [ShortcutItemMessage]) throws { + shortcutItemProvider.shortcutItems = shortcutItemParser.parseShortcutItems(itemsList) + } + + func clearShortcutItems() throws { + shortcutItemProvider.shortcutItems = [] } public func application( @@ -80,12 +71,14 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin { public func applicationDidBecomeActive(_ application: UIApplication) { if let shortcutType = launchingShortcutType { handleShortcut(shortcutType) - launchingShortcutType = nil + self.launchingShortcutType = nil } } - private func handleShortcut(_ shortcut: String) { - channel.invokeMethod("launch", arguments: shortcut) + func handleShortcut(_ shortcut: String) { + self.testStub?() + flutterApi.launchAction(action: shortcut) { + // noop + } } - } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift index 0945b4a386f..583af4105c6 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift @@ -12,26 +12,24 @@ protocol ShortcutItemParser { /// - Parameter items an array of raw shortcut items to be parsed. /// - Returns an array of parsed shortcut items to be set. /// - func parseShortcutItems(_ items: [[String: Any]]) -> [UIApplicationShortcutItem] + func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] } /// A default implementation of the `ShortcutItemParser` protocol. final class DefaultShortcutItemParser: ShortcutItemParser { - func parseShortcutItems(_ items: [[String: Any]]) -> [UIApplicationShortcutItem] { + func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { return items.compactMap { deserializeShortcutItem(with: $0) } } - private func deserializeShortcutItem(with serialized: [String: Any]) -> UIApplicationShortcutItem? + private func deserializeShortcutItem(with serialized: ShortcutItemMessage) + -> UIApplicationShortcutItem? { - guard - let type = serialized["type"] as? String, - let localizedTitle = serialized["localizedTitle"] as? String - else { - return nil - } - let icon = (serialized["icon"] as? String).map { + let type = serialized.type + let localizedTitle = serialized.localizedTitle + + let icon = (serialized.icon).map { UIApplicationShortcutIcon(templateImageName: $0) } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift new file mode 100644 index 00000000000..59ba5eca41c --- /dev/null +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift @@ -0,0 +1,169 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation +#if os(iOS) +import Flutter +#elseif os(macOS) +import FlutterMacOS +#else +#error("Unsupported platform.") +#endif + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)" + ] +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +/// Home screen quick-action shortcut item. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct ShortcutItemMessage { + /// The identifier of this item; should be unique within the app. + var type: String + /// Localized title of the item. + var localizedTitle: String + /// Name of native resource to be displayed as the icon for this item. + var icon: String? = nil + + static func fromList(_ list: [Any?]) -> ShortcutItemMessage? { + let type = list[0] as! String + let localizedTitle = list[1] as! String + let icon: String? = nilOrValue(list[2]) + + return ShortcutItemMessage( + type: type, + localizedTitle: localizedTitle, + icon: icon + ) + } + func toList() -> [Any?] { + return [ + type, + localizedTitle, + icon, + ] + } +} +private class IosQuickActionsApiCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + return ShortcutItemMessage.fromList(self.readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class IosQuickActionsApiCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? ShortcutItemMessage { + super.writeByte(128) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class IosQuickActionsApiCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return IosQuickActionsApiCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return IosQuickActionsApiCodecWriter(data: data) + } +} + +class IosQuickActionsApiCodec: FlutterStandardMessageCodec { + static let shared = IosQuickActionsApiCodec(readerWriter: IosQuickActionsApiCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol IosQuickActionsApi { + /// Sets the dynamic shortcuts for the app. + func setShortcutItems(itemsList: [ShortcutItemMessage]) throws + /// Removes all dynamic shortcuts. + func clearShortcutItems() throws +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class IosQuickActionsApiSetup { + /// The codec used by IosQuickActionsApi. + static var codec: FlutterStandardMessageCodec { IosQuickActionsApiCodec.shared } + /// Sets up an instance of `IosQuickActionsApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: IosQuickActionsApi?) { + /// Sets the dynamic shortcuts for the app. + let setShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.setShortcutItems", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + setShortcutItemsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let itemsListArg = args[0] as! [ShortcutItemMessage] + do { + try api.setShortcutItems(itemsList: itemsListArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + setShortcutItemsChannel.setMessageHandler(nil) + } + /// Removes all dynamic shortcuts. + let clearShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.clearShortcutItems", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + clearShortcutItemsChannel.setMessageHandler { _, reply in + do { + try api.clearShortcutItems() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearShortcutItemsChannel.setMessageHandler(nil) + } + } +} +/// Generated class from Pigeon that represents Flutter messages that can be called from Swift. +class IosQuickActionsFlutterApi { + private let binaryMessenger: FlutterBinaryMessenger + init(binaryMessenger: FlutterBinaryMessenger){ + self.binaryMessenger = binaryMessenger + } + /// Sends a string representing a shortcut from the native platform to the app. + func launchAction(action actionArg: String, completion: @escaping () -> Void) { + let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction", binaryMessenger: binaryMessenger) + channel.sendMessage([actionArg] as [Any?]) { _ in + completion() + } + } +} diff --git a/packages/quick_actions/quick_actions_ios/lib/messages.g.dart b/packages/quick_actions/quick_actions_ios/lib/messages.g.dart new file mode 100644 index 00000000000..13a05bc005d --- /dev/null +++ b/packages/quick_actions/quick_actions_ios/lib/messages.g.dart @@ -0,0 +1,160 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +/// Home screen quick-action shortcut item. +class ShortcutItemMessage { + ShortcutItemMessage({ + required this.type, + required this.localizedTitle, + this.icon, + }); + + /// The identifier of this item; should be unique within the app. + String type; + + /// Localized title of the item. + String localizedTitle; + + /// Name of native resource to be displayed as the icon for this item. + String? icon; + + Object encode() { + return [ + type, + localizedTitle, + icon, + ]; + } + + static ShortcutItemMessage decode(Object result) { + result as List; + return ShortcutItemMessage( + type: result[0]! as String, + localizedTitle: result[1]! as String, + icon: result[2] as String?, + ); + } +} + +class _IosQuickActionsApiCodec extends StandardMessageCodec { + const _IosQuickActionsApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is ShortcutItemMessage) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return ShortcutItemMessage.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +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}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _IosQuickActionsApiCodec(); + + /// Sets the dynamic shortcuts for the app. + Future setShortcutItems( + List arg_itemsList) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.setShortcutItems', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_itemsList]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + /// Removes all dynamic shortcuts. + Future clearShortcutItems() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.clearShortcutItems', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +abstract class IosQuickActionsFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Sends a string representing a shortcut from the native platform to the app. + void launchAction(String action); + + static void setup(IosQuickActionsFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction was null.'); + final List args = (message as List?)!; + final String? arg_action = (args[0] as String?); + assert(arg_action != null, + 'Argument for dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction was null, expected non-null String.'); + api.launchAction(arg_action!); + return; + }); + } + } + } +} diff --git a/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart b/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart index d19c9ee371b..31d85e6120f 100644 --- a/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart +++ b/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart @@ -3,54 +3,58 @@ // found in the LICENSE file. import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'package:quick_actions_platform_interface/quick_actions_platform_interface.dart'; +import 'messages.g.dart'; + export 'package:quick_actions_platform_interface/types/types.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/quick_actions_ios'); +late QuickActionHandler _handler; /// An implementation of [QuickActionsPlatform] for iOS. class QuickActionsIos extends QuickActionsPlatform { + /// Creates a new plugin implementation instance. + QuickActionsIos({ + @visibleForTesting IosQuickActionsApi? api, + }) : _hostApi = api ?? IosQuickActionsApi(); + + final IosQuickActionsApi _hostApi; + /// Registers this class as the default instance of [QuickActionsPlatform]. static void registerWith() { QuickActionsPlatform.instance = QuickActionsIos(); } - /// The MethodChannel that is being used by this implementation of the plugin. - @visibleForTesting - MethodChannel get channel => _channel; - @override Future initialize(QuickActionHandler handler) async { - channel.setMethodCallHandler((MethodCall call) async { - assert(call.method == 'launch'); - handler(call.arguments as String); - }); - final String? action = - await channel.invokeMethod('getLaunchAction'); - if (action != null) { - handler(action); - } + final _QuickActionHandlerApi quickActionsHandlerApi = + _QuickActionHandlerApi(); + IosQuickActionsFlutterApi.setup(quickActionsHandlerApi); + _handler = handler; } @override Future setShortcutItems(List items) async { - final List> itemsList = - items.map(_serializeItem).toList(); - await channel.invokeMethod('setShortcutItems', itemsList); + await _hostApi.setShortcutItems( + items.map(_shortcutItemToShortcutItemMessage).toList(), + ); } @override - Future clearShortcutItems() => - channel.invokeMethod('clearShortcutItems'); - - Map _serializeItem(ShortcutItem item) { - return { - 'type': item.type, - 'localizedTitle': item.localizedTitle, - 'icon': item.icon, - }; + Future clearShortcutItems() => _hostApi.clearShortcutItems(); + + ShortcutItemMessage _shortcutItemToShortcutItemMessage(ShortcutItem item) { + return ShortcutItemMessage( + type: item.type, + localizedTitle: item.localizedTitle, + icon: item.icon, + ); + } +} + +class _QuickActionHandlerApi extends IosQuickActionsFlutterApi { + @override + void launchAction(String action) { + _handler(action); } } diff --git a/packages/quick_actions/quick_actions_ios/pigeons/copyright.txt b/packages/quick_actions/quick_actions_ios/pigeons/copyright.txt new file mode 100644 index 00000000000..1236b63caf3 --- /dev/null +++ b/packages/quick_actions/quick_actions_ios/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/packages/quick_actions/quick_actions_ios/pigeons/messages.dart b/packages/quick_actions/quick_actions_ios/pigeons/messages.dart new file mode 100644 index 00000000000..7e173fee6ae --- /dev/null +++ b/packages/quick_actions/quick_actions_ios/pigeons/messages.dart @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/messages.g.dart', + dartTestOut: 'test/test_api.g.dart', + swiftOut: 'ios/Classes/messages.g.swift', + copyrightHeader: 'pigeons/copyright.txt', +)) + +/// Home screen quick-action shortcut item. +class ShortcutItemMessage { + ShortcutItemMessage( + this.type, + this.localizedTitle, + this.icon, + ); + + /// The identifier of this item; should be unique within the app. + String type; + + /// Localized title of the item. + String localizedTitle; + + /// Name of native resource to be displayed as the icon for this item. + String? icon; +} + +@HostApi() +abstract class IosQuickActionsApi { + /// Sets the dynamic shortcuts for the app. + void setShortcutItems(List itemsList); + + /// Removes all dynamic shortcuts. + void clearShortcutItems(); +} + +@FlutterApi() +abstract class IosQuickActionsFlutterApi { + /// Sends a string representing a shortcut from the native platform to the app. + void launchAction(String action); +} diff --git a/packages/quick_actions/quick_actions_ios/pubspec.yaml b/packages/quick_actions/quick_actions_ios/pubspec.yaml index b7e31d8646b..4268a1aa5de 100644 --- a/packages/quick_actions/quick_actions_ios/pubspec.yaml +++ b/packages/quick_actions/quick_actions_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: quick_actions_ios description: An implementation for the iOS platform of the Flutter `quick_actions` plugin. repository: https://github.com/flutter/packages/tree/main/packages/quick_actions/quick_actions_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 1.0.7 +version: 1.0.8 environment: sdk: ">=2.19.0 <4.0.0" @@ -26,6 +26,7 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + pigeon: ^11.0.1 plugin_platform_interface: ^2.1.2 topics: diff --git a/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart b/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart index d2b062fff22..90f49a8a8c2 100644 --- a/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart +++ b/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart @@ -2,171 +2,89 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:quick_actions_ios/messages.g.dart'; import 'package:quick_actions_ios/quick_actions_ios.dart'; import 'package:quick_actions_platform_interface/quick_actions_platform_interface.dart'; +const String LAUNCH_ACTION_STRING = 'aString'; + void main() { TestWidgetsFlutterBinding.ensureInitialized(); - group('$QuickActionsIos', () { - late List log; + final _FakeQuickActionsApi api = _FakeQuickActionsApi(); + final QuickActionsIos quickActions = QuickActionsIos(api: api); - setUp(() { - log = []; - }); - - QuickActionsIos buildQuickActionsPlugin() { - final QuickActionsIos quickActions = QuickActionsIos(); - _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .setMockMethodCallHandler(quickActions.channel, - (MethodCall methodCall) async { - log.add(methodCall); - return ''; - }); - - return quickActions; - } + test('registerWith() registers correct instance', () { + QuickActionsIos.registerWith(); + expect(QuickActionsPlatform.instance, isA()); + }); - test('registerWith() registers correct instance', () { - QuickActionsIos.registerWith(); - expect(QuickActionsPlatform.instance, isA()); + group('#initialize', () { + test('initialize', () async { + await quickActions.initialize((_) {}); }); + }); - group('#initialize', () { - test('passes getLaunchAction on launch method', () { - final QuickActionsIos quickActions = buildQuickActionsPlugin(); - quickActions.initialize((String type) {}); - - expect( - log, - [ - isMethodCall('getLaunchAction', arguments: null), - ], - ); - }); - - test('initialize', () async { - final QuickActionsIos quickActions = buildQuickActionsPlugin(); - final Completer quickActionsHandler = Completer(); - await quickActions - .initialize((_) => quickActionsHandler.complete(true)); - expect( - log, - [ - isMethodCall('getLaunchAction', arguments: null), - ], - ); - log.clear(); - - expect(quickActionsHandler.future, completion(isTrue)); - }); - }); + test('setShortCutItems', () async { + await quickActions.initialize((String type) {}); + const ShortcutItem item = + ShortcutItem(type: 'test', localizedTitle: 'title', icon: 'icon.svg'); + await quickActions.setShortcutItems([item]); - group('#setShortCutItems', () { - test('passes shortcutItem through channel', () { - final QuickActionsIos quickActions = buildQuickActionsPlugin(); - quickActions.initialize((String type) {}); - quickActions.setShortcutItems([ - const ShortcutItem( - type: 'test', localizedTitle: 'title', icon: 'icon.svg') - ]); - - expect( - log, - [ - isMethodCall('getLaunchAction', arguments: null), - isMethodCall('setShortcutItems', arguments: >[ - { - 'type': 'test', - 'localizedTitle': 'title', - 'icon': 'icon.svg', - } - ]), - ], - ); - }); - - test('setShortcutItems with demo data', () async { - const String type = 'type'; - const String localizedTitle = 'localizedTitle'; - const String icon = 'icon'; - final QuickActionsIos quickActions = buildQuickActionsPlugin(); - await quickActions.setShortcutItems( - const [ - ShortcutItem(type: type, localizedTitle: localizedTitle, icon: icon) - ], - ); - expect( - log, - [ - isMethodCall( - 'setShortcutItems', - arguments: >[ - { - 'type': type, - 'localizedTitle': localizedTitle, - 'icon': icon, - } - ], - ), - ], - ); - log.clear(); - }); - }); + expect(api.items.first.type, item.type); + expect(api.items.first.localizedTitle, item.localizedTitle); + expect(api.items.first.icon, item.icon); + }); - group('#clearShortCutItems', () { - test('send clearShortcutItems through channel', () { - final QuickActionsIos quickActions = buildQuickActionsPlugin(); - quickActions.initialize((String type) {}); - quickActions.clearShortcutItems(); - - expect( - log, - [ - isMethodCall('getLaunchAction', arguments: null), - isMethodCall('clearShortcutItems', arguments: null), - ], - ); - }); - - test('clearShortcutItems', () { - final QuickActionsIos quickActions = buildQuickActionsPlugin(); - quickActions.clearShortcutItems(); - expect( - log, - [ - isMethodCall('clearShortcutItems', arguments: null), - ], - ); - log.clear(); - }); - }); + test('clearShortCutItems', () { + quickActions.initialize((String type) {}); + const ShortcutItem item = + ShortcutItem(type: 'test', localizedTitle: 'title', icon: 'icon.svg'); + quickActions.setShortcutItems([item]); + quickActions.clearShortcutItems(); + + expect(api.items.isEmpty, true); }); - group('$ShortcutItem', () { - test('Shortcut item can be constructed', () { - const String type = 'type'; - const String localizedTitle = 'title'; - const String icon = 'foo'; + test('Shortcut item can be constructed', () { + const String type = 'type'; + const String localizedTitle = 'title'; + const String icon = 'foo'; - const ShortcutItem item = - ShortcutItem(type: type, localizedTitle: localizedTitle, icon: icon); + const ShortcutItem item = + ShortcutItem(type: type, localizedTitle: localizedTitle, icon: icon); - expect(item.type, type); - expect(item.localizedTitle, localizedTitle); - expect(item.icon, icon); - }); + expect(item.type, type); + expect(item.localizedTitle, localizedTitle); + expect(item.icon, icon); }); } -/// This allows a value of type T or T? to be treated as a value of type T?. -/// -/// We use this so that APIs that have become non-nullable can still be used -/// with `!` and `?` on the stable branch. -T? _ambiguate(T? value) => value; +class _FakeQuickActionsApi implements IosQuickActionsApi { + List items = []; + bool getLaunchActionCalled = false; + + @override + Future clearShortcutItems() async { + items = []; + return; + } + + @override + Future setShortcutItems(List itemsList) async { + await clearShortcutItems(); + for (final ShortcutItemMessage? element in itemsList) { + items.add(shortcutItemMessageToShortcutItem(element!)); + } + } +} + +/// Conversion tool to change [ShortcutItemMessage] back to [ShortcutItem] +ShortcutItem shortcutItemMessageToShortcutItem(ShortcutItemMessage item) { + return ShortcutItem( + type: item.type, + localizedTitle: item.localizedTitle, + icon: item.icon, + ); +} diff --git a/packages/quick_actions/quick_actions_ios/test/test_api.g.dart b/packages/quick_actions/quick_actions_ios/test/test_api.g.dart new file mode 100644 index 00000000000..021ba0b0256 --- /dev/null +++ b/packages/quick_actions/quick_actions_ios/test/test_api.g.dart @@ -0,0 +1,14 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import +// ignore_for_file: avoid_relative_lib_imports +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:quick_actions_ios/messages.g.dart'; From cbbd1213c4d5ff54d6f04cb44d7520f63f43a8ca Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Wed, 18 Oct 2023 03:33:52 -0700 Subject: [PATCH 02/10] doc --- .../quick_actions_ios/ios/Classes/QuickActionsPlugin.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index ec84cb51ac5..11ddd6fcd2b 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -29,6 +29,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IosQuickActionsA self.flutterApi = IosQuickActionsFlutterApi(binaryMessenger: messenger) } + /// Method to allow for async testing. var testStub: (() -> Void)? = nil func setShortcutItems(itemsList: [ShortcutItemMessage]) throws { From 01599f29c76b358edcf573b9c0ff7f49a4ea9dae Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Thu, 19 Oct 2023 22:33:29 -0700 Subject: [PATCH 03/10] nits and test fixes --- .../ios/Runner.xcodeproj/project.pbxproj | 4 - .../Mocks/MockShortcutItemParser.swift | 16 --- .../RunnerTests/QuickActionsPluginTests.swift | 103 ++++++++---------- .../ios/Classes/QuickActionsPlugin.swift | 34 +++--- .../ios/Classes/messages.g.swift | 48 ++++---- .../quick_actions_ios/lib/messages.g.dart | 50 ++++++--- .../lib/quick_actions_ios.dart | 10 +- .../quick_actions_ios/pigeons/messages.dart | 5 +- .../quick_actions_ios/pubspec.yaml | 2 +- .../test/quick_actions_ios_test.dart | 8 +- .../quick_actions_ios/test/test_api.g.dart | 14 --- 11 files changed, 138 insertions(+), 156 deletions(-) delete mode 100644 packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift delete mode 100644 packages/quick_actions/quick_actions_ios/test/test_api.g.dart diff --git a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj index d471313d3e0..6c1835f4ec5 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -21,7 +21,6 @@ E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */; }; E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */; }; E092A7F628D128EB005C7F67 /* RunnerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F528D128EB005C7F67 /* RunnerUITests.swift */; }; - E0A075D529147FE200329BAE /* MockShortcutItemParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A075D429147FE200329BAE /* MockShortcutItemParser.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -83,7 +82,6 @@ E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShortcutItemProvider.swift; sourceTree = ""; }; E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultShortcutItemParserTests.swift; sourceTree = ""; }; E092A7F528D128EB005C7F67 /* RunnerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerUITests.swift; sourceTree = ""; }; - E0A075D429147FE200329BAE /* MockShortcutItemParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShortcutItemParser.swift; sourceTree = ""; }; F0609304FBCAEC2289164BD5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -217,7 +215,6 @@ children = ( 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */, E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */, - E0A075D429147FE200329BAE /* MockShortcutItemParser.swift */, ); path = Mocks; sourceTree = ""; @@ -438,7 +435,6 @@ E092A7EE28D10802005C7F67 /* QuickActionsPluginTests.swift in Sources */, 47B0F9522ADE93E300947B4D /* MockBinaryMessenger.swift in Sources */, E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */, - E0A075D529147FE200329BAE /* MockShortcutItemParser.swift in Sources */, E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift deleted file mode 100644 index fd9032ff625..00000000000 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockShortcutItemParser.swift +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - -@testable import quick_actions_ios - -final class MockShortcutItemParser: ShortcutItemParser { - - var parseShortcutItemsStub: ((_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem])? = nil - - func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { - return parseShortcutItemsStub?(items) ?? [] - } -} diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift index d542bc85b24..736d4b47120 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift @@ -7,6 +7,18 @@ import XCTest @testable import quick_actions_ios +class MockFlutterApi: IOSQuickActionsFlutterApiProtocol { + /// Method to allow for async testing. + var testStub: ((String) -> Void)? = nil + + func launchAction( + action actionArg: String, completion: @escaping (Result) -> Void + ) { + self.testStub?(actionArg) + completion(.success(Void())) + } +} + class QuickActionsPluginTests: XCTestCase { func testHandleMethodCall_setShortcutItems() { @@ -23,28 +35,15 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) - - let parseShortcutItemsExpectation = expectation( - description: "parseShortcutItems must be called.") - mockShortcutItemParser.parseShortcutItemsStub = { items in - XCTAssertEqual(items.first!.icon, rawItem.icon) - XCTAssertEqual(items.first!.localizedTitle, rawItem.localizedTitle) - XCTAssertEqual(items.first!.type, rawItem.type) - parseShortcutItemsExpectation.fulfill() - return [item] - } + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) - try? plugin.setShortcutItems(itemsList: [rawItem]) + plugin.setShortcutItems(itemsList: [rawItem]) XCTAssertEqual(mockShortcutItemProvider.shortcutItems, [item], "Must set shortcut items.") - waitForExpectations(timeout: 1) } func testHandleMethodCall_clearShortcutItems() { @@ -55,32 +54,28 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) mockShortcutItemProvider.shortcutItems = [item] - try? plugin.clearShortcutItems() + plugin.clearShortcutItems() XCTAssertEqual(mockShortcutItemProvider.shortcutItems, [], "Must clear shortcut items.") } func testApplicationPerformActionForShortcutItem() { - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) let item = UIApplicationShortcutItem( type: "SearchTheThing", @@ -90,7 +85,8 @@ class QuickActionsPluginTests: XCTestCase { userInfo: nil) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - plugin.testStub = { + flutterApi.testStub = { aString in + XCTAssertEqual(aString, item.type) invokeMethodExpectation.fulfill() } @@ -106,14 +102,12 @@ class QuickActionsPluginTests: XCTestCase { } func testApplicationDidFinishLaunchingWithOptions_launchWithShortcut() { - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) let item = UIApplicationShortcutItem( type: "SearchTheThing", @@ -130,14 +124,12 @@ class QuickActionsPluginTests: XCTestCase { } func testApplicationDidFinishLaunchingWithOptions_launchWithoutShortcut() { - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) let launchResult = plugin.application(UIApplication.shared, didFinishLaunchingWithOptions: [:]) XCTAssert( @@ -145,14 +137,12 @@ class QuickActionsPluginTests: XCTestCase { } func testApplicationDidBecomeActive_launchWithoutShortcut() { - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) let launchResult = plugin.application(UIApplication.shared, didFinishLaunchingWithOptions: [:]) XCTAssert( @@ -169,17 +159,16 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - plugin.testStub = { + flutterApi.testStub = { aString in + XCTAssertEqual(aString, item.type) invokeMethodExpectation.fulfill() } @@ -202,19 +191,18 @@ class QuickActionsPluginTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let mockMessenger = MockBinaryMessenger() + let flutterApi: MockFlutterApi = MockFlutterApi() let mockShortcutItemProvider = MockShortcutItemProvider() - let mockShortcutItemParser = MockShortcutItemParser() let plugin = QuickActionsPlugin( - messenger: mockMessenger, - shortcutItemProvider: mockShortcutItemProvider, - shortcutItemParser: mockShortcutItemParser) + flutterApi: flutterApi, + shortcutItemProvider: mockShortcutItemProvider) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") var invokeMethodCount = 0 - plugin.testStub = { + flutterApi.testStub = { aString in + XCTAssertEqual(aString, item.type) invokeMethodCount += 1 invokeMethodExpectation.fulfill() } @@ -228,6 +216,7 @@ class QuickActionsPluginTests: XCTestCase { plugin.applicationDidBecomeActive(UIApplication.shared) waitForExpectations(timeout: 1) - } + XCTAssertEqual(invokeMethodCount, 1, "shortcut should only be handled once per launch.") + } } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 11ddd6fcd2b..ecd3c010546 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -4,39 +4,44 @@ import Flutter -public final class QuickActionsPlugin: NSObject, FlutterPlugin, IosQuickActionsApi { +public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsApi { public static func register(with registrar: FlutterPluginRegistrar) { let messenger = registrar.messenger() let instance = QuickActionsPlugin(messenger: messenger) - IosQuickActionsApiSetup.setUp(binaryMessenger: messenger, api: instance) + IOSQuickActionsApiSetup.setUp(binaryMessenger: messenger, api: instance) registrar.addApplicationDelegate(instance) } private let shortcutItemProvider: ShortcutItemProviding - private let shortcutItemParser: ShortcutItemParser - private let flutterApi: IosQuickActionsFlutterApi + private let shortcutItemParser: ShortcutItemParser = DefaultShortcutItemParser() + private let flutterApi: IOSQuickActionsFlutterApiProtocol /// The type of the shortcut item selected when launching the app. private var launchingShortcutType: String? = nil + // This init is meant for unit testing only. init( - messenger: FlutterBinaryMessenger, - shortcutItemProvider: ShortcutItemProviding = UIApplication.shared, - shortcutItemParser: ShortcutItemParser = DefaultShortcutItemParser() + flutterApi: IOSQuickActionsFlutterApiProtocol, + shortcutItemProvider: ShortcutItemProviding = UIApplication.shared ) { + self.flutterApi = flutterApi self.shortcutItemProvider = shortcutItemProvider - self.shortcutItemParser = shortcutItemParser - self.flutterApi = IosQuickActionsFlutterApi(binaryMessenger: messenger) } - /// Method to allow for async testing. - var testStub: (() -> Void)? = nil + convenience init( + messenger: FlutterBinaryMessenger, + shortcutItemProvider: ShortcutItemProviding = UIApplication.shared + ) { + let shortcutItemProvider = shortcutItemProvider + let flutterApi = IOSQuickActionsFlutterApi(binaryMessenger: messenger) + self.init(flutterApi: flutterApi, shortcutItemProvider: shortcutItemProvider) + } - func setShortcutItems(itemsList: [ShortcutItemMessage]) throws { + func setShortcutItems(itemsList: [ShortcutItemMessage]) { shortcutItemProvider.shortcutItems = shortcutItemParser.parseShortcutItems(itemsList) } - func clearShortcutItems() throws { + func clearShortcutItems() { shortcutItemProvider.shortcutItems = [] } @@ -77,8 +82,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IosQuickActionsA } func handleShortcut(_ shortcut: String) { - self.testStub?() - flutterApi.launchAction(action: shortcut) { + flutterApi.launchAction(action: shortcut) { _ in // noop } } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift index 59ba5eca41c..0dec7a61994 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/messages.g.swift @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v12.0.1), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -13,6 +13,8 @@ import FlutterMacOS #error("Unsupported platform.") #endif +extension FlutterError: Error {} + private func isNullish(_ value: Any?) -> Bool { return value is NSNull || value == nil } @@ -71,7 +73,7 @@ struct ShortcutItemMessage { ] } } -private class IosQuickActionsApiCodecReader: FlutterStandardReader { +private class IOSQuickActionsApiCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { case 128: @@ -82,7 +84,7 @@ private class IosQuickActionsApiCodecReader: FlutterStandardReader { } } -private class IosQuickActionsApiCodecWriter: FlutterStandardWriter { +private class IOSQuickActionsApiCodecWriter: FlutterStandardWriter { override func writeValue(_ value: Any) { if let value = value as? ShortcutItemMessage { super.writeByte(128) @@ -93,22 +95,22 @@ private class IosQuickActionsApiCodecWriter: FlutterStandardWriter { } } -private class IosQuickActionsApiCodecReaderWriter: FlutterStandardReaderWriter { +private class IOSQuickActionsApiCodecReaderWriter: FlutterStandardReaderWriter { override func reader(with data: Data) -> FlutterStandardReader { - return IosQuickActionsApiCodecReader(data: data) + return IOSQuickActionsApiCodecReader(data: data) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return IosQuickActionsApiCodecWriter(data: data) + return IOSQuickActionsApiCodecWriter(data: data) } } -class IosQuickActionsApiCodec: FlutterStandardMessageCodec { - static let shared = IosQuickActionsApiCodec(readerWriter: IosQuickActionsApiCodecReaderWriter()) +class IOSQuickActionsApiCodec: FlutterStandardMessageCodec { + static let shared = IOSQuickActionsApiCodec(readerWriter: IOSQuickActionsApiCodecReaderWriter()) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol IosQuickActionsApi { +protocol IOSQuickActionsApi { /// Sets the dynamic shortcuts for the app. func setShortcutItems(itemsList: [ShortcutItemMessage]) throws /// Removes all dynamic shortcuts. @@ -116,13 +118,13 @@ protocol IosQuickActionsApi { } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class IosQuickActionsApiSetup { - /// The codec used by IosQuickActionsApi. - static var codec: FlutterStandardMessageCodec { IosQuickActionsApiCodec.shared } - /// Sets up an instance of `IosQuickActionsApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: IosQuickActionsApi?) { +class IOSQuickActionsApiSetup { + /// The codec used by IOSQuickActionsApi. + static var codec: FlutterStandardMessageCodec { IOSQuickActionsApiCodec.shared } + /// Sets up an instance of `IOSQuickActionsApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: IOSQuickActionsApi?) { /// Sets the dynamic shortcuts for the app. - let setShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.setShortcutItems", binaryMessenger: binaryMessenger, codec: codec) + let setShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.setShortcutItems", binaryMessenger: binaryMessenger, codec: codec) if let api = api { setShortcutItemsChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -138,7 +140,7 @@ class IosQuickActionsApiSetup { setShortcutItemsChannel.setMessageHandler(nil) } /// Removes all dynamic shortcuts. - let clearShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.clearShortcutItems", binaryMessenger: binaryMessenger, codec: codec) + let clearShortcutItemsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.clearShortcutItems", binaryMessenger: binaryMessenger, codec: codec) if let api = api { clearShortcutItemsChannel.setMessageHandler { _, reply in do { @@ -153,17 +155,21 @@ class IosQuickActionsApiSetup { } } } -/// Generated class from Pigeon that represents Flutter messages that can be called from Swift. -class IosQuickActionsFlutterApi { +/// 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) +} +class IOSQuickActionsFlutterApi: IOSQuickActionsFlutterApiProtocol { private let binaryMessenger: FlutterBinaryMessenger init(binaryMessenger: FlutterBinaryMessenger){ self.binaryMessenger = binaryMessenger } /// Sends a string representing a shortcut from the native platform to the app. - func launchAction(action actionArg: String, completion: @escaping () -> Void) { - let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction", binaryMessenger: binaryMessenger) + func launchAction(action actionArg: String, completion: @escaping (Result) -> Void) { + let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction", binaryMessenger: binaryMessenger) channel.sendMessage([actionArg] as [Any?]) { _ in - completion() + completion(.success(Void())) } } } diff --git a/packages/quick_actions/quick_actions_ios/lib/messages.g.dart b/packages/quick_actions/quick_actions_ios/lib/messages.g.dart index 13a05bc005d..f1d64464772 100644 --- a/packages/quick_actions/quick_actions_ios/lib/messages.g.dart +++ b/packages/quick_actions/quick_actions_ios/lib/messages.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v12.0.1), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -11,6 +11,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + /// Home screen quick-action shortcut item. class ShortcutItemMessage { ShortcutItemMessage({ @@ -46,8 +57,8 @@ class ShortcutItemMessage { } } -class _IosQuickActionsApiCodec extends StandardMessageCodec { - const _IosQuickActionsApiCodec(); +class _IOSQuickActionsApiCodec extends StandardMessageCodec { + const _IOSQuickActionsApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { if (value is ShortcutItemMessage) { @@ -69,21 +80,21 @@ class _IosQuickActionsApiCodec extends StandardMessageCodec { } } -class IosQuickActionsApi { - /// Constructor for [IosQuickActionsApi]. The [binaryMessenger] named argument is +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}) + IOSQuickActionsApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; - static const MessageCodec codec = _IosQuickActionsApiCodec(); + static const MessageCodec codec = _IOSQuickActionsApiCodec(); /// Sets the dynamic shortcuts for the app. Future setShortcutItems( List arg_itemsList) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.setShortcutItems', + 'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.setShortcutItems', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -107,7 +118,7 @@ class IosQuickActionsApi { /// Removes all dynamic shortcuts. Future clearShortcutItems() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.quick_actions_ios.IosQuickActionsApi.clearShortcutItems', + 'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsApi.clearShortcutItems', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send(null) as List?; @@ -128,17 +139,17 @@ class IosQuickActionsApi { } } -abstract class IosQuickActionsFlutterApi { +abstract class IOSQuickActionsFlutterApi { static const MessageCodec codec = StandardMessageCodec(); /// Sends a string representing a shortcut from the native platform to the app. void launchAction(String action); - static void setup(IosQuickActionsFlutterApi? api, + static void setup(IOSQuickActionsFlutterApi? api, {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction', + 'dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -146,13 +157,20 @@ abstract class IosQuickActionsFlutterApi { } else { 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 args = (message as List?)!; final String? arg_action = (args[0] as String?); assert(arg_action != null, - 'Argument for dev.flutter.pigeon.quick_actions_ios.IosQuickActionsFlutterApi.launchAction was null, expected non-null String.'); - api.launchAction(arg_action!); - return; + 'Argument for dev.flutter.pigeon.quick_actions_ios.IOSQuickActionsFlutterApi.launchAction was null, expected non-null String.'); + try { + api.launchAction(arg_action!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart b/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart index 31d85e6120f..235591774c5 100644 --- a/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart +++ b/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart @@ -15,10 +15,10 @@ late QuickActionHandler _handler; class QuickActionsIos extends QuickActionsPlatform { /// Creates a new plugin implementation instance. QuickActionsIos({ - @visibleForTesting IosQuickActionsApi? api, - }) : _hostApi = api ?? IosQuickActionsApi(); + @visibleForTesting IOSQuickActionsApi? api, + }) : _hostApi = api ?? IOSQuickActionsApi(); - final IosQuickActionsApi _hostApi; + final IOSQuickActionsApi _hostApi; /// Registers this class as the default instance of [QuickActionsPlatform]. static void registerWith() { @@ -29,7 +29,7 @@ class QuickActionsIos extends QuickActionsPlatform { Future initialize(QuickActionHandler handler) async { final _QuickActionHandlerApi quickActionsHandlerApi = _QuickActionHandlerApi(); - IosQuickActionsFlutterApi.setup(quickActionsHandlerApi); + IOSQuickActionsFlutterApi.setup(quickActionsHandlerApi); _handler = handler; } @@ -52,7 +52,7 @@ class QuickActionsIos extends QuickActionsPlatform { } } -class _QuickActionHandlerApi extends IosQuickActionsFlutterApi { +class _QuickActionHandlerApi extends IOSQuickActionsFlutterApi { @override void launchAction(String action) { _handler(action); diff --git a/packages/quick_actions/quick_actions_ios/pigeons/messages.dart b/packages/quick_actions/quick_actions_ios/pigeons/messages.dart index 7e173fee6ae..553d8552cf7 100644 --- a/packages/quick_actions/quick_actions_ios/pigeons/messages.dart +++ b/packages/quick_actions/quick_actions_ios/pigeons/messages.dart @@ -6,7 +6,6 @@ import 'package:pigeon/pigeon.dart'; @ConfigurePigeon(PigeonOptions( dartOut: 'lib/messages.g.dart', - dartTestOut: 'test/test_api.g.dart', swiftOut: 'ios/Classes/messages.g.swift', copyrightHeader: 'pigeons/copyright.txt', )) @@ -30,7 +29,7 @@ class ShortcutItemMessage { } @HostApi() -abstract class IosQuickActionsApi { +abstract class IOSQuickActionsApi { /// Sets the dynamic shortcuts for the app. void setShortcutItems(List itemsList); @@ -39,7 +38,7 @@ abstract class IosQuickActionsApi { } @FlutterApi() -abstract class IosQuickActionsFlutterApi { +abstract class IOSQuickActionsFlutterApi { /// Sends a string representing a shortcut from the native platform to the app. void launchAction(String action); } diff --git a/packages/quick_actions/quick_actions_ios/pubspec.yaml b/packages/quick_actions/quick_actions_ios/pubspec.yaml index 4268a1aa5de..3be66b4f886 100644 --- a/packages/quick_actions/quick_actions_ios/pubspec.yaml +++ b/packages/quick_actions/quick_actions_ios/pubspec.yaml @@ -26,7 +26,7 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter - pigeon: ^11.0.1 + pigeon: ^12.0.1 plugin_platform_interface: ^2.1.2 topics: diff --git a/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart b/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart index 90f49a8a8c2..c2e281a1a14 100644 --- a/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart +++ b/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart @@ -21,12 +21,12 @@ void main() { }); group('#initialize', () { - test('initialize', () async { - await quickActions.initialize((_) {}); + test('initialize', () { + expect(quickActions.initialize((_) {}), completes); }); }); - test('setShortCutItems', () async { + test('setShortcutItems', () async { await quickActions.initialize((String type) {}); const ShortcutItem item = ShortcutItem(type: 'test', localizedTitle: 'title', icon: 'icon.svg'); @@ -61,7 +61,7 @@ void main() { }); } -class _FakeQuickActionsApi implements IosQuickActionsApi { +class _FakeQuickActionsApi implements IOSQuickActionsApi { List items = []; bool getLaunchActionCalled = false; diff --git a/packages/quick_actions/quick_actions_ios/test/test_api.g.dart b/packages/quick_actions/quick_actions_ios/test/test_api.g.dart deleted file mode 100644 index 021ba0b0256..00000000000 --- a/packages/quick_actions/quick_actions_ios/test/test_api.g.dart +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import -// ignore_for_file: avoid_relative_lib_imports -import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:quick_actions_ios/messages.g.dart'; From 2ca39806a8f3424b1e78e287b0869ff240adff90 Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 09:09:14 -0700 Subject: [PATCH 04/10] nits --- .../ios/RunnerTests/QuickActionsPluginTests.swift | 10 +++++----- .../ios/Classes/QuickActionsPlugin.swift | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift index 736d4b47120..f0dff1650b7 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/QuickActionsPluginTests.swift @@ -9,12 +9,12 @@ import XCTest class MockFlutterApi: IOSQuickActionsFlutterApiProtocol { /// Method to allow for async testing. - var testStub: ((String) -> Void)? = nil + var launchActionCallback: ((String) -> Void)? = nil func launchAction( action actionArg: String, completion: @escaping (Result) -> Void ) { - self.testStub?(actionArg) + self.launchActionCallback?(actionArg) completion(.success(Void())) } } @@ -85,7 +85,7 @@ class QuickActionsPluginTests: XCTestCase { userInfo: nil) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - flutterApi.testStub = { aString in + flutterApi.launchActionCallback = { aString in XCTAssertEqual(aString, item.type) invokeMethodExpectation.fulfill() } @@ -167,7 +167,7 @@ class QuickActionsPluginTests: XCTestCase { shortcutItemProvider: mockShortcutItemProvider) let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") - flutterApi.testStub = { aString in + flutterApi.launchActionCallback = { aString in XCTAssertEqual(aString, item.type) invokeMethodExpectation.fulfill() } @@ -201,7 +201,7 @@ class QuickActionsPluginTests: XCTestCase { let invokeMethodExpectation = expectation(description: "invokeMethod must be called.") var invokeMethodCount = 0 - flutterApi.testStub = { aString in + flutterApi.launchActionCallback = { aString in XCTAssertEqual(aString, item.type) invokeMethodCount += 1 invokeMethodExpectation.fulfill() diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index ecd3c010546..524aab712d3 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -32,7 +32,6 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA messenger: FlutterBinaryMessenger, shortcutItemProvider: ShortcutItemProviding = UIApplication.shared ) { - let shortcutItemProvider = shortcutItemProvider let flutterApi = IOSQuickActionsFlutterApi(binaryMessenger: messenger) self.init(flutterApi: flutterApi, shortcutItemProvider: shortcutItemProvider) } From 110a311eacea0cef77b8d1c1f43e1698ddfa530d Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 10:24:08 -0700 Subject: [PATCH 05/10] delete file --- .../ios/Runner.xcodeproj/project.pbxproj | 4 -- .../Mocks/MockBinaryMessenger.swift | 40 ------------------- 2 files changed, 44 deletions(-) delete mode 100644 packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockBinaryMessenger.swift diff --git a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj index 6c1835f4ec5..118bd6f0912 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 2632072169FF635893D8EB4D /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 436668746754BEEA28B76E55 /* libPods-RunnerTests.a */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 47B0F9522ADE93E300947B4D /* MockBinaryMessenger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */; }; 6A841C2B6AED5CF8DB2A1894 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C35AD3650AB6BF850E016715 /* libPods-Runner.a */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; @@ -60,7 +59,6 @@ 33E20B3626EFCDFC00A4A191 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 436668746754BEEA28B76E55 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockBinaryMessenger.swift; sourceTree = ""; }; 5278439583922091276A37C9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 686BE82D25E58CCF00862533 /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 686BE83125E58CCF00862533 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -213,7 +211,6 @@ E092A7F228D10908005C7F67 /* Mocks */ = { isa = PBXGroup; children = ( - 47B0F9512ADE93E300947B4D /* MockBinaryMessenger.swift */, E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */, ); path = Mocks; @@ -433,7 +430,6 @@ buildActionMask = 2147483647; files = ( E092A7EE28D10802005C7F67 /* QuickActionsPluginTests.swift in Sources */, - 47B0F9522ADE93E300947B4D /* MockBinaryMessenger.swift in Sources */, E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */, E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */, ); diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockBinaryMessenger.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockBinaryMessenger.swift deleted file mode 100644 index 8b3d4843f63..00000000000 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/Mocks/MockBinaryMessenger.swift +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter - -@testable import quick_actions_ios - -class MockBinaryMessenger: NSObject, FlutterBinaryMessenger { - let codec: FlutterMessageCodec - var result: Any? - private(set) var handlers: [String: FlutterBinaryMessageHandler] = [:] - - override init() { - self.codec = FlutterStandardMessageCodec.sharedInstance() - super.init() - } - - func send(onChannel channel: String, message: Data?) {} - - func send( - onChannel channel: String, - message: Data?, - binaryReply callback: FlutterBinaryReply? = nil - ) { - if let result = result { - callback?(codec.encode([result])) - } - } - - func setMessageHandlerOnChannel( - _ channel: String, - binaryMessageHandler handler: FlutterBinaryMessageHandler? = nil - ) -> FlutterBinaryMessengerConnection { - handlers[channel] = handler - return .init(handlers.count) - } - - func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) {} -} From 20796bb00899621d3efaf5fabddca5b87d64ef28 Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 11:21:04 -0700 Subject: [PATCH 06/10] remove parser class --- .../DefaultShortcutItemParserTests.swift | 6 +-- .../ios/Classes/QuickActionsPlugin.swift | 47 ++++++++++++------- .../ios/Classes/ShortcutItemParser.swift | 44 ----------------- 3 files changed, 33 insertions(+), 64 deletions(-) delete mode 100644 packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift index 24aa754818c..8f7d54db5c6 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift @@ -23,8 +23,7 @@ class DefaultShortcutItemParserTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - let parser = DefaultShortcutItemParser() - XCTAssertEqual(parser.parseShortcutItems([rawItem]), [expectedItem]) + XCTAssertEqual(QuickActionsPlugin.parseShortcutItems([rawItem]), [expectedItem]) } func testParseShortcutItems_noIcon() { @@ -40,7 +39,6 @@ class DefaultShortcutItemParserTests: XCTestCase { icon: nil, userInfo: nil) - let parser = DefaultShortcutItemParser() - XCTAssertEqual(parser.parseShortcutItems([rawItem]), [expectedItem]) + XCTAssertEqual(QuickActionsPlugin.parseShortcutItems([rawItem]), [expectedItem]) } } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 524aab712d3..38fb7ba3fdc 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -8,18 +8,17 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA public static func register(with registrar: FlutterPluginRegistrar) { let messenger = registrar.messenger() - let instance = QuickActionsPlugin(messenger: messenger) + let flutterApi = IOSQuickActionsFlutterApi(binaryMessenger: messenger) + let instance = QuickActionsPlugin(flutterApi: flutterApi) IOSQuickActionsApiSetup.setUp(binaryMessenger: messenger, api: instance) registrar.addApplicationDelegate(instance) } private let shortcutItemProvider: ShortcutItemProviding - private let shortcutItemParser: ShortcutItemParser = DefaultShortcutItemParser() private let flutterApi: IOSQuickActionsFlutterApiProtocol /// The type of the shortcut item selected when launching the app. private var launchingShortcutType: String? = nil - // This init is meant for unit testing only. init( flutterApi: IOSQuickActionsFlutterApiProtocol, shortcutItemProvider: ShortcutItemProviding = UIApplication.shared @@ -28,27 +27,19 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA self.shortcutItemProvider = shortcutItemProvider } - convenience init( - messenger: FlutterBinaryMessenger, - shortcutItemProvider: ShortcutItemProviding = UIApplication.shared - ) { - let flutterApi = IOSQuickActionsFlutterApi(binaryMessenger: messenger) - self.init(flutterApi: flutterApi, shortcutItemProvider: shortcutItemProvider) - } - func setShortcutItems(itemsList: [ShortcutItemMessage]) { - shortcutItemProvider.shortcutItems = shortcutItemParser.parseShortcutItems(itemsList) + self.shortcutItemProvider.shortcutItems = QuickActionsPlugin.parseShortcutItems(itemsList) } func clearShortcutItems() { - shortcutItemProvider.shortcutItems = [] + self.shortcutItemProvider.shortcutItems = [] } public func application( _ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void ) -> Bool { - handleShortcut(shortcutItem.type) + self.handleShortcut(shortcutItem.type) return true } @@ -75,14 +66,38 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA public func applicationDidBecomeActive(_ application: UIApplication) { if let shortcutType = launchingShortcutType { - handleShortcut(shortcutType) + self.handleShortcut(shortcutType) self.launchingShortcutType = nil } } func handleShortcut(_ shortcut: String) { - flutterApi.launchAction(action: shortcut) { _ in + self.flutterApi.launchAction(action: shortcut) { _ in // noop } } + + static func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { + return items.compactMap { deserializeShortcutItem(with: $0) } + } + + static private func deserializeShortcutItem(with serialized: ShortcutItemMessage) + -> UIApplicationShortcutItem? + { + + let type = serialized.type + let localizedTitle = serialized.localizedTitle + + let icon = (serialized.icon).map { + UIApplicationShortcutIcon(templateImageName: $0) + } + + // type and localizedTitle are required. + return UIApplicationShortcutItem( + type: type, + localizedTitle: localizedTitle, + localizedSubtitle: nil, + icon: icon, + userInfo: nil) + } } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift deleted file mode 100644 index 583af4105c6..00000000000 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemParser.swift +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import UIKit - -/// A parser that parses an array of raw shortcut items. -protocol ShortcutItemParser { - - /// Parses an array of raw shortcut items into an array of UIApplicationShortcutItems - /// - /// - Parameter items an array of raw shortcut items to be parsed. - /// - Returns an array of parsed shortcut items to be set. - /// - func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] -} - -/// A default implementation of the `ShortcutItemParser` protocol. -final class DefaultShortcutItemParser: ShortcutItemParser { - - func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { - return items.compactMap { deserializeShortcutItem(with: $0) } - } - - private func deserializeShortcutItem(with serialized: ShortcutItemMessage) - -> UIApplicationShortcutItem? - { - - let type = serialized.type - let localizedTitle = serialized.localizedTitle - - let icon = (serialized.icon).map { - UIApplicationShortcutIcon(templateImageName: $0) - } - - // type and localizedTitle are required. - return UIApplicationShortcutItem( - type: type, - localizedTitle: localizedTitle, - localizedSubtitle: nil, - icon: icon, - userInfo: nil) - } -} From e2dc2b7c4bc87a2f413693b828c7d661218e1200 Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 11:33:33 -0700 Subject: [PATCH 07/10] method names --- .../DefaultShortcutItemParserTests.swift | 4 ++-- .../ios/Classes/QuickActionsPlugin.swift | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift index 8f7d54db5c6..abdb61a5ac2 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift @@ -23,7 +23,7 @@ class DefaultShortcutItemParserTests: XCTestCase { icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), userInfo: nil) - XCTAssertEqual(QuickActionsPlugin.parseShortcutItems([rawItem]), [expectedItem]) + XCTAssertEqual(QuickActionsPlugin.convertShortcutItemListToUIApplicationShortcutItemList([rawItem]), [expectedItem]) } func testParseShortcutItems_noIcon() { @@ -39,6 +39,6 @@ class DefaultShortcutItemParserTests: XCTestCase { icon: nil, userInfo: nil) - XCTAssertEqual(QuickActionsPlugin.parseShortcutItems([rawItem]), [expectedItem]) + XCTAssertEqual(QuickActionsPlugin.convertShortcutItemListToUIApplicationShortcutItemList([rawItem]), [expectedItem]) } } diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 38fb7ba3fdc..12fad59f4cc 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -28,7 +28,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } func setShortcutItems(itemsList: [ShortcutItemMessage]) { - self.shortcutItemProvider.shortcutItems = QuickActionsPlugin.parseShortcutItems(itemsList) + self.shortcutItemProvider.shortcutItems = QuickActionsPlugin.convertShortcutItemListToUIApplicationShortcutItemList(itemsList) } func clearShortcutItems() { @@ -77,18 +77,18 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } } - static func parseShortcutItems(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { - return items.compactMap { deserializeShortcutItem(with: $0) } + static func convertShortcutItemListToUIApplicationShortcutItemList(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { + return items.compactMap { convertShortcutItemToUIApplicationShortcutItem(with: $0) } } - static private func deserializeShortcutItem(with serialized: ShortcutItemMessage) + static private func convertShortcutItemToUIApplicationShortcutItem(with shortcut: ShortcutItemMessage) -> UIApplicationShortcutItem? { - let type = serialized.type - let localizedTitle = serialized.localizedTitle + let type = shortcut.type + let localizedTitle = shortcut.localizedTitle - let icon = (serialized.icon).map { + let icon = (shortcut.icon).map { UIApplicationShortcutIcon(templateImageName: $0) } From bfe3748109dae123b1f0535e3a4dbc98c4eb225a Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 11:48:02 -0700 Subject: [PATCH 08/10] non static --- .../ios/Runner.xcodeproj/project.pbxproj | 4 -- .../DefaultShortcutItemParserTests.swift | 44 ------------------- .../ios/Classes/QuickActionsPlugin.swift | 6 +-- 3 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift diff --git a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj index 118bd6f0912..ed64aa55762 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/quick_actions/quick_actions_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; E092A7EE28D10802005C7F67 /* QuickActionsPluginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7EB28D10802005C7F67 /* QuickActionsPluginTests.swift */; }; E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */; }; - E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */; }; E092A7F628D128EB005C7F67 /* RunnerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E092A7F528D128EB005C7F67 /* RunnerUITests.swift */; }; /* End PBXBuildFile section */ @@ -78,7 +77,6 @@ C35AD3650AB6BF850E016715 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E092A7EB28D10802005C7F67 /* QuickActionsPluginTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickActionsPluginTests.swift; sourceTree = ""; }; E092A7F028D10890005C7F67 /* MockShortcutItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShortcutItemProvider.swift; sourceTree = ""; }; - E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultShortcutItemParserTests.swift; sourceTree = ""; }; E092A7F528D128EB005C7F67 /* RunnerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerUITests.swift; sourceTree = ""; }; F0609304FBCAEC2289164BD5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -116,7 +114,6 @@ E092A7F228D10908005C7F67 /* Mocks */, 33E20B3626EFCDFC00A4A191 /* Info.plist */, E092A7EB28D10802005C7F67 /* QuickActionsPluginTests.swift */, - E092A7F328D110B3005C7F67 /* DefaultShortcutItemParserTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -431,7 +428,6 @@ files = ( E092A7EE28D10802005C7F67 /* QuickActionsPluginTests.swift in Sources */, E092A7F128D10890005C7F67 /* MockShortcutItemProvider.swift in Sources */, - E092A7F428D110B3005C7F67 /* DefaultShortcutItemParserTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift deleted file mode 100644 index abdb61a5ac2..00000000000 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerTests/DefaultShortcutItemParserTests.swift +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import XCTest - -@testable import quick_actions_ios - -class DefaultShortcutItemParserTests: XCTestCase { - - func testParseShortcutItems() { - let rawItem = ShortcutItemMessage( - type: "SearchTheThing", - localizedTitle: "Search the thing", - icon: "search_the_thing.png" - ) - - let expectedItem = UIApplicationShortcutItem( - type: "SearchTheThing", - localizedTitle: "Search the thing", - localizedSubtitle: nil, - icon: UIApplicationShortcutIcon(templateImageName: "search_the_thing.png"), - userInfo: nil) - - XCTAssertEqual(QuickActionsPlugin.convertShortcutItemListToUIApplicationShortcutItemList([rawItem]), [expectedItem]) - } - - func testParseShortcutItems_noIcon() { - let rawItem = ShortcutItemMessage( - type: "SearchTheThing", - localizedTitle: "Search the thing" - ) - - let expectedItem = UIApplicationShortcutItem( - type: "SearchTheThing", - localizedTitle: "Search the thing", - localizedSubtitle: nil, - icon: nil, - userInfo: nil) - - XCTAssertEqual(QuickActionsPlugin.convertShortcutItemListToUIApplicationShortcutItemList([rawItem]), [expectedItem]) - } -} diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 12fad59f4cc..99fd1dd42d6 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -28,7 +28,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } func setShortcutItems(itemsList: [ShortcutItemMessage]) { - self.shortcutItemProvider.shortcutItems = QuickActionsPlugin.convertShortcutItemListToUIApplicationShortcutItemList(itemsList) + self.shortcutItemProvider.shortcutItems = self.convertShortcutItemListToUIApplicationShortcutItemList(itemsList) } func clearShortcutItems() { @@ -77,11 +77,11 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } } - static func convertShortcutItemListToUIApplicationShortcutItemList(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { + private func convertShortcutItemListToUIApplicationShortcutItemList(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { return items.compactMap { convertShortcutItemToUIApplicationShortcutItem(with: $0) } } - static private func convertShortcutItemToUIApplicationShortcutItem(with shortcut: ShortcutItemMessage) + private func convertShortcutItemToUIApplicationShortcutItem(with shortcut: ShortcutItemMessage) -> UIApplicationShortcutItem? { From f8bf4b2c51de117b24c781b9f630649943760b4d Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 12:06:00 -0700 Subject: [PATCH 09/10] message --- .../ios/Classes/QuickActionsPlugin.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 99fd1dd42d6..933830c9dd8 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -28,7 +28,7 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } func setShortcutItems(itemsList: [ShortcutItemMessage]) { - self.shortcutItemProvider.shortcutItems = self.convertShortcutItemListToUIApplicationShortcutItemList(itemsList) + self.shortcutItemProvider.shortcutItems = self.convertShortcutItemMessageListToUIApplicationShortcutItemList(itemsList) } func clearShortcutItems() { @@ -77,11 +77,11 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } } - private func convertShortcutItemListToUIApplicationShortcutItemList(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { - return items.compactMap { convertShortcutItemToUIApplicationShortcutItem(with: $0) } + private func convertShortcutItemMessageListToUIApplicationShortcutItemList(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { + return items.compactMap { convertShortcutItemMessageToUIApplicationShortcutItem(with: $0) } } - private func convertShortcutItemToUIApplicationShortcutItem(with shortcut: ShortcutItemMessage) + private func convertShortcutItemMessageToUIApplicationShortcutItem(with shortcut: ShortcutItemMessage) -> UIApplicationShortcutItem? { From 249d3f88488070e3da5cecd3fc57cf8c572f0b08 Mon Sep 17 00:00:00 2001 From: tarrinneal Date: Fri, 20 Oct 2023 12:09:39 -0700 Subject: [PATCH 10/10] selfies --- .../ios/Classes/QuickActionsPlugin.swift | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift index 933830c9dd8..dc8ffb812f3 100644 --- a/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/Classes/QuickActionsPlugin.swift @@ -28,18 +28,19 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA } func setShortcutItems(itemsList: [ShortcutItemMessage]) { - self.shortcutItemProvider.shortcutItems = self.convertShortcutItemMessageListToUIApplicationShortcutItemList(itemsList) + shortcutItemProvider.shortcutItems = + convertShortcutItemMessageListToUIApplicationShortcutItemList(itemsList) } func clearShortcutItems() { - self.shortcutItemProvider.shortcutItems = [] + shortcutItemProvider.shortcutItems = [] } public func application( _ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void ) -> Bool { - self.handleShortcut(shortcutItem.type) + handleShortcut(shortcutItem.type) return true } @@ -66,28 +67,32 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA public func applicationDidBecomeActive(_ application: UIApplication) { if let shortcutType = launchingShortcutType { - self.handleShortcut(shortcutType) - self.launchingShortcutType = nil + handleShortcut(shortcutType) + launchingShortcutType = nil } } func handleShortcut(_ shortcut: String) { - self.flutterApi.launchAction(action: shortcut) { _ in + flutterApi.launchAction(action: shortcut) { _ in // noop } } - private func convertShortcutItemMessageListToUIApplicationShortcutItemList(_ items: [ShortcutItemMessage]) -> [UIApplicationShortcutItem] { + private func convertShortcutItemMessageListToUIApplicationShortcutItemList( + _ items: [ShortcutItemMessage] + ) -> [UIApplicationShortcutItem] { return items.compactMap { convertShortcutItemMessageToUIApplicationShortcutItem(with: $0) } } - private func convertShortcutItemMessageToUIApplicationShortcutItem(with shortcut: ShortcutItemMessage) + private func convertShortcutItemMessageToUIApplicationShortcutItem( + with shortcut: ShortcutItemMessage + ) -> UIApplicationShortcutItem? { let type = shortcut.type let localizedTitle = shortcut.localizedTitle - + let icon = (shortcut.icon).map { UIApplicationShortcutIcon(templateImageName: $0) }