Skip to content

Commit

Permalink
Merge branch 'main' into rehan/push-click-behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
mrehan27 committed Oct 30, 2023
2 parents bc3d262 + 4a4d885 commit a695cf7
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 25 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## [3.7.0](https://github.com/customerio/customerio-android/compare/3.6.7...3.7.0) (2023-10-25)


### Features

* persistant in-app messages ([#269](https://github.com/customerio/customerio-android/issues/269)) ([4fcb781](https://github.com/customerio/customerio-android/commit/4fcb781a3cf1a0e3b1414a6096deac40495250eb))

## [3.6.7](https://github.com/customerio/customerio-android/compare/3.6.6...3.6.7) (2023-10-17)


Expand Down
1 change: 1 addition & 0 deletions messaginginapp/api/messaginginapp.api
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ public final class io/customer/messaginginapp/gist/presentation/GistSdk : androi
public static field dataCenter Ljava/lang/String;
public static field siteId Ljava/lang/String;
public final fun addListener (Lio/customer/messaginginapp/gist/presentation/GistListener;)V
public final fun clearCurrentMessage ()V
public final fun clearListeners ()V
public final fun clearUserToken ()V
public final fun dismissMessage ()V
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.customer.messaginginapp.gist.data.listeners

import android.content.Context
import android.util.Base64
import android.util.Log
import io.customer.messaginginapp.gist.data.NetworkUtilities
Expand All @@ -9,47 +10,94 @@ import io.customer.messaginginapp.gist.data.repository.GistQueueService
import io.customer.messaginginapp.gist.presentation.GIST_TAG
import io.customer.messaginginapp.gist.presentation.GistListener
import io.customer.messaginginapp.gist.presentation.GistSdk
import java.io.File
import java.util.regex.PatternSyntaxException
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class Queue : GistListener {

private var localMessageStore: MutableList<Message> = mutableListOf()
private val cacheMap = mutableMapOf<String, Response>()

init {
GistSdk.addListener(this)
}

private val cacheSize = 10 * 1024 * 1024 // 10 MB
private val cacheDirectory by lazy { File(GistSdk.application.cacheDir, "http_cache") }
private val cache by lazy { Cache(cacheDirectory, cacheSize.toLong()) }

private fun saveToPrefs(context: Context, key: String, value: String) {
val prefs = context.getSharedPreferences("network_cache", Context.MODE_PRIVATE)
prefs.edit().putString(key, value).apply()
}

Check warning on line 40 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt#L38-L40

Added lines #L38 - L40 were not covered by tests

private fun getFromPrefs(context: Context, key: String): String? {
val prefs = context.getSharedPreferences("network_cache", Context.MODE_PRIVATE)
return prefs.getString(key, null)

Check warning on line 44 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt#L43-L44

Added lines #L43 - L44 were not covered by tests
}

private val gistQueueService by lazy {
val httpClient: OkHttpClient = OkHttpClient.Builder()
.addInterceptor { chain ->
GistSdk.getUserToken()?.let { userToken ->
val request: Request = chain.request().newBuilder()
.addHeader(NetworkUtilities.CIO_SITE_ID_HEADER, GistSdk.siteId)
.addHeader(NetworkUtilities.CIO_DATACENTER_HEADER, GistSdk.dataCenter)
.addHeader(
NetworkUtilities.USER_TOKEN_HEADER,
// The NO_WRAP flag will omit all line terminators (i.e., the output will be on one long line).
Base64.encodeToString(userToken.toByteArray(), Base64.NO_WRAP)
)
.build()
// Interceptor to set up request headers like site ID, data center, and user token.
val httpClient: OkHttpClient =
OkHttpClient.Builder().cache(cache)
.addInterceptor { chain ->

Check warning on line 51 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt#L49-L51

Added lines #L49 - L51 were not covered by tests
val originalRequest = chain.request()

chain.proceed(request)
} ?: run {
val request: Request = chain.request().newBuilder()
val networkRequest = originalRequest.newBuilder()
.addHeader(NetworkUtilities.CIO_SITE_ID_HEADER, GistSdk.siteId)
.addHeader(NetworkUtilities.CIO_DATACENTER_HEADER, GistSdk.dataCenter)
.apply {
GistSdk.getUserToken()?.let { userToken ->
addHeader(
NetworkUtilities.USER_TOKEN_HEADER,
// The NO_WRAP flag will omit all line terminators (i.e., the output will be on one long line).
Base64.encodeToString(userToken.toByteArray(), Base64.NO_WRAP)
)
}
}
.header("Cache-Control", "no-cache")
.build()

chain.proceed(request)
val response = chain.proceed(networkRequest)

when (response.code) {
200 -> {
response.body?.let { responseBody ->
val responseBodyString = responseBody.string()
saveToPrefs(
GistSdk.application,
originalRequest.url.toString(),
responseBodyString
)
return@addInterceptor response.newBuilder().body(
responseBodyString.toResponseBody(responseBody.contentType())
).build()
}
}

304 -> {
val cachedResponse =
getFromPrefs(GistSdk.application, originalRequest.url.toString())
cachedResponse?.let {
return@addInterceptor response.newBuilder()
.body(it.toResponseBody(null)).code(200).build()
} ?: return@addInterceptor response
}

else -> return@addInterceptor response
}

response
}
}
.build()
.build()

Check warning on line 100 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/data/listeners/Queue.kt#L100

Added line #L100 was not covered by tests

Retrofit.Builder()
.baseUrl(GistSdk.gistEnvironment.getGistQueueApiUrl())
Expand All @@ -72,8 +120,6 @@ class Queue : GistListener {
try {
Log.i(GIST_TAG, "Fetching user messages")
val latestMessagesResponse = gistQueueService.fetchMessagesForUser()
// If there's no change (304), move on.
if (latestMessagesResponse.code() == 304) { return@launch }

// To prevent us from showing expired / revoked messages, clear user messages from local queue.
clearUserMessagesFromLocalStore()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class GistMessageProperties {
}
}
gistProperties["persistent"]?.let { id ->
(id as Boolean).let { persistentValue ->
(id as? Boolean)?.let { persistentValue ->
persistent = persistentValue
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.core.animation.doOnEnd
import com.google.gson.Gson
Expand Down Expand Up @@ -61,6 +62,12 @@ class GistModalActivity : AppCompatActivity(), GistListener, GistViewListener {
} ?: run {
finish()
}

// Update back button to handle in-app message behavior, disable back press for persistent messages, true otherwise
val onBackPressedCallback = object : OnBackPressedCallback(isPersistentMessage()) {
override fun handleOnBackPressed() {}

Check warning on line 68 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt#L67-L68

Added lines #L67 - L68 were not covered by tests
}
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)

Check warning on line 70 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt#L70

Added line #L70 was not covered by tests
}

override fun onResume() {
Expand Down Expand Up @@ -91,10 +98,21 @@ class GistModalActivity : AppCompatActivity(), GistListener, GistViewListener {

override fun onDestroy() {
GistSdk.removeListener(this)
GistSdk.dismissMessage()
// If the message is not persistent, dismiss it and inform the callback
if (!isPersistentMessage()) {
GistSdk.dismissMessage()

Check warning on line 103 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt#L103

Added line #L103 was not covered by tests
} else {
GistSdk.clearCurrentMessage()

Check warning on line 105 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt#L105

Added line #L105 was not covered by tests
}
super.onDestroy()
}

private fun isPersistentMessage(): Boolean = currentMessage?.let {
GistMessageProperties.getGistProperties(
it
).persistent
} ?: false

Check warning on line 114 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalActivity.kt#L111-L114

Added lines #L111 - L114 were not covered by tests

override fun onMessageShown(message: Message) {
runOnUiThread {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ internal class GistModalManager : GistListener {

internal fun showModalMessage(message: Message, position: MessagePosition? = null): Boolean {
currentMessage?.let { currentMessage ->
Log.i(GIST_TAG, "Message ${message.messageId} not shown, ${currentMessage.messageId} is already showing.")
Log.i(
GIST_TAG,
"Message ${message.messageId} not shown, ${currentMessage.messageId} is already showing."

Check warning on line 20 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalManager.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalManager.kt#L18-L20

Added lines #L18 - L20 were not covered by tests
)
return false
}

Expand Down Expand Up @@ -55,4 +58,8 @@ internal class GistModalManager : GistListener {
override fun onMessageShown(message: Message) {}

override fun onAction(message: Message, currentRoute: String, action: String, name: String) {}

internal fun clearCurrentMessage() {
currentMessage = null
}

Check warning on line 64 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalManager.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistModalManager.kt#L63-L64

Added lines #L63 - L64 were not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ object GistSdk : Application.ActivityLifecycleCallbacks {
gistModalManager.dismissActiveMessage()
}

fun clearCurrentMessage() {
gistModalManager.clearCurrentMessage()
}

Check warning on line 165 in messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistSdk.kt

View check run for this annotation

Codecov / codecov/patch

messaginginapp/src/main/java/io/customer/messaginginapp/gist/presentation/GistSdk.kt#L164-L165

Added lines #L164 - L165 were not covered by tests

// Listeners

fun addListener(listener: GistListener) {
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/main/java/io/customer/sdk/Version.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ package io.customer.sdk

internal object Version {

const val version: String = "3.6.7"
const val version: String = "3.7.0"
}

0 comments on commit a695cf7

Please sign in to comment.