Skip to content

Commit

Permalink
Moved Google Firebase Auth to KMP
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoine Robiez committed Mar 8, 2024
1 parent fbaf20b commit 8b0d49a
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 63 deletions.
2 changes: 0 additions & 2 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ dependencies {

// Firebase
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.auth)
implementation(libs.firebase.config)
implementation(libs.firebase.crashlytics.ktx)
implementation(libs.firebase.inappmessaging)
implementation(libs.firebase.messaging)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import fr.androidmakers.domain.repo.PartnersRepository
import fr.androidmakers.domain.repo.RoomsRepository
import fr.androidmakers.domain.repo.SessionsRepository
import fr.androidmakers.domain.repo.SpeakersRepository
import fr.androidmakers.domain.repo.UserRepository
import fr.androidmakers.store.firebase.FirebaseUserRepository
import fr.androidmakers.store.graphql.ApolloClientBuilder
import fr.androidmakers.store.graphql.PartnersGraphQLRepository
import fr.androidmakers.store.graphql.RoomsGraphQLRepository
Expand All @@ -33,6 +35,7 @@ class AndroidMakersApplication : Application() {
lateinit var roomsRepository: RoomsRepository
lateinit var sessionsRepository: SessionsRepository
lateinit var speakersRepository: SpeakersRepository
lateinit var userRepository: UserRepository

lateinit var bookmarksStore: BookmarksRepository

Expand Down Expand Up @@ -68,6 +71,8 @@ class AndroidMakersApplication : Application() {
filesDir.resolve("bookmarks.preferences_pb").absolutePath
})

userRepository = FirebaseUserRepository()

syncBookmarksUseCase = SyncBookmarksUseCase(
bookmarksStore,
sessionsRepository
Expand Down
78 changes: 35 additions & 43 deletions androidApp/src/main/java/fr/paug/androidmakers/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,45 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.tasks.Task
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.GoogleAuthProvider
import com.google.firebase.messaging.FirebaseMessaging
import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.auth.FirebaseAuth
import dev.gitlive.firebase.auth.GoogleAuthProvider
import dev.gitlive.firebase.auth.auth
import fr.androidmakers.domain.model.User
import fr.androidmakers.store.firebase.toUser
import fr.paug.androidmakers.AndroidMakersApplication
import fr.paug.androidmakers.R
import fr.paug.androidmakers.ui.components.MainLayout
import fr.paug.androidmakers.ui.components.about.AboutActions
import fr.paug.androidmakers.ui.theme.AndroidMakersTheme
import fr.paug.androidmakers.util.CustomTabUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch

val LocalActivity = staticCompositionLocalOf<MainActivity> { throw NotImplementedError() }

data class AMUser(
private val firebaseUser: FirebaseUser
) {
val uid: String
get() = firebaseUser.uid
val photoUrl: String?
get() = firebaseUser.photoUrl?.toString()
}
class MainActivity : AppCompatActivity() {

private fun FirebaseUser.toAMUser(): AMUser {
return AMUser(this)
}
private val userRepository = AndroidMakersApplication.instance().userRepository

class MainActivity : AppCompatActivity() {
private val _user = MutableStateFlow(FirebaseAuth.getInstance().currentUser?.toAMUser())
private val _user = MutableStateFlow<User?>(null)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

lifecycleScope.launch {
_user.emit(userRepository.getUser())
}

val currentUser = _user.value
if (currentUser != null) {
lifecycleScope.launch {
// fire & forget
// This is racy but oh well...
mergeBookmarks(currentUser.uid)
mergeBookmarks(currentUser.id)
}
}

Expand Down Expand Up @@ -189,32 +187,24 @@ class MainActivity : AppCompatActivity() {
// with Firebase.
// Got an ID token from Google. Use it to authenticate
// with Firebase.
val firebaseCredential = GoogleAuthProvider.getCredential(idToken, null)
val auth = FirebaseAuth.getInstance()

auth.signInWithCredential(firebaseCredential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
lifecycleScope.launch {
_user.value = auth.currentUser?.toAMUser()
mergeBookmarks(auth.currentUser!!.uid)
}
} else {
// If sign in fails, display a message to the user.
task.exception?.printStackTrace()
_user.value = null
}
}
val firebaseCredential = GoogleAuthProvider.credential(idToken, null)
val auth = Firebase.auth

CoroutineScope(Dispatchers.Default).launch {
val result = auth.signInWithCredential(firebaseCredential)
// Sign in success, update UI with the signed-in user's information
lifecycleScope.launch {
_user.value = result.user?.toUser()
mergeBookmarks(auth.currentUser!!.uid)
}
}
}

else -> {
_user.value = null
// Shouldn't happen.
}
else -> {}
}
} catch (e: ApiException) {
e.printStackTrace()
_user.value = null
}
}
}
Expand All @@ -239,10 +229,12 @@ class MainActivity : AppCompatActivity() {
.build()
val googleSignInClient = GoogleSignIn.getClient(activity, gso)

FirebaseAuth.getInstance().signOut()
googleSignInClient.signOut()
googleSignInClient.revokeAccess()
_user.value = null
lifecycleScope.launch {
Firebase.auth.signOut()
googleSignInClient.signOut()
googleSignInClient.revokeAccess()
_user.emit(null)
}
}

