@freshworks/react-native-freshdesk-sdk
Version:
React Native wrapper for Freshdesk Android and iOS SDKs
104 lines (85 loc) • 5.62 kB
Markdown
# Platform behavior differences
`FreshdeskSDK`'s public API is the same on both platforms, but a few methods have
different **runtime behavior** because the underlying native Android and iOS SDKs
don't expose the same capability. These are not bugs in this wrapper — the
divergence is inherent to what each native SDK can report — but they're
documented here because the JS types can't express them.
## `resetUser()`
- **Android:** the native SDK has both `onSuccess` and `onFailure` callbacks, so
a genuine failure (e.g. a network error during reset) resolves
`{ success: false, error }`.
- **iOS:** the native SDK's `resetUser()` call is synchronous and has **no
failure callback at all**. This wrapper cannot detect a reset failure on iOS —
it always resolves `{ success: true }` once the SDK is initialized. The
promise only **rejects** for the programmer-error case (`resetUser()` called
before `initialize()` resolved).
**Do not rely on `resetUser()` resolving `{ success: false }` as a cross-platform
signal.** Treat a resolved promise as "reset was requested"; a rejected promise
as a usage error. If you need confirmed reset-failure detection on iOS, that
requires a completion handler on the native `Freshdesk.resetUser()` API, which
is a native-SDK feature request, not something this wrapper can add.
## `initialize(config)` settle delay (iOS)
- **iOS:** the native SDK's `Freshdesk.initialize(with:)` has no completion
callback, `async` variant, notification, or published readiness property —
confirmed by inspecting both the public and private `.swiftinterface` files
in the vendored `FreshdeskSDK.xcframework`. It does its own async internal
loading after `initialize()` returns, and calls made before that finishes
are silently queued/dropped by the native SDK itself (logged as "Tasks will
be executed once the SDK is loaded"). This wrapper cannot detect real
readiness, so `initialize()`'s promise resolves only after a fixed
**2-second settle delay** past the native call returning, not the instant it
returns. This is a heuristic, not a guarantee — there is no telemetry on the
native SDK's real load time behind that number.
- **Android:** `initialize()` waits on the native SDK's real init callback (or
a readiness re-check / hard timeout as a fallback — see
`FreshdeskInitCoordinator`), so it resolves only once the SDK has actually
confirmed readiness, with no fixed heuristic delay involved.
**Practical effect:** `initialize()` on iOS always takes at least ~2 seconds,
even on a fast/local network, where Android can resolve sooner if the native
callback fires quickly. If you called `openSupport()` / `trackEvent()` /
`setUserProperties()` / `setTicketProperties()` immediately after
`initialize()` resolved and saw them silently fail intermittently (or nearly
always) on iOS before this delay was added, that was this exact race —
not a bug in your integration code.
## `trackEvent(name, properties)`
- **Android:** property values reach the native SDK with their original type
(`string | number | boolean`) — the wrapper passes the properties object
straight through as a typed map.
- **iOS:** every property value is coerced to a string (`String(describing:)`)
before being handed to the native SDK, because `Freshdesk.trackUserEvents`
takes a `[String: String]` payload. `trackEvent('purchase', { amount: 42 })`
reaches Android's analytics backend with a numeric `amount`, but iOS's with
the string `"42"`.
**If your analytics backend distinguishes types (e.g. numeric aggregation on
`amount`), be aware iOS always reports strings.** This is a native-SDK
constraint (`Freshdesk.trackUserEvents`'s payload type), not something this
wrapper can normalize without silently lying about the Android value's type.
## `enableDebugLogs(enabled)`
- **iOS:** toggles debug logging at runtime.
- **Android:** the native SDK only accepts a debug-logging flag at
`SDKConfig` construction time (`initialize()`). Calling
`enableDebugLogs(true)` **after** `initialize()` is a no-op on Android unless
you already passed `debugMode: true` to `initialize()` — it does not
retroactively enable logging, and does not re-initialize the SDK to do so.
Calling `enableDebugLogs(true)` before `initialize()` resolves rejects with
`FreshdeskErrorCode.NOT_INITIALIZED`.
**To get Android debug logs, pass `debugMode: true` to `initialize()`.**
`enableDebugLogs()` is reliable only on iOS; treat it as an iOS-only runtime
toggle and use `initialize({ debugMode })` for Android.
## `getUnreadCount()`
- **Android:** the native SDK does not expose a synchronous "current count"
getter — it only pushes count changes via a broadcast. This wrapper caches
the last broadcast value and returns it, so it resolves `0` until the first
broadcast arrives after `initialize()` (there is no reliable way to fetch the
count eagerly).
- **iOS:** the native SDK exposes the count directly, so this call resolves the
live value.
For a value you can trust immediately after `initialize()` on both platforms,
prefer `addUnreadCountListener()` over polling `getUnreadCount()`.
## Error codes
Not every `FreshdeskErrorCode` is rejected on both platforms — Android has
several method-specific codes (`TRACK_ERROR`, `TICKET_PROPERTIES_ERROR`,
`AUTH_ERROR`, `DISMISS_ERROR`, `OPEN_ERROR`, `NO_ACTIVITY`, `INIT_TIMEOUT`,
`INIT_ERROR`, `NOT_READY`) that iOS does not emit, and iOS has two of its own
(`NO_VIEW_CONTROLLER`, `USER_PARSE_ERROR`). See the JSDoc on each
`FreshdeskErrorCode` member for which platform(s) it can occur on.