TP-58731 | Sohan Reddy | Rewriting ResponseCallback for RR module (#10017)

This commit is contained in:
Sohan Reddy Atukula
2024-03-19 20:57:45 +05:30
committed by GitHub
parent 34e780dbfe
commit 45e17ff3a6
29 changed files with 725 additions and 151 deletions

View File

@@ -18,6 +18,7 @@ import com.navi.common.utils.Constants.API_LATENCY
import com.navi.common.utils.Constants.API_METRIC_EVENT
import com.navi.common.utils.Constants.CONTENT_SIZE_IN_KB
import com.navi.naviwidgets.utils.VERTICAL
import java.io.IOException
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Protocol
@@ -53,7 +54,7 @@ class MetricInterceptor : Interceptor {
)
return chainResponse
} catch (e: Exception) {
} catch (e: IOException) {
val errorMessage = handleException(e)
logIOException(e, errorMessage, request)
// A mocked response in case of n/w exception

View File

@@ -7,12 +7,11 @@ import com.navi.common.listeners.BackPressedListener
import com.navi.common.listeners.FragmentInterchangeListener
import com.navi.common.model.ModuleNameV2
import com.navi.rr.R
import com.navi.common.R as CommonR
import com.navi.rr.rewards.ui.activity.RewardsDashboardActivity
import com.navi.rr.tds.ui.TdsFragment
import com.navi.rr.upi.ui.UpiFragment
import com.navi.rr.utils.Constants
import dagger.hilt.android.AndroidEntryPoint
import com.navi.common.R as CommonR
@AndroidEntryPoint
class RRFragmentSelectorActivity() : RRBaseActivity(), FragmentInterchangeListener {

View File

@@ -4,17 +4,20 @@ import com.navi.common.forge.model.ScreenDefinition
import com.navi.common.model.ModuleName
import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.common.constants.FORGE_LEADERBOARD_SCREEN
import com.navi.rr.leaderboard.models.LeaderboardListResponse
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import javax.inject.Inject
class LeaderboardScreenRepo @Inject constructor(private val retrofitService: RetrofitService) :
ResponseCallback() {
class LeaderboardScreenRepo @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchReferralForgeScreen() : RepoResult<ScreenDefinition> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
target = ModuleNameV2.FORGE.name,
screenId = FORGE_LEADERBOARD_SCREEN
@@ -23,7 +26,7 @@ class LeaderboardScreenRepo @Inject constructor(private val retrofitService: Ret
}
suspend fun fetchLeaderboardList(userEntered : Boolean) : RepoResult<LeaderboardListResponse> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.fetchLeaderboardList(
target = ModuleName.REFERRAL.name,
userEntered = userEntered

View File

@@ -0,0 +1,39 @@
package com.navi.rr.network.response.handlers
import com.navi.common.network.models.ErrorMessage
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.rr.network.response.handlers.NetworkResponseProcessor.Companion.DEFAULT_DESCRIPTION
import com.navi.rr.network.response.handlers.NetworkResponseProcessor.Companion.DEFAULT_MESSAGE
import retrofit2.Response
abstract class ExceptionHandler: Handler<ExceptionHandler>() {
override var chain: ExceptionHandler? = null
fun <T> setError(
message: String,
description: String,
statusCode: Int,
appRequestId: String?,
vertical: String?,
): RepoResult<T> {
val result = RepoResult<T>()
val errorMessage = ErrorMessage()
errorMessage.apply {
this.message = message
this.description = description
this.statusCode = statusCode
this.appRequestId = appRequestId
this.vertical = vertical
}
result.error = errorMessage
return result
}
abstract fun <T> handleException(exception: Exception, response: Response<GenericResponse<T>>): RepoResult<T>
open val message: String = DEFAULT_MESSAGE
open val description: String = DEFAULT_DESCRIPTION
}

View File

@@ -0,0 +1,5 @@
package com.navi.rr.network.response.handlers
open class Handler<T> {
open var chain: T? = null
}

View File

@@ -0,0 +1,66 @@
package com.navi.rr.network.response.handlers
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.navi.analytics.utils.NaviAnalyticsHelper
import com.navi.common.network.ApiConstants.API_CODE_ERROR
import com.navi.common.network.models.ErrorMessage
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.rr.network.response.handlers.chains.rrExceptionHandlerChain
import com.navi.rr.network.util.trackApiEvent
import retrofit2.Response
import timber.log.Timber
abstract class NetworkResponseProcessor(private val responseCode: Int): Handler<NetworkResponseProcessor>() {
override var chain: NetworkResponseProcessor? = null
open fun <T> onResponseReceive(
responseCode: Int,
response: Response<GenericResponse<T>>,
): RepoResult<T> {
return try {
if (this.responseCode == responseCode) {
trackApiEvent(response, responseCode)
handleResponse(response)
} else {
chain?.onResponseReceive(responseCode, response)
?: RepoResult(
error = ErrorMessage(
message = DEFAULT_MESSAGE,
description = DEFAULT_DESCRIPTION,
statusCode = API_CODE_ERROR
)
)
}
} catch (exception: Exception) {
handleException(exception, response)
}
}
private fun <T> handleException(exception: Exception, response: Response<GenericResponse<T>>): RepoResult<T> {
Timber.d(exception, "Failure during processing")
NaviAnalyticsHelper.recordException(exception)
val result = rrExceptionHandlerChain().handleException(exception, response)
try {
result.error?.apiUrl = response.raw().request.url.toString()
} catch (th: Throwable) {
FirebaseCrashlytics.getInstance().log("Api url logging error: ${th.message.toString()}")
}
return result
}
protected abstract fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T>
open val message: String? = DEFAULT_MESSAGE
open val description: String? = DEFAULT_DESCRIPTION
companion object {
const val DEFAULT_MESSAGE = "Something went wrong"
const val DEFAULT_DESCRIPTION = "Please try again later"
}
}

View File

@@ -0,0 +1,14 @@
package com.navi.rr.network.response.handlers.chains
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.rr.network.response.handlers.ExceptionHandler
import retrofit2.Response
class ExceptionHandlerChain: HandlerChain<ExceptionHandler>() {
override var previousHandler: ExceptionHandler? = null
fun <T> handleException(exception: Exception, response: Response<GenericResponse<T>>): RepoResult<T> {
return previousHandler?.handleException(exception, response) ?: RepoResult<T>()
}
}

View File

@@ -0,0 +1,57 @@
package com.navi.rr.network.response.handlers.chains
import com.navi.rr.network.response.handlers.Handler
import com.navi.rr.network.response.handlers.types.BadGatewayHandlerNetwork
import com.navi.rr.network.response.handlers.types.BadRequestHandlerNetwork
import com.navi.rr.network.response.handlers.types.ConnectErrorHandlerNetwork
import com.navi.rr.network.response.handlers.types.DefaultExceptionHandler
import com.navi.rr.network.response.handlers.types.IOExceptionHandlerNetwork
import com.navi.rr.network.response.handlers.types.InternalServerErrorHandlerNetwork
import com.navi.rr.network.response.handlers.types.JsonParseExceptionHandlerNetwork
import com.navi.rr.network.response.handlers.types.NoContentHandlerNetwork
import com.navi.rr.network.response.handlers.types.NoInternetExceptionHandler
import com.navi.rr.network.response.handlers.types.NoInternetHandlerNetwork
import com.navi.rr.network.response.handlers.types.NoUserFoundHandlerNetwork
import com.navi.rr.network.response.handlers.types.PeerUnverifiedErrorHandlerNetwork
import com.navi.rr.network.response.handlers.types.SSLHandshakeExceptionHandlerNetwork
import com.navi.rr.network.response.handlers.types.SocketTimeoutErrorHandlerNetwork
import com.navi.rr.network.response.handlers.types.SuccessHandlerNetwork
import com.navi.rr.network.response.handlers.types.UnknownHostExceptionHandlerNetwork
fun rrExceptionHandlerChain() = ExceptionHandlerChain().apply {
addHandler(NoInternetExceptionHandler())
addHandler(DefaultExceptionHandler())
}
fun rrNetworkProcessorChain() = NetworkResponseProcessorChain().apply {
addHandler(SocketTimeoutErrorHandlerNetwork())
addHandler(ConnectErrorHandlerNetwork())
addHandler(NoInternetHandlerNetwork())
addHandler(UnknownHostExceptionHandlerNetwork())
addHandler(SSLHandshakeExceptionHandlerNetwork())
addHandler(JsonParseExceptionHandlerNetwork())
addHandler(IOExceptionHandlerNetwork())
addHandler(SuccessHandlerNetwork())
addHandler(NoContentHandlerNetwork())
addHandler(BadGatewayHandlerNetwork())
addHandler(InternalServerErrorHandlerNetwork())
addHandler(PeerUnverifiedErrorHandlerNetwork())
addHandler(NoUserFoundHandlerNetwork())
addHandler(BadRequestHandlerNetwork())
}
abstract class HandlerChain<T : Handler<T>>{
open var previousHandler: T? = null
open fun addHandler(handler: T) {
if (previousHandler == null) {
previousHandler = handler
} else {
var lastHandler = previousHandler
while (lastHandler?.chain != null) {
lastHandler = lastHandler.chain
}
lastHandler?.chain = handler
}
}
}

View File

@@ -0,0 +1,47 @@
package com.navi.rr.network.response.handlers.chains
import com.navi.common.network.ApiConstants.API_CODE_ERROR
import com.navi.common.network.models.ErrorMessage
import com.navi.common.network.models.GenericErrorResponse
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.common.utils.CommonUtils
import com.navi.rr.network.response.handlers.NetworkResponseProcessor
import retrofit2.Response
class NetworkResponseProcessorChain: HandlerChain<NetworkResponseProcessor>() {
override var previousHandler: NetworkResponseProcessor? = null
fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
addApiUrlInErrorResponse(response.body()?.errors, response.raw().request.url.toString())
CommonUtils.buildLogMessageForNetWatch(response)
return response.body()?.statusCode?.let {
previousHandler?.onResponseReceive(
it,
response
) ?: RepoResult(
data = null,
error = ErrorMessage(
message = NetworkResponseProcessor.DEFAULT_MESSAGE,
description = NetworkResponseProcessor.DEFAULT_DESCRIPTION,
statusCode = API_CODE_ERROR
)
)
} ?:
previousHandler?.onResponseReceive(
response.code(),
response
) ?: RepoResult(
data = null,
error = ErrorMessage(
message = NetworkResponseProcessor.DEFAULT_MESSAGE,
description = NetworkResponseProcessor.DEFAULT_DESCRIPTION,
statusCode = API_CODE_ERROR
)
)
}
private fun addApiUrlInErrorResponse(errors: List<GenericErrorResponse>?, apiUrl: String) {
errors?.forEach { it.apiUrl = apiUrl }
}
}

View File

@@ -0,0 +1,55 @@
package com.navi.rr.network.response.handlers.types
import com.navi.base.utils.BaseUtils
import com.navi.common.CommonLibManager
import com.navi.common.network.ApiConstants.API_CODE_ERROR
import com.navi.common.network.ApiConstants.NO_INTERNET
import com.navi.common.network.getRequestIdFromResponse
import com.navi.common.network.getVerticalFromResponse
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.rr.network.response.handlers.ExceptionHandler
import com.navi.rr.network.util.trackApiEvent
import retrofit2.Response
class NoInternetExceptionHandler : ExceptionHandler() {
override fun <T> handleException(
exception: Exception,
response: Response<GenericResponse<T>>,
): RepoResult<T> {
return if (!BaseUtils.isNetworkAvailable(CommonLibManager.application)) {
trackApiEvent(response, NO_INTERNET)
return setError(
message,
description,
NO_INTERNET,
getRequestIdFromResponse(response),
getVerticalFromResponse(response)
)
} else {
chain?.handleException(exception, response) ?: RepoResult<T>()
}
}
override val message: String = "No Internet"
override val description: String = "Please check your internet connection"
}
class DefaultExceptionHandler : ExceptionHandler() {
override fun <T> handleException(
exception: Exception,
response: Response<GenericResponse<T>>,
): RepoResult<T> {
trackApiEvent(response, API_CODE_ERROR)
return setError(
message,
description,
API_CODE_ERROR,
getRequestIdFromResponse(response),
getVerticalFromResponse(response)
)
}
override val message = "Something went wrong"
override val description = "Please try again"
}

View File

@@ -0,0 +1,309 @@
package com.navi.rr.network.response.handlers.types
import com.navi.common.network.ApiConstants.API_BAD_GATEWAY
import com.navi.common.network.ApiConstants.API_BAD_REQUEST
import com.navi.common.network.ApiConstants.API_CODE_CONNECT_EXCEPTION
import com.navi.common.network.ApiConstants.API_CODE_SOCKET_TIMEOUT
import com.navi.common.network.ApiConstants.API_CODE_SSL_HANDSHAKE_EXCEPTION
import com.navi.common.network.ApiConstants.API_CODE_UNKNOWN_HOST
import com.navi.common.network.ApiConstants.API_ERROR_NO_USER_FOUND
import com.navi.common.network.ApiConstants.API_ERROR_PEER_UNVERIFIED
import com.navi.common.network.ApiConstants.API_INTERNAL_SERVER_ERROR
import com.navi.common.network.ApiConstants.API_NOT_FOUND
import com.navi.common.network.ApiConstants.API_SUCCESS_CODE
import com.navi.common.network.ApiConstants.API_SUCCESS_CODE_204
import com.navi.common.network.ApiConstants.API_WRONG_ERROR_RESPONSE
import com.navi.common.network.ApiConstants.IO_EXCEPTION_ERROR
import com.navi.common.network.ApiConstants.NO_INTERNET
import com.navi.common.network.fetchNewKeyFromFirebaseAndRestart
import com.navi.common.network.getRequestIdFromResponse
import com.navi.common.network.getVerticalFromResponse
import com.navi.common.network.models.ErrorMessage
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.rr.network.response.handlers.NetworkResponseProcessor
import retrofit2.Response
class BadGatewayHandlerNetwork : NetworkResponseProcessor(API_BAD_GATEWAY) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_BAD_GATEWAY,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_BAD_GATEWAY,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Server Down"
override val description = "Please try again later."
}
class ConnectErrorHandlerNetwork: NetworkResponseProcessor(API_CODE_CONNECT_EXCEPTION) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_CODE_CONNECT_EXCEPTION,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_CODE_CONNECT_EXCEPTION,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "No Internet"
override val description = "Please check your internet connection"
}
class BadRequestHandlerNetwork: NetworkResponseProcessor(API_BAD_REQUEST) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_BAD_REQUEST,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_BAD_REQUEST,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Bad Request"
override val description = "Please try again later."
}
class InternalServerErrorHandlerNetwork : NetworkResponseProcessor(API_INTERNAL_SERVER_ERROR) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_INTERNAL_SERVER_ERROR,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_INTERNAL_SERVER_ERROR,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Something went wrong"
override val description = "Please try again"
}
class NoContentHandlerNetwork : NetworkResponseProcessor(API_SUCCESS_CODE_204) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = null,
statusCode = API_SUCCESS_CODE_204,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = null
override val description = null
}
class NoInternetHandlerNetwork: NetworkResponseProcessor(NO_INTERNET) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = NO_INTERNET,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = NO_INTERNET,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "No Internet"
override val description = "Please try again later."
}
class NoUserFoundHandlerNetwork : NetworkResponseProcessor(API_ERROR_NO_USER_FOUND) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_ERROR_NO_USER_FOUND,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_NOT_FOUND,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "You have been logged out"
override val description = "Please try again"
}
class PeerUnverifiedErrorHandlerNetwork : NetworkResponseProcessor(API_ERROR_PEER_UNVERIFIED) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
fetchNewKeyFromFirebaseAndRestart()
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_ERROR_PEER_UNVERIFIED,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_ERROR_PEER_UNVERIFIED,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Peer unverified"
override val description = "Please try again"
}
class SocketTimeoutErrorHandlerNetwork: NetworkResponseProcessor(API_CODE_SOCKET_TIMEOUT) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_CODE_SOCKET_TIMEOUT,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_CODE_SOCKET_TIMEOUT,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Internet too slow"
override val description = "Please try again"
}
class SuccessHandlerNetwork : NetworkResponseProcessor(API_SUCCESS_CODE) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = response.body()?.data,
error = null,
statusCode = API_SUCCESS_CODE,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = null
override val description = null
}
class SSLHandshakeExceptionHandlerNetwork : NetworkResponseProcessor(API_CODE_SSL_HANDSHAKE_EXCEPTION) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_CODE_SSL_HANDSHAKE_EXCEPTION,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_CODE_SSL_HANDSHAKE_EXCEPTION,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "SSL Handshake Exception"
override val description = "Please try again"
}
class JsonParseExceptionHandlerNetwork : NetworkResponseProcessor(API_WRONG_ERROR_RESPONSE) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_WRONG_ERROR_RESPONSE,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_WRONG_ERROR_RESPONSE,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Something went wrong"
override val description = "Please try again"
}
class UnknownHostExceptionHandlerNetwork : NetworkResponseProcessor(API_CODE_UNKNOWN_HOST) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = API_CODE_UNKNOWN_HOST,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = API_CODE_UNKNOWN_HOST,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Something went wrong"
override val description = "Please try again"
}
class IOExceptionHandlerNetwork : NetworkResponseProcessor(IO_EXCEPTION_ERROR) {
override fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return RepoResult(
data = null,
error = ErrorMessage(
message = message,
description = description,
statusCode = IO_EXCEPTION_ERROR,
appRequestId = getRequestIdFromResponse(response),
vertical = getVerticalFromResponse(response)
),
statusCode = IO_EXCEPTION_ERROR,
warning = response.body()?.warning,
errors = response.body()?.errors
)
}
override val message = "Something went wrong"
override val description = "Please try again"
}