fun signin() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import at.asitplus.KmmResult
import fr.androidmakers.domain.model.Partner
import fr.androidmakers.domain.model.PartnerGroup
import fr.androidmakers.domain.model.SpeakerId
import fr.androidmakers.domain.model.User
import fr.paug.androidmakers.AndroidMakersApplication
import fr.paug.androidmakers.R
import fr.paug.androidmakers.ui.AMUser
import fr.paug.androidmakers.ui.MR
import fr.paug.androidmakers.ui.components.about.AboutActions
import fr.paug.androidmakers.ui.components.about.AboutLayout
Expand All @@ -80,7 +79,7 @@ import kotlinx.coroutines.launch
fun AVALayout(
onSessionClick: (sessionId: String, roomId: String, startTimestamp: Long, endTimestamp: Long) -> Unit,
aboutActions: AboutActions,
user: AMUser?,
user: User?,
navigateToSpeakerDetails: (SpeakerId) -> Unit,
) {
val avaNavController = rememberNavController()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import fr.androidmakers.domain.model.SpeakerId
import fr.paug.androidmakers.ui.AMUser
import fr.androidmakers.domain.model.User
import fr.paug.androidmakers.ui.components.about.AboutActions
import fr.paug.androidmakers.ui.components.session.SessionDetailLayout
import fr.paug.androidmakers.ui.components.session.SessionDetailViewModel
Expand All @@ -25,7 +25,7 @@ import fr.paug.androidmakers.ui.viewmodel.Lce
* The main layout: entry point of the application
*/
@Composable
fun MainLayout(aboutActions: AboutActions, user: AMUser?) {
fun MainLayout(aboutActions: AboutActions, user: User?) {
val mainNavController = rememberNavController()
MainNavHost(
mainNavController = mainNavController,
Expand All @@ -45,7 +45,7 @@ private fun MainNavHost(
mainNavController: NavHostController,
onSessionClick: (sessionId: String, roomId: String, startTimestamp: Long, endTimestamp: Long) -> Unit,
aboutActions: AboutActions,
user: AMUser?,
user: User?,
navigateToSpeakerDetails: (SpeakerId) -> Unit,
) {
NavHost(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import coil.compose.AsyncImage
import coil.request.ImageRequest
import fr.paug.androidmakers.ui.AMUser
import fr.androidmakers.domain.model.User
import fr.paug.androidmakers.ui.LocalActivity
import fr.paug.androidmakers.ui.MR
import fr.paug.androidmakers.ui.util.stringResource


@Composable
fun SigninButton(user: AMUser?) {
fun SigninButton(user: User?) {
val activity = LocalActivity.current
val expandedState = remember { mutableStateOf(false) }

Expand Down
9 changes: 4 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
version-code = "1456"
sdk-compile = "34"
sdk-min = "21"
sdk-min = "24"
androidxActivity = "1.8.2"
androidxAppCompat = "1.6.1"
androidxLifecycle = "2.7.0"
Expand All @@ -18,6 +18,7 @@ moko-graphics = "0.9.0"
compose-mp = "1.5.12"
datastore = "1.1.0-beta01"
skie = "0.6.1"
firebase = "1.11.1"

[libraries]
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" }
Expand All @@ -36,10 +37,7 @@ compose-material = { group = "androidx.compose.material", name = "material", ver
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
espresso-core = "androidx.test.espresso:espresso-core:3.5.1"
firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx" }
firebase-auth = { module = "com.google.firebase:firebase-auth" }
firebase-auth-ktx = { module = "com.google.firebase:firebase-auth-ktx" }
firebase-bom = "com.google.firebase:firebase-bom:32.7.2"
firebase-config = { module = "com.google.firebase:firebase-config" }
firebase-crashlytics-ktx = { module = "com.google.firebase:firebase-crashlytics-ktx" }
firebase-inappmessaging = { module = "com.google.firebase:firebase-inappmessaging-display-ktx" }
firebase-messaging = { module = "com.google.firebase:firebase-messaging" }
Expand All @@ -64,7 +62,8 @@ moko-graphics = { module = "dev.icerock.moko:graphics", version.ref = "moko-grap
compose-mp-icons = { module = "org.jetbrains.compose.material:material-icons-extended-desktop", version.ref = "compose-mp" }
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" }
androidx-datastore-preferences-core = { group = "androidx.datastore", name = "datastore-preferences-core", version.ref = "datastore" }

firebase-installations = { module = "dev.gitlive:firebase-installations", version.ref = "firebase" }
firebase-auth = { module = "dev.gitlive:firebase-auth", version.ref = "firebase" }

android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "android-gradle-plugin" }
firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "crashlytics-plugin" }
Expand Down
8 changes: 3 additions & 5 deletions shared/data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ kotlin {

implementation(libs.androidx.datastore.preferences.core)
api(libs.androidx.datastore.preferences)
}
}

androidMain.dependencies {
implementation(libs.firebase.auth)
implementation(libs.firebase.auth.ktx)
api(libs.firebase.auth)

}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package fr.androidmakers.store.firebase

import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.auth.auth
import fr.androidmakers.domain.model.User
import fr.androidmakers.domain.repo.UserRepository

class FirebaseUserRepository : UserRepository {
override suspend fun getUser(): User? {
return Firebase.auth.currentUser?.toUser()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fr.androidmakers.store.firebase

import dev.gitlive.firebase.auth.FirebaseUser
import fr.androidmakers.domain.model.User

fun FirebaseUser.toUser(): User {
return User(uid, photoURL)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package fr.androidmakers.domain.model

data class User(
val id: String,
val photoUrl: String?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package fr.androidmakers.domain.repo

import fr.androidmakers.domain.model.User

interface UserRepository {
suspend fun getUser(): User?
}

0 comments on commit 8b0d49a

Please sign in to comment.