Skip to content

Commit 4d7effa

Browse files
authored
Merge pull request #592 from intercom/vinesh/sample_app_update
Vinesh/sample app update
2 parents 5829c56 + 69978b8 commit 4d7effa

File tree

13 files changed

+366
-200
lines changed

13 files changed

+366
-200
lines changed

sample/.idea/gradle.xml

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sample/app/build.gradle

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,28 @@ android {
4343
excludes += '/META-INF/{AL2.0,LGPL2.1}'
4444
}
4545
}
46+
namespace 'com.intercom.sample'
4647
}
4748

4849
dependencies {
49-
implementation 'androidx.core:core-ktx:1.7.0'
50+
implementation 'androidx.core:core-ktx:1.9.0'
5051
implementation "androidx.compose.ui:ui:$compose_version"
5152
implementation "androidx.compose.material:material:$compose_version"
5253
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
53-
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
54-
implementation 'androidx.activity:activity-compose:1.3.1'
55-
implementation("androidx.navigation:navigation-compose:2.4.1")
54+
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
55+
implementation 'androidx.activity:activity-compose:1.6.1'
56+
implementation("androidx.navigation:navigation-compose:2.5.3")
57+
58+
implementation "com.google.accompanist:accompanist-flowlayout:0.27.0"
59+
5660
implementation("androidx.datastore:datastore-preferences:1.0.0")
5761

5862
implementation("io.intercom.android:intercom-sdk:14.0.0")
59-
implementation("com.google.firebase:firebase-messaging:20.2.+")
63+
implementation("com.google.firebase:firebase-messaging:23.1.0")
6064

6165
testImplementation 'junit:junit:4.13.2'
6266
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
6367
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
6468
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
6569
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
66-
}
70+
}

sample/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
package="com.intercom.sample">
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
43

54
<uses-permission android:name="android.permission.INTERNET"/>
65
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
@@ -27,4 +26,4 @@
2726
</activity>
2827
</application>
2928

30-
</manifest>
29+
</manifest>
Lines changed: 30 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,65 @@
11
package com.intercom.sample
22

3-
import android.content.Context
43
import android.os.Bundle
4+
import android.widget.Toast
55
import androidx.activity.ComponentActivity
66
import androidx.activity.compose.setContent
7-
import androidx.compose.foundation.layout.fillMaxSize
8-
import androidx.compose.material.MaterialTheme
9-
import androidx.compose.material.Surface
10-
import androidx.compose.runtime.collectAsState
11-
import androidx.compose.runtime.rememberCoroutineScope
7+
import androidx.activity.viewModels
8+
import androidx.compose.foundation.layout.padding
9+
import androidx.compose.material.Scaffold
10+
import androidx.compose.runtime.LaunchedEffect
1211
import androidx.compose.ui.Modifier
13-
import androidx.datastore.preferences.core.booleanPreferencesKey
14-
import androidx.datastore.preferences.core.edit
15-
import androidx.datastore.preferences.preferencesDataStore
16-
import androidx.lifecycle.lifecycleScope
1712
import androidx.navigation.compose.NavHost
1813
import androidx.navigation.compose.composable
1914
import androidx.navigation.compose.rememberNavController
2015
import com.intercom.sample.screens.HomeScreen
2116
import com.intercom.sample.screens.UserDetailsScreen
2217
import com.intercom.sample.ui.theme.SampleTheme
23-
import io.intercom.android.sdk.Intercom
24-
import kotlinx.coroutines.flow.Flow
25-
import kotlinx.coroutines.flow.collect
26-
import kotlinx.coroutines.flow.map
27-
import kotlinx.coroutines.launch
28-
29-
private val Context.dataStore by preferencesDataStore("settings")
3018

