-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[image_picker_macos] macOS native image picker #8079
base: main
Are you sure you want to change the base?
[image_picker_macos] macOS native image picker #8079
Conversation
56235d8
to
6843278
Compare
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 left TODOs in the code that should be addressed in this PR before continuing further except the TODO of adding macOS native UI tests.
I welcome any feedback and suggestions.
private func createTestImage(size: NSSize) -> NSImage { | ||
let image = NSImage(size: size) | ||
image.lockFocus() | ||
NSColor.white.set() | ||
NSBezierPath(rect: NSRect(origin: .zero, size: size)).fill() | ||
image.unlockFocus() | ||
return image | ||
} |
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.
This is duplicated in both ImageCompressTests
and ImageResizeTests
, should I extract it?
Most unit tests of plugins on this repo are implemented with one file RunnerTests
.
packages/image_picker/image_picker_macos/example/macos/Runner/AppDelegate.swift
Show resolved
Hide resolved
private func createTestImage(size: NSSize) -> NSImage { | ||
let image = NSImage(size: size) | ||
image.lockFocus() | ||
NSColor.black.set() | ||
NSBezierPath(rect: NSRect(origin: .zero, size: size)).fill() | ||
image.unlockFocus() | ||
return image | ||
} |
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.
Duplicated.
/// * [useMacOSPHPicker] to check whether **PHPicker** should be preferred over [file_selector_macos](https://pub.dev/packages/file_selector_macos). | ||
/// * [supportsPHPicker] to verify if the current macOS version supports **PHPicker**. | ||
@visibleForTesting | ||
Future<bool> shouldUsePHPicker() async => |
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 mean that this should be public?
// TODO(EchoEllet): Is there a convention for the error code? ImageConversionError or IMAGE_CONVERSION_ERROR or image-conversion-error. Update all codes. | ||
throw PigeonError( | ||
code: "ImageConversionError", message: "Failed to convert NSImage to TIFF data.", |
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.
Probably image-conversion-error
?
packages/image_picker/image_picker_macos/macos/image_picker_macos.podspec
Show resolved
Hide resolved
assert(quality != 100, "Quality 100 means no compression.") | ||
assert(quality >= 0, "Quality can't be negative.") |
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.
Should I remove the asserts from the platform side since it will crash the app on failure when not running using Xcode (flutter run -d macos
)?
...ker/image_picker_macos/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
Show resolved
Hide resolved
I ran the script Output
image_picker/image_picker_macos/macos/image_picker_macos/Sources/image_picker_macos/Messages.g.swift:166:15: warning: [TypeNamesShouldBeCapitalized] rename the class 'messagesPigeonCodecReader' using UpperCamelCase; for example, 'MessagesPigeonCodecReader'
image_picker/image_picker_macos/macos/image_picker_macos/Sources/image_picker_macos/Messages.g.swift:183:15: warning: [TypeNamesShouldBeCapitalized] rename the class 'messagesPigeonCodecWriter' using UpperCamelCase; for example, 'MessagesPigeonCodecWriter'
image_picker/image_picker_macos/macos/image_picker_macos/Sources/image_picker_macos/Messages.g.swift:203:15: warning: [TypeNamesShouldBeCapitalized] rename the class 'messagesPigeonCodecReaderWriter' using UpperCamelCase; for example, 'MessagesPigeonCodecReaderWriter'
image_picker/image_picker_macos/macos/image_picker_macos/Sources/image_picker_macos/Messages.g.swift:213:7: warning: [TypeNamesShouldBeCapitalized] rename the class 'messagesPigeonCodec' using UpperCamelCase; for example, 'MessagesPigeonCodec'
Swift linter found issues. See above for linter output.
I'm using Xcode 16.1 with Swift 6, maybe the CI uses Swift 5?
I'm new to Apple/Xcode/Swift ecosystem, should I only mark |
The doc comments of
This is also possible with the native macOS implementation (when PHPicker is used). Should I update those parts of the docs to reflect the change? |
The @override
bool supportsImageSource(ImageSource source) {
if (source == ImageSource.camera) {
return cameraDelegate != null;
}
return false;
}
It's also possible to support those on |
noActiveWindow() | ||
return | ||
} | ||
// TODO(EchoEllet): IMPORTANT The window size of the picker is smaller than expected, see the video in https://discord.com/channels/608014603317936148/1295165633931120642/1295470850283147335 |
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.
This is an important issue to fix since it affects the user experience, see the video in this PR.
_imageOptionsToImageSelectionOptions(options.imageOptions), | ||
), | ||
GeneralOptions( | ||
limit: options.limit ?? (options.allowMultiple ? 0 : 1), |
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.
This seems to be incorrect and needs validation similarly to image_picker_android. The current code doesn't check allowMultiple
in case limit
was provided.
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.
It looks like there is validation from the app-facing package (image_picker
) for all methods, do we still need to verify from the platform implementation side?
c0177fb
to
277a923
Compare
277a923
to
6a489e6
Compare
Signed-off-by: Ellet <[email protected]>
6a489e6
to
d3535ee
Compare
…mated), deprecated @NSApplicationMain attribute Signed-off-by: Ellet <[email protected]>
…acos - Updates the `image_picke_macos`'s `pubspec.yaml` to add `pigeon` as dev dependency and add the `pluginClass` for Swift native code - Adds the `ImagePickerPlugin` in `image_picker_macos/macos` for native macOS plugin with support for SPM and CocoaPods with basic native unit tests - Uses the steps in https://github.com/flutter/flutter/blob/master/docs/ecosystem/testing/Plugin-Tests.md#enabling-xctests-or-xcuitests to enable `XCTests` and `XCUITests` - Updates the `image_picker_macos_test.dart` to fix the test failure and ensure PHPicker is disabled by default - Adds a new button in the example to enable/disable PHPicker macOS implementation and enable the PHPicker by default - Updates the `README.md` of `image_picker_macos` and `image_picker` to document the usage - Removes two TODOs in `image_picker_macos.dart` as they are done with this PR - Adds TODOs that need to be done before merging the PR, some of them are questions, will be removed - Implement the getMultiImageWithOptions() since the getMultiImage is deprecated, updates getMultiImage() to delegate to getMultiImageWithOptions() since getMultiImageWithOptions() is required to access the limit property - Updates the Dart unit tests of image_picker_macos - Adds simple integration test for the example - Updates `pubspec.yaml` and `CHANGELOG.md` of `image_picker` and `image_picker_macos` Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
…icker_macos plugin Signed-off-by: Ellet <[email protected]>
…nit test for consistency Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
Signed-off-by: Ellet <[email protected]>
d3535ee
to
c9122f9
Compare
Adds support for macOS native image picker for
image_picker_macos
.An alternative implementation that is based on PHPickerViewController instead of file_selector.
FlutterNativeMacOSImagePicker.mp4
Usage
Similar to the Android Photo Picker in
image_picker_android
:Note
It's only supported on macOS +13, on macOS 12 and older versions, will fallback to the
file_selector_macos
implementation.Related Issues
image_picker
flutter#85100Limiations
maxWidth
,maxHeight
,imageQuality
, andlimit
when using the PHPicker implementation.maxDuration
of video selection, andrequestFullMetadata
(iOS-specific).No Photos
message if they don't have photos within the app.Motivation
The macOS native picker only supports picking images, videos, and media from the Photos for macOS app.
If the user has photos in a directory, they will need to open the app and import the images they need, however, this app integrates with other macOS apps and the Apple ecosystem, and it supports features such as importing pictures seamlessly from an iOS device, albums, favorites, recently deleted, duplicates.
Screenshot
Tip
It doesn't require file read-only access entitlement.
IMO
it's better to keep this implementation optional instead of making it as default, the developer can provide the option to switch between implementations based on the user preference since it's not common on desktops to have a photos app like mobile platforms, maybe provide a method to check if it's supported:
Testing
This branch has been manually tested on macOS 14.6.1.
Native and Dart Unit tests have been added, though unfortunately, native UI tests are missing (see #70234). I left a TODO since currently it doesn't seem to be possible.
Additional Context
Related Discord Threads:
XCUITest
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style, or this PR is exempt from CHANGELOG changes.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.