UNPKG

@freshworks/react-native-freshdesk-sdk

Version:
512 lines (363 loc) 22.7 kB
--- name: freshdesk-react-native-integration description: Integrate, debug, verify, and answer questions about the Freshdesk React Native SDK (@freshworks/react-native-freshdesk-sdk) in a host React Native app for Android and iOS. Use for greenfield integration, integration Q&A (knowledge base), diagnostics-driven debugging, FreshdeskSDK.initialize/openSupport/openKnowledgeBase, JWT, push notifications, ContentConfiguration, or any customer question about wiring the SDK. --- # Freshdesk React Native SDK Integration This skill teaches an AI agent how to integrate, debug, verify, and **answer integration questions** for the Freshdesk React Native SDK in a host app. **Three modes:** - **Mode A — Greenfield integration**: SDK not yet in the app. Follow the phased workflow below. - **Mode B — Diagnostics-driven debugging**: SDK already integrated. Use `FreshdeskSDK.runDiagnostics()` as source of truth and apply each check's `fixHint`. - **Mode C — Integration Q&A (knowledge base)**: Customer asks a question about integration (setup, APIs, push, JWT, errors, platform differences). **Read [integration-knowledge-base.md](integration-knowledge-base.md) first**, answer directly from it, and cite [platform-apis.md](platform-apis.md) when platforms differ. Escalate to Mode A (full wiring) or Mode B (diagnostics) only when the question requires it. > **Consumer apps only.** Do not edit `sdk_src` or files inside `node_modules/@freshworks/react-native-freshdesk-sdk`. Only change the target app's files. **References:** - [integration-faq.md](integration-faq.md) — prerequisites, app changes, post-integration checklist - [integration-knowledge-base.md](integration-knowledge-base.md) — Q&A for any integration question - [platform-apis.md](platform-apis.md) — Android vs iOS API and native differences - [examples.md](examples.md) — worked scenarios ## When to use Apply when integrating, auditing, debugging, or **answering questions about** `@freshworks/react-native-freshdesk-sdk` in a React Native app. Examples of Mode C questions: - "How do I open the knowledge base?" - "Do I need Firebase for chat?" - "What's the difference between Android and iOS push setup?" - "Why does openSupport show a spinner?" - "Where do I put my Freshdesk token?" Do NOT use for Freshdesk web/dashboard config unrelated to the mobile SDK, generic RN questions with no Freshdesk involvement, or SDK wrapper maintenance. ## Prerequisites - React Native **0.75.0+**. Backward-compatible with both the New Architecture (TurboModule) and the classic bridge — no consumer-facing choice to make; `runDiagnostics()` reports which one is active (`architecture: 'old'|'new'`). On **React Native 0.79+** (Kotlin 2.1.x toolchain) use wrapper **2.0.1+** — earlier builds fail to compile `FreshdeskModule.kt` against RN 0.79's nullable `ReadableMap.toHashMap()` (see [troubleshooting.md](troubleshooting.md), Issue 5). - iOS deployment target **15.0+**. The native SDK ships as a vendored, statically-linked `FreshdeskSDK.xcframework`**no `use_frameworks!`, Swift Package Manager, or `FRESHDESK_IOS_USE_VENDORED` env var required** (2.0.0+; older 1.4.x used an SPM path that needed those — see [troubleshooting.md](troubleshooting.md) if the target app is still on 1.4.x). - Android `minSdkVersion 26+`. The wrapper reads `compileSdkVersion`/`targetSdkVersion` from your app's own root `build.gradle` `ext` block if set; otherwise it falls back to **35**, which requires AGP **8.6+**. Apps that set `compileSdkVersion 36` (Android 16) in their own `ext` block should use AGP **8.9.1+** (9.x recommended). - CocoaPods **1.12+** (iOS). - Freshdesk portal access: **Admin Settings → Mobile Chat SDK**. --- ## Step 0 — Detect mode 1. Search `package.json` for `@freshworks/react-native-freshdesk-sdk`. 2. Search source for `FreshdeskSDK.initialize(` or imports from the package. 3. Classify the user's request: | Request type | Mode | |--------------|------| | Question about integration (how-to, what-if, error meaning, API usage) | **Mode C** → [integration-knowledge-base.md](integration-knowledge-base.md) | | "Integrate Freshdesk" / greenfield / SDK not in app | **Mode A** → Phase 1 | | Bug report / something broken / verify existing integration | **Mode B** → Step B1 | | Question + broken symptom | **Mode C** answer first, then **Mode B** if needed | If unsure between A and B, ask: "Is the Freshdesk React Native SDK already in your app, or is this a new integration?" --- ## Mode C — Integration Q&A (knowledge base) **When the customer asks any integration question**, act as a knowledgeable support agent: 1. **Search** [integration-knowledge-base.md](integration-knowledge-base.md) for the topic (credentials, init, push, JWT, APIs, errors, platform differences). 2. **Answer directly** — concise, accurate, with code snippets when they help. Do not start a full greenfield workflow unless they ask to integrate. 3. **Platform-specific?** Cross-check [platform-apis.md](platform-apis.md) and state Android vs iOS differences explicitly. 4. **Symptom / bug?** After answering, suggest `runDiagnostics()` and offer Mode B triage if they share the report. 5. **Full integration requested?** Hand off to Mode A. ### Mode C response format 1. Direct answer to the question (2–5 sentences or a short code block). 2. Related gotchas (platform differences, common mistakes) — only if relevant. 3. Optional: "If you want me to wire this into your app, say so and I'll integrate it." Never invent credentials. Never paste secrets in chat. --- ## Mode A — Greenfield integration (phased workflow) ### Phase 1 — Interactive setup (host & language) **Ask the user directly** (do not invent values): 1. **Host** — Freshdesk instance URL from Admin → Mobile Chat SDK. Accepts **either** `yourcompany.freshdesk.com` **or** `https://yourcompany.freshdesk.com` — the SDK auto-prefixes `https://` when omitted. 2. **Language / locale** — BCP-47 code for widget UI (default `en` if unspecified). Record answers for use in `.env`, `initialize({ locale })`, and native credential files. Also confirm in one batch: | Question | Why | |----------|-----| | Target platforms (Android, iOS, both)? | Scopes native work | | Android `applicationId` / iOS bundle id? | Push portal setup | | Is JWT enforced on the widget? | JWT wiring vs `setUserProperties` | | Push notifications needed? | Native init mandatory | ### Phase 2 — Secrets via file paths (never paste in chat) **Do not ask the user to paste token, SDK ID, or JWT in the chat.** Discover paths in the host app, then tell the user exactly which files to edit: #### 2a — Create or update `.env` (app root, gitignored) ```bash FRESHDESK_HOST=<value from Phase 1> FRESHDESK_LOCALE=<value from Phase 1> FRESHDESK_TOKEN= # ← user fills from portal App Keys FRESHDESK_SDK_ID= # ← user fills from portal FRESHDESK_JWT= # ← user fills if JWT enforced; leave empty otherwise ``` If the app uses `react-native-dotenv` / `@env`, ensure `babel.config.js` includes the plugin and `src/types/env.d.ts` declares the keys. #### 2b — Android native credentials (required when push is enabled) Point to `android/app/build.gradle``defaultConfig`: ```gradle buildConfigField "String", "FRESHDESK_TOKEN", "\"...\"" buildConfigField "String", "FRESHDESK_HOST", "\"...\"" buildConfigField "String", "FRESHDESK_SDK_ID", "\"...\"" buildConfigField "String", "FRESHDESK_JWT", "\"...\"" buildConfigField "String", "FRESHDESK_LOCALE", "\"en\"" ``` Prefer reading from `.env` via a helper (see SDK sample app `freshdeskEnvValue()`). #### 2c — iOS native credentials (required when push is enabled) Point to `ios/<AppName>/Info.plist`: ```xml <key>FreshdeskHost</key><string>...</string> <key>FreshdeskLocale</key><string>en</string> <key>FreshdeskToken</key><string>...</string> <key>FreshdeskSdkId</key><string>...</string> <key>FreshdeskJwt</key><string>...</string> <!-- if JWT enforced --> ``` **Stop and wait** until the user confirms credentials are filled. Do not proceed with init testing while placeholders remain. ### Phase 3 — Install package ```bash npm install @freshworks/react-native-freshdesk-sdk ``` Autolinking handles native linking (RN 0.60+). ### Phase 4 — Integration inventory (existing code vs agent creates) For **each area below**, ask: **"Do you already have code for this in your app?"** - **Yes** → show the exposed API(s), inspect their file(s), wire SDK calls into their existing code. - **No** → agent implements the integration from scratch (minimal, idiomatic to their app structure). Process areas in this order: #### 4.1 SDK initialization **API:** ```typescript await FreshdeskSDK.initialize({ token, host, sdkId, locale: FRESHDESK_LOCALE || 'en', jwt: FRESHDESK_JWT, // JWT-enforced only debugMode: __DEV__, // Android Logcat only }); ``` **If no existing code:** create a `FreshdeskProvider` (or init in root `App.tsx` / `useEffect`) that: - Reads credentials from `@env` or config module. - Calls `initialize()` once on mount. - Sets `isInitialized` state; guards all SDK calls until true. - On failure: log error, do not silently continue. **If existing code:** merge init params (host, locale from Phase 1); ensure single init, awaited before other calls. #### 4.2 Support entry points **APIs:** | Method | Purpose | |--------|---------| | `openSupport()` | Support home / chat | | `openKnowledgeBase()` | FAQ / KB directly | | `openTopic({ topicName, topicId? })` | Specific topic | **If no existing code:** add a support button (settings, profile, or tab) calling `openSupport()` with try/catch and init guard. **If existing code:** connect their button/navigation handler to the appropriate API. #### 4.3 User identity **JWT enforced** (from Phase 1): | API | When | |-----|------| | `initialize({ jwt })` | At startup | | `authenticateAndUpdate(jwt)` | After token refresh | | `addUserStateListener(cb)` | Handle `authExpired`, `notAuthenticated` | | `resetUser()` | On logout | Do **not** call `setUserProperties` for identity when JWT is enforced. **Non-JWT:** | API | When | |-----|------| | `setUserProperties({ name, email, phone, ... })` | After login | | `resetUser()` | On logout | **If no existing code:** add listener in provider; hook login/logout flows if auth exists in app. #### 4.4 Push notifications (native — per platform) **No JS push API.** Ask if they have existing FCM/APNs wiring. **If yes:** integrate Freshdesk into their existing `FirebaseMessagingService` (Android) and `AppDelegate` push handlers (iOS). See [platform-apis.md](platform-apis.md). **If no:** create native wiring mirroring SDK sample app: | Platform | Files to create/modify | |----------|------------------------| | Android | `FreshdeskMessagingService.kt` (headless init), `AndroidManifest.xml`, `google-services.json`, `build.gradle` | | iOS | `AppDelegate.mm`/`.swift`, `FreshdeskPush.swift` (if needed), `Info.plist`, Xcode Push + Background Modes | > **Critical (Android):** Do **not** call native `FreshdeskSDK.initialize()` in `MainApplication.onCreate()` — it conflicts with JS init and breaks `openSupport()`. Use JS init for in-app support; native init **only** inside `FirebaseMessagingService` for headless push. Android headless init (inside `FreshdeskMessagingService`, via `FreshdeskInitializer` pattern — not `MainApplication`): ```kotlin FreshdeskInitializer.ensureInitializedBlocking(applicationContext) FreshdeskSDK.handleFCMNotification(data) ``` iOS native init (in `AppDelegate` early, before RN bridge): ```objc [FreshdeskNativeModuleBridge initializeSDKWithToken:... host:... sdkId:... locale:... jwt:...]; ``` Forward tokens and handle all three iOS notification delivery paths. #### 4.5 Content configuration & localization **API:** ```typescript await FreshdeskSDK.setContentConfiguration({ headers: { chat: '...', faq: '...' }, placeholders: { replyField: '...', searchField: '...' }, actions: { tabChat: '...' }, privacyPolicySetting: { ... }, }); ``` Pass `{}` to reset to widget defaults. **If no existing code:** call after successful init with strings matching Phase 1 locale if custom copy is needed. #### 4.6 Event listeners | API | Platform | Purpose | |-----|----------|---------| | `addUnreadCountListener(cb)` | Both | Badge / tab count | | `addUserStateListener(cb)` | Both | JWT auth state | | `addUserCreatedListener(cb)` | **iOS only** | New anonymous user | | `setLinkHandler(cb)` | Both | Custom in-widget URLs | **If no existing code:** register in provider; `.remove()` on unmount; call `removeAllListeners()` in cleanup. #### 4.7 Analytics (optional) **API:** `trackEvent(name, properties?)` Wire only if user requests or already has analytics hooks. ### Phase 5 — Platform native baseline Apply even when push is disabled: **Android (all apps):** - `mavenCentral()` in repositories. - `minSdkVersion 26`. Set `compileSdkVersion`/`targetSdkVersion` explicitly in the app's own `ext` block — the wrapper falls back to **35** (AGP 8.6+) if unset, so apps targeting **36** (Android 16) should set it explicitly and use AGP **8.9.1+**. - JDK 17–21 for Gradle. - Apply `android/freshdesk-consumer.gradle` from the npm package (Kotlin metadata fix — see [troubleshooting.md](troubleshooting.md)). - Set `kotlinOptions { freeCompilerArgs += ["-Xskip-metadata-version-check"] }` on the app module. - RN 0.79+ (Kotlin 2.1.x): keep the wrapper at **2.0.1+**. Older wrapper builds do not compile against RN 0.79's nullable `ReadableMap.toHashMap()` ([troubleshooting.md](troubleshooting.md), Issue 5). **iOS (all apps, 2.0.0+):** Nothing Freshdesk-specific to add beyond the deployment target — the native SDK is a vendored static xcframework, so it does not force `use_frameworks!` and needs no `post_install` hook of its own: ```ruby platform :ios, '15.0' ``` ```bash cd ios && pod install ``` Keep `use_frameworks!` only if some *other* dependency in the app needs it — prefer `:linkage => :static` if so. If the target app's `package.json` still pins `@freshworks/react-native-freshdesk-sdk@~1.4.x`, it needs the older SPM path instead — see [troubleshooting.md](troubleshooting.md). ### Phase 6 — Verify initialization & debug failures **Mandatory before declaring success:** 1. Build and run each targeted platform. 2. Confirm init completes (no `FRESHDESK_INVALID_CONFIG` / `FRESHDESK_INIT_ERROR` in logs). 3. Open support entry point once. 4. Run diagnostics: ```typescript await FreshdeskSDK.enableDebugLogs(true); const report = await FreshdeskSDK.runDiagnostics(); console.log(report.prettyPrinted); ``` 5. Triage any non-`pass` check — apply `fixHint` verbatim (hand off to Mode B). 6. Confirm `runtime.sdkInitialized: pass`. 7. **Output the Integration Summary** and link [integration-faq.md](integration-faq.md) (see Output format). **Android extra signal:** `debugMode: true` in `initialize()` + Logcat tag `Freshdesk`. **iOS extra signal:** full native report with masked secrets — safe to share. **iOS `initialize()` normally takes ≥2 seconds — this is expected, not a bug.** The native SDK has no readiness signal of its own, so the wrapper holds `initialize()`'s promise until a fixed settle delay has passed (see [platform-apis.md](platform-apis.md)). Do not "fix" a 2+ second `initialize()` call on iOS; do flag it as a real bug if `openSupport()`/`trackEvent()`/ `setUserProperties()` fail or no-op **after** `initialize()` has resolved — that combination means either an SDK version without this fix (check `CHANGELOG.md` for the "iOS `initialize()` settle delay" entry), or a genuine credentials/network problem worth diagnostics. Do not declare integration complete until diagnostics and the user's symptom both confirm success. --- ## Mode B — Diagnostics-driven debugging ### Step B1 — Run diagnostics first ```typescript await FreshdeskSDK.enableDebugLogs(true); const report = await FreshdeskSDK.runDiagnostics(); console.log(report.prettyPrinted); ``` Do not change code without a diagnostic signal. Each check: `id`, `status` (`pass|warn|fail|skipped`), `details`, `fixHint`. ### Step B2 — Triage (priority order) 1. `fail` — fix first. 2. `warn` — likely symptom cause. 3. `skipped` — informational (Android `runtime.diagnostics` until native parity). | Check / symptom | Action | |-----------------|--------| | `config.token` empty | User must fill `.env` / native files (Phase 2) | | `network.configEndpoint` 401/403/404 | Wrong token, host, or sdkId | | `config.hostScheme` warn (Android) | Bare domain — auto-normalized on 1.2.2+; prefer `https://` in `.env` | | `runtime.doubleInit` warn (Android) | Remove `MainApplication.onCreate()` native init; use JS init | | `runtime.sdkInitialized` fail | Ensure `initialize()` awaited before other calls | | `runtime.nativeModule` fail | `pod install`, Gradle clean, rebuild native app | | `push.sdkToken` not set (iOS) | Native init + APNs forwarding | | `push.messagingService` warn (Android) | Register FCM messaging service | | Init throws `FRESHDESK_INVALID_CONFIG` | Empty token/host/sdkId in env wiring | | iOS: `openSupport()`/`trackEvent()`/`setUserProperties()` silently no-op or fail right after `initialize()` resolves | Confirm the SDK version includes the `initialize()` settle-delay fix (see `CHANGELOG.md` / [platform-apis.md](platform-apis.md)). On a version without it, add a short delay after `initialize()` resolves before the first other call, or upgrade. | Always cite exact `fixHint` from the report. ### Step B3 — JWT troubleshooting If `jwt.*` fails or `UserState` not `authenticated`/`identifierUpdated`: 1. Check `remoteConfig.jwtEnforced` in iOS report. 2. Pass `jwt` at init; refresh with `authenticateAndUpdate(jwt)`. 3. `addUserStateListener` for `authExpired`. 4. Verify server signing key matches widget encryption key. Reference: https://support.freshdesk.com/en/support/solutions/articles/50000011580-enable-jwt-authentication ### Step B4 — Validate fix Re-run diagnostics after each change. Confirm previously failing checks are `pass` and symptom resolved. --- ## Output format ### Mode C must include 1. Direct answer sourced from [integration-knowledge-base.md](integration-knowledge-base.md) or [integration-faq.md](integration-faq.md). 2. Platform callouts when Android and iOS differ. 3. Code snippet only when it clarifies the answer. 4. Diagnostics suggestion if the question implies a failure. 5. For "what do I need before integrating?" questions → point to [integration-faq.md](integration-faq.md) **Before you integrate** section. ### Mode A must include 1. Mode confirmation (greenfield). 2. Host + locale collected; credential file paths listed with placeholders for token/sdkId/jwt. 3. Integration inventory results (existing vs created per area). 4. **Integration Summary** — mandatory section at the end (see template below). 5. Link to **[integration-faq.md](integration-faq.md)** for post-integration checklist and common questions. 6. Diagnostics hand-off: build, run, open support, share report. #### Integration Summary template (required output) After all code changes, output this section so the customer knows exactly what changed: ```markdown ## Freshdesk integration summary ### Credentials — you update manually - List each file path (`.env`, `build.gradle`, `Info.plist`) and which keys need portal values ### Files changed | Area | File | What changed | |------|------|--------------| | npm | package.json | Added @freshworks/react-native-freshdesk-sdk | | JS | ... | Init provider, support button, listeners | | Android | ... | (list each file or "none") | | iOS | ... | (list each file or "none") | | Push | ... | (if applicable) | | JWT | ... | (if applicable) | ### APIs wired - List each FreshdeskSDK method integrated (initialize, openSupport, listeners, push, JWT, etc.) ### Manual steps for you 1. Fill credentials in listed files 2. pod install / rebuild commands 3. Test: open support, run diagnostics ### Docs & FAQ - [Integration FAQ](ai/skills/freshdesk-react-native-integration/integration-faq.md) — prerequisites, what changed, post-integration checklist - [Knowledge base](ai/skills/freshdesk-react-native-integration/integration-knowledge-base.md) — answer any follow-up questions - [Platform APIs](ai/skills/freshdesk-react-native-integration/platform-apis.md) — Android vs iOS differences ``` Populate every row with **actual files touched** in the host app — do not leave generic placeholders. ### Mode B must include 1. `overallStatus` + first non-pass check (`id`, `details`, `fixHint`). 2. Minimal fix per check using `fixHint` verbatim. 3. Re-run diagnostics verification step. 4. If files were modified: brief **Integration Summary** (files changed + what was fixed) and link [integration-faq.md](integration-faq.md). Never invent token, host, sdkId, or JWT. Never ask users to paste secrets in chat. --- ## Reference links - [integration-faq.md](integration-faq.md) — prerequisites, what changes in your app, post-integration checklist - [integration-knowledge-base.md](integration-knowledge-base.md) — Q&A knowledge base for any integration question - [platform-apis.md](platform-apis.md) — Android vs iOS differences - [troubleshooting.md](troubleshooting.md) — Kotlin metadata mismatch, iOS FreshdeskSDK embed, common build/launch fixes - [examples.md](examples.md) — worked scenarios - `PLATFORM_DIFFERENCES.md` (ships in the npm package root) — every method whose runtime behavior, not just error surface, differs by platform: `resetUser()`, `enableDebugLogs()`, `getUnreadCount()`, `trackEvent()`, and the iOS `initialize()` settle delay. - Installation: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/installation.md - Initialization: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/initialization.md - API reference: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/api_reference.md - Troubleshooting: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/troubleshooting.md ## Do not - Do not edit `sdk_src` or `node_modules/@freshworks/react-native-freshdesk-sdk` in consumer apps. - Do not commit `.env`, `google-services.json`, APNs keys, or real credentials. - Do not use JS-only init for push. - Do not set iOS deployment target below `15.0` or Android `minSdkVersion` below `26`. - Do not invent credentials or paste secrets into chat.