npm.io
1.0.2 • Published yesterday

@watermarker/react-native

Licence
MIT
Version
1.0.2
Deps
0
Size
42 kB
Vulns
0
Weekly
0

@watermarker/react-native

The React Native binding: a TurboModule over the shared native packages — WatermarkerKit on iOS, the io.github.alexdonh:watermarker AAR on Android.

Everything crossing the bridge is a short string: two file paths, the options JSON, and a small assets array. The photo itself never crosses — the engine reads and writes it by path. That is why this is a TurboModule and not a JSI binding: JSI exists to avoid serializing large payloads, and there are none.

New architecture only.

Architecture

bindings/react-native/
  src/
    index.tsx                  the API: watermarkFile / watermarkFiles / watermarkBase64
    NativeWatermarker.ts       the TurboModule spec, which codegen reads
    options.ts                 typed options schema (Layer/Layout/Style/...)
  ios/Watermarker.mm           ObjC++ module over the C ABI, via WatermarkerKit
  android/src/
    main/java/.../WatermarkerModuleImpl.kt   the shared implementation
    newarch/, oldarch/                        the two module shells
  watermarker.podspec          depends on the WatermarkerKit pod

The JSON options schema is identical on every platform.

Install

npm install @watermarker/react-native

The package autolinks. On iOS, the engine ships separately as the prebuilt WatermarkerKit pod; add one line to your ios/Podfile pointing at the matching release so CocoaPods can resolve it:

pod 'WatermarkerKit', :podspec =>
  'https://github.com/alexdonh/watermarker/releases/download/v<version>/WatermarkerKit.podspec'
cd ios && pod install

On Android the engine resolves from Maven Central, so just keep mavenCentral() in your app's repositories; no credentials or other setup is needed.

Usage

import {
  watermarkFile, watermarkFiles, watermarkBase64,
  presetNames, presetOptions, abiVersion,
} from '@watermarker/react-native';

const options = { layers: [{ type: 'text', value: '© Alex Do', layout: 'corner' }] };

// By path: the photo never crosses the bridge.
await watermarkFile(photo.uri, outPath, options);

// One prepared mark for a whole roll. Every photo after the first is only a
// blend, which is what makes this worth using over a loop.
await watermarkFiles(photos.map(p => ({ inputPath: p.uri, outputPath: out(p) })), options);

// Base64 in, base64 out, for a live preview with no file churn.
const preview = await watermarkBase64(base64, options);

// A preset is never merged into an object you wrote; this is how to start from one.
const layout = { ...(await presetOptions('layout', 'mesh')), gap: '8%' };

Inline logo and font bytes are source / font strings in the options; they are split out and uploaded for you, so asset ids stay internal.

Paths

A file:// URL — what react-native-image-picker hands back on iOS — is turned into a filesystem path for you. An Android content:// URI is not a path at all and cannot be made into one; copy it to the cache directory first.

See the demo in examples/react-native.

Keywords