Skip to content

Commit

Permalink
Separating into two services
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinSchildhorn committed Mar 29, 2024
1 parent d57fbbe commit c81872c
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import co.touchlab.droidcon.R
import co.touchlab.droidcon.android.service.impl.AndroidGoogleSignInService
import co.touchlab.droidcon.application.service.NotificationSchedulingService
import co.touchlab.droidcon.application.service.NotificationService
import co.touchlab.droidcon.domain.service.AnalyticsService
import co.touchlab.droidcon.domain.service.AuthenticationService
import co.touchlab.droidcon.domain.service.GoogleSignInService
import co.touchlab.droidcon.domain.service.SyncService
import co.touchlab.droidcon.service.AndroidNotificationService
import co.touchlab.droidcon.ui.theme.Colors
Expand Down Expand Up @@ -56,19 +58,20 @@ class MainActivity : ComponentActivity(), KoinComponent {

private val applicationViewModel: ApplicationViewModel by inject()
private val root = LifecycleGraph.Root(this)
private val firebaseService: AuthenticationService by inject()
private val authenticationService: AuthenticationService by inject()
private val googleSignInService: GoogleSignInService by inject()

private lateinit var auth: FirebaseAuth

private val firebaseAuthListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
firebaseAuth.currentUser?.let { user ->
firebaseService.setCredentials(
authenticationService.setCredentials(
id = user.uid,
name = user.displayName,
email = user.email,
pictureUrl = user.photoUrl?.toString(),
)
} ?: run { firebaseService.clearCredentials() }
} ?: run { authenticationService.clearCredentials() }
}

