# aigens-sdk-huawei

Web-side plugin for Aigens BYOD apps running inside HarmonyOS WebView.

## Documentation

- [API Docs](./docs/index.html) - Generated TypeDoc API reference for all classes, interfaces and functions.

## Installation

```bash
npm install aigens-sdk-huawei
```

## Quick Start

```typescript
import { isHuaWei, getHuaweiCore } from 'aigens-sdk-huawei';
import { Core } from '@aigens/aigens-sdk-core';

// Auto-detect environment and pick the right Core
const activeCore = isHuaWei() ? getHuaweiCore() : Core;

// Use it like regular Core
const { member } = await activeCore.getMember({});
const { deeplink } = await activeCore.getDeeplink({});
await activeCore.dismiss({ closedData: { status: 'done' } });
```

## API

### isHuaWei(): boolean

Detects HarmonyOS WebView via User-Agent. Cached after first call.

### getHuaweiCore(): CorePlugin

Returns a singleton `CoreHuawei` instance (drop-in replacement for Capacitor `Core`).

### CorePlugin Methods

All methods route through JS Bridge to HarmonyOS native.

#### getMember(options): Promise&lt;{ member: Member }&gt;

Returns current member info.

```typescript
interface Member {
  deviceId: string;
  memberCode?: string;
  source?: string;
  sessionId?: string;
  appScheme?: string;
  universalLink?: string;
  name?: string;
  email?: string;
  phone?: string;
}
```

#### getDeeplink(options): Promise&lt;{ deeplink: Deeplink }&gt;

Returns launch deeplink parameters.

```typescript
interface Deeplink {
  addItemId?: string;
  addDiscountCode?: string;
  addOfferId?: string;
  addOrder?: string;
}
```

#### dismiss(options): Promise&lt;any&gt;

Closes the WebView and returns data to native.

#### finish(options): Promise&lt;any&gt;

Same as dismiss.

#### isInstalledApp(options: { key: string }): Promise&lt;{ install: boolean }&gt;

Checks if an app is installed.

#### isDebug(): Promise&lt;{ debug: boolean }&gt;

Returns whether debug mode is active.

#### openExternalUrl(options: { url: string }): Promise&lt;any&gt;

Opens a URL in the system browser.

#### setTextZoom(options: { value: number }): Promise&lt;any&gt;

Sets text zoom level (0–1).

#### readClipboard(): Promise&lt;{ value: string; type: 'text/plain' }&gt;

Reads clipboard content.

#### makeHKFPSPayment(options: FPSPaymentOptions): Promise&lt;FPSResultOptions&gt;

Initiates HK FPS payment.

```typescript
interface FPSPaymentOptions {
  paymentRequestUrl: string;
  callbackUrl?: string;
  typeIdentifier?: string;
  title?: string;
}

interface FPSResultOptions {
  result: boolean;
  url?: string;
  intent?: string;
}
```

#### setNativeBackPressEnabled(options: { enable: boolean }): Promise&lt;{ enabled: boolean }&gt;

Controls whether the system back press (swipe / back button) is handled by the native WebView container.

- **`enable: true`** (default): back press navigates the WebView back in history; if no history, dismisses the WebView.
- **`enable: false`**: back press is completely ignored while the WebView is open (swipe does nothing). `dismiss()` still works programmatically. After the WebView is dismissed, the host app's normal back behavior is automatically restored.

```typescript
const core = getHuaweiCore();

// Disable native back press — swipe / back button do nothing
await core.setNativeBackPressEnabled({ enable: false });

// Re-enable default behavior
await core.setNativeBackPressEnabled({ enable: true });
```

#### setNativeBackPressHandler(callback: () => void): void

Registers a callback invoked when a native back press occurs (swipe, back button, etc.).

- Only effective when `NativeBackPressEnabled = true`.
- When a back press is triggered, the callback fires instead of the default WebView-back-or-dismiss behavior.
- If `NativeBackPressEnabled = false`, a warning is logged to the console and the handler will not fire.

```typescript
const core = getHuaweiCore();

// Register a custom back press handler
core.setNativeBackPressHandler(() => {
  console.log('Back pressed — Web decides what to do');
  // e.g. navigate within SPA, show confirmation dialog, etc.
});
```

## Geolocation

A drop-in replacement for `@capacitor/geolocation` when running inside HarmonyOS WebView.

### Quick Start

```typescript
import { isHuaWei, getHuaweiGeolocation } from 'aigens-sdk-huawei';
import { Geolocation as CapGeolocation } from '@capacitor/geolocation';

// Auto-detect environment and pick the right Geolocation
const Geo = isHuaWei() ? getHuaweiGeolocation() : CapGeolocation;

// One-shot position
const position = await Geo.getCurrentPosition();
console.log(position.coords.latitude, position.coords.longitude);

// Watch position
const watchId = await Geo.watchPosition({ enableHighAccuracy: true }, (pos, err) => {
  if (err) { console.error(err); return; }
  console.log('Update:', pos.coords.latitude, pos.coords.longitude);
});

// Stop watching
await Geo.clearWatch({ id: watchId });
```

