@phucprime/react-native-image-editor 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -161
- package/android/build.gradle +11 -11
- package/ios/RNPhotoEditor.h +0 -5
- package/ios/RNPhotoEditor.m +7 -157
- package/ios/RNPhotoEditor.swift +168 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -1
- package/lib/index.js.map +1 -1
- package/package.json +5 -5
- package/react-native-image-editor.podspec +1 -1
- package/src/index.ts +10 -3
package/README.md
CHANGED
|
@@ -1,44 +1,32 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="https://lh3.googleusercontent.com/dsJXfHnUx0qvZIB_80F-q0iN18eIqmx6g10bmsVN8R6nEnLQDKvJ9lXCbnPCgDEZMw=s180" width="80" />
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
1
|
<h1 align="center">@phucprime/react-native-image-editor</h1>
|
|
6
2
|
|
|
7
3
|
<p align="center">
|
|
8
|
-
Native image editor for React Native — crop, draw,
|
|
4
|
+
Native image editor for React Native — crop, draw, text, stickers, and more.<br/>
|
|
5
|
+
Supports <strong>New Architecture</strong> (Fabric + TurboModules) and the classic bridge.
|
|
9
6
|
</p>
|
|
10
7
|
|
|
11
8
|
<p align="center">
|
|
12
9
|
<a href="https://www.npmjs.com/package/@phucprime/react-native-image-editor"><img src="https://img.shields.io/npm/v/@phucprime/react-native-image-editor.svg?style=flat-square" alt="npm version" /></a>
|
|
13
10
|
<a href="https://www.npmjs.com/package/@phucprime/react-native-image-editor"><img src="https://img.shields.io/npm/dm/@phucprime/react-native-image-editor.svg?style=flat-square" alt="npm downloads" /></a>
|
|
14
11
|
<a href="https://github.com/phucprime/react-native-image-editor/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@phucprime/react-native-image-editor.svg?style=flat-square" alt="license" /></a>
|
|
15
|
-
<a href="https://github.com/phucprime/react-native-image-editor/pulls"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt="PRs Welcome" /></a>
|
|
16
12
|
</p>
|
|
17
13
|
|
|
18
14
|
---
|
|
19
15
|
|
|
20
|
-
## Features
|
|
21
|
-
|
|
22
|
-
- **Cropping** — Resize and reframe images
|
|
23
|
-
- **Drawing** — Freehand drawing with color picker
|
|
24
|
-
- **Text** — Add text overlays with custom colors
|
|
25
|
-
- **Stickers** — Add image stickers from your app resources
|
|
26
|
-
- **Scaling & Rotating** — Transform any added element
|
|
27
|
-
- **Saving & Sharing** — Export edited images
|
|
28
|
-
|
|
29
|
-
## Demo
|
|
30
|
-
|
|
31
16
|
| iOS | Android |
|
|
32
17
|
| :-: | :-: |
|
|
33
|
-
| <img src="assets/ios.gif" width="
|
|
18
|
+
| <img src="assets/ios.gif" width="280" /> | <img src="assets/android.gif" width="280" /> |
|
|
19
|
+
|
|
20
|
+
## Compatibility
|
|
34
21
|
|
|
35
|
-
|
|
22
|
+
| | Minimum | Tested |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| React Native | 0.73 | **0.78.2** |
|
|
25
|
+
| iOS | 13.0 | 18 |
|
|
26
|
+
| Android | API 24 | API 35 |
|
|
27
|
+
| Architecture | Old Arch ✅ | **New Arch ✅** |
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
| -------- | --------------- |
|
|
39
|
-
| iOS | 13.0 |
|
|
40
|
-
| Android | API 21 (5.0) |
|
|
41
|
-
| React Native | >= 0.60 |
|
|
29
|
+
> Requires **JDK 17** and **Gradle 8.x** for Android builds.
|
|
42
30
|
|
|
43
31
|
## Installation
|
|
44
32
|
|
|
@@ -48,33 +36,18 @@ npm install @phucprime/react-native-image-editor
|
|
|
48
36
|
yarn add @phucprime/react-native-image-editor
|
|
49
37
|
```
|
|
50
38
|
|
|
51
|
-
### iOS
|
|
39
|
+
### iOS
|
|
52
40
|
|
|
53
|
-
|
|
41
|
+
Add to your `Podfile`:
|
|
54
42
|
|
|
55
43
|
```ruby
|
|
56
|
-
use_native_modules!
|
|
57
|
-
|
|
58
|
-
# Required: Flipper must be disabled when using iOSPhotoEditor with use_frameworks!
|
|
59
|
-
flipper_config = FlipperConfiguration.disabled
|
|
60
|
-
|
|
61
44
|
use_frameworks! :linkage => :static
|
|
62
45
|
pod "iOSPhotoEditor", :git => "https://github.com/phucprime/photo-editor", :branch => "master"
|
|
63
|
-
|
|
64
|
-
post_install do |installer|
|
|
65
|
-
installer.pods_project.targets.each do |target|
|
|
66
|
-
if target.name.include?('iOSPhotoEditor')
|
|
67
|
-
target.build_configurations.each do |config|
|
|
68
|
-
config.build_settings['SWIFT_VERSION'] = '5'
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
46
|
```
|
|
74
47
|
|
|
75
|
-
|
|
48
|
+
Then run `pod install`.
|
|
76
49
|
|
|
77
|
-
|
|
50
|
+
Add to `Info.plist`:
|
|
78
51
|
|
|
79
52
|
```xml
|
|
80
53
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
|
@@ -83,164 +56,70 @@ end
|
|
|
83
56
|
<string>Allow access to select photos for editing</string>
|
|
84
57
|
```
|
|
85
58
|
|
|
86
|
-
### Android
|
|
59
|
+
### Android
|
|
87
60
|
|
|
88
|
-
|
|
61
|
+
Add JitPack to your root `android/build.gradle`:
|
|
89
62
|
|
|
90
63
|
```groovy
|
|
91
64
|
allprojects {
|
|
92
65
|
repositories {
|
|
93
|
-
// ...existing repos...
|
|
94
66
|
maven { url "https://jitpack.io" }
|
|
95
67
|
}
|
|
96
68
|
}
|
|
97
69
|
```
|
|
98
70
|
|
|
99
|
-
|
|
71
|
+
Add activities to `AndroidManifest.xml`:
|
|
100
72
|
|
|
101
73
|
```xml
|
|
102
74
|
<activity android:name="com.ahmedadeltito.photoeditor.PhotoEditorActivity" />
|
|
103
75
|
<activity android:name="com.yalantis.ucrop.UCropActivity" />
|
|
104
76
|
```
|
|
105
77
|
|
|
106
|
-
3. For saving to external storage:
|
|
107
|
-
|
|
108
|
-
```xml
|
|
109
|
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
4. **JDK 17 required** (AGP 7.x is incompatible with JDK 21). Add to `android/gradle.properties`:
|
|
113
|
-
|
|
114
|
-
```properties
|
|
115
|
-
org.gradle.java.home=/path/to/your/jdk-17
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
> macOS Homebrew: `brew install openjdk@17`, then use `/opt/homebrew/Cellar/openjdk@17/<version>/libexec/openjdk.jdk/Contents/Home`
|
|
119
|
-
|
|
120
78
|
## Usage
|
|
121
79
|
|
|
122
|
-
### Promise
|
|
80
|
+
### Promise API (recommended)
|
|
123
81
|
|
|
124
82
|
```typescript
|
|
125
83
|
import { ImageEditor } from '@phucprime/react-native-image-editor';
|
|
126
84
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
console.log('Edited image saved to:', editedPath);
|
|
133
|
-
} catch (error) {
|
|
134
|
-
console.log('Editor was cancelled');
|
|
135
|
-
}
|
|
85
|
+
const editedPath = await ImageEditor.edit('/path/to/image.jpg', {
|
|
86
|
+
colors: ['#ff0000', '#00ff00', '#0000ff'],
|
|
87
|
+
stickers: ['sticker1', 'sticker2'],
|
|
88
|
+
});
|
|
136
89
|
```
|
|
137
90
|
|
|
138
|
-
### Callback
|
|
91
|
+
### Callback API
|
|
139
92
|
|
|
140
93
|
```typescript
|
|
141
|
-
import { ImageEditor } from '@phucprime/react-native-image-editor';
|
|
142
|
-
|
|
143
94
|
ImageEditor.open({
|
|
144
95
|
path: '/path/to/image.jpg',
|
|
145
|
-
onDone: (
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
onCancel: (resultCode) => {
|
|
149
|
-
console.log('Editor cancelled with code:', resultCode);
|
|
150
|
-
},
|
|
96
|
+
onDone: (path) => console.log('Saved:', path),
|
|
97
|
+
onCancel: () => console.log('Cancelled'),
|
|
151
98
|
});
|
|
152
99
|
```
|
|
153
100
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
## API Reference
|
|
157
|
-
|
|
158
|
-
### `ImageEditor.edit(path, options?): Promise<string>`
|
|
159
|
-
|
|
160
|
-
Opens the editor and returns a promise with the edited image path.
|
|
101
|
+
## Options
|
|
161
102
|
|
|
162
|
-
|
|
|
163
|
-
|
|
|
164
|
-
| `path` | `string` | Path to the image file
|
|
165
|
-
| `
|
|
103
|
+
| Property | Type | Description |
|
|
104
|
+
| -------- | ---- | ----------- |
|
|
105
|
+
| `path` | `string` | Path to the image file |
|
|
106
|
+
| `colors` | `string[]` | Hex colors for draw/text palette |
|
|
107
|
+
| `stickers` | `string[]` | Sticker image names from native resources |
|
|
108
|
+
| `hiddenControls` | `string[]` | Hide: `'text'` `'clear'` `'draw'` `'save'` `'share'` `'sticker'` `'crop'` |
|
|
109
|
+
| `languages` | `object` | UI localization strings |
|
|
166
110
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
Opens the editor with callback-based API.
|
|
170
|
-
|
|
171
|
-
### Configuration
|
|
172
|
-
|
|
173
|
-
| Property | Type | Default | Description |
|
|
174
|
-
| -------- | ---- | ------- | ----------- |
|
|
175
|
-
| `path` | `string` | *required* | Path to the image file |
|
|
176
|
-
| `colors` | `string[]` | 13 default colors | Hex color strings for draw/text palette |
|
|
177
|
-
| `stickers` | `string[]` | `[]` | Sticker image names from native resources |
|
|
178
|
-
| `hiddenControls` | `EditorControl[]` | `[]` | Controls to hide: `'text'`, `'clear'`, `'draw'`, `'save'`, `'share'`, `'sticker'`, `'crop'` |
|
|
179
|
-
| `languages` | `ImageEditorLanguage` | English defaults | UI localization strings |
|
|
180
|
-
| `onDone` | `(path: string) => void` | — | Callback when editing completes |
|
|
181
|
-
| `onCancel` | `(code: number) => void` | — | Callback when editing is cancelled |
|
|
111
|
+
> **Tip:** Use [react-native-fs](https://github.com/itinance/react-native-fs) to copy images into the app sandbox before editing.
|
|
182
112
|
|
|
183
113
|
## Stickers
|
|
184
114
|
|
|
185
|
-
Add
|
|
186
|
-
|
|
187
|
-
- **iOS:** Add to the Resources folder
|
|
188
|
-
- **Android:** Add to the `drawable` folder
|
|
189
|
-
|
|
190
|
-
See the [Example](Example/) project for reference.
|
|
191
|
-
|
|
192
|
-
## Migrating from react-native-photo-editor
|
|
193
|
-
|
|
194
|
-
```diff
|
|
195
|
-
- import PhotoEditor from 'react-native-photo-editor';
|
|
196
|
-
+ import { ImageEditor } from '@phucprime/react-native-image-editor';
|
|
197
|
-
|
|
198
|
-
- PhotoEditor.Edit({ path: imagePath, onDone: handleDone });
|
|
199
|
-
+ ImageEditor.open({ path: imagePath, onDone: handleDone });
|
|
200
|
-
// or use the Promise API:
|
|
201
|
-
+ const result = await ImageEditor.edit(imagePath);
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
Update your iOS `Podfile`:
|
|
205
|
-
|
|
206
|
-
```diff
|
|
207
|
-
- pod 'RNPhotoEditor', :path => '../node_modules/react-native-photo-editor'
|
|
208
|
-
+ pod 'RNImageEditor', :path => '../node_modules/@phucprime/react-native-image-editor'
|
|
209
|
-
- pod 'iOSPhotoEditor', :git => 'https://github.com/prscX/photo-editor'
|
|
210
|
-
+ pod 'iOSPhotoEditor', :git => 'https://github.com/phucprime/photo-editor'
|
|
211
|
-
```
|
|
115
|
+
- **iOS** — Add images to the Resources folder
|
|
116
|
+
- **Android** — Add images to the `drawable` folder
|
|
212
117
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
### React Native Firebase v6+
|
|
216
|
-
|
|
217
|
-
If using Firebase with `use_frameworks!`, add to your `Podfile`:
|
|
218
|
-
|
|
219
|
-
```ruby
|
|
220
|
-
$RNFirebaseAsStaticFramework = true
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Kotlin Metadata Version Mismatch (Gradle 8.x + RN 0.72)
|
|
224
|
-
|
|
225
|
-
Add `-Xskip-metadata-version-check` to `node_modules/@react-native/gradle-plugin/build.gradle.kts`:
|
|
226
|
-
|
|
227
|
-
```kotlin
|
|
228
|
-
tasks.withType<KotlinCompile> {
|
|
229
|
-
kotlinOptions {
|
|
230
|
-
freeCompilerArgs += listOf("-Xskip-metadata-version-check")
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
```
|
|
118
|
+
See the [Example](Example/) project for a working setup.
|
|
234
119
|
|
|
235
120
|
## Credits
|
|
236
121
|
|
|
237
|
-
|
|
238
|
-
- iOS Photo Editor: [eventtus/photo-editor](https://github.com/eventtus/photo-editor)
|
|
239
|
-
- Original library: [prscX/react-native-photo-editor](https://github.com/prscX/react-native-photo-editor)
|
|
240
|
-
|
|
241
|
-
## Contributing
|
|
242
|
-
|
|
243
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
122
|
+
Based on [prscX/react-native-photo-editor](https://github.com/prscX/react-native-photo-editor), with photo editor SDKs by [eventtus](https://github.com/eventtus).
|
|
244
123
|
|
|
245
124
|
## License
|
|
246
125
|
|
package/android/build.gradle
CHANGED
|
@@ -16,19 +16,19 @@ buildscript {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
dependencies {
|
|
19
|
-
classpath('com.android.tools.build:gradle:
|
|
19
|
+
classpath('com.android.tools.build:gradle:8.2.1')
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
android {
|
|
25
25
|
namespace "ui.photoeditor"
|
|
26
|
-
compileSdkVersion safeExtGet('compileSdkVersion',
|
|
27
|
-
buildToolsVersion safeExtGet('buildToolsVersion', '
|
|
26
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
27
|
+
buildToolsVersion safeExtGet('buildToolsVersion', '35.0.0')
|
|
28
28
|
|
|
29
29
|
defaultConfig {
|
|
30
|
-
minSdkVersion safeExtGet('minSdkVersion',
|
|
31
|
-
targetSdkVersion safeExtGet('targetSdkVersion',
|
|
30
|
+
minSdkVersion safeExtGet('minSdkVersion', 24)
|
|
31
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
32
32
|
versionCode 1
|
|
33
33
|
versionName "1.0"
|
|
34
34
|
}
|
|
@@ -38,8 +38,8 @@ android {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
compileOptions {
|
|
41
|
-
sourceCompatibility JavaVersion.
|
|
42
|
-
targetCompatibility JavaVersion.
|
|
41
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
42
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -54,9 +54,9 @@ dependencies {
|
|
|
54
54
|
implementation files('libs/photo-editor-android.jar')
|
|
55
55
|
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar'
|
|
56
56
|
implementation 'com.nineoldandroids:library:2.4.0'
|
|
57
|
-
implementation 'com.android.
|
|
58
|
-
implementation '
|
|
59
|
-
implementation '
|
|
57
|
+
implementation 'com.google.android.material:material:1.9.0'
|
|
58
|
+
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
59
|
+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
|
60
60
|
implementation 'com.github.yalantis:ucrop:2.2.2-native'
|
|
61
|
-
implementation '
|
|
61
|
+
implementation 'androidx.exifinterface:exifinterface:1.3.7'
|
|
62
62
|
}
|
package/ios/RNPhotoEditor.h
CHANGED
package/ios/RNPhotoEditor.m
CHANGED
|
@@ -1,163 +1,13 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
1
2
|
|
|
2
|
-
|
|
3
|
+
@interface RCT_EXTERN_MODULE(RNPhotoEditor, NSObject)
|
|
3
4
|
|
|
5
|
+
RCT_EXTERN_METHOD(Edit:(NSDictionary *)props
|
|
6
|
+
onDone:(RCTResponseSenderBlock)onDone
|
|
7
|
+
onCancel:(RCTResponseSenderBlock)onCancel)
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- (dispatch_queue_t)methodQueue
|
|
8
|
-
{
|
|
9
|
-
return dispatch_get_main_queue();
|
|
10
|
-
}
|
|
11
|
-
RCT_EXPORT_MODULE()
|
|
12
|
-
|
|
13
|
-
NSString *_editImagePath = nil;
|
|
14
|
-
|
|
15
|
-
RCTResponseSenderBlock _onDoneEditing = nil;
|
|
16
|
-
RCTResponseSenderBlock _onCancelEditing = nil;
|
|
17
|
-
|
|
18
|
-
- (void)doneEditingWithImage:(UIImage *)image {
|
|
19
|
-
if (_onDoneEditing == nil) return;
|
|
20
|
-
|
|
21
|
-
NSError* error;
|
|
22
|
-
|
|
23
|
-
BOOL isPNG = [_editImagePath.pathExtension.lowercaseString isEqualToString:@"png"];
|
|
24
|
-
NSString* path = _editImagePath;
|
|
25
|
-
|
|
26
|
-
if ([path containsString:@"file://"]) {
|
|
27
|
-
NSURL *url = [NSURL URLWithString:_editImagePath];
|
|
28
|
-
path = url.path;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
[isPNG ? UIImagePNGRepresentation(image) : UIImageJPEGRepresentation(image, 0.8) writeToFile:path options:NSDataWritingAtomic error:&error];
|
|
32
|
-
|
|
33
|
-
if (error != nil)
|
|
34
|
-
NSLog(@"write error %@", error);
|
|
35
|
-
|
|
36
|
-
_onDoneEditing(@[path]);
|
|
9
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
10
|
+
return YES;
|
|
37
11
|
}
|
|
38
12
|
|
|
39
|
-
- (void)canceledEditing {
|
|
40
|
-
if (_onCancelEditing == nil) return;
|
|
41
|
-
|
|
42
|
-
_onCancelEditing(@[]);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
RCT_EXPORT_METHOD(Edit:(nonnull NSDictionary *)props onDone:(RCTResponseSenderBlock)onDone onCancel:(RCTResponseSenderBlock)onCancel) {
|
|
46
|
-
|
|
47
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
48
|
-
_editImagePath = [props objectForKey: @"path"];
|
|
49
|
-
|
|
50
|
-
_onDoneEditing = onDone;
|
|
51
|
-
_onCancelEditing = onCancel;
|
|
52
|
-
|
|
53
|
-
PhotoEditorViewController *photoEditor = [[PhotoEditorViewController alloc] initWithNibName:@"PhotoEditorViewController" bundle: [NSBundle bundleForClass:[PhotoEditorViewController class]]];
|
|
54
|
-
// set language
|
|
55
|
-
NSDictionary *languages = [props objectForKey: @"languages"];
|
|
56
|
-
[[TranslationService shared] initTranslations:languages];
|
|
57
|
-
|
|
58
|
-
// Process Image for Editing
|
|
59
|
-
UIImage *image = [UIImage imageWithContentsOfFile:_editImagePath];
|
|
60
|
-
if (image == nil) {
|
|
61
|
-
NSURL *url = [NSURL URLWithString:_editImagePath];
|
|
62
|
-
NSData *data = [NSData dataWithContentsOfURL:url];
|
|
63
|
-
|
|
64
|
-
image = [UIImage imageWithData:data];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
photoEditor.image = image;
|
|
68
|
-
|
|
69
|
-
// Process Stickers
|
|
70
|
-
NSArray *stickers = [props objectForKey: @"stickers"];
|
|
71
|
-
NSMutableArray *imageStickers = [[NSMutableArray alloc] initWithCapacity:stickers.count];
|
|
72
|
-
|
|
73
|
-
for (NSString *sticker in stickers) {
|
|
74
|
-
[imageStickers addObject: [UIImage imageNamed: sticker]];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
photoEditor.stickers = imageStickers;
|
|
78
|
-
|
|
79
|
-
//Process Controls
|
|
80
|
-
NSArray *hiddenControls = [props objectForKey: @"hiddenControls"];
|
|
81
|
-
NSMutableArray *passHiddenControls = [[NSMutableArray alloc] initWithCapacity:hiddenControls.count];
|
|
82
|
-
|
|
83
|
-
for (NSString *hiddenControl in hiddenControls) {
|
|
84
|
-
[passHiddenControls addObject: [[NSString alloc] initWithString: hiddenControl]];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
photoEditor.hiddenControls = passHiddenControls;
|
|
88
|
-
|
|
89
|
-
//Process Colors
|
|
90
|
-
NSArray *colors = [props objectForKey: @"colors"];
|
|
91
|
-
NSMutableArray *passColors = [[NSMutableArray alloc] initWithCapacity:colors.count];
|
|
92
|
-
|
|
93
|
-
for (NSString *color in colors) {
|
|
94
|
-
[passColors addObject: [self colorWithHexString: color]];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
photoEditor.colors = passColors;
|
|
98
|
-
|
|
99
|
-
// Invoke Editor
|
|
100
|
-
photoEditor.photoEditorDelegate = self;
|
|
101
|
-
|
|
102
|
-
// The default modal presenting is page sheet in ios 13, not full screen
|
|
103
|
-
if (@available(iOS 13, *)) {
|
|
104
|
-
[photoEditor setModalPresentationStyle: UIModalPresentationFullScreen];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
id<UIApplicationDelegate> app = [[UIApplication sharedApplication] delegate];
|
|
108
|
-
UINavigationController *rootViewController = ((UINavigationController*) app.window.rootViewController);
|
|
109
|
-
|
|
110
|
-
if (rootViewController.presentedViewController) {
|
|
111
|
-
[rootViewController.presentedViewController presentViewController:photoEditor animated:YES completion:nil];
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
[rootViewController presentViewController:photoEditor animated:YES completion:nil];
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
- (CGFloat) colorComponentFrom: (NSString *) string start: (NSUInteger) start length: (NSUInteger) length {
|
|
121
|
-
NSString *substring = [string substringWithRange: NSMakeRange(start, length)];
|
|
122
|
-
NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring];
|
|
123
|
-
unsigned hexComponent;
|
|
124
|
-
[[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent];
|
|
125
|
-
return hexComponent / 255.0;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
- (UIColor *) colorWithHexString: (NSString *) hexString {
|
|
129
|
-
NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString];
|
|
130
|
-
CGFloat alpha, red, blue, green;
|
|
131
|
-
switch ([colorString length]) {
|
|
132
|
-
case 3: // #RGB
|
|
133
|
-
alpha = 1.0f;
|
|
134
|
-
red = [self colorComponentFrom: colorString start: 0 length: 1];
|
|
135
|
-
green = [self colorComponentFrom: colorString start: 1 length: 1];
|
|
136
|
-
blue = [self colorComponentFrom: colorString start: 2 length: 1];
|
|
137
|
-
break;
|
|
138
|
-
case 4: // #ARGB
|
|
139
|
-
alpha = [self colorComponentFrom: colorString start: 0 length: 1];
|
|
140
|
-
red = [self colorComponentFrom: colorString start: 1 length: 1];
|
|
141
|
-
green = [self colorComponentFrom: colorString start: 2 length: 1];
|
|
142
|
-
blue = [self colorComponentFrom: colorString start: 3 length: 1];
|
|
143
|
-
break;
|
|
144
|
-
case 6: // #RRGGBB
|
|
145
|
-
alpha = 1.0f;
|
|
146
|
-
red = [self colorComponentFrom: colorString start: 0 length: 2];
|
|
147
|
-
green = [self colorComponentFrom: colorString start: 2 length: 2];
|
|
148
|
-
blue = [self colorComponentFrom: colorString start: 4 length: 2];
|
|
149
|
-
break;
|
|
150
|
-
case 8: // #AARRGGBB
|
|
151
|
-
alpha = [self colorComponentFrom: colorString start: 0 length: 2];
|
|
152
|
-
red = [self colorComponentFrom: colorString start: 2 length: 2];
|
|
153
|
-
green = [self colorComponentFrom: colorString start: 4 length: 2];
|
|
154
|
-
blue = [self colorComponentFrom: colorString start: 6 length: 2];
|
|
155
|
-
break;
|
|
156
|
-
default:
|
|
157
|
-
return nil;
|
|
158
|
-
}
|
|
159
|
-
return [UIColor colorWithRed: red green: green blue: blue alpha: alpha];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
13
|
@end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
import iOSPhotoEditor
|
|
4
|
+
|
|
5
|
+
@objc(RNPhotoEditor)
|
|
6
|
+
class RNPhotoEditor: NSObject {
|
|
7
|
+
|
|
8
|
+
private var editImagePath: String?
|
|
9
|
+
private var onDoneEditing: RCTResponseSenderBlock?
|
|
10
|
+
private var onCancelEditing: RCTResponseSenderBlock?
|
|
11
|
+
|
|
12
|
+
@objc static func requiresMainQueueSetup() -> Bool {
|
|
13
|
+
return true
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@objc func methodQueue() -> DispatchQueue {
|
|
17
|
+
return .main
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@objc(Edit:onDone:onCancel:)
|
|
21
|
+
func edit(_ props: NSDictionary, onDone: @escaping RCTResponseSenderBlock, onCancel: @escaping RCTResponseSenderBlock) {
|
|
22
|
+
DispatchQueue.main.async { [weak self] in
|
|
23
|
+
guard let self = self else { return }
|
|
24
|
+
|
|
25
|
+
self.editImagePath = props["path"] as? String
|
|
26
|
+
self.onDoneEditing = onDone
|
|
27
|
+
self.onCancelEditing = onCancel
|
|
28
|
+
|
|
29
|
+
let photoEditor = PhotoEditorViewController(
|
|
30
|
+
nibName: "PhotoEditorViewController",
|
|
31
|
+
bundle: Bundle(for: PhotoEditorViewController.self)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
// Set language translations
|
|
35
|
+
// TODO: Re-enable when TranslationService is added to the iOSPhotoEditor pod
|
|
36
|
+
// if let languages = props["languages"] as? [String: String] {
|
|
37
|
+
// TranslationService.shared.initTranslations(languages)
|
|
38
|
+
// }
|
|
39
|
+
|
|
40
|
+
// Process Image for Editing
|
|
41
|
+
var image: UIImage?
|
|
42
|
+
if let path = self.editImagePath {
|
|
43
|
+
image = UIImage(contentsOfFile: path)
|
|
44
|
+
if image == nil, let url = URL(string: path), let data = try? Data(contentsOf: url) {
|
|
45
|
+
image = UIImage(data: data)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
photoEditor.image = image
|
|
49
|
+
|
|
50
|
+
// Process Stickers
|
|
51
|
+
if let stickers = props["stickers"] as? [String] {
|
|
52
|
+
photoEditor.stickers = stickers.compactMap { UIImage(named: $0) }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Process Controls
|
|
56
|
+
if let hiddenControls = props["hiddenControls"] as? [String] {
|
|
57
|
+
photoEditor.hiddenControls = hiddenControls.compactMap { controlName in
|
|
58
|
+
switch controlName.lowercased() {
|
|
59
|
+
case "crop": return .crop
|
|
60
|
+
case "sticker": return .sticker
|
|
61
|
+
case "draw": return .draw
|
|
62
|
+
case "text": return .text
|
|
63
|
+
case "save": return .save
|
|
64
|
+
case "share": return .share
|
|
65
|
+
case "clear": return .clear
|
|
66
|
+
default: return nil
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Process Colors
|
|
72
|
+
if let colors = props["colors"] as? [String] {
|
|
73
|
+
photoEditor.colors = colors.compactMap { self.color(fromHexString: $0) }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Invoke Editor
|
|
77
|
+
photoEditor.photoEditorDelegate = self
|
|
78
|
+
|
|
79
|
+
// The default modal presenting is page sheet in iOS 13, not full screen
|
|
80
|
+
photoEditor.modalPresentationStyle = .fullScreen
|
|
81
|
+
|
|
82
|
+
guard let rootViewController = UIApplication.shared.delegate?.window??.rootViewController else { return }
|
|
83
|
+
|
|
84
|
+
if let presentedVC = rootViewController.presentedViewController {
|
|
85
|
+
presentedVC.present(photoEditor, animated: true, completion: nil)
|
|
86
|
+
} else {
|
|
87
|
+
rootViewController.present(photoEditor, animated: true, completion: nil)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// MARK: - Hex Color Utilities
|
|
93
|
+
|
|
94
|
+
private func colorComponent(from string: String, start: Int, length: Int) -> CGFloat {
|
|
95
|
+
let startIndex = string.index(string.startIndex, offsetBy: start)
|
|
96
|
+
let endIndex = string.index(startIndex, offsetBy: length)
|
|
97
|
+
var substring = String(string[startIndex..<endIndex])
|
|
98
|
+
if length == 1 {
|
|
99
|
+
substring = "\(substring)\(substring)"
|
|
100
|
+
}
|
|
101
|
+
var hexComponent: UInt64 = 0
|
|
102
|
+
Scanner(string: substring).scanHexInt64(&hexComponent)
|
|
103
|
+
return CGFloat(hexComponent) / 255.0
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private func color(fromHexString hexString: String) -> UIColor? {
|
|
107
|
+
let colorString = hexString.replacingOccurrences(of: "#", with: "").uppercased()
|
|
108
|
+
let alpha: CGFloat
|
|
109
|
+
let red: CGFloat
|
|
110
|
+
let green: CGFloat
|
|
111
|
+
let blue: CGFloat
|
|
112
|
+
|
|
113
|
+
switch colorString.count {
|
|
114
|
+
case 3: // #RGB
|
|
115
|
+
alpha = 1.0
|
|
116
|
+
red = colorComponent(from: colorString, start: 0, length: 1)
|
|
117
|
+
green = colorComponent(from: colorString, start: 1, length: 1)
|
|
118
|
+
blue = colorComponent(from: colorString, start: 2, length: 1)
|
|
119
|
+
case 4: // #ARGB
|
|
120
|
+
alpha = colorComponent(from: colorString, start: 0, length: 1)
|
|
121
|
+
red = colorComponent(from: colorString, start: 1, length: 1)
|
|
122
|
+
green = colorComponent(from: colorString, start: 2, length: 1)
|
|
123
|
+
blue = colorComponent(from: colorString, start: 3, length: 1)
|
|
124
|
+
case 6: // #RRGGBB
|
|
125
|
+
alpha = 1.0
|
|
126
|
+
red = colorComponent(from: colorString, start: 0, length: 2)
|
|
127
|
+
green = colorComponent(from: colorString, start: 2, length: 2)
|
|
128
|
+
blue = colorComponent(from: colorString, start: 4, length: 2)
|
|
129
|
+
case 8: // #AARRGGBB
|
|
130
|
+
alpha = colorComponent(from: colorString, start: 0, length: 2)
|
|
131
|
+
red = colorComponent(from: colorString, start: 2, length: 2)
|
|
132
|
+
green = colorComponent(from: colorString, start: 4, length: 2)
|
|
133
|
+
blue = colorComponent(from: colorString, start: 6, length: 2)
|
|
134
|
+
default:
|
|
135
|
+
return nil
|
|
136
|
+
}
|
|
137
|
+
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// MARK: - PhotoEditorDelegate
|
|
142
|
+
|
|
143
|
+
extension RNPhotoEditor: PhotoEditorDelegate {
|
|
144
|
+
func doneEditing(image: UIImage) {
|
|
145
|
+
guard let onDoneEditing = onDoneEditing, let editImagePath = editImagePath else { return }
|
|
146
|
+
|
|
147
|
+
let isPNG = (editImagePath as NSString).pathExtension.lowercased() == "png"
|
|
148
|
+
var path = editImagePath
|
|
149
|
+
|
|
150
|
+
if path.contains("file://"), let url = URL(string: editImagePath) {
|
|
151
|
+
path = url.path
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let data = isPNG ? image.pngData() : image.jpegData(compressionQuality: 0.8)
|
|
155
|
+
do {
|
|
156
|
+
try data?.write(to: URL(fileURLWithPath: path), options: .atomic)
|
|
157
|
+
} catch {
|
|
158
|
+
NSLog("write error %@", error.localizedDescription)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
onDoneEditing([path])
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
func canceledEditing() {
|
|
165
|
+
guard let onCancelEditing = onCancelEditing else { return }
|
|
166
|
+
onCancelEditing([])
|
|
167
|
+
}
|
|
168
|
+
}
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wDAAwD;AACxD,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,OAAO,GACP,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IAEjC;;OAEG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAEhC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAsCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,cAAM,WAAW;IACf;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAgC5C;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC,GAChE,OAAO,CAAC,MAAM,CAAC;IAYlB;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,QAAA,MAAM,WAAW,oBAAc,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AACpC,eAAe,WAAW,CAAC;AAG3B,mDAAmD;AACnD,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AACjD,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAAG,mBAAmB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -13,7 +13,13 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.PhotoEditor = exports.ImageEditor = void 0;
|
|
15
15
|
const react_native_1 = require("react-native");
|
|
16
|
-
|
|
16
|
+
// Support both New Architecture (interop layer) and Old Architecture (NativeModules bridge).
|
|
17
|
+
// In RN 0.78+, NativeModules works through the TurboModule interop layer in bridgeless mode.
|
|
18
|
+
const RNPhotoEditor = react_native_1.NativeModules.RNPhotoEditor;
|
|
19
|
+
if (!RNPhotoEditor) {
|
|
20
|
+
throw new Error('@phucprime/react-native-image-editor: NativeModule RNPhotoEditor is null. ' +
|
|
21
|
+
'Make sure the native module is properly linked.');
|
|
22
|
+
}
|
|
17
23
|
/** Default color palette for the editor. */
|
|
18
24
|
const DEFAULT_COLORS = [
|
|
19
25
|
'#000000',
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,+CAAuD;AAEvD,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,+CAAuD;AAEvD,6FAA6F;AAC7F,6FAA6F;AAC7F,MAAM,aAAa,GAAG,4BAAa,CAAC,aAAa,CAAC;AAClD,IAAI,CAAC,aAAa,EAAE,CAAC;IACnB,MAAM,IAAI,KAAK,CACb,4EAA4E;QAC1E,iDAAiD,CACpD,CAAC;AACJ,CAAC;AA4FD,4CAA4C;AAC5C,MAAM,cAAc,GAAa;IAC/B,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;CACV,CAAC;AAEF,oCAAoC;AACpC,MAAM,iBAAiB,GAAkC;IACvD,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,aAAa,EAAE,WAAW;IAC1B,WAAW,EAAE,QAAQ;IACrB,YAAY,EAAE,SAAS;IACvB,iBAAiB,EAAE,cAAc;IACjC,iBAAiB,EAAE,gBAAgB;IACnC,mBAAmB,EAAE,4BAA4B;IACjD,yBAAyB,EACvB,0DAA0D;IAC5D,WAAW,EAAE,UAAU;IACvB,MAAM,EAAE,SAAS;IACjB,oBAAoB,EAAE,qDAAqD;IAC3E,gBAAgB,EAAE,aAAa;IAC/B,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW;IACf;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,MAAyB;QACnC,MAAM,EACJ,QAAQ,GAAG,EAAE,EACb,cAAc,GAAG,EAAE,EACnB,MAAM,GAAG,cAAc,EACvB,SAAS,EACT,MAAM,EACN,QAAQ,KAEN,MAAM,EADL,IAAI,UACL,MAAM,EARJ,2EAQL,CAAS,CAAC;QAEX,MAAM,eAAe,GAAG,SAAS;YAC/B,CAAC,iCAAM,iBAAiB,GAAK,SAAS,EACtC,CAAC,CAAC,iBAAiB,CAAC;QAEtB,aAAa,CAAC,IAAI,iBAEd,MAAM;YACN,cAAc;YACd,QAAQ,EACR,SAAS,EAAE,eAAe,IACvB,IAAI,GAET,CAAC,SAAiB,EAAE,EAAE;YACpB,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAG,SAAS,CAAC,CAAC;QACtB,CAAC,EACD,CAAC,UAAkB,EAAE,EAAE;YACrB,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,UAAU,CAAC,CAAC;QACzB,CAAC,CACF,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CACT,IAAY,EACZ,OAAiE;QAEjE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,WAAW,CAAC,IAAI,iCACX,OAAO,KACV,IAAI,EACJ,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CACvB,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC,IAChE,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,MAAyB;QACnC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;CACF;AAOQ,kCAAW;AALpB;;GAEG;AACH,MAAM,WAAW,GAAG,WAAW,CAAC;AAEV,kCAAW;AACjC,kBAAe,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phucprime/react-native-image-editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "React Native: Native Image Editor for iOS and Android with drawing, text, stickers, cropping and more",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"format": "prettier --write src/",
|
|
32
32
|
"clean": "rm -rf lib/",
|
|
33
33
|
"prepare": "npm run clean && npm run build",
|
|
34
|
-
"release": "npm run prepare && npm publish --access public"
|
|
34
|
+
"release": "npm run prepare && npm publish --access public --registry https://registry.npmjs.org/"
|
|
35
35
|
},
|
|
36
36
|
"keywords": [
|
|
37
37
|
"react-native",
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@types/react": "^18.2.0",
|
|
66
|
-
"@types/react-native": "^0.72.0",
|
|
65
|
+
"@types/react": "^18.2.0 || ^19.0.0",
|
|
67
66
|
"prettier": "^3.2.0",
|
|
67
|
+
"react-native": "0.78.2",
|
|
68
68
|
"typescript": "^5.3.0"
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
71
|
"node": ">=16.0.0"
|
|
72
72
|
}
|
|
73
|
-
}
|
|
73
|
+
}
|
|
@@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
|
|
12
12
|
s.platforms = { :ios => "13.0" }
|
|
13
13
|
s.source = { :git => "https://github.com/phucprime/react-native-image-editor.git", :tag => "#{s.version}" }
|
|
14
14
|
|
|
15
|
-
s.source_files = "ios/**/*.{h,m,mm}"
|
|
15
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
16
16
|
s.dependency "iOSPhotoEditor"
|
|
17
17
|
|
|
18
18
|
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// Support both New Architecture (interop layer) and Old Architecture (NativeModules bridge).
|
|
4
|
+
// In RN 0.78+, NativeModules works through the TurboModule interop layer in bridgeless mode.
|
|
5
|
+
const RNPhotoEditor = NativeModules.RNPhotoEditor;
|
|
6
|
+
if (!RNPhotoEditor) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
'@phucprime/react-native-image-editor: NativeModule RNPhotoEditor is null. ' +
|
|
9
|
+
'Make sure the native module is properly linked.',
|
|
10
|
+
);
|
|
11
|
+
}
|
|
4
12
|
|
|
5
13
|
/**
|
|
6
14
|
* Localization strings for the image editor UI.
|
|
@@ -123,8 +131,7 @@ const DEFAULT_LANGUAGES: Required<ImageEditorLanguage> = {
|
|
|
123
131
|
'To attach photos, we need to access media on your device',
|
|
124
132
|
continueTxt: 'Continue',
|
|
125
133
|
notNow: 'NOT NOW',
|
|
126
|
-
mediaAccessDeniedMsg:
|
|
127
|
-
'You denied storage access, no photos will be added.',
|
|
134
|
+
mediaAccessDeniedMsg: 'You denied storage access, no photos will be added.',
|
|
128
135
|
saveImageSucceed: 'Image saved',
|
|
129
136
|
eraserTitle: 'Eraser',
|
|
130
137
|
};
|