-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[quick_actions]Migrates all remaining components to Swift, and deprecate OCMock #6597
[quick_actions]Migrates all remaining components to Swift, and deprecate OCMock #6597
Conversation
| } | ||
|
|
||
| /// A default implementation of the `MethodChannel` protocol. | ||
| extension FlutterMethodChannel: MethodChannel {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I put this extension in the same file as the protocol. Alternatively we can also use separate files and I am ok either way.
More details discussed in Rule 3(b) of the Swift POP naming convention proposal. Feel free to leave any comments.
| } | ||
|
|
||
| /// A default implementation of `ShortcutStateManaging` protocol. | ||
| final class DefaultShortcutStateManager: ShortcutStateManaging { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: i put this class in the same file as the protocol, but also ok to use separate files.
More details discussed in Rule 3(b) of the Swift POP naming convention proposal. Feel free to leave any comments.
|
|
||
| // type and localizedTitle are required. | ||
| return UIApplicationShortcutItem( | ||
| type: serialized["type"] as! String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should not let this plugin crash the production app? Maybe use Assert to crash debug app and return nil if either serialized["type"] or serialized["localizedTitle"] is nil in release.
Does the original Objective-C API crashes the App if type or localizedTitle is nil? If so, I'm ok with keep the same behavior and follow up with a fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the original Objective-C API crashes the App if type or localizedTitle is nil?
I think so, the API is non-null (and that's why it bridges to non-null String in Swift): https://developer.apple.com/documentation/uikit/uiapplicationshortcutitem/1623372-initwithtype?language=objc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adopting pigeon would solve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the Objective-C API actually crash if you pass in nil though? A lot of Objective-C APIs that predate nullability do handle nils under the covers, especially since most implementation files aren't wrapped in NS_ASSUME_NULL to catch the error in analysis. Ideally passing in the wrong types would give an actionable error, but at the least this should not introduce a new crash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Let me try it out.
The dart counterpart also guarantees that this is never null though. So it likely doesn't matter anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried it out - indeed the objc API did not crash - instead it just ignores it.
|
friendly ping |
packages/quick_actions/quick_actions_ios/ios/Classes/ShortcutItemServicing.swift
Outdated
Show resolved
Hide resolved
| import UIKit | ||
|
|
||
| /// Manages the shortcut related states. | ||
| protocol ShortcutStateManaging { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense for there to be a var shortcutItems: [UIApplicationShortcutItem]? { get set } protocol as well as this one? It looks like DefaultShortcutStateManager could easily implement ShortcutItemServicing instead by exposing service.shortcutItems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The var shortcutItems: [UIApplicationShortcutItem]? { get set } protocol is just an abstraction to stub UIApplication. The ShortcutStateManager has extra parsing logic. So it is better not to combine these 2.
An alternative way is to define a ShortcutItemParser, like this:
protocol ShortcutItemParser {
func parseItems(_ items: [[String, Any]]) -> [UIApplicationShortcutItem]
}
This will make the dependency DAG more "flat". Let me try and see how it goes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated ShortcutStateManager to ShortcutItemParser, and renamed ShortcutItemServicing to AppShortcutControlling.
The benefit is simpler and more flat dependency tree: Now the QuickActionsPlugin depends on both ShortcutItemParser and AppShortcutControlling, and these 2 subcomponents do not depend on each other anymore.
PTAL thx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that we still want to have a separate AppShortcutControlling protocol, so that we can stub out the UIApplication.default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShortcutItemParser SGTM.
But AppShortcutControlling isn't a capability in the sense the docs mean, in that setting this shortcutItems collection is not operating on the "implementing" UIApplication, it's more mutating it. Like the example ProgressReporting would be reporting on the progress of the thing implementing the protocol.
In addition, "AppShortcutControlling" doesn't exactly make sense in English. How about ShortcutItemProvider? At the end of the day Swift's naming guidance is purposely very loosey, we should name it in a way that describes what it does, and also makes sense in English.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, Provide sounds like it only provides something, with only getter and no setters (e.g. AgeProviding in the style guide).
How about AppShortcutManaging? it's setting a collection, but also making iOS to update the springboard shortcuts. So it feels like performing an action, rather than just a collection holder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm circling back on this - i think i am fine with the Provider name (it's not ideal, as explained above), but i can't think of a better name.
Though we want Providing for protocol name, since it's a capability to provide something (similar to NameProviding and AgeProviding in our style guide. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! Thanks for iterating on this with me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to ShortcutItemProviding (unless @cyanglaz or @stuartmorgan can think of a better name?)
|
|
||
| // type and localizedTitle are required. | ||
| return UIApplicationShortcutItem( | ||
| type: serialized["type"] as! String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adopting pigeon would solve this.
b48938a to
1295feb
Compare
| /// Services `UIApplicationShortcutItem`s. | ||
| protocol ShortcutItemServicing: AnyObject { | ||
| /// Controlls app's shortcut behavior. | ||
| protocol AppShortcutControlling: AnyObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this need AnyObject?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AnyObject scopes this protocol to reference types (classes). It prevents any value types (enums & structs) to conform to it.
Since this is injected dependency with no value semantics, we want to scope it to reference types. See the NOTE below:
class QuickActionsPlugin {
// NOTE: If we remove `AnyObject`, we have to use `var` here.
private let controller: AppShortcutControlling
func foo() {
controller.shortcutItems = [] // mutate here
}
}| import UIKit | ||
|
|
||
| /// Manages the shortcut related states. | ||
| protocol ShortcutStateManaging { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShortcutItemParser SGTM.
But AppShortcutControlling isn't a capability in the sense the docs mean, in that setting this shortcutItems collection is not operating on the "implementing" UIApplication, it's more mutating it. Like the example ProgressReporting would be reporting on the progress of the thing implementing the protocol.
In addition, "AppShortcutControlling" doesn't exactly make sense in English. How about ShortcutItemProvider? At the end of the day Swift's naming guidance is purposely very loosey, we should name it in a way that describes what it does, and also makes sense in English.
6d5c871 to
fd9968e
Compare
cyanglaz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
jmagman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
de2266a to
76d835e
Compare
…and deprecate OCMock (flutter/plugins#6597)
* 19673b341 [camera]: Bump camerax_version (flutter/plugins#6709) * b8282424e [gh_actions]: Bump ossf/scorecard-action from 2.0.4 to 2.0.6 (flutter/plugins#6610) * 2ba4c0a70 [file_selector] Add getDirectoryPaths method to the file_selector_platform_interface. (flutter/plugins#6572) * 89cbf74c8 [quick_actions]Migrates all remaining components to Swift, and deprecate OCMock (flutter/plugins#6597) * 51d084453 [quick_actions] Fix Android integration test flake (flutter/plugins#6688) * b2fe01bc0 [google_sign_in] Correctly passes `serverClientId` to native libs (flutter/plugins#6691)
…ate OCMock (flutter#6597) * [quick_actions]migrate shortcut state manager, deprecate OCMock and use POP * remove objc proj settings * rename shortcut state manager * bump version * run swift-format * nit * remove public_header_files * use shortcut item parser instead of shortcut state manager * some nit * rename AppShortcutControlling to ShortcutItemProviding * nit * do not crash if no type or title * update license
…#115656) * 19673b341 [camera]: Bump camerax_version (flutter/plugins#6709) * b8282424e [gh_actions]: Bump ossf/scorecard-action from 2.0.4 to 2.0.6 (flutter/plugins#6610) * 2ba4c0a70 [file_selector] Add getDirectoryPaths method to the file_selector_platform_interface. (flutter/plugins#6572) * 89cbf74c8 [quick_actions]Migrates all remaining components to Swift, and deprecate OCMock (flutter/plugins#6597) * 51d084453 [quick_actions] Fix Android integration test flake (flutter/plugins#6688) * b2fe01bc0 [google_sign_in] Correctly passes `serverClientId` to native libs (flutter/plugins#6691)
…#115656) * 19673b341 [camera]: Bump camerax_version (flutter/plugins#6709) * b8282424e [gh_actions]: Bump ossf/scorecard-action from 2.0.4 to 2.0.6 (flutter/plugins#6610) * 2ba4c0a70 [file_selector] Add getDirectoryPaths method to the file_selector_platform_interface. (flutter/plugins#6572) * 89cbf74c8 [quick_actions]Migrates all remaining components to Swift, and deprecate OCMock (flutter/plugins#6597) * 51d084453 [quick_actions] Fix Android integration test flake (flutter/plugins#6688) * b2fe01bc0 [google_sign_in] Correctly passes `serverClientId` to native libs (flutter/plugins#6691)
…ate OCMock (flutter#6597) * [quick_actions]migrate shortcut state manager, deprecate OCMock and use POP * remove objc proj settings * rename shortcut state manager * bump version * run swift-format * nit * remove public_header_files * use shortcut item parser instead of shortcut state manager * some nit * rename AppShortcutControlling to ShortcutItemProviding * nit * do not crash if no type or title * update license
This PR completes the Swift migration for quick_actions plugin. The main part is to migrate
FLTShortcutStateManagerusing POP. We defined the following new types:MethodChannelprotocol (to whichFlutterMethodChannelconforms)AppShortcutControllingprotocol (to whichUIApplicationconforms)ShortcutItemParserprotocolThe above naming follows the proposal "Swift POP naming convention".
Note that we have to migrate
FLTQuickActionsPluginTeststoo in this PR, because this test depends onShortcutStateManaging, which is non-objc type that OCMock does not support.If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
flutter/flutter#108750
Pre-launch Checklist
dart format.)[shared_preferences]pubspec.yamlwith an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.mdto add a description of the change, following repository CHANGELOG style.///).If you need help, consider asking for advice on the #hackers-new channel on Discord.