diff --git a/android/src/main/java/com/exponea/ExponeaModule.kt b/android/src/main/java/com/exponea/ExponeaModule.kt index fb7dc39..fcedc09 100644 --- a/android/src/main/java/com/exponea/ExponeaModule.kt +++ b/android/src/main/java/com/exponea/ExponeaModule.kt @@ -520,9 +520,23 @@ class ExponeaModule(private val reactContext: ReactApplicationContext) : override fun markAppInboxAsRead(message: ReadableMap, promise: Promise) = requireInitialized(promise) { catchAndReject(promise) { - val messageItem = message.toMessageItem() - Exponea.markAppInboxAsRead(messageItem) { success -> - promise.resolve(success) + val messageData = message.toHashMapRecursively().toMessageItem() + if (messageData == null) { + promise.reject("ExponeaDataException", "AppInbox message data are invalid. See logs", null) + return@catchAndReject + } + Exponea.fetchAppInboxItem(messageId = messageData.id) { nativeMessage -> + if (nativeMessage == null) { + promise.reject("ExponeaDataException", "AppInbox message not found. See logs", null) + return@fetchAppInboxItem + } + Exponea.markAppInboxAsRead(nativeMessage) { success -> + if (success) { + promise.resolve(true) + } else { + promise.reject("ExponeaError", "Failed to mark AppInbox message as read", null) + } + } } } } diff --git a/android/src/main/java/com/exponea/Extensions.kt b/android/src/main/java/com/exponea/Extensions.kt index 7c8e8ab..e4b2df9 100644 --- a/android/src/main/java/com/exponea/Extensions.kt +++ b/android/src/main/java/com/exponea/Extensions.kt @@ -756,7 +756,8 @@ internal fun Map.toMessageItem(): MessageItem? { internal fun Map.toMessageItemAction(): MessageItemAction? { val source = this - val sourceType = MessageItemAction.Type.find(source.getNullSafely("type")) ?: return null + val typeKey = source.getNullSafely("type", String::class) ?: source.getNullSafely("action", String::class) + val sourceType = MessageItemAction.Type.find(typeKey) ?: return null return MessageItemAction().apply { type = sourceType title = source.getNullSafely("title") diff --git a/ios/Exponea.mm b/ios/Exponea.mm index 805d3ea..b994ce9 100644 --- a/ios/Exponea.mm +++ b/ios/Exponea.mm @@ -95,6 +95,26 @@ + (NSString *)moduleName return @"Exponea"; } +- (NSDictionary *)appInboxMessageToDictionary:(const JS::NativeExponea::AppInboxMessage &)message +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + dict[@"id"] = message.id_(); + dict[@"type"] = message.type(); + if (message.is_read().has_value()) { dict[@"is_read"] = @(message.is_read().value()); } + if (message.create_time().has_value()) { dict[@"create_time"] = @(message.create_time().value()); } + if (message.content()) { dict[@"content"] = message.content(); } + return dict; +} + +- (NSDictionary *)appInboxActionToDictionary:(const JS::NativeExponea::AppInboxAction &)action +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (action.action()) { dict[@"action"] = action.action(); } + if (action.title()) { dict[@"title"] = action.title(); } + if (action.url()) { dict[@"url"] = action.url(); } + return dict; +} + - (NSNumber *)isConfigured { return @([_exponeaBridge isConfigured]); @@ -587,19 +607,33 @@ - (void)fetchAppInboxItem:(NSString *)messageId }]; } -- (void)markAppInboxAsRead:(NSDictionary *)message +- (void)markAppInboxAsRead:(JS::NativeExponea::AppInboxMessage &)message resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - BOOL success = [_exponeaBridge markAppInboxAsRead:message]; - resolve(@(success)); + NSString *messageId = message.id_(); + if (messageId == nil || messageId.length == 0) { + reject(@"ExponeaError", @"App inbox message ID is missing", nil); + return; + } + + [_exponeaBridge markAppInboxAsRead:messageId + success:^(BOOL marked) { + if (marked) { + resolve(@(YES)); + } else { + reject(@"ExponeaError", [NSString stringWithFormat:@"Failed to mark app inbox message %@ as read", messageId], nil); + } + } failure:^(NSError *error) { + reject(@"ExponeaError", error.localizedDescription, error); + }]; } -- (void)trackAppInboxOpened:(NSDictionary *)message +- (void)trackAppInboxOpened:(JS::NativeExponea::AppInboxMessage &)message resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - BOOL success = [_exponeaBridge trackAppInboxOpened:message considerConsent:YES]; + BOOL success = [_exponeaBridge trackAppInboxOpened:[self appInboxMessageToDictionary:message] considerConsent:YES]; if (success) { resolve([NSNull null]); } else { @@ -607,11 +641,11 @@ - (void)trackAppInboxOpened:(NSDictionary *)message } } -- (void)trackAppInboxOpenedWithoutTrackingConsent:(NSDictionary *)message +- (void)trackAppInboxOpenedWithoutTrackingConsent:(JS::NativeExponea::AppInboxMessage &)message resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - BOOL success = [_exponeaBridge trackAppInboxOpened:message considerConsent:NO]; + BOOL success = [_exponeaBridge trackAppInboxOpened:[self appInboxMessageToDictionary:message] considerConsent:NO]; if (success) { resolve([NSNull null]); } else { @@ -619,13 +653,13 @@ - (void)trackAppInboxOpenedWithoutTrackingConsent:(NSDictionary *)message } } -- (void)trackAppInboxClick:(NSDictionary *)action - message:(NSDictionary *)message +- (void)trackAppInboxClick:(JS::NativeExponea::AppInboxAction &)action + message:(JS::NativeExponea::AppInboxMessage &)message resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - BOOL success = [_exponeaBridge trackAppInboxClick:action - message:message + BOOL success = [_exponeaBridge trackAppInboxClick:[self appInboxActionToDictionary:action] + message:[self appInboxMessageToDictionary:message] considerConsent:YES]; if (success) { resolve([NSNull null]); @@ -634,13 +668,13 @@ - (void)trackAppInboxClick:(NSDictionary *)action } } -- (void)trackAppInboxClickWithoutTrackingConsent:(NSDictionary *)action - message:(NSDictionary *)message +- (void)trackAppInboxClickWithoutTrackingConsent:(JS::NativeExponea::AppInboxAction &)action + message:(JS::NativeExponea::AppInboxMessage &)message resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { - BOOL success = [_exponeaBridge trackAppInboxClick:action - message:message + BOOL success = [_exponeaBridge trackAppInboxClick:[self appInboxActionToDictionary:action] + message:[self appInboxMessageToDictionary:message] considerConsent:NO]; if (success) { resolve([NSNull null]); diff --git a/ios/ExponeaBridge.swift b/ios/ExponeaBridge.swift index f5b862e..5dcda5b 100644 --- a/ios/ExponeaBridge.swift +++ b/ios/ExponeaBridge.swift @@ -585,21 +585,30 @@ public class ExponeaRNVersion: NSObject, ExponeaVersionProvider { } } - public func markAppInboxAsRead(_ messageDict: [AnyHashable: Any]) -> Bool { + public func markAppInboxAsRead( + _ messageId: String, + success: @escaping (Bool) -> Void, + failure: @escaping (Error) -> Void + ) { guard ExponeaBridge.exponeaInstance.isConfigured else { print("ExponeaBridge: SDK not configured") - return false + failure(ExponeaError.notConfigured) + return } - do { - let message = try TypeConverters.parseAppInboxMessage(from: messageDict as NSDictionary) - ExponeaSDK.Exponea.shared.markAppInboxAsRead(message) { marked in - print("ExponeaBridge: Message marked as read: \(marked)") + print("ExponeaBridge: Fetching native AppInbox message before marking as read: \(messageId)") + ExponeaSDK.Exponea.shared.fetchAppInboxItem(messageId) { result in + switch result { + case .success(let message): + print("ExponeaBridge: Marking native AppInbox message as read: \(messageId)") + ExponeaSDK.Exponea.shared.markAppInboxAsRead(message) { marked in + print("ExponeaBridge: AppInbox message \(messageId) marked as read: \(marked)") + success(marked) + } + case .failure(let error): + print("ExponeaBridge: Failed to fetch native AppInbox message \(messageId) before marking as read: \(error)") + failure(error) } - return true - } catch { - print("ExponeaBridge: Failed to parse app inbox message: \(error)") - return false } }