Skip to content

Commit 7a09cb5

Browse files
authored
1.19.3 (#413)
1 parent d9e5683 commit 7a09cb5

11 files changed

Lines changed: 1114 additions & 661 deletions

File tree

CLAUDE.md

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
# CLAUDE.md — react-native-compressor
2+
3+
This file is a project guide for Claude Code / AI agents working on `react-native-compressor`. It describes the repository layout, how the library is structured, how to build and test, common pitfalls, and the conventions used when making changes.
4+
5+
## 1. Project overview
6+
7+
`react-native-compressor` is a React Native module that compresses images, videos, and audio, creates video thumbnails, downloads remote media, and performs background file uploads.
8+
9+
- **Language stack:** TypeScript (JS wrapper), Kotlin (Android), Swift/Objective-C++ (iOS).
10+
- **Module systems:** Supports both the legacy Native Modules bridge and the New Architecture TurboModules spec. The current `1.19.3` branch remains on TurboModules; `main` (2.x) has migrated to Nitro Modules (see §8).
11+
- **Package manager:** Yarn 4 with workspaces. The repository contains two example apps under `examples/`.
12+
- **Node engine:** >= 22.11.0.
13+
14+
## 2. Repository layout
15+
16+
```text
17+
react-native-compressor/
18+
├── android/ # Android library (Kotlin, Gradle)
19+
├── ios/ # iOS library (Swift, Objective-C++)
20+
├── src/ # TypeScript source and TurboModule spec
21+
│ ├── Audio/
22+
│ ├── Image/
23+
│ ├── Video/
24+
│ ├── Spec/ # TurboModule spec
25+
│ ├── expo-plugin/
26+
│ ├── utils/ # Upload, download, helpers
27+
│ ├── Main.tsx # Module resolution (Turbo / legacy)
28+
│ ├── index.tsx # Public exports
29+
│ └── global.d.ts
30+
├── __tests__/ # Jest unit tests
31+
├── examples/
32+
│ ├── bare/ # Bare React Native example
33+
│ └── expo/ # Expo example
34+
├── harness/ # react-native-harness configuration
35+
├── media/ # Test assets
36+
├── package.json
37+
├── CONTRIBUTING.md
38+
├── TRIAGE.md # Upstream issue audit
39+
└── README.md
40+
```
41+
42+
## 3. Public API
43+
44+
The default export and named exports live in `src/index.tsx`:
45+
46+
```ts
47+
import {
48+
Image,
49+
Video,
50+
Audio,
51+
backgroundUpload,
52+
cancelUpload,
53+
download,
54+
getDetails,
55+
uuidv4,
56+
generateFilePath,
57+
getRealPath,
58+
getVideoMetaData,
59+
getImageMetaData,
60+
createVideoThumbnail,
61+
clearCache,
62+
getFileSize,
63+
UploadType,
64+
UploaderHttpMethod,
65+
} from 'react-native-compressor';
66+
```
67+
68+
Key behavioral rules:
69+
70+
- `Image.compress(value, options?)` rejects empty `value` before calling native code and strips `data:image/...;base64,` headers.
71+
- `Video.compress(fileUrl, options?, onProgress?)` always generates an internal UUID, defaults `compressionMethod` to `'auto'` and `maxSize` to `640`, and supports `stripAudio`.
72+
- `Audio.compress(url, options?)` defaults to `{ quality: 'medium' }`.
73+
- `backgroundUpload(url, fileUrl, options, onProgress?, abortSignal?)` removes the `file://` prefix on Android and wires an `AbortSignal` to `cancelUpload`.
74+
- `download(fileUrl, progress?, progressDivider?)` also strips `file://` on Android.
75+
76+
## 4. Native module resolution
77+
78+
`src/Main.tsx` resolves the native module:
79+
80+
```ts
81+
const isTurboModuleEnabled = global.__turboModuleProxy != null;
82+
const CompressorModule = isTurboModuleEnabled
83+
? require('./Spec/NativeCompressor').default
84+
: NativeModules.Compressor;
85+
```
86+
87+
The TurboModule spec is in `src/Spec/NativeCompressor.ts`. Do **not** rename these methods without updating all native call sites.
88+
89+
## 5. Development workflow
90+
91+
Install dependencies:
92+
93+
```sh
94+
yarn
95+
```
96+
97+
Run the examples:
98+
99+
```sh
100+
yarn example:bare start
101+
yarn example:bare android
102+
yarn example:bare ios
103+
yarn example:expo start
104+
```
105+
106+
Code quality gates:
107+
108+
```sh
109+
yarn typecheck # tsc --noEmit
110+
yarn lint # eslint "**/*.{js,ts,tsx}"
111+
yarn lint --fix # auto-fix formatting / lint issues
112+
yarn test # Jest unit tests
113+
yarn test:pr # test + typecheck + lint (CI gate)
114+
```
115+
116+
Clean build folders:
117+
118+
```sh
119+
yarn clean
120+
```
121+
122+
Release (maintainers only):
123+
124+
```sh
125+
yarn release
126+
```
127+
128+
## 6. Testing
129+
130+
### Unit tests
131+
132+
`__tests__/compressor.test.ts` mocks the native module and validates the JS wrapper contract. When you change option forwarding, event-emitter wiring, or the export surface, update this test.
133+
134+
Run:
135+
136+
```sh
137+
yarn test
138+
```
139+
140+
### Native harness tests
141+
142+
For changes that affect compression/upload/download native behavior, run the harness tests on a real device or simulator:
143+
144+
```sh
145+
yarn test:harness:android
146+
yarn test:harness:ios
147+
```
148+
149+
Harness config lives in `examples/bare/jest.harness.config.mjs`. The harness tests exercise actual media decoding and are the source of truth for native behavior.
150+
151+
### Example apps
152+
153+
Always test manually in `examples/bare` and `examples/expo` when touching:
154+
155+
- Native Android/iOS code
156+
- The Expo plugin (`app.plugin.js`, `src/expo-plugin/`)
157+
- Upload/download progress wiring
158+
159+
## 7. Git conventions
160+
161+
- **Commit format:** Conventional Commits.
162+
- `fix:` bug fixes
163+
- `feat:` new features
164+
- `refactor:` code refactoring
165+
- `docs:` documentation changes
166+
- `test:` test changes
167+
- `chore:` tooling / CI
168+
- **Pre-commit hooks** (`lefthook.yml`) run ESLint and `tsc --noEmit` on staged files; `commit-msg` runs `commitlint`.
169+
- **PR template:** `.github/PULL_REQUEST_TEMPLATE.md` requires a Summary, Changelog entry, and Test Plan.
170+
171+
Always run the PR gate before pushing:
172+
173+
```sh
174+
yarn test:pr
175+
```
176+
177+
## 8. Branch strategy and the Nitro migration
178+
179+
- `main` is on 2.x and has migrated to **Nitro Modules** (`feat: migrate react-native-compressor to Nitro Modules #401`).
180+
- The current working branch is `1.19.3`, which keeps the TurboModule / legacy bridge structure.
181+
- Fixes that land on `1.19.3` may need to be forward-ported to `main`/Nitro, and vice versa. Check both branches when resolving regressions.
182+
183+
## 9. Platform-specific notes
184+
185+
### Android
186+
187+
- Source lives in `android/src/main/java/com/reactnativecompressor/`.
188+
- Uses Kotlin coroutines (`kotlinx-coroutines-core/android 1.6.4`).
189+
- Uses `org.mp4parser:isoparser:1.9.56` for MP4 container manipulation.
190+
- Uses `com.github.kaushik-naik:TAndroidLame` for audio encoding.
191+
- `android/build.gradle` enables `buildConfig` for AGP 8+ compatibility.
192+
- `file://` prefixes are stripped before passing paths to native methods (done in JS for download/upload).
193+
194+
### iOS
195+
196+
- Source lives in `ios/` and is organized into `Audio/`, `Image/`, `Video/`, and `Utils/`.
197+
- Entry point: `ios/Compressor.mm` with `CompressorManager.swift` coordinating work.
198+
- `AssetsLibrary` has been removed (iOS 26 / modern SDK support).
199+
- Guard against audio-only / missing video tracks; exports must fail explicitly rather than silently producing audio-only MP4s.
200+
201+
## 10. Common pitfalls
202+
203+
1. **Native method names.** The spec in `src/Spec/NativeCompressor.ts` must match the Android/iOS method names. Renames require three-way updates.
204+
2. **UUID wiring.** Progress events are keyed by UUID. If a native call does not receive the UUID, progress callbacks will not fire.
205+
3. **File URI normalization.** Android native APIs expect plain filesystem paths; `file://` stripping happens in `src/utils/Uploader.tsx` and `Downloader.tsx`. iOS generally accepts `file://` URIs.
206+
4. **Event listener cleanup.** Wrappers add `NativeEventEmitter` listeners in `try` and remove them in `finally`. Always preserve this pattern to avoid leaks.
207+
5. **Base64 images.** `Image.compress` strips the base64 data URL header before calling `image_compress`. Do not double-strip in native code.
208+
6. **Expo plugin changes.** If you change config-plugin behavior, test in `examples/expo` and verify `app.plugin.js` still resolves correctly.
209+
7. **New Architecture.** Builds with `newArchEnabled=true` generate code into `android/build/generated/source/codegen/java`. Clean builds are required when the spec changes.
210+
8. **Swift errors vs NSException.** Do not call `NSException.raise()` in iOS Swift code invoked by a TurboModule — it aborts the process and no JS catch can intercept it. Use Swift `throw` with a typed error; the calling Swift code wraps in `do/catch` and calls `reject`. This applies to all iOS image/video/audio compression handlers.
211+
212+
## 11. What to do when touching specific areas
213+
214+
| Area | Files to read / update | Validation |
215+
| --- | --- | --- |
216+
| Image compression | `src/Image/index.tsx`, `ios/Image/`, `android/src/.../Image/` | Unit test + bare example |
217+
| Video compression | `src/Video/index.tsx`, `ios/Video/`, `android/src/.../Video/` | Harness test + bare example |
218+
| Audio compression | `src/Audio/index.tsx`, `ios/Audio/`, `android/src/.../Audio/` | Bare example |
219+
| Upload / download | `src/utils/Uploader.tsx`, `src/utils/Downloader.tsx` | Unit test + harness test |
220+
| Thumbnails / metadata | `src/utils/index.tsx`, native utils | Unit test + bare example |
221+
| Expo plugin | `app.plugin.js`, `src/expo-plugin/` | `examples/expo` build |
222+
| TurboModule spec | `src/Spec/NativeCompressor.ts` | `yarn typecheck`, rebuild native apps |
223+
| CI / tooling | `.github/workflows/`, `package.json`, `lefthook.yml` | Push to a PR and inspect Actions |
224+
225+
## 12. Useful commands
226+
227+
```sh
228+
# Full PR gate
229+
yarn test:pr
230+
231+
# Android build (debug)
232+
yarn build:android
233+
234+
# iOS build (debug simulator)
235+
yarn build:ios
236+
237+
# Native harness
238+
yarn test:harness:android
239+
yarn test:harness:ios
240+
241+
# Clean everything
242+
yarn clean
243+
```
244+
245+
## 13. Release notes
246+
247+
Published versions use `release-it` with the conventional-changelog plugin. The changelog is generated from commit messages, so write clear, scoped commits.
248+
249+
---
250+
251+
When in doubt, keep changes minimal, add or update unit tests, and run `yarn test:pr` before asking for review.

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div align="center">
22
<img height="150" src="/media/logo.png" />
33
</div>
4-
4+
55
<br/>
66

77
<div align="center">
@@ -14,6 +14,12 @@
1414

1515
</div>
1616

17+
> ⚠️ **Legacy Notice**
18+
>
19+
> This repository is now in **maintenance mode** for the v1 series. Version **1.19.3** will be the last release of v1. Development has moved to **[v2](https://github.com/numandev1/react-native-compressor)** which uses **Nitro Modules** for improved performance and maintainability.
20+
>
21+
> New features, bug fixes and enhancements will land in v2 only.
22+
1723
**REACT-NATIVE-COMPRESSOR** is a react-native package, which helps us to Compress `Image`, `Video`, and `Audio` before uploading, same like **Whatsapp** without knowing the compression `algorithm`
1824

1925
<div align="center">

TRIAGE.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Upstream issue triage
22

3-
Audited against `numandev1/react-native-compressor` open issues on 2026-04-27 and compared with the current tree in this fork.
3+
Audited against `numandev1/react-native-compressor` open issues on 2026-07-14 and compared with the current tree in this fork.
44

55
Legend:
66
- `real` = credible library issue
@@ -80,6 +80,45 @@ These should be closed upstream unless a current repro still exists on the lates
8080
- #370
8181
- #318
8282

83+
## Recent PRs on the 1.19.3 branch
84+
85+
Since the last audit, the branch has integrated or backported work reflected in the following areas:
86+
87+
| PR | What changed |
88+
| --- | --- |
89+
| #408 | Fixed Expo plugin/release build references so managed Expo apps can build against the current module structure. |
90+
| #407 | Corrected Nitro module imports/paths to keep `main` working after the 2.0.0 Nitro migration. |
91+
| #411 | iOS image compression: replaced `NSException.raise()` with Swift `throw` so errors properly reject the promise instead of aborting the whole app. |
92+
| #403 / #400 | iOS export session now fails explicitly instead of silently returning an audio-only MP4 when the video track is missing or cannot be written. |
93+
| #402 | Dolby Vision compatibility improvements on iOS. |
94+
| #399 | Dolby Vision crash fix, up to ~50% faster iOS transcode, and corrected fps/bitrate/GPS metadata handling. |
95+
| #397 | Cross-platform compressor hardening and review-feedback fixes. |
96+
| #396 | Additional test coverage for compression paths. |
97+
| #395 | Refined video compression profiles after upstream issue triage. |
98+
| #393 | New `stripAudio` option on video compression to drop the audio track from the output. |
99+
| #392 | Upstream issue triage and high-resolution video compression hardening. |
100+
| #388 | iOS background upload now resolves with the server response body, matching Android behavior. |
101+
| #391 | Tooling, CI, and example-app modernization (Yarn 4, React Native 0.85, updated harness). |
102+
| #386 | Android 14+ orientation correction for images. |
103+
| #385 | Out-of-memory crash mitigation during large-file processing. |
104+
| #374 | Base64 image compression handling on iOS. |
105+
| #372 | 16 KB page-size support on Android. |
106+
| #368 | Removed deprecated iOS `AssetsLibrary` API and fixed an iOS runtime crash. |
107+
| #351 | Replaced `toLowerCase()` with Kotlin `lowercase()`. |
108+
| #342 | Moved `uuidv4` to a dedicated helper to avoid circular dependencies with React Compiler. |
109+
| #341 | Refactored `createVideoThumbnail` internals. |
110+
| #339 | Preserved original audio channel count to fix iOS playback for certain Android-compressed videos. |
111+
| #334 | Fixed iOS crash when processing file size of an unparsed URL. |
112+
| #328 | Documentation repetition fix. |
113+
| #325 / #324 | Build fixes for missing `kAudioFormatAPAC` symbol on some Xcode versions. |
114+
| #321 | iPhone 16 / Pro Max compression fix. |
115+
| #320 | Yarn upgrade and workspace tooling refresh. |
116+
| #311 | `isoparser` 1.9.x migration and old-code cleanup. |
117+
| #305 | Same `isoparser` modernization. |
118+
| #295 | iOS manual image compression source fix. |
119+
| #290 | mp4parser compatibility fix. |
120+
| #284 / #281 | Android upload and speed fixes. |
121+
83122
## Minor fixes made in this branch
84123

85124
- Android: enable `buildConfig` generation for AGP 8+ builds

android/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ dependencies {
119119
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
120120
implementation 'org.mp4parser:isoparser:1.9.56'
121121
implementation 'com.github.kaushik-naik:TAndroidLame:277c2ab4b0'
122-
implementation 'javazoom:jlayer:1.0.1'
123122
}
124123

125124
if (isNewArchitectureEnabled()) {

0 commit comments

Comments
 (0)