Skip to content

Commit

Permalink
Merge branch 'android-splash-screen'
Browse files Browse the repository at this point in the history
  • Loading branch information
Rawa committed Jul 4, 2024
2 parents 8263dc7 + d23e892 commit c59d28f
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 15 deletions.
1 change: 1 addition & 0 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ dependencies {
implementation(Dependencies.commonsValidator)
implementation(Dependencies.AndroidX.activityCompose)
implementation(Dependencies.AndroidX.coreKtx)
implementation(Dependencies.AndroidX.coreSplashscreen)
implementation(Dependencies.AndroidX.lifecycleRuntimeKtx)
implementation(Dependencies.AndroidX.lifecycleViewmodelKtx)
implementation(Dependencies.AndroidX.lifecycleRuntimeCompose)
Expand Down
4 changes: 2 additions & 2 deletions android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
tools:ignore="ScopedStorage" />
<application android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
android:theme="@style/Theme.App.Starting"
android:extractNativeLibs="true"
android:allowBackup="false"
android:banner="@drawable/banner"
android:name=".MullvadApplication"
tools:ignore="DataExtractionRules,GoogleAppIndexingWarning"></application>
tools:ignore="DataExtractionRules,GoogleAppIndexingWarning"/>
</manifest>
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
android:theme="@style/Theme.App.Starting"
tools:ignore="GoogleAppIndexingWarning">
<!--
MainActivity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import com.ramcosta.composedestinations.generated.destinations.PrivacyDisclaimer
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar
import net.mullvad.mullvadvpn.compose.transitions.DefaultTransition
import net.mullvad.mullvadvpn.compose.util.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
Expand All @@ -45,7 +44,7 @@ private fun PreviewLoadingScreen() {
}

// Set this as the start destination of the default nav graph
@Destination<RootGraph>(start = true, style = DefaultTransition::class)
@Destination<RootGraph>(start = true)
@Composable
fun Splash(navigator: DestinationsNavigator) {
val viewModel: SplashViewModel = koinViewModel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import net.mullvad.mullvadvpn.repository.RelayListFilterRepository
import net.mullvad.mullvadvpn.repository.RelayListRepository
import net.mullvad.mullvadvpn.repository.RelayOverridesRepository
import net.mullvad.mullvadvpn.repository.SettingsRepository
import net.mullvad.mullvadvpn.repository.SplashCompleteRepository
import net.mullvad.mullvadvpn.repository.SplitTunnelingRepository
import net.mullvad.mullvadvpn.ui.serviceconnection.AppVersionInfoRepository
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
Expand Down Expand Up @@ -120,6 +121,7 @@ val uiModule = module {
single { SplitTunnelingRepository(get()) }
single { ApiAccessRepository(get()) }
single { NewDeviceRepository() }
single { SplashCompleteRepository() }

single { AccountExpiryNotificationUseCase(get()) }
single { TunnelStateNotificationUseCase(get()) }
Expand Down Expand Up @@ -182,7 +184,7 @@ val uiModule = module {
viewModel { PrivacyDisclaimerViewModel(get(), IS_PLAY_BUILD) }
viewModel { SelectLocationViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { SettingsViewModel(get(), get(), IS_PLAY_BUILD) }
viewModel { SplashViewModel(get(), get(), get()) }
viewModel { SplashViewModel(get(), get(), get(), get()) }
viewModel { VoucherDialogViewModel(get()) }
viewModel { VpnSettingsViewModel(get(), get(), get()) }
viewModel { WelcomeViewModel(get(), get(), get(), get(), isPlayBuild = IS_PLAY_BUILD) }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.mullvad.mullvadvpn.repository

class SplashCompleteRepository {
private var splashComplete = false

fun isSplashComplete() = splashComplete

fun onSplashCompleted() {
splashComplete = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
Expand All @@ -17,6 +18,7 @@ import net.mullvad.mullvadvpn.lib.common.util.SdkUtils.requestNotificationPermis
import net.mullvad.mullvadvpn.lib.intent.IntentProvider
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository
import net.mullvad.mullvadvpn.repository.SplashCompleteRepository
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.viewmodel.NoDaemonViewModel
import org.koin.android.ext.android.getKoin
Expand All @@ -31,6 +33,8 @@ class MainActivity : ComponentActivity() {

private lateinit var privacyDisclaimerRepository: PrivacyDisclaimerRepository
private lateinit var serviceConnectionManager: ServiceConnectionManager
private lateinit var splashCompleteRepository: SplashCompleteRepository
private var isReadyNextDraw: Boolean = false
private lateinit var noDaemonViewModel: NoDaemonViewModel
private lateinit var intentProvider: IntentProvider

Expand All @@ -45,16 +49,21 @@ class MainActivity : ComponentActivity() {
serviceConnectionManager = get()
noDaemonViewModel = get()
intentProvider = get()
splashCompleteRepository = get()
}
lifecycle.addObserver(noDaemonViewModel)

installSplashScreen().setKeepOnScreenCondition {
val isReady = isReadyNextDraw
isReadyNextDraw = splashCompleteRepository.isSplashComplete()
!isReady
}
super.onCreate(savedInstanceState)

// Needs to be before set content since we want to access the intent in compose
if (savedInstanceState == null) {
intentProvider.setStartIntent(intent)
}

setContent { AppTheme { MullvadApp() } }

// This is to protect against tapjacking attacks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package net.mullvad.mullvadvpn.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
Expand All @@ -14,14 +16,24 @@ import net.mullvad.mullvadvpn.lib.model.DeviceState
import net.mullvad.mullvadvpn.lib.shared.AccountRepository
import net.mullvad.mullvadvpn.lib.shared.DeviceRepository
import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository
import net.mullvad.mullvadvpn.repository.SplashCompleteRepository

data class SplashScreenState(val splashComplete: Boolean = false)

class SplashViewModel(
private val privacyDisclaimerRepository: PrivacyDisclaimerRepository,
private val accountRepository: AccountRepository,
private val deviceRepository: DeviceRepository,
private val splashCompleteRepository: SplashCompleteRepository
) : ViewModel() {

val uiSideEffect = flow { emit(getStartDestination()) }
val uiSideEffect = flow {
emit(getStartDestination())
splashCompleteRepository.onSplashCompleted()
}

private val _uiState = MutableStateFlow<SplashScreenState>(SplashScreenState(false))
val uiState: StateFlow<SplashScreenState> = _uiState

private suspend fun getStartDestination(): SplashUiSideEffect {
if (!privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) {
Expand Down
1 change: 1 addition & 0 deletions android/buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ object Dependencies {
"androidx.activity:activity-compose:${Versions.AndroidX.activityCompose}"
const val appcompat = "androidx.appcompat:appcompat:${Versions.AndroidX.appcompat}"
const val coreKtx = "androidx.core:core-ktx:${Versions.AndroidX.coreKtx}"
const val coreSplashscreen = "androidx.core:core-splashscreen:${Versions.AndroidX.coreSplashscreen}"
const val fragmentTestning =
"androidx.fragment:fragment-testing:${Versions.AndroidX.fragmentTesting}"
const val lifecycleRuntimeKtx =
Expand Down
1 change: 1 addition & 0 deletions android/buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ object Versions {
const val activityCompose = "1.9.0"
const val appcompat = "1.7.0"
const val coreKtx = "1.12.0"
const val coreSplashscreen = "1.1.0-rc01"
const val espresso = "3.6.1"
const val lifecycle = "2.8.2"
const val fragmentTesting = "1.8.1"
Expand Down
8 changes: 8 additions & 0 deletions android/gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,14 @@
<sha256 value="4d46646066c794f2812d5b33a9422d37e4f918c4d809cd1fb2579c7022ef2818" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.core" name="core-splashscreen" version="1.1.0-rc01">
<artifact name="core-splashscreen-1.1.0-rc01.aar">
<sha256 value="3b14be0db541a7847d072bd78ba0818d7ca7b4fb6a2214943bf4fe16921dc6c3" origin="Generated by Gradle"/>
</artifact>
<artifact name="core-splashscreen-1.1.0-rc01.module">
<sha256 value="4d7e4a3ee0b721e5e371fa01def735559ad3a4a66d24a84587117d7a1e5f5cbe" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.cursoradapter" name="cursoradapter" version="1.0.0">
<artifact name="cursoradapter-1.0.0.aar">
<sha256 value="a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564" origin="Generated by Gradle"/>
Expand Down
5 changes: 4 additions & 1 deletion android/lib/resource/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ android {
}
}

dependencies { implementation(Dependencies.AndroidX.appcompat) }
dependencies {
implementation(Dependencies.AndroidX.appcompat)
implementation(Dependencies.AndroidX.coreSplashscreen)
}
Loading

0 comments on commit c59d28f

Please sign in to comment.