diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/managers/NotificationManager.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/managers/NotificationManager.kt new file mode 100644 index 0000000..1859bb2 --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/managers/NotificationManager.kt @@ -0,0 +1,49 @@ +package com.keyvalue.siren.androidsdk.data.managers + +import com.keyvalue.siren.androidsdk.data.model.UnViewedNotificationResponseData +import com.keyvalue.siren.androidsdk.data.networkcallbacks.NetworkCallback +import com.keyvalue.siren.androidsdk.data.repository.NotificationRepository +import com.keyvalue.siren.androidsdk.data.repository.NotificationRepositoryImplementation +import com.keyvalue.siren.androidsdk.data.state.NotificationUnViewedState +import kotlinx.coroutines.flow.MutableStateFlow +import org.json.JSONObject + +class NotificationManager(baseURL: String) { + private var service: NotificationRepository = + NotificationRepositoryImplementation(baseURL) + var notificationUnViewedState: MutableStateFlow = + MutableStateFlow(null) + + suspend fun fetchUnViewedNotificationsCount( + userToken: String, + recipientId: String, + ) { + service.fetchUnViewedNotificationsCount( + userToken, + recipientId, + object : NetworkCallback { + override suspend fun onResult(classObject: Any) { + val notificationUnViewedState = + NotificationUnViewedState( + notificationUnViewedResponse = classObject as UnViewedNotificationResponseData, + errorResponse = null, + ) + this@NotificationManager.notificationUnViewedState.emit( + notificationUnViewedState, + ) + } + + override suspend fun onError(errorObject: JSONObject) { + val notificationUnViewedState = + NotificationUnViewedState( + notificationUnViewedResponse = null, + errorResponse = errorObject, + ) + this@NotificationManager.notificationUnViewedState.emit( + notificationUnViewedState, + ) + } + }, + ) + } +} diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/model/UnViewedNotificationResponse.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/model/UnViewedNotificationResponse.kt new file mode 100644 index 0000000..8d4f545 --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/model/UnViewedNotificationResponse.kt @@ -0,0 +1,10 @@ +package com.keyvalue.siren.androidsdk.data.model + +import com.google.gson.annotations.SerializedName + +data class UnViewedNotificationResponse( + @SerializedName("data") + val unViewedNotificationResponse: UnViewedNotificationResponseData?, + @SerializedName("error") + val error: ErrorResponse?, +) diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/model/UnViewedNotificationResponseData.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/model/UnViewedNotificationResponseData.kt new file mode 100644 index 0000000..71e049c --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/model/UnViewedNotificationResponseData.kt @@ -0,0 +1,16 @@ +package com.keyvalue.siren.androidsdk.data.model + +data class UnViewedNotificationResponseData( + val id: String, + val createdAt: String, + val updatedAt: String, + val deletedAt: String?, + val createdBy: String, + val updatedBy: String, + val deletedBy: String?, + val projectEnvironmentId: String, + val referenceId: String, + val providerIntegrationId: String, + val lastOpenedAt: String?, + val totalUnviewed: Long, +) diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/repository/NotificationRepository.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/repository/NotificationRepository.kt new file mode 100644 index 0000000..d5e2120 --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/repository/NotificationRepository.kt @@ -0,0 +1,11 @@ +package com.keyvalue.siren.androidsdk.data.repository + +import com.keyvalue.siren.androidsdk.data.networkcallbacks.NetworkCallback + +interface NotificationRepository { + suspend fun fetchUnViewedNotificationsCount( + userToken: String, + recipientId: String, + networkCallback: NetworkCallback, + ) +} diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/repository/NotificationRepositoryImplementation.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/repository/NotificationRepositoryImplementation.kt new file mode 100644 index 0000000..81a7df1 --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/repository/NotificationRepositoryImplementation.kt @@ -0,0 +1,68 @@ +package com.keyvalue.siren.androidsdk.data.repository + +import com.google.gson.Gson +import com.keyvalue.siren.androidsdk.data.model.UnViewedNotificationResponse +import com.keyvalue.siren.androidsdk.data.networkcallbacks.NetworkCallback +import com.keyvalue.siren.androidsdk.data.retrofit.RetrofitClient +import com.keyvalue.siren.androidsdk.data.service.NotificationApiService +import com.keyvalue.siren.androidsdk.utils.constants.CODE_GENERIC_API_ERROR +import com.keyvalue.siren.androidsdk.utils.constants.CODE_TIMED_OUT +import com.keyvalue.siren.androidsdk.utils.constants.ERROR_MESSAGE_SERVICE_NOT_AVAILABLE +import com.keyvalue.siren.androidsdk.utils.constants.ERROR_MESSAGE_TIMED_OUT +import com.keyvalue.siren.androidsdk.utils.constants.SirenErrorTypes +import org.json.JSONObject +import java.net.SocketTimeoutException + +class NotificationRepositoryImplementation(baseURL: String) : NotificationRepository { + private var notificationsApiService: NotificationApiService? = null + + init { + notificationsApiService = + RetrofitClient.getRetrofitInstance(baseURL)?.create( + NotificationApiService::class.java, + ) + } + + override suspend fun fetchUnViewedNotificationsCount( + userToken: String, + recipientId: String, + networkCallback: NetworkCallback, + ) { + try { + val parentResponse = + notificationsApiService?.fetchUnViewedNotificationsCount(recipientId, userToken) + val response = parentResponse?.body() + if (response?.unViewedNotificationResponse != null) { + response.unViewedNotificationResponse.let { + networkCallback.onResult(it) + } + } else { + val errorBody = parentResponse?.errorBody()?.string() + if (errorBody != null) { + val errors = + Gson().fromJson( + errorBody, + UnViewedNotificationResponse::class.java, + ) + networkCallback.onError( + JSONObject().put("type", SirenErrorTypes.ERROR) + .put("code", errors.error?.errorCode ?: CODE_GENERIC_API_ERROR).put( + "message", + errors.error?.message + ?: "HTTP error! status: ${parentResponse.raw().code} ${parentResponse.raw().message}", + ), + ) + } + } + } catch (e: SocketTimeoutException) { + networkCallback.onError( + JSONObject().put("code", CODE_TIMED_OUT).put("message", ERROR_MESSAGE_TIMED_OUT), + ) + } catch (e: Exception) { + networkCallback.onError( + JSONObject().put("code", CODE_GENERIC_API_ERROR) + .put("message", ERROR_MESSAGE_SERVICE_NOT_AVAILABLE), + ) + } + } +} diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/service/NotificationApiService.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/service/NotificationApiService.kt new file mode 100644 index 0000000..ee0fd42 --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/service/NotificationApiService.kt @@ -0,0 +1,15 @@ +package com.keyvalue.siren.androidsdk.data.service + +import com.keyvalue.siren.androidsdk.data.model.UnViewedNotificationResponse +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.Path + +interface NotificationApiService { + @GET("api/v2/in-app/recipients/{inAppRecipientId}") + suspend fun fetchUnViewedNotificationsCount( + @Path("inAppRecipientId") id: String, + @Header("Authorization") token: String, + ): Response +} diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/state/NotificationUnViewedState.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/state/NotificationUnViewedState.kt new file mode 100644 index 0000000..fbceabf --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/data/state/NotificationUnViewedState.kt @@ -0,0 +1,9 @@ +package com.keyvalue.siren.androidsdk.data.state + +import com.keyvalue.siren.androidsdk.data.model.UnViewedNotificationResponseData +import org.json.JSONObject + +class NotificationUnViewedState( + var errorResponse: JSONObject? = null, + var notificationUnViewedResponse: UnViewedNotificationResponseData? = null, +) diff --git a/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/presenter/NotificationPresenter.kt b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/presenter/NotificationPresenter.kt new file mode 100644 index 0000000..cd1e157 --- /dev/null +++ b/siren-sdk/src/main/java/com/keyvalue/siren/androidsdk/presenter/NotificationPresenter.kt @@ -0,0 +1,42 @@ +package com.keyvalue.siren.androidsdk.presenter + +import com.keyvalue.siren.androidsdk.data.managers.NotificationManager +import com.keyvalue.siren.androidsdk.data.model.UnViewedNotificationResponseData +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.json.JSONObject + +class NotificationPresenter( + private var userToken: String, + private var recipientId: String, +) : BasePresenter() { + private var notificationManager: NotificationManager? = null + + init { + notificationManager = NotificationManager(baseURL) + } + + fun fetchUnViewedNotificationsCount(callback: (UnViewedNotificationResponseData?, JSONObject?, Boolean) -> Unit) { + CoroutineScope(Dispatchers.IO).launch { + notificationManager?.fetchUnViewedNotificationsCount(userToken, recipientId) + notificationManager?.notificationUnViewedState?.collect { notificationUnViewedState -> + if (notificationUnViewedState?.errorResponse == null) { + notificationUnViewedState?.notificationUnViewedResponse?.let { response -> + callback( + response, + null, + false, + ) + } + } else { + callback( + null, + notificationUnViewedState.errorResponse, + true, + ) + } + } + } + } +}