Browse Source

API Integration Started...

Khubaib 1 year ago
parent
commit
e712dca010
56 changed files with 3794 additions and 290 deletions
  1. 25 5
      app/build.gradle.kts
  2. 2 0
      app/src/main/AndroidManifest.xml
  3. 4 0
      app/src/main/java/com/vpn/fastestvpnservice/MainActivity.kt
  4. 19 0
      app/src/main/java/com/vpn/fastestvpnservice/application/App.java
  5. 66 0
      app/src/main/java/com/vpn/fastestvpnservice/application/BaseApplication.java
  6. 25 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/DataResponse.kt
  7. 17 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/IpInfo.kt
  8. 9 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/Notification.kt
  9. 17 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/Product.kt
  10. 23 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/ProductFeatures.kt
  11. 5 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/Protocol.kt
  12. 46 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/SelectApplicationEntry.kt
  13. 32 88
      app/src/main/java/com/vpn/fastestvpnservice/beans/Server.kt
  14. 12 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/ServerData.kt
  15. 89 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/ServerList.kt
  16. 12 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/ServerResponse.kt
  17. 34 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/SettingsData.kt
  18. 21 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/UpgradePrice.kt
  19. 19 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/User.kt
  20. 27 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/UserResponse.kt
  21. 7 0
      app/src/main/java/com/vpn/fastestvpnservice/beans/WireGuard.kt
  22. 45 0
      app/src/main/java/com/vpn/fastestvpnservice/broadcasts/ConnectivityReceiver.java
  23. 29 0
      app/src/main/java/com/vpn/fastestvpnservice/constants/AppConstant.kt
  24. 23 0
      app/src/main/java/com/vpn/fastestvpnservice/constants/AppEnum.kt
  25. 5 5
      app/src/main/java/com/vpn/fastestvpnservice/customItems/CountryItem.kt
  26. 9 9
      app/src/main/java/com/vpn/fastestvpnservice/customItems/ServerItem.kt
  27. 0 1
      app/src/main/java/com/vpn/fastestvpnservice/customItems/SubscriptionDataItem.kt
  28. 452 0
      app/src/main/java/com/vpn/fastestvpnservice/helpers/BasePreferenceHelper.kt
  29. 114 0
      app/src/main/java/com/vpn/fastestvpnservice/helpers/PreferencesHelper.java
  30. 408 0
      app/src/main/java/com/vpn/fastestvpnservice/helpers/UIHelper.java
  31. 3 2
      app/src/main/java/com/vpn/fastestvpnservice/navigation/BottomBarNavGraph.kt
  32. 2 1
      app/src/main/java/com/vpn/fastestvpnservice/navigation/NavGraph.kt
  33. 43 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/Api.kt
  34. 170 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/RetrofitNetworkHandling.java
  35. 60 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/WebResponse.java
  36. 11 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/WebServiceConstants.java
  37. 71 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/WebServiceFactory.java
  38. 186 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/GsonFactory.java
  39. 19 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ResultResponse.java
  40. 47 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ServiceDate.java
  41. 36 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ServiceDateTime.java
  42. 20 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ServiceTime.java
  43. 28 13
      app/src/main/java/com/vpn/fastestvpnservice/screens/BottomBarMainScreen.kt
  44. 176 53
      app/src/main/java/com/vpn/fastestvpnservice/screens/LoginScreen.kt
  45. 29 3
      app/src/main/java/com/vpn/fastestvpnservice/screens/ServerListScreen.kt
  46. 183 56
      app/src/main/java/com/vpn/fastestvpnservice/screens/SignUpScreen.kt
  47. 19 21
      app/src/main/java/com/vpn/fastestvpnservice/screens/SplashScreen.kt
  48. 1 2
      app/src/main/java/com/vpn/fastestvpnservice/screens/accountScreensAll/FavoriteServersScreen.kt
  49. 129 30
      app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/AccountScreen.kt
  50. 5 1
      app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/HomeScreen.kt
  51. 279 0
      app/src/main/java/com/vpn/fastestvpnservice/utils/CheckInternetConnection.java
  52. 100 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/AccountViewModel.kt
  53. 110 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/LoginViewModel.kt
  54. 400 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/ServerListViewModel.kt
  55. 70 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SignUpViewModel.kt
  56. 1 0
      app/src/main/res/values/strings.xml

+ 25 - 5
app/build.gradle.kts

@@ -28,6 +28,13 @@ android {
                 "proguard-rules.pro"
             )
         }
+        debug {
+            isMinifyEnabled = false
+            proguardFiles(
+                getDefaultProguardFile("proguard-android-optimize.txt"),
+                "proguard-rules.pro"
+            )
+        }
     }
     compileOptions {
         sourceCompatibility = JavaVersion.VERSION_1_8
@@ -54,15 +61,28 @@ dependencies {
     implementation("androidx.core:core-ktx:1.12.0")
     implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
     implementation("androidx.activity:activity-compose:1.8.2")
+    implementation("androidx.fragment:fragment-ktx:1.6.2")
+    implementation("androidx.activity:activity-ktx:1.8.2")
     implementation(platform("androidx.compose:compose-bom:2023.08.00"))
     implementation("androidx.compose.ui:ui")
     implementation("androidx.compose.ui:ui-graphics")
     implementation("androidx.compose.ui:ui-tooling-preview")
-    implementation("androidx.compose.material3:material3:1.1.2")
-    implementation("androidx.compose.material:material:1.6.0")
-    implementation("androidx.navigation:navigation-compose:2.7.6")
-    implementation("androidx.compose.material:material-icons-extended:1.5.4")
-    implementation("androidx.compose.ui:ui-text-google-fonts:1.5.4")
+    implementation("androidx.compose.material3:material3:1.2.0")
+    implementation("androidx.compose.material:material:1.6.1")
+    implementation("androidx.navigation:navigation-compose:2.7.7")
+    implementation("androidx.compose.material:material-icons-extended:1.6.1")
+    implementation("androidx.compose.ui:ui-text-google-fonts:1.6.1")
+
+    // Retrofit
+    implementation("com.squareup.retrofit2:retrofit:2.9.0")
+    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
+    implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
+
+    // Coroutines
+    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
+
+    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
+    implementation("androidx.compose.runtime:runtime-livedata:1.6.1")
 
     testImplementation("junit:junit:4.13.2")
     androidTestImplementation("androidx.test.ext:junit:1.1.5")

+ 2 - 0
app/src/main/AndroidManifest.xml

@@ -2,9 +2,11 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
 
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application
+        android:name=".application.App"
         android:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
         android:fullBackupContent="@xml/backup_rules"

+ 4 - 0
app/src/main/java/com/vpn/fastestvpnservice/MainActivity.kt

@@ -4,6 +4,7 @@ import android.os.Bundle
 import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
+import androidx.activity.viewModels
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.material.ripple.LocalRippleTheme
@@ -20,14 +21,17 @@ import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.tooling.preview.Preview
+import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.beans.isDarkTheme
 import com.vpn.fastestvpnservice.beans.selectedtheme
 import com.vpn.fastestvpnservice.beans.themesList
 import com.vpn.fastestvpnservice.navigation.SetUpNavGraph
 import com.vpn.fastestvpnservice.ui.theme.FastestVPNTheme
+import com.vpn.fastestvpnservice.viewmodels.LoginViewModel
 
 class MainActivity : ComponentActivity() {
+    val loginViewModel: LoginViewModel by viewModels()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)

+ 19 - 0
app/src/main/java/com/vpn/fastestvpnservice/application/App.java

@@ -0,0 +1,19 @@
+package com.vpn.fastestvpnservice.application;
+
+import android.app.Application;
+
+public class App extends Application {
+
+    private static App instance;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        instance = this;
+    }
+
+    public static App getApplication() {
+        return instance;
+    }
+}

+ 66 - 0
app/src/main/java/com/vpn/fastestvpnservice/application/BaseApplication.java

@@ -0,0 +1,66 @@
+package com.vpn.fastestvpnservice.application;
+
+import android.app.Application;
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import com.vpn.fastestvpnservice.R;
+import com.vpn.fastestvpnservice.broadcasts.ConnectivityReceiver;
+
+
+public class BaseApplication extends Application {
+
+    private static BaseApplication instance;
+
+   /* public static BaseApplication getApplication() {
+        return instance;
+    }*/
+
+    public void setConnectivityListener(ConnectivityReceiver.ConnectivityReceiverListener listener) {
+        ConnectivityReceiver.connectivityReceiverListener = listener;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        // TODO uncomment_this_JC
+//        FirebaseApp.initializeApp(this);
+//        FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true);
+        instance = this;
+
+        // TODO uncomment_this_JC
+//        initializeImageloader();
+
+    }
+
+    public static BaseApplication getApplication() {
+        return instance;
+    }
+
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+    }
+
+    public void initializeImageloader() {
+        // TODO uncomment_this_JC
+//        DisplayImageOptions options = new DisplayImageOptions.Builder()
+//                .showImageForEmptyUri(R.drawable.ic_launcher_foreground)
+//                .showImageOnFail(R.drawable.ic_launcher_foreground)
+//                .showImageOnLoading(R.drawable.ic_launcher_foreground)
+//                .resetViewBeforeLoading(true)
+//                .cacheInMemory(true)
+//                .cacheOnDisc(true)
+//                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
+//                .displayer(new FadeInBitmapDisplayer(300))
+//                .bitmapConfig(Bitmap.Config.RGB_565).build();
+//
+//        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
+//                getApplicationContext()).defaultDisplayImageOptions(options)
+//                .build();
+//
+//        com.nostra13.universalimageloader.core.ImageLoader.getInstance().init(config);
+//        L.disableLogging();
+    }
+}

+ 25 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/DataResponse.kt

@@ -0,0 +1,25 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+data class DataResponse<T>(
+    @SerializedName("status") var status: Boolean,
+    @SerializedName("message") var message: String? = null,
+    @SerializedName("data") var data: T? = null
+)
+
+data class DataResponseServers<T>(
+    @SerializedName("status") var status: Boolean,
+    @SerializedName("message") var message: String? = null,
+    @SerializedName("product") val product: Product? = null,
+    @SerializedName("wg") val wireguard: WireGuard? = null,
+    @SerializedName("enabled_protocols") var enabled_protocols: ArrayList<String>,
+    @SerializedName("available_protocols") var available_protocols: ArrayList<String>,
+    @SerializedName("data") var data: T? = null
+)
+
+data class DataResponseToken(
+    @SerializedName("status") var status: Boolean,
+    @SerializedName("message") var message: String? = null,
+    @SerializedName("data") var data: TokenResponse? = null
+)

+ 17 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/IpInfo.kt

@@ -0,0 +1,17 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+class IpInfo(
+    @SerializedName("status") var status: String? = null,
+    @SerializedName("country") var country: String? = null,
+    @SerializedName("countryCode") var countryCode: String? = null,
+    @SerializedName("region") var region: String? = null,
+    @SerializedName("regionName") var regionName: String? = null,
+    @SerializedName("city") var city: String? = null,
+    @SerializedName("timezone") var timezone: String? = null,
+    @SerializedName("query") var query: String? = null,
+    @SerializedName("zip") var zip: String? = null,
+    @SerializedName("lat") var latitute: Double? = null,
+    @SerializedName("lon") var longitude: Double? = null
+)

+ 9 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/Notification.kt

@@ -0,0 +1,9 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+data class Notification(
+    @SerializedName("id") var id: String,
+    @SerializedName("title") var title: String,
+    @SerializedName("html") var html: String
+)

+ 17 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/Product.kt

@@ -0,0 +1,17 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+class Product(
+
+    @SerializedName("productName") var productName: String? = null,
+    @SerializedName("productId") val productId: Int? = null,
+    @SerializedName("serviceId") val serviceId: Int? = null,
+    @SerializedName("billingCycle") val billingCycle: String? = null,
+    @SerializedName("regDate") val regDate: String? = null,
+    @SerializedName("status") val status: String? = null,
+    @SerializedName("suspenduntil") val suspenduntil: String? = null,
+    @SerializedName("identifier") var identifier: String? = null,
+    @SerializedName("is_pro") val is_pro: Boolean? = null
+
+    )

+ 23 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/ProductFeatures.kt

@@ -0,0 +1,23 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+class ProductFeatures (
+    @SerializedName("features") var features: ArrayList<Features>? = null,
+    @SerializedName("identifier") var identifier: String? = null,
+    @SerializedName("title") var title: String? = null,
+    @SerializedName("description") var description: String? = null,
+    @SerializedName("price") var price: String? = null,
+    var isSelected: Boolean? = null,
+    var double: Double
+
+)
+
+class Features(
+    @SerializedName("title") var title: String? = null,
+    @SerializedName("details") var details: String? = null
+    )
+
+class TokenResponse(
+    @SerializedName("token") var token: String? = null
+)

+ 5 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/Protocol.kt

@@ -0,0 +1,5 @@
+package com.vpn.fastestvpnservice.beans
+
+class Protocol(
+    var full_name:String, var title: String, var index: Int
+)

+ 46 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/SelectApplicationEntry.kt

@@ -0,0 +1,46 @@
+package com.vpn.fastestvpnservice.beans
+
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.graphics.drawable.Drawable
+import java.text.Collator
+
+class SelectApplicationEntry : Comparable<SelectApplicationEntry> {
+
+    constructor(packageManager: PackageManager?, info: ApplicationInfo) {
+        mInfo = info
+        val name = info.loadLabel(packageManager!!)
+        mName = name.toString()
+        mIcon = info.loadIcon(packageManager)
+    }
+
+    private var mInfo: ApplicationInfo? = null
+    private var mIcon: Drawable? = null
+    private var mName: String? = null
+    private var mSelected = false
+
+    fun setSelected(selected: Boolean) {
+        mSelected = selected
+    }
+
+    fun isSelected(): Boolean {
+        return mSelected
+    }
+
+    fun getInfo(): ApplicationInfo? {
+        return mInfo
+    }
+
+    fun getIcon(): Drawable? {
+        return mIcon
+    }
+
+    override fun toString(): String {
+        return mName!!
+    }
+
+    override fun compareTo(another: SelectApplicationEntry): Int {
+        return Collator.getInstance().compare(toString(), another.toString())
+    }
+}
+

+ 32 - 88
app/src/main/java/com/vpn/fastestvpnservice/beans/Server.kt

@@ -1,91 +1,35 @@
 package com.vpn.fastestvpnservice.beans
 
