Skip to content

Commit 0c0c8a9

Browse files
authored
Merge pull request #252 from YAPP-Github/refactor/#251-fortune-create-status
[REFACTOR] ์šด์„ธ ์ƒ์„ฑ ์ƒํƒœ ๊ด€๋ฆฌ์šฉ FortuneCreateStatusFlow ๋„์ž…
2 parents 117f65d + 83c9ade commit 0c0c8a9

File tree

10 files changed

+136
-94
lines changed

10 files changed

+136
-94
lines changed

โ€Žcore/alarm/src/main/java/com/yapp/alarm/receivers/AlarmInteractionActivityReceiver.ktโ€Ž

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.content.Intent
66
import androidx.activity.ComponentActivity
77
import androidx.core.net.toUri
88
import com.yapp.alarm.AlarmConstants
9+
import com.yapp.domain.model.FortuneCreateStatus
910
import com.yapp.domain.model.MissionType
1011
import com.yapp.domain.repository.FortuneRepository
1112
import dagger.hilt.android.AndroidEntryPoint
@@ -45,31 +46,51 @@ class AlarmInteractionActivityReceiver(private val activity: ComponentActivity)
4546
CoroutineScope(Dispatchers.Main).launch {
4647
try {
4748
if (!hasValidMissionData) {
48-
val hasUnseenFortune = withContext(Dispatchers.IO) {
49-
fortuneRepository.hasUnseenFortuneFlow.first()
49+
val (fortuneCreateStatus, hasUnseenFortune) = withContext(Dispatchers.IO) {
50+
val status = fortuneRepository.fortuneCreateStatusFlow.first()
51+
val unseen = fortuneRepository.hasUnseenFortuneFlow.first()
52+
status to unseen
5053
}
51-
if (hasUnseenFortune) {
52-
context?.let { ctx ->
53-
val uri = "orbitapp://fortune".toUri()
54-
val fortuneIntent = Intent(Intent.ACTION_VIEW, uri).apply {
55-
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
56-
setPackage(ctx.packageName)
54+
55+
when (fortuneCreateStatus) {
56+
is FortuneCreateStatus.Creating -> {
57+
context?.let { ctx ->
58+
val uri = "orbitapp://fortune".toUri()
59+
val fortuneIntent = Intent(Intent.ACTION_VIEW, uri).apply {
60+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
61+
setPackage(ctx.packageName)
62+
}
63+
ctx.startActivity(fortuneIntent)
5764
}
58-
ctx.startActivity(fortuneIntent)
5965
}
60-
}
61-
return@launch
62-
}
6366

64-
context?.let { ctx ->
65-
val uriString =
66-
"orbitapp://mission?notificationId=$notificationId&missionType=${missionType.value}&missionCount=$missionCount"
67-
val missionIntent =
68-
Intent(Intent.ACTION_VIEW, uriString.toUri()).apply {
69-
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
70-
setPackage(ctx.packageName)
67+
is FortuneCreateStatus.Success -> {
68+
if (hasUnseenFortune) {
69+
context?.let { ctx ->
70+
val uri = "orbitapp://fortune".toUri()
71+
val fortuneIntent =
72+
Intent(Intent.ACTION_VIEW, uri).apply {
73+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
74+
setPackage(ctx.packageName)
75+
}
76+
ctx.startActivity(fortuneIntent)
77+
}
78+
}
7179
}
72-
ctx.startActivity(missionIntent)
80+
81+
FortuneCreateStatus.Failure, FortuneCreateStatus.Idle -> { }
82+
}
83+
} else {
84+
context?.let { ctx ->
85+
val uriString =
86+
"orbitapp://mission?notificationId=$notificationId&missionType=${missionType.value}&missionCount=$missionCount"
87+
val missionIntent =
88+
Intent(Intent.ACTION_VIEW, uriString.toUri()).apply {
89+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
90+
setPackage(ctx.packageName)
91+
}
92+
ctx.startActivity(missionIntent)
93+
}
7394
}
7495
} finally {
7596
pending.finish()

โ€Žcore/datastore/src/main/java/com/yapp/datastore/UserPreferences.ktโ€Ž

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -131,20 +131,6 @@ class UserPreferences @Inject constructor(
131131
}
132132
}
133133

134-
suspend fun tryMarkFortuneCreating(): Boolean {
135-
var canStart = false
136-
dataStore.edit { pref ->
137-
val hasTodayFortune = pref[Keys.FORTUNE_DATE] == today() && pref[Keys.FORTUNE_ID] != null
138-
val creating = pref[Keys.FORTUNE_CREATING] ?: false
139-
if (!hasTodayFortune && !creating) {
140-
pref[Keys.FORTUNE_CREATING] = true
141-
pref[Keys.FORTUNE_FAILED] = false
142-
canStart = true
143-
}
144-
}
145-
return canStart
146-
}
147-
148134
suspend fun markFortuneCreating() {
149135
dataStore.edit { pref ->
150136
pref[Keys.FORTUNE_CREATING] = true

โ€Ždata/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSource.ktโ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.yapp.data.local.datasource
22

3+
import com.yapp.domain.model.FortuneCreateStatus
34
import kotlinx.coroutines.flow.Flow
45

56
interface FortuneLocalDataSource {
@@ -9,11 +10,10 @@ interface FortuneLocalDataSource {
910
val fortuneScoreFlow: Flow<Int?>
1011
val hasUnseenFortuneFlow: Flow<Boolean>
1112
val shouldShowFortuneToolTipFlow: Flow<Boolean>
12-
val isFortuneCreatingFlow: Flow<Boolean>
13-
val isFortuneFailedFlow: Flow<Boolean>
1413
val isFirstAlarmDismissedTodayFlow: Flow<Boolean>
1514

16-
suspend fun tryMarkFortuneCreating(): Boolean
15+
val fortuneCreateStatusFlow: Flow<FortuneCreateStatus>
16+
1717
suspend fun markFortuneCreating()
1818
suspend fun markFortuneCreated(fortuneId: Long)
1919
suspend fun markFortuneFailed()

โ€Ždata/src/main/java/com/yapp/data/local/datasource/FortuneLocalDataSourceImpl.ktโ€Ž

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package com.yapp.data.local.datasource
22

33
import com.yapp.datastore.UserPreferences
4+
import com.yapp.domain.model.FortuneCreateStatus
5+
import kotlinx.coroutines.flow.combine
6+
import kotlinx.coroutines.flow.distinctUntilChanged
7+
import java.time.LocalDate
8+
import java.time.format.DateTimeFormatter
49
import javax.inject.Inject
510

611
class FortuneLocalDataSourceImpl @Inject constructor(
@@ -13,13 +18,23 @@ class FortuneLocalDataSourceImpl @Inject constructor(
1318
override val fortuneScoreFlow = userPreferences.fortuneScoreFlow
1419
override val hasUnseenFortuneFlow = userPreferences.hasUnseenFortuneFlow
1520
override val shouldShowFortuneToolTipFlow = userPreferences.shouldShowFortuneToolTipFlow
16-
override val isFortuneCreatingFlow = userPreferences.isFortuneCreatingFlow
17-
override val isFortuneFailedFlow = userPreferences.isFortuneFailedFlow
1821
override val isFirstAlarmDismissedTodayFlow = userPreferences.isFirstAlarmDismissedTodayFlow
1922

20-
override suspend fun tryMarkFortuneCreating(): Boolean {
21-
return userPreferences.tryMarkFortuneCreating()
22-
}
23+
override val fortuneCreateStatusFlow = combine(
24+
userPreferences.fortuneIdFlow,
25+
userPreferences.fortuneDateFlow,
26+
userPreferences.isFortuneCreatingFlow,
27+
userPreferences.isFortuneFailedFlow,
28+
) { fortuneId, fortuneDate, isCreating, isFailed ->
29+
when {
30+
isFailed -> FortuneCreateStatus.Failure
31+
isCreating -> FortuneCreateStatus.Creating
32+
fortuneId != null && fortuneDate == today() -> FortuneCreateStatus.Success(fortuneId)
33+
else -> FortuneCreateStatus.Idle
34+
}
35+
}.distinctUntilChanged()
36+
37+
private fun today(): String = LocalDate.now().format(DateTimeFormatter.ISO_DATE)
2338

2439
override suspend fun markFortuneCreating() {
2540
userPreferences.markFortuneCreating()

โ€Ždata/src/main/java/com/yapp/data/repositoryimpl/FortuneRepositoryImpl.ktโ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.yapp.data.local.datasource.FortuneLocalDataSource
44
import com.yapp.data.remote.datasource.FortuneDataSource
55
import com.yapp.data.remote.dto.response.toDomain
66
import com.yapp.domain.model.Fortune
7+
import com.yapp.domain.model.FortuneCreateStatus
78
import com.yapp.domain.repository.FortuneRepository
89
import kotlinx.coroutines.flow.Flow
910
import javax.inject.Inject
@@ -19,11 +20,10 @@ class FortuneRepositoryImpl @Inject constructor(
1920
override val fortuneScoreFlow: Flow<Int?> = fortuneLocalDataSource.fortuneScoreFlow
2021
override val hasUnseenFortuneFlow: Flow<Boolean> = fortuneLocalDataSource.hasUnseenFortuneFlow
2122
override val shouldShowFortuneToolTipFlow: Flow<Boolean> = fortuneLocalDataSource.shouldShowFortuneToolTipFlow
22-
override val isFortuneCreatingFlow: Flow<Boolean> = fortuneLocalDataSource.isFortuneCreatingFlow
23-
override val isFortuneFailedFlow: Flow<Boolean> = fortuneLocalDataSource.isFortuneFailedFlow
2423
override val isFirstAlarmDismissedTodayFlow: Flow<Boolean> = fortuneLocalDataSource.isFirstAlarmDismissedTodayFlow
2524

26-
override suspend fun tryMarkFortuneCreating() = fortuneLocalDataSource.tryMarkFortuneCreating()
25+
override val fortuneCreateStatusFlow: Flow<FortuneCreateStatus> = fortuneLocalDataSource.fortuneCreateStatusFlow
26+
2727
override suspend fun markFortuneAsCreating() = fortuneLocalDataSource.markFortuneCreating()
2828
override suspend fun markFortuneAsCreated(fortuneId: Long) = fortuneLocalDataSource.markFortuneCreated(fortuneId)
2929
override suspend fun markFortuneAsFailed() = fortuneLocalDataSource.markFortuneFailed()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.yapp.domain.model
2+
3+
sealed class FortuneCreateStatus {
4+
data object Idle : FortuneCreateStatus()
5+
data object Creating : FortuneCreateStatus()
6+
data class Success(val fortuneId: Long) : FortuneCreateStatus()
7+
data object Failure : FortuneCreateStatus()
8+
}

โ€Ždomain/src/main/java/com/yapp/domain/repository/FortuneRepository.ktโ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.yapp.domain.repository
22

33
import com.yapp.domain.model.Fortune
4+
import com.yapp.domain.model.FortuneCreateStatus
45
import kotlinx.coroutines.flow.Flow
56

67
interface FortuneRepository {
@@ -10,11 +11,10 @@ interface FortuneRepository {
1011
val fortuneScoreFlow: Flow<Int?>
1112
val hasUnseenFortuneFlow: Flow<Boolean>
1213
val shouldShowFortuneToolTipFlow: Flow<Boolean>
13-
val isFortuneCreatingFlow: Flow<Boolean>
14-
val isFortuneFailedFlow: Flow<Boolean>
1514
val isFirstAlarmDismissedTodayFlow: Flow<Boolean>
1615

17-
suspend fun tryMarkFortuneCreating(): Boolean
16+
val fortuneCreateStatusFlow: Flow<FortuneCreateStatus>
17+
1818
suspend fun markFortuneAsCreating()
1919
suspend fun markFortuneAsCreated(fortuneId: Long)
2020
suspend fun markFortuneAsFailed()

โ€Žfeature/fortune/src/main/java/com/yapp/fortune/FortuneViewModel.ktโ€Ž

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import android.app.Application
44
import android.util.Log
55
import androidx.annotation.DrawableRes
66
import androidx.lifecycle.ViewModel
7+
import com.yapp.domain.model.FortuneCreateStatus
78
import com.yapp.domain.repository.FortuneRepository
89
import com.yapp.fortune.page.toFortunePages
910
import com.yapp.media.decoder.ImageUtils
1011
import com.yapp.media.storage.ImageSaver
1112
import dagger.hilt.android.lifecycle.HiltViewModel
12-
import kotlinx.coroutines.flow.combine
13+
import kotlinx.coroutines.flow.first
1314
import kotlinx.coroutines.flow.firstOrNull
1415
import org.orbitmvi.orbit.Container
1516
import org.orbitmvi.orbit.ContainerHost
@@ -50,22 +51,21 @@ class FortuneViewModel @Inject constructor(
5051
}
5152

5253
private fun observeFortune() = intent {
53-
combine(
54-
fortuneRepository.fortuneIdFlow,
55-
fortuneRepository.isFirstAlarmDismissedTodayFlow,
56-
fortuneRepository.isFortuneCreatingFlow,
57-
) { fortuneId: Long?, isFirstAlarmDismissedToday: Boolean, isCreating: Boolean ->
58-
Triple(fortuneId, isFirstAlarmDismissedToday, isCreating)
59-
}.collect { (fortuneId, isFirstAlarmDismissedToday, isCreating) ->
60-
when {
61-
isCreating -> {
54+
fortuneRepository.fortuneCreateStatusFlow.collect { status ->
55+
when (status) {
56+
is FortuneCreateStatus.Creating -> {
6257
reduce { state.copy(isLoading = true) }
6358
}
64-
fortuneId != null -> {
65-
fetchAndUpdateFortune(fortuneId, isFirstAlarmDismissedToday)
59+
60+
is FortuneCreateStatus.Success -> {
61+
fetchAndUpdateFortune(
62+
fortuneId = status.fortuneId,
63+
isFirstAlarmDismissedToday = fortuneRepository.isFirstAlarmDismissedTodayFlow.first(),
64+
)
6665
}
67-
else -> {
68-
reduce { state.copy(isLoading = false) }
66+
67+
is FortuneCreateStatus.Failure, FortuneCreateStatus.Idle -> {
68+
postSideEffect(FortuneContract.SideEffect.NavigateToHome)
6969
}
7070
}
7171
}

โ€Žfeature/fortune/src/main/java/com/yapp/fortune/worker/PostFortuneWorker.ktโ€Ž

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.Context
44
import androidx.hilt.work.HiltWorker
55
import androidx.work.CoroutineWorker
66
import androidx.work.WorkerParameters
7+
import com.yapp.domain.model.FortuneCreateStatus
78
import com.yapp.domain.repository.FortuneRepository
89
import com.yapp.domain.repository.UserInfoRepository
910
import dagger.assisted.Assisted
@@ -20,35 +21,43 @@ class PostFortuneWorker @AssistedInject constructor(
2021
) : CoroutineWorker(appContext, params) {
2122

2223
override suspend fun doWork(): Result {
23-
val hasUnseenFortune = fortuneRepository.hasUnseenFortuneFlow.first()
24-
if (hasUnseenFortune) return Result.success()
25-
26-
val acquired = fortuneRepository.tryMarkFortuneCreating()
27-
if (!acquired) return Result.success()
28-
29-
val userId = userInfoRepository.userIdFlow.firstOrNull()
30-
?: run {
31-
fortuneRepository.markFortuneAsFailed()
32-
return Result.failure()
24+
when (fortuneRepository.fortuneCreateStatusFlow.first()) {
25+
is FortuneCreateStatus.Creating,
26+
is FortuneCreateStatus.Success,
27+
-> {
28+
return Result.success()
3329
}
30+
FortuneCreateStatus.Failure,
31+
FortuneCreateStatus.Idle,
32+
-> {
33+
val userId = userInfoRepository.userIdFlow.firstOrNull()
34+
?: run {
35+
// ์‚ฌ์šฉ์ž ์—†์œผ๋ฉด ์‹คํŒจ ์ƒํƒœ ํ‘œ์‹œ ํ›„ ์‹คํŒจ ๋ฐ˜ํ™˜
36+
fortuneRepository.markFortuneAsFailed()
37+
return Result.failure()
38+
}
3439

35-
return try {
36-
fortuneRepository.markFortuneAsCreating()
37-
val result = fortuneRepository.postFortune(userId)
38-
result.fold(
39-
onSuccess = { fortune ->
40-
fortuneRepository.markFortuneAsCreated(fortune.id)
41-
fortuneRepository.saveFortuneScore(fortune.avgFortuneScore)
42-
Result.success()
43-
},
44-
onFailure = { e ->
40+
return try {
41+
fortuneRepository.markFortuneAsCreating()
42+
43+
val result = fortuneRepository.postFortune(userId)
44+
result.fold(
45+
onSuccess = { fortune ->
46+
fortuneRepository.markFortuneAsCreated(fortune.id)
47+
fortuneRepository.saveFortuneScore(fortune.avgFortuneScore)
48+
Result.success()
49+
},
50+
onFailure = {
51+
fortuneRepository.markFortuneAsFailed()
52+
// WM ๋ฐฑ์˜คํ”„ ๊ทœ์น™์— ๋”ฐ๋ผ ์žฌ์‹œ๋„
53+
Result.retry()
54+
},
55+
)
56+
} catch (_: Throwable) {
4557
fortuneRepository.markFortuneAsFailed()
4658
Result.retry()
47-
},
48-
)
49-
} catch (_: Throwable) {
50-
fortuneRepository.markFortuneAsFailed()
51-
Result.retry()
59+
}
60+
}
5261
}
5362
}
5463
}

โ€Žfeature/mission/src/main/java/com/yapp/mission/MissionViewModel.ktโ€Ž

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.yapp.alarm.pendingIntent.interaction.createAlarmDismissIntent
77
import com.yapp.analytics.AnalyticsEvent
88
import com.yapp.analytics.AnalyticsHelper
99
import com.yapp.domain.MissionMode
10+
import com.yapp.domain.model.FortuneCreateStatus
1011
import com.yapp.domain.model.MissionType
1112
import com.yapp.domain.repository.FortuneRepository
1213
import com.yapp.media.haptic.HapticFeedbackManager
@@ -133,13 +134,15 @@ class MissionViewModel @Inject constructor(
133134
performHapticSuccess()
134135
logMissionSuccess(type)
135136
if (state.missionMode == MissionMode.REAL) {
136-
val hasUnseenFortune = fortuneRepository.hasUnseenFortuneFlow.first()
137-
val isFortuneCreating = fortuneRepository.isFortuneCreatingFlow.first()
138-
139-
if (hasUnseenFortune || isFortuneCreating) {
140-
postSideEffect(MissionContract.SideEffect.NavigateToFortune)
141-
} else {
142-
postSideEffect(MissionContract.SideEffect.NavigateBack)
137+
val fortuneCreateStaus = fortuneRepository.fortuneCreateStatusFlow.first()
138+
139+
when (fortuneCreateStaus) {
140+
is FortuneCreateStatus.Creating, is FortuneCreateStatus.Success -> {
141+
postSideEffect(MissionContract.SideEffect.NavigateToFortune)
142+
}
143+
FortuneCreateStatus.Failure, FortuneCreateStatus.Idle -> {
144+
postSideEffect(MissionContract.SideEffect.NavigateBack)
145+
}
143146
}
144147
} else {
145148
postSideEffect(MissionContract.SideEffect.NavigateBack)

0 commit comments

Comments
ย (0)