3119
class MainActivity : ComponentActivity() {
32-
private val USER_REGISTERED = booleanPreferencesKey("user_registered")
20+
private val vm: MainVm by viewModels(factoryProducer = { MainVm.getVmFactory(dataStore) })
3321

3422
override fun onCreate(savedInstanceState: Bundle?) {
3523
super.onCreate(savedInstanceState)
36-
37-
val registrationStatusFlow: Flow<Boolean> = dataStore.data.map { preferences ->
38-
preferences[USER_REGISTERED] ?: false
39-
}
40-
41-
lifecycleScope.launch {
42-
registrationStatusFlow.collect {
43-
if (it) {
44-
Intercom.client().setLauncherVisibility(Intercom.VISIBLE)
45-
} else {
46-
Intercom.client().setLauncherVisibility(Intercom.GONE)
24+
setContent {
25+
LaunchedEffect(key1 = "") {
26+
vm.effects.collect {
27+
when (it) {
28+
is MainEffects.ShowToast -> Toast.makeText(
29+
applicationContext,
30+
it.message,
31+
Toast.LENGTH_LONG
32+
).show()
33+
}
4734
}
4835
}
49-
}
50-
51-
setContent {
5236
SampleTheme {
5337
val navController = rememberNavController()
54-
55-
Surface(
56-
modifier = Modifier.fillMaxSize(),
57-
color = MaterialTheme.colors.background
58-
) {
59-
NavHost(navController = navController, startDestination = "home") {
38+
Scaffold {
39+
NavHost(
40+
modifier = Modifier.padding(it),
41+
navController = navController,
42+
startDestination = "home"
43+
) {
6044
composable("home") {
61-
val rememberCoroutineScope = rememberCoroutineScope()
62-
val userRegistrationsStatus =
63-
registrationStatusFlow.collectAsState(initial = false)
64-
6545
HomeScreen(
46+
vm = vm,
6647
onUserEditorLaunched = {
6748
navController.navigate("user_editor")
6849
},
69-
currentRegistrationStatus = userRegistrationsStatus.value,
70-
toggleRegistrationStatus = {
71-
rememberCoroutineScope.launch { saveRegistrationStatus(it) }
72-
})
50+
)
7351
}
7452
composable("user_editor") {
75-
UserDetailsScreen(onUserDetailsSaved = {
76-
navController.popBackStack()
77-
})
53+
UserDetailsScreen(
54+
onUserDetailsSaved = { userAttrib ->
55+
vm.updateUser(userAttrib)
56+
navController.popBackStack()
57+
}
58+
)
7859
}
7960
}
8061
}
8162
}
8263
}
8364
}
84-
85-
suspend fun saveRegistrationStatus(status: Boolean) {
86-
dataStore.edit { preferences ->
87-
preferences[USER_REGISTERED] = status
88-
}
89-
}
9065
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.intercom.sample
2+
3+
import android.content.Context
4+
import androidx.datastore.core.DataStore
5+
import androidx.datastore.preferences.core.Preferences
6+
import androidx.datastore.preferences.core.booleanPreferencesKey
7+
import androidx.datastore.preferences.core.edit
8+
import androidx.datastore.preferences.preferencesDataStore
9+
import androidx.lifecycle.ViewModel
10+
import androidx.lifecycle.ViewModelProvider
11+
import androidx.lifecycle.viewModelScope
12+
import com.intercom.sample.components.SelfServeAlertDialogController
13+
import io.intercom.android.sdk.Intercom
14+
import io.intercom.android.sdk.IntercomContent
15+
import io.intercom.android.sdk.IntercomError
16+
import io.intercom.android.sdk.IntercomSpace
17+
import io.intercom.android.sdk.IntercomStatusCallback
18+
import io.intercom.android.sdk.UserAttributes
19+
import io.intercom.android.sdk.identity.Registration
20+
import kotlinx.coroutines.flow.Flow
21+
import kotlinx.coroutines.flow.MutableSharedFlow
22+
import kotlinx.coroutines.flow.asSharedFlow
23+
import kotlinx.coroutines.flow.map
24+
import kotlinx.coroutines.launch
25+
26+
val Context.dataStore by preferencesDataStore("settings")
27+
28+
class MainVm(private val prefDataStore: DataStore<Preferences>) : ViewModel(), SelfServeActions {
29+
val dialogController = SelfServeAlertDialogController()
30+
private val keyUserRegistered = booleanPreferencesKey("user_registered")
31+
32+
val userRegistrationStatus: Flow<Boolean> = prefDataStore.data.map { preferences ->
33+
preferences[keyUserRegistered] ?: false
34+
}
35+
36+
private val _effects = MutableSharedFlow<MainEffects>()
37+
val effects = _effects.asSharedFlow()
38+
39+
private val userRegistrationCallback = object : IntercomStatusCallback {
40+
override fun onFailure(intercomError: IntercomError) {
41+
setUserRegistrationStatus(false)
42+
showToast(intercomError.errorMessage)
43+
}
44+
45+
override fun onSuccess() {
46+
setUserRegistrationStatus(true)
47+
showToast("User Registered")
48+
}
49+
}
50+
51+
init {
52+
viewModelScope.launch {
53+
userRegistrationStatus.collect { userRegistered ->
54+
Intercom.client().setLauncherVisibility(
55+
if (userRegistered) Intercom.VISIBLE else Intercom.GONE
56+
)
57+
}
58+
}
59+
}
60+
61+
fun loginIdentifiedUserWithId(id: String) {
62+
Intercom.client().loginIdentifiedUser(
63+
userRegistration = Registration().withUserId(id),
64+
intercomStatusCallback = userRegistrationCallback
65+
)
66+
}
67+
68+
fun loginIdentifiedUserWithEmail(email: String) {
69+
Intercom.client().loginIdentifiedUser(
70+
userRegistration = Registration().withEmail(email),
71+
intercomStatusCallback = userRegistrationCallback
72+
)
73+
}
74+
75+
fun loginUnidentifiedUser() {
76+
Intercom.client().loginUnidentifiedUser(
77+
intercomStatusCallback = userRegistrationCallback
78+
)
79+
}
80+
81+
fun logout() {
82+
Intercom.client().logout()
83+
setUserRegistrationStatus(false)
84+
}
85+
86+
override fun openMessage() = Intercom.client().present(IntercomSpace.Messages)
87+
override fun openHelpCenter() = Intercom.client().present(IntercomSpace.HelpCenter)
88+
override fun showArticle() {
89+
dialogController.show("Article id") {
90+
Intercom.client().presentContent(IntercomContent.Article(id = it))
91+
}
92+
}
93+
94+
override fun showCarousel() {
95+
dialogController.show("Carousel id") {
96+
Intercom.client().presentContent(IntercomContent.Carousel(id = it))
97+
}
98+
}
99+
100+
override fun showSurvey() {
101+
dialogController.show("Survey id") {
102+
Intercom.client().presentContent(IntercomContent.Survey(id = it))
103+
}
104+
}
105+
106+
override fun showCollections() {
107+
dialogController.show("Collection ids") {
108+
Intercom.client()
109+
.presentContent(IntercomContent.HelpCenterCollections(ids = it.split(",")))
110+
}
111+
}
112+
113+
fun updateUser(userAttributes: UserAttributes) {
114+
Intercom.client().updateUser(userAttributes)
115+
}
116+
117+
fun setUserRegistrationStatus(status: Boolean) {
118+
viewModelScope.launch {
119+
prefDataStore.edit { preferences -> preferences[keyUserRegistered] = status }
120+
}
121+
}
122+
123+
private fun showToast(message: String) {
124+
viewModelScope.launch {
125+
_effects.emit(MainEffects.ShowToast(message))
126+
}
127+
}
128+
129+
companion object {
130+
fun getVmFactory(dataStore: DataStore<Preferences>): ViewModelProvider.Factory =
131+
object : ViewModelProvider.Factory {
132+
@Suppress("UNCHECKED_CAST")
133+
override fun <T : ViewModel> create(
134+
modelClass: Class<T>
135+
): T {
136+
return MainVm(dataStore) as T
137+
}
138+
}
139+
}
140+
141+
}
142+
143+
interface SelfServeActions {
144+
fun openMessage()
145+
fun openHelpCenter()
146+
fun showArticle()
147+
fun showCarousel()
148+
fun showSurvey()
149+
fun showCollections()
150+
}
151+
152+
sealed class MainEffects {
153+
data class ShowToast(val message: String) : MainEffects()
154+
}

0 commit comments

Comments
 (0)