-import androidx.compose.ui.graphics.painter.Painter
-import com.vpn.fastestvpnservice.R
-
-data class Server(
-    val country: String,
-    val serverName: String,
-    val ping: String,
-    val icon: Int
-)
-
-data class CountryServer(
-    val country: String,
-    val icon: Int,
-    val server: List<Server>?
-)
-
-val favList = listOf(
-    Server("Spain", "Barcelona", "130ms", R.drawable.spainlogo3x),
-//    Server("Spain", "Barcelona", "130ms", R.drawable.spainlogo3x),
-//    Server("Spain", "Barcelona", "130ms", R.drawable.spainlogo3x)
-)
-
-val favServersList = listOf(
-    Server("Spain", "Barcelona", "95ms", R.drawable.spainlogo3x),
-    Server("Pakistan", "Karachi", "95ms", R.drawable.pklogo3x),
-    Server("Spain", "Rome", "95ms", R.drawable.spainlogo3x),
-    Server("Pakistan", "Lahore", "95ms", R.drawable.pklogo3x),
-    Server("Spain", "Italy", "95ms", R.drawable.spainlogo3x),
-)
-
-val smartList = listOf(Server("Spain", "Rome", "124ms", R.drawable.spainlogo3x))
-
-val recentList = listOf(
-    Server("Pakistan", "Multan", "95ms", R.drawable.pklogo3x),
-    Server("Pakistan", "Islamabad", "85ms", R.drawable.pklogo3x)
-)
-
-val recommendedList = listOf(
-    Server("Spain", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("Spain", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("Spain", "Milan", "85ms", R.drawable.spainlogo3x)
-)
-
-val streamingList = listOf(
-    Server("Streaming Spain", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("Streaming Spain", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("Streaming Spain", "Milan", "85ms", R.drawable.spainlogo3x)
-)
-
-val dvpnList = listOf(
-    Server("UK VIA USA", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("USA VIA CANADA", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("CANADA VIA UK", "Milan", "85ms", R.drawable.spainlogo3x)
-)
-
-val p2pList = listOf(
-    Server("P2P UK", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("P2P USA", "Milan", "85ms", R.drawable.spainlogo3x),
-    Server("P2P CANADA", "Milan", "85ms", R.drawable.spainlogo3x)
-)
-
-val countryList = listOf(
-    Server("Spain", "Venice", "101ms", R.drawable.spainlogo3x),
-    Server("Spain", "Italy", "102ms", R.drawable.spainlogo3x),
-    Server("Spain", "Rome", "103ms", R.drawable.spainlogo3x),
-    Server("Spain", "Venice", "104ms", R.drawable.spainlogo3x),
-    Server("Spain", "Italy", "105ms", R.drawable.spainlogo3x),
-    )
-
-val countryList2 = listOf(
-    Server("Spain", "Venice", "101ms", R.drawable.spainlogo3x)
-)
-
-val countryList3 = listOf(
-    Server("Spain", "Venice", "101ms", R.drawable.spainlogo3x)
-)
-
-val countryList4 = listOf(
-    Server("Pakistan", "Karachi", "107ms", R.drawable.pklogo3x),
-    Server("Pakistan", "Lahore", "108ms", R.drawable.pklogo3x)
-)
-
-val allLocationsList = listOf(
-    CountryServer("USA", R.drawable.spainlogo3x, countryList),
-    CountryServer("Argentina", R.drawable.spainlogo3x, countryList2),
-    CountryServer("Germany", R.drawable.spainlogo3x, countryList3),
-    CountryServer("Pakistan", R.drawable.pklogo3x, countryList4)
-
+import com.google.gson.annotations.SerializedName
+
+class Server(
+
+    @SerializedName("id") var id: Int? = null,
+    @SerializedName("continent") val continent: String? = null,
+    @SerializedName("country") val country: String? = null,
+    @SerializedName("state") val state: String? = null,
+    @SerializedName("city") val city: Any? = null,
+    @SerializedName("name") val name: String? = null,
+    @SerializedName("dns") val dns: String? = null,
+    @SerializedName("iso") val iso: String? = null,
+    @SerializedName("lt") val lt: Double? = null,
+    @SerializedName("lg") var lg: Double? = null,
+    @SerializedName("ip") val ip: Any? = null,
+    @SerializedName("port") val port: String? = null,
+    @SerializedName("protocol") val protocol: String? = null,
+    @SerializedName("ipsec") val ipsec: Any? = null,
+    @SerializedName("remote_id") val remoteId: Any? = null,
+    @SerializedName("is_trial") val isTrial: Boolean? = null,
+    @SerializedName("active") val active: Boolean? = null,
+    @SerializedName("flag") val flag: String? = null,
+    @SerializedName("server_name") val server_name: String? = null,
+    @SerializedName("is_favourited") var isFavourited: Boolean? = null,
+    @SerializedName("country_sort") val country_sort: Int = 0,
+    @SerializedName("connection_count") val connection_count: Int = 0,
+    @SerializedName("wg_key") val wg_key: String? = null,
+    @SerializedName("enable") var enable: Int = 1,
+    var countryServers: List<Server>,
+    var totalServers: Int = 1,
+    var enableServers: Int = 1,
+    var distance: Float = 0.0f
 )

+ 12 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/ServerData.kt

@@ -0,0 +1,12 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+import java.util.*
+
+class ServerData(
+    @SerializedName("name")
+    var name: String? = null,
+    @SerializedName("servers")
+    val servers: ArrayList<Server>? = null,
+    val isSelected: Boolean = false
+)

+ 89 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/ServerList.kt

@@ -0,0 +1,89 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.vpn.fastestvpnservice.R
+
+data class ServerList(
+    val country: String,
+    val ServerListName: String,
+    val ping: String,
+    val icon: Int
+)
+
+data class CountryServerList(
+    val country: String,
+    val icon: Int,
+    val server: List<ServerList>?
+)
+
+val favList = listOf(
+    ServerList("Spain", "Barcelona", "130ms", R.drawable.spainlogo3x),
+//    ServerList("Spain", "Barcelona", "130ms", R.drawable.spainlogo3x),
+//    ServerList("Spain", "Barcelona", "130ms", R.drawable.spainlogo3x)
+)
+
+val favServerListsList = listOf(
+    ServerList("Spain", "Barcelona", "95ms", R.drawable.spainlogo3x),
+    ServerList("Pakistan", "Karachi", "95ms", R.drawable.pklogo3x),
+    ServerList("Spain", "Rome", "95ms", R.drawable.spainlogo3x),
+    ServerList("Pakistan", "Lahore", "95ms", R.drawable.pklogo3x),
+    ServerList("Spain", "Italy", "95ms", R.drawable.spainlogo3x),
+)
+
+val smartList = listOf(ServerList("Spain", "Rome", "124ms", R.drawable.spainlogo3x))
+
+val recentList = listOf(
+    ServerList("Pakistan", "Multan", "95ms", R.drawable.pklogo3x),
+    ServerList("Pakistan", "Islamabad", "85ms", R.drawable.pklogo3x)
+)
+
+val recommendedList = listOf(
+    ServerList("Spain", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("Spain", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("Spain", "Milan", "85ms", R.drawable.spainlogo3x)
+)
+
+val streamingList = listOf(
+    ServerList("Streaming Spain", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("Streaming Spain", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("Streaming Spain", "Milan", "85ms", R.drawable.spainlogo3x)
+)
+
+val dvpnList = listOf(
+    ServerList("UK VIA USA", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("USA VIA CANADA", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("CANADA VIA UK", "Milan", "85ms", R.drawable.spainlogo3x)
+)
+
+val p2pList = listOf(
+    ServerList("P2P UK", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("P2P USA", "Milan", "85ms", R.drawable.spainlogo3x),
+    ServerList("P2P CANADA", "Milan", "85ms", R.drawable.spainlogo3x)
+)
+
+val countryList = listOf(
+    ServerList("Spain", "Venice", "101ms", R.drawable.spainlogo3x),
+    ServerList("Spain", "Italy", "102ms", R.drawable.spainlogo3x),
+    ServerList("Spain", "Rome", "103ms", R.drawable.spainlogo3x),
+    ServerList("Spain", "Venice", "104ms", R.drawable.spainlogo3x),
+    ServerList("Spain", "Italy", "105ms", R.drawable.spainlogo3x),
+    )
+
+val countryList2 = listOf(
+    ServerList("Spain", "Venice", "101ms", R.drawable.spainlogo3x)
+)
+
+val countryList3 = listOf(
+    ServerList("Spain", "Venice", "101ms", R.drawable.spainlogo3x)
+)
+
+val countryList4 = listOf(
+    ServerList("Pakistan", "Karachi", "107ms", R.drawable.pklogo3x),
+    ServerList("Pakistan", "Lahore", "108ms", R.drawable.pklogo3x)
+)
+
+val allLocationsList = listOf(
+    CountryServerList("USA", R.drawable.spainlogo3x, countryList),
+    CountryServerList("Argentina", R.drawable.spainlogo3x, countryList2),
+    CountryServerList("Germany", R.drawable.spainlogo3x, countryList3),
+    CountryServerList("Pakistan", R.drawable.pklogo3x, countryList4)
+)

+ 12 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/ServerResponse.kt

@@ -0,0 +1,12 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+class ServerResponse(
+
+    @SerializedName("error") var error: Int?,
+    @SerializedName("message") val message: String?
+//    @SerializedName("servers") val servers: List<Server>
+
+)
+

+ 34 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/SettingsData.kt

@@ -0,0 +1,34 @@
+package com.vpn.fastestvpnservice.beans
+
+import android.graphics.drawable.Drawable
+
+class SettingsData (
+    var iconItem: String,
+    var iconName: String
+    )
+
+class TvSplitTunneling(
+    var appId: Int,
+    var appNames: String,
+    var appIcons: Drawable,
+    var appPackageName: String
+)
+
+class TvEnableApps(
+    var appId: Int,
+    var appNames: String,
+    var appPackageName: String
+)
+
+class TvDisableApps(
+    var appId: Int,
+    var appNames: String,
+    var appPackageName: String
+)
+
+class TvDrawableNames(
+    var appId: Int,
+    var appNames: String,
+    var appPackageName: String,
+    var appIcons: Drawable
+)

+ 21 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/UpgradePrice.kt

@@ -0,0 +1,21 @@
+package com.vpn.fastestvpnservice.beans
+
+data class UpgradePrice(
+    var title: String,
+    var subTitle: String
+)
+
+data class TvAppsList(
+    var title: String,
+    var index: Int
+)
+
+data class UpgradePriceList(
+    var title: String,
+    var description: String,
+    var price: String,
+    var validity: String,
+    var isEnabled: Boolean,
+    var intValue: Int
+)
+

+ 19 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/User.kt

@@ -0,0 +1,19 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+data class User(
+
+    @SerializedName("firstname") var firstname: String? = null,
+    @SerializedName("lastname") val lastname: String? = null,
+    @SerializedName("email") val email: String? = null,
+    @SerializedName("address") val address: String? = null,
+    @SerializedName("city") val city: String? = null,
+    @SerializedName("state") val state: String? = null,
+    @SerializedName("countrycode") val countrycode: Any? = null,
+    @SerializedName("phonenumber") val phonenumber: String? = null,
+    @SerializedName("countryname") val countryname: Any? = null,
+    @SerializedName("uniqueid") val uniqueid: String? = null,
+    @SerializedName("subscription") val subscription: Boolean = false
+
+)

+ 27 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/UserResponse.kt

@@ -0,0 +1,27 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+import java.util.*
+
+data class UserResponse(
+
+    @SerializedName("error") var error: Int? = null,
+
+    @SerializedName("id") val id: Int? = null,
+
+    @SerializedName("token") val token: String? = null,
+
+    @SerializedName("userinfo") val userinfo: User? = null,
+
+    @SerializedName("servers") val servers: ArrayList<ServerData>? = null,
+
+    @SerializedName("product") val product: Product? = null,
+
+    @SerializedName("subscription") val subscription: Boolean = false,
+
+    @SerializedName("wg") val wireguard: WireGuard? = null,
+
+    @SerializedName("enabled_protocols") var enabled_protocols: ArrayList<String>,
+
+    @SerializedName("available_protocols") var available_protocols: ArrayList<String>
+)

+ 7 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/WireGuard.kt

@@ -0,0 +1,7 @@
+package com.vpn.fastestvpnservice.beans
+
+import com.google.gson.annotations.SerializedName
+
+data class WireGuard(
+    @SerializedName("key") var key: String? = null, @SerializedName("ip") val ip: String? = null
+)

+ 45 - 0
app/src/main/java/com/vpn/fastestvpnservice/broadcasts/ConnectivityReceiver.java

@@ -0,0 +1,45 @@
+package com.vpn.fastestvpnservice.broadcasts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import com.vpn.fastestvpnservice.application.App;
+
+public class ConnectivityReceiver
+        extends BroadcastReceiver {
+
+    public static ConnectivityReceiverListener connectivityReceiverListener;
+
+    public ConnectivityReceiver() {
+        super();
+    }
+
+    public static boolean isConnected() {
+        ConnectivityManager
+                cm = (ConnectivityManager) App.getApplication().getApplicationContext()
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+        return activeNetwork != null
+                && activeNetwork.isConnectedOrConnecting();
+    }
+
+    @Override
+    public void onReceive(Context context, Intent arg1) {
+        ConnectivityManager cm = (ConnectivityManager) context
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+        boolean isConnected = activeNetwork != null
+                && activeNetwork.isConnectedOrConnecting();
+
+        if (connectivityReceiverListener != null) {
+            connectivityReceiverListener.onNetworkConnectionChanged(isConnected);
+        }
+    }
+
+
+    public interface ConnectivityReceiverListener {
+        void onNetworkConnectionChanged(boolean isConnected);
+    }
+}

+ 29 - 0
app/src/main/java/com/vpn/fastestvpnservice/constants/AppConstant.kt

@@ -0,0 +1,29 @@
+package com.vpn.fastestvpnservice.constants
+
+class AppConstant {
+
+    companion object {
+
+        const val SIGN_UP_WEBVIEW_URL = "https://fastestvpn.com/buy-vpn"
+        const val UPGRADE_WEBVIEW_URL = "https://fastestvpn.com/buy-vpn"
+
+        const val FAQ_WEBVIEW_URL = "https://fastestvpn.com/faq?device=android"
+        const val CHANGE_PASSWORD_URL = "https://fastestvpn.com/password/reset"
+        const val POLICY_WEBVIEW_URL = "https://fastestvpn.com/privacy-policy?device=android"
+        const val TERMS_WEBVIEW_URL = "https://fastestvpn.com/terms-of-service?device=android"
+        const val ABOUT_WEBVIEW_URL = "https://fastestvpn.com/about?device=android"
+        const val CHAT_WEBVIEW_URL = "https://api.fastestvpn.com/v2/chat?device=android&email="
+
+        //Api Base Url
+        const val BASE_URL = "https://api.fastestvpn.com/v2/"
+        var IS_DEBUG = false
+
+        // Params
+        const val DISPLAY_FAVOURITE_ENABLE = "display_favourite_enable"
+        const val NOTIFICATION_CHANNEL_ID = "com.vpn.fastestvpnservice"
+
+        const val SERVER = "server"
+        const val USER_RESPONSE = "user_response"
+
+    }
+}

+ 23 - 0
app/src/main/java/com/vpn/fastestvpnservice/constants/AppEnum.kt

@@ -0,0 +1,23 @@
+package com.vpn.fastestvpnservice.constants
+
+enum class AppEnum(val key: String,var title:String = "") {
+
+    SCREEN_NAME("SCREEN_NAME"), PRIVACY_POLICY("Privacy policy"), TERM_CONDITION("Terms and Conditions"), LOGIN_SCREEN(
+        "LOGIN_SCREEN"
+    ),
+    HELP_SCREEN("HELP"), SIGNUP_SCREEN("SIGNUP_SCREEN"), FORGOT_PASS_SCREEN("FORGOT_PASS_SCREEN"), WELCOME_SCREEN(
+        "WELCOME_SCREEN"
+    ),
+    HOME_SCREEN("HOME_SCREEN"), AUTO_PROTOCOL("AUTO","Auto"), IKEV2_PROTOCOL("IKEV2","IKEv2"), TCP_PROTOCOL("TCP","OpenVPN TCP"), UDP_PROTOCOL(
+        "UDP","OpenVPN UDP"
+    ),
+    FREE("com.fastestvpn.vpn.free"), LIFETIME_OLD("com.fastestvpn.vpn.lifetime.old"),
+    LIFETIME_NEW("com.fastestvpn.vpn.lifetime.new"), PRO("com.fastestvpn.vpn.pro"),
+    ONE_MONTH("com.fastestvpn.vpn.one.month"), ONE_YEAR("com.fastestvpn.vpn.one.year"),
+    TWO_YEARS("com.fastestvpn.vpn.two.years"), THREE_YEARS("com.fastestvpn.vpn.three.years"),
+    FIVE_YEARS("com.fastestvpn.vpn.five.years"),
+    WG_PROTOCOL(
+        "WG","WireGuard"
+    );
+
+}

+ 5 - 5
app/src/main/java/com/vpn/fastestvpnservice/customItems/CountryItem.kt

@@ -40,13 +40,13 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import com.vpn.fastestvpnservice.R
-import com.vpn.fastestvpnservice.beans.CountryServer
+import com.vpn.fastestvpnservice.beans.CountryServerList
 import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.allLocationsList
 import com.vpn.fastestvpnservice.beans.favList
 
 @Composable
-fun CountryItem(server: CountryServer) {
+fun CountryItem(server: CountryServerList) {
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -220,7 +220,7 @@ fun CountryItem(server: CountryServer) {
 }
 
 @Composable
-fun ColumnScope.ExpandableRow(server: CountryServer) {
+fun ColumnScope.ExpandableRow(server: CountryServerList) {
     val context = LocalContext.current
 
     Column(
@@ -249,13 +249,13 @@ fun ColumnScope.ExpandableRow(server: CountryServer) {
                                 Toast
                                     .makeText(
                                         context,
-                                        serverInfo.serverName,
+                                        serverInfo.ServerListName,
                                         Toast.LENGTH_SHORT
                                     )
                                     .show()
                             }
                     ) {
-                        Text(text = serverInfo.serverName,
+                        Text(text = serverInfo.ServerListName,
                             style = TextStyle(
                                 fontSize = 16.sp,
                                 color = MaterialTheme.colorScheme.primary

+ 9 - 9
app/src/main/java/com/vpn/fastestvpnservice/customItems/ServerItem.kt

@@ -38,11 +38,11 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.Server
+import com.vpn.fastestvpnservice.beans.ServerList
 import com.vpn.fastestvpnservice.beans.favList
-import com.vpn.fastestvpnservice.beans.favServersList
 
 @Composable
-fun ServerItem(server: Server) {
+fun ServerItem(server: ServerList) {
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -64,7 +64,7 @@ fun ServerItem(server: Server) {
                     Toast
                         .makeText(
                             context,
-                            server.serverName,
+                            server.ServerListName,
                             Toast.LENGTH_SHORT
                         )
                         .show()
@@ -147,7 +147,7 @@ fun ServerItem(server: Server) {
 }
 
 @Composable
-fun FavoriteServerItem(server: Server) {
+fun FavoriteServerItem(server: ServerList) {
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -169,7 +169,7 @@ fun FavoriteServerItem(server: Server) {
                     Toast
                         .makeText(
                             context,
-                            server.serverName,
+                            server.ServerListName,
                             Toast.LENGTH_SHORT
                         )
                         .show()
@@ -253,7 +253,7 @@ fun FavoriteServerItem(server: Server) {
 }
 
 @Composable
-fun ServerSearchItem(server: Server) {
+fun ServerSearchItem(server: ServerList) {
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -276,7 +276,7 @@ fun ServerSearchItem(server: Server) {
                     Toast
                         .makeText(
                             context,
-                            server.serverName,
+                            server.ServerListName,
                             Toast.LENGTH_SHORT
                         )
                         .show()
@@ -367,13 +367,13 @@ fun ServerItemPreview() {
 @Preview
 @Composable
 fun FavoriteServerItemPreview() {
-    FavoriteServerItem(server = favServersList[0])
+    FavoriteServerItem(server = favList[0])
 }
 
 @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
 @Composable
 fun FavoriteServerItemPreviewDark() {
-    FavoriteServerItem(server = favServersList[0])
+    FavoriteServerItem(server = favList[0])
 }
 
 @Preview

+ 0 - 1
app/src/main/java/com/vpn/fastestvpnservice/customItems/SubscriptionDataItem.kt

@@ -42,7 +42,6 @@ import androidx.compose.ui.unit.sp
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.SubscriptionDataList
-import com.vpn.fastestvpnservice.beans.favServersList
 import com.vpn.fastestvpnservice.beans.subscriptionList
 
 @Composable

+ 452 - 0
app/src/main/java/com/vpn/fastestvpnservice/helpers/BasePreferenceHelper.kt

@@ -0,0 +1,452 @@
+package com.vpn.fastestvpnservice.helpers
+
+import android.app.Activity
+import android.content.Context
+import android.graphics.drawable.AdaptiveIconDrawable
+import android.graphics.drawable.Drawable
+import android.util.Log
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.beans.*
+import com.vpn.fastestvpnservice.constants.AppEnum
+
+class BasePreferenceHelper(private val context: Context) : PreferencesHelper() {
+
+    fun clearAllData() {
+        removePreference(context, KEY_FILENAME, KEY_USER)
+        removePreference(context, KEY_FILENAME, KEY_USER_PASSWORD)
+        removePreference(context, KEY_FILENAME, KEY_SERVERS_DATA)
+//        removePreference(context, KEY_FILENAME, KEY_SERVERS)
+        removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS)
+        removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN)
+        removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW)
+        removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL)
+        removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV)
+        removePreference(context, KEY_FILENAME, PROTOCOL)
+        removePreference(context, KEY_FILENAME, X_PLATFORM_TOKEN)
+        removePreference(context, KEY_FILENAME, KEY_PRODUCT)
+        removePreference(context, KEY_FILENAME, KEY_AVAILABLE_PROTOCOLS)
+        removePreference(context, KEY_FILENAME, KEY_ENABLED_PROTOCOLS)
+        removePreference(context, KEY_FILENAME, KEY_WIREGUARD)
+        removePreference(context, KEY_FILENAME, KEY_FEATURES_DATA)
+        removePreference(context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV)
+        removePreference(context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV)
+        removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY)
+        removePreference(context, KEY_FILENAME, TV_SPLIT_CLASS)
+        removePreference(context, KEY_FILENAME, KEY_ADBLOCK_SWITCH)
+        removePreference(context, KEY_FILENAME, KEY_ISLOGGEDIN)
+    }
+
+    fun saveUser(user: UserResponse) {
+        putStringPreference(context, KEY_FILENAME, KEY_USER, Gson().toJson(user))
+    }
+
+    fun getUser(): UserResponse? {
+        return Gson().fromJson<UserResponse>(
+            getStringPreference(context, KEY_FILENAME, KEY_USER), UserResponse::class.java
+        )
+    }
+
+    fun saveProduct(product: Product) {
+        putStringPreference(context, KEY_FILENAME, KEY_PRODUCT, Gson().toJson(product))
+    }
+
+    fun getProduct(): Product? {
+        return Gson().fromJson<Product>(
+            getStringPreference(context, KEY_FILENAME, KEY_PRODUCT), Product::class.java
+        )
+    }
+
+    fun saveWireGuard(wireGuard: WireGuard) {
+        putStringPreference(context, KEY_FILENAME, KEY_WIREGUARD, Gson().toJson(wireGuard))
+    }
+
+    fun getWireGuard(): WireGuard? {
+        return Gson().fromJson<WireGuard>(
+            getStringPreference(context, KEY_FILENAME, KEY_WIREGUARD), WireGuard::class.java
+        )
+    }
+
+    fun saveIpInfo(ipInfo: IpInfo) {
+        putStringPreference(context, KEY_FILENAME, KEY_IPINFO, Gson().toJson(ipInfo))
+    }
+
+    fun getIpinfo(): IpInfo? {
+        return Gson().fromJson<IpInfo>(
+            getStringPreference(context, KEY_FILENAME, KEY_IPINFO), IpInfo::class.java
+        )
+    }
+
+    fun savePassword(pass: String) {
+        putStringPreference(context, KEY_FILENAME, KEY_USER_PASSWORD, pass)
+    }
+
+    fun getPassword(): String {
+        return getStringPreference(context, KEY_FILENAME, KEY_USER_PASSWORD)
+    }
+
+    fun saveServerData(list: ArrayList<ServerData>) {
+        putStringPreference(context, KEY_FILENAME, KEY_SERVERS_DATA, Gson().toJson(list))
+    }
+
+    fun getServerData(): List<ServerData> {
+        val type = object : TypeToken<List<ServerData?>?>() {}.type
+        return Gson().fromJson<List<ServerData>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_SERVERS_DATA
+            ), type
+        )
+    }
+
+    fun saveFeaturesData(list: ArrayList<ProductFeatures>) {
+        putStringPreference(context, KEY_FILENAME, KEY_FEATURES_DATA, Gson().toJson(list))
+    }
+
+    fun getFeaturesData(): List<ProductFeatures> {
+        val type = object : TypeToken<List<ProductFeatures?>?>() {}.type
+        return Gson().fromJson<List<ProductFeatures>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_FEATURES_DATA
+            ), type
+        )
+    }
+
+    fun saveEnabledProtocols(list: ArrayList<String>) {
+        putStringPreference(context, KEY_FILENAME, KEY_ENABLED_PROTOCOLS, Gson().toJson(list))
+    }
+
+    fun getEnabledProtocols(): ArrayList<String> {
+        val type = object : TypeToken<ArrayList<String?>?>() {}.type
+        try {
+            return Gson().fromJson<ArrayList<String>>(
+                getStringPreference(
+                    context, KEY_FILENAME, KEY_ENABLED_PROTOCOLS
+                ), type
+            )
+        }
+        catch (e: Exception) {
+            val tempList = ArrayList<String>()
+            tempList.add("WG")
+            tempList.add("IKEV2")
+            tempList.add("TCP")
+            tempList.add("UDP")
+
+            return tempList
+        }
+
+    }
+
+    fun saveAvailableProtocols(list: ArrayList<String>) {
+        var tempList = ArrayList<String>()
+
+        if (list.contains(AppEnum.WG_PROTOCOL.key)) {
+            tempList.add(AppEnum.WG_PROTOCOL.key)
+        }
+        if (list.contains(AppEnum.IKEV2_PROTOCOL.key)) {
+            tempList.add(AppEnum.IKEV2_PROTOCOL.key)
+        }
+        if (list.contains(AppEnum.TCP_PROTOCOL.key)) {
+            tempList.add(AppEnum.TCP_PROTOCOL.key)
+        }
+        if (list.contains(AppEnum.UDP_PROTOCOL.key)) {
+            tempList.add(AppEnum.UDP_PROTOCOL.key)
+        }
+
+        putStringPreference(context, KEY_FILENAME, KEY_AVAILABLE_PROTOCOLS, Gson().toJson(tempList))
+    }
+
+    fun getAvailableProtocols(): ArrayList<String> {
+        val type = object : TypeToken<ArrayList<String?>?>() {}.type
+        return try {
+            Gson().fromJson<ArrayList<String>>(
+                getStringPreference(
+                    context, KEY_FILENAME, KEY_AVAILABLE_PROTOCOLS
+                ), type
+            )
+        } catch (e: Exception) {
+            val tempList = ArrayList<String>()
+            tempList.add("WG")
+            tempList.add("IKEV2")
+            tempList.add("TCP")
+            tempList.add("UDP")
+
+            return tempList
+        }
+
+    }
+
+    fun getEnableTvAppsSplit(): ArrayList<TvEnableApps>? {
+
+        val type = object : TypeToken<ArrayList<TvEnableApps?>?>() {}.type
+        return Gson().fromJson<ArrayList<TvEnableApps>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV
+            ), type
+        )
+    }
+
+    fun setEnableTvAppsSplit(allSplitTunnelEnabled: ArrayList<TvEnableApps>?) {
+        if (allSplitTunnelEnabled == null) {
+            removePreference(context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_ENABLE_TV, Gson().toJson(allSplitTunnelEnabled))
+    }
+
+    fun getDisableTvAppsSplit(): ArrayList<TvDisableApps>? {
+
+        val type = object : TypeToken<ArrayList<TvDisableApps?>?>() {}.type
+        return Gson().fromJson<ArrayList<TvDisableApps>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV
+            ), type
+        )
+    }
+
+    fun setDisableTvAppsSplit(allSplitTunnelEnabled: ArrayList<TvDisableApps>?) {
+        if (allSplitTunnelEnabled == null) {
+            removePreference(context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_DISABLE_TV, Gson().toJson(allSplitTunnelEnabled))
+    }
+
+    fun getSplitTunnelTvAppsName(): ArrayList<String>? {
+
+        val type = object : TypeToken<ArrayList<String?>?>() {}.type
+        return Gson().fromJson<ArrayList<String>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_SPLIT_TUNNEL
+            ), type
+        )
+    }
+
+    fun setSplitTunnelTvAppsName(allSplitTunnelEnabled: ArrayList<String>?) {
+        if (allSplitTunnelEnabled == null) {
+            removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL, Gson().toJson(allSplitTunnelEnabled))
+    }
+
+    fun getSplitTunnelTvAppsPackageName(): ArrayList<String>? {
+
+        val type = object : TypeToken<ArrayList<String?>?>() {}.type
+        return Gson().fromJson<ArrayList<String>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV
+            ), type
+        )
+    }
+
+    fun setSplitTunnelTvAppsPackageName(allSplitTunnelEnabled: ArrayList<String>?) {
+        if (allSplitTunnelEnabled == null) {
+            removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_TV, Gson().toJson(allSplitTunnelEnabled))
+    }
+
+    fun getSplitTunnelTvAppsEntry(): ArrayList<String>? {
+
+        val type = object : TypeToken<ArrayList<String?>?>() {}.type
+        return Gson().fromJson<ArrayList<String>>(
+            getStringPreference(
+                context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY
+            ), type
+        )
+    }
+
+    fun setSplitTunnelTvAppsEntry(appsEntry: ArrayList<String>?) {
+        if (appsEntry == null) {
+            removePreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SPLIT_TUNNEL_ENTRY, Gson().toJson(appsEntry))
+    }
+
+    fun setInstanceActivity(activity: Activity){
+        putStringPreference(context, KEY_FILENAME, KEY_ACTIVITY, Gson().toJson(activity))
+
+    }
+
+    fun getInstanceActivity(): Activity? {
+        var activity: Activity? = null
+        val mainActivity = getStringPreference(context, KEY_FILENAME, KEY_ACTIVITY)
+        if (mainActivity != null){
+            val gson = GsonBuilder().create()
+            activity = gson.fromJson(mainActivity, Activity::class.java)
+        }
+        return activity
+    }
+
+    fun getServerObject(): Server? {
+        var serverObj: Server? = null
+        val serverObjStr: String = getStringPreference(context, KEY_FILENAME, KEY_SERVERS)
+        if (serverObjStr != null) {
+            val gson = GsonBuilder().create()
+            serverObj = gson.fromJson(serverObjStr, Server::class.java)
+        }
+        return serverObj
+    }
+
+    fun setServerObject(serverObj: Server?) {
+        putStringPreference(context, KEY_FILENAME, KEY_SERVERS, Gson().toJson(serverObj))
+    }
+
+    fun getSplitTunneledApps(): String? {
+        return getStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS)
+    }
+
+    fun setSplitTunneledApps(selectedApps: String?) {
+        if (selectedApps == null) {
+            removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS, selectedApps)
+    }
+
+    fun getSplitTunneledAppsNoVpn(): String? {
+        return getStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN)
+    }
+
+    fun setSplitTunneledAppsNoVpn(selectedApps: String?) {
+        if (selectedApps == null) {
+            removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NO_VPN, selectedApps)
+    }
+
+    fun getSplitTunneledAppsNotAllow(): String? {
+        return getStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW)
+    }
+
+    fun setSplitTunneledAppsNotAllow(selectedApps: String?) {
+        if (selectedApps == null) {
+            removePreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW)
+            return
+        }
+        putStringPreference(context, KEY_FILENAME, KEY_SELECTED_APPS_NOT_ALLOW, selectedApps)
+    }
+
+    fun saveAppDetails(appDetails: String) {
+        putStringPreference(context, KEY_FILENAME, APP_DETAILS, appDetails)
+    }
+
+    fun getAppDetails(): String {
+        return getStringPreference(context, KEY_FILENAME, APP_DETAILS)
+    }
+
+    fun saveFileDetails(fileDetails: String) {
+        putStringPreference(context, KEY_FILENAME, FILE_DETAILS, fileDetails)
+    }
+
+    fun getFileDetails(): String {
+        return getStringPreference(context, KEY_FILENAME, FILE_DETAILS)
+    }
+
+
+    fun saveTvSplitTunnel(tvSplitTunneling: ArrayList<TvSplitTunneling>) {
+        putStringPreference(context, KEY_FILENAME, TV_SPLIT_CLASS, Gson().toJson(tvSplitTunneling))
+    }
+
+    fun getTvSplitTunnel(): ArrayList<TvSplitTunneling> {
+        val tvSplitTunneling = Gson().fromJson<ArrayList<TvSplitTunneling>>(
+            getStringPreference(context, KEY_FILENAME, TV_SPLIT_CLASS), TvSplitTunneling::class.java
+        )
+        return tvSplitTunneling
+    }
+
+    fun saveProtocol(protocol: Protocol) {
+        putStringPreference(context, KEY_FILENAME, PROTOCOL, Gson().toJson(protocol))
+    }
+
+    fun getProtocol(): Protocol {
+        var protocol = Gson().fromJson<Protocol>(
+            getStringPreference(context, KEY_FILENAME, PROTOCOL), Protocol::class.java
+        )
+        protocol?.let {
+            return protocol
+        } ?: kotlin.run {
+            return Protocol(
+                AppEnum.WG_PROTOCOL.title, AppEnum.WG_PROTOCOL.key, 1
+//                AppEnum.AUTO_PROTOCOL.title, AppEnum.IKEV2_PROTOCOL.key, 0
+            ) //By default (AUTO) Protocol is selected (index 0 = AUTO). Checking IKEV2 first then check TCP/UDP
+        }
+    }
+
+    fun saveRadioBtnSplitPos(position: Int) {
+        putIntegerPreference(context, KEY_FILENAME, KEY_SPLIT_POS, position)
+    }
+
+    fun getRadioBtnSplitPos(): Int {
+        return getIntegerPreference(context, KEY_FILENAME, KEY_SPLIT_POS)
+    }
+
+    fun saveAdBlockState(status: Boolean) {
+        putBooleanPreference(context, KEY_FILENAME, KEY_ADBLOCK_SWITCH, status)
+    }
+
+    fun getAdBlockState(): Boolean {
+        return getBooleanPreference(context, KEY_FILENAME, KEY_ADBLOCK_SWITCH)
+    }
+
+    fun saveFcmToken(token: String) {
+        putStringPreference(context, KEY_FILENAME, KEY_FCM, token)
+    }
+
+    fun getLoggedInState(): Boolean {
+        return getBooleanPreference(context, KEY_FILENAME, KEY_ISLOGGEDIN)
+    }
+
+    fun setLoggedInState(state: Boolean) {
+        putBooleanPreference(context, KEY_FILENAME, KEY_ISLOGGEDIN, state)
+    }
+
+    fun getFcmToken(): String {
+        return getStringPreference(context, KEY_FILENAME, KEY_FCM)
+    }
+
+    fun saveXPlatformToken(token: String) {
+        putStringPreference(context, KEY_FILENAME, X_PLATFORM_TOKEN, token)
+    }
+
+    fun getXPlatformToken(): String {
+        return getStringPreference(context, KEY_FILENAME, X_PLATFORM_TOKEN)
+    }
+
+    companion object {
+        private const val KEY_FILENAME = "file_fastestvpn"
+        private const val KEY_USER = "keydata_user"
+        private const val KEY_PRODUCT = "keydata_product"
+        private const val KEY_WIREGUARD = "keydata_wireguard"
+        private const val KEY_IPINFO = "keydata_ipinfo"
+        private const val KEY_USER_PASSWORD = "keydata_user_password"
+        private const val KEY_SERVERS_DATA = "keydata_servers_data"
+        private const val KEY_FEATURES_DATA = "keydata_features_data"
+        private const val KEY_ENABLED_PROTOCOLS = "keydata_enabled_protocols"
+        private const val KEY_AVAILABLE_PROTOCOLS = "keydata_available_protocols"
+        private const val KEY_SERVERS = "keydata_server"
+        private const val KEY_SELECTED_APPS = "keydata_selectedApps"
+        private const val KEY_SELECTED_APPS_NO_VPN = "keydata_selectedAppsNoVpn"
+        private const val KEY_SELECTED_APPS_NOT_ALLOW = "keydata_selectedAppsNotAllow"
+        private const val KEY_SPLIT_TUNNEL = "keydata_tv_apps_name"
+        private const val KEY_SPLIT_TUNNEL_TV = "keydata_tv_apps_package_name"
+        private const val KEY_SPLIT_ENABLE_TV = "keydata_tv_apps_enable"
+        private const val KEY_SPLIT_DISABLE_TV = "keydata_tv_apps_disable"
+        private const val KEY_SPLIT_TUNNEL_ENTRY = "keydata_tv_apps_entry"
+        private const val APP_DETAILS = "keydata_app_detail"
+        private const val FILE_DETAILS = "keydata_file_details"
+        private const val PROTOCOL = "keydata_protocol"
+        private const val TV_SPLIT_CLASS = "keydata_tvsplitclass"
+        private const val X_PLATFORM_TOKEN = "keydata_x_platform_token"
+        private const val KEY_FCM = "keydata_fcm"
+        private const val KEY_SPLIT_POS = "keydata_split_pos"
+        private const val KEY_ACTIVITY = "keydata_activity"
+        private const val KEY_ADBLOCK_SWITCH = "keydata_adblock"
+        private const val KEY_ISLOGGEDIN = "key_isloggedin"
+    }
+}

+ 114 - 0
app/src/main/java/com/vpn/fastestvpnservice/helpers/PreferencesHelper.java

@@ -0,0 +1,114 @@
+package com.vpn.fastestvpnservice.helpers;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+
+
+public class PreferencesHelper {
+
+
+    protected void putStringPreference(Context context, String prefsName, String key, String value) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+
+        editor.putString(key, value);
+        editor.commit();
+    }
+
+    protected String getStringPreference(Context context, String prefsName, String key) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        String value = preferences.getString(key, "");
+        return value;
+    }
+
+    protected void putBooleanPreference(Context context, String prefsName, String key, boolean value) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+
+        editor.putBoolean(key, value);
+        editor.commit();
+    }
+
+    protected boolean getBooleanPreference(Context context, String prefsName, String key) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        boolean value = preferences.getBoolean(key, false);
+        return value;
+    }
+
+    protected void putIntegerPreference(Context context, String prefsName, String key, int value) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+
+        editor.putInt(key, value);
+        editor.commit();
+    }
+
+    /**
+     * Get a integer under a particular key and filename
+     *
+     * @param context the filename of preferences
+     * @param key     name of preference
+     * @return -1 if key is not found
+     */
+    protected int getIntegerPreference(Context context, String prefsName, String key) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        int value = preferences.getInt(key, -1);
+        return value;
+    }
+
+    protected void putLongPreference(Context context, String prefsName, String key, long value) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+
+        editor.putLong(key, value);
+        editor.commit();
+    }
+
+    /**
+     * Get a integer under a particular key and filename
+     *
+     * @param context the filename of preferences
+     * @param key     name of preference
+     * @return Integer.MIN if key is not found
+     */
+    protected long getLongPreference(Context context, String prefsName, String key) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        long value = preferences.getLong(key, Integer.MIN_VALUE);
+        return value;
+    }
+
+    protected void putFloatPreference(Context context, String prefsName, String key, float value) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putFloat(key, value);
+        editor.commit();
+    }
+
+    protected float getFloatPreference(Context context, String prefsName, String key) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        float value = preferences.getFloat(key, Float.MIN_VALUE);
+        return value;
+    }
+
+    protected void removePreference(Context context, String prefsName, String key) {
+
+        SharedPreferences preferences = context.getSharedPreferences(prefsName, Activity.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+
+        editor.remove(key);
+        editor.commit();
+    }
+
+
+}

+ 408 - 0
app/src/main/java/com/vpn/fastestvpnservice/helpers/UIHelper.java

@@ -0,0 +1,408 @@
+package com.vpn.fastestvpnservice.helpers;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.GradientDrawable;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.text.TextUtils.TruncateAt;
+import android.text.format.Time;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.StringRes;
+
+import com.vpn.fastestvpnservice.MainActivity;
+import com.vpn.fastestvpnservice.application.App;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Calendar;
+import java.util.Date;
+
+
+public class UIHelper {
+
+    static final int READ_BLOCK_SIZE = 100;
+
+    private static Toast mToast = Toast.makeText(App.getApplication().getApplicationContext(), "", Toast.LENGTH_SHORT);
+
+    public static void showToast(CharSequence message) {
+        mToast.setText(message);
+        mToast.setGravity(Gravity.CENTER, 0, 0);
+        mToast.show();
+    }
+
+    public static void showToast(@StringRes int resId) {
+        mToast.setText(resId);
+        mToast.setGravity(Gravity.CENTER, 0, 0);
+        mToast.show();
+    }
+
+//	public static void showLongToastInCenter(Context ctx, int messageId) {
+//		if(ctx== null){return;}
+//
+//		Toast toast = Toast.makeText(ctx, messageId, Toast.LENGTH_LONG);
+//		toast.setGravity(Gravity.CENTER, 0, 0);
+//		toast.show();
+//	}
+//
+//	public static void showLongToastInCenter(Context ctx, String message) {
+//
+//		if(ctx== null){return;}
+//
+//		Toast toast = Toast.makeText(ctx, message, Toast.LENGTH_LONG);
+//		toast.setGravity(Gravity.CENTER, 0, 0);
+//		toast.show();
+//	}
+//
+//	public static void showShortToastInCenter(Context ctx, String message) {
+//		if(ctx== null){return;}
+//
+//		Toast toast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT);
+//		toast.setGravity(Gravity.CENTER, 0, 0);
+//		toast.show();
+//	}
+//
+//	public static void ShowToast(Context context, String message){
+//		if(context== null){return;}
+//
+//		Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+//	}
+//
+//	public static void ShowToastShort(Context context, String message){
+//		if(context== null){return;}
+//
+//		Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+//	}
+
+//	public static void showConnectionFailedToast(Context ctx) {
+//		showLongToastInCenter(ctx, R.string.msg_connection_failed);
+//	}
+//
+//	public static void shSowConnectionErrorToast(Context ctx) {
+//		showLongToastInCenter(ctx, R.string.msg_connection_error);
+//	}
+
+    public static void hideSoftKeyboard(MainActivity context, View editText) {
+        if (context == null) {
+            return;
+        }
+
+        InputMethodManager imm = (InputMethodManager) context
+                .getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
+
+    }
+
+    public static void hideSoftKeyboard(Context context, View view) {
+        InputMethodManager imm = (InputMethodManager) context
+                .getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+
+    }
+
+    public static void showAlertDialog(String message, CharSequence title,
+                                       Context context) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message).setTitle(title).setCancelable(true)
+                .setNegativeButton("OK", new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        dialog.cancel();
+                    }
+                });
+
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+
+
+    public static Rect locateView(View v) {
+        int[] loc_int = new int[2];
+        if (v == null)
+            return null;
+        try {
+            v.getLocationOnScreen(loc_int);
+        } catch (NullPointerException npe) {
+            // Happens when the view doesn't exist on screen anymore.
+            return null;
+        }
+        Rect location = new Rect();
+        location.left = loc_int[0];
+        location.top = loc_int[1];
+        location.right = location.left + v.getWidth();
+        location.bottom = location.top + v.getHeight();
+        return location;
+    }
+
+    public static void textMarquee(TextView txtView) {
+        // Use this to marquee Textview inside listview
+
+        txtView.setEllipsize(TruncateAt.END);
+        // Enable to Start Scroll
+
+        // txtView.setMarqueeRepeatLimit(-1);
+        // txtView.setHorizontallyScrolling(true);
+        // txtView.setSelected(true);
+    }
+
+
+    public static void dimBehind(Dialog dialog) {
+        WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
+        lp.dimAmount = 0.9f;
+        dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        dialog.setCancelable(false);
+    }
+
+    public static void hideSoftKeyboard(Activity activity) {
+
+        InputMethodManager inputMethodManager = (InputMethodManager) activity
+                .getSystemService(Activity.INPUT_METHOD_SERVICE);
+        inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus()
+                .getWindowToken(), 0);
+    }
+
+    public static String currentTime() {
+        Time now = new Time();
+        now.setToNow();
+        String current_time = pad(now.year) + "-" + pad(now.month + 1) + "-"
+                + pad(now.monthDay) + " " + pad(now.hour) + ":"
+                + pad(now.minute) + ":" + pad(now.second);
+        return current_time;
+
+    }
+
+    public static String pad(int c) {
+        if (c >= 10)
+            return String.valueOf(c);
+        else
+            return "0" + String.valueOf(c);
+    }
+
+    public static AlertDialog showAlertDialogWithButtons(String questionText,
+                                                         String title, String positiveText, String negativeText,
+                                                         DialogInterface.OnClickListener dialogListener, Context context) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(questionText).setTitle(title).setCancelable(true)
+                .setPositiveButton(positiveText, dialogListener)
+                .setNegativeButton(negativeText, dialogListener);
+        AlertDialog alert = builder.create();
+        alert.show();
+        return alert;
+    }
+
+    public static int getOrientation(Context context, Uri photoUri) {
+        /* it's on the external media. */
+        Cursor cursor = context.getContentResolver().query(photoUri,
+                new String[]{MediaStore.Images.ImageColumns.ORIENTATION},
+                null, null, null);
+
+        if (cursor.getCount() != 1) {
+            return -1;
+        }
+
+        cursor.moveToFirst();
+        return cursor.getInt(0);
+    }
+
+    public static int getOrientaionFromRotation(int rotation) {
+        if (rotation == 90)
+            return 6;
+        if (rotation == 180)
+            return 3;
+        if (rotation == 270)
+            return 8;
+        return 0;
+    }
+
+    public static boolean saveImage(Context context, Bitmap bmp, String fileName) {
+        boolean file_saved = false;
+        try {
+            String[] dirList = getDirList();
+            for (int i = 0; i < dirList.length; i++) {
+                if (dirList[i].contains("sdcard")) {
+                    String NewFolder = "/Whistle";
+                    String extStorageDirectory;
+                    extStorageDirectory = "/mnt/" + dirList[i];
+                    File mkTarDir = new File(extStorageDirectory + NewFolder);
+                    if (mkTarDir.isDirectory()) {
+                        file_saved = saveImage(bmp, fileName, NewFolder,
+                                extStorageDirectory);
+                        break;
+                    } else {
+                        boolean dir = mkTarDir.mkdir();
+                        if (dir) {
+                            if (dir) {
+                                file_saved = saveImage(bmp, fileName,
+                                        NewFolder, extStorageDirectory);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return file_saved;
+    }
+
+    protected static String[] getDirList() {
+        File storageDir = new File("/mnt/");
+        if (storageDir.isDirectory()) {
+            String[] dirList = storageDir.list();
+            return dirList;
+        }
+        return null;
+    }
+
+    protected static boolean saveImage(Bitmap bmp, String fileName,
+                                       String NewFolder, String extStorageDirectory)
+            throws FileNotFoundException, IOException {
+        boolean file_saved;
+        OutputStream stream = new FileOutputStream(extStorageDirectory
+                + NewFolder + "/" + fileName);// "+.jpg"
+        file_saved = bmp.compress(Bitmap.CompressFormat.JPEG, 50, stream);
+        stream.close();
+        return file_saved;
+    }
+
+    public static String getFileName(String ext) {
+        Calendar calendar = Calendar.getInstance();
+        Date now = calendar.getTime();
+        long time = now.getTime();
+        String fileName = String.valueOf(time) + "." + ext;
+        return fileName;
+    }
+
+    public static String getFullImagePath(String filename) {
+        String[] dirList = getDirList();
+        for (int i = 0; i < dirList.length; i++) {
+            if (dirList[i].contains("sdcard")) {
+                String NewFolder = "/Whistle";
+                String extStorageDirectory;
+                extStorageDirectory = "/mnt/" + dirList[i] + NewFolder;
+                String fullImagePath = extStorageDirectory + "/" + filename;// +".jpg"
+                return fullImagePath;
+            }
+
+        }
+        return null;
+    }
+
+    public static boolean deleteAllFiles() {
+        File direct = new File(Environment.getExternalStorageDirectory()
+                + "/Whistle");
+        if (direct.exists()) {
+            for (File c : direct.listFiles()) {
+                c.delete();
+            }
+        }
+        return false;
+    }
+
+    // write text to file
+    public static void WriteFile(Activity context, String value, String fileName) {
+        // add-write text into file
+        try {
+
+//			OutputStream stream = new FileOutputStream(extStorageDirectory
+//					+ NewFolder + "/" + fileName);// "+.jpg"
+            FileOutputStream fileout = context.openFileOutput("mytextfile.txt", Context.MODE_PRIVATE);
+            OutputStreamWriter outputWriter = new OutputStreamWriter(fileout);
+            outputWriter.write(value);
+            outputWriter.close();
+
+            //display file saved message
+            Toast.makeText(context, "File saved successfully!",
+                    Toast.LENGTH_SHORT).show();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    // Read text from file
+    public static void ReadFile(Activity context, String fileName) {
+        //reading text from file
+        try {
+            FileInputStream fileIn = context.openFileInput(fileName + ".txt");
+            InputStreamReader InputRead = new InputStreamReader(fileIn);
+
+            char[] inputBuffer = new char[READ_BLOCK_SIZE];
+            String s = "";
+            int charRead;
+
+            while ((charRead = InputRead.read(inputBuffer)) > 0) {
+                // char to string conversion
+                String readstring = String.copyValueOf(inputBuffer, 0, charRead);
+                s += readstring;
+            }
+            InputRead.close();
+            Toast.makeText(context, s, Toast.LENGTH_SHORT).show();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void generateNoteOnSD(Context context, String sFileName, String sBody) {
+        try {
+            File root = new File(Environment.getExternalStorageDirectory(), "Notes");
+            if (!root.exists()) {
+                root.mkdirs();
+            }
+            File gpxfile = new File(root, sFileName);
+            FileWriter writer = new FileWriter(gpxfile);
+            writer.append(sBody);
+            writer.flush();
+            writer.close();
+            Toast.makeText(context, "Saved", Toast.LENGTH_SHORT).show();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    public static GradientDrawable addCornorRadius(int radius) {
+        GradientDrawable shape = new GradientDrawable();
+        shape.setCornerRadius(radius);
+
+        return shape;
+    }
+
+    public static String skipNullFromString(String value) {
+        if (value == null) {
+            value = "";
+        } else if (value.equals("")) {
+            value = "";
+        } else if (value.equals("null")) {
+            value = "";
+        } else {
+            return value;
+        }
+        return value;
+    }
+
+
+
+}

+ 3 - 2
app/src/main/java/com/vpn/fastestvpnservice/navigation/BottomBarNavGraph.kt

@@ -24,7 +24,7 @@ import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
 import com.vpn.fastestvpnservice.sealedClass.Screen
 
 @Composable
-fun BottomBarNavGraph(navHostController: NavHostController) {
+fun BottomBarNavGraph(navHostController: NavHostController, settingsNavHostController: NavHostController) {
     NavHost(navController = navHostController,
         startDestination = BottomBarScreen.Home.route) {
 
@@ -38,7 +38,8 @@ fun BottomBarNavGraph(navHostController: NavHostController) {
             Help(navHostController = navHostController)
         }
         composable(route = BottomBarScreen.Account.route) {
-            Account(navHostController = navHostController)
+            Account(navHostController = navHostController,
+                settingsNavHostController = settingsNavHostController)
         }
         composable(route = Screen.FAQ.route) {
             FAQ(navHostController = navHostController)

+ 2 - 1
app/src/main/java/com/vpn/fastestvpnservice/navigation/NavGraph.kt

@@ -1,6 +1,7 @@
 package com.vpn.fastestvpnservice.navigation
 
 import androidx.compose.runtime.Composable
+import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.NavHost
 import androidx.navigation.compose.composable
@@ -34,7 +35,7 @@ fun SetUpNavGraph(navHostController: NavHostController) {
             Started(navHostController = navHostController)
         }
         composable(route = Screen.BottomBarMainScreen.route) {
-            BottomBarMainScreen()
+            BottomBarMainScreen(navController = navHostController)
         }
     }
 }

+ 43 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/Api.kt

@@ -0,0 +1,43 @@
+package com.vpn.fastestvpnservice.retrofit
+
+import com.vpn.fastestvpnservice.beans.DataResponse
+import com.vpn.fastestvpnservice.beans.UserResponse
+import retrofit2.Call
+import retrofit2.http.Field
+import retrofit2.http.FormUrlEncoded
+import retrofit2.http.POST
+
+interface Api {
+
+    @FormUrlEncoded
+    @POST("authenticate")
+    fun login(
+        @Field("email") email: String?, @Field("password") password: String?,
+        @Field("platform") platform: String?, @Field("version") version: String?,
+        @Field("app_version") app_version: String?
+    ): Call<Any?>
+
+    @FormUrlEncoded
+    @POST("fcm")
+    fun sendFcmToken(
+        @Field("device") device: String?, @Field("token") token: String?
+    ): Call<Any>
+
+    @FormUrlEncoded
+    @POST("signup")
+    fun signup(
+        @Field("email") email: String?, @Field("password") password: String?, @Field("name") name: String?
+    ): Call<Any?>
+
+    @POST("logout")
+    fun logout(): Call<Any>
+
+    @POST("me/delete")
+    fun deleteAccount(): Call<Any>
+
+    @FormUrlEncoded
+    @POST("favourites")
+    fun setFavUnfav(
+        @Field("server_id") serverId: String?
+    ): Call<Any>
+}

+ 170 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/RetrofitNetworkHandling.java

@@ -0,0 +1,170 @@
+package com.vpn.fastestvpnservice.retrofit;
+
+import android.content.Context;
+import android.view.View;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.vpn.fastestvpnservice.R;
+import com.vpn.fastestvpnservice.application.App;
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper;
+import com.vpn.fastestvpnservice.helpers.UIHelper;
+import com.vpn.fastestvpnservice.utils.CheckInternetConnection;
+
+import java.lang.reflect.Type;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+
+public class RetrofitNetworkHandling<T> implements Callback<T> {
+
+    private final Context context;
+    private View view;
+    private final ResponseCallback<T> listener;
+
+    public RetrofitNetworkHandling(ResponseCallback<T> listener) {
+        this.context = App.getApplication();
+        this.listener = listener;
+    }
+
+    public RetrofitNetworkHandling(View view, ResponseCallback<T> listener) {
+        this.context = App.getApplication();
+        this.view = view;
+        this.listener = listener;
+    }
+
+    @Override
+    public void onResponse(Call<T> call, Response<T> response) {
+        //TODO mainactivity- check this loading finish for possible exceptions
+
+        if (!CheckInternetConnection.getInternetConnection(context).isConnectedToInternet()) {
+            UIHelper.showToast(R.string.chk_internet_connectivity);
+            return;
+        }
+
+        if (response.headers().get("auth-token") != null && !response.headers().get("auth-token").equals("")) {
+            BasePreferenceHelper prefHelper = new BasePreferenceHelper(context.getApplicationContext());
+//            prefHelper.putAccessToken(response.headers().get("auth-token"));
+        }
+
+        if (view != null) {
+            view.setEnabled(true);
+        }
+
+        switch (response.code()) {
+            case HttpURLConnection.HTTP_OK:
+            case HttpURLConnection.HTTP_ACCEPTED:
+                /**In Successful Response**/
+                listener.onSuccess(call, response.body());
+                break;
+
+            case HttpURLConnection.HTTP_UNAUTHORIZED:
+
+                //Session Timeout
+                try {
+                    if (context != null) {
+                        WebResponse errorResponse = new WebResponse();
+                        errorResponse.setMessage("Session Time Out");
+                        listener.onFail(call, (T) errorResponse);
+                        //UIHelper.showToast(((WebResponse) response.body()).getMessage());
+                        //((MainActivity) context).getFragmentNavigator().clearAllFragments();
+                        // ((MainActivity)context).addDockableFragment(LoginFragment.newInstance());
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+                break;
+            case HttpURLConnection.HTTP_FORBIDDEN:
+                /**In Authentication **/
+                try {
+
+                    final String string = response.errorBody().string();
+                    Type collectionType = new TypeToken<WebResponse<T>>() {
+                    }.getType();
+
+                    final WebResponse<T> o = new Gson().fromJson(string, collectionType);
+                    listener.onFail(call, (T) o);
+
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    WebResponse errorResponse = new WebResponse();
+//                    errorResponse.setMessage("Please try again...");
+                    listener.onError(call, (T) errorResponse);
+                }
+
+                break;
+
+            default:
+                /**In Authentication **/
+                try {
+                    listener.onFail(call, (T) response);
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+
+                    WebResponse errorResponse = new WebResponse();
+                    errorResponse.setMessage("Please try again...");
+                    listener.onError(call, (T) errorResponse);
+                }
+                break;
+        }
+    }
+
+    @Override
+    public void onFailure(Call<T> call, Throwable t) {
+        t.printStackTrace();
+
+        if (!CheckInternetConnection.getInternetConnection(context).isConnectedToInternet()) {
+            UIHelper.showToast(R.string.chk_internet_connectivity);
+            return;
+        }
+
+        WebResponse errorResponse = new WebResponse();
+//        errorResponse.setMessage("Please try again...");
+
+        try {
+            if (context != null) {
+                //Todo UI Action If Needed
+
+                if (view != null) {
+                    view.setEnabled(true);
+                }
+                listener.onFail(call, (T) errorResponse);
+            }
+
+        } catch (ClassCastException cce) {
+            cce.printStackTrace();
+            //listener.onError(call, (T) errorResponse);
+        }
+
+        //Log.e("Retrofit Connection Error ",arg0.getMessage()+"");
+        if (t.getCause() instanceof SocketTimeoutException) {
+            UIHelper.showToast("Connection Timeout");
+        } else if (t.getCause() instanceof ConnectException) {
+//            UIHelper.showToast("No Internet Connection");
+        } else if (t.getCause() instanceof UnknownHostException) {
+//            UIHelper.showToast("Check internet connection or try again!");
+        } else {
+//            UIHelper.showLongToastInCenter(context, "Problem occurred");
+        }
+    }
+
+
+    public interface ResponseCallback<T> {
+        void onSuccess(Call<T> call, T response);
+
+        void onFail(Call<T> call, T response);
+
+        void onError(Call<T> call, T response);
+
+
+    }
+}

+ 60 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/WebResponse.java

@@ -0,0 +1,60 @@
+package com.vpn.fastestvpnservice.retrofit;
+
+public class WebResponse<T> {
+
+//    {
+//        "status": true,
+//            "response_code": 200,
+//            "response_description": "FORGOT_PASSWORD",
+//            "data": null,
+//        "message": "Reset password link has been sent to your email address."
+//    }
+
+    private boolean status;
+    private int response_code;
+    private String response_description;
+
+    private T data;
+    private String message;
+
+    public boolean isStatus() {
+        return status;
+    }
+
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+
+    public int getResponse_code() {
+        return response_code;
+    }
+
+    public void setResponse_code(int response_code) {
+        this.response_code = response_code;
+    }
+
+    public String getResponse_description() {
+        return response_description;
+    }
+
+    public void setResponse_description(String response_description) {
+        this.response_description = response_description;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}
+

+ 11 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/WebServiceConstants.java

@@ -0,0 +1,11 @@
+package com.vpn.fastestvpnservice.retrofit;
+
+
+public class WebServiceConstants {
+
+//    public static final String SERVER_STAGGING = "http://69.162.81.82:6523/api/v1/";
+    public static final String SERVER_STAGGING = "http://69.162.81.82:6524/api/v1/";
+
+    public static final String BASE_URL = SERVER_STAGGING;
+
+}

+ 71 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/WebServiceFactory.java

@@ -0,0 +1,71 @@
+package com.vpn.fastestvpnservice.retrofit;
+
+import com.vpn.fastestvpnservice.application.App;
+import com.vpn.fastestvpnservice.constants.AppConstant;
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper;
+import com.vpn.fastestvpnservice.retrofit.entities.GsonFactory;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.logging.HttpLoggingInterceptor;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class WebServiceFactory {
+
+    final static String TAG = WebServiceFactory.class.getSimpleName();
+
+    private static final String KEY_HEADER_AUTHORIZATION = "Authorization";
+    private static final String X_PLATFORM = "X-PLATFORM";
+    private static final String X_PLATFORM_TOKEN = "X-PLATFORM-TOKEN";
+    private static final String PLATFORM = "platform";
+    private static final String VERSION = "version";
+
+    private static Api instance;
+    private static Api instance2;
+
+    public static Api getInstance() {
+
+        BasePreferenceHelper prefHelper = new BasePreferenceHelper(App.getApplication());
+
+        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
+        httpClient.connectTimeout(120, TimeUnit.SECONDS);
+        httpClient.readTimeout(120, TimeUnit.SECONDS);
+
+        if (instance == null) {
+            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
+            // TODO uncomment_this_JC
+//            if (BuildConfig.DEBUG) {
+//                logging.setLevel(HttpLoggingInterceptor.Level.BODY);
+//            }
+
+            httpClient.addInterceptor(new Interceptor() {
+                @Override
+                public Response intercept(Chain chain) throws IOException {
+
+                    Request original = chain.request();
+                    Request.Builder requestBuilder;
+                    requestBuilder = original.newBuilder()
+                            .header(X_PLATFORM, "android")
+                            .header(KEY_HEADER_AUTHORIZATION, (prefHelper.getUser() != null) ? "Bearer " + prefHelper.getUser().getToken() : "")
+                            .header(X_PLATFORM_TOKEN, (prefHelper.getXPlatformToken() != null) ? prefHelper.getXPlatformToken() : "");
+
+                    return chain.proceed(requestBuilder.build());
+                }
+            });
+
+
+            OkHttpClient client = httpClient.addInterceptor(logging).build();
+            Retrofit retrofit = new Retrofit.Builder().baseUrl(AppConstant.BASE_URL).client(client).addConverterFactory(GsonConverterFactory.create(GsonFactory.getSimpleGson())).build();
+
+            instance = retrofit.create(Api.class);
+        }
+        return instance;
+    }
+
+}

+ 186 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/GsonFactory.java

@@ -0,0 +1,186 @@
+package com.vpn.fastestvpnservice.retrofit.entities;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+public class GsonFactory {
+
+    public static final String DATE_FROMAT      = "dd-MM-yyyy";
+    public static final String TIME_FROMAT      = "HH:mm:ss";
+    public static final String DATE_TIME_FROMAT = "yyyy-MM-dd HH:mm:ss";
+
+    private static Gson configuredGson;
+    private static Gson simpleGson;
+
+    public static Gson getConfiguredGson () {
+
+        if ( configuredGson == null ) {
+            GsonBuilder builder = new GsonBuilder();
+            // Date
+            builder.registerTypeAdapter( ServiceDate.class, new ServiceDateSerializer( DATE_FROMAT ) );
+            // Time
+            builder.registerTypeAdapter( ServiceTime.class, new ServiceTimeSerializer( TIME_FROMAT ) );
+            // Date Time
+            builder.registerTypeAdapter( ServiceDateTime.class, new ServiceDateTimeSerializer( DATE_TIME_FROMAT ) );
+            // java.util.Date
+            builder.registerTypeAdapter( Date.class, new DateSerializer( DATE_TIME_FROMAT ) );
+
+
+            configuredGson = builder.serializeNulls().create();
+        }
+
+        return configuredGson;
+    }
+    
+  
+
+    public static Gson getSimpleGson () {
+
+        if ( simpleGson == null ) {
+            GsonBuilder builder = new GsonBuilder();
+            // Date
+            builder.registerTypeAdapter( ServiceDate.class, new ServiceDateSerializer( DATE_FROMAT ) );
+            // Time
+            builder.registerTypeAdapter( ServiceTime.class, new ServiceTimeSerializer( TIME_FROMAT ) );
+            // Date Time
+            builder.registerTypeAdapter( ServiceDateTime.class, new ServiceDateTimeSerializer( DATE_TIME_FROMAT ) );
+            // java.util.Date
+            builder.registerTypeAdapter( Date.class, new DateSerializer( DATE_TIME_FROMAT ) );
+
+            simpleGson = builder.serializeNulls().create();
+        }
+
+        return simpleGson;
+    }
+
+   
+
+    public static class ServiceDateSerializer implements JsonSerializer<ServiceDate>, JsonDeserializer<ServiceDate> {
+        SimpleDateFormat sf;
+
+        public ServiceDateSerializer (String format) {
+            sf = new SimpleDateFormat( format );
+        }
+
+        @Override
+        public JsonElement serialize (ServiceDate src, Type typeOfSrc, JsonSerializationContext context) {
+            return new JsonPrimitive( sf.format( src.getDate() ) );
+        }
+
+        @Override
+        public ServiceDate deserialize (JsonElement json, Type arg1, JsonDeserializationContext arg2)
+                throws JsonParseException {
+            ServiceDate date = new ServiceDate();
+            try {
+                date.setDate( sf.parse( json.getAsJsonPrimitive().getAsString() ) );
+            } catch ( ParseException e ) {
+                // TODO : Add proper logs.
+                return null;
+            }
+            return date;
+        }
+    }
+
+    ;
+
+    public static class ServiceTimeSerializer implements JsonSerializer<ServiceTime>, JsonDeserializer<ServiceTime> {
+
+        SimpleDateFormat sf;
+
+        public ServiceTimeSerializer (String format) {
+            sf = new SimpleDateFormat( format );
+        }
+
+        @Override
+        public JsonElement serialize (ServiceTime src, Type typeOfSrc, JsonSerializationContext context) {
+
+            return new JsonPrimitive( sf.format( src.getDate() ) );
+        }
+
+        @Override
+        public ServiceTime deserialize (JsonElement json, Type arg1, JsonDeserializationContext arg2)
+                throws JsonParseException {
+            ServiceTime time = new ServiceTime();
+            try {
+                time.setDate( sf.parse( json.getAsJsonPrimitive().getAsString() ) );
+            } catch ( ParseException e ) {
+                // TODO : Add proper logs.
+                return null;
+            }
+            return time;
+        }
+    }
+
+    ;
+
+    public static class ServiceDateTimeSerializer
+            implements JsonSerializer<ServiceDateTime>, JsonDeserializer<ServiceDateTime> {
+
+        SimpleDateFormat sf;
+
+        public ServiceDateTimeSerializer (String format) {
+            sf = new SimpleDateFormat( format );
+        }
+
+        @Override
+        public ServiceDateTime deserialize (JsonElement json, Type arg1, JsonDeserializationContext arg2)
+                throws JsonParseException {
+            ServiceDateTime time = new ServiceDateTime();
+            try {
+                time.setDate( sf.parse( json.getAsJsonPrimitive().getAsString() ) );
+            } catch ( ParseException e ) {
+                // TODO : Add proper logs.
+                return null;
+            }
+            return time;
+        }
+
+        @Override
+        public JsonElement serialize (ServiceDateTime src, Type arg1, JsonSerializationContext arg2) {
+            return new JsonPrimitive( sf.format( src.getDate() ) );
+        }
+
+    }
+
+    public static class DateSerializer implements JsonSerializer<Date>, JsonDeserializer<Date> {
+
+        SimpleDateFormat sf;
+
+        public DateSerializer (String format) {
+            sf = new SimpleDateFormat( format );
+        }
+
+        @Override
+        public Date deserialize (JsonElement json, Type arg1, JsonDeserializationContext arg2)
+                throws JsonParseException {
+            Date time = null;
+            try {
+                time = sf.parse( json.getAsJsonPrimitive().getAsString() );
+            } catch ( ParseException e ) {
+                // TODO : Add proper logs.
+                return null;
+            }
+            return time;
+        }
+
+        @Override
+        public JsonElement serialize (Date src, Type arg1, JsonSerializationContext arg2) {
+            return new JsonPrimitive( sf.format( src ) );
+        }
+
+    }
+
+}

+ 19 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ResultResponse.java

@@ -0,0 +1,19 @@
+package com.vpn.fastestvpnservice.retrofit.entities;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class ResultResponse<T> {
+
+    @SerializedName("data")
+    @Expose
+    private T data;
+
+    public T getResult() {
+        return data;
+    }
+
+    public void setResult(T data) {
+        this.data = data;
+    }
+}

+ 47 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ServiceDate.java

@@ -0,0 +1,47 @@
+package com.vpn.fastestvpnservice.retrofit.entities;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Only consider the date portion of any instance of this class. The time
+ * portion is uninitialized.
+ */
+
+public class ServiceDate {
+	
+	private Date date;
+	
+	public static final String DATE_FORMAT = "MMM dd, yyyy | EEE";
+	public static final String DAY_FORMAT = "EEEEEEE";
+	public static final String TIME_FORMAT = "h:mm a";
+	
+	public String getDayFormatted() {
+		
+		SimpleDateFormat sdf = new SimpleDateFormat( DAY_FORMAT );
+		return sdf.format( getDate() );
+		
+	}
+	
+	public String getDateFormatted() {
+		
+		SimpleDateFormat sdf = new SimpleDateFormat( DATE_FORMAT );
+		return sdf.format( getDate() );
+		
+	}
+	
+	public String getTimeFormatted() {
+		
+		SimpleDateFormat sdf = new SimpleDateFormat( TIME_FORMAT );
+		return sdf.format( getDate() );
+		
+	}
+	
+	public Date getDate() {
+		return date;
+	}
+	
+	public void setDate( Date date ) {
+		this.date = date;
+	}
+}

+ 36 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ServiceDateTime.java

@@ -0,0 +1,36 @@
+package com.vpn.fastestvpnservice.retrofit.entities;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Complete DateTime received from web service, TimeZone is not receieved from
+ * the webservice..
+ */
+public class ServiceDateTime {
+	Date date;
+	
+	public ServiceDateTime() {
+	}
+	
+	public ServiceDateTime( String strDate ) {
+		SimpleDateFormat simpleDateFormat = new SimpleDateFormat( "yyyy" );
+		
+		try {
+			date = simpleDateFormat.parse( strDate );
+		} catch ( ParseException e ) {
+			
+			e.printStackTrace();
+		}
+	}
+	
+	public Date getDate() {
+		return date;
+	}
+	
+	public void setDate( Date date ) {
+		this.date = date;
+	}
+	
+}

+ 20 - 0
app/src/main/java/com/vpn/fastestvpnservice/retrofit/entities/ServiceTime.java

@@ -0,0 +1,20 @@
+package com.vpn.fastestvpnservice.retrofit.entities;
+
+import java.util.Date;
+
+/**
+ * Only consider the time portion of any instance of this class. The date
+ * portion is uninitialized.
+ */
+public class ServiceTime {
+
+	Date date;
+
+	public Date getDate() {
+		return date;
+	}
+
+	public void setDate(Date date) {
+		this.date = date;
+	}
+}

+ 28 - 13
app/src/main/java/com/vpn/fastestvpnservice/screens/BottomBarMainScreen.kt

@@ -20,6 +20,10 @@ import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.res.colorResource
@@ -37,29 +41,40 @@ import com.vpn.fastestvpnservice.navigation.BottomBarNavGraph
 import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
 
 @Composable
-fun BottomBarMainScreen() {
-    val navController = rememberNavController()
+fun BottomBarMainScreen(navController: NavHostController) {
+    val navController1 = rememberNavController()
+    var isBottomBarVisible by remember { mutableStateOf(true) }
+
+    val screens = listOf(
+        BottomBarScreen.Home,
+        BottomBarScreen.Settings,
+        BottomBarScreen.Help,
+        BottomBarScreen.Account
+    )
+
+    navController1.addOnDestinationChangedListener { _,_,_ ->
+        isBottomBarVisible = navController1.currentDestination?.route in listOf(
+            screens[0].route, screens[1].route, screens[2].route, screens[3].route)
+    }
 
     Scaffold (
         bottomBar = {
-            BottomBar(navController)
+                    if (isBottomBarVisible) {
+                        BottomBar(navController1, screens)
+                    }
         },
         content = { padding ->
             Box(modifier = Modifier.padding(padding)) {
-                BottomBarNavGraph(navHostController = navController)
+                BottomBarNavGraph(navHostController = navController1,
+                    settingsNavHostController = navController)
             }
         }
     )
 }
 
 @Composable
-fun BottomBar(navHostController: NavHostController) {
-    val screens = listOf(
-        BottomBarScreen.Home,
-        BottomBarScreen.Settings,
-        BottomBarScreen.Help,
-        BottomBarScreen.Account
-    )
+fun BottomBar(navHostController: NavHostController, screens: List<BottomBarScreen>) {
+
 
     val navBackStackEntry = navHostController.currentBackStackEntryAsState()
     val currentDestination = navBackStackEntry.value?.destination
@@ -165,11 +180,11 @@ fun currentRoute(navController: NavHostController): String? {
 @Composable
 @Preview
 fun BottomNavBarPreview() {
-    BottomBarMainScreen()
+    BottomBarMainScreen(rememberNavController())
 }
 
 @Composable
 @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
 fun BottomNavBarPreviewDark() {
-    BottomBarMainScreen()
+    BottomBarMainScreen(rememberNavController())
 }

+ 176 - 53
app/src/main/java/com/vpn/fastestvpnservice/screens/LoginScreen.kt

@@ -12,9 +12,11 @@ import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
@@ -43,6 +45,7 @@ import androidx.compose.material3.Button
 import androidx.compose.material3.ButtonColors
 import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.ButtonElevation
+import androidx.compose.material3.CircularProgressIndicator
 import androidx.compose.material3.ElevatedButton
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -51,8 +54,11 @@ import androidx.compose.material3.TextField
 import androidx.compose.material3.TextFieldColors
 import androidx.compose.material3.TextFieldDefaults
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.setValue
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableFloatStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCompositionContext
@@ -64,6 +70,7 @@ import androidx.compose.ui.draw.paint
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.res.colorResource
@@ -81,12 +88,18 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavController
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.beans.DataResponse
+import com.vpn.fastestvpnservice.beans.UserResponse
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.AddText
 import com.vpn.fastestvpnservice.sealedClass.Screen
+import com.vpn.fastestvpnservice.viewmodels.LoginViewModel
+import kotlinx.coroutines.delay
 import kotlin.coroutines.coroutineContext
 import kotlin.random.Random
 
@@ -97,14 +110,16 @@ fun Login(navHostController: NavHostController) {
     val focusManager = LocalFocusManager.current
     val random = Random.nextInt(1,999)
 
-//    Image(
-//        painter = painterResource(id = R.drawable.bg_img3),
-//        contentDescription = "FastestVPN Background",
-//        modifier = Modifier
-//            .fillMaxWidth()
-//            .fillMaxHeight(),
-//        contentScale = ContentScale.FillBounds
-//    )
+    val loginViewModel: LoginViewModel = viewModel()
+    val readOnly = loginViewModel.liveDataLoginStatus.observeAsState().value
+
+    var textChanged by remember { mutableStateOf("testacc1@yopmail.com") }
+    var passwordChanged by remember { mutableStateOf("test") }
+    var passwordVisible by remember { mutableStateOf(false) }
+
+    val context = LocalContext.current
+    var basePreferenceHelper = BasePreferenceHelper(context)
+
     Box(
         modifier = Modifier
             .fillMaxSize()
@@ -112,6 +127,7 @@ fun Login(navHostController: NavHostController) {
                 painter = painterResource(id = R.drawable.bg_img3),
                 contentScale = ContentScale.FillBounds
             )
+            .alpha(if (readOnly == true) 0.6F else 1F)
 //            .background(
 //                if (isSystemInDarkTheme()) Color.Black
 //                else Color.Transparent
@@ -121,8 +137,8 @@ fun Login(navHostController: NavHostController) {
                     focusManager.clearFocus()
                     keyboardController?.hide()
                 }
-            },
-
+            }
+        ,
 //        contentAlignment = Alignment.Center
 
     ) {
@@ -160,14 +176,12 @@ fun Login(navHostController: NavHostController) {
 
             Spacer(modifier = Modifier.height(20.dp))
 
-            var textChanged by remember { mutableStateOf("") }
-
-
             TextField(
                 value = textChanged,
                 onValueChange = {
                     textChanged = it
                 },
+                readOnly = readOnly!!,
 
                 textStyle = TextStyle(
                     fontSize = 20.sp,
@@ -183,7 +197,8 @@ fun Login(navHostController: NavHostController) {
                         1.dp,
                         color = colorResource(id = R.color.white),
                         shape = RoundedCornerShape(16.dp)
-                    ),
+                    )
+                    .clickable() { },
 
 //                placeholder = {
 //                    Text(text = "Enter email address",
@@ -229,15 +244,13 @@ fun Login(navHostController: NavHostController) {
 
             Spacer(modifier = Modifier.height(20.dp))
 
-            var passwordChanged by remember { mutableStateOf("") }
-            var passwordVisible by remember { mutableStateOf(false) }
-
             TextField(
                 value = passwordChanged,
                 onValueChange = {
                     Log.d("onClick_test", "onValueChange -> ")
                     passwordChanged = it
                 },
+                readOnly = readOnly,
 
                 textStyle = TextStyle(
                     fontSize = 20.sp,
@@ -254,7 +267,8 @@ fun Login(navHostController: NavHostController) {
                         color = colorResource(id = R.color.grey_password_field),
                         shape = RoundedCornerShape(16.dp)
                     )
-                    .background(color = colorResource(id = R.color.transparent)),
+                    .background(color = colorResource(id = R.color.transparent))
+                    .clickable() { },
 
                 shape = RoundedCornerShape(15.dp),
 //                placeholder = {
@@ -309,7 +323,9 @@ fun Login(navHostController: NavHostController) {
                     else "Show Password"
 
                     IconButton(onClick = {
-                        passwordVisible = !passwordVisible
+                        if (!readOnly) {
+                            passwordVisible = !passwordVisible
+                        }
                     })
                     {
                         if (passwordVisible) {
@@ -335,8 +351,10 @@ fun Login(navHostController: NavHostController) {
             Spacer(modifier = Modifier.height(15.dp))
             ClickableText(
                 onClick = {
-                    Log.d("onClick_test", "Forgot Password Clicked")
-                    navHostController.navigate(Screen.ForgotPassword.route)
+                    if (!readOnly) {
+                        Log.d("onClick_test", "Forgot Password Clicked")
+                        navHostController.navigate(Screen.ForgotPassword.route)
+                    }
                 },
                 modifier = Modifier
                     .padding(end = 15.dp)
@@ -351,41 +369,19 @@ fun Login(navHostController: NavHostController) {
 
         }
 
-        Button(
-            onClick = {
-                Log.d("test_button", "onClick")
-                navHostController.popBackStack()
-                navHostController.navigate(Screen.BottomBarMainScreen.route)
-            },
-            modifier = Modifier
-                .padding(
-                    start = 15.dp, end = 15.dp,
-                    bottom = 109.dp
-                )
-                .align(Alignment.BottomCenter)
-                .background(colorResource(id = R.color.transparent))
-                .fillMaxWidth()
-                .height(60.dp),
-            shape = RoundedCornerShape(15.dp),
-//            border = BorderStroke(25.dp, colorResource(id = R.color.black)),
-            colors = ButtonDefaults.buttonColors(
-                contentColor = colorResource(id = R.color.blue_text),
-                containerColor = colorResource(id = R.color.white),
-            ),
-            )
-        {
-            Text(text = "Sign In",
-                fontSize = 18.sp,
-                fontWeight = FontWeight.Medium,
-                fontStyle = FontStyle.Normal
+        SignInButton(
+            navHostController = navHostController,
+            textChanged,
+            passwordChanged,
+            loginViewModel = loginViewModel,
+            basePreferenceHelper
             )
-        }
         Row (
             modifier = Modifier
                 .align(Alignment.BottomCenter)
                 .padding(57.dp),
         ){
-            TextMsgSignUp(navHostController = navHostController)
+            TextMsgSignUp(navHostController = navHostController, loginViewModel, readOnly!!)
 //            Text(
 //                modifier = Modifier
 //                    .padding(0.dp),
@@ -414,8 +410,11 @@ fun Login(navHostController: NavHostController) {
 }
 
 @Composable
-fun RowScope.TextMsgSignUp(navHostController: NavHostController) {
-
+fun RowScope.TextMsgSignUp(
+    navHostController: NavHostController,
+    loginViewModel: LoginViewModel,
+    isEnabled: Boolean
+) {
         Text(
             modifier = Modifier
                 .padding(0.dp),
@@ -427,7 +426,9 @@ fun RowScope.TextMsgSignUp(navHostController: NavHostController) {
         )
         ClickableText(
             onClick = {
-                navHostController.navigate(Screen.SignUp.route)
+                if (isEnabled == false) {
+                    navHostController.navigate(Screen.SignUp.route)
+                }
             },
             modifier = Modifier
                 .padding(0.dp),
@@ -442,6 +443,128 @@ fun RowScope.TextMsgSignUp(navHostController: NavHostController) {
 }
 
 @Composable
+fun BoxScope.SignInButton(
+    navHostController: NavHostController,
+    email: String,
+    password: String,
+    loginViewModel: LoginViewModel,
+    prefHelper: BasePreferenceHelper
+) {
+//    var showLoader by remember { mutableStateOf(false) }
+
+    if (loginViewModel.liveDataLoginStatus.value == true) {
+        var progress by remember { mutableFloatStateOf(0.1F) }
+
+        LaunchedEffect(key1 = Unit) {
+            while (true) {
+                for (i in 1..100) {
+                    progress = i.toFloat()/100F
+                    delay(150)
+                }
+                progress = 0.1F
+            }
+        }
+
+        CircularProgressIndicator(
+            progress = { progress },
+            modifier = Modifier
+                .align(Alignment.Center)
+                .size(50.dp),
+            color = colorResource(id = R.color.yellow_text),
+            strokeWidth = 5.dp,
+        )
+    }
+
+    Button(
+        modifier = Modifier
+            .padding(
+                start = 15.dp, end = 15.dp,
+                bottom = 109.dp
+            )
+            .align(Alignment.BottomCenter)
+            .background(colorResource(id = R.color.transparent))
+            .fillMaxWidth()
+            .height(60.dp)
+            .clickable() { },
+        onClick = {
+            Log.d("test_api_response live", "Login Clicked:")
+//            showLoader = true
+            if (loginViewModel.liveDataLoginStatus.value == false) {
+                Log.d("test_api_response live", "SignIn: $email $password")
+                loginViewModel.setLoginStatus(true)
+                loginViewModel.loginRequest(
+                    email,
+                    password,
+                    "android",
+                    "11",
+                    "3.2.4"
+                )
+            }
+        },
+        shape = RoundedCornerShape(15.dp),
+//            border = BorderStroke(25.dp, colorResource(id = R.color.black)),
+        colors = ButtonDefaults.buttonColors(
+            contentColor = colorResource(id = R.color.blue_text),
+            containerColor = colorResource(id = R.color.white),
+        ),
+    )
+    {
+        Text(text = "Sign In",
+            fontSize = 18.sp,
+            fontWeight = FontWeight.Medium,
+            fontStyle = FontStyle.Normal
+        )
+
+        val loginData by loginViewModel.liveDataUserResponse.observeAsState()
+        loginData?.let { response ->
+            Log.d("test_api_response live", "live: ${loginData?.status} ${loginData?.message}")
+            loginViewModel.setLoginStatus(false)
+//            showLoader = false
+            if (response.status) {
+                response.data?.let {
+                    prefHelper.setLoggedInState(true)
+
+                    prefHelper.savePassword(password)
+                    prefHelper.saveUser(it)
+                    it.wireguard?.let { it1 -> prefHelper.saveWireGuard(it1) }
+                    it.product?.let { it1 -> prefHelper.saveProduct(it1) }
+                    prefHelper.saveEnabledProtocols(it.enabled_protocols)
+                    prefHelper.saveAvailableProtocols(it.available_protocols)
+                    prefHelper.saveXPlatformToken(it.userinfo?.email + "_" + System.currentTimeMillis())
+                    prefHelper.saveAdBlockState(false)
+
+                    it.servers?.let {
+                        prefHelper.saveServerData(it)
+                    }
+
+                    Log.d("bearer_token", it.token.toString())
+
+//                    upgradePriceViewModel.getProducts()
+
+//                    prefHelper.getFcmToken().let {
+//                        loginViewModel.sendFcmToken(it)
+//                        Log.d("fcm token get", prefHelper.getFcmToken())
+//                    }
+
+                    prefHelper.saveRadioBtnSplitPos(0)
+
+
+
+
+
+
+
+                    navHostController.popBackStack()
+                    navHostController.navigate(Screen.BottomBarMainScreen.route)
+                }
+
+            }
+            loginViewModel.mutableLiveDataUserResponse.value = null
+        }
+    }
+}
+
+@Composable
 fun ColumnScope.TextMsg(fontSize: TextUnit, text: String, color: Color) {
     Text(
         modifier = Modifier

+ 29 - 3
app/src/main/java/com/vpn/fastestvpnservice/screens/ServerListScreen.kt

@@ -1,6 +1,7 @@
 package com.vpn.fastestvpnservice.screens
 
 import android.content.res.Configuration
+import android.util.Log
 import android.widget.Toast
 import androidx.compose.animation.Animatable
 import androidx.compose.animation.core.animateFloatAsState
@@ -86,6 +87,9 @@ import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
 import androidx.compose.ui.res.painterResource
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.viewmodel.ViewModelFactoryDsl
+import androidx.lifecycle.viewmodel.compose.viewModel
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.allLocationsList
@@ -99,15 +103,26 @@ import com.vpn.fastestvpnservice.beans.streamingList
 import com.vpn.fastestvpnservice.customItems.CountryItem
 import com.vpn.fastestvpnservice.customItems.ServerItem
 import com.vpn.fastestvpnservice.customItems.ServerSearchItem
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.AddTextSettings
 import com.vpn.fastestvpnservice.sealedClass.Screen
+import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
 import kotlinx.coroutines.launch
 
 @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
 @Composable
-fun ServerList(navHostController: NavHostController, isAllLocationsShown: Boolean) {
+fun ServerList(
+    navHostController: NavHostController,
+    isAllLocationsShown: Boolean,
+) {
     val focusManager = LocalFocusManager.current
     val context = LocalContext.current
+
+    var serverListViewModel: ServerListViewModel = viewModel {
+        ServerListViewModel(context = context)
+    }
+    val basePreferenceHelper = BasePreferenceHelper(context)
+
     Box(
         modifier = Modifier
             .fillMaxSize()
@@ -209,7 +224,7 @@ fun ServerList(navHostController: NavHostController, isAllLocationsShown: Boolea
                             ShowRecommendedList()
                         }
                         else if (page == 1) {
-                            ShowAllLocationsList()
+                            ShowAllLocationsList(serverListViewModel, basePreferenceHelper)
                         }
                     }
                 }
@@ -411,7 +426,10 @@ fun ColumnScope.ShowRecommendedList() {
 
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
-fun ColumnScope.ShowAllLocationsList() {
+fun ColumnScope.ShowAllLocationsList(
+    serverListViewModel: ServerListViewModel,
+    basePreferenceHelper: BasePreferenceHelper
+) {
     val allLocationsTabItems = listOf(
         "Countries", "Streaming", "D-VPN", "P2P"
     )
@@ -562,6 +580,14 @@ fun ColumnScope.ShowAllLocationsList() {
                             CompositionLocalProvider(
                                 LocalOverscrollConfiguration provides null
                             ) {
+                                val country = basePreferenceHelper.getServerData()
+                                val filterData = country.get(0).servers?.let {
+                                    serverListViewModel.filterServersByISO(
+                                        it
+                                    )
+                                }
+                                Log.d("test_country_list", filterData?.get(0)?.country.toString() + " " + filterData?.size)
+
                                 LazyColumn() {
                                     items(items = allLocationsList) { country ->
                                         CountryItem(server = country)

+ 183 - 56
app/src/main/java/com/vpn/fastestvpnservice/screens/SignUpScreen.kt

@@ -2,6 +2,7 @@ package com.vpn.fastestvpnservice.screens
 
 import android.content.res.Configuration
 import android.util.Log
+import android.widget.Toast
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
@@ -9,6 +10,7 @@ import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
@@ -34,24 +36,30 @@ import androidx.compose.material.icons.outlined.Visibility
 import androidx.compose.material.icons.sharp.Visibility
 import androidx.compose.material3.Button
 import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.CircularProgressIndicator
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextField
 import androidx.compose.material3.TextFieldDefaults
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableFloatStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.draw.paint
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.res.colorResource
@@ -69,10 +77,15 @@ import androidx.compose.ui.text.style.LineHeightStyle
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.sealedClass.Screen
+import com.vpn.fastestvpnservice.viewmodels.LoginViewModel
+import com.vpn.fastestvpnservice.viewmodels.SignUpViewModel
+import kotlinx.coroutines.delay
 
 @OptIn(ExperimentalComposeUiApi::class)
 @Composable
@@ -80,12 +93,20 @@ fun SignUp(navHostController: NavHostController) {
     val keyboardController = LocalSoftwareKeyboardController.current
     val focusManager = LocalFocusManager.current
 
+    val signUpViewModel: SignUpViewModel = viewModel()
+    var isSignUpEnabled = signUpViewModel.liveDataSignUpStatus.observeAsState().value
+
+    var textChanged by remember { mutableStateOf("testacc1@yopmail.com") }
+    var passwordChanged by remember { mutableStateOf("test") }
+    var passwordVisible by remember { mutableStateOf(false) }
 
     Box(
         modifier = Modifier
             .paint(
                 painter = painterResource(id = R.drawable.bg_img3),
-                contentScale = ContentScale.FillBounds)
+                contentScale = ContentScale.FillBounds
+            )
+            .alpha(if (isSignUpEnabled!!) 0.6F else 1F)
 //            .background(
 //                if (isSystemInDarkTheme()) Color.Black
 //                else Color.Transparent
@@ -115,7 +136,9 @@ fun SignUp(navHostController: NavHostController) {
 
             IconButton(
                 onClick = {
-                    navHostController.popBackStack()
+                    if (!isSignUpEnabled) {
+                        navHostController.popBackStack()
+                    }
                 },
                 modifier = Modifier
                     .padding(start = 16.dp, top = 25.dp)
@@ -164,14 +187,12 @@ fun SignUp(navHostController: NavHostController) {
             )
             Spacer(modifier = Modifier.height(20.dp))
 
-            var textChanged by remember { mutableStateOf("") }
-
-
             TextField(
                 value = textChanged,
                 onValueChange = {
                     textChanged = it
                 },
+                readOnly = isSignUpEnabled,
 
                 textStyle = TextStyle(
                     fontSize = 20.sp,
@@ -237,15 +258,13 @@ fun SignUp(navHostController: NavHostController) {
 
             Spacer(modifier = Modifier.height(20.dp))
 
-            var passwordChanged by remember { mutableStateOf("") }
-            var passwordVisible by remember { mutableStateOf(false) }
-
             TextField(
                 value = passwordChanged,
                 onValueChange = {
                     Log.d("onClick_test", "onValueChange -> ")
                     passwordChanged = it
                 },
+                readOnly = isSignUpEnabled,
 
                 textStyle = TextStyle(
                     fontSize = 20.sp,
@@ -321,7 +340,9 @@ fun SignUp(navHostController: NavHostController) {
                     else "Show Password"
 
                     IconButton(onClick = {
-                        passwordVisible = !passwordVisible
+                        if (!isSignUpEnabled) {
+                            passwordVisible = !passwordVisible
+                        }
                     })
                     {
                         if (passwordVisible) {
@@ -383,48 +404,26 @@ fun SignUp(navHostController: NavHostController) {
                     tint = colorResource(id = R.color.transparent),
                     modifier = Modifier.size(24.dp),
                 )
-                Text(
+                ClickableText(
+                    onClick = {
+                        if (!isSignUpEnabled) {
+
+                        }
+                    },
                     modifier = Modifier
                         .padding(start = 15.dp),
-                    fontSize = 15.sp,
-                    fontStyle = FontStyle.Normal,
-                    text = "Terms & Conditions",
-                    color = colorResource(id = R.color.yellow_text),
+                    text = AnnotatedString("Terms & Conditions"),
+                    style = TextStyle(
+                        fontSize = 15.sp,
+                        fontStyle = FontStyle.Normal,
+                        color = colorResource(id = R.color.yellow_text)
+                    )
                 )
             }
 
         }
 
-        Button(
-            onClick = {
-                Log.d("test_button", "onClick")
-            },
-            modifier = Modifier
-                .padding(
-                    start = 15.dp, end = 15.dp,
-                    bottom = 100.dp
-                )
-                .align(Alignment.BottomCenter)
-                .background(colorResource(id = R.color.transparent))
-                .fillMaxWidth()
-                .height(60.dp),
-            shape = RoundedCornerShape(15.dp),
-//            border = BorderStroke(25.dp, colorResource(id = R.color.black)),
-            colors = ButtonDefaults.buttonColors(
-                contentColor = colorResource(id = R.color.light_blue),
-                containerColor = colorResource(id = R.color.white),
-            ),
-        )
-        {
-            Text(text = "Sign Up",
-                style = TextStyle(
-                    fontSize = 18.sp,
-                    color = colorResource(id = R.color.blue_text),
-                    fontWeight = FontWeight.Medium
-                ),
-
-                )
-        }
+        SignUpButton(signUpViewModel, textChanged, passwordChanged, navHostController)
 
         Row (
             modifier = Modifier
@@ -442,19 +441,21 @@ fun SignUp(navHostController: NavHostController) {
             )
             ClickableText(
                 onClick = {
-                    navHostController.popBackStack()
+                    if (!isSignUpEnabled) {
+                        navHostController.popBackStack()
 
-                    if (navHostController.currentDestination?.id != null &&
-                        navHostController.currentDestination?.route != null){
-                        Log.d("test_signup", "From Sign In -> id = " + navHostController.currentDestination?.id
-                                + " route = " + navHostController.currentDestination?.route
-                        )
-                    }
-                    else {
-                        Log.d("test_signup", "From Sign Up -> id = " + navHostController.currentDestination?.id
-                                + " route = " + navHostController.currentDestination?.route
-                        )
-                        navHostController.navigate(Screen.Login.route)
+                        if (navHostController.currentDestination?.id != null &&
+                            navHostController.currentDestination?.route != null){
+                            Log.d("test_signup", "From Sign In -> id = " + navHostController.currentDestination?.id
+                                    + " route = " + navHostController.currentDestination?.route
+                            )
+                        }
+                        else {
+                            Log.d("test_signup", "From Sign Up -> id = " + navHostController.currentDestination?.id
+                                    + " route = " + navHostController.currentDestination?.route
+                            )
+                            navHostController.navigate(Screen.Login.route)
+                        }
                     }
 
                 },
@@ -471,6 +472,132 @@ fun SignUp(navHostController: NavHostController) {
     }
 }
 
+@Composable
+fun BoxScope.SignUpButton(
+    signUpViewModel: SignUpViewModel,
+    email: String,
+    password: String,
+    navHostController: NavHostController,
+) {
+    val loginViewModel: LoginViewModel = viewModel()
+    val context = LocalContext.current
+    val prefHelper = BasePreferenceHelper(context)
+
+    if (signUpViewModel.liveDataSignUpStatus.value == true) {
+        var progress by remember { mutableFloatStateOf(0.1F) }
+
+            LaunchedEffect(key1 = Unit) {
+                while (true) {
+                    for (i in 1..100) {
+                        progress = i.toFloat()/100F
+                        delay(150)
+                    }
+                    progress = 0.1F
+                }
+            }
+
+        CircularProgressIndicator(
+            progress = { progress },
+            modifier = Modifier
+                .align(Alignment.Center)
+                .size(50.dp),
+            color = colorResource(id = R.color.yellow_text),
+            strokeWidth = 5.dp,
+        )
+    }
+
+    Button(
+        onClick = {
+//            navHostController.popBackStack()
+//            navHostController.navigate(Screen.BottomBarMainScreen.route)
+
+            if (signUpViewModel.liveDataSignUpStatus.value == false) {
+                Log.d("test_button", "onClick")
+                signUpViewModel.setSignUpStatus(true)
+                signUpViewModel.signUp(email, password)
+            }
+        },
+        modifier = Modifier
+            .padding(
+                start = 15.dp, end = 15.dp,
+                bottom = 100.dp
+            )
+            .align(Alignment.BottomCenter)
+            .background(colorResource(id = R.color.transparent))
+            .fillMaxWidth()
+            .height(60.dp),
+        shape = RoundedCornerShape(15.dp),
+//            border = BorderStroke(25.dp, colorResource(id = R.color.black)),
+        colors = ButtonDefaults.buttonColors(
+            contentColor = colorResource(id = R.color.light_blue),
+            containerColor = colorResource(id = R.color.white),
+        ),
+    )
+    {
+        Text(text = "Sign Up",
+            style = TextStyle(
+                fontSize = 18.sp,
+                color = colorResource(id = R.color.blue_text),
+                fontWeight = FontWeight.Medium
+            ),
+        )
+
+        val signUpData = signUpViewModel.liveDataSignUp.observeAsState().value
+        signUpData?.let { response ->
+            signUpViewModel.setSignUpStatus(false)
+            if (response.status) {
+                signUpViewModel.setSignUpStatus(true)
+
+                loginViewModel.loginRequest(
+                    email, password, "android", "11", "3.2.4"
+                )
+            } else {
+                Toast.makeText(context, response.message, Toast.LENGTH_SHORT).show()
+            }
+            signUpViewModel.mutableLiveData.value = null
+        }
+
+        val loginData by loginViewModel.liveDataUserResponse.observeAsState()
+        loginData?.let { response ->
+            Log.d("test_api_response live", "live: ${loginData?.status} ${loginData?.message}")
+            signUpViewModel.setSignUpStatus(false)
+            if (response.status) {
+                response.data?.let {
+                    prefHelper.setLoggedInState(true)
+
+                    prefHelper.savePassword(password)
+                    prefHelper.saveUser(it)
+                    it.wireguard?.let { it1 -> prefHelper.saveWireGuard(it1) }
+                    it.product?.let { it1 -> prefHelper.saveProduct(it1) }
+                    prefHelper.saveEnabledProtocols(it.enabled_protocols)
+                    prefHelper.saveAvailableProtocols(it.available_protocols)
+                    prefHelper.saveXPlatformToken(it.userinfo?.email + "_" + System.currentTimeMillis())
+                    prefHelper.saveAdBlockState(false)
+
+                    it.servers?.let {
+                        prefHelper.saveServerData(it)
+                    }
+
+                    Log.d("bearer_token", it.token.toString())
+
+//                    upgradePriceViewModel.getProducts()
+
+//                    prefHelper.getFcmToken().let {
+//                        loginViewModel.sendFcmToken(it)
+//                        Log.d("fcm token get", prefHelper.getFcmToken())
+//                    }
+
+                    prefHelper.saveRadioBtnSplitPos(0)
+                }
+
+                navHostController.popBackStack()
+                navHostController.navigate(Screen.BottomBarMainScreen.route)
+            }
+            loginViewModel.mutableLiveDataUserResponse.value = null
+        }
+    }
+}
+
 @Preview
 @Composable
 fun SignUpPreview() {

+ 19 - 21
app/src/main/java/com/vpn/fastestvpnservice/screens/SplashScreen.kt

@@ -5,6 +5,7 @@ import android.graphics.fonts.Font
 import android.graphics.fonts.FontStyle
 import android.provider.CalendarContract.Colors
 import android.text.Layout
+import android.widget.Toast
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.isSystemInDarkTheme
@@ -31,6 +32,7 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.paint
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.TextStyle
@@ -44,11 +46,15 @@ import androidx.compose.ui.unit.sp
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import kotlinx.coroutines.delay
 
 @Composable
 fun Splash(navHostController: NavHostController) {
+    val context = LocalContext.current
+    val basePreferenceHelper = BasePreferenceHelper(context)
+
     Box(modifier = Modifier
         .paint(
             painter = painterResource(id = R.drawable.bg_img3),
@@ -83,33 +89,25 @@ fun Splash(navHostController: NavHostController) {
                 .padding(50.dp),
         ){
 
-
-//            Text(
-//                modifier = Modifier
-//                    .padding(0.dp),
-//                fontSize = 30.sp,
-//                fontWeight = FontWeight.Bold,
-//                fontStyle = androidx.compose.ui.text.font.FontStyle.Italic,
-//                text = "Fastest",
-//                color = Color.White,
-//            )
-//            Text(
-//                modifier = Modifier
-//                    .padding(0.dp),
-//                fontSize = 30.sp,
-//                fontWeight = FontWeight.Bold,
-//                fontStyle = androidx.compose.ui.text.font.FontStyle.Italic,
-//                text = "VPN",
-//                color = colorResource(id = R.color.yellow),
-//            )
         }
 
     }
 
+    val isLoggedIn = basePreferenceHelper.getLoggedInState()
+
     LaunchedEffect(key1 = true) {
         delay(3000)
-        navHostController.popBackStack()
-        navHostController.navigate(Screen.Started.route)
+
+        if (isLoggedIn) {
+//            Toast.makeText(context, "if $isLoggedIn", Toast.LENGTH_SHORT).show()
+            navHostController.popBackStack()
+            navHostController.navigate(Screen.BottomBarMainScreen.route)
+        } else {
+//            Toast.makeText(context, "else $isLoggedIn", Toast.LENGTH_SHORT).show()
+            navHostController.popBackStack()
+            navHostController.navigate(Screen.Started.route)
+        }
+
     }
 }
 

+ 1 - 2
app/src/main/java/com/vpn/fastestvpnservice/screens/accountScreensAll/FavoriteServersScreen.kt

@@ -34,7 +34,6 @@ import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.favList
-import com.vpn.fastestvpnservice.beans.favServersList
 import com.vpn.fastestvpnservice.customItems.FavoriteServerItem
 import com.vpn.fastestvpnservice.customItems.ServerItem
 
@@ -60,7 +59,7 @@ fun FavoriteServers(navHostController: NavHostController) {
                 .background(Color.Transparent)
         ) {
             LazyColumn() {
-                items(items = favServersList) {server ->
+                items(items = favList) {server ->
                     FavoriteServerItem(server = server)
                 }
             }

+ 129 - 30
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/AccountScreen.kt

@@ -2,12 +2,10 @@ package com.vpn.fastestvpnservice.screens.bottomNavBarScreens
 
 import android.content.res.Configuration
 import android.util.Log
-import androidx.compose.foundation.BorderStroke
+import android.widget.Toast
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
-import androidx.compose.foundation.border
 import androidx.compose.foundation.gestures.detectTapGestures
-import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
@@ -15,45 +13,36 @@ import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.filled.Logout
-import androidx.compose.material.icons.filled.AccountCircle
-import androidx.compose.material.icons.filled.Delete
-import androidx.compose.material.icons.filled.Favorite
-import androidx.compose.material.icons.filled.Lock
-import androidx.compose.material.icons.filled.Logout
-import androidx.compose.material.icons.filled.MonetizationOn
 import androidx.compose.material3.AlertDialog
 import androidx.compose.material3.Button
 import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.CircularProgressIndicator
 import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableFloatStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.runtime.staticCompositionLocalOf
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.ColorFilter
 import androidx.compose.ui.graphics.painter.Painter
-import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.TextStyle
@@ -65,19 +54,30 @@ import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.window.DialogProperties
+import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.sealedClass.Screen
+import com.vpn.fastestvpnservice.viewmodels.AccountViewModel
+import kotlinx.coroutines.delay
 
 //var LocalLoggedOut = staticCompositionLocalOf<Boolean> { false }
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
-fun Account(navHostController: NavHostController) {
+fun Account(navHostController: NavHostController,
+            settingsNavHostController: NavHostController)
+{
     var isLoggedOut by remember { mutableStateOf(false) }
     var isDelete by remember { mutableStateOf(false) }
 
+    val context = LocalContext.current
+    val basePreferenceHelper = BasePreferenceHelper(context)
+
+    val accountViewModel: AccountViewModel = viewModel()
+
     Box(modifier = Modifier
         .background(MaterialTheme.colorScheme.background)
         .fillMaxSize()
@@ -97,9 +97,9 @@ fun Account(navHostController: NavHostController) {
                 size = 28.sp,
                 color = MaterialTheme.colorScheme.primary
             )
-            AddRowAccount("Email:", "asif@yopmail.com")
-            AddRowAccount("Product:", "Lifetime Plan")
-            AddRowAccount("Account Status:", "Active")
+            AddRowAccount("Email:", basePreferenceHelper.getUser()?.userinfo?.email ?: "")
+            AddRowAccount("Product:", basePreferenceHelper.getUser()?.product?.productName ?: "")
+            AddRowAccount("Account Status:", basePreferenceHelper.getUser()?.product?.status ?: "")
 
             Surface(
                 modifier = Modifier
@@ -166,7 +166,14 @@ fun Account(navHostController: NavHostController) {
                 ) {
                 LogoutDialog("Logout Account",
                     "Are you sure to logout the account?",
-                    onCancel = { isLoggedOut = false }
+                    onCancel = {
+                        isLoggedOut = false
+                    },
+                    settingsNavHostController,
+                    isLoggedOut,
+                    isDelete,
+                    basePreferenceHelper,
+                    accountViewModel
                     )
             }
         }
@@ -183,11 +190,71 @@ fun Account(navHostController: NavHostController) {
             ) {
                 LogoutDialog("Delete Account",
                     "Are you sure to delete the account?",
-                    onCancel = { isDelete = false }
+                    onCancel = { isDelete = false },
+                    settingsNavHostController,
+                    isLoggedOut,
+                    isDelete,
+                    basePreferenceHelper,
+                    accountViewModel
                     )
             }
         }
 
+        if (accountViewModel.liveDataLogoutStatus.value == true) {
+            var progress by remember { mutableFloatStateOf(0.1F) }
+
+            LaunchedEffect(key1 = Unit) {
+                for (i in 1..100) {
+                    progress = i.toFloat()/100F
+                    delay(100)
+                }
+            }
+
+            CircularProgressIndicator(
+                progress = { progress },
+                modifier = Modifier
+                    .align(Alignment.Center)
+                    .size(50.dp),
+                color = colorResource(id = R.color.yellow_text),
+                strokeWidth = 5.dp,
+            )
+        }
+
+        val logoutResponse = accountViewModel.liveDataLogout.observeAsState().value
+        logoutResponse?.let {
+            accountViewModel.setLogoutStatus(false)
+            if (it) {
+                Log.d("test_api_response","Logout live: $logoutResponse")
+                basePreferenceHelper.setLoggedInState(false)
+                basePreferenceHelper.clearAllData()
+                settingsNavHostController.popBackStack()
+                settingsNavHostController.navigate(Screen.Started.route)
+            }
+            else {
+                Log.d("test_api_response","Logout false: $logoutResponse")
+                accountViewModel.mutableLiveDataLogoutStatus.value = false
+                Toast.makeText(context, logoutResponse.toString(), Toast.LENGTH_SHORT).show()
+            }
+            accountViewModel.mutableLiveDataLogout.value = null
+        }
+
+        val deleteResponse = accountViewModel.liveDataDelete.observeAsState().value
+        deleteResponse?.let {
+            accountViewModel.setLogoutStatus(false)
+            if (it.status) {
+                Log.d("test_api_response","Delete live: ${deleteResponse.status}")
+                basePreferenceHelper.setLoggedInState(false)
+                basePreferenceHelper.clearAllData()
+                settingsNavHostController.popBackStack()
+                settingsNavHostController.navigate(Screen.Started.route)
+            }
+            else {
+                Log.d("test_api_response","Delete false: ${deleteResponse.status}")
+                accountViewModel.mutableLiveDataDeleteStatus.value = false
+                Toast.makeText(context, deleteResponse.status.toString(), Toast.LENGTH_SHORT).show()
+            }
+            accountViewModel.mutableLiveDataDelete.value = null
+        }
     }
 }
 
@@ -342,8 +409,14 @@ fun ColumnScope.AddRowAccountIcon(
 fun BoxScope.LogoutDialog(
     title: String,
     desc: String,
-    onCancel : () -> Unit
+    onCancel : () -> Unit,
+    settingsNavHostController: NavHostController,
+    isLogout: Boolean,
+    isDelete: Boolean,
+    basePreferenceHelper: BasePreferenceHelper,
+    accountViewModel: AccountViewModel
 ) {
+
     Surface(
         color = colorResource(id = R.color.white),
         modifier = Modifier
@@ -387,7 +460,7 @@ fun BoxScope.LogoutDialog(
             ) {
                 Button(
                     onClick = {
-                        Log.d("test_button", "onClick Send Code")
+                        Log.d("test_button", "No")
                         onCancel()
 //                                    navHostController.popBackStack()
 //                                    navHostController.navigate(Screen.Login.route)
@@ -414,9 +487,22 @@ fun BoxScope.LogoutDialog(
 
                 Button(
                     onClick = {
-                        Log.d("test_button", "onClick Send Code")
-//                                    navHostController.popBackStack()
-//                                    navHostController.navigate(Screen.SignUp.route)
+                        Log.d("test_button", "Yes")
+
+                        if (isLogout) {
+                            Log.d("test_api_response","Logout click = $isLogout")
+                            accountViewModel.setLogoutStatus(true)
+                            accountViewModel.logout()
+                            onCancel()
+                        }
+
+                        if (isDelete) {
+                            Log.d("test_api_response","Delete click = $isDelete")
+                            accountViewModel.setLogoutStatus(true)
+                            accountViewModel.deleteAccount()
+                            onCancel()
+                        }
+
                     },
                     modifier = Modifier
                         .padding(
@@ -437,6 +523,19 @@ fun BoxScope.LogoutDialog(
                 {
                     Text(text = "Yes", fontSize = 20.sp)
                     Log.d("test_button", "RowScope")
+
+//                    val logoutResponse = accountViewModel.liveDataLogout.observeAsState().value
+//                    if (logoutResponse == true) {
+//                        accountViewModel.setLogoutStatus(false)
+//                        Log.d("test_api_response","Logout live: $logoutResponse")
+//                        basePreferenceHelper.setLoggedInState(false)
+//                        settingsNavHostController.popBackStack()
+//                        settingsNavHostController.navigate(Screen.Started.route)
+//                    }
+//                    else {
+////                        accountViewModel.setLogoutStatus(false)
+////                        onCancel()
+//                    }
                 }
             }
         }
@@ -447,11 +546,11 @@ fun BoxScope.LogoutDialog(
 @Preview
 @Composable
 fun AccountPreview() {
-    Account(rememberNavController())
+    Account(rememberNavController(), rememberNavController())
 }
 
 @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
 @Composable
 fun AccountPreviewDark() {
-    Account(rememberNavController())
+    Account(rememberNavController(), rememberNavController())
 }

+ 5 - 1
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/HomeScreen.kt

@@ -71,9 +71,11 @@ import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalContext
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.beans.isDarkTheme
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
 import com.vpn.fastestvpnservice.ui.theme.FastestVPNTheme
 
@@ -81,7 +83,9 @@ import com.vpn.fastestvpnservice.ui.theme.FastestVPNTheme
 @Composable
 fun Home(navHostController: NavHostController) {
 
+    val context = LocalContext.current
     var isConnect by remember { mutableStateOf(false) }
+    val basePreferenceHelper = BasePreferenceHelper(context)
     Box(
         modifier = Modifier
             .background(MaterialTheme.colorScheme.background)
@@ -110,8 +114,8 @@ fun Home(navHostController: NavHostController) {
 
         IconButton(
             onClick = {
-                Log.d("test_button", "onClick Connect")
                 isConnect = !isConnect
+                val status = basePreferenceHelper.getAdBlockState()
             },
             modifier = Modifier
                 .align(Alignment.TopCenter)

+ 279 - 0
app/src/main/java/com/vpn/fastestvpnservice/utils/CheckInternetConnection.java

@@ -0,0 +1,279 @@
+package com.vpn.fastestvpnservice.utils;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.wifi.ScanResult;
+
+public class CheckInternetConnection {
+
+    Context a;
+    boolean statusToReturn;
+
+    public static CheckInternetConnection checkInternetConnection = null;
+
+    public static CheckInternetConnection getInternetConnection(Context a) {
+        if (checkInternetConnection == null) {
+            checkInternetConnection = new CheckInternetConnection(a);
+        }
+
+        return checkInternetConnection;
+    }
+
+    public CheckInternetConnection(Context a) {
+        this.a = a;
+    }
+
+    public boolean isConnectedToInternet() {
+        ConnectivityManager connectivity = (ConnectivityManager) a.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (connectivity != null) {
+            NetworkInfo[] info = connectivity.getAllNetworkInfo();
+            if (info != null)
+                for (int i = 0; i < info.length; i++)
+                {
+                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
+                        return true;
+                    }
+                }
+        }
+        return false;
+    }
+
+    public boolean isOpenWifiConnected() {
+
+        ConnectivityManager connectivityManager = (ConnectivityManager) a.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (connectivityManager != null)
+        {
+            Network[] allNetworks = connectivityManager.getAllNetworks();
+            for (Network network : allNetworks){
+                NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
+                if (networkCapabilities != null && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){
+                    if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)){
+                        if (!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)){ // checking Authentication
+                            return true;    // Open Wifi Connected
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+//    public boolean isConnectedOpenWifi1() {
+//        WifiManager wifiManager1 = (WifiManager) a.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+//
+//        WifiManager wifiManager2 = (WifiManager) App.getApplication().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+//        Log.d("OpenWiFi test t...", "Testing...");
+//
+//        if (wifiManager1 == null) {
+//            Log.e("OpenWiFi", "Wi-Fi is not supported on this device.");
+//            return false;
+//        }
+//
+////        if (!wifiManager.isWifiEnabled()) {
+////            Log.d("OpenWiFi test wifi en", "Not Enable");
+////            wifiManager.setWifiEnabled(true);
+////        }
+//
+//        if (wifiManager1.isWifiEnabled()) {
+//            boolean status = wifiManager1.startScan();
+//
+//            Log.d("OpenWiFi test scan stat", "Status = " + status);
+//
+//            List<ScanResult> scanResults = wifiManager1.getScanResults();
+//
+//            Log.d("OpenWiFi test scan", String.valueOf(scanResults.size()) + status);
+//
+//            for (ScanResult scanResult : scanResults) {
+//                String ssid = scanResult.SSID;
+//                String securityType = getSecurityType(scanResult);
+//
+//                Log.d("OpenWiFi test type", securityType);
+//
+//                if (securityType.equals("Open")) {
+//                    Log.d("OpenWiFi test", "Open Wi-Fi network: " + ssid);
+//
+//                    ConnectivityManager connectivityManager = (ConnectivityManager) a.getSystemService(Context.CONNECTIVITY_SERVICE);
+//                    NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
+//
+//                    if (activeNetwork != null && activeNetwork.isConnected() && activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
+//                        WifiManager wifiManager3 = (WifiManager) a.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+//                        WifiInfo wifiInfo = wifiManager3.getConnectionInfo();
+//
+//                        if (wifiInfo != null && wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
+//                            String connectedSSID = wifiInfo.getSSID().replace("\"", "");
+//                            String targetSSID = ssid;
+//
+//                            Log.d("open wifi rec WiFi Conn", "Normal wifi connected " + connectedSSID);
+//
+//                            if (connectedSSID.equals(targetSSID)) {
+//                                Log.d("open wifi rec Open con", "Device is connected to the open Wi-Fi network: " + connectedSSID);
+//                                return true;
+//                            } else {
+//                                Log.d("open wifi rec nrml conn", "Device is connected to the Normal Wi-Fi network: " + connectedSSID);
+//                            }
+//                        }
+//
+//                        return true;
+//                    }
+//                }
+//            }
+//        }
+//        return false;
+//    }
+
+//    public boolean isConnectedOpenWifi3() {
+//
+//        WifiManager wifiManager = (WifiManager) a.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+//
+//        if (wifiManager == null) {
+//            Log.e("Open wifi test ns", "Wi-Fi is not supported on this device.");
+//            return false;
+//        }
+//
+//        if (wifiManager.isWifiEnabled())
+//        {
+//            wifiManager.startScan();
+//
+//            List<ScanResult> results = wifiManager.getScanResults();
+//
+//            Log.d("open wifi rec results", results.size() + "");
+//
+//
+//            for (ScanResult scanResult : results) {
+//
+//                Log.d("open wifi rec list", scanResult.SSID);
+//
+//                String ssid = scanResult.SSID;
+//
+//                if (scanResult.capabilities != null) {
+//
+//                    if (scanResult.capabilities.equals("[ESS]")) {
+//                        Log.d("open wifi rec ESS", "Open wifi detected " + ssid);
+//
+//                        ConnectivityManager connectivityManager = (ConnectivityManager) a.getSystemService(Context.CONNECTIVITY_SERVICE);
+//                        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
+//
+//                        if (activeNetwork != null && activeNetwork.isConnected() && activeNetwork.getType() == ConnectivityManager.TYPE_WIFI){
+//                            WifiManager wifiManager1 = (WifiManager) a.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+//                            WifiInfo wifiInfo = wifiManager1.getConnectionInfo();
+//
+//                            if (wifiInfo != null && wifiInfo.getSupplicantState() == SupplicantState.COMPLETED){
+//                                String connectedSSID = wifiInfo.getSSID().replace("\"", "");
+//                                String targetSSID = ssid;
+//
+//                                Log.d("open wifi rec WiFi Conn", "Normal wifi connected " + connectedSSID);
+//
+//                                if (connectedSSID.equals(targetSSID)){
+//                                    Log.d("open wifi rec Open con", "Device is connected to the open Wi-Fi network: " + connectedSSID);
+//                                    return true;
+//                                }
+//                                else{
+//                                    Log.d("open wifi rec nrml conn", "Device is connected to the Normal Wi-Fi network: " + connectedSSID);
+//                                }
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//
+//
+//        return false;
+//    }
+    private String getSecurityType(ScanResult result) {
+        String securityType = "Unknown";
+
+        if (result.capabilities.contains("WPA")) {
+            securityType = "WPA";
+        } else if (result.capabilities.contains("WEP")) {
+            securityType = "WEP";
+        } else if (result.capabilities.contains("EAP")) {
+            securityType = "EAP";
+        } else if (result.capabilities.contains("PSK")) {
+            securityType = "WPA-PSK";
+        } else if (result.capabilities.contains("SAE")) {
+            securityType = "WPA3-SAE";
+        } else if (result.capabilities.contains("OWE")) {
+            securityType = "WPA3-OWE";
+        } else if (result.capabilities.contains("MFP")) {
+            securityType = "WPA2-MFP";
+        } else if (result.capabilities.contains("WAPI-KEY")) {
+            securityType = "WAPI";
+        } else if (result.capabilities.contains("ESS")){
+            securityType = "Open";
+        }
+        else {
+            securityType = "Open";
+        }
+
+        return securityType;
+    }
+
+//    public boolean isConnectedOpenWifi2() {
+//
+//        WifiManager wifiManager = (WifiManager) a.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+//
+//        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+//            @Override
+//            public void onReceive(Context context, Intent intent) {
+//
+////                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+////                {
+////                    boolean success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);
+////
+////                    if (success){
+////                        statusToReturn = scanSuccess(wifiManager);
+////                    }
+////                    else{
+////                        statusToReturn = scanFailure(wifiManager);
+////                    }
+////                }
+//
+//
+//            }
+//        };
+//
+//
+//        IntentFilter intentFilter = new IntentFilter();
+//        intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+//        a.registerReceiver(broadcastReceiver, intentFilter);
+//
+//        boolean success = wifiManager.startScan();
+//        if (!success)
+//        {
+//            statusToReturn = scanFailure(wifiManager);
+//        }
+//
+//        Log.d("OpenWiFi test status", String.valueOf(statusToReturn));
+//        return statusToReturn;
+//    }
+
+
+//    private boolean scanSuccess(WifiManager wifiManager) {
+//        List<ScanResult> scanResults = wifiManager.getScanResults();
+//
+//        Log.d("OpenWiFi test scan", String.valueOf(scanResults.size()));
+//
+//        for (ScanResult scanResult : scanResults){
+//            String ssid = scanResult.SSID;
+//            String securityType = getSecurityType(scanResult);
+//
+//            Log.d("OpenWiFi test type", securityType);
+//
+//            if (securityType.equals("Open")){
+//                Log.d("OpenWiFi test", "Open Wi-Fi network: " + ssid);
+//                return true;
+//            }
+//        }
+//        return false;
+//    }
+//    private boolean scanFailure(WifiManager wifiManager) {
+//        List<ScanResult> scanResults = wifiManager.getScanResults();
+//
+//        return false;
+//    }
+
+}

+ 100 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/AccountViewModel.kt

@@ -0,0 +1,100 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.beans.DataResponse
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+import java.util.Objects
+
+class AccountViewModel: ViewModel() {
+    var mutableLiveDataLogout = MutableLiveData<Boolean>()
+    var liveDataLogout: LiveData<Boolean> = mutableLiveDataLogout
+
+    var mutableLiveDataLogoutStatus = MutableLiveData<Boolean>(false)
+    var liveDataLogoutStatus: LiveData<Boolean> = mutableLiveDataLogoutStatus
+
+    var mutableLiveDataDelete = MutableLiveData<DataResponse<Objects>?>()
+    var liveDataDelete: LiveData<DataResponse<Objects>?> = mutableLiveDataDelete
+
+    var mutableLiveDataDeleteStatus = MutableLiveData<Boolean>(false)
+    var liveDataDeleteStatus: LiveData<Boolean> = mutableLiveDataDeleteStatus
+
+    fun logout(){
+        WebServiceFactory.getInstance().logout().enqueue(
+            RetrofitNetworkHandling<Any>(
+            object : RetrofitNetworkHandling.ResponseCallback<Any> {
+                override fun onSuccess(call: Call<Any>?, response: Any?) {
+                    try {
+                        Log.d("test_api_response","Logout onSuccess: ${response.toString()}")
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<DataResponse<Object>>() {}.type
+                        val data = gson.fromJson<DataResponse<Object>>(jsonString, type)
+                        mutableLiveDataLogout.value = data.status
+
+                        Log.d("test_api_response","Logout After onSuccess: ${response.toString()}")
+                    } catch (ex: Exception) {
+
+                    }
+
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response","Logout onFail:")
+                    mutableLiveDataLogout.value = false
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response","Logout onError:")
+                    mutableLiveDataLogout.value = false
+                }
+            })
+        )
+    }
+
+    fun setLogoutStatus(status: Boolean) {
+        mutableLiveDataLogoutStatus.value = status
+    }
+
+    fun deleteAccount() {
+        WebServiceFactory.getInstance().deleteAccount().enqueue(
+            RetrofitNetworkHandling<Any>(object :
+                RetrofitNetworkHandling.ResponseCallback<Any> {
+                override fun onSuccess(call: Call<Any>?, response: Any?) {
+                    try {
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<DataResponse<Objects>>() {}.type
+                        val data = gson.fromJson<DataResponse<Objects>>(jsonString, type)
+                        Log.d("test_api_response","Delete try ${data.status}:")
+
+                        mutableLiveDataDelete.value = data
+                    } catch (ex: Exception) {
+
+                    }
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response","Delete onFail:")
+                    mutableLiveDataDelete.value = DataResponse(false)
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response","Delete onError:")
+                    mutableLiveDataDelete.value = DataResponse(false)
+                }
+            })
+        )
+    }
+
+    fun setDeleteStatus(status: Boolean) {
+        mutableLiveDataDeleteStatus.value = status
+    }
+
+}

+ 110 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/LoginViewModel.kt

@@ -0,0 +1,110 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.util.Log
+import androidx.compose.runtime.mutableStateOf
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.beans.DataResponse
+import com.vpn.fastestvpnservice.beans.UserResponse
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+import java.util.Objects
+
+class LoginViewModel: ViewModel() {
+    var mutableLiveDataUserResponse = MutableLiveData<DataResponse<UserResponse>>()
+    var liveDataUserResponse: LiveData<DataResponse<UserResponse>> = mutableLiveDataUserResponse
+
+    var mutableLiveDataUserResponseErrorStatus = MutableLiveData<Boolean>()
+
+    private var mutableLiveDataLoginStatus = MutableLiveData<Boolean>(false)
+    var liveDataLoginStatus: LiveData<Boolean> = mutableLiveDataLoginStatus
+
+
+    var mutableLiveDataFcm = MutableLiveData<DataResponse<Objects>>()
+    var liveDataFcm: LiveData<DataResponse<Objects>> = mutableLiveDataFcm
+    fun loginRequest(
+        email: String,
+        password: String,
+        platform: String,
+        version: String,
+        app_version: String
+    ) {
+        WebServiceFactory.getInstance().login(
+            email, password, platform, version, app_version).enqueue(
+            RetrofitNetworkHandling<Any?>(object :
+                RetrofitNetworkHandling.ResponseCallback<Any?> {
+                override fun onSuccess(call: Call<Any?>?, response: Any?) {
+                    try {
+                        Log.d("test_api_response","Response login = " + response.toString())
+
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<DataResponse<UserResponse>>() {}.type
+                        val data = gson.fromJson<DataResponse<UserResponse>>(jsonString, type)
+
+                        Log.d("test_api_response", "login = ${data.status} ${data.message}")
+
+                        data.let {
+                            if (it?.status == true) {
+                                mutableLiveDataUserResponse.value = data
+                            } else {
+                                mutableLiveDataUserResponse.value = data
+                            }
+                        }
+                    } catch (ex: Exception) {
+                        Log.d("test_api_response", "catch")
+                    }
+                }
+
+                override fun onFail(call: Call<Any?>?, response: Any?) {
+                    Log.d("test_api_response","Response onFail:")
+                    mutableLiveDataUserResponseErrorStatus.value = true
+                    mutableLiveDataLoginStatus.value = false
+                }
+
+                override fun onError(call: Call<Any?>?, response: Any?) {
+                    Log.d("test_api_response","Response onError:")
+                    mutableLiveDataUserResponseErrorStatus.value = true
+                    mutableLiveDataLoginStatus.value = false
+                }
+            })
+        )
+    }
+
+    fun setLoginStatus(status: Boolean) {
+        mutableLiveDataLoginStatus.value = status
+    }
+
+    fun sendFcmToken(token: String) {
+        WebServiceFactory.getInstance()
+            .sendFcmToken("android", if (token.isEmpty()) "test_123" else token).enqueue(
+                RetrofitNetworkHandling<Any>(object :
+                    RetrofitNetworkHandling.ResponseCallback<Any> {
+                    override fun onSuccess(call: Call<Any>?, response: Any?) {
+                        try {
+                            val gson = Gson()
+                            val jsonString = gson.toJson(response)
+                            val type = object : TypeToken<DataResponse<Objects>>() {}.type
+                            val data = gson.fromJson<DataResponse<Objects>>(jsonString, type)
+                            mutableLiveDataFcm.value = data
+                        } catch (ex: Exception) {
+                        }
+                    }
+
+                    override fun onFail(call: Call<Any>?, response: Any?) {
+                    }
+
+                    override fun onError(call: Call<Any>?, response: Any?) {
+                    }
+
+
+                })
+            )
+    }
+
+
+}

+ 400 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/ServerListViewModel.kt

@@ -0,0 +1,400 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.content.Context
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.beans.Server
+import com.vpn.fastestvpnservice.beans.ServerData
+import com.vpn.fastestvpnservice.beans.ServerResponse
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+
+class ServerListViewModel(context: Context): ViewModel() {
+
+    val mutableLiveData = MutableLiveData<List<ServerData>>()
+    val mutableLiveDataFavourite = MutableLiveData<List<Server>>()
+    val mutableLiveDataFavUnFav = MutableLiveData<ServerResponse?>()
+    private var preferencesHelper: BasePreferenceHelper
+
+    init {
+        preferencesHelper = BasePreferenceHelper(context)
+    }
+
+    fun getFavList(): ArrayList<Server> {
+        var tempList = ArrayList<Server>()
+        preferencesHelper.getServerData().let {
+            it.forEach {
+                tempList.addAll(it.servers?.filter {
+                    it.isFavourited == true
+                }!!)
+            }
+        }
+        return tempList
+    }
+
+    fun updateFavServer(server: Server) {
+        server.isFavourited = server.isFavourited != true
+        val serverData = preferencesHelper.getServerData()
+
+        serverData.forEach {
+            it.servers?.forEachIndexed { index, obj ->
+                if (server.id == obj.id) {
+                    it.servers.set(index, server)
+
+                }
+            }
+        }
+        preferencesHelper.saveServerData(serverData as ArrayList<ServerData>)
+    }
+
+    fun filterServersByISO(serverlist: ArrayList<Server>): ArrayList<Server> {
+
+        serverlist.forEachIndexed { index, server ->
+            Log.d("serverlist_test", server.server_name + " , " + server.country)
+        }
+
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        serverlist.forEachIndexed { index, server ->
+            Log.d("serverlist_test 2", server.server_name + " , " + server.country)
+        }
+
+        var serverprotocol = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        serverprotocol.forEachIndexed { index, server ->
+            Log.d("serverlist_test p", server.server_name + " , " + server.country)
+        }
+
+        var distinctBy: List<Server>
+        distinctBy = serverprotocol.distinctBy {
+            it.iso
+        }
+
+        distinctBy.forEachIndexed { index, server ->
+            Log.d("serverlist_test d", server.server_name + " , " + server.country)
+        }
+
+        serverprotocol.groupBy(Server::country).mapValues { entry ->
+
+            for ((index, value) in distinctBy.withIndex()) {
+
+                if (entry.key == value.country) {
+                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
+
+                    var total_enables = entry.value.sumBy { it.enable }
+
+                    println("--testing "+entry.value.size +" : "+total_enables+" : "+value.country)
+
+                    entry.value.forEachIndexed { indexs, server ->
+                        Log.d("test_country_servers",server.country + " " + server.server_name.toString())
+                    }
+
+                    if (total_enables >= 1) {
+                        distinctBy.get(index).enableServers = 1
+                    } else {
+                        distinctBy.get(index).enableServers = 0
+                    }
+                }
+
+            }
+        }
+
+        distinctBy.forEachIndexed { index, server ->
+            Log.d("serverlist_test d 2", server.server_name + " , " + server.country + " , " + server.totalServers)
+        }
+
+        return (distinctBy as ArrayList<Server>)
+    }
+
+    fun filterServersByISOTV(serverlist: ArrayList<Server>): ArrayList<Server> {
+
+        serverlist.forEachIndexed { index, server ->
+            Log.d("serverlist test", server.server_name + " , " + server.country)
+        }
+
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        serverlist.forEachIndexed { index, server ->
+            Log.d("serverlist 2 test 2", server.server_name + " , " + server.country)
+        }
+
+        var serverprotocol = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        serverprotocol.forEachIndexed { index, server ->
+            Log.d("serverprotocol test", server.server_name + " , " + server.country)
+        }
+
+        var distinctBy: List<Server>
+        distinctBy = serverprotocol.distinctBy {
+            it.iso
+        }
+
+        distinctBy.forEachIndexed { index, server ->
+            Log.d("distinctBy test", server.server_name + " , " + server.country)
+        }
+
+        serverprotocol.groupBy(Server::country).mapValues { entry ->
+
+            for ((index, value) in distinctBy.withIndex()) {
+
+                if (entry.key == value.country) {
+                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
+
+                    var total_enables = entry.value.sumBy { it.enable }
+
+                    println("--testing "+entry.value.size +" : "+total_enables+" : "+value.country)
+
+                    if (total_enables >= 1) {
+                        distinctBy.get(index).enableServers = 1
+                    } else {
+                        distinctBy.get(index).enableServers = 0
+                    }
+                }
+
+            }
+        }
+
+        distinctBy.forEachIndexed { index, server ->
+            Log.d("distinctBy_test_enable", server.server_name + " , " + server.enable)
+        }
+
+        val enabledServer = distinctBy.filter {
+            it.enable == 1
+        }
+
+        return (enabledServer as ArrayList<Server>)
+    }
+
+
+    // By Khubaib...
+
+    fun filterServersAllCategory(serverlist: ArrayList<Server>): ArrayList<Server> {
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        val serverProtocol = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        val distinctBy: List<Server> = serverProtocol.distinctBy {
+            it.server_name
+        }
+
+        val data = distinctBy as ArrayList<Server>
+
+        data.sortBy {
+            it.server_name
+        }
+//        serverProtocol.groupBy(Server::country).mapValues { entry ->
+//            for ((index, value) in distinctBy.withIndex()) {
+//                if (entry.key == value.country) {
+//                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
+//                }
+//            }
+//        }
+
+        return (data)
+    }
+
+    fun filterServersWithTvCountries(serverlist: ArrayList<Server>): ArrayList<Server> {
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        val serverprotocol = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        val distinctBy: List<Server> = serverprotocol.distinctBy {
+            it.server_name
+        }
+
+        serverprotocol.groupBy(Server::country).mapValues { entry ->
+            for ((index, value) in distinctBy.withIndex()) {
+                if (entry.key == value.country) {
+                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
+                }
+            }
+        }
+
+        val enabledServer = distinctBy.filter {
+            it.enable == 1
+        }
+
+        return (enabledServer as ArrayList<Server>)
+    }
+
+    fun filterServersByStreamingServers(serverlist: ArrayList<Server>): ArrayList<Server> {
+
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        var serverprotocol = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        var distinctBy: List<Server>
+        distinctBy = serverprotocol.distinctBy {
+            it.server_name
+        }
+
+        serverprotocol.groupBy(Server::country).mapValues { entry ->
+            for ((index, value) in distinctBy.withIndex()) {
+                if (entry.key == value.country) {
+                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
+                }
+            }
+        }
+        return (distinctBy as ArrayList<Server>)
+    }
+
+    fun filterServersByStreamingServersTV(serverlist: ArrayList<Server>): ArrayList<Server> {
+
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        var serverprotocol = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        var distinctBy: List<Server>
+        distinctBy = serverprotocol.distinctBy {
+            it.server_name
+        }
+
+        serverprotocol.groupBy(Server::country).mapValues { entry ->
+            for ((index, value) in distinctBy.withIndex()) {
+                if (entry.key == value.country) {
+                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
+                }
+            }
+        }
+
+        val enabledServer = distinctBy.filter {
+            it.enable == 1
+        }
+
+        return (enabledServer as ArrayList<Server>)
+    }
+
+    fun filterServerByConnectionCount(serverlist: ArrayList<Server>): Server {
+        //sort start//
+        serverlist.sortWith(Comparator { s1, s2 ->
+            return@Comparator s1.country_sort.compareTo(s2.country_sort)
+        })
+
+        var temp = serverlist.filter {
+            it.protocol.equals(preferencesHelper.getProtocol().title, ignoreCase = true)
+        }
+
+        val distinctBy = temp.sortedBy {
+            it.connection_count
+        }.distinctBy {
+            it.iso
+        }
+
+        distinctBy.forEachIndexed { index, server ->
+            Log.d("test server cc", server.server_name.toString() + server.country)
+        }
+
+        return distinctBy[0]
+    }
+
+    fun getFilteredServerListByConnectionCount(serverList: ArrayList<Server>, serverObj: Server): Server {
+        val protocol = preferencesHelper.getProtocol().title
+        var tempList = ArrayList<Server>()
+        var tempList2 = ArrayList<Server>()
+
+        for (i in serverList.indices) {
+            var obj = serverList[i]
+
+            if (obj.iso == serverObj.iso && protocol.equals(obj.protocol, ignoreCase = true)) {
+                tempList.add(obj)
+            }
+        }
+
+        for (server in tempList)
+        {
+            if (serverObj.enableServers == 1)
+            {
+                if (server.enable == 1)
+                {
+                    tempList2.add(server)
+                }
+            }
+            else{
+                if (server.enable == 0){
+                    tempList2.add(server)
+                }
+            }
+
+        }
+
+        tempList2.sortBy {
+            it.connection_count
+        }
+
+        tempList2.forEach {
+            Log.d("tempList2", it.server_name + " : " + it.connection_count)
+        }
+
+        return tempList2[0]
+    }
+
+    fun favAndUnFav(server: Server) {
+        updateFavServer(server)
+        WebServiceFactory.getInstance().setFavUnfav("${server.id}")
+            .enqueue(RetrofitNetworkHandling<Any>(object :
+                RetrofitNetworkHandling.ResponseCallback<Any> {
+                override fun onSuccess(call: Call<Any>?, response: Any?) {
+                    try {
+                        Log.d("test_api_response","Response favAndUnFav = " + response.toString())
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<ServerResponse>() {}.type
+                        val data = gson.fromJson<ServerResponse>(jsonString, type)
+                        Log.d("test_api_response","favAndUnFav = " + response.toString())
+
+                        if (data.error == 0)
+                        {
+                            mutableLiveDataFavUnFav.value = data
+//                        UIHelper.showToast(data.message)
+                        }
+                        else {
+                            mutableLiveDataFavUnFav.value = null
+                        }
+                    } catch (ex: Exception) {
+                        Log.d("test_api_response","favAndUnFav catch = " + response.toString())
+
+                    }
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    mutableLiveDataFavUnFav.value = null
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    mutableLiveDataFavUnFav.value = null
+                }
+
+            }))
+
+    }
+}

+ 70 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SignUpViewModel.kt

@@ -0,0 +1,70 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.beans.DataResponse
+import com.vpn.fastestvpnservice.beans.UserResponse
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+class SignUpViewModel: ViewModel() {
+
+    var mutableLiveData = MutableLiveData<DataResponse<UserResponse>?>()
+    var liveDataSignUp: LiveData<DataResponse<UserResponse>?> = mutableLiveData
+
+    var mutableLiveDataStatus = MutableLiveData<Boolean>()
+    var mutableLiveDataMessage = MutableLiveData<String>()
+
+    private var mutableLiveDataSignUpStatus = MutableLiveData<Boolean>(false)
+    var liveDataSignUpStatus: LiveData<Boolean> = mutableLiveDataSignUpStatus
+
+    fun signUp(email: String, password: String) {
+        WebServiceFactory.getInstance().signup(email, password, "no-name")
+            .enqueue(RetrofitNetworkHandling<Any?>(object :
+            RetrofitNetworkHandling.ResponseCallback<Any?>{
+                override fun onSuccess(call: Call<Any?>?, response: Any?) {
+                    Log.d("test_api_response", "signup::")
+                    try {
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<DataResponse<UserResponse>>() {}.type
+                        val data = gson.fromJson<DataResponse<UserResponse>>(jsonString, type)
+
+                        Log.d("test_api_response", "signup:: ${data.status}")
+
+                        data.let {
+                            mutableLiveData.value = data
+                        }
+                    } catch (ex: Exception) {
+                        Log.d("test_api_response", "signup:: catch")
+                        mutableLiveDataSignUpStatus.value = false
+                        mutableLiveData.value = null
+                    }
+                }
+
+                override fun onFail(call: Call<Any?>?, response: Any?) {
+                    Log.d("test_api_response", "signup:: onFail")
+                    mutableLiveData.value = null
+                    mutableLiveDataSignUpStatus.value = false
+                }
+
+                override fun onError(call: Call<Any?>?, response: Any?) {
+                    Log.d("test_api_response", "signup:: onError")
+                    mutableLiveData.value = null
+                    mutableLiveDataSignUpStatus.value = false
+                }
+
+            }))
+    }
+
+    fun setSignUpStatus(status: Boolean) {
+        mutableLiveDataSignUpStatus.value = status
+    }
+}

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -1,3 +1,4 @@
 <resources>
     <string name="app_name">FastestVPN</string>
+    <string name="chk_internet_connectivity">Please check your internet connection</string>
 </resources>