### getHuaweiGeolocation(): GeolocationPlugin

Returns a singleton `GeolocationHuawei` instance.

### GeolocationPlugin Methods

All methods route through JS Bridge to HarmonyOS native (`@kit.LocationKit`).

#### getCurrentPosition(options?): Promise&lt;Position&gt;

Gets the current GPS position.

#### watchPosition(options, callback): Promise&lt;CallbackID&gt;

Starts continuous position updates. Native pushes updates via `window.aigensGeolocationWatch(id, position)`.

#### clearWatch(options: { id }): Promise&lt;void&gt;

Stops a position watch.

#### checkPermissions(): Promise&lt;PermissionStatus&gt;

Checks location permission state. Returns `{ location, coarseLocation }` where each is `'granted'` / `'denied'` / `'prompt'`.

#### requestPermissions(): Promise&lt;PermissionStatus&gt;

Requests `ohos.permission.LOCATION` and `ohos.permission.APPROXIMATELY_LOCATION` from the user.

### Types

```typescript
interface Position {
  timestamp: number;
  coords: {
    latitude: number;
    longitude: number;
    accuracy: number;
    altitudeAccuracy: number | null | undefined;
    altitude: number | null;
    speed: number | null;
    heading: number | null;
  };
}

interface PositionOptions {
  enableHighAccuracy?: boolean;
  timeout?: number;       // ms
  maximumAge?: number;    // ms
}
```

## Device

A drop-in replacement for `@capacitor/device` when running inside HarmonyOS WebView.

### Quick Start

```typescript
import { isHuaWei, getHuaweiDevice } from 'aigens-sdk-huawei';
import { Device as CapDevice } from '@capacitor/device';

// Auto-detect environment and pick the right Device
const Device = isHuaWei() ? getHuaweiDevice() : CapDevice;

const info = await Device.getInfo();
console.log(info.model, info.osVersion);

const battery = await Device.getBatteryInfo();
console.log(battery.batteryLevel, battery.isCharging);

const { uuid } = await Device.getId();
const { value: lang } = await Device.getLanguageCode();
```

### getHuaweiDevice(): DevicePlugin

Returns a singleton `DeviceHuawei` instance.

### DevicePlugin Methods

All methods route through JS Bridge to HarmonyOS native (`deviceInfo`, `batteryInfo`, `i18n`, `statvfs`).

#### getId(): Promise&lt;DeviceId&gt;

Returns a unique device identifier with a 3-tier fallback chain: `deviceInfo.udid` (system apps only) → `identifier.getOAID()` (device-level, **stable across app reinstall**; requires `ohos.permission.ADVERTISING_INFO`, ACL-enabled) → random UUID persisted via `preferences` (changes on reinstall).

```typescript
interface DeviceId {
  uuid: string;
}
```

#### getInfo(): Promise&lt;DeviceInfo&gt;

Returns device/os/platform information from HarmonyOS `deviceInfo` and `statvfs`.

```typescript
interface DeviceInfo {
  name?: string;            // deviceInfo.marketName
  model: string;            // deviceInfo.deviceModel
  platform: 'ios' | 'android' | 'web' | 'harmony';
  operatingSystem: OperatingSystem;
  osVersion: string;        // deviceInfo.osReleaseVersion
  manufacturer: string;     // deviceInfo.manufactureBrand
  isVirtual: boolean;
  memUsed?: number;
  diskFree?: number;
  diskTotal?: number;
  realDiskFree?: number;
  realDiskTotal?: number;
  webViewVersion: string;
}

type OperatingSystem = 'ios' | 'android' | 'windows' | 'mac' | 'unknown';
```

#### getBatteryInfo(): Promise&lt;BatteryInfo&gt;

Returns battery level (0–1) and charging state from HarmonyOS `batteryInfo`.

```typescript
interface BatteryInfo {
  batteryLevel?: number;   // 0 to 1
  isCharging?: boolean;
}
```

#### getLanguageCode(): Promise&lt;GetLanguageCodeResult&gt;

Returns the system language locale code from HarmonyOS `i18n`.

```typescript
interface GetLanguageCodeResult {
  value: string;
}
```

## Preferences

A drop-in replacement for `@capacitor/preferences` when running inside HarmonyOS WebView.

Data is stored in HarmonyOS native `preferences` storage — persistent and not subject
to the periodic `localStorage` clears the OS may perform on WebViews. Data is cleared
when the app is uninstalled. No permissions required.

### Quick Start

