Aller au contenu principal
DocumentationiOS
Version 0.2.0iOS 15.1 ou version ultérieure

Intégrer le SDK iOS DobroDesk

Ajoutez le Swift Package signé, créez le client natif et présentez le widget partagé depuis un view controller.

Sur cette page

Votre app iOS présente le widget natif DobroDesk avec un état durable lié au compte et les préférences système de mouvement.

Ajouter le Swift Package publié

Dans Xcode, ajoutez le dépôt https://github.com/comstud-io/dobrodesk-mobile-sdk.git à la release 0.2.0 et ajoutez DobroDeskSDK et DobroDeskUI à la cible de l'app. Le package binaire prend en charge iOS 15.1 et les versions ultérieures. Cette release contient seulement des artefacts. Le code source de l'implémentation native n'est pas inclus.

Swift Package
https://github.com/comstud-io/dobrodesk-mobile-sdk.git

Initialiser et présenter le client natif

L'app doit fournir un JWT d'identité client de courte durée via credentialProvider. L'authentification native exige un utilisateur signé : utilisez un backend de l'hôte et ne livrez jamais le signing secret ni un support API token dans l'app.

Avec la concurrence stricte de Swift 6, déclarez le loader de l'hôte comme une closure @Sendable () async throws -> String et transmettez cette closure à credentialProvider.

Présentation Swift
import Foundation
import UIKit
import DobroDeskSDK
import DobroDeskUI

let loadDobroDeskToken: @Sendable () async throws -> String = {
  // Replace this placeholder with a request to your host backend.
  "short-lived-token-from-host-backend"
}

let client = try DobroDeskClient(
  configuration: DobroDeskConfiguration(
    apiOrigin: URL(string: "https://dobrodesk.com")!,
    integrationId: "wgt_0123456789abcdef0123456789abcdef",
    accountScope: currentCustomer.id,
    locale: "en",
    credentialProvider: loadDobroDeskToken,
    pollInterval: 1
  )
)

try await DobroDeskWidgetBridgePresenter.shared.present(
  client: client,
  options: ["locale": "en"],
  from: viewController
)

Utiliser un déclencheur personnalisé ou une surface intégrée

Pour une surface intégrée, utilisez un UIView dédié avec des contraintes vers safeArea top, leading et trailing ainsi qu'un ancrage inférieur sur keyboardLayoutGuide. Définissez une hauteur initiale de 560 points avec priority .defaultHigh et montez la vue seulement après sa connexion à window. Créez un presenter propre à chaque montage afin qu'un close échoué ou obsolète ne ferme pas une autre surface.

Le bouton personnalisé doit rester accessible au clavier et exposer aria-controls ainsi que aria-expanded. Le wrapper de l'hôte doit intercepter les erreurs de embed avec do/catch et les transmettre à son propre callback onError typé pour l'interface de récupération. Lors d'un nouveau montage, réutilisez le même client, la même session et le même brouillon.

Les API inline font partie des artefacts publiés de Mobile SDK 0.2.0. Utilisez la surface inline lorsque l'hôte contrôle son placement et la présentation modale lorsque l'hôte doit gérer tout l'écran.

Intégration intégrée
import UIKit
import DobroDeskSDK
import DobroDeskUI

@MainActor
final class SupportPanelHost {
  private let client: DobroDeskClient
  private weak var parent: UIViewController?
  private let onError: (Error) -> Void
  private let supportContainer = UIView()
  private var presenter: DobroDeskWidgetBridgePresenter?
  private var mountTask: Task<Void, Never>?
  private var mountGeneration = 0
  private var isMounted = false

