Skip to content

Commit 94aeb45

Browse files
authored
Merge pull request #255 from YAPP-Github/release/1.1.3
Merge release/1.1.3 to develop
2 parents 8852463 + 700e803 commit 94aeb45

File tree

78 files changed

+1216
-638
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1216
-638
lines changed

.github/workflows/android_ci.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,6 @@ on:
77
- '**/*.kt'
88
- 'build.gradle'
99
- 'app/**'
10-
push:
11-
branches:
12-
- 'release/**'
13-
paths:
14-
- '**/*.kt'
15-
- 'build.gradle'
16-
- 'app/**'
1710

1811
jobs:
1912
build:

app/build.gradle.kts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ plugins {
88

99
android {
1010
namespace = "com.yapp.orbit"
11+
compileSdk = 35
1112

1213
defaultConfig {
13-
versionCode = 5
14-
versionName = "1.0.3"
14+
versionCode = 6
15+
versionName = "1.1.3"
1516
targetSdk = 35
1617
}
1718

@@ -53,4 +54,6 @@ dependencies {
5354
implementation(libs.firebase.crashlytics)
5455
implementation(libs.play.services.ads)
5556
implementation(libs.kotlin.reflect)
57+
implementation(libs.hilt.worker)
58+
implementation(libs.androidx.work.runtime)
5659
}

app/src/main/AndroidManifest.xml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
1212
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
1313
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
14+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
1415

1516
<application
1617
android:name=".OrbitApplication"
@@ -46,9 +47,7 @@
4647
<action android:name="android.intent.action.VIEW" />
4748
<category android:name="android.intent.category.DEFAULT" />
4849
<category android:name="android.intent.category.BROWSABLE" />
49-
<data
50-
android:scheme="orbitapp"
51-
android:host="mission"/>
50+
<data android:scheme="orbitapp" />
5251
</intent-filter>
5352
</activity>
5453

@@ -80,5 +79,15 @@
8079
<service
8180
android:name="com.yapp.alarm.services.AlarmService"
8281
android:foregroundServiceType="mediaPlayback" />
82+
83+
<provider
84+
android:name="androidx.startup.InitializationProvider"
85+
android:authorities="${applicationId}.androidx-startup"
86+
android:exported="false"
87+
tools:node="merge">
88+
<meta-data
89+
android:name="androidx.work.WorkManagerInitializer"
90+
tools:node="remove" />
91+
</provider>
8392
</application>
8493
</manifest>
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
package com.yapp.orbit
22

33
import android.app.Application
4+
import androidx.hilt.work.HiltWorkerFactory
5+
import androidx.work.Configuration
46
import com.google.android.gms.ads.MobileAds
57
import dagger.hilt.android.HiltAndroidApp
8+
import javax.inject.Inject
69

710
@HiltAndroidApp
8-
class OrbitApplication : Application() {
11+
class OrbitApplication() : Application(), Configuration.Provider {
12+
13+
@Inject lateinit var workerFactory: HiltWorkerFactory
14+
915
override fun onCreate() {
1016
super.onCreate()
1117
MobileAds.initialize(this)
1218
}
19+
20+
override val workManagerConfiguration: Configuration
21+
get() = Configuration.Builder()
22+
.setWorkerFactory(workerFactory)
23+
.build()
1324
}

app/src/main/java/com/yapp/orbit/OrbitNavHost.kt

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,16 @@ import androidx.compose.animation.fadeIn
66
import androidx.compose.animation.fadeOut
77
import androidx.compose.animation.slideInVertically
88
import androidx.compose.animation.slideOutVertically
9-
import androidx.compose.foundation.background
109
import androidx.compose.foundation.layout.Box
11-
import androidx.compose.foundation.layout.BoxScope
12-
import androidx.compose.foundation.layout.WindowInsets
13-
import androidx.compose.foundation.layout.fillMaxWidth
14-
import androidx.compose.foundation.layout.navigationBars
10+
import androidx.compose.foundation.layout.navigationBarsPadding
1511
import androidx.compose.foundation.layout.padding
16-
import androidx.compose.foundation.layout.windowInsetsBottomHeight
1712
import androidx.compose.material3.Scaffold
1813
import androidx.compose.material3.SnackbarHost
1914
import androidx.compose.material3.SnackbarHostState
2015
import androidx.compose.runtime.Composable
2116
import androidx.compose.runtime.remember
22-
import androidx.compose.ui.Alignment
2317
import androidx.compose.ui.Modifier
24-
import androidx.compose.ui.graphics.Color
2518
import androidx.compose.ui.unit.dp
26-
import androidx.compose.ui.zIndex
2719
import androidx.navigation.compose.NavHost
2820
import com.yapp.common.navigation.OrbitNavigator
2921
import com.yapp.common.navigation.rememberOrbitNavigator
@@ -34,9 +26,9 @@ import com.yapp.mission.missionScreen
3426
import com.yapp.onboarding.onboardingNavGraph
3527
import com.yapp.setting.settingNavGraph
3628
import com.yapp.splash.splashScreen
37-
import com.yapp.ui.component.bottomsheet.OrbitBottomSheetLayout
3829
import com.yapp.ui.component.bottomsheet.OrbitBottomSheetState
3930
import com.yapp.ui.component.bottomsheet.rememberOrbitBottomSheetState
31+
import com.yapp.ui.component.navigation.NavigationBarScrim
4032
import com.yapp.ui.component.snackbar.CustomSnackBarVisuals
4133
import com.yapp.ui.component.snackbar.OrbitSnackBar
4234
import com.yapp.webview.webViewScreen
@@ -51,18 +43,16 @@ internal fun OrbitNavHost(
5143
val snackBarHostState = remember { SnackbarHostState() }
5244

5345
Box {
54-
OrbitBottomSheetLayout(sheetState = bottomSheetState) {
55-
Scaffold(
56-
modifier = modifier,
57-
snackbarHost = { OrbitSnackBarHost(snackBarHostState) },
58-
containerColor = OrbitTheme.colors.gray_900,
59-
) {
60-
OrbitNavigationGraph(
61-
navigator = navigator,
62-
bottomSheetState = bottomSheetState,
63-
snackBarHostState = snackBarHostState,
64-
)
65-
}
46+
Scaffold(
47+
modifier = modifier,
48+
snackbarHost = { OrbitSnackBarHost(snackBarHostState) },
49+
containerColor = OrbitTheme.colors.gray_900,
50+
) {
51+
OrbitNavigationGraph(
52+
navigator = navigator,
53+
bottomSheetState = bottomSheetState,
54+
snackBarHostState = snackBarHostState,
55+
)
6656
}
6757

6858
NavigationBarScrim()
@@ -76,6 +66,7 @@ private fun OrbitNavigationGraph(
7666
snackBarHostState: SnackbarHostState,
7767
) {
7868
NavHost(
69+
modifier = Modifier.navigationBarsPadding(),
7970
navController = navigator.navController,
8071
startDestination = navigator.startDestination,
8172
) {
@@ -89,18 +80,6 @@ private fun OrbitNavigationGraph(
8980
}
9081
}
9182

92-
@Composable
93-
private fun BoxScope.NavigationBarScrim() {
94-
Box(
95-
modifier = Modifier
96-
.align(Alignment.BottomCenter)
97-
.fillMaxWidth()
98-
.windowInsetsBottomHeight(WindowInsets.navigationBars)
99-
.background(Color.Black)
100-
.zIndex(1f),
101-
)
102-
}
103-
10483
@Composable
10584
private fun OrbitSnackBarHost(
10685
snackBarHostState: SnackbarHostState,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.yapp.orbit.di
2+
3+
import com.yapp.orbit.BuildConfig
4+
import dagger.Module
5+
import dagger.Provides
6+
import dagger.hilt.InstallIn
7+
import dagger.hilt.components.SingletonComponent
8+
import javax.inject.Named
9+
import javax.inject.Singleton
10+
11+
@Module
12+
@InstallIn(SingletonComponent::class)
13+
object AppVersionModule {
14+
@Provides
15+
@Singleton
16+
@Named("appVersion")
17+
fun provideAppVersion(): String = BuildConfig.VERSION_NAME
18+
}

build-logic/src/main/java/com/yapp/convention/HiltAndroid.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ internal fun Project.configureHiltAndroid() {
1414
dependencies {
1515
"implementation"(libs.findLibrary("hilt.android").get())
1616
"ksp"(libs.findLibrary("hilt.android.compiler").get())
17+
"ksp"(libs.findLibrary("androidx-hilt-compiler").get())
1718
"implementation"(libs.findLibrary("hilt-navigation-compose").get())
19+
"implementation"(libs.findLibrary("hilt-worker").get())
1820
}
1921
}
2022

build-logic/src/main/java/orbit.android.feature.gradle.kts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import com.yapp.convention.configureHiltAndroid
21
import com.yapp.convention.libs
32

43
plugins {
54
id("orbit.android.library")
65
id("orbit.android.compose")
76
}
87

9-
configureHiltAndroid()
10-
118
dependencies {
129
implementation(project(":core:designsystem"))
1310
implementation(project(":core:ui"))

core/alarm/src/main/java/com/yapp/alarm/AndroidAlarmScheduler.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.yapp.alarm
22

33
import android.app.AlarmManager
44
import android.app.Application
5+
import android.util.Log
56
import com.yapp.alarm.pendingIntent.schedule.createAlarmReceiverPendingIntentForSchedule
67
import com.yapp.alarm.pendingIntent.schedule.createAlarmReceiverPendingIntentForUnSchedule
78
import com.yapp.domain.model.Alarm
@@ -16,6 +17,15 @@ class AndroidAlarmScheduler @Inject constructor(
1617
private val alarmTimeCalculator: AlarmTimeCalculator,
1718
) : AlarmScheduler {
1819

20+
private fun logSchedule(tag: String, alarm: Alarm, triggerMillis: Long, extra: String = "") {
21+
Log.d("ScheduleTrace", "scheduleAlarm Called", Throwable())
22+
Log.d(
23+
"AlarmSchedule",
24+
"[$tag] id=${alarm.id}, repeatDays=${alarm.repeatDays}, " +
25+
"time=${java.time.Instant.ofEpochMilli(triggerMillis)} $extra",
26+
)
27+
}
28+
1929
override fun scheduleAlarm(alarm: Alarm) {
2030
val selectedDays = alarm.repeatDays.toAlarmDays()
2131

@@ -31,7 +41,7 @@ class AndroidAlarmScheduler @Inject constructor(
3141
private fun setRepeatingAlarm(day: AlarmDay, alarm: Alarm) {
3242
val triggerMillis = alarmTimeCalculator.calculateNextRepeatingTimeMillis(alarm, day)
3343
val pendingIntent = createAlarmReceiverPendingIntentForSchedule(app, alarm, day)
34-
44+
logSchedule("REPEAT", alarm, triggerMillis, "day=$day")
3545
alarmManager.setExactAndAllowWhileIdle(
3646
AlarmManager.RTC_WAKEUP,
3747
triggerMillis,
@@ -42,7 +52,7 @@ class AndroidAlarmScheduler @Inject constructor(
4252
private fun setNonRepeatingAlarm(alarm: Alarm) {
4353
val triggerMillis = alarmTimeCalculator.calculateNonRepeatingTimeMillis(alarm)
4454
val pendingIntent = createAlarmReceiverPendingIntentForSchedule(app, alarm)
45-
55+
logSchedule("NON_REPEAT", alarm, triggerMillis)
4656
alarmManager.setExactAndAllowWhileIdle(
4757
AlarmManager.RTC_WAKEUP,
4858
triggerMillis,
@@ -53,7 +63,7 @@ class AndroidAlarmScheduler @Inject constructor(
5363
fun rescheduleUpcomingWeeklyAlarm(alarm: Alarm, day: AlarmDay) {
5464
val triggerMillis = alarmTimeCalculator.calculateNextWeeklyRescheduledTimeMillis(alarm, day)
5565
val pendingIntent = createAlarmReceiverPendingIntentForSchedule(app, alarm, day)
56-
66+
logSchedule("RESCHEDULE_WEEKLY", alarm, triggerMillis, "day=$day")
5767
alarmManager.setExactAndAllowWhileIdle(
5868
AlarmManager.RTC_WAKEUP,
5969
triggerMillis,

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

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ package com.yapp.alarm.receivers
33
import android.content.BroadcastReceiver
44
import android.content.Context
55
import android.content.Intent
6-
import android.util.Log
76
import androidx.activity.ComponentActivity
87
import androidx.core.net.toUri
98
import com.yapp.alarm.AlarmConstants
9+
import com.yapp.domain.model.FortuneCreateStatus
10+
import com.yapp.domain.model.MissionType
1011
import com.yapp.domain.repository.FortuneRepository
1112
import dagger.hilt.android.AndroidEntryPoint
1213
import kotlinx.coroutines.CoroutineScope
1314
import kotlinx.coroutines.Dispatchers
14-
import kotlinx.coroutines.flow.firstOrNull
15+
import kotlinx.coroutines.flow.first
1516
import kotlinx.coroutines.launch
16-
import java.time.LocalDate
17-
import java.time.format.DateTimeFormatter
17+
import kotlinx.coroutines.withContext
1818
import javax.inject.Inject
1919

2020
@AndroidEntryPoint
@@ -31,29 +31,69 @@ class AlarmInteractionActivityReceiver(private val activity: ComponentActivity)
3131

3232
if (!isSnoozed) {
3333
val notificationId = intent.getLongExtra(AlarmConstants.EXTRA_NOTIFICATION_ID, -1L)
34-
val missionType = intent.getIntExtra(AlarmConstants.EXTRA_MISSION_TYPE, -1)
34+
val missionTypeRaw = intent.getIntExtra(AlarmConstants.EXTRA_MISSION_TYPE, -1)
3535
val missionCount = intent.getIntExtra(AlarmConstants.EXTRA_MISSION_COUNT, -1)
3636

37-
if (notificationId == -1L || missionType == -1 || missionCount == -1) {
38-
Log.e("AlarmInteraction", "필수 값 누락")
39-
return
40-
}
37+
val missionType = MissionType.fromInt(missionTypeRaw)
38+
39+
val hasValidMissionData = (
40+
notificationId != -1L &&
41+
missionType != MissionType.NONE &&
42+
missionCount != -1
43+
)
44+
45+
val pending = goAsync()
46+
CoroutineScope(Dispatchers.Main).launch {
47+
try {
48+
if (!hasValidMissionData) {
49+
val (fortuneCreateStatus, hasUnseenFortune) = withContext(Dispatchers.IO) {
50+
val status = fortuneRepository.fortuneCreateStatusFlow.first()
51+
val unseen = fortuneRepository.hasUnseenFortuneFlow.first()
52+
status to unseen
53+
}
4154

42-
CoroutineScope(Dispatchers.IO).launch {
43-
val fortuneDate = fortuneRepository.fortuneDateFlow.firstOrNull()
44-
val todayDate = LocalDate.now().format(DateTimeFormatter.ISO_DATE)
45-
46-
if (fortuneDate != todayDate) {
47-
context?.let {
48-
val uriString =
49-
"orbitapp://mission?notificationId=$notificationId&missionType=$missionType&missionCount=$missionCount"
50-
val missionIntent =
51-
Intent(Intent.ACTION_VIEW, uriString.toUri()).apply {
52-
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
53-
setPackage(context.packageName)
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)
64+
}
5465
}
55-
it.startActivity(missionIntent)
66+
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+
}
79+
}
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+
}
5694
}
95+
} finally {
96+
pending.finish()
5797
}
5898
}
5999
}

0 commit comments

Comments
 (0)