```typescript
import { isHuaWei, getHuaweiPreferences } from 'aigens-sdk-huawei';
import { Preferences as CapPreferences } from '@capacitor/preferences';

// Auto-detect environment and pick the right Preferences
const Preferences = isHuaWei() ? getHuaweiPreferences() : CapPreferences;

await Preferences.set({ key: 'name', value: 'Max' });
const { value } = await Preferences.get({ key: 'name' }); // 'Max'
await Preferences.remove({ key: 'name' });
const { keys } = await Preferences.keys();
await Preferences.clear();
```

### getHuaweiPreferences(): PreferencesPlugin

Returns a singleton `PreferencesHuawei` instance.

### PreferencesPlugin Methods

All methods route through JS Bridge to HarmonyOS native `preferences` (ArkData).

| Method | Notes |
|--------|-------|
| `configure({ group })` | `group` maps to the native preferences store name. Default: `'CapacitorStorage'`. |
| `get({ key })` | Returns `{ value: string \| null }` — `null` when the key was never set or was removed. |
| `set({ key, value })` | String values only (use `JSON.stringify` for objects), then flushes to disk. **Setting an empty value removes the key** (cookie-like semantics — differs from `@capacitor/preferences`, which stores the empty string). |
| `remove({ key })` | Deletes the key. |
| `clear()` | Deletes all keys in the current group. |
| `keys()` | Returns `{ keys: string[] }`. |

## Share

A drop-in replacement for `@capacitor/share` when running inside HarmonyOS WebView.

Opens the HarmonyOS system share panel (Share Kit). The promise resolves once the
panel is presented; user completion is not awaited (same as Android). No permissions required.

### Quick Start

```typescript
import { isHuaWei, getHuaweiShare } from 'aigens-sdk-huawei';
import { Share as CapShare } from '@capacitor/share';

// Auto-detect environment and pick the right Share
const Share = isHuaWei() ? getHuaweiShare() : CapShare;

await Share.share({
  title: 'Check this out',
  text: 'Great coffee nearby',
  url: 'https://example.com',
});
```

### getHuaweiShare(): SharePlugin

Returns a singleton `ShareHuawei` instance.

### SharePlugin Methods

| Method | Notes |
|--------|-------|
| `canShare()` | Always resolves `{ value: true }` (system share panel is always available). |
| `share({ title?, text?, url? })` | Opens the system share panel. At least one of `text` / `url` is required. `dialogTitle` is ignored. `activityType` is always `''`. |

## Camera

A drop-in replacement for `@capacitor/camera` when running inside HarmonyOS WebView.

Uses the HarmonyOS system pickers, which require **no permissions**:
- `CAMERA` source — secure system camera (`cameraPicker`)
- `PHOTOS` source — system gallery (`PhotoViewPicker`)
- `PROMPT` source (default) — an ActionSheet lets the user choose; labels are
  customizable via `promptLabelHeader` / `promptLabelPhoto` / `promptLabelPicture`

User cancellation rejects with `Error('User cancelled')`, matching Capacitor.

### Quick Start

```typescript
import { isHuaWei, getHuaweiCamera } from 'aigens-sdk-huawei';
import { Camera as CapCamera, CameraResultType } from '@capacitor/camera';

// Auto-detect environment and pick the right Camera
const Camera = isHuaWei() ? getHuaweiCamera() : CapCamera;

// Take a photo / pick from gallery, get a data URL
const photo = await Camera.getPhoto({
  resultType: CameraResultType.DataUrl,
  quality: 80,
});
imgElement.src = photo.dataUrl;

// Get a file path instead
const { webPath } = await Camera.getPhoto({
  resultType: CameraResultType.Uri,
});
imgElement.src = webPath;

// Pick multiple images
const { photos } = await Camera.pickImages({ limit: 5 });
```

### getHuaweiCamera(): CameraPlugin

Returns a singleton `CameraHuawei` instance.

### CameraPlugin Methods

| Method | Notes |
|--------|-------|
| `getPhoto(options)` | `resultType` is required: `'uri'` returns `{ path, webPath }` (photo copied into the app cache dir; `webPath` is loadable by `<img>` inside the WebView), `'base64'` / `'dataUrl'` return a JPEG re-encoded with `quality` (default 100) and optional `width` / `height` (aspect ratio preserved). `source` defaults to `'PROMPT'`; `direction` applies to `'CAMERA'`. `allowEditing` / `promptLabelCancel` are accepted for `@capacitor/camera` drop-in compatibility but ignored (`saved` is always `false`). |
| `pickImages(options?)` | Multiple gallery pick; `limit` 0/undefined = system max (500). Returns `{ photos: [{ path, webPath, format }] }` — URIs only, no base64 (avoids large memory overhead). |
| `checkPermissions()` | Always `{ camera: 'granted', photos: 'granted' }` (system pickers need no permissions). |
| `requestPermissions()` | Same as `checkPermissions()` — a no-op. |