  init(
    client: DobroDeskClient,
    parent: UIViewController,
    onError: @escaping (Error) -> Void
  ) {
    self.client = client
    self.parent = parent
    self.onError = onError
    supportContainer.translatesAutoresizingMaskIntoConstraints = false
    parent.view.addSubview(supportContainer)
    let safeArea = parent.view.safeAreaLayoutGuide
    let keyboardGuide = parent.view.keyboardLayoutGuide
    let height = supportContainer.heightAnchor.constraint(equalToConstant: 560)
    height.priority = .defaultHigh
    NSLayoutConstraint.activate([
      supportContainer.topAnchor.constraint(equalTo: safeArea.topAnchor),
      supportContainer.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
      supportContainer.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor),
      supportContainer.bottomAnchor.constraint(equalTo: keyboardGuide.topAnchor),
      height,
    ])
  }

  func mountAfterAppearance() {
    guard mountTask == nil, !isMounted, let parent, supportContainer.window != nil else { return }
    mountGeneration += 1
    let generation = mountGeneration
    let mountPresenter = DobroDeskWidgetBridgePresenter()
    let client = self.client
    let supportContainer = self.supportContainer
    presenter = mountPresenter
    mountTask = Task { @MainActor [weak self] in
      defer {
        if let self, self.mountGeneration == generation {
          self.mountTask = nil
        }
      }
      do {
        try await mountPresenter.embed(
          client: client,
          options: ["locale": "en", "view": "home"],
          in: supportContainer,
          parent: parent
        )
        guard let self, self.mountGeneration == generation else {
          mountPresenter.close()
          return
        }
        isMounted = true
      } catch {
        guard let self, self.mountGeneration == generation else { return }
        mountPresenter.close()
        presenter = nil
        onError(error)
      }
    }
  }

  func setVisible(_ visible: Bool) {
    guard isMounted else { return }
    presenter?.setEmbeddedVisible(visible)
  }

  func close() {
    mountGeneration += 1
    mountTask?.cancel()
    mountTask = nil
    presenter?.close()
    presenter = nil
    isMounted = false
  }
}

Garder la présentation et le cycle du compte explicites

Présentez depuis un UIViewController au premier plan et appelez close lorsque l'écran hôte est détruit. Appelez client.resetSession() lorsque le client abandonne volontairement la conversation. Le client iOS direct ne possède pas logout : réinitialisez-le, détruisez-le et créez un nouveau client avant de changer accountScope.

Le presenter natif utilise le même contrat d'apparence que le widget web. Omettez reduceMotion sauf si le client a choisi un réglage explicite dans l'app. Le réglage système de réduction des mouvements reste prioritaire.

Gérer le chargement, la visibilité et l'accessibilité

Utilisez les hooks de chargement ou les événements typés pour l'état de l'écran hôte. La surface affiche elle-même le chargement des messages, l'attente et les nouvelles tentatives afin d'éviter un second indicateur sur le champ de saisie.

Masquez ou affichez la surface lors d'une navigation temporaire en conservant le client. Le widget respecte les préférences système de réduction des mouvements. Le retrait ou la fermeture ne supprime ni la session ni le brouillon.

  1. Lors du nouveau montage, réutilisez le même client et des dimensions stables pour le conteneur.
  2. Utilisez la fonction de visibilité pour un masquage temporaire, sans réinitialiser la session.
  3. Terminez la session uniquement lors de la déconnexion ou d'un changement de compte volontaire.

Vérifier le flux iOS

  1. Ouvrez le widget depuis un écran au premier plan et confirmez qu'un double appui sur le bouton ne crée pas de second contrôleur.
  2. Démarrez une conversation, fermez puis rouvrez le widget et confirmez que le brouillon et l'envoi en attente restent liés au même compte.
  3. Faites pivoter ou mettez l'app en arrière-plan pendant une opération en attente et attendez l'état explicite de reconnexion ou de nouvelle tentative avant de recommencer.
  4. Réinitialisez et détruisez le client iOS direct avant de changer de compte. Créez ensuite le client suivant et confirmez qu'il ne peut pas voir la conversation précédente.

Aperçu des SDK natifs

Visualisez le même parcours d'assistance avec les contrôles natifs d'iOS et d'Android.

Écran de conversation du SDK iOS natif DobroDesk avec un message client, un champ de saisie et une navigation inférieure
Aperçu iOS natif avec textes personnalisés en français, message client localisé, saisie native et barre d'onglets.