summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2024-06-28 14:45:01 +0200
committerDavid Göransson <david.goransson@mullvad.net>2024-07-04 12:09:36 +0200
commitd23e892ded487453ef6d8149fc3d9b7d21d72ca9 (patch)
tree45b7b78a1ae3bb941ddf8b8ffe76d67202858b5a /android/app/src
parent6ec847fea0db4223c32b7297c920ebcc71414abb (diff)
downloadmullvadvpn-d23e892ded487453ef6d8149fc3d9b7d21d72ca9.tar.xz
mullvadvpn-d23e892ded487453ef6d8149fc3d9b7d21d72ca9.zip
Add splash screen
Diffstat (limited to 'android/app/src')
-rw-r--r--android/app/src/debug/AndroidManifest.xml4
-rw-r--r--android/app/src/main/AndroidManifest.xml2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SplashCompleteRepository.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt14
7 files changed, 41 insertions, 8 deletions
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 61ef2c7e50..cfe2c7c4df 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -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>
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index f6f60cdd1f..f69801a46d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -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
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt
index f5977e7b57..a81fa5f42f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt
@@ -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
@@ -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()
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
index ec940364dc..5ecf8ecbd9 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
@@ -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
@@ -120,6 +121,7 @@ val uiModule = module {
single { SplitTunnelingRepository(get()) }
single { ApiAccessRepository(get()) }
single { NewDeviceRepository() }
+ single { SplashCompleteRepository() }
single { AccountExpiryNotificationUseCase(get()) }
single { TunnelStateNotificationUseCase(get()) }
@@ -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) }
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SplashCompleteRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SplashCompleteRepository.kt
new file mode 100644
index 0000000000..03e5b908f7
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SplashCompleteRepository.kt
@@ -0,0 +1,11 @@
+package net.mullvad.mullvadvpn.repository
+
+class SplashCompleteRepository {
+ private var splashComplete = false
+
+ fun isSplashComplete() = splashComplete
+
+ fun onSplashCompleted() {
+ splashComplete = true
+ }
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
index 7d592f468a..8339a25f61 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
@@ -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
@@ -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
@@ -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
@@ -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
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt
index bd34161e2c..cc97435105 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt
@@ -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
@@ -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()) {