Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ dependencies {
implementation libs.androidx.swiperefreshlayout
implementation libs.androidx.preference.ktx
implementation libs.androidx.security.crypto.ktx
implementation libs.androidx.splashscreen

// Compose
implementation platform(libs.compose.bom)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,36 @@ package com.runnect.runnect.presentation.splash

import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.runnect.runnect.R
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.runnect.runnect.presentation.login.LoginActivity
import com.runnect.runnect.presentation.scheme.SchemeActivity

import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch

@AndroidEntryPoint
class SplashActivity : AppCompatActivity() {
private val handler = Handler(Looper.getMainLooper())
private val viewModel: SplashViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { !viewModel.isReady.value }
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
navigateToLoginScreen()
}

private fun navigateToLoginScreen() {
handler.postDelayed({
val intent = Intent(this, LoginActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
startActivity(intent)
finish()
}, DELAY_TIME)
}
enableEdgeToEdge()

companion object {
private const val DELAY_TIME = 1000L
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.navigateEvent.collect {
startActivity(Intent(this@SplashActivity, LoginActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
})
finish()
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.runnect.runnect.presentation.splash

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class SplashViewModel @Inject constructor() : ViewModel() {

private val _isReady = MutableStateFlow(false)
val isReady: StateFlow<Boolean> = _isReady.asStateFlow()

private val _navigateEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
val navigateEvent: SharedFlow<Unit> = _navigateEvent.asSharedFlow()

init {
viewModelScope.launch {
delay(SPLASH_DELAY)
_isReady.value = true
_navigateEvent.emit(Unit)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
}

companion object {
const val SPLASH_DELAY = 1000L
}
}
9 changes: 0 additions & 9 deletions app/src/main/res/layout/activity_splash.xml

This file was deleted.

8 changes: 4 additions & 4 deletions app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
<item name="editTextStyle">@style/Widget.Runnect.EditText</item>
</style>

<style name="SplashTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowBackground">@drawable/splash</item>
<style name="SplashTheme" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/white</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash</item>
<item name="postSplashScreenTheme">@style/Theme.Runnect</item>
</style>

<!-- 신고하기 BottomSheet 테마 -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.runnect.runnect.presentation.splash

import app.cash.turbine.test
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class SplashViewModelTest {
private val testDispatcher = StandardTestDispatcher()

@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
}

@After
fun tearDown() {
Dispatchers.resetMain()
}

@Test
fun `초기 상태에서 isReady는 false다`() {
val viewModel = SplashViewModel()
assertFalse(viewModel.isReady.value)
}

@Test
fun `1초 경과 전에는 isReady가 false다`() = runTest(testDispatcher) {
val viewModel = SplashViewModel()
advanceTimeBy(SplashViewModel.SPLASH_DELAY - 1)
assertFalse(viewModel.isReady.value)
}

@Test
fun `1초 경과 후 isReady가 true가 된다`() = runTest(testDispatcher) {
val viewModel = SplashViewModel()
advanceUntilIdle()
assertTrue(viewModel.isReady.value)
}

@Test
fun `1초 후 navigateEvent가 emit된다`() = runTest(testDispatcher) {
val viewModel = SplashViewModel()
viewModel.navigateEvent.test {
advanceTimeBy(SplashViewModel.SPLASH_DELAY)
awaitItem()
cancelAndIgnoreRemainingEvents()
}
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ viewpager2 = "1.1.0"
swiperefreshlayout = "1.2.0"
preference-ktx = "1.2.1"
security-crypto = "1.1.0"
splashscreen = "1.0.1"

# Compose
compose-bom = "2026.03.01"
Expand Down Expand Up @@ -106,6 +107,7 @@ androidx-viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", vers
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
androidx-preference-ktx = { group = "androidx.preference", name = "preference-ktx", version.ref = "preference-ktx" }
androidx-security-crypto-ktx = { group = "androidx.security", name = "security-crypto-ktx", version.ref = "security-crypto" }
androidx-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splashscreen" }

# Compose
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
Expand Down
Loading