private val firebaseIntentResultLauncher: ActivityResultLauncher<IntentSenderRequest> =
Expand All @@ -84,7 +87,7 @@ class MainActivity : ComponentActivity(), KoinComponent {
if (task.isSuccessful) {
logger.d { "signInWithCredential:success" }
auth.currentUser?.let { user ->
firebaseService.setCredentials(
authenticationService.setCredentials(
id = user.uid,
name = user.displayName,
email = user.email,
Expand All @@ -107,7 +110,7 @@ class MainActivity : ComponentActivity(), KoinComponent {
installSplashScreen()
AppChecker.checkTimeZoneHash()

(firebaseService as FirebaseService).setActivity(this, firebaseIntentResultLauncher)
(googleSignInService as AndroidGoogleSignInService).setActivity(this, firebaseIntentResultLauncher)
analyticsService.logEvent(AnalyticsService.EVENT_STARTED)

applicationViewModel.lifecycle.removeFromParent()
Expand Down
7 changes: 4 additions & 3 deletions android/src/main/java/co/touchlab/droidcon/android/MainApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import co.touchlab.droidcon.android.service.impl.AndroidAnalyticsService
import co.touchlab.droidcon.android.service.impl.AndroidGoogleSignInService
import co.touchlab.droidcon.android.service.impl.DefaultParseUrlViewService
import co.touchlab.droidcon.android.util.NotificationLocalizedStringFactory
import co.touchlab.droidcon.application.service.NotificationSchedulingService
import co.touchlab.droidcon.domain.service.AnalyticsService
import co.touchlab.droidcon.domain.service.AuthenticationService
import co.touchlab.droidcon.domain.service.GoogleSignInService
import co.touchlab.droidcon.domain.service.impl.ResourceReader
import co.touchlab.droidcon.initKoin
import co.touchlab.droidcon.service.ParseUrlViewService
Expand Down Expand Up @@ -55,8 +56,8 @@ class MainApp : Application() {
AndroidAnalyticsService(firebaseAnalytics = Firebase.analytics)
}

single<AuthenticationService> {
FirebaseService()
single<GoogleSignInService> {
AndroidGoogleSignInService()
}
} + uiModule
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package co.touchlab.droidcon.android
package co.touchlab.droidcon.android.service.impl

import android.app.Activity
import android.content.IntentSender
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
import co.touchlab.droidcon.BuildConfig
import co.touchlab.droidcon.domain.service.AuthenticationService
import co.touchlab.droidcon.domain.service.GoogleSignInService
import co.touchlab.kermit.Logger
import com.google.android.gms.auth.api.identity.BeginSignInRequest
import com.google.android.gms.auth.api.identity.Identity
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import org.brightify.hyperdrive.utils.WeakReference
import org.koin.core.component.KoinComponent

class FirebaseService : AuthenticationService(FirebaseAuth.getInstance().currentUser != null) {
class AndroidGoogleSignInService : GoogleSignInService, KoinComponent {

private val logger = Logger.withTag("AuthenticationService")
private val clientId = BuildConfig.CLIENT_ID
Expand Down Expand Up @@ -64,8 +64,8 @@ class FirebaseService : AuthenticationService(FirebaseAuth.getInstance().current
return false
}

override fun performLogout(): Boolean {
override fun performGoogleLogout(): Boolean {
Firebase.auth.signOut()
return super.performLogout()
return true
}
}
8 changes: 4 additions & 4 deletions ios/Droidcon/Droidcon.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
A35DC2E328AB6C6F00C7B298 /* ComposeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A35DC2E228AB6C6F00C7B298 /* ComposeController.swift */; };
A35DEF2228AA265C0072605A /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = A35DEF2128AA265C0072605A /* Settings.bundle */; };
A35DEF2428AA26C80072605A /* SettingsBundleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A35DEF2328AA26C80072605A /* SettingsBundleHelper.swift */; };
F127D3592BB46A0A00E08281 /* FirebaseService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F127D3582BB46A0A00E08281 /* FirebaseService.swift */; };
F127D3592BB46A0A00E08281 /* IOSGoogleSignInService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F127D3582BB46A0A00E08281 /* IOSGoogleSignInService.swift */; };
F1465F0123AA94BF0055F7C3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1465F0023AA94BF0055F7C3 /* AppDelegate.swift */; };
F1465F0A23AA94BF0055F7C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F1465F0923AA94BF0055F7C3 /* Assets.xcassets */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -98,7 +98,7 @@
A35DEF2328AA26C80072605A /* SettingsBundleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsBundleHelper.swift; sourceTree = "<group>"; };
DD90C0C0A4D331CEBDBE69E8 /* Pods-Droidcon.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Droidcon.release.xcconfig"; path = "Target Support Files/Pods-Droidcon/Pods-Droidcon.release.xcconfig"; sourceTree = "<group>"; };
EBA278C64D82609BA00FE2A5 /* Pods_Droidcon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Droidcon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F127D3582BB46A0A00E08281 /* FirebaseService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseService.swift; sourceTree = "<group>"; };
F127D3582BB46A0A00E08281 /* IOSGoogleSignInService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOSGoogleSignInService.swift; sourceTree = "<group>"; };
F1465EFD23AA94BF0055F7C3 /* Droidcon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Droidcon.app; sourceTree = BUILT_PRODUCTS_DIR; };
F1465F0023AA94BF0055F7C3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F1465F0923AA94BF0055F7C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -256,7 +256,7 @@
F1465F0023AA94BF0055F7C3 /* AppDelegate.swift */,
46B5284C249C5CF400A7725D /* Koin.swift */,
8404D80D26C64B9E00AE200F /* IOSAnalyticsService.swift */,
F127D3582BB46A0A00E08281 /* FirebaseService.swift */,
F127D3582BB46A0A00E08281 /* IOSGoogleSignInService.swift */,
F1465F0923AA94BF0055F7C3 /* Assets.xcassets */,
F1465F0B23AA94BF0055F7C3 /* LaunchScreen.storyboard */,
F1465F0E23AA94BF0055F7C3 /* Info.plist */,
Expand Down Expand Up @@ -450,7 +450,7 @@
684FAA7726B2A4EA00673AFF /* SettingsView.swift in Sources */,
689DD2FB26B40F1800A9B009 /* LazyView.swift in Sources */,
689DD30526B438CA00A9B009 /* Avatar.swift in Sources */,
F127D3592BB46A0A00E08281 /* FirebaseService.swift in Sources */,
F127D3592BB46A0A00E08281 /* IOSGoogleSignInService.swift in Sources */,
681C95A126C555D90011330B /* VisualEffectView.swift in Sources */,
1833221026B0CF5600D79482 /* DroidconApp.swift in Sources */,
684FAA7426B2A4D400673AFF /* ScheduleView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@ import GoogleSignIn
import FirebaseAuth
import DroidconKit

class FirebaseService : AuthenticationService {
class IOSGoogleSignInService : GoogleSignInService {

let logger = Logger.companion.withTag(tag: "AuthenticationService")

init() {
super.init(isSignedIn: Auth.auth().currentUser != nil)
}
let logger = Logger.companion.withTag(tag: "IOSGoogleSignInService")

override func performGoogleLogin() -> Bool {
func performGoogleLogin() -> Bool {
logger.i(message: { "Performing Google Login" })
guard let clientID = FirebaseApp.app()?.options.clientID else {
logger.e(message: { "No ClientId" })
Expand Down Expand Up @@ -54,28 +50,21 @@ class FirebaseService : AuthenticationService {
Auth.auth().signIn(with: credential) { result, error in
if let error {
self.logger.e(message: { error.localizedDescription })
self.clearCredentials()
} else {
self.logger.v(message: { "Got results from Auth!" })
self.setCredentials(
id: result?.user.uid ?? "",
name: result?.user.displayName,
email: result?.user.email,
pictureUrl: result?.user.photoURL?.absoluteString
)
}
}
}
return true
}

override func performLogout() -> Bool {
func performGoogleLogout() -> Bool {
do {
self.logger.v(message: { "Performing Logout" })
try Auth.auth().signOut()
return super.performLogout()
return true
} catch let signOutError as NSError {
self.logger.v(message: { "Error occured signing out" })
self.logger.e(message: { "Error occured signing out: \(signOutError.localizedDescription)" })
return false
}
}
Expand Down
2 changes: 1 addition & 1 deletion ios/Droidcon/Droidcon/Koin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ func startKoin() {
let koinApplication = DependencyInjectionKt.doInitKoinIos(
userDefaults: userDefaults,
analyticsService: IOSAnalyticsService(),
authenticationService: FirebaseService()
googleSignInService: IOSGoogleSignInService()
)
_koin = koinApplication.koin
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package co.touchlab.droidcon.ios

import co.touchlab.droidcon.application.service.NotificationSchedulingService
import co.touchlab.droidcon.domain.service.AnalyticsService
import co.touchlab.droidcon.domain.service.AuthenticationService
import co.touchlab.droidcon.domain.service.GoogleSignInService
import co.touchlab.droidcon.domain.service.impl.ResourceReader
import co.touchlab.droidcon.initKoin
import co.touchlab.droidcon.ios.service.DefaultParseUrlViewService
Expand All @@ -26,7 +26,7 @@ import platform.Foundation.NSUserDefaults
fun initKoinIos(
userDefaults: NSUserDefaults,
analyticsService: AnalyticsService,
authenticationService: AuthenticationService,
googleSignInService: GoogleSignInService,
): KoinApplication = initKoin(
module {
single { BundleProvider(bundle = NSBundle.mainBundle) }
Expand All @@ -40,7 +40,7 @@ fun initKoinIos(
}

single { analyticsService }
single { authenticationService }
single { googleSignInService }

single<ParseUrlViewService> { DefaultParseUrlViewService() }
} + uiModule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ val uiModule = module {
SettingsViewModel.Factory(
settingsGateway = get(),
authenticationService = get(),
googleSignInService = get(),
aboutFactory = get()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package co.touchlab.droidcon.viewmodel.settings

import co.touchlab.droidcon.application.gateway.SettingsGateway
import co.touchlab.droidcon.domain.service.AuthenticationService
import co.touchlab.droidcon.domain.service.GoogleSignInService
import org.brightify.hyperdrive.multiplatformx.BaseViewModel

class SettingsViewModel(
settingsGateway: SettingsGateway,
private val authenticationService: AuthenticationService,
private val googleSignInService: GoogleSignInService,
private val aboutFactory: AboutViewModel.Factory,
) : BaseViewModel() {

Expand Down Expand Up @@ -55,15 +57,16 @@ class SettingsViewModel(
)
val observeIsAuthenticated by observe(::isAuthenticated)

fun signIn() = authenticationService.performGoogleLogin()
fun signOut() = authenticationService.performLogout()
fun signIn() = googleSignInService.performGoogleLogin()
fun signOut() = googleSignInService.performGoogleLogout()

class Factory(
private val settingsGateway: SettingsGateway,
private val authenticationService: AuthenticationService,
private val googleSignInService: GoogleSignInService,
private val aboutFactory: AboutViewModel.Factory,
) {

fun create() = SettingsViewModel(settingsGateway, authenticationService, aboutFactory)
fun create() = SettingsViewModel(settingsGateway, authenticationService, googleSignInService, aboutFactory)
}
}
3 changes: 3 additions & 0 deletions shared/src/commonMain/kotlin/co/touchlab/droidcon/Koin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ import co.touchlab.droidcon.domain.repository.impl.SqlDelightSessionRepository
import co.touchlab.droidcon.domain.repository.impl.SqlDelightSponsorGroupRepository
import co.touchlab.droidcon.domain.repository.impl.SqlDelightSponsorRepository
import co.touchlab.droidcon.domain.repository.impl.adapter.InstantSqlDelightAdapter
import co.touchlab.droidcon.domain.service.AuthenticationService
import co.touchlab.droidcon.domain.service.DateTimeService
import co.touchlab.droidcon.domain.service.FeedbackService
import co.touchlab.droidcon.domain.service.ScheduleService
import co.touchlab.droidcon.domain.service.ServerApi
import co.touchlab.droidcon.domain.service.SyncService
import co.touchlab.droidcon.domain.service.UserIdProvider
import co.touchlab.droidcon.domain.service.impl.DefaultApiDataSource
import co.touchlab.droidcon.domain.service.impl.DefaultAuthenticationService
import co.touchlab.droidcon.domain.service.impl.DefaultDateTimeService
import co.touchlab.droidcon.domain.service.impl.DefaultFeedbackService
import co.touchlab.droidcon.domain.service.impl.DefaultScheduleService
Expand Down Expand Up @@ -235,6 +237,7 @@ private val coreModule = module {
clock = get(),
)
}
single<AuthenticationService> { DefaultAuthenticationService() }
}

internal inline fun <reified T> Scope.getWith(vararg params: Any?): T {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,15 @@
package co.touchlab.droidcon.domain.service

import co.touchlab.droidcon.UserContext
import co.touchlab.droidcon.UserData
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

abstract class AuthenticationService(isSignedIn: Boolean) : KoinComponent {
private val userIdProvider: UserIdProvider by inject()

private val _isAuthenticated = MutableStateFlow(isSignedIn)
val isAuthenticated: StateFlow<Boolean> = _isAuthenticated

abstract fun performGoogleLogin(): Boolean
open fun performLogout(): Boolean {
clearCredentials()
return true
}
interface AuthenticationService {
val isAuthenticated: StateFlow<Boolean>

fun setCredentials(
id: String,
name: String?,
email: String?,
pictureUrl: String?,
) {
_isAuthenticated.update { true }
userIdProvider.saveUserContext(
UserContext(
isAuthenticated = true,
userData = UserData(
id = id,
name = name,
email = email,
pictureUrl = pictureUrl,
)
)
)
}

fun clearCredentials() {
_isAuthenticated.update { false }
userIdProvider.saveUserContext(
UserContext(
isAuthenticated = false,
userData = null
)
)
}
)
fun clearCredentials()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package co.touchlab.droidcon.domain.service

interface GoogleSignInService {
fun performGoogleLogin(): Boolean
fun performGoogleLogout(): Boolean
}
Loading

0 comments on commit c81872c

Please sign in to comment.