View File

@@ -0,0 +1,13 @@
package com.navi.rr.network.retrofit
import com.navi.common.network.models.GenericResponse
import com.navi.common.network.models.RepoResult
import com.navi.rr.network.response.handlers.chains.rrNetworkProcessorChain
import retrofit2.Response
import javax.inject.Inject
open class ResponseHandler @Inject constructor() {
open fun <T> handleResponse(response: Response<GenericResponse<T>>): RepoResult<T> {
return rrNetworkProcessorChain().handleResponse(response)
}
}

View File

@@ -12,5 +12,6 @@ import androidx.annotation.Keep
@Keep
object ApiConstants {
const val API_CONNECT_TIMEOUT_VALUE = 20L
const val API_SUCCESS_CODE = 200
}
const val API_EVENT_NAME = "dev_api_metric_rr"
const val API_STATUS_CODE = "status_code"
}

View File

@@ -7,8 +7,13 @@
package com.navi.rr.network.util
import com.navi.analytics.utils.NaviTrackEvent
import com.navi.common.CommonLibManager
import com.navi.common.model.NetworkInfo
import com.navi.common.utils.Constants.API_ENDPOINT
import com.navi.rr.network.util.ApiConstants.API_EVENT_NAME
import com.navi.rr.network.util.ApiConstants.API_STATUS_CODE
import retrofit2.Response
fun getNetworkInfo(timeOutInSeconds: Long = ApiConstants.API_CONNECT_TIMEOUT_VALUE): NetworkInfo {
return NetworkInfo(
@@ -31,3 +36,16 @@ fun getNetworkInfoSuperApp(
baseUrl = CommonLibManager.buildConfigDetails.baseUrl
)
}
fun trackApiEvent(
response: Response<*>,
responseCode: Int,
) {
NaviTrackEvent.trackEventOnClickStream(
eventName = API_EVENT_NAME,
mapOf(
Pair(API_ENDPOINT, response.raw().request.url.toString()),
Pair(API_STATUS_CODE, responseCode.toString())
)
)
}

View File

@@ -11,15 +11,17 @@ import com.navi.common.forge.model.ScreenDefinition
import com.navi.common.model.ModuleName
import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.common.constants.FORGE_REFEREE_TRACKER_SCREEN
import com.navi.rr.common.constants.FORGE_REFEREE_TRACKER_SCREEN_V2
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import javax.inject.Inject
class RefereeTrackerRepo @Inject constructor(@SuperAppRetrofitForRR private val retrofitService: RetrofitService) :
ResponseCallback() {
class RefereeTrackerRepo @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun postRefereeToReminder(refereeID: String) {
retrofitService.postRefereeToReminder(
@@ -31,7 +33,7 @@ class RefereeTrackerRepo @Inject constructor(@SuperAppRetrofitForRR private val
suspend fun fetchRefereeTrackerDetails(
pageNo: Int,
pageSize: Int
) = apiResponseCallback(
) = responseHandler.handleResponse(
retrofitService.fetchRefereeTrackerDetails(
pageNo = pageNo,
pageSize = pageSize,
@@ -41,7 +43,7 @@ class RefereeTrackerRepo @Inject constructor(@SuperAppRetrofitForRR private val
suspend fun fetchRefereeTrackerDetailsV3(
pageNo: Int,
pageSize: Int
) = apiResponseCallback(
) = responseHandler.handleResponse(
retrofitService.fetchRefereeTrackerDetailsV3(
pageNo = pageNo,
pageSize = pageSize,
@@ -50,7 +52,7 @@ class RefereeTrackerRepo @Inject constructor(@SuperAppRetrofitForRR private val
)
suspend fun fetchRefereeTrackerForgeElement(): RepoResult<ScreenDefinition> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
target = ModuleNameV2.FORGE.name,
screenId = FORGE_REFEREE_TRACKER_SCREEN
@@ -59,7 +61,7 @@ class RefereeTrackerRepo @Inject constructor(@SuperAppRetrofitForRR private val
}
suspend fun fetchRefereeTrackerV2ForgeElement(): RepoResult<ScreenDefinition> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
target = ModuleNameV2.FORGE.name,
screenId = FORGE_REFEREE_TRACKER_SCREEN_V2

View File

@@ -10,22 +10,24 @@ package com.navi.rr.referral.repo
import com.navi.common.forge.model.ScreenDefinition
import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.common.constants.FORGE_REFERRAL_HOME_SCREEN
import com.navi.rr.leaderboard.utils.Constants
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import com.navi.rr.utils.ReferralHomeConstants.REFERRAL_POPUP_SCREEN
import javax.inject.Inject
class ReferralHomeRepo @Inject constructor(@SuperAppRetrofitForRR private val superAppRetrofitService: RetrofitService) :
ResponseCallback() {
class ReferralHomeRepo @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchReferralDetails() =
apiResponseCallback(superAppRetrofitService.getReferralDetails())
responseHandler.handleResponse(retrofitService.getReferralDetails())
suspend fun fetchReferralForgeScreen(): RepoResult<ScreenDefinition> {
return apiResponseCallback(
superAppRetrofitService.fetchForgeScreen(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
target = ModuleNameV2.FORGE.name,
screenId = FORGE_REFERRAL_HOME_SCREEN
)
@@ -33,8 +35,8 @@ class ReferralHomeRepo @Inject constructor(@SuperAppRetrofitForRR private val su
}
suspend fun fetchReferralPopupScreen(): RepoResult<ScreenDefinition> {
return apiResponseCallback(
superAppRetrofitService.fetchForgeScreen(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
target = ModuleNameV2.FORGE.name,
screenId = REFERRAL_POPUP_SCREEN
)
@@ -42,8 +44,8 @@ class ReferralHomeRepo @Inject constructor(@SuperAppRetrofitForRR private val su
}
suspend fun fetchLeaderboardPopUp(): RepoResult<ScreenDefinition> {
return apiResponseCallback(
superAppRetrofitService.fetchForgeScreen(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
target = ModuleNameV2.FORGE.name,
screenId = Constants.REFERRAL_LEADERBOARD_GRATIFICATION_SCREEN
)

View File

@@ -67,8 +67,8 @@ import com.navi.design.R as DesignR
@Composable
fun NaviReferralErrorScreen(
title: String = ERROR_TITLE,
subtitle: String = ERROR_SUBTITLE,
title: String? = ERROR_TITLE,
subtitle: String? = ERROR_SUBTITLE,
buttonText: String = ERROR_BUTTON_TEXT,
errorImage: Int = R.drawable.something_went_wrong_triangle,
retry: (() -> Unit)? = null
@@ -86,7 +86,7 @@ fun NaviReferralErrorScreen(
modifier = Modifier.size(160.dp)
)
Text(
text = title,
text = title ?: ERROR_TITLE,
style =
TextStyle(
fontSize = 14.sp,
@@ -99,7 +99,7 @@ fun NaviReferralErrorScreen(
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = subtitle,
text = subtitle ?: ERROR_SUBTITLE,
style =
TextStyle(
fontSize = 12.sp,

View File

@@ -91,6 +91,11 @@ import com.navi.rr.referral.viewmodels.RefereeTrackerScreenState
import com.navi.rr.referral.viewmodels.RefereeTrackerVM
import com.navi.rr.utils.Constants.CLOSE_SHEET
import com.navi.rr.utils.Constants.GENERIC_SHARE
import com.navi.rr.utils.NaviRRAnalytics
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFEREE_TRACKER_PAGE_LOAD_ERROR
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFEREE_TRACKER_SCREEN
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFEREE_TRACKER_SCROLL_ERROR
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFERRAL_REMIND_CTA_CLICK
import com.navi.rr.utils.RefereeTrackerConstants.BLOCKED_BOTTOM_BOTTOMSHEET
import com.navi.rr.utils.RefereeTrackerConstants.BLOCKED_TOP_BOTTOMSHEET
import com.navi.rr.utils.RefereeTrackerConstants.BLOCKED_TOP_CASH_BOTTOMSHEET
@@ -107,11 +112,6 @@ import com.navi.rr.utils.RefereeTrackerConstants.NOT_STARTED_TOP_BOTTOMSHEET
import com.navi.rr.utils.RefereeTrackerConstants.NOT_STARTED_TOP_CASH_BOTTOMSHEET
import com.navi.rr.utils.RefereeTrackerConstants.REFEREE_TRACKER_BOTTOMSHEET_EARNINGS_KEY
import com.navi.rr.utils.RefereeTrackerConstants.REFEREE_TRACKER_BOTTOMSHEET_NAME_KEY
import com.navi.rr.utils.NaviRRAnalytics
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFEREE_TRACKER_PAGE_LOAD_ERROR
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFEREE_TRACKER_SCREEN
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFEREE_TRACKER_SCROLL_ERROR
import com.navi.rr.utils.NaviRRAnalytics.Companion.REFERRAL_REMIND_CTA_CLICK
import com.navi.rr.utils.clickable
import com.navi.rr.utils.formatIndianNumberingWithoutShortening
import com.navi.rr.utils.maskNumber

View File

@@ -1,6 +1,5 @@
package com.navi.rr.referral.ui.compose
import android.app.Activity
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.LocalOverscrollConfiguration

View File

@@ -61,6 +61,7 @@ import com.navi.rr.R
import com.navi.rr.referral.models.ReferralContact
import com.navi.rr.referral.viewmodels.ReferralContactsBottomSheetVM
import com.navi.rr.utils.Constants
import com.navi.rr.utils.NaviRRAnalytics
import com.navi.rr.utils.ReferralContactBottomSheetConstants.CONTACT_NUMBER_LENGTH
import com.navi.rr.utils.ReferralContactBottomSheetConstants.CONTACT_NUMBER_LENGTH_WITH_COUNTRY_CODE
import com.navi.rr.utils.ReferralContactBottomSheetConstants.CONTACT_NUMBER_LENGTH_WITH_ZERO
@@ -68,7 +69,6 @@ import com.navi.rr.utils.ReferralContactBottomSheetConstants.INITIALS_MAX_LENGTH
import com.navi.rr.utils.ReferralContactBottomSheetConstants.NUMBER_REGEX_WITHOUT_COUNTRY_CODE
import com.navi.rr.utils.ReferralContactBottomSheetConstants.NUMBER_REGEX_WITH_COUNTRY_CODE
import com.navi.rr.utils.ReferralContactBottomSheetConstants.NUMBER_REGEX_WITH_ZERO
import com.navi.rr.utils.NaviRRAnalytics
import com.navi.rr.utils.isAppInstalled
import co.hyperverge.hypersnapsdk.R as HyperSnapR
import com.navi.common.R as CommonR

View File

@@ -9,24 +9,24 @@ package com.navi.rr.rewards.repo
import com.navi.common.model.ModuleName
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import com.navi.rr.rewards.models.RewardsDashboardResponse
import javax.inject.Inject
class RewardDashboardRepository
@Inject
constructor(@SuperAppRetrofitForRR private val superAppRetrofitService: RetrofitService) :
ResponseCallback() {
class RewardDashboardRepository @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchRewardDashboardData(
density: String,
connectivityType: String,
selectedTabPosition: String
): RepoResult<RewardsDashboardResponse> =
apiResponseCallback(
superAppRetrofitService.fetchRewardsDashboardDetails(
responseHandler.handleResponse(
retrofitService.fetchRewardsDashboardDetails(
deviceDensity = density,
connectivityType = connectivityType,
selectedTabPosition = selectedTabPosition
@@ -34,11 +34,11 @@ constructor(@SuperAppRetrofitForRR private val superAppRetrofitService: Retrofit
)
suspend fun fetchABExperiment(experimentName: String) =
superAppRetrofitService.fetchABExperiment(experimentName, ModuleName.LITMUS.name)
retrofitService.fetchABExperiment(experimentName, ModuleName.LITMUS.name)
suspend fun fetchRewardsCSATResponse(featureName: String?, productId: String?) =
apiResponseCallback(
superAppRetrofitService.fetchRewardsCsatResponse(
responseHandler.handleResponse(
retrofitService.fetchRewardsCsatResponse(
featureName = featureName,
productId = productId
)

View File

@@ -9,15 +9,17 @@ package com.navi.rr.rewards.repo
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import com.navi.rr.rewards.models.RewardInfoResponse
import com.navi.rr.utils.Constants
import javax.inject.Inject
class RewardInfoRepository @Inject constructor(@SuperAppRetrofitForRR private val retrofitService: RetrofitService) :
ResponseCallback() {
class RewardInfoRepository @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchInfoCards(
context: String,
@@ -25,9 +27,9 @@ class RewardInfoRepository @Inject constructor(@SuperAppRetrofitForRR private va
queryParams: HashMap<String, String> = HashMap()
): RepoResult<RewardInfoResponse> {
return if (version == Constants.V2) {
apiResponseCallback(retrofitService.fetchRewardsInfoDetailsV2(queryParams = queryParams))
responseHandler.handleResponse(retrofitService.fetchRewardsInfoDetailsV2(queryParams = queryParams))
} else {
apiResponseCallback(retrofitService.fetchRewardsInfoDetails(context = context))
responseHandler.handleResponse(retrofitService.fetchRewardsInfoDetails(context = context))
}
}
}

View File

@@ -8,18 +8,18 @@
package com.navi.rr.rewards.repo
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.common.models.RRWidgetResponse
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import javax.inject.Inject
class RewardProductRepository
@Inject
constructor(@SuperAppRetrofitForRR private val superAppRetrofitService: RetrofitService) :
ResponseCallback() {
class RewardProductRepository @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchProductItems(): RepoResult<RRWidgetResponse> =
apiResponseCallback(superAppRetrofitService.fetchRewardsHistoryDetails())
responseHandler.handleResponse(retrofitService.fetchRewardsHistoryDetails())
}

View File

@@ -8,14 +8,15 @@
package com.navi.rr.rewards.repo
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import javax.inject.Inject
class RewardSummaryRepository @Inject constructor(@SuperAppRetrofitForRR private val retrofitService: RetrofitService) :
ResponseCallback() {
class RewardSummaryRepository @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchRewardItems() =
apiResponseCallback(retrofitService.fetchRewardsSummary())
responseHandler.handleResponse(retrofitService.fetchRewardsSummary())
}

View File

@@ -1,17 +0,0 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.rr.rewards.repo
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.network.retrofit.RetrofitService
import javax.inject.Inject
class RewardsRepo @Inject constructor(
private val retrofitService: RetrofitService
) : ResponseCallback() {
}

View File

@@ -11,21 +11,24 @@ import com.navi.common.forge.model.ScreenDefinition
import com.navi.common.model.ModuleName
import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.leaderboard.utils.Constants.REWARDS_SCRATCH_CARD_SCREEN
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import com.navi.rr.scratchcard.model.ScratchCardNudgeResponse
import com.navi.rr.scratchcard.model.ScratchCardResponse
import javax.inject.Inject
class ScratchCardRepo @Inject constructor(private val retrofitService: RetrofitService) :
ResponseCallback() {
class ScratchCardRepo @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun getNudgeRewardObjective(
product: String,
objective: String
): RepoResult<ScratchCardNudgeResponse> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.getNudgeRewardObjective(
product = product,
objective = objective,
@@ -35,7 +38,7 @@ class ScratchCardRepo @Inject constructor(private val retrofitService: RetrofitS
}
suspend fun getNudgeRewardInfo(eventId: String): RepoResult<ScratchCardResponse> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.getNudgeRewardInfo(
eventId = eventId,
target = ModuleName.REWARDS.name
@@ -47,7 +50,7 @@ class ScratchCardRepo @Inject constructor(private val retrofitService: RetrofitS
}
suspend fun fetchScratchCardTemplate() : RepoResult<ScreenDefinition> {
return apiResponseCallback(
return responseHandler.handleResponse(
retrofitService.fetchForgeScreen(
screenId = REWARDS_SCRATCH_CARD_SCREEN,
target = ModuleNameV2.FORGE.name,

View File

@@ -9,23 +9,24 @@ package com.navi.rr.tds.repo
import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import com.navi.rr.tds.models.KycCheckPollingConfigResponse
import com.navi.rr.tds.models.KycCheckPollingResponse
import com.navi.rr.tds.models.TdsKycVerifyRequest
import javax.inject.Inject
class TdsRepository @Inject constructor(@SuperAppRetrofitForRR private val superAppRetrofitService: RetrofitService) :
ResponseCallback() {
class TdsRepository @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchTdsScreenDetails(source: String) =
apiResponseCallback(superAppRetrofitService.fetchTdsScreenDetails(source))
responseHandler.handleResponse(retrofitService.fetchTdsScreenDetails(source))
suspend fun fetchTDSKycVerifyPollingConfig(kycVerifyRequest: TdsKycVerifyRequest?): RepoResult<KycCheckPollingConfigResponse> {
return apiResponseCallback(
superAppRetrofitService.getKycVerifyPollingDetails(
return responseHandler.handleResponse(
retrofitService.getKycVerifyPollingDetails(
kycVerifyRequest,
ModuleNameV2.REWARDS.name
)
@@ -33,6 +34,6 @@ class TdsRepository @Inject constructor(@SuperAppRetrofitForRR private val super
}
suspend fun pollKycVerificationStatus(requestId: String): RepoResult<KycCheckPollingResponse> {
return apiResponseCallback(superAppRetrofitService.pollKycVerificationStatus(requestId))
return responseHandler.handleResponse(retrofitService.pollKycVerificationStatus(requestId))
}
}

View File

@@ -7,29 +7,30 @@
package com.navi.rr.upi.repo
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.rr.network.di.SuperAppRetrofitForRR
import com.navi.rr.network.retrofit.ResponseHandler
import com.navi.rr.network.retrofit.RetrofitService
import com.navi.rr.upi.models.RegisterUpiRequestModel
import javax.inject.Inject
class UpiRepository @Inject constructor(@SuperAppRetrofitForRR private val superAppRetrofitService: RetrofitService) :
ResponseCallback() {
class UpiRepository @Inject constructor(
private val responseHandler: ResponseHandler,
@SuperAppRetrofitForRR private val retrofitService: RetrofitService,
) {
suspend fun fetchUpiScreenDetails(source: String) =
apiResponseCallback(superAppRetrofitService.fetchUpiScreenDetails(source))
responseHandler.handleResponse(retrofitService.fetchUpiScreenDetails(source))
suspend fun fetchUpiValidation(upiId: String, source: String) =
apiResponseCallback(
superAppRetrofitService.fetchUpiValidation(
responseHandler.handleResponse(
retrofitService.fetchUpiValidation(
upiId = upiId,
source = source
)
)
suspend fun registerUpi(upiId: String, customerId: String, source: String) =
apiResponseCallback(
superAppRetrofitService.registerUpi(
responseHandler.handleResponse(
retrofitService.registerUpi(
registerUpiRequest = RegisterUpiRequestModel(
upiId = upiId,
customerId = customerId,

View File

@@ -1,47 +0,0 @@
package com.navi.rr.rewards.repo
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.navi.rr.common.TestDispatcher
import com.navi.rr.network.retrofit.RetrofitService
import io.mockk.MockKAnnotations
import io.mockk.impl.annotations.RelaxedMockK
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
class RewardsRepoTest {
// Mock the RetrofitService dependency
@RelaxedMockK
private lateinit var retrofitService: RetrofitService
// Create an instance of RewardsRepo
private lateinit var rewardsRepo: RewardsRepo
@get:Rule
var rule: TestRule = InstantTaskExecutorRule()
@InternalCoroutinesApi
lateinit var testDispatcher: TestDispatcher
@OptIn(InternalCoroutinesApi::class)
@Before
fun setUp() {
// Initialize Mockito annotations
MockKAnnotations.init(this, relaxUnitFun = true)
testDispatcher = TestDispatcher()
// Create an instance of RewardsRepo with the mocked RetrofitService
rewardsRepo = RewardsRepo(retrofitService)
}
@OptIn(InternalCoroutinesApi::class)
@Test
fun testSomeFunctionInRepo() = runBlocking(testDispatcher) {
assert(true)
}
}