react-native-macos/Libraries/Image/RCTImageEditingManager.mm

105 строки
3.6 KiB
Plaintext
Исходник Обычный вид История

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
CocoaPods frameworks compatibility: Step 2 (#25619) Summary: This is my proposal for fixing `use_frameworks!` compatibility without breaking all `<React/*>` imports I outlined in https://github.com/facebook/react-native/pull/25393#issuecomment-508457700. If accepted, it will fix https://github.com/facebook/react-native/issues/25349. It builds on the changes I made in https://github.com/facebook/react-native/pull/25496 by ensuring each podspec has a unique value for `header_dir` so that framework imports do not conflict. Every podspec which should be included in the `<React/*>` namespace now includes it's headers from `React-Core.podspec`. The following pods can still be imported with `<React/*>` and so should not have breaking changes: `React-ART`,`React-DevSupport`, `React-CoreModules`, `React-RCTActionSheet`, `React-RCTAnimation`, `React-RCTBlob`, `React-RCTImage`, `React-RCTLinking`, `React-RCTNetwork`, `React-RCTPushNotification`, `React-RCTSettings`, `React-RCTText`, `React-RCTSettings`, `React-RCTVibration`, `React-RCTWebSocket` . There are still a few breaking changes which I hope will be acceptable: - `React-Core.podspec` has been moved to the root of the project. Any `Podfile` that references it will need to update the path. - ~~`React-turbomodule-core`'s headers now live under `<turbomodule/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - ~~`React-turbomodulesamples`'s headers now live under `<turbomodulesamples/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - ~~`React-TypeSaferty`'s headers now live under `<TypeSafety/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511040967. - ~~`React-jscallinvoker`'s headers now live under `<jscallinvoker/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - Each podspec now uses `s.static_framework = true`. This means that a minimum of CocoaPods 1.5 ([released in April 2018](http://blog.cocoapods.org/CocoaPods-1.5.0/)) is now required. This is needed so that the ` __has_include` conditions can still work when frameworks are enabled. Still to do: - ~~Including `React-turbomodule-core` with `use_frameworks!` enabled causes the C++ import failures we saw in https://github.com/facebook/react-native/issues/25349. I'm sure it will be possible to fix this but I need to dig deeper (perhaps a custom modulemap would be needed).~~ Addressed by https://github.com/facebook/react-native/pull/25619/commits/33573511f02f3502a28bad48e085e9a4b8608302. - I haven't got Fabric working yet. I wonder if it would be acceptable to move Fabric out of the `<React/*>` namespace since it is new? � ## Changelog [iOS] [Fixed] - Fixed compatibility with CocoaPods frameworks. Pull Request resolved: https://github.com/facebook/react-native/pull/25619 Test Plan: ### FB ``` buck build catalyst ``` ### Sample Project Everything should work exactly as before, where `use_frameworks!` is not in `Podfile`s. I have a branch on my [sample project](https://github.com/jtreanor/react-native-cocoapods-frameworks) here which has `use_frameworks!` in its `Podfile` to demonstrate this is fixed. You can see that it works with these steps: 1. `git clone git@github.com:jtreanor/react-native-cocoapods-frameworks.git` 2. `git checkout fix-frameworks-subspecs` 3. `cd ios && pod install` 4. `cd .. && react-native run-ios` The sample app will build and run successfully. To see that it still works without frameworks, remove `use_frameworks!` from the `Podfile` and do steps 3 and 4 again. ### RNTesterPods `RNTesterPodsPods` can now work with or without `use_frameworks!`. 1. Go to the `RNTester` directory and run `pod install`. 2. Run the tests in `RNTesterPods.xcworkspace` to see that everything still works fine. 3. Uncomment the `use_frameworks!` line at the top of `RNTester/Podfile` and run `pod install` again. 4. Run the tests again and see that it still works with frameworks enabled. Reviewed By: PeteTheHeat Differential Revision: D16465247 Pulled By: PeteTheHeat fbshipit-source-id: cad837e9cced06d30cc5b372af1c65c7780b9e7a
2019-07-25 08:26:42 +03:00
#import <React/RCTImageEditingManager.h>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTConvert.h>
CocoaPods frameworks compatibility: Step 2 (#25619) Summary: This is my proposal for fixing `use_frameworks!` compatibility without breaking all `<React/*>` imports I outlined in https://github.com/facebook/react-native/pull/25393#issuecomment-508457700. If accepted, it will fix https://github.com/facebook/react-native/issues/25349. It builds on the changes I made in https://github.com/facebook/react-native/pull/25496 by ensuring each podspec has a unique value for `header_dir` so that framework imports do not conflict. Every podspec which should be included in the `<React/*>` namespace now includes it's headers from `React-Core.podspec`. The following pods can still be imported with `<React/*>` and so should not have breaking changes: `React-ART`,`React-DevSupport`, `React-CoreModules`, `React-RCTActionSheet`, `React-RCTAnimation`, `React-RCTBlob`, `React-RCTImage`, `React-RCTLinking`, `React-RCTNetwork`, `React-RCTPushNotification`, `React-RCTSettings`, `React-RCTText`, `React-RCTSettings`, `React-RCTVibration`, `React-RCTWebSocket` . There are still a few breaking changes which I hope will be acceptable: - `React-Core.podspec` has been moved to the root of the project. Any `Podfile` that references it will need to update the path. - ~~`React-turbomodule-core`'s headers now live under `<turbomodule/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - ~~`React-turbomodulesamples`'s headers now live under `<turbomodulesamples/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - ~~`React-TypeSaferty`'s headers now live under `<TypeSafety/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511040967. - ~~`React-jscallinvoker`'s headers now live under `<jscallinvoker/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - Each podspec now uses `s.static_framework = true`. This means that a minimum of CocoaPods 1.5 ([released in April 2018](http://blog.cocoapods.org/CocoaPods-1.5.0/)) is now required. This is needed so that the ` __has_include` conditions can still work when frameworks are enabled. Still to do: - ~~Including `React-turbomodule-core` with `use_frameworks!` enabled causes the C++ import failures we saw in https://github.com/facebook/react-native/issues/25349. I'm sure it will be possible to fix this but I need to dig deeper (perhaps a custom modulemap would be needed).~~ Addressed by https://github.com/facebook/react-native/pull/25619/commits/33573511f02f3502a28bad48e085e9a4b8608302. - I haven't got Fabric working yet. I wonder if it would be acceptable to move Fabric out of the `<React/*>` namespace since it is new? � ## Changelog [iOS] [Fixed] - Fixed compatibility with CocoaPods frameworks. Pull Request resolved: https://github.com/facebook/react-native/pull/25619 Test Plan: ### FB ``` buck build catalyst ``` ### Sample Project Everything should work exactly as before, where `use_frameworks!` is not in `Podfile`s. I have a branch on my [sample project](https://github.com/jtreanor/react-native-cocoapods-frameworks) here which has `use_frameworks!` in its `Podfile` to demonstrate this is fixed. You can see that it works with these steps: 1. `git clone git@github.com:jtreanor/react-native-cocoapods-frameworks.git` 2. `git checkout fix-frameworks-subspecs` 3. `cd ios && pod install` 4. `cd .. && react-native run-ios` The sample app will build and run successfully. To see that it still works without frameworks, remove `use_frameworks!` from the `Podfile` and do steps 3 and 4 again. ### RNTesterPods `RNTesterPodsPods` can now work with or without `use_frameworks!`. 1. Go to the `RNTester` directory and run `pod install`. 2. Run the tests in `RNTesterPods.xcworkspace` to see that everything still works fine. 3. Uncomment the `use_frameworks!` line at the top of `RNTester/Podfile` and run `pod install` again. 4. Run the tests again and see that it still works with frameworks enabled. Reviewed By: PeteTheHeat Differential Revision: D16465247 Pulled By: PeteTheHeat fbshipit-source-id: cad837e9cced06d30cc5b372af1c65c7780b9e7a
2019-07-25 08:26:42 +03:00
#import <React/RCTImageLoader.h>
#import <React/RCTImageStoreManager.h>
#import <React/RCTImageUtils.h>
#import <React/RCTImageLoaderProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
#import <UIKit/UIKit.h>
#import "RCTImagePlugins.h"
@interface RCTImageEditingManager() <NativeImageEditorSpec>
@end
@implementation RCTImageEditingManager
RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
/**
* Crops an image and adds the result to the image store.
*
* @param imageRequest An image URL
* @param cropData Dictionary with `offset`, `size` and `displaySize`.
* `offset` and `size` are relative to the full-resolution image size.
* `displaySize` is an optimization - if specified, the image will
* be scaled down to `displaySize` rather than `size`.
* All units are in px (not points).
*/
RCT_EXPORT_METHOD(cropImage:(NSURLRequest *)imageRequest
cropData:(JS::NativeImageEditor::Options &)cropData
successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseSenderBlock)errorCallback)
{
CGRect rect = {
[RCTConvert CGPoint:@{
@"x": @(cropData.offset().x()),
@"y": @(cropData.offset().y()),
}],
[RCTConvert CGSize:@{
@"width": @(cropData.size().width()),
@"height": @(cropData.size().height()),
}]
};
// We must keep a copy of cropData so that we can access data from it at a later time
JS::NativeImageEditor::Options cropDataCopy = cropData;
[[_bridge moduleForName:@"ImageLoader" lazilyLoadIfNecessary:YES]
loadImageWithURLRequest:imageRequest callback:^(NSError *error, UIImage *image) {
if (error) {
errorCallback(@[RCTJSErrorFromNSError(error)]);
return;
}
// Crop image
CGSize targetSize = rect.size;
CGRect targetRect = {{-rect.origin.x, -rect.origin.y}, image.size};
CGAffineTransform transform = RCTTransformFromTargetRect(image.size, targetRect);
UIImage *croppedImage = RCTTransformImage(image, targetSize, image.scale, transform);
// Scale image
if (cropDataCopy.displaySize()) {
targetSize = [RCTConvert CGSize:@{@"width": @(cropDataCopy.displaySize()->width()), @"height": @(cropDataCopy.displaySize()->height())}]; // in pixels
RCTResizeMode resizeMode = [RCTConvert RCTResizeMode:cropDataCopy.resizeMode() ?: @"contain"];
targetRect = RCTTargetRect(croppedImage.size, targetSize, 1, resizeMode);
transform = RCTTransformFromTargetRect(croppedImage.size, targetRect);
croppedImage = RCTTransformImage(croppedImage, targetSize, image.scale, transform);
}
// Store image
[self->_bridge.imageStoreManager storeImage:croppedImage withBlock:^(NSString *croppedImageTag) {
if (!croppedImageTag) {
NSString *errorMessage = @"Error storing cropped image in RCTImageStoreManager";
RCTLogWarn(@"%@", errorMessage);
errorCallback(@[RCTJSErrorFromNSError(RCTErrorWithMessage(errorMessage))]);
return;
}
successCallback(@[croppedImageTag]);
}];
}];
}
Part 2: Update ObjC++ codegen classes to use ObjCTurboModule::InitParams Summary: ## Summary Please check out D21035209. ## Changes - Codemod all ObjC NativeModule `getTurboModuleWithJsInvoker:nativeInvoker:perfLogger` methods to `getTurboModule:(const ObjCTurboModule::Args)` ## Script ``` var withSpaces = (...args) => args.join('\s*') var regexString = withSpaces( '-', '\(', 'std::shared_ptr', '<', '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)', '>', '\)', 'getTurboModuleWithJsInvoker', ':', '\(', 'std::shared_ptr', '<', '(?<fbNamespace>(facebook::react::|react::|::|))CallInvoker', '>', '\)', '(?<jsInvokerInstance>[A-Za-z0-9]+)', 'nativeInvoker', ':', '\(', 'std::shared_ptr', '<', '(facebook::react::|react::|::|)CallInvoker', '>', '\)', '(?<nativeInvokerInstance>[A-Za-z0-9]+)', 'perfLogger', ':', '\(', 'id', '<', 'RCTTurboModulePerformanceLogger', '>', '\)', '(?<perfLoggerInstance>[A-Za-z0-9]+)', '{', 'return', 'std::make_shared', '<', '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)', '>', '\(', 'self', ',', '\k<jsInvokerInstance>', ',', '\k<nativeInvokerInstance>', ',', '\k<perfLoggerInstance>', '\)', ';', '}', ) var replaceString = `- (std::shared_ptr<$<turboModuleClass>>) getTurboModule:(const $<fbNamespace>ObjCTurboModule::InitParams &)params { return std::make_shared<$<specName>>(params); }` const exec = require('../lib/exec'); const abspath = require('../lib/abspath'); const relpath = require('../lib/relpath'); const readFile = (filename) => require('fs').readFileSync(filename, 'utf8'); const writeFile = (filename, content) => require('fs').writeFileSync(filename, content); function main() { const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean); tmFiles .filter((filename) => !filename.includes('microsoft-fork-of-react-native')) .map(abspath) .forEach((filename) => { const source = readFile(filename); const newSource = source.replace(new RegExp(regexString, 'g'), replaceString); if (source == newSource) { console.log(relpath(filename)); } writeFile(filename, newSource); }); } if (!module.parent) { main(); } ``` ## Re-generating diff ``` > hg revert -r .^ --all > node index.js # run script ``` Changelog: [iOS][Changed] - Make all ObjC NativeModules create TurboModules using ObjCTurboModule::Args Reviewed By: PeteTheHeat Differential Revision: D21036265 fbshipit-source-id: 404bcc548d1775ef23d793527606d02fe384a0a2
2020-04-17 03:23:39 +03:00
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params
{
Part 2: Update ObjC++ codegen classes to use ObjCTurboModule::InitParams Summary: ## Summary Please check out D21035209. ## Changes - Codemod all ObjC NativeModule `getTurboModuleWithJsInvoker:nativeInvoker:perfLogger` methods to `getTurboModule:(const ObjCTurboModule::Args)` ## Script ``` var withSpaces = (...args) => args.join('\s*') var regexString = withSpaces( '-', '\(', 'std::shared_ptr', '<', '(?<turboModuleClass>(facebook::react::|react::|::|)TurboModule)', '>', '\)', 'getTurboModuleWithJsInvoker', ':', '\(', 'std::shared_ptr', '<', '(?<fbNamespace>(facebook::react::|react::|::|))CallInvoker', '>', '\)', '(?<jsInvokerInstance>[A-Za-z0-9]+)', 'nativeInvoker', ':', '\(', 'std::shared_ptr', '<', '(facebook::react::|react::|::|)CallInvoker', '>', '\)', '(?<nativeInvokerInstance>[A-Za-z0-9]+)', 'perfLogger', ':', '\(', 'id', '<', 'RCTTurboModulePerformanceLogger', '>', '\)', '(?<perfLoggerInstance>[A-Za-z0-9]+)', '{', 'return', 'std::make_shared', '<', '(?<specName>(facebook::react::|react::|::|)Native[%A-Za-z0-9]+SpecJSI)', '>', '\(', 'self', ',', '\k<jsInvokerInstance>', ',', '\k<nativeInvokerInstance>', ',', '\k<perfLoggerInstance>', '\)', ';', '}', ) var replaceString = `- (std::shared_ptr<$<turboModuleClass>>) getTurboModule:(const $<fbNamespace>ObjCTurboModule::InitParams &)params { return std::make_shared<$<specName>>(params); }` const exec = require('../lib/exec'); const abspath = require('../lib/abspath'); const relpath = require('../lib/relpath'); const readFile = (filename) => require('fs').readFileSync(filename, 'utf8'); const writeFile = (filename, content) => require('fs').writeFileSync(filename, content); function main() { const tmFiles = exec('cd ~/fbsource && xbgs -n 10000 -l getTurboModuleWithJsInvoker:').split('\n').filter(Boolean); tmFiles .filter((filename) => !filename.includes('microsoft-fork-of-react-native')) .map(abspath) .forEach((filename) => { const source = readFile(filename); const newSource = source.replace(new RegExp(regexString, 'g'), replaceString); if (source == newSource) { console.log(relpath(filename)); } writeFile(filename, newSource); }); } if (!module.parent) { main(); } ``` ## Re-generating diff ``` > hg revert -r .^ --all > node index.js # run script ``` Changelog: [iOS][Changed] - Make all ObjC NativeModules create TurboModules using ObjCTurboModule::Args Reviewed By: PeteTheHeat Differential Revision: D21036265 fbshipit-source-id: 404bcc548d1775ef23d793527606d02fe384a0a2
2020-04-17 03:23:39 +03:00
return std::make_shared<facebook::react::NativeImageEditorSpecJSI>(params);
}
@end
Class RCTImageEditingManagerCls() {
return RCTImageEditingManager.class;
}