diff --git a/android/build.gradle b/android/build.gradle index c53414f3..1c1ecbf9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -28,6 +28,10 @@ buildscript { apply plugin: 'com.android.library' +def isNewArchitectureEnabled() { + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} + def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } @@ -43,6 +47,17 @@ android { versionCode 1 versionName "1.0" buildConfigField 'String', 'INTERCOM_VERSION_NAME', packageVersion + buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()) + } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ['src/newarch'] + } else { + java.srcDirs += ['src/oldarch'] + } + } } buildTypes { diff --git a/android/src/main/java/com/intercom/reactnative/IntercomModule.java b/android/src/main/java/com/intercom/reactnative/IntercomModule.java deleted file mode 100644 index a18736b5..00000000 --- a/android/src/main/java/com/intercom/reactnative/IntercomModule.java +++ /dev/null @@ -1,535 +0,0 @@ -package com.intercom.reactnative; - -import android.app.Activity; -import android.app.Application; -import android.util.Log; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.module.annotations.ReactModule; -import com.google.firebase.messaging.RemoteMessage; - -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Map; - -import io.intercom.android.sdk.Intercom; -import io.intercom.android.sdk.IntercomContent; -import io.intercom.android.sdk.IntercomError; -import io.intercom.android.sdk.IntercomSpace; -import io.intercom.android.sdk.IntercomStatusCallback; -import io.intercom.android.sdk.UserAttributes; -import io.intercom.android.sdk.api.ReactNativeHeaderInterceptor; -import io.intercom.android.sdk.helpcenter.api.CollectionContentRequestCallback; -import io.intercom.android.sdk.helpcenter.api.CollectionRequestCallback; -import io.intercom.android.sdk.helpcenter.api.HelpCenterArticleSearchResult; -import io.intercom.android.sdk.helpcenter.api.SearchRequestCallback; -import io.intercom.android.sdk.helpcenter.collections.HelpCenterCollection; -import io.intercom.android.sdk.helpcenter.sections.HelpCenterCollectionContent; -import io.intercom.android.sdk.identity.Registration; -import io.intercom.android.sdk.push.IntercomPushClient; - -@ReactModule(name = IntercomModule.NAME) -public class IntercomModule extends ReactContextBaseJavaModule { - public static final String NAME = "IntercomModule"; - - private static final IntercomPushClient intercomPushClient = new IntercomPushClient(); - - public IntercomModule(ReactApplicationContext reactContext) { - super(reactContext); - } - - @Override - @NonNull - public String getName() { - return NAME; - } - - public static boolean isIntercomPush(RemoteMessage remoteMessage) { - try { - Map message = remoteMessage.getData(); - return intercomPushClient.isIntercomPush(message); - } catch (Exception err) { - Log.e(NAME, "isIntercomPush error:"); - Log.e(NAME, err.toString()); - return false; - } - } - - public static void handleRemotePushMessage(@NonNull Application application, RemoteMessage - remoteMessage) { - try { - Map message = remoteMessage.getData(); - intercomPushClient.handlePush(application, message); - } catch (Exception err) { - Log.e(NAME, "handleRemotePushMessage error:"); - Log.e(NAME, err.toString()); - } - } - - public static void sendTokenToIntercom(Application application, @NonNull String token) { - intercomPushClient.sendTokenToIntercom(application, token); - Log.d(NAME, "sendTokenToIntercom"); - } - - @ReactMethod - public void handlePushMessage(Promise promise) { - try { - Intercom.client().handlePushMessage(); - promise.resolve(true); - Log.d(NAME, "handlePushMessage"); - } catch (Exception err) { - Log.e(NAME, "handlePushMessage error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.HANDLE_PUSH_MESSAGE, err.toString()); - } - } - - @ReactMethod - public void sendTokenToIntercom(@NonNull String token, Promise promise) { - try { - Activity activity = getCurrentActivity(); - if (activity != null) { - intercomPushClient.sendTokenToIntercom(activity.getApplication(), token); - Log.d(NAME, "sendTokenToIntercom"); - promise.resolve(true); - } else { - Log.e(NAME, "sendTokenToIntercom"); - Log.e(NAME, "no current activity"); - } - - } catch ( - Exception err) { - Log.e(NAME, "sendTokenToIntercom error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SEND_TOKEN_TO_INTERCOM, err.toString()); - } - } - - @ReactMethod - public void loginUnidentifiedUser(Promise promise) { - Intercom.client().loginUnidentifiedUser(new IntercomStatusCallback() { - @Override - public void onSuccess() { - promise.resolve(true); - } - - @Override - public void onFailure(@NonNull IntercomError intercomError) { - Log.e("ERROR", intercomError.getErrorMessage()); - promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage()); - } - }); - } - - @ReactMethod - public void loginUserWithUserAttributes(ReadableMap params, Promise promise) { - Boolean hasEmail = params.hasKey("email") && IntercomHelpers.getValueAsStringForKey(params, "email").length() > 0; - Boolean hasUserId = params.hasKey("userId") && IntercomHelpers.getValueAsStringForKey(params, "userId").length() > 0; - Registration registration = null; - if (hasEmail && hasUserId) { - String email = IntercomHelpers.getValueAsStringForKey(params, "email"); - String userId = IntercomHelpers.getValueAsStringForKey(params, "userId"); - registration = new Registration().withEmail(email).withUserId(userId); - } else if (hasEmail) { - String email = IntercomHelpers.getValueAsStringForKey(params, "email"); - registration = new Registration().withEmail(email); - } else if (hasUserId) { - String userId = IntercomHelpers.getValueAsStringForKey(params, "userId"); - registration = new Registration().withUserId(userId); - } else { - Log.e(NAME, "loginUserWithUserAttributes called with invalid userId or email"); - Log.e(NAME, "You must provide userId or email"); - promise.reject(IntercomErrorCodes.IDENTIFIED_REGISTRATION, "Invalid userId or email"); - } - if (registration != null) { - Intercom.client().loginIdentifiedUser(registration, new IntercomStatusCallback() { - @Override - public void onSuccess() { - promise.resolve(true); - } - - @Override - public void onFailure(@NonNull IntercomError intercomError) { - Log.e("ERROR", intercomError.getErrorMessage()); - promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage()); - } - }); - } - } - - @ReactMethod - public void setUserHash(String userHash, Promise promise) { - try { - Intercom.client().setUserHash(userHash); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "setUserHash error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SET_USER_HASH, err.toString()); - } - } - - @ReactMethod - public void updateUser(ReadableMap params, Promise promise) { - UserAttributes userAttributes = IntercomHelpers.buildUserAttributes(params); - Intercom.client().updateUser(userAttributes, new IntercomStatusCallback() { - @Override - public void onSuccess() { - promise.resolve(true); - } - - @Override - public void onFailure(@NonNull IntercomError intercomError) { - Log.e("ERROR", intercomError.getErrorMessage()); - promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage()); - } - }); - } - - @ReactMethod - public void isUserLoggedIn(Promise promise) { - promise.resolve(Intercom.client().isUserLoggedIn()); - } - - @ReactMethod - public void fetchLoggedInUserAttributes(Promise promise) { - Registration registration = Intercom.client().fetchLoggedInUserAttributes(); - promise.resolve(IntercomHelpers.deconstructRegistration(registration)); - } - - @ReactMethod - public void logout(Promise promise) { - try { - Intercom.client().logout(); - Log.d(NAME, "logout"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "logout error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.LOGOUT, err.toString()); - } - } - - @ReactMethod - public void getUnreadConversationCount(Promise promise) { - try { - promise.resolve(Intercom.client().getUnreadConversationCount()); - Log.d(NAME, "getUnreadConversationCount"); - } catch (Exception err) { - Log.e(NAME, "getUnreadConversationCount error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.GET_UNREAD_CONVERSATION, err.toString()); - } - } - - @ReactMethod - public void setLogLevel(String logLevel, Promise promise) { - try { - Intercom.setLogLevel(IntercomHelpers.stringToLogLevel(logLevel)); - Log.d(NAME, "setLogLevel"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "setLogLevel error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SET_LOG_LEVEL, err.toString()); - } - } - - @ReactMethod - public void logEvent(String eventName, @Nullable ReadableMap metaData, Promise promise) { - try { - if (metaData != null) { - Intercom.client().logEvent(eventName, IntercomHelpers.deconstructReadableMap(metaData, false)); - } else { - Intercom.client().logEvent(eventName); - } - Log.d(NAME, "logEvent"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "logEvent error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.LOG_EVENT_HASH, err.toString()); - } - } - - @ReactMethod - public void presentIntercom(Promise promise) { - try { - Intercom.client().present(); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "presentMessenger error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.DISPLAY_MESSENGER, err.toString()); - } - } - - @ReactMethod - public void presentIntercomSpace(String space, Promise promise) { - try { - IntercomSpace selectedSpace = IntercomSpace.Home; - switch (space) { - case "TICKETS": - selectedSpace = IntercomSpace.Tickets; - break; - case "MESSAGES": - selectedSpace = IntercomSpace.Messages; - break; - case "HELP_CENTER": - selectedSpace = IntercomSpace.HelpCenter; - break; - default: - selectedSpace = IntercomSpace.Home; - } - Intercom.client().present(selectedSpace); - promise.resolve(true); - } catch (Exception error) { - Log.e(NAME, "presentIntercomSpace error:"); - Log.e(NAME, error.toString()); - promise.reject(IntercomErrorCodes.DISPLAY_MESSENGER, error.toString()); - } - } - - @ReactMethod - public void presentMessageComposer(@Nullable String initialMessage, Promise promise) { - try { - if (initialMessage != null) { - Intercom.client().displayMessageComposer(initialMessage); - } else { - Intercom.client().displayMessageComposer(); - } - Log.d(NAME, "presentMessageComposer"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "presentMessageComposer error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.DISPLAY_MESSENGER_COMPOSER, err.toString()); - } - } - - @ReactMethod - public void presentContent(ReadableMap params, Promise promise) { - try { - Boolean hasContentType = params.hasKey("type") && params.getString("type").length() > 0; - if (hasContentType) { - IntercomContent content = null; - String contentType = params.getString("type"); - - switch (contentType) { - case "ARTICLE": - content = new IntercomContent.Article(params.getString("id")); - break; - case "CAROUSEL": - content = new IntercomContent.Carousel(params.getString("id")); - break; - case "SURVEY": - content = new IntercomContent.Survey(params.getString("id")); - break; - case "HELP_CENTER_COLLECTIONS": - List collectionIds = IntercomHelpers.readableArrayToStringList(params.getArray("ids")); - content = new IntercomContent.HelpCenterCollections(collectionIds); - break; - case "CONVERSATION": - content = new IntercomContent.Conversation(params.getString("id")); - break; - } - if (content != null) { - Intercom.client().presentContent(content); - promise.resolve(true); - } else { - promise.reject(IntercomErrorCodes.DISPLAY_CONTENT, "Invalid content type"); - } - } else { - promise.reject(IntercomErrorCodes.DISPLAY_CONTENT, "Intercom content must have a type"); - } - } catch (Exception error) { - Log.e(NAME, error.toString()); - promise.reject(IntercomErrorCodes.DISPLAY_CONTENT, error.toString()); - } - } - - - @ReactMethod - public void fetchHelpCenterCollections(Promise promise) { - try { - - CollectionRequestCallback collectionRequestCallback = new CollectionRequestCallback() { - @Override - public void onComplete(@NotNull List list) { - promise.resolve(IntercomHelpCenterHelpers.parseHelpCenterCollectionsToReadableArray(list)); - } - - @Override - public void onError(int i) { - Log.e(NAME, "fetchHelpCenterCollections error"); - promise.reject(String.valueOf(i), "fetchHelpCenterCollections error"); - } - - @Override - public void onFailure() { - Log.e(NAME, "fetchHelpCenterCollections failure"); - promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTIONS, "fetchHelpCenterCollections failure"); - } - }; - Log.d(NAME, "fetchHelpCenterCollections"); - Intercom.client().fetchHelpCenterCollections(collectionRequestCallback); - - } catch (Exception err) { - Log.e(NAME, "fetchHelpCenterCollections error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTIONS, err.toString()); - } - } - - @ReactMethod - public void fetchHelpCenterCollection(String collectionId, Promise promise) { - try { - if (collectionId.equals("")) { - promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTION, "collectionID can\'t be empty"); - } else { - CollectionContentRequestCallback collectionContentCallback = new CollectionContentRequestCallback() { - @Override - public void onComplete(@NotNull HelpCenterCollectionContent helpCenterCollectionContent) { - promise.resolve(IntercomHelpCenterHelpers.parseHelpCenterCollectionsContentToReadableMap(helpCenterCollectionContent)); - } - - @Override - public void onError(int i) { - Log.e(NAME, "fetchHelpCenterCollection error"); - promise.reject(String.valueOf(i), "fetchHelpCenterCollection error"); - } - - @Override - public void onFailure() { - Log.e(NAME, "fetchHelpCenterCollection failure"); - promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTION, "fetchHelpCenterCollection failure"); - } - }; - Log.d(NAME, "fetchHelpCenterCollection"); - Intercom.client().fetchHelpCenterCollection(collectionId, collectionContentCallback); - } - - } catch (Exception err) { - Log.e(NAME, "fetchHelpCenterCollection error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTION, err.toString()); - } - } - - @ReactMethod - public void searchHelpCenter(String searchTerm, Promise promise) { - if (searchTerm.equals("")) { - promise.reject(IntercomErrorCodes.SEARCH_HELP_CENTER, "searchTerm can\'t be empty"); - } else { - try { - SearchRequestCallback collectionContentCallback = new SearchRequestCallback() { - @Override - public void onComplete(@NotNull List helpCenterArticleSearchResult) { - promise.resolve(IntercomHelpCenterHelpers.parseHelpCenterArticleSearchToReadableArray(helpCenterArticleSearchResult)); - } - - @Override - public void onError(int i) { - Log.e(NAME, "searchHelpCenter error"); - promise.reject(String.valueOf(i), "searchHelpCenter error"); - } - - @Override - public void onFailure() { - Log.e(NAME, "searchHelpCenter failure"); - promise.reject(IntercomErrorCodes.SEARCH_HELP_CENTER, "searchHelpCenter failure"); - } - }; - Log.d(NAME, "searchHelpCenter"); - Intercom.client().searchHelpCenter(searchTerm, collectionContentCallback); - - } catch (Exception err) { - Log.e(NAME, "searchHelpCenter error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SEARCH_HELP_CENTER, err.toString()); - } - } - } - - @ReactMethod - public void setInAppMessageVisibility(String visibility, Promise promise) { - try { - Intercom.client().setInAppMessageVisibility(IntercomHelpers.stringToVisibility(visibility)); - Log.d(NAME, "setInAppMessageVisibility"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "setInAppMessageVisibility error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SET_IN_APP_MESSAGE_VISIBILITY, err.toString()); - } - } - - @ReactMethod - public void hideIntercom(Promise promise) { - try { - Intercom.client().hideIntercom(); - Log.d(NAME, "hideIntercom"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "hideIntercom error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.HIDE_INTERCOM, err.toString()); - } - } - - @ReactMethod - public void setLauncherVisibility(String visibility, Promise promise) { - try { - Intercom.client().setLauncherVisibility(IntercomHelpers.stringToVisibility(visibility)); - Log.d(NAME, "setInAppMessageVisibility"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "setInAppMessageVisibility error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SET_LAUNCHER_VISIBILITY, err.toString()); - } - } - - @ReactMethod - public void setBottomPadding(int paddingBottom, Promise promise) { - try { - Intercom.client().setBottomPadding(paddingBottom); - Log.d(NAME, "setBottomPadding"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "setBottomPadding error:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SET_BOTTOM_PADDING, err.toString()); - } - } - - @ReactMethod - public void setUserJwt(String jwt, Promise promise) { - try { - Intercom.client().setUserJwt(jwt); - Log.d(NAME, "Setting JWT"); - promise.resolve(true); - } catch (Exception err) { - Log.e(NAME, "Error Setting JWT:"); - Log.e(NAME, err.toString()); - promise.reject(IntercomErrorCodes.SET_USER_JWT, err.toString()); - } - } - - public static synchronized void initialize(Application application, String apiKey, String appId) { - String sdkVersion = BuildConfig.INTERCOM_VERSION_NAME; - ReactNativeHeaderInterceptor.setReactNativeVersion(application.getApplicationContext(), sdkVersion); - Intercom.initialize(application, apiKey, appId); - } - -} diff --git a/android/src/main/java/com/intercom/reactnative/IntercomModuleImpl.java b/android/src/main/java/com/intercom/reactnative/IntercomModuleImpl.java new file mode 100644 index 00000000..f2f47d0b --- /dev/null +++ b/android/src/main/java/com/intercom/reactnative/IntercomModuleImpl.java @@ -0,0 +1,499 @@ +package com.intercom.reactnative; + +import android.app.Activity; +import android.app.Application; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.google.firebase.messaging.RemoteMessage; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +import io.intercom.android.sdk.Intercom; +import io.intercom.android.sdk.IntercomContent; +import io.intercom.android.sdk.IntercomError; +import io.intercom.android.sdk.IntercomSpace; +import io.intercom.android.sdk.IntercomStatusCallback; +import io.intercom.android.sdk.UserAttributes; +import io.intercom.android.sdk.api.ReactNativeHeaderInterceptor; +import io.intercom.android.sdk.helpcenter.api.CollectionContentRequestCallback; +import io.intercom.android.sdk.helpcenter.api.CollectionRequestCallback; +import io.intercom.android.sdk.helpcenter.api.HelpCenterArticleSearchResult; +import io.intercom.android.sdk.helpcenter.api.SearchRequestCallback; +import io.intercom.android.sdk.helpcenter.collections.HelpCenterCollection; +import io.intercom.android.sdk.helpcenter.sections.HelpCenterCollectionContent; +import io.intercom.android.sdk.identity.Registration; +import io.intercom.android.sdk.push.IntercomPushClient; + +public class IntercomModuleImpl { + + public static final String NAME = "IntercomModule"; + private final ReactApplicationContext reactContext; + private static final IntercomPushClient intercomPushClient = new IntercomPushClient(); + + public IntercomModuleImpl(ReactApplicationContext reactContext) { + this.reactContext = reactContext; + } + + // Static methods for compatibility with existing usage + public static synchronized void initialize(Application application, String apiKey, String appId) { + String sdkVersion = BuildConfig.INTERCOM_VERSION_NAME; + ReactNativeHeaderInterceptor.setReactNativeVersion(application.getApplicationContext(), sdkVersion); + Intercom.initialize(application, apiKey, appId); + } + + public static boolean isIntercomPush(RemoteMessage remoteMessage) { + try { + Map message = remoteMessage.getData(); + return intercomPushClient.isIntercomPush(message); + } catch (Exception err) { + Log.e(NAME, "isIntercomPush error:"); + Log.e(NAME, err.toString()); + return false; + } + } + + public static void handleRemotePushMessage(@NonNull Application application, RemoteMessage remoteMessage) { + try { + Map message = remoteMessage.getData(); + intercomPushClient.handlePush(application, message); + } catch (Exception err) { + Log.e(NAME, "handleRemotePushMessage error:"); + Log.e(NAME, err.toString()); + } + } + + public static void sendTokenToIntercom(Application application, @NonNull String token) { + intercomPushClient.sendTokenToIntercom(application, token); + Log.d(NAME, "sendTokenToIntercom"); + } + + // Instance methods for the React Native bridge + public void handlePushMessage(Promise promise) { + try { + Intercom.client().handlePushMessage(); + promise.resolve(true); + Log.d(NAME, "handlePushMessage"); + } catch (Exception err) { + Log.e(NAME, "handlePushMessage error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.HANDLE_PUSH_MESSAGE, err.toString()); + } + } + + public void sendTokenToIntercom(@NonNull String token, Promise promise) { + try { + Activity activity = reactContext.getCurrentActivity(); + if (activity != null) { + intercomPushClient.sendTokenToIntercom(activity.getApplication(), token); + Log.d(NAME, "sendTokenToIntercom"); + promise.resolve(true); + } else { + Log.e(NAME, "sendTokenToIntercom"); + Log.e(NAME, "no current activity"); + } + } catch (Exception err) { + Log.e(NAME, "sendTokenToIntercom error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SEND_TOKEN_TO_INTERCOM, err.toString()); + } + } + + public void loginUnidentifiedUser(Promise promise) { + Intercom.client().loginUnidentifiedUser(new IntercomStatusCallback() { + @Override + public void onSuccess() { + promise.resolve(true); + } + + @Override + public void onFailure(@NonNull IntercomError intercomError) { + Log.e("ERROR", intercomError.getErrorMessage()); + promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage()); + } + }); + } + + public void loginUserWithUserAttributes(ReadableMap params, Promise promise) { + Boolean hasEmail = params.hasKey("email") && IntercomHelpers.getValueAsStringForKey(params, "email").length() > 0; + Boolean hasUserId = params.hasKey("userId") && IntercomHelpers.getValueAsStringForKey(params, "userId").length() > 0; + Registration registration = null; + if (hasEmail && hasUserId) { + String email = IntercomHelpers.getValueAsStringForKey(params, "email"); + String userId = IntercomHelpers.getValueAsStringForKey(params, "userId"); + registration = new Registration().withEmail(email).withUserId(userId); + } else if (hasEmail) { + String email = IntercomHelpers.getValueAsStringForKey(params, "email"); + registration = new Registration().withEmail(email); + } else if (hasUserId) { + String userId = IntercomHelpers.getValueAsStringForKey(params, "userId"); + registration = new Registration().withUserId(userId); + } else { + Log.e(NAME, "loginUserWithUserAttributes called with invalid userId or email"); + Log.e(NAME, "You must provide userId or email"); + promise.reject(IntercomErrorCodes.IDENTIFIED_REGISTRATION, "Invalid userId or email"); + } + if (registration != null) { + Intercom.client().loginIdentifiedUser(registration, new IntercomStatusCallback() { + @Override + public void onSuccess() { + promise.resolve(true); + } + + @Override + public void onFailure(@NonNull IntercomError intercomError) { + Log.e("ERROR", intercomError.getErrorMessage()); + promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage()); + } + }); + } + } + + public void setUserHash(String userHash, Promise promise) { + try { + Intercom.client().setUserHash(userHash); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "setUserHash error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SET_USER_HASH, err.toString()); + } + } + + public void updateUser(ReadableMap params, Promise promise) { + UserAttributes userAttributes = IntercomHelpers.buildUserAttributes(params); + Intercom.client().updateUser(userAttributes, new IntercomStatusCallback() { + @Override + public void onSuccess() { + promise.resolve(true); + } + + @Override + public void onFailure(@NonNull IntercomError intercomError) { + Log.e("ERROR", intercomError.getErrorMessage()); + promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage()); + } + }); + } + + public void isUserLoggedIn(Promise promise) { + promise.resolve(Intercom.client().isUserLoggedIn()); + } + + public void fetchLoggedInUserAttributes(Promise promise) { + Registration registration = Intercom.client().fetchLoggedInUserAttributes(); + promise.resolve(IntercomHelpers.deconstructRegistration(registration)); + } + + public void logout(Promise promise) { + try { + Intercom.client().logout(); + Log.d(NAME, "logout"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "logout error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.LOGOUT, err.toString()); + } + } + + public void getUnreadConversationCount(Promise promise) { + try { + promise.resolve(Intercom.client().getUnreadConversationCount()); + Log.d(NAME, "getUnreadConversationCount"); + } catch (Exception err) { + Log.e(NAME, "getUnreadConversationCount error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.GET_UNREAD_CONVERSATION, err.toString()); + } + } + + public void setLogLevel(String logLevel, Promise promise) { + try { + Intercom.setLogLevel(IntercomHelpers.stringToLogLevel(logLevel)); + Log.d(NAME, "setLogLevel"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "setLogLevel error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SET_LOG_LEVEL, err.toString()); + } + } + + public void logEvent(String eventName, @Nullable ReadableMap metaData, Promise promise) { + try { + if (metaData != null) { + Intercom.client().logEvent(eventName, IntercomHelpers.deconstructReadableMap(metaData, false)); + } else { + Intercom.client().logEvent(eventName); + } + Log.d(NAME, "logEvent"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "logEvent error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.LOG_EVENT_HASH, err.toString()); + } + } + + public void presentIntercom(Promise promise) { + try { + Intercom.client().present(); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "presentMessenger error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.DISPLAY_MESSENGER, err.toString()); + } + } + + public void presentIntercomSpace(String space, Promise promise) { + try { + IntercomSpace selectedSpace = IntercomSpace.Home; + switch (space) { + case "TICKETS": + selectedSpace = IntercomSpace.Tickets; + break; + case "MESSAGES": + selectedSpace = IntercomSpace.Messages; + break; + case "HELP_CENTER": + selectedSpace = IntercomSpace.HelpCenter; + break; + default: + selectedSpace = IntercomSpace.Home; + } + Intercom.client().present(selectedSpace); + promise.resolve(true); + } catch (Exception error) { + Log.e(NAME, "presentIntercomSpace error:"); + Log.e(NAME, error.toString()); + promise.reject(IntercomErrorCodes.DISPLAY_MESSENGER, error.toString()); + } + } + + public void presentMessageComposer(@Nullable String initialMessage, Promise promise) { + try { + if (initialMessage != null) { + Intercom.client().displayMessageComposer(initialMessage); + } else { + Intercom.client().displayMessageComposer(); + } + Log.d(NAME, "presentMessageComposer"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "presentMessageComposer error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.DISPLAY_MESSENGER_COMPOSER, err.toString()); + } + } + + public void presentContent(ReadableMap params, Promise promise) { + try { + Boolean hasContentType = params.hasKey("type") && params.getString("type").length() > 0; + if (hasContentType) { + IntercomContent content = null; + String contentType = params.getString("type"); + + switch (contentType) { + case "ARTICLE": + content = new IntercomContent.Article(params.getString("id")); + break; + case "CAROUSEL": + content = new IntercomContent.Carousel(params.getString("id")); + break; + case "SURVEY": + content = new IntercomContent.Survey(params.getString("id")); + break; + case "HELP_CENTER_COLLECTIONS": + List collectionIds = IntercomHelpers.readableArrayToStringList(params.getArray("ids")); + content = new IntercomContent.HelpCenterCollections(collectionIds); + break; + case "CONVERSATION": + content = new IntercomContent.Conversation(params.getString("id")); + break; + } + if (content != null) { + Intercom.client().presentContent(content); + promise.resolve(true); + } else { + promise.reject(IntercomErrorCodes.DISPLAY_CONTENT, "Invalid content type"); + } + } else { + promise.reject(IntercomErrorCodes.DISPLAY_CONTENT, "Intercom content must have a type"); + } + } catch (Exception error) { + Log.e(NAME, error.toString()); + promise.reject(IntercomErrorCodes.DISPLAY_CONTENT, error.toString()); + } + } + + public void fetchHelpCenterCollections(Promise promise) { + try { + CollectionRequestCallback collectionRequestCallback = new CollectionRequestCallback() { + @Override + public void onComplete(@NotNull List list) { + promise.resolve(IntercomHelpCenterHelpers.parseHelpCenterCollectionsToReadableArray(list)); + } + + @Override + public void onError(int i) { + Log.e(NAME, "fetchHelpCenterCollections error"); + promise.reject(String.valueOf(i), "fetchHelpCenterCollections error"); + } + + @Override + public void onFailure() { + Log.e(NAME, "fetchHelpCenterCollections failure"); + promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTIONS, "fetchHelpCenterCollections failure"); + } + }; + Log.d(NAME, "fetchHelpCenterCollections"); + Intercom.client().fetchHelpCenterCollections(collectionRequestCallback); + } catch (Exception err) { + Log.e(NAME, "fetchHelpCenterCollections error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTIONS, err.toString()); + } + } + + public void fetchHelpCenterCollection(String collectionId, Promise promise) { + try { + if (collectionId.equals("")) { + promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTION, "collectionID can\'t be empty"); + } else { + CollectionContentRequestCallback collectionContentCallback = new CollectionContentRequestCallback() { + @Override + public void onComplete(@NotNull HelpCenterCollectionContent helpCenterCollectionContent) { + promise.resolve(IntercomHelpCenterHelpers.parseHelpCenterCollectionsContentToReadableMap(helpCenterCollectionContent)); + } + + @Override + public void onError(int i) { + Log.e(NAME, "fetchHelpCenterCollection error"); + promise.reject(String.valueOf(i), "fetchHelpCenterCollection error"); + } + + @Override + public void onFailure() { + Log.e(NAME, "fetchHelpCenterCollection failure"); + promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTION, "fetchHelpCenterCollection failure"); + } + }; + Log.d(NAME, "fetchHelpCenterCollection"); + Intercom.client().fetchHelpCenterCollection(collectionId, collectionContentCallback); + } + } catch (Exception err) { + Log.e(NAME, "fetchHelpCenterCollection error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.FETCH_HELP_CENTER_COLLECTION, err.toString()); + } + } + + public void searchHelpCenter(String searchTerm, Promise promise) { + if (searchTerm.equals("")) { + promise.reject(IntercomErrorCodes.SEARCH_HELP_CENTER, "searchTerm can\'t be empty"); + } else { + try { + SearchRequestCallback collectionContentCallback = new SearchRequestCallback() { + @Override + public void onComplete(@NotNull List helpCenterArticleSearchResult) { + promise.resolve(IntercomHelpCenterHelpers.parseHelpCenterArticleSearchToReadableArray(helpCenterArticleSearchResult)); + } + + @Override + public void onError(int i) { + Log.e(NAME, "searchHelpCenter error"); + promise.reject(String.valueOf(i), "searchHelpCenter error"); + } + + @Override + public void onFailure() { + Log.e(NAME, "searchHelpCenter failure"); + promise.reject(IntercomErrorCodes.SEARCH_HELP_CENTER, "searchHelpCenter failure"); + } + }; + Log.d(NAME, "searchHelpCenter"); + Intercom.client().searchHelpCenter(searchTerm, collectionContentCallback); + } catch (Exception err) { + Log.e(NAME, "searchHelpCenter error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SEARCH_HELP_CENTER, err.toString()); + } + } + } + + public void setInAppMessageVisibility(String visibility, Promise promise) { + try { + Intercom.client().setInAppMessageVisibility(IntercomHelpers.stringToVisibility(visibility)); + Log.d(NAME, "setInAppMessageVisibility"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "setInAppMessageVisibility error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SET_IN_APP_MESSAGE_VISIBILITY, err.toString()); + } + } + + public void hideIntercom(Promise promise) { + try { + Intercom.client().hideIntercom(); + Log.d(NAME, "hideIntercom"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "hideIntercom error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.HIDE_INTERCOM, err.toString()); + } + } + + public void setLauncherVisibility(String visibility, Promise promise) { + try { + Intercom.client().setLauncherVisibility(IntercomHelpers.stringToVisibility(visibility)); + Log.d(NAME, "setInAppMessageVisibility"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "setInAppMessageVisibility error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SET_LAUNCHER_VISIBILITY, err.toString()); + } + } + + public void setBottomPadding(double paddingBottom, Promise promise) { + try { + Intercom.client().setBottomPadding((int) paddingBottom); + Log.d(NAME, "setBottomPadding"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "setBottomPadding error:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SET_BOTTOM_PADDING, err.toString()); + } + } + + public void setUserJwt(String jwt, Promise promise) { + try { + Intercom.client().setUserJwt(jwt); + Log.d(NAME, "Setting JWT"); + promise.resolve(true); + } catch (Exception err) { + Log.e(NAME, "Error Setting JWT:"); + Log.e(NAME, err.toString()); + promise.reject(IntercomErrorCodes.SET_USER_JWT, err.toString()); + } + } + + public void setNeedsStatusBarAppearanceUpdate(Promise promise) { + // This is an iOS-only method + promise.resolve(null); + } +} diff --git a/android/src/newarch/java/com/intercom/reactnative/IntercomModule.java b/android/src/newarch/java/com/intercom/reactnative/IntercomModule.java new file mode 100644 index 00000000..62a7f3fe --- /dev/null +++ b/android/src/newarch/java/com/intercom/reactnative/IntercomModule.java @@ -0,0 +1,168 @@ +package com.intercom.reactnative; + +import androidx.annotation.NonNull; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableMap; + +public class IntercomModule extends IntercomModuleSpec { + + // declare an instance of the implementation + private IntercomModuleImpl implementation; + + IntercomModule(ReactApplicationContext context) { + super(context); + // initialize the implementation of the module + implementation = new IntercomModuleImpl(context); + } + + @Override + @NonNull + public String getName() { + // NAME is a static variable, so we can access it using the class name. + return IntercomModuleImpl.NAME; + } + + @Override + public void loginUnidentifiedUser(Promise promise) { + implementation.loginUnidentifiedUser(promise); + } + + @Override + public void loginUserWithUserAttributes(ReadableMap userAttributes, Promise promise) { + implementation.loginUserWithUserAttributes(userAttributes, promise); + } + + @Override + public void logout(Promise promise) { + implementation.logout(promise); + } + + @Override + public void updateUser(ReadableMap userAttributes, Promise promise) { + implementation.updateUser(userAttributes, promise); + } + + @Override + public void isUserLoggedIn(Promise promise) { + implementation.isUserLoggedIn(promise); + } + + @Override + public void fetchLoggedInUserAttributes(Promise promise) { + implementation.fetchLoggedInUserAttributes(promise); + } + + @Override + public void setUserHash(String userHash, Promise promise) { + implementation.setUserHash(userHash, promise); + } + + @Override + public void logEvent(String eventName, ReadableMap metaData, Promise promise) { + implementation.logEvent(eventName, metaData, promise); + } + + @Override + public void sendTokenToIntercom(String token, Promise promise) { + implementation.sendTokenToIntercom(token, promise); + } + + @Override + public void presentIntercom(Promise promise) { + implementation.presentIntercom(promise); + } + + @Override + public void presentMessageComposer(String initialMessage, Promise promise) { + implementation.presentMessageComposer(initialMessage, promise); + } + + @Override + public void presentIntercomSpace(String space, Promise promise) { + implementation.presentIntercomSpace(space, promise); + } + + @Override + public void presentContent(ReadableMap content, Promise promise) { + implementation.presentContent(content, promise); + } + + @Override + public void fetchHelpCenterCollections(Promise promise) { + implementation.fetchHelpCenterCollections(promise); + } + + @Override + public void fetchHelpCenterCollection(String collectionId, Promise promise) { + implementation.fetchHelpCenterCollection(collectionId, promise); + } + + @Override + public void searchHelpCenter(String searchTerm, Promise promise) { + implementation.searchHelpCenter(searchTerm, promise); + } + + @Override + public void hideIntercom(Promise promise) { + implementation.hideIntercom(promise); + } + + @Override + public void setBottomPadding(double bottomPadding, Promise promise) { + implementation.setBottomPadding(bottomPadding, promise); + } + + @Override + public void setLauncherVisibility(String visibility, Promise promise) { + implementation.setLauncherVisibility(visibility, promise); + } + + @Override + public void setInAppMessageVisibility(String visibility, Promise promise) { + implementation.setInAppMessageVisibility(visibility, promise); + } + + @Override + public void getUnreadConversationCount(Promise promise) { + implementation.getUnreadConversationCount(promise); + } + + @Override + public void setUserJwt(String jwt, Promise promise) { + implementation.setUserJwt(jwt, promise); + } + + @Override + public void setLogLevel(String level, Promise promise) { + implementation.setLogLevel(level, promise); + } + + @Override + public void setNeedsStatusBarAppearanceUpdate(Promise promise) { + implementation.setNeedsStatusBarAppearanceUpdate(promise); + } + + // Static methods for compatibility with existing usage + public static void initialize(android.app.Application application, String apiKey, String appId) { + IntercomModuleImpl.initialize(application, apiKey, appId); + } + + public static boolean isIntercomPush(com.google.firebase.messaging.RemoteMessage remoteMessage) { + return IntercomModuleImpl.isIntercomPush(remoteMessage); + } + + public static void handleRemotePushMessage(android.app.Application application, com.google.firebase.messaging.RemoteMessage remoteMessage) { + IntercomModuleImpl.handleRemotePushMessage(application, remoteMessage); + } + + public static void sendTokenToIntercom(android.app.Application application, String token) { + IntercomModuleImpl.sendTokenToIntercom(application, token); + } + + // Also add this missing @Override method: + @Override + public void handlePushMessage(Promise promise) { + implementation.handlePushMessage(promise); + } +} diff --git a/android/src/oldarch/java/com/intercom/reactnative/IntercomModule.java b/android/src/oldarch/java/com/intercom/reactnative/IntercomModule.java new file mode 100644 index 00000000..b525d0f9 --- /dev/null +++ b/android/src/oldarch/java/com/intercom/reactnative/IntercomModule.java @@ -0,0 +1,169 @@ +package com.intercom.reactnative; + +import androidx.annotation.NonNull; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; + +public class IntercomModule extends ReactContextBaseJavaModule { + + // declare an instance of the implementation + private IntercomModuleImpl implementation; + + IntercomModule(ReactApplicationContext context) { + super(context); + // initialize the implementation of the module + implementation = new IntercomModuleImpl(context); + } + + // Static methods for compatibility with existing usage + public static void initialize(android.app.Application application, String apiKey, String appId) { + IntercomModuleImpl.initialize(application, apiKey, appId); + } + + public static boolean isIntercomPush(com.google.firebase.messaging.RemoteMessage remoteMessage) { + return IntercomModuleImpl.isIntercomPush(remoteMessage); + } + + public static void handleRemotePushMessage(android.app.Application application, com.google.firebase.messaging.RemoteMessage remoteMessage) { + IntercomModuleImpl.handleRemotePushMessage(application, remoteMessage); + } + + public static void sendTokenToIntercom(android.app.Application application, String token) { + IntercomModuleImpl.sendTokenToIntercom(application, token); + } + + @Override + @NonNull + public String getName() { + // NAME is a static variable, so we can access it using the class name. + return IntercomModuleImpl.NAME; + } + + @ReactMethod + public void loginUnidentifiedUser(Promise promise) { + implementation.loginUnidentifiedUser(promise); + } + + @ReactMethod + public void loginUserWithUserAttributes(ReadableMap userAttributes, Promise promise) { + implementation.loginUserWithUserAttributes(userAttributes, promise); + } + + @ReactMethod + public void logout(Promise promise) { + implementation.logout(promise); + } + + @ReactMethod + public void updateUser(ReadableMap userAttributes, Promise promise) { + implementation.updateUser(userAttributes, promise); + } + + @ReactMethod + public void isUserLoggedIn(Promise promise) { + implementation.isUserLoggedIn(promise); + } + + @ReactMethod + public void fetchLoggedInUserAttributes(Promise promise) { + implementation.fetchLoggedInUserAttributes(promise); + } + + @ReactMethod + public void setUserHash(String userHash, Promise promise) { + implementation.setUserHash(userHash, promise); + } + + @ReactMethod + public void logEvent(String eventName, ReadableMap metaData, Promise promise) { + implementation.logEvent(eventName, metaData, promise); + } + + @ReactMethod + public void sendTokenToIntercom(String token, Promise promise) { + implementation.sendTokenToIntercom(token, promise); + } + + @ReactMethod + public void presentIntercom(Promise promise) { + implementation.presentIntercom(promise); + } + + @ReactMethod + public void presentMessageComposer(String initialMessage, Promise promise) { + implementation.presentMessageComposer(initialMessage, promise); + } + + @ReactMethod + public void presentIntercomSpace(String space, Promise promise) { + implementation.presentIntercomSpace(space, promise); + } + + @ReactMethod + public void presentContent(ReadableMap content, Promise promise) { + implementation.presentContent(content, promise); + } + + @ReactMethod + public void fetchHelpCenterCollections(Promise promise) { + implementation.fetchHelpCenterCollections(promise); + } + + @ReactMethod + public void fetchHelpCenterCollection(String collectionId, Promise promise) { + implementation.fetchHelpCenterCollection(collectionId, promise); + } + + @ReactMethod + public void searchHelpCenter(String searchTerm, Promise promise) { + implementation.searchHelpCenter(searchTerm, promise); + } + + @ReactMethod + public void hideIntercom(Promise promise) { + implementation.hideIntercom(promise); + } + + @ReactMethod + public void setBottomPadding(double bottomPadding, Promise promise) { + implementation.setBottomPadding(bottomPadding, promise); + } + + @ReactMethod + public void setLauncherVisibility(String visibility, Promise promise) { + implementation.setLauncherVisibility(visibility, promise); + } + + @ReactMethod + public void setInAppMessageVisibility(String visibility, Promise promise) { + implementation.setInAppMessageVisibility(visibility, promise); + } + + @ReactMethod + public void getUnreadConversationCount(Promise promise) { + implementation.getUnreadConversationCount(promise); + } + + @ReactMethod + public void setUserJwt(String jwt, Promise promise) { + implementation.setUserJwt(jwt, promise); + } + + @ReactMethod + public void setLogLevel(String level, Promise promise) { + implementation.setLogLevel(level, promise); + } + + @ReactMethod + public void setNeedsStatusBarAppearanceUpdate(Promise promise) { + implementation.setNeedsStatusBarAppearanceUpdate(promise); + } + + @ReactMethod + public void handlePushMessage(Promise promise) { + implementation.handlePushMessage(promise); + } +} diff --git a/example/README.md b/example/README.md index df11a15c..6564dffc 100644 --- a/example/README.md +++ b/example/README.md @@ -20,10 +20,10 @@ This command will create a .env file inside the example directory. Fill in the required App ID in the .env file. Other variables are optional. ## Before you run the app - + Please set up your React Native Development Environment for Android as described in the guide below (if you didn't do it before): -[Android enviroment setup](https://reactnative.dev/docs/environment-setup?package-manager=yarn&guide=native&platform=android) +[Android enviroment setup](https://reactnative.dev/docs/set-up-your-environment?platform=android) ## Running the app diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f3695626..f5f37c49 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -5,9 +5,28 @@ PODS: - fmt (9.1.0) - glog (0.3.5) - Intercom (18.7.3) - - intercom-react-native (8.5.0): + - intercom-react-native (8.7.0): + - DoubleConversion + - glog - Intercom (~> 18.7.3) + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - RCT-Folly (2024.01.01.00): - boost - DoubleConversion @@ -1314,55 +1333,55 @@ SPEC CHECKSUMS: fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2 Intercom: 93c6f5d9815b34bf2a7e5f03bcf7b6e08c1a4788 - intercom-react-native: 985eb561fd1eb0765f86a3332a89a4f31ce3dfaa - RCT-Folly: 045d6ecaa59d826c5736dfba0b2f4083ff8d79df + intercom-react-native: d2b3c5cd9d8de856ab622145caa60cad77c3ac6d + RCT-Folly: 5f972de9f7d384c7d0e7380dd7da506228e568f5 RCTDeprecation: 3ca8b6c36bfb302e1895b72cfe7db0de0c92cd47 RCTRequired: 9fc183af555fd0c89a366c34c1ae70b7e03b1dc5 RCTTypeSafety: db1dd5ad1081a5e160d30bb29ef922693d5ac4b1 React: 8650d592d90b99097504b8dcfebab883972aed71 React-callinvoker: 6bb8b399ab8cec59e52458c3a592aa1fca130b68 - React-Codegen: 0c5fb82424bc21119c79da38b93ab8a62bcf5f9f - React-Core: 6dc6cccf86dd6eb53e5f689211ceb2037d65d3a6 - React-CoreModules: 087c24b785afc79d29d23bffe7b02f79bb00cf76 - React-cxxreact: 8b5a860f8c673ba4f98a3e30b41d4a2ae20f3a31 + React-Codegen: fbad87d0dc7c5bc1536b25bc5cf2f19a1449e438 + React-Core: ab1b60c382b7b79c374b68918f856826ec7f02a9 + React-CoreModules: c5791800e490979b15b819e13ceaee42aa4a2672 + React-cxxreact: 7a5de9c31527a3a36b02caa3540ab55080a6448a React-debug: 41175f3e30dfa8af6eab2631261e1eac26307f9f - React-Fabric: 109d6c97fb4856f3edd848d5d896b71dedeaa361 - React-FabricImage: de46a64a0ca4b0409a0acfb2f5ccdf1195f2d8e2 + React-Fabric: c96fe05717ffb9ab37f7533e9697e68932a621d4 + React-FabricImage: 837a4d681f01084888c7ed55df848eb3611c5691 React-featureflags: 5e7e78c607661fe7f72bc38c6f03736e0876753a - React-graphics: 354adf8693bf849e696bf5096abc8cdc22c78ab4 - React-ImageManager: 74e0898e24b12c45c40019b8558a1310d0b2a47c + React-graphics: ea6e3c3f77683565552986548ba6a2938cb83251 + React-ImageManager: 49a461cd14ed15749fe7371afb1924e8a72aecc1 React-jsc: 8c066d00deacb809aba74cbe3fc94b76d5ae6b7e - React-jserrorhandler: 33cb327f5c6e1571b362f1a9c762ff839a5adb15 - React-jsi: 9ab5aa12ce6d9238a150e81f43c99b97e53a48a7 - React-jsiexecutor: c30f9dda4147c7339cffc64d6ad596c6faddddb9 - React-jsinspector: 50cfdab96549beab8d6554e39f3d36ed2ba23078 - React-jsitracing: 36a2bbc272300313653d980de5ab700ec86c534a - React-logger: 03f2f7b955cfe24593a2b8c9705c23e142d1ad24 - React-Mapbuffer: 5e05d78fe6505f4a054b86f415733d4ad02dd314 - react-native-config: 3367df9c1f25bb96197007ec531c7087ed4554c3 + React-jserrorhandler: bccc0691bf5195f4da1292a4d2fbaa13fa895f89 + React-jsi: 20c796a75f92a22b083ebe78005b50fecfe025bd + React-jsiexecutor: 2ac1b518e12547c6389d6b314f4d17b283feab7a + React-jsinspector: 1cdd1dbae4aa9c455da2fec9ecda2381dda54695 + React-jsitracing: d30048b056e8c9673dfbe67813bdb874c03558a5 + React-logger: 5ae0978955199c132e71e8cf7797f619a6d17164 + React-Mapbuffer: 3b85b3778e447cd1f06d353b8e967af50f272829 + react-native-config: 644074ab88db883fcfaa584f03520ec29589d7df React-nativeconfig: 951ec32f632e81cbd7d40aebb3211313251c092e - React-NativeModulesApple: add06f130d91f3ca13b92d35861fdd6fdb9157e6 + React-NativeModulesApple: 612f931b1e79736f2d59353979042a424fb314c8 React-perflogger: 271f1111779fef70f9502d1d38da5132e5585230 React-RCTActionSheet: 5d6fb9adb11ab1bfbce6695a2b785767e4658c53 - React-RCTAnimation: 86ace32c56e69b3822e7e5184ea83a79d47fc7b9 - React-RCTAppDelegate: 6379a11a49fd0be615dc2e23da0c8a84c52ec65c - React-RCTBlob: 558daf7c11715ef24d97a0be5ccc3b209753682c - React-RCTFabric: eb4b1fc3718040717f17114b7782a519987bd7c4 - React-RCTImage: b482f07cfdbe8e413edbf9d85953cecdb569472c - React-RCTLinking: fbd73a66cab34df69b2389c17f200e4722890fd9 - React-RCTNetwork: fbdd716fbd6e53feb6d8e00eeb85e8184ad42ac8 - React-RCTSettings: 11c3051b965593988298a3f5fb39e23bf6f7df9f - React-RCTText: f240b4d39c36c295204d29e7634a2fac450b6d29 - React-RCTVibration: 1750f80b39e1ad9b4f509f4fdf19a803f7ab0d38 - React-rendererdebug: a89ffa25c7670de8f22e0b322dfdd8333bc0d126 + React-RCTAnimation: 0d11291f869c8a15cff4fd21dca031a83f9e8527 + React-RCTAppDelegate: 77a7b9a27f10aa55da5a44132be281a15cc0848c + React-RCTBlob: 72759b7acf86de079c87a1562a440612c57da1b0 + React-RCTFabric: a0345a090221724893e0ea20ffab73324f4b6520 + React-RCTImage: 80ba9b23ecf87536b14c5eb38bd76f9d2b842c8a + React-RCTLinking: afd22b0854eba28eb277baad45c37ada5ef77bc3 + React-RCTNetwork: ffe5a1021f5a0bcbdf7944665dc44856493ab5bd + React-RCTSettings: f8472ee7998de8d186c198e820c40fcaf9ce4571 + React-RCTText: f556484bf1ba49a7c9b1ce1138608657d80e0bcb + React-RCTVibration: 236755b4231073ebac6cabc3864edb4cd6308d89 + React-rendererdebug: c1dac9f04b12f05929b6113a50aec5fcd5132b94 React-rncore: a3ab9e7271a5c692918e2a483beb900ff0a51169 - React-RuntimeApple: dbaeec3eb503510c93e91d49e92fc39c0ccf7e3a - React-RuntimeCore: 67e737df40b8815f65671fbaf8f75440e7fba96e + React-RuntimeApple: 7fae2c2c7aa890e78830465f5ca7bd13b91939ed + React-RuntimeCore: 38f46aedbab24c4887cf763b8d0c676a059f95e6 React-runtimeexecutor: 4471221991b6e518466a0422fbeb2158c07c36e1 - React-runtimescheduler: 203e25504974651c4472ad00e035658d32002305 - React-utils: 67c666fd04996cdb6bba26590586753d3e8ff7ed - ReactCommon: 53dbd9a55e29188ded016078708d1da8de2db19d - RNCAsyncStorage: ec53e44dc3e75b44aa2a9f37618a49c3bc080a7a + React-runtimescheduler: 1b7a5ce47ba798252278727248a3f50e991e2631 + React-utils: 5eded69fc2a3be3f1823a64c6aa7b202e8e5dd94 + ReactCommon: 649ff2cbfc22342f119b43af78ee85bad61e8919 + RNCAsyncStorage: b6410dead2732b5c72a7fdb1ecb5651bbcf4674b SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: 56f906bf6c11c931588191dde1229fd3e4e3d557 diff --git a/intercom-react-native.podspec b/intercom-react-native.podspec index 4934af23..fd6e0996 100644 --- a/intercom-react-native.podspec +++ b/intercom-react-native.podspec @@ -3,6 +3,9 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# This is required to make install_modules_dependencies available +require_relative 'node_modules/react-native/scripts/react_native_pods' + Pod::Spec.new do |s| s.name = "intercom-react-native" s.version = package["version"] @@ -19,6 +22,6 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" } - s.dependency "React-Core" + install_modules_dependencies(s) s.dependency "Intercom", '~> 18.7.3' end diff --git a/ios/IntercomModule.h b/ios/IntercomModule.h index 2b15d4bc..024389a5 100644 --- a/ios/IntercomModule.h +++ b/ios/IntercomModule.h @@ -1,6 +1,15 @@ #import +#ifdef RCT_NEW_ARCH_ENABLED +#import "intercom_react_native.h" +#endif + +#ifdef RCT_NEW_ARCH_ENABLED +@interface IntercomModule : NSObject +#else @interface IntercomModule : NSObject +#endif + + (void)initialize:(nonnull NSString *)apiKey withAppId:(nonnull NSString *)appId; + (void)setDeviceToken:(nonnull NSData *)deviceToken; + (BOOL)isIntercomPushNotification:(nonnull NSDictionary *)userInfo; diff --git a/package.json b/package.json index 58bef29d..4f6f0ac2 100644 --- a/package.json +++ b/package.json @@ -168,5 +168,13 @@ }, "dependencies": { "node-fetch": "^2.6.1" + }, + "codegenConfig": { + "name": "intercom-react-native", + "type": "modules", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.intercom.reactnative" + } } } diff --git a/src/NativeIntercom.ts b/src/NativeIntercom.ts new file mode 100644 index 00000000..2c511ff9 --- /dev/null +++ b/src/NativeIntercom.ts @@ -0,0 +1,30 @@ +import { TurboModuleRegistry, type TurboModule } from 'react-native'; + +export interface Spec extends TurboModule { + sendTokenToIntercom(token: string): Promise; + loginUnidentifiedUser(): Promise; + loginUserWithUserAttributes(userAttributes: Object): Promise; + logout(): Promise; + updateUser(userAttributes: Object): Promise; + isUserLoggedIn(): Promise; + fetchLoggedInUserAttributes(): Promise; + setUserHash(userHash: string): Promise; + logEvent(eventName: string, metaData?: Object): Promise; + presentIntercom(): Promise; + presentMessageComposer(initialMessage: string): Promise; + presentIntercomSpace(space: string): Promise; + presentContent(content: Object): Promise; + fetchHelpCenterCollections(): Promise>; + fetchHelpCenterCollection(collectionId: string): Promise; + searchHelpCenter(searchTerm: string): Promise>; + hideIntercom(): Promise; + setBottomPadding(bottomPadding: number): Promise; + setLauncherVisibility(visibility: string): Promise; + setUserJwt(jwt: string): Promise; + setInAppMessageVisibility(visibility: string): Promise; + getUnreadConversationCount(): Promise; + setLogLevel(level: string): Promise; + setNeedsStatusBarAppearanceUpdate(): Promise; +} + +export default TurboModuleRegistry.get('IntercomModule'); diff --git a/src/index.tsx b/src/index.tsx index 9b304c21..fa33a416 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,19 +1,13 @@ -import { - NativeModules, - NativeEventEmitter, - Platform, - type EmitterSubscription, -} from 'react-native'; +import { NativeEventEmitter, NativeModules } from 'react-native'; -const { IntercomModule, IntercomEventEmitter } = NativeModules; +const IntercomTurboModule = require('./NativeIntercom').default; +// Re-export types and enums that consumers might need export enum Visibility { GONE = 'GONE', VISIBLE = 'VISIBLE', } -type VisibilityType = keyof typeof Visibility; - export enum LogLevel { ASSERT = 'ASSERT', DEBUG = 'DEBUG', @@ -24,27 +18,26 @@ export enum LogLevel { WARN = 'WARN', } -type LogLevelType = keyof typeof LogLevel; - -export const IntercomEvents = { - IntercomUnreadCountDidChange: - IntercomEventEmitter.UNREAD_COUNT_CHANGE_NOTIFICATION, - IntercomWindowDidHide: IntercomEventEmitter.WINDOW_DID_HIDE_NOTIFICATION, - IntercomWindowDidShow: IntercomEventEmitter.WINDOW_DID_SHOW_NOTIFICATION, - IntercomHelpCenterWindowDidShow: - IntercomEventEmitter.WINDOW_DID_SHOW_NOTIFICATION, - IntercomHelpCenterWindowDidHide: - IntercomEventEmitter.WINDOW_DID_HIDE_NOTIFICATION, -}; +export enum Space { + home = 'HOME', + helpCenter = 'HELP_CENTER', + messages = 'MESSAGES', + tickets = 'TICKETS', +} -type EventType = - | 'IntercomUnreadConversationCountDidChangeNotification' - | 'IntercomWindowDidHideNotification' - | 'IntercomWindowDidShowNotification'; +export enum ContentType { + Article = 'ARTICLE', + Carousel = 'CAROUSEL', + Survey = 'SURVEY', + HelpCenterCollections = 'HELP_CENTER_COLLECTIONS', + Conversation = 'CONVERSATION', +} +// Type definitions export type CustomAttributes = { [key: string]: boolean | string | number; }; + export type MetaData = { [key: string]: any; }; @@ -74,15 +67,18 @@ export type HelpCenterArticle = { id: string; title: string; }; + export type HelpCenterSection = { title: string; articles: HelpCenterArticle; }; + export type HelpCenterCollectionItem = { id: string; title: string; summary: string; }; + export type HelpCenterCollectionContent = { id: string; title: string; @@ -90,6 +86,7 @@ export type HelpCenterCollectionContent = { articles: HelpCenterArticle[]; sections: HelpCenterSection[]; }; + export type HelpCenterArticleSearchResult = { id: string; title: string; @@ -97,363 +94,55 @@ export type HelpCenterArticleSearchResult = { summary: string; }; -export enum Space { - home = 'HOME', - helpCenter = 'HELP_CENTER', - messages = 'MESSAGES', - tickets = 'TICKETS', +export interface Content { + type: ContentType; } -export type IntercomType = { - /** - * Login a unidentified user. - * This is a user that doesn't have any identifiable information such as a `userId` or `email`. - * @return {Promise} A promise to the token. - */ - loginUnidentifiedUser: () => Promise; - - /** - * Login a user with identifiable information. - * Valid identifiers are `userId` and `email` which must be set in the {@link UserAttributes} object. - * @param params The {@link UserAttributes} object that contains the user's `email` or `userId`. - */ - loginUserWithUserAttributes: (params: UserAttributes) => Promise; - - /** - * Log a user out of their Intercom session. - * This will dismiss any Intercom UI and clear Intercom's local cache. - */ - logout(): Promise; - - /** - * Set `hash` string if you are using Identity Verification for your Intercom workspace. - * @note This should be called before any user login takes place. - * - * Identity Verification helps to make sure that conversations between you and your users are kept private, and that one - * user can't impersonate another. If Identity Verification is enabled for your app, Intercom for iOS will sign all requests - * going to the Intercom servers with tokens. It requires your mobile application to have its own server which authenticates the app's users, - * and which can store a secret. - * - * @see More information on Identity Verification can be found {@link https://developers.intercom.com/installing-intercom/docs/react-native-identity-verification here} - * @param hash A HMAC digest of the user ID or email. - */ - setUserHash(hash: string): Promise; - - /** - * Update a user in Intercom with data specified in {@link UserAttributes}. - * Full details of the data data attributes that can be stored on a user can be found in {@link UserAttributes}. - * - * @param userAttributes The {@link UserAttributes} object with the user data. - */ - updateUser(userAttributes: UserAttributes): Promise; - - /** - * Determines if there is currently a user logged in. - */ - isUserLoggedIn(): Promise; - - /** - * Gets a logged in user's attributes - * - * @return {Promise} A promise to the user's attributes with `email`and/or `userId` populated.. - */ - fetchLoggedInUserAttributes: () => Promise; - - /** - * Log an event with a given name and metaData. - * You can log events in Intercom based on user actions in your app. - * - * @param eventName The name of the event. - * @param metaData Metadata Objects support a few simple types that Intercom can present on your behalf, - * see the @{https://developers.intercom.com/intercom-api-reference/reference/event-model Intercom API docs} - */ - logEvent(eventName: string, metaData?: MetaData): Promise; - - /** - * Present Intercom as a modal overlay in your app. - * The `Home` space is displayed by default. - */ - present(): Promise; - - /** - * Present an Intercom `space` as a modal overlay in your app - * @see {@link Space} for a list of valid spaces. - * - * @param space The Intercom space to be presented. - */ - presentSpace(space: Space): Promise; - - /** - * Present Intercom content. - * - * An {@link IntercomContent} object. - */ - presentContent(content: Content): Promise; - - /** - * Present the message composer. - * - * @param initialMessage An optional message that is used to pre-populate the composer with some text. - */ - presentMessageComposer(initialMessage?: string): Promise; - - /** - * Fetch all Help Center collections. - * - * @return {Promise>} An array of {@link HelpCenterCollectionItem} objects. - */ - fetchHelpCenterCollections: () => Promise>; - - /** - * Fetch the contents of a Help Center collection. - * - * @param id The ID of the Help Center collection. - * - * @return {Promise} A {@link HelpCenterCollectionContent} object. - */ - fetchHelpCenterCollection: ( - id: string - ) => Promise; - - /** - * Search the Help Center. - * - * @param term The search term. - * - * @return {Promise} An array of {@link HelpCenterArticleSearchResult} objects. - */ - searchHelpCenter: ( - term: string - ) => Promise>; - - /** - * Fetch the current number of unread conversations for the logged in User. - * @return {Promise} the number of unread conversations. - */ - getUnreadConversationCount(): Promise; - - /** - * Hide all Intercom windows that are currently displayed. - * This will hide the Messenger, Help Center, Articles, and in-product messages (eg. Mobile Carousels, chats, and posts). - */ - hideIntercom(): Promise; - - /** - * Set a fixed bottom padding for in app messages and the Intercom Launcher. - * @param bottomPadding The size of the bottom padding in points. - */ - setBottomPadding(bottomPadding: number): Promise; - - /** - * Show or hide the Intercom InApp Messages in your app. - * @note All InApp Messages are visible by default. - * - * @param visibility A boolean indicating if the InApps should be visible. - */ - setInAppMessageVisibility(visibility: VisibilityType): Promise; - - /** - * Show or hide the Intercom Launcher in your app. - * @note The Launcher is hidden by default. - * - * @param visibility A boolean indicating if the Intercom Launcher should be visible. - */ - setLauncherVisibility(visibility: VisibilityType): Promise; - - /** - * Change the Status Bar's style or visibility while an Intercom notification is on - * screen. - * Call this method so that Intercom's window can reflect your app's status bar accordingly. - */ - setNeedsStatusBarAppearanceUpdate(): Promise; - - /** - * Handle an Android push notification payload sent by Intercom. - * - * @note Android only. iOS handles push notifications automatically. - */ - handlePushMessage(): Promise; - - /** - * Send a device token to Intercom to enable push notifications to be sent to the User. - * @param token The device token to send to the server. - */ - sendTokenToIntercom(token: string): Promise; - - /** - * Enable logging for Intercom. - * @param logLevel The logging level to set. - * - * @note iOS will ignore the logging level and by default shows `DEBUG` logging. - */ - setLogLevel(logLevel: LogLevelType): Promise; - - /** - Sets a JWT token for the user, necessary for using the Messenger - when Messenger Security is enforced. This is an improvement to Identity Verification. - - Secure your Messenger to make sure that bad actors can't impersonate your users, - see their conversation history or make unauthorised updates to data. - - This should be called before any user login takes place. - - Parameters: - - jwt: A JWT token signed with your app's secret key. - */ - setUserJwt(JWT: String): Promise; - - /** - * Add an event listener for the supported event types. - */ - addEventListener: ( - event: EventType, - callback: (response: { count?: number; visible: boolean }) => void - ) => EmitterSubscription; -}; - -const Intercom: IntercomType = { - loginUnidentifiedUser: () => IntercomModule.loginUnidentifiedUser(), - loginUserWithUserAttributes: (userAttributes) => - IntercomModule.loginUserWithUserAttributes(userAttributes), - logout: () => IntercomModule.logout(), - setUserHash: (hash) => IntercomModule.setUserHash(hash), - updateUser: (userAttributes) => IntercomModule.updateUser(userAttributes), - isUserLoggedIn: () => IntercomModule.isUserLoggedIn(), - fetchLoggedInUserAttributes: () => - IntercomModule.fetchLoggedInUserAttributes(), - logEvent: (eventName, metaData = undefined) => - IntercomModule.logEvent(eventName, metaData), - - fetchHelpCenterCollections: () => IntercomModule.fetchHelpCenterCollections(), - fetchHelpCenterCollection: (id = '') => - IntercomModule.fetchHelpCenterCollection(id), - searchHelpCenter: (term = '') => IntercomModule.searchHelpCenter(term), - - present: () => IntercomModule.presentIntercom(), - presentSpace: (space) => IntercomModule.presentIntercomSpace(space), - presentContent: (content) => IntercomModule.presentContent(content), - presentMessageComposer: (initialMessage = undefined) => - IntercomModule.presentMessageComposer(initialMessage), - getUnreadConversationCount: () => IntercomModule.getUnreadConversationCount(), - - hideIntercom: () => IntercomModule.hideIntercom(), - setBottomPadding: (paddingBottom) => - IntercomModule.setBottomPadding(paddingBottom), - setInAppMessageVisibility: (visibility) => - IntercomModule.setInAppMessageVisibility(visibility), - setLauncherVisibility: (visibility) => - IntercomModule.setLauncherVisibility(visibility), - - setNeedsStatusBarAppearanceUpdate: Platform.select({ - ios: IntercomModule.setNeedsStatusBarAppearanceUpdate, - default: async () => true, +// Export IntercomContent and IntercomEvents for backward compatibility +export const IntercomContent = { + articleWithArticleId: (articleId: string) => ({ + type: ContentType.Article, + id: articleId, }), - - handlePushMessage: Platform.select({ - android: IntercomModule.handlePushMessage, - default: async () => true, + carouselWithCarouselId: (carouselId: string) => ({ + type: ContentType.Carousel, + id: carouselId, + }), + surveyWithSurveyId: (surveyId: string) => ({ + type: ContentType.Survey, + id: surveyId, + }), + helpCenterCollectionsWithIds: (collectionIds: string[]) => ({ + type: ContentType.HelpCenterCollections, + ids: collectionIds, + }), + conversationWithConversationId: (conversationId: string) => ({ + type: ContentType.Conversation, + id: conversationId, }), - - sendTokenToIntercom: (token) => IntercomModule.sendTokenToIntercom(token), - setLogLevel: (logLevel) => IntercomModule.setLogLevel(logLevel), - setUserJwt: (jwt) => IntercomModule.setUserJwt(jwt), - addEventListener: (event, callback) => { - event === IntercomEvents.IntercomUnreadCountDidChange && - Platform.OS === 'android' && - IntercomEventEmitter.startEventListener(); - const eventEmitter = new NativeEventEmitter(IntercomEventEmitter); - const listener = eventEmitter.addListener(event, callback); - const originalRemove = listener.remove; - listener.remove = () => { - event === IntercomEvents.IntercomUnreadCountDidChange && - Platform.OS === 'android' && - IntercomEventEmitter.removeEventListener(); - originalRemove(); - }; - return listener; - }, }; -export default Intercom; - -export enum ContentType { - Article = 'ARTICLE', - Carousel = 'CAROUSEL', - Survey = 'SURVEY', - HelpCenterCollections = 'HELP_CENTER_COLLECTIONS', - Conversation = 'CONVERSATION', -} - -export interface Content { - type: ContentType; -} - -export interface Article extends Content { - id: string; -} - -interface Carousel extends Content { - id: string; -} - -interface Survey extends Content { - id: string; -} - -interface HelpCenterCollections extends Content { - ids: string[]; -} - -interface Conversation extends Content { - id: string; -} - -export type IntercomContentType = { - /** - * Create - */ - articleWithArticleId: (articleId: string) => Article; - carouselWithCarouselId: (carouselId: string) => Carousel; - surveyWithSurveyId: (surveyId: string) => Survey; - helpCenterCollectionsWithIds: ( - collectionIds: string[] - ) => HelpCenterCollections; - conversationWithConversationId: (conversationId: string) => Conversation; +export const IntercomEvents = { + IntercomUnreadCountDidChange: + 'IntercomUnreadConversationCountDidChangeNotification', + IntercomWindowDidHide: 'IntercomWindowDidHideNotification', + IntercomWindowDidShow: 'IntercomWindowDidShowNotification', + IntercomHelpCenterWindowDidShow: 'IntercomWindowDidShowNotification', + IntercomHelpCenterWindowDidHide: 'IntercomWindowDidHideNotification', }; -export const IntercomContent: IntercomContentType = { - articleWithArticleId(articleId) { - let articleContent = {} as Article; - articleContent.type = ContentType.Article; - articleContent.id = articleId; - return articleContent; - }, +// Custom event handling implementation +const eventEmitter = new NativeEventEmitter(NativeModules.IntercomEventEmitter); - carouselWithCarouselId(carouselId) { - let carouselContent = {} as Carousel; - carouselContent.type = ContentType.Carousel; - carouselContent.id = carouselId; - return carouselContent; +// Create a combined object that includes both TurboModule methods and event handling +const Intercom = { + ...IntercomTurboModule, + addEventListener: (event: string, callback: (response: any) => void) => { + return eventEmitter.addListener(event, callback); }, - - surveyWithSurveyId(surveyId) { - let surveyContent = {} as Survey; - surveyContent.type = ContentType.Survey; - surveyContent.id = surveyId; - return surveyContent; - }, - - helpCenterCollectionsWithIds(collectionIds) { - let helpCenterCollectionsContent = {} as HelpCenterCollections; - helpCenterCollectionsContent.type = ContentType.HelpCenterCollections; - helpCenterCollectionsContent.ids = collectionIds; - return helpCenterCollectionsContent; - }, - - conversationWithConversationId(conversationId) { - let conversationContent = {} as Conversation; - conversationContent.type = ContentType.Conversation; - conversationContent.id = conversationId; - return conversationContent; + removeEventListener: (event: string, _callback: (response: any) => void) => { + eventEmitter.removeAllListeners(event); }, }; + +export default Intercom;