diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f307397..4d5cef1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) implementation(libs.androidx.material.icons.extended) + implementation(libs.androidx.interpolator) debugImplementation(libs.androidx.ui.tooling) // Navigation @@ -72,4 +73,7 @@ dependencies { // Coroutines implementation(libs.kotlinx.coroutines.android) + + //Splash Screen + implementation(libs.androidx.core.splashscreen) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f67e717..4bfcaeb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,6 @@ - @@ -20,18 +19,15 @@ android:supportsRtl="true" android:theme="@style/Theme.AppFence"> - - - - - + android:theme="@style/Theme.AppFence.Splash"> + + + - - - + \ No newline at end of file diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..1ff4ad4 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/yogesh/appfence/ui/MainActivity.kt b/app/src/main/java/com/yogesh/appfence/ui/MainActivity.kt index c02f6c1..d53917d 100644 --- a/app/src/main/java/com/yogesh/appfence/ui/MainActivity.kt +++ b/app/src/main/java/com/yogesh/appfence/ui/MainActivity.kt @@ -1,7 +1,6 @@ package com.yogesh.appfence.ui import android.app.Activity -import android.content.Intent import android.net.VpnService import android.os.Bundle import android.widget.Toast @@ -13,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.ViewModelProvider import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -23,7 +23,6 @@ import com.yogesh.appfence.ui.screens.SettingsScreen import com.yogesh.appfence.ui.theme.AppFenceTheme import com.yogesh.appfence.ui.viewmodel.MainViewModel import com.yogesh.appfence.ui.viewmodel.SettingsViewModel -import com.yogesh.appfence.vpn.NetworkType /** * Single-activity host for the entire Compose UI. @@ -42,7 +41,6 @@ class MainActivity : ComponentActivity() { ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == Activity.RESULT_OK) { - // Permission granted — start VPN and complete onboarding settingsViewModel.startVpn() settingsViewModel.completeOnboarding() } else { @@ -55,54 +53,58 @@ class MainActivity : ComponentActivity() { } override fun onCreate(savedInstanceState: Bundle?) { + + val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) - enableEdgeToEdge() mainViewModel = ViewModelProvider(this)[MainViewModel::class.java] settingsViewModel = ViewModelProvider(this)[SettingsViewModel::class.java] + + splashScreen.setKeepOnScreenCondition { false } + + enableEdgeToEdge() + setContent { AppFenceTheme { val navController = rememberNavController() val onboardingCompleted by settingsViewModel.onboardingCompleted.collectAsState() val networkType by settingsViewModel.networkMonitor.networkType.collectAsState() + val isLoading by mainViewModel.isLoading.collectAsState() - val startDestination = if (onboardingCompleted) "main" else "onboarding" - - NavHost( - navController = navController, - startDestination = startDestination, - modifier = Modifier.fillMaxSize() - ) { - composable("onboarding") { - OnboardingScreen( - onGrantVpnPermission = { requestVpnPermission() } - ) - } + if (isLoading) { + com.yogesh.appfence.ui.screens.AppFenceSplashScreen() + } else { + val startDestination = if (onboardingCompleted) "main" else "onboarding" - composable("main") { - MainScreen( - viewModel = mainViewModel, - networkType = networkType, - onNavigateToSettings = { - navController.navigate("settings") - } - ) + NavHost( + navController = navController, + startDestination = startDestination, + modifier = Modifier.fillMaxSize() + ) { + composable("onboarding") { + OnboardingScreen(onGrantVpnPermission = { requestVpnPermission() }) + } + composable("main") { + MainScreen( + viewModel = mainViewModel, + networkType = networkType, + onNavigateToSettings = { navController.navigate("settings") } + ) + } + composable("settings") { + SettingsScreen( + viewModel = settingsViewModel, + onNavigateBack = { navController.popBackStack() }, + onRequestVpnPermission = { requestVpnPermission() } + ) + } } - composable("settings") { - SettingsScreen( - viewModel = settingsViewModel, - onNavigateBack = { navController.popBackStack() }, - onRequestVpnPermission = { requestVpnPermission() } - ) - } - } - - // If onboarding was just completed, navigate to main - if (onboardingCompleted && navController.currentDestination?.route == "onboarding") { - navController.navigate("main") { - popUpTo("onboarding") { inclusive = true } + if (onboardingCompleted && navController.currentDestination?.route == "onboarding") { + navController.navigate("main") { + popUpTo("onboarding") { inclusive = true } + } } } } @@ -124,9 +126,8 @@ class MainActivity : ComponentActivity() { if (prepareIntent != null) { vpnPermissionLauncher.launch(prepareIntent) } else { - // Permission already granted settingsViewModel.startVpn() settingsViewModel.completeOnboarding() } } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/yogesh/appfence/ui/screens/SplashScreen.kt b/app/src/main/java/com/yogesh/appfence/ui/screens/SplashScreen.kt new file mode 100644 index 0000000..2652599 --- /dev/null +++ b/app/src/main/java/com/yogesh/appfence/ui/screens/SplashScreen.kt @@ -0,0 +1,48 @@ +package com.yogesh.appfence.ui.screens + +import androidx.compose.animation.core.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.yogesh.appfence.R + +@Composable +fun AppFenceSplashScreen() { + val infiniteTransition = rememberInfiniteTransition(label = "SplashRotation") + val rotationAngle by infiniteTransition.animateFloat( + initialValue = 0f, + targetValue = 360f, + animationSpec = infiniteRepeatable( + animation = tween( + durationMillis = 1000, + easing = LinearEasing + ), + repeatMode = RepeatMode.Restart + ), + label = "LogoAngle" + ) + Box( + modifier = Modifier + .fillMaxSize() + .background(Color(0xFF001A35)), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(id = R.drawable.circle_logo), + contentDescription = "Loading...", + modifier = Modifier + .size(192.dp) + .rotate(rotationAngle) + ) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/circle_logo.png b/app/src/main/res/drawable/circle_logo.png new file mode 100644 index 0000000..b24e793 Binary files /dev/null and b/app/src/main/res/drawable/circle_logo.png differ diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 7680e5f..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..fd7decc Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index a76fff5..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..30ee392 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1f4a96e..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..0d6df0f Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index a8b89dd..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..0dc0be9 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 99105ec..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..376cd3f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 5593535..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..bcb1ead Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index e4911ed..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..92f7d27 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 40c8430..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..35546a4 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 5c0665d..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9a6ed90 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index bea1718..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..1379a9d Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 6366b2b..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..a7ed1e2 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 10c954a..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..f9d31d8 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index ce73f3e..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..a24e3b5 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 9a70dc1..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..55d953a Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 118c434..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1a3d9f2 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..5efdb61 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #0D1B2A + #00E5CC + \ No newline at end of file diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml index 05fb2e3..9c0476a 100644 --- a/app/src/main/res/values/ic_launcher_background.xml +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -1,4 +1,4 @@ - #0D1B2A - + #041D3B + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index f278cff..b9758e3 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,4 +1,11 @@ - + + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd0d544..c2805ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,6 +10,8 @@ navigationCompose = "2.8.5" room = "2.6.1" coroutines = "1.9.0" datastorePreferences = "1.1.1" +splashscreen = "1.0.1" +interpolator = "1.0.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -30,6 +32,8 @@ androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastorePreferences" } kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } +androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splashscreen" } +androidx-interpolator = { group = "androidx.interpolator", name = "interpolator", version.ref = "interpolator" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }