Skip to content

Commit 56bc9d2

Browse files
authored
Merge pull request #221 from YAPP-Github/BOOK-430-feature/#220
feat: 멀티디바이스 푸시 알림 지원을 위한 API 스펙 변경 반영
2 parents 2c3b9e7 + 962f1c4 commit 56bc9d2

File tree

7 files changed

+52
-16
lines changed

7 files changed

+52
-16
lines changed

core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/UserRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,6 @@ interface UserRepository {
2929
suspend fun setLastNotificationSyncedEnabled(isEnabled: Boolean)
3030

3131
suspend fun updateNotificationSettings(notificationEnabled: Boolean): Result<UserProfileModel>
32+
33+
suspend fun resetNotificationData()
3234
}

core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/di/FirebaseModule.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.ninecraft.booket.core.data.impl.di
22

33
import com.google.firebase.Firebase
4+
import com.google.firebase.installations.FirebaseInstallations
5+
import com.google.firebase.installations.installations
46
import com.google.firebase.messaging.FirebaseMessaging
57
import com.google.firebase.messaging.messaging
68
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
@@ -32,4 +34,8 @@ internal object FirebaseModule {
3234
@Singleton
3335
@Provides
3436
fun provideFirebaseMessaging(): FirebaseMessaging = Firebase.messaging
37+
38+
@Singleton
39+
@Provides
40+
fun provideFirebaseInstallation(): FirebaseInstallations = Firebase.installations
3541
}

core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/repository/DefaultAuthRepository.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.ninecraft.booket.core.data.impl.repository
22

