11package com.ninecraft.booket.core.data.impl.repository
22
3+ import com.google.firebase.messaging.FirebaseMessaging
34import com.ninecraft.booket.core.common.utils.runSuspendCatching
45import com.ninecraft.booket.core.data.api.repository.UserRepository
56import com.ninecraft.booket.core.data.impl.mapper.toModel
67import com.ninecraft.booket.core.datastore.api.datasource.NotificationDataSource
78import com.ninecraft.booket.core.datastore.api.datasource.OnboardingDataSource
9+ import com.ninecraft.booket.core.network.request.FcmTokenRequest
10+ import com.ninecraft.booket.core.network.request.NotificationSettingsRequest
811import com.ninecraft.booket.core.network.request.TermsAgreementRequest
912import com.ninecraft.booket.core.network.service.ReedService
13+ import com.orhanobut.logger.Logger
14+ import kotlinx.coroutines.flow.first
15+ import kotlinx.coroutines.flow.firstOrNull
16+ import kotlinx.coroutines.tasks.await
1017import javax.inject.Inject
1118
1219internal class DefaultUserRepository @Inject constructor(
1320 private val service : ReedService ,
1421 private val onboardingDataSource : OnboardingDataSource ,
1522 private val notificationDataSource : NotificationDataSource ,
23+ private val firebaseMessaging : FirebaseMessaging ,
1624) : UserRepository {
1725 override suspend fun agreeTerms (termsAgreed : Boolean ) = runSuspendCatching {
1826 service.agreeTerms(TermsAgreementRequest (termsAgreed)).toModel()
@@ -28,9 +36,59 @@ internal class DefaultUserRepository @Inject constructor(
2836 onboardingDataSource.setOnboardingCompleted(isCompleted)
2937 }
3038
31- override val isNotificationEnabled = notificationDataSource.isNotificationEnabled
39+ override suspend fun syncFcmToken () = runSuspendCatching {
40+ val newToken = getRemoteFcmToken()
41+ val localToken = getLocalFcmToken()
3242
33- override suspend fun setNotificationEnabled (isEnabled : Boolean ) {
34- notificationDataSource.setNotificationEnabled(isEnabled)
43+ if (newToken == localToken) {
44+ Logger .d(" Skip FCM token sync (already up-to-date)" )
45+ return @runSuspendCatching
46+ }
47+
48+ updateFcmToken(newToken)
49+ setFcmToken(newToken)
50+ }
51+
52+ override suspend fun syncFcmToken (fcmToken : String ): Result <Unit > = runSuspendCatching {
53+ updateFcmToken(fcmToken)
54+ setFcmToken(fcmToken)
55+ }
56+
57+ override val isUserNotificationEnabled = notificationDataSource.isUserNotificationEnabled
58+
59+ override suspend fun getUserNotificationEnabled (): Boolean = isUserNotificationEnabled.first()
60+
61+ override suspend fun setUserNotificationEnabled (isEnabled : Boolean ) {
62+ notificationDataSource.setUserNotificationEnabled(isEnabled)
63+ }
64+
65+ override suspend fun getLastSyncedNotificationEnabled (): Boolean? =
66+ notificationDataSource.lastSyncedNotificationEnabled.firstOrNull()
67+
68+ override suspend fun setLastNotificationSyncedEnabled (isEnabled : Boolean ) {
69+ notificationDataSource.setLastSyncedNotificationEnabled(isEnabled)
70+ }
71+
72+ override suspend fun updateNotificationSettings (notificationEnabled : Boolean ) = runSuspendCatching {
73+ service.updateNotificationSettings(NotificationSettingsRequest (notificationEnabled)).toModel()
74+ }
75+
76+ private suspend fun getRemoteFcmToken (): String {
77+ return try {
78+ firebaseMessaging.token.await()
79+ } catch (e: Exception ) {
80+ Logger .e(" Failed to fetch FCM token: ${e.message} " )
81+ throw e
82+ }
83+ }
84+
85+ private suspend fun getLocalFcmToken (): String = notificationDataSource.fcmToken.first()
86+
87+ private suspend fun setFcmToken (fcmToken : String ) {
88+ notificationDataSource.setFcmToken(fcmToken)
89+ }
90+
91+ private suspend fun updateFcmToken (fcmToken : String ) {
92+ service.updateFcmToken(FcmTokenRequest (fcmToken))
3593 }
3694}
0 commit comments