UNPKG

@freshworks/react-native-freshdesk-sdk

Version:
118 lines (95 loc) 8.39 kB
# Platform API Differences — Freshdesk React Native SDK Use this reference when wiring integrations. The JavaScript API is shared; native setup and a few JS methods differ by platform. ## JavaScript APIs — platform matrix | API | Android | iOS | Notes | |-----|---------|-----|-------| | `initialize(config)` | Yes | Yes | Required once before any other call. **iOS resolves only after a ~2s settle delay** — expected, not a bug; see below. | | `openSupport()` | Yes | Yes | On iOS, only call after `initialize()` has actually resolved — see settle-delay note below | | `openKnowledgeBase()` | Yes | Yes | | | `openTopic({ topicName, topicId? })` | Yes | Yes | | | `getUnreadCount()` | Yes | Yes | Android: cached broadcast value, resolves `0` until the first broadcast after init. iOS: live value. | | `dismiss()` | Yes | Yes | | | `resetUser()` | Yes | Yes | Call on logout. **iOS has no failure callback** — always resolves `{success:true}` once initialized; only rejects if called before init. Do not treat a resolved promise as proof of a successful reset on iOS. | | `setUserProperties(props)` | Yes | Yes | **Do not use when JWT is enforced.** On iOS, only call after `initialize()` has actually resolved. | | `setTicketProperties(props)` | Yes | Yes | | | `authenticateAndUpdate(jwt)` | Yes | Yes | Refresh JWT after init | | `trackEvent(name, props?)` | Yes | Yes | **Android passes property values through typed** (`string \| number \| boolean`); **iOS coerces every value to a string** before handing it to the native SDK. A numeric property reaches Android's backend as a number, iOS's as a string. On iOS, only call after `initialize()` has actually resolved. | | `getSDKVersion()` | Yes | Yes | | | `getUser()` | Yes | Yes | | | `setContentConfiguration(config)` | Yes | Yes | Persists immediately | | `addUnreadCountListener(cb)` | Yes | Yes | Returns subscription with `.remove()` | | `addUserStateListener(cb)` | Yes | Yes | JWT auth states | | `addUserCreatedListener(cb)` | **No** | **Yes** | iOS only — new anonymous user created | | `setLinkHandler(cb)` | Yes | Yes | Custom URL handling inside widget | | `removeAllListeners()` | Yes | Yes | Cleanup on unmount | | `enableDebugLogs(enabled)` | Yes | Yes | iOS toggles native logs immediately at any time. **Android only takes effect if `debugMode: true` was passed to `initialize()`** — calling `enableDebugLogs(true)` afterward is a no-op on Android, it does not retroactively enable logging or re-init. | | `runDiagnostics()` | Partial | Full | See Diagnostics section | | `debugMode` in `initialize()` | **Yes** | No-op | Android: the *only* reliable way to get Logcat output — set it here, not via `enableDebugLogs()` after the fact. iOS: ignored by `initialize()`; use `enableDebugLogs()` instead, works anytime. | | `FreshdeskErrorCode` | Partial | Partial | Exported enum of all reject codes. Not every code is emitted on both platforms — Android has several method-specific codes iOS doesn't, iOS has `NO_VIEW_CONTROLLER`/`USER_PARSE_ERROR` Android doesn't. Check each member's JSDoc for which platform(s) can throw it. | ### iOS `initialize()` settle delay The native iOS SDK's `Freshdesk.initialize(with:)` has **no completion callback, `async` variant, or readiness signal of any kind** — confirmed by inspecting the vendored xcframework's own `.swiftinterface`. It does its own async internal loading after `initialize()` returns; calling `openSupport()`/ `trackEvent()`/`setUserProperties()`/etc. before that finishes gets silently queued and can be dropped by the native SDK (logged as `"Tasks will be executed once the SDK is loaded"`). The wrapper holds `initialize()`'s promise for a fixed ~2 second settle delay past the native call returning before resolving, so **normal `await initialize()` usage is safe** — the only thing to know is that the `await` itself now always takes ≥2s on iOS. Do not "optimize" this away, and do not diagnose a 2+ second `initialize()` call on iOS as a bug on its own. ## Push notifications — no JavaScript API Push is **native only**. FCM/APNs tokens can arrive before JavaScript loads. | Concern | Android | iOS | |---------|---------|-----| | In-app init | **JS** `FreshdeskSDK.initialize()` | **JS** or native in AppDelegate for push | | Headless/killed push init | **`FirebaseMessagingService` only** — not `MainApplication.onCreate` | `AppDelegate` `didFinishLaunchingWithOptions` (sync) | | Token forwarding | `setPushRegistrationToken(token)` in FCM service | APNs token in `didRegisterForRemoteNotificationsWithDeviceToken` | | Message handling | `isFreshdeskSDKNotification()` + `handleFCMNotification()` | Three paths: foreground, tap, background/killed | | Credentials source | `BuildConfig.FRESHDESK_*` from `build.gradle` | `Info.plist` keys `FreshdeskToken`, `FreshdeskHost`, `FreshdeskSdkId`, `FreshdeskLocale`, `FreshdeskJwt` | | Firebase / APNs | `google-services.json`, Google Services plugin, portal FCM upload | `.p8` Auth Key, Push + Background Modes capabilities, real device required | | Diagnostics checks | `push.messagingService` (wrapper) | `push.permission`, `push.sdkToken`, `push.deviceRegistered`, etc. | ## Diagnostics — platform behavior | Check area | iOS | Android | |------------|-----|---------| | Config (`config.token`, `config.host`, `config.sdkId`) | Native, secrets masked | Wrapper-level | | Network (`network.configEndpoint`) | Native | Skipped until native parity | | JWT (`jwt.*`, `remoteConfig.jwtEnforced`) | Native | Skipped | | Push (`push.*`) | Native | `push.messagingService` wrapper check | | Runtime (`runtime.sdkInitialized`, `runtime.nativeModule`) | Native + wrapper | Wrapper | | `runtime.diagnostics` | pass | **skipped** — use `debugMode: true` + Logcat | Always run after init: ```typescript await FreshdeskSDK.enableDebugLogs(true); const report = await FreshdeskSDK.runDiagnostics(); console.log(report.prettyPrinted); ``` Apply each non-pass check's `fixHint` verbatim. ## Credential file paths (discover in host app) Agent must locate these paths in the target app — names vary by project: | Value | JS / shared | Android (push) | iOS (push) | |-------|-------------|----------------|------------| | Token | `.env``FRESHDESK_TOKEN` | `android/app/build.gradle``buildConfigField "FRESHDESK_TOKEN"` | `ios/<App>/Info.plist``FreshdeskToken` | | Host | `.env``FRESHDESK_HOST` | `buildConfigField "FRESHDESK_HOST"` | `FreshdeskHost` | | SDK ID | `.env``FRESHDESK_SDK_ID` | `buildConfigField "FRESHDESK_SDK_ID"` | `FreshdeskSdkId` | | Locale | `.env``FRESHDESK_LOCALE` | `buildConfigField "FRESHDESK_LOCALE"` | `FreshdeskLocale` | | JWT | `.env``FRESHDESK_JWT` | `buildConfigField "FRESHDESK_JWT"` | `FreshdeskJwt` | Host accepts bare domain or full URL; SDK normalizes to `https://` automatically (1.2.2+). ## Initialization verification After wiring, confirm: 1. `FreshdeskSDK.initialize()` runs once, early (root provider / `App.tsx`). 2. `runtime.sdkInitialized` is `pass` in diagnostics. 3. If push enabled: native init runs on both platforms before JS (mirror sample app). 4. Opening support once before declaring success. 5. Re-run diagnostics; all targeted checks `pass` or acceptable `warn`. Common init failures: | Symptom | Likely cause | Fix | |---------|--------------|-----| | `FRESHDESK_INVALID_CONFIG` | Empty token/host/sdkId in `.env` or babel `@env` not wired | Fill `.env`, restart Metro | | `FRESHDESK_NOT_INITIALIZED` | Method called before init completes | Await init in provider; guard UI | | `runtime.nativeModule: fail` | Pods/Gradle not linked | `pod install`, clean rebuild | | `network.configEndpoint: fail` | Wrong host format or revoked token | Host is auto-normalized (https:// prefixed) on wrapper 1.2.2+ | | Push token not set | JS-only init | Add native init in FCM service only — not MainApplication | | `runtime.doubleInit: warn` | Native init in MainApplication + JS init | Remove MainApplication.onCreate init; JS for in-app, FCM service for headless push | | iOS: `openSupport()`/`trackEvent()`/etc. silently no-op right after `initialize()` resolves | Method called before the SDK's *own* async internal loading finished — see the settle-delay note above | Confirm the SDK version has the settle-delay fix (`CHANGELOG.md`); it makes `await initialize()` safe on its own |