Skip to content
Open
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
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@ dependencies {

// Coroutines
implementation(libs.kotlinx.coroutines.android)

//Splash Screen
implementation("androidx.core:core-splashscreen:1.0.1")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style / Project Conventions

Hardcoded dependency string instead of version catalog

PR adds:

implementation("androidx.core:core-splashscreen:1.0.1")

Should be β€” add to libs.versions.toml first:

implementation(libs.androidx.core.splashscreen)

Every other dependency in build.gradle.kts uses libs.*, so this should follow the same convention for consistency.

}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:theme="@style/Theme.AppFence">
android:theme="@style/Theme.AppFence.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down
27 changes: 25 additions & 2 deletions app/src/main/java/com/yogesh/appfence/ui/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.yogesh.appfence.ui

import android.animation.ObjectAnimator
import android.app.Activity
import android.content.Intent
import android.net.VpnService
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
Expand All @@ -13,6 +14,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.core.animation.doOnEnd
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
Expand All @@ -23,7 +26,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.
Expand Down Expand Up @@ -55,7 +57,28 @@ class MainActivity : ComponentActivity() {
}

override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]

@yogesh-7 yogesh-7 May 1, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate ViewModel initialization in MainActivity.kt

The PR correctly moves mainViewModel and settingsViewModel initialization earlier (to use them in setKeepOnScreenCondition), but the original initialization lines further down in onCreate were not removed.

As a result, both ViewModels are being constructed twice on every cold start.

Fix:

Remove the duplicate initialization lines (the ones in the original position):

mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
settingsViewModel = ViewModelProvider(this)[SettingsViewModel::class.java]

settingsViewModel = ViewModelProvider(this)[SettingsViewModel::class.java]


splashScreen.setKeepOnScreenCondition {
mainViewModel.isLoading.value
}

//Subtle fade-out animation
splashScreen.setOnExitAnimationListener { splashScreenView ->
val fadeOut = ObjectAnimator.ofFloat(
splashScreenView.view,
View.ALPHA,
1f,
0f
)
fadeOut.duration = 400L //400ms fade
fadeOut.doOnEnd { splashScreenView.remove() }
fadeOut.start()
}
enableEdgeToEdge()

mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
Expand Down
34 changes: 34 additions & 0 deletions app/src/main/res/drawable/avd_appfence_pulse.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:drawable="@drawable/ic_appfence_logo">

<target android:name="wifi_arc_inner">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="strokeAlpha"
android:duration="800"
android:valueFrom="0.3"
android:valueTo="1.0"
android:valueType="floatType"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
</aapt:attr>
</target>

<target android:name="wifi_arc_outer">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="strokeAlpha"
android:duration="800"
android:startOffset="200"
android:valueFrom="0.3"
android:valueTo="1.0"
android:valueType="floatType"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
</aapt:attr>
</target>
</animated-vector>
53 changes: 53 additions & 0 deletions app/src/main/res/drawable/ic_appfence_logo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocker

ic_appfence_logo.xml β€” licensing risk

You can Use These for now also update the App icon if you use this

Image Image

android:height="108dp"
android:viewportHeight="64"
android:viewportWidth="64"
android:width="108dp">

<group
android:translateX="8"
android:translateY="8">
<path
android:fillColor="#00000000"
android:pathData="M18.61,27.2c0,-3.58 1.83,-5.92 5.41,-5.92s5.37,2.34 5.37,5.92"
android:strokeColor="#00E5CC"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2"/>

<path
android:fillColor="#00000000"
android:pathData="M17.54,31s-0.16,5.89 1.07,8.08S24,43.9 24,43.9s4.15,-2.66 5.39,-4.85S30.46,31 30.46,31 26.22,29.36 24,29.36 17.54,31 17.54,31Z"
android:strokeColor="#00E5CC"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2"/>

<path
android:name="wifi_arc_inner"
android:fillColor="#00000000"
android:pathData="M13.33,16.75A18.38,18.38 0,0 1,24 13.14,18.32 18.32,0 0,1 34.6,16.75"
android:strokeColor="#00E5CC"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2"/>

<path
android:name="wifi_arc_outer"
android:fillColor="#00000000"
android:pathData="M6.76,11A26.7,26.7 0,0 1,24 4.9c6.14,0 12.82,2.15 17.24,6.14"
android:strokeColor="#00E5CC"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="2"/>

<path
android:fillColor="#00E5CC"
android:pathData="M24,32.39a1.72,1.72 0,0 0,-1.71 1.71,1.67 1.67,0 0,0 0.5,1.2l-0.49,3.42h3.41L25.2,35.3a1.67,1.67 0,0 0,0.5 -1.2A1.71,1.71 0,0 0,24 32.39Z"
android:strokeColor="#00E5CC"
android:strokeLineCap="round"
android:strokeLineJoin="round"
android:strokeWidth="1"/>
</group>

</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_background">#0D1B2A</color>
<color name="splash_teal">#00E5CC</color>
</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.AppFence" parent="android:Theme.Material.NoActionBar" />
<style name="Theme.AppFence.Splash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/splash_background</item>
<item name="postSplashScreenTheme">@style/Theme.AppFence</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/avd_appfence_pulse</item>
<item name="windowSplashScreenAnimationDuration">800</item>
</style>
</resources>