Merge pull request #4122 from mhss1/main
Migrate deprecated Google SignIn + disable android backup
This commit is contained in:
@ -104,8 +104,9 @@ dependencies {
|
|||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
|
|
||||||
implementation(libs.gms.playServicesBase)
|
implementation(libs.androidx.credentials.auth)
|
||||||
implementation(libs.gms.playServicesAuth)
|
implementation(libs.androidx.credentials)
|
||||||
|
implementation(libs.googleid)
|
||||||
|
|
||||||
val bom = platform(libs.androidx.compose.bom)
|
val bom = platform(libs.androidx.compose.bom)
|
||||||
implementation(bom)
|
implementation(bom)
|
||||||
|
|||||||
5
android/Omnivore/app/proguard-rules.pro
vendored
5
android/Omnivore/app/proguard-rules.pro
vendored
@ -19,3 +19,8 @@
|
|||||||
# If you keep the line number information, uncomment this to
|
# If you keep the line number information, uncomment this to
|
||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
-if class androidx.credentials.CredentialManager
|
||||||
|
-keep class androidx.credentials.playservices.** {
|
||||||
|
*;
|
||||||
|
}
|
||||||
|
|||||||
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".OmnivoreApplication"
|
android:name=".OmnivoreApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="false"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="false"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
|||||||
@ -1,15 +1,9 @@
|
|||||||
package app.omnivore.omnivore.feature.library
|
package app.omnivore.omnivore.feature.library
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.content.pm.PackageManager.*
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.core.app.ActivityCompat
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
@ -39,7 +33,6 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.jar.Manifest
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|||||||
@ -35,9 +35,7 @@ import app.omnivore.omnivore.graphql.generated.ValidateUsernameQuery
|
|||||||
import app.omnivore.omnivore.utils.Constants
|
import app.omnivore.omnivore.utils.Constants
|
||||||
import app.omnivore.omnivore.utils.ResourceProvider
|
import app.omnivore.omnivore.utils.ResourceProvider
|
||||||
import com.apollographql.apollo3.ApolloClient
|
import com.apollographql.apollo3.ApolloClient
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
|
||||||
import com.google.android.gms.common.api.ApiException
|
|
||||||
import com.google.android.gms.tasks.Task
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import io.intercom.android.sdk.Intercom
|
import io.intercom.android.sdk.Intercom
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@ -359,9 +357,8 @@ class OnboardingViewModel @Inject constructor(
|
|||||||
setErrorMessage(resourceProvider.getString(R.string.login_view_model_google_auth_error_msg))
|
setErrorMessage(resourceProvider.getString(R.string.login_view_model_google_auth_error_msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleGoogleAuthTask(task: Task<GoogleSignInAccount>) {
|
fun handleGoogleAuthCredential(credential: GoogleIdTokenCredential) {
|
||||||
val result = task.getResult(ApiException::class.java)
|
val googleIdToken = credential.idToken
|
||||||
val googleIdToken = result?.idToken ?: ""
|
|
||||||
|
|
||||||
// If token is missing then set the error message
|
// If token is missing then set the error message
|
||||||
if (googleIdToken.isEmpty()) {
|
if (googleIdToken.isEmpty()) {
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -27,28 +26,25 @@ import app.omnivore.omnivore.feature.onboarding.OnboardingViewModel
|
|||||||
import app.omnivore.omnivore.feature.onboarding.auth.provider.AppleAuthButton
|
import app.omnivore.omnivore.feature.onboarding.auth.provider.AppleAuthButton
|
||||||
import app.omnivore.omnivore.feature.onboarding.auth.provider.GoogleAuthButton
|
import app.omnivore.omnivore.feature.onboarding.auth.provider.GoogleAuthButton
|
||||||
import app.omnivore.omnivore.navigation.Routes
|
import app.omnivore.omnivore.navigation.Routes
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AuthProviderScreen(
|
fun AuthProviderScreen(
|
||||||
welcomeNavController: NavHostController,
|
welcomeNavController: NavHostController,
|
||||||
viewModel: OnboardingViewModel
|
viewModel: OnboardingViewModel
|
||||||
) {
|
) {
|
||||||
val isGoogleAuthAvailable: Boolean =
|
|
||||||
GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(LocalContext.current) == 0
|
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
modifier = Modifier.fillMaxWidth().padding(bottom = 64.dp)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(bottom = 64.dp)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier.width(500.dp)
|
modifier = Modifier.width(500.dp)
|
||||||
) {
|
) {
|
||||||
if (isGoogleAuthAvailable) {
|
GoogleAuthButton(viewModel)
|
||||||
GoogleAuthButton(viewModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppleAuthButton(viewModel)
|
AppleAuthButton(viewModel)
|
||||||
|
|
||||||
@ -66,7 +62,10 @@ fun AuthProviderScreen(
|
|||||||
contentColor = MaterialTheme.colorScheme.onSurface
|
contentColor = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(R.string.welcome_screen_action_continue_with_email), modifier = Modifier.padding(vertical = 6.dp))
|
Text(
|
||||||
|
text = stringResource(R.string.welcome_screen_action_continue_with_email),
|
||||||
|
modifier = Modifier.padding(vertical = 6.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1.0F))
|
Spacer(modifier = Modifier.weight(1.0F))
|
||||||
@ -80,7 +79,7 @@ fun AuthProviderScreen(
|
|||||||
colors = ButtonDefaults.textButtonColors(
|
colors = ButtonDefaults.textButtonColors(
|
||||||
contentColor = MaterialTheme.colorScheme.onSurface
|
contentColor = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
){
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.welcome_screen_action_self_hosting_options),
|
text = stringResource(R.string.welcome_screen_action_self_hosting_options),
|
||||||
textDecoration = TextDecoration.Underline
|
textDecoration = TextDecoration.Underline
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
package app.omnivore.omnivore.feature.onboarding.auth.provider
|
package app.omnivore.omnivore.feature.onboarding.auth.provider
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
||||||
import androidx.activity.result.ActivityResult
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@ -17,53 +13,64 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.credentials.CredentialManager
|
||||||
|
import androidx.credentials.CustomCredential
|
||||||
|
import androidx.credentials.GetCredentialRequest
|
||||||
import app.omnivore.omnivore.BuildConfig
|
import app.omnivore.omnivore.BuildConfig
|
||||||
import app.omnivore.omnivore.R
|
import app.omnivore.omnivore.R
|
||||||
import app.omnivore.omnivore.feature.onboarding.OnboardingViewModel
|
import app.omnivore.omnivore.feature.onboarding.OnboardingViewModel
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
|
import kotlinx.coroutines.launch
|
||||||
import com.google.android.gms.tasks.Task
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GoogleAuthButton(viewModel: OnboardingViewModel) {
|
fun GoogleAuthButton(viewModel: OnboardingViewModel) {
|
||||||
|
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val credentialManager = remember { CredentialManager.create(context) }
|
||||||
|
|
||||||
val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
val googleIdOption = remember {
|
||||||
.requestIdToken(BuildConfig.OMNIVORE_GAUTH_SERVER_CLIENT_ID).requestEmail().build()
|
GetSignInWithGoogleOption.Builder(BuildConfig.OMNIVORE_GAUTH_SERVER_CLIENT_ID)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
val startForResult =
|
val request = remember {
|
||||||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
|
GetCredentialRequest.Builder()
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
.addCredentialOption(googleIdOption)
|
||||||
val intent = result.data
|
.build()
|
||||||
if (result.data != null) {
|
}
|
||||||
val task: Task<GoogleSignInAccount> =
|
|
||||||
GoogleSignIn.getSignedInAccountFromIntent(intent)
|
|
||||||
viewModel.handleGoogleAuthTask(task)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewModel.showGoogleErrorMessage()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
val googleSignIn = GoogleSignIn.getClient(context, signInOptions)
|
scope.launch {
|
||||||
|
try {
|
||||||
googleSignIn.silentSignIn().addOnCompleteListener { task ->
|
val credential = credentialManager.getCredential(
|
||||||
if (task.isSuccessful) {
|
request = request,
|
||||||
viewModel.handleGoogleAuthTask(task)
|
context = context,
|
||||||
} else {
|
).credential
|
||||||
startForResult.launch(googleSignIn.signInIntent)
|
if (credential is CustomCredential &&
|
||||||
|
credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
|
||||||
|
) {
|
||||||
|
viewModel.handleGoogleAuthCredential(
|
||||||
|
GoogleIdTokenCredential
|
||||||
|
.createFrom(credential.data)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
viewModel.showGoogleErrorMessage()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
viewModel.showGoogleErrorMessage()
|
||||||
}
|
}
|
||||||
}.addOnFailureListener {
|
|
||||||
startForResult.launch(googleSignIn.signInIntent)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -80,7 +87,10 @@ fun GoogleAuthButton(viewModel: OnboardingViewModel) {
|
|||||||
contentDescription = "",
|
contentDescription = "",
|
||||||
modifier = Modifier.padding(end = 10.dp)
|
modifier = Modifier.padding(end = 10.dp)
|
||||||
)
|
)
|
||||||
Text(text = stringResource(R.string.google_auth_text), modifier = Modifier.padding(vertical = 6.dp))
|
Text(
|
||||||
|
text = stringResource(R.string.google_auth_text),
|
||||||
|
modifier = Modifier.padding(vertical = 6.dp)
|
||||||
|
)
|
||||||
if (viewModel.isLoading) {
|
if (viewModel.isLoading) {
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
|
|||||||
@ -6,16 +6,22 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.credentials.ClearCredentialStateRequest
|
||||||
|
import androidx.credentials.CredentialManager
|
||||||
import app.omnivore.omnivore.R
|
import app.omnivore.omnivore.R
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
import kotlinx.coroutines.launch
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LogoutDialog(onClose: (Boolean) -> Unit) {
|
fun LogoutDialog(onClose: (Boolean) -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val credentialManager = remember { CredentialManager.create(context) }
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
AlertDialog(onDismissRequest = { onClose(false) },
|
AlertDialog(onDismissRequest = { onClose(false) },
|
||||||
title = { Text(text = stringResource(R.string.logout_dialog_title)) },
|
title = { Text(text = stringResource(R.string.logout_dialog_title)) },
|
||||||
text = {
|
text = {
|
||||||
@ -28,12 +34,10 @@ fun LogoutDialog(onClose: (Boolean) -> Unit) {
|
|||||||
contentColor = MaterialTheme.colorScheme.onSurface
|
contentColor = MaterialTheme.colorScheme.onSurface
|
||||||
),
|
),
|
||||||
onClick = {
|
onClick = {
|
||||||
val signInOptions =
|
scope.launch {
|
||||||
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build()
|
credentialManager.clearCredentialState(ClearCredentialStateRequest())
|
||||||
|
onClose(true)
|
||||||
val googleSignIn = GoogleSignIn.getClient(context, signInOptions)
|
}
|
||||||
googleSignIn.signOut()
|
|
||||||
onClose(true)
|
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.logout_dialog_action_confirm))
|
Text(stringResource(R.string.logout_dialog_action_confirm))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,15 +5,17 @@
|
|||||||
-->
|
-->
|
||||||
<data-extraction-rules>
|
<data-extraction-rules>
|
||||||
<cloud-backup>
|
<cloud-backup>
|
||||||
<!-- Use <include> and <exclude> to control what is backed up.
|
<exclude domain="root" />
|
||||||
<include .../>
|
<exclude domain="file" />
|
||||||
<exclude .../>
|
<exclude domain="database" />
|
||||||
-->
|
<exclude domain="sharedpref" />
|
||||||
|
<exclude domain="external" />
|
||||||
</cloud-backup>
|
</cloud-backup>
|
||||||
<!--
|
|
||||||
<device-transfer>
|
<device-transfer>
|
||||||
<include .../>
|
<exclude domain="root" />
|
||||||
<exclude .../>
|
<exclude domain="file" />
|
||||||
|
<exclude domain="database" />
|
||||||
|
<exclude domain="sharedpref" />
|
||||||
|
<exclude domain="external" />
|
||||||
</device-transfer>
|
</device-transfer>
|
||||||
-->
|
|
||||||
</data-extraction-rules>
|
</data-extraction-rules>
|
||||||
|
|||||||
@ -24,14 +24,14 @@ junit4 = "4.13.2"
|
|||||||
kotlin = "2.0.0"
|
kotlin = "2.0.0"
|
||||||
ksp = "2.0.0-1.0.21"
|
ksp = "2.0.0-1.0.21"
|
||||||
kotlinxCoroutines = "1.8.0"
|
kotlinxCoroutines = "1.8.0"
|
||||||
playServices = "18.5.0"
|
androidxCredentials = "1.2.2"
|
||||||
playServicesAuth = "21.2.0"
|
|
||||||
posthog = "2.0.3"
|
posthog = "2.0.3"
|
||||||
pspdfkit = "8.9.1"
|
pspdfkit = "8.9.1"
|
||||||
retrofit = "2.11.0"
|
retrofit = "2.11.0"
|
||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
workManager = "2.9.0"
|
workManager = "2.9.0"
|
||||||
hiltWork = "1.2.0"
|
hiltWork = "1.2.0"
|
||||||
|
googleid = "1.1.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
accompanist-flowlayout = { group = "com.google.accompanist", name = "accompanist-flowlayout", version.ref = "accompanistFlowLayout" }
|
accompanist-flowlayout = { group = "com.google.accompanist", name = "accompanist-flowlayout", version.ref = "accompanistFlowLayout" }
|
||||||
@ -65,8 +65,9 @@ chiptextfield-m3 = { group = "io.github.dokar3", name = "chiptextfield-m3", vers
|
|||||||
coil-kt-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
|
coil-kt-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
|
||||||
compose-markdown = { group = "com.github.jeziellago", name = "compose-markdown", version.ref = "composeMarkdown" }
|
compose-markdown = { group = "com.github.jeziellago", name = "compose-markdown", version.ref = "composeMarkdown" }
|
||||||
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
||||||
gms-playServicesAuth = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "playServicesAuth" }
|
androidx-credentials = { group = "androidx.credentials", name = "credentials", version.ref = "androidxCredentials" }
|
||||||
gms-playServicesBase = { group = "com.google.android.gms", name = "play-services-base", version.ref = "playServices" }
|
androidx-credentials-auth = { group = "androidx.credentials", name = "credentials-play-services-auth", version.ref = "androidxCredentials" }
|
||||||
|
googleid = { group = "com.google.android.libraries.identity.googleid", name = "googleid", version.ref = "googleid" }
|
||||||
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
|
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
|
||||||
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
|
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
|
||||||
intercom = { group = "io.intercom.android", name = "intercom-sdk", version.ref = "intercom" }
|
intercom = { group = "io.intercom.android", name = "intercom-sdk", version.ref = "intercom" }
|
||||||
|
|||||||
Reference in New Issue
Block a user