33
import com.ninecraft.booket.core.common.utils.runSuspendCatching
44
import com.ninecraft.booket.core.data.api.repository.AuthRepository
5-
import com.ninecraft.booket.core.datastore.api.datasource.NotificationDataSource
65
import com.ninecraft.booket.core.datastore.api.datasource.TokenDataSource
76
import com.ninecraft.booket.core.model.AutoLoginState
87
import com.ninecraft.booket.core.model.UserState
@@ -16,7 +15,6 @@ private const val KAKAO_PROVIDER_TYPE = "KAKAO"
1615
internal class DefaultAuthRepository @Inject constructor(
1716
private val service: ReedService,
1817
private val tokenDataSource: TokenDataSource,
19-
private val notificationDataSource: NotificationDataSource,
2018
) : AuthRepository {
2119
override suspend fun login(accessToken: String) = runSuspendCatching {
2220
val response = service.login(
@@ -31,7 +29,6 @@ internal class DefaultAuthRepository @Inject constructor(
3129
override suspend fun logout() = runSuspendCatching {
3230
service.logout()
3331
clearTokens()
34-
clearNotificationDataStore()
3532
}
3633

3734
override suspend fun withdraw() = runSuspendCatching {
@@ -64,8 +61,4 @@ internal class DefaultAuthRepository @Inject constructor(
6461
val accessToken = tokenDataSource.getAccessToken()
6562
return if (accessToken.isBlank()) UserState.Guest else UserState.LoggedIn
6663
}
67-
68-
private suspend fun clearNotificationDataStore() {
69-
notificationDataSource.clearNotificationDataStore()
70-
}
7164
}

core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/repository/DefaultUserRepository.kt

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package com.ninecraft.booket.core.data.impl.repository
22

3+
import com.google.firebase.installations.FirebaseInstallations
34
import com.google.firebase.messaging.FirebaseMessaging
45
import com.ninecraft.booket.core.common.utils.runSuspendCatching
56
import com.ninecraft.booket.core.data.api.repository.UserRepository
67
import com.ninecraft.booket.core.data.impl.mapper.toModel
78
import com.ninecraft.booket.core.datastore.api.datasource.NotificationDataSource
89
import 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.DeviceRegistrationRequest
1011
import com.ninecraft.booket.core.network.request.NotificationSettingsRequest
1112
import com.ninecraft.booket.core.network.request.TermsAgreementRequest
1213
import com.ninecraft.booket.core.network.service.ReedService
@@ -21,6 +22,7 @@ internal class DefaultUserRepository @Inject constructor(
2122
private val onboardingDataSource: OnboardingDataSource,
2223
private val notificationDataSource: NotificationDataSource,
2324
private val firebaseMessaging: FirebaseMessaging,
25+
private val firebaseInstallations: FirebaseInstallations,
2426
) : UserRepository {
2527
override suspend fun agreeTerms(termsAgreed: Boolean) = runSuspendCatching {
2628
service.agreeTerms(TermsAgreementRequest(termsAgreed)).toModel()
@@ -45,12 +47,12 @@ internal class DefaultUserRepository @Inject constructor(
4547
return@runSuspendCatching
4648
}
4749

48-
updateFcmToken(newToken)
50+
registerDevice(newToken)
4951
setFcmToken(newToken)
5052
}
5153

5254
override suspend fun syncFcmToken(fcmToken: String): Result<Unit> = runSuspendCatching {
53-
updateFcmToken(fcmToken)
55+
registerDevice(fcmToken)
5456
setFcmToken(fcmToken)
5557
}
5658

@@ -73,6 +75,15 @@ internal class DefaultUserRepository @Inject constructor(
7375
service.updateNotificationSettings(NotificationSettingsRequest(notificationEnabled)).toModel()
7476
}
7577

78+
override suspend fun resetNotificationData() {
79+
try {
80+
deleteRemoteFcmToken()
81+
clearNotificationDataStore()
82+
} catch (e: Exception) {
83+
Logger.e("Failed to reset notification data: ${e.message}")
84+
}
85+
}
86+
7687
private suspend fun getRemoteFcmToken(): String {
7788
return try {
7889
firebaseMessaging.token.await()
@@ -88,7 +99,25 @@ internal class DefaultUserRepository @Inject constructor(
8899
notificationDataSource.setFcmToken(fcmToken)
89100
}
90101

91-
private suspend fun updateFcmToken(fcmToken: String) {
92-
service.updateFcmToken(FcmTokenRequest(fcmToken))
102+
private suspend fun getDeviceId(): String {
103+
return try {
104+
firebaseInstallations.id.await()
105+
} catch (e: Exception) {
106+
Logger.e("Failed to fetch device ID: ${e.message}")
107+
throw e
108+
}
109+
}
110+
111+
private suspend fun registerDevice(fcmToken: String) {
112+
val deviceId = getDeviceId()
113+
service.upsertDevice(DeviceRegistrationRequest(deviceId, fcmToken))
114+
}
115+
116+
private suspend fun deleteRemoteFcmToken() {
117+
firebaseMessaging.deleteToken().await()
118+
}
119+
120+
private suspend fun clearNotificationDataStore() {
121+
notificationDataSource.clearNotificationDataStore()
93122
}
94123
}

core/network/src/main/kotlin/com/ninecraft/booket/core/network/request/FcmTokenRequest.kt renamed to core/network/src/main/kotlin/com/ninecraft/booket/core/network/request/DeviceRegistrationRequest.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import kotlinx.serialization.SerialName
44
import kotlinx.serialization.Serializable
55

66
@Serializable
7-
data class FcmTokenRequest(
7+
data class DeviceRegistrationRequest(
8+
@SerialName("deviceId")
9+
val deviceId: String,
810
@SerialName("fcmToken")
911
val fcmToken: String,
1012
)

core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.ninecraft.booket.core.network.service
22

33
import com.ninecraft.booket.core.network.request.BookUpsertRequest
4-
import com.ninecraft.booket.core.network.request.FcmTokenRequest
4+
import com.ninecraft.booket.core.network.request.DeviceRegistrationRequest
55
import com.ninecraft.booket.core.network.request.LoginRequest
66
import com.ninecraft.booket.core.network.request.NotificationSettingsRequest
77
import com.ninecraft.booket.core.network.request.RecordRegisterRequest
@@ -53,8 +53,8 @@ interface ReedService {
5353
@GET("api/v1/users/me")
5454
suspend fun getUserProfile(): UserProfileResponse
5555

56-
@PUT("api/v1/users/me/fcm-token")
57-
suspend fun updateFcmToken(@Body fcmTokenRequest: FcmTokenRequest): UserProfileResponse
56+
@PUT("api/v1/users/me/devices")
57+
suspend fun upsertDevice(@Body deviceRegistrationRequest: DeviceRegistrationRequest): UserProfileResponse
5858

5959
@PUT("api/v1/users/me/notification-settings")
6060
suspend fun updateNotificationSettings(@Body notificationSettingsRequest: NotificationSettingsRequest): UserProfileResponse

feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/SettingsPresenter.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.ninecraft.booket.core.common.constants.WebViewConstants
1010
import com.ninecraft.booket.core.common.utils.handleException
1111
import com.ninecraft.booket.core.data.api.repository.AuthRepository
1212
import com.ninecraft.booket.core.data.api.repository.RemoteConfigRepository
13+
import com.ninecraft.booket.core.data.api.repository.UserRepository
1314
import com.ninecraft.booket.core.model.UserState
1415
import com.ninecraft.booket.feature.screens.LoginScreen
1516
import com.ninecraft.booket.feature.screens.NotificationScreen
@@ -34,6 +35,7 @@ import kotlinx.coroutines.launch
3435
class SettingsPresenter @AssistedInject constructor(
3536
@Assisted val navigator: Navigator,
3637
private val authRepository: AuthRepository,
38+
private val userRepository: UserRepository,
3739
private val remoteConfigRepository: RemoteConfigRepository,
3840
private val analyticsHelper: AnalyticsHelper,
3941
) : Presenter<SettingsUiState> {
@@ -62,6 +64,7 @@ class SettingsPresenter @AssistedInject constructor(
6264
isLoading = true
6365
authRepository.logout()
6466
.onSuccess {
67+
userRepository.resetNotificationData()
6568
analyticsHelper.logEvent(SETTINGS_LOGOUT_COMPLETE)
6669
navigator.resetRoot(LoginScreen())
6770
}
@@ -91,6 +94,7 @@ class SettingsPresenter @AssistedInject constructor(
9194
isLoading = true
9295
authRepository.withdraw()
9396
.onSuccess {
97+
userRepository.resetNotificationData()
9498
analyticsHelper.logEvent(SETTINGS_WITHDRAWAL_COMPLETE)
9599
navigator.resetRoot(LoginScreen())
96100
}

0 commit comments

Comments
 (0)