Browse Source

Favorite API integrated, fav is added via API...

Khubaib 1 year ago
parent
commit
1aa71b0067
22 changed files with 1318 additions and 372 deletions
  1. 3 1
      app/src/main/AndroidManifest.xml
  2. 1 2
      app/src/main/java/com/vpn/fastestvpnservice/beans/ServerData.kt
  3. 4 4
      app/src/main/java/com/vpn/fastestvpnservice/beans/SubscriptionDataList.kt
  4. 197 132
      app/src/main/java/com/vpn/fastestvpnservice/customItems/CountryItem.kt
  5. 61 0
      app/src/main/java/com/vpn/fastestvpnservice/customItems/NotificationItem.kt
  6. 132 58
      app/src/main/java/com/vpn/fastestvpnservice/customItems/ServerItem.kt
  7. 4 3
      app/src/main/java/com/vpn/fastestvpnservice/customItems/SubscriptionDataItem.kt
  8. 3 3
      app/src/main/java/com/vpn/fastestvpnservice/helpers/BasePreferenceHelper.kt
  9. 21 0
      app/src/main/java/com/vpn/fastestvpnservice/retrofit/Api.kt
  10. 216 119
      app/src/main/java/com/vpn/fastestvpnservice/screens/ServerListScreen.kt
  11. 8 1
      app/src/main/java/com/vpn/fastestvpnservice/screens/SplashScreen.kt
  12. 28 12
      app/src/main/java/com/vpn/fastestvpnservice/screens/accountScreensAll/FavoriteServersScreen.kt
  13. 60 3
      app/src/main/java/com/vpn/fastestvpnservice/screens/accountScreensAll/SubscriptionScreen.kt
  14. 104 2
      app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/HomeScreen.kt
  15. 28 0
      app/src/main/java/com/vpn/fastestvpnservice/screens/settingsScreenAll/NotificationsScreen.kt
  16. 28 0
      app/src/main/java/com/vpn/fastestvpnservice/utils/Utils.kt
  17. 98 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/HomeViewModel.kt
  18. 53 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/NotificationViewModel.kt
  19. 44 1
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SearchListViewModel.kt
  20. 78 31
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/ServerListViewModel.kt
  21. 78 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SplashViewModel.kt
  22. 69 0
      app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SubscriptionViewModel.kt

+ 3 - 1
app/src/main/AndroidManifest.xml

@@ -15,7 +15,9 @@
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
         android:theme="@style/Theme.FastestVPN"
-        tools:targetApi="31">
+        tools:targetApi="31"
+        android:usesCleartextTraffic="true"
+        >
         <activity
             android:name=".MainActivity"
             android:exported="true"

+ 1 - 2
app/src/main/java/com/vpn/fastestvpnservice/beans/ServerData.kt

@@ -9,6 +9,5 @@ class ServerData(
     @SerializedName("name")
     var name: String? = null,
     @SerializedName("servers")
-    val servers: ArrayList<Server>? = null,
-    var isExpanded: MutableState<Boolean> = mutableStateOf(true)
+    var servers: ArrayList<Server>? = null,
 )

+ 4 - 4
app/src/main/java/com/vpn/fastestvpnservice/beans/SubscriptionDataList.kt

@@ -9,10 +9,10 @@ data class SubscriptionDataList(
 )
 
 val subscriptionList = listOf(
-    SubscriptionDataList("Unlimited Data", "That Explains itself! No more bandwidth caps!"),
-    SubscriptionDataList("Ad-Blocker", "Repel Ads with one click!"),
-    SubscriptionDataList("10 Gbps Faster Connection","Servers are now faster than ever!"),
-    SubscriptionDataList("Link unto 10 Devices","Protect multiple devices with one subscription!")
+    Features("Unlimited Data", "That Explains itself! No more bandwidth caps!"),
+    Features("Ad-Blocker", "Repel Ads with one click!"),
+    Features("10 Gbps Faster Connection","Servers are now faster than ever!"),
+    Features("Link unto 10 Devices","Protect multiple devices with one subscription!")
 )
 
 data class SubscriptionPackageList(

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

@@ -20,11 +20,14 @@ import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
 import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 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.mutableIntStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -41,6 +44,7 @@ import androidx.compose.ui.text.TextStyle
 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 com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.CountryServerList
 import com.vpn.fastestvpnservice.beans.Server
@@ -51,11 +55,14 @@ import com.vpn.fastestvpnservice.utils.Utils
 import com.stealthcopter.networktools.Ping
 import com.stealthcopter.networktools.ping.PingResult
 import com.stealthcopter.networktools.ping.PingStats
+import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 import java.lang.Exception
 import java.util.logging.Handler
 
 @Composable
 fun CountryItem(server: Server, category: String) {
+    Log.d("test_countrySize", "CountryItem Called")
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -63,24 +70,135 @@ fun CountryItem(server: Server, category: String) {
                 color = MaterialTheme.colorScheme.background
             )
             .padding(bottom = 1.dp)
-
     ) {
         val context = LocalContext.current
-        val countrySize by rememberSaveable { mutableStateOf(server.totalServers) }
+        var countrySize by rememberSaveable { mutableStateOf(server.countryServers) }
         var isServerExpanded by rememberSaveable { mutableStateOf(false) }
+        val serverListViewModel: ServerListViewModel = viewModel{
+            ServerListViewModel(context)
+        }
+        val splashViewModel: SplashViewModel = viewModel{
+            SplashViewModel(context)
+        }
+//        var countrySize: Int = 0
+
+        Log.d("test_countrySize", "countrySize $countrySize")
+
+//        LaunchedEffect(key1 = Unit) {
+//            Log.d("test_countrySize", "countrySize LE() $countrySize")
+//            if (countrySize == 0) {
+//                Log.d("test_countrySize", "countrySize==0 $countrySize")
+//                countrySize = server.totalServers
+//            }
+//        }
+
+            if (countrySize != null){
+                countrySize.let { size ->
+                    if (size?.size!! > 1) {
+                        Column {
+                            /* Country Location's Row */
+                            Row(
+                                verticalAlignment = Alignment.Top,
+                                horizontalArrangement = Arrangement.Start,
+                                modifier = Modifier
+                                    .fillMaxWidth()
+                                    .padding(
+                                        start = 16.dp, end = 12.dp, top = 12.dp
+                                    )
+                                    .clickable(
+                                        indication = null,
+                                        interactionSource = remember { MutableInteractionSource() }
+                                    ) {
+                                        Toast
+                                            .makeText(
+                                                context,
+                                                server.country,
+                                                Toast.LENGTH_SHORT
+                                            )
+                                            .show()
+                                    }
+                            ) {
+                                val icon = Utils.getDrawable(context, server.iso)
+                                Icon(
+                                    painter = painterResource(id = icon),
+                                    contentDescription = "Server Logo",
+                                    tint = Color.Unspecified,
+                                    modifier = Modifier
+                                        .padding(bottom = 16.dp)
+                                        .size(24.dp)
+                                )
+                                Text(text = server.country!!,
+                                    style = TextStyle(
+                                        fontSize = 16.sp,
+                                        color = MaterialTheme.colorScheme.primary
+                                    ),
+                                    modifier = Modifier
+                                        .padding(start = 16.dp, bottom = 18.dp)
+                                        .align(Alignment.CenterVertically)
+                                )
+                                Spacer(modifier = Modifier.weight(1F))
+                                Text(text = "${countrySize?.size} locations",
+                                    style = TextStyle(
+                                        fontSize = 16.sp,
+                                        color = colorResource(id = R.color.blue_text)
+                                    ),
+                                    modifier = Modifier
+                                        .padding(end = 30.dp, bottom = 18.dp)
+                                        .align(Alignment.CenterVertically)
+                                )
+//            Spacer(modifier = Modifier.weight(1F))
+
+                                Icon(
+                                    modifier = Modifier
+                                        .padding(bottom = 18.dp, end = 0.dp)
+                                        .size(12.dp, 7.dp)
+                                        .align(Alignment.CenterVertically)
+                                        .clickable(
+                                            indication = null,
+                                            interactionSource = remember { MutableInteractionSource() }
+                                        ) { isServerExpanded = !isServerExpanded },
+
+                                    painter = if (isServerExpanded) painterResource(
+                                        id = R.drawable.dragarrow3x) else painterResource(
+                                        id = R.drawable.downarrow3x),
+
+                                    contentDescription = "Server Logo",
+                                    tint = MaterialTheme.colorScheme.primary,
+                                )
+                            }
+
+                            /* Country Expandable's Row */
+                            if (isServerExpanded) {
+                                ExpandableRow(server = server)
+                            }
+                        }
+                    }
+                    else {
+
+//                    Log.d("test_servers_count", "${server.server_name} ${server.countryServers?.size}")
+                        /* Country Location's Row -> 1 Location() */
+
+                        var ping by remember { mutableIntStateOf(0) }
+                        Ping.onAddress(server.ip as String).setTimeOutMillis(1000).doPing(
+                            object : Ping.PingListener{
+                                override fun onResult(pingResult: PingResult?) {
+                                    android.os.Handler(Looper.getMainLooper()).post {
+                                        ping = pingResult?.timeTaken?.toInt()!!
+                                        Log.d("test_ping", "ping = $ping")
+                                    }
+                                }
+
+                                override fun onError(e: Exception?) {}
+                                override fun onFinished(pingStats: PingStats?) {}
+                            }
+                        )
 
-            countrySize.let { size ->
-                if (size > 1) {
-                    Column {
-                        /* Country Location's Row */
                         Row(
                             verticalAlignment = Alignment.Top,
                             horizontalArrangement = Arrangement.Start,
                             modifier = Modifier
                                 .fillMaxWidth()
-                                .padding(
-                                    start = 16.dp, end = 12.dp, top = 12.dp
-                                )
+                                .padding(start = 16.dp, end = 7.dp, top = 12.dp)
                                 .clickable(
                                     indication = null,
                                     interactionSource = remember { MutableInteractionSource() }
@@ -103,7 +221,8 @@ fun CountryItem(server: Server, category: String) {
                                     .padding(bottom = 16.dp)
                                     .size(24.dp)
                             )
-                            Text(text = server.country!!,
+                            val serverTitle = if (category.lowercase().toString() == "servers") server.country else server.server_name
+                            Text(text = serverTitle!!,
                                 style = TextStyle(
                                     fontSize = 16.sp,
                                     color = MaterialTheme.colorScheme.primary
@@ -113,7 +232,8 @@ fun CountryItem(server: Server, category: String) {
                                     .align(Alignment.CenterVertically)
                             )
                             Spacer(modifier = Modifier.weight(1F))
-                            Text(text = "$countrySize locations",
+                            Text(
+                                text = "$ping ms",
                                 style = TextStyle(
                                     fontSize = 16.sp,
                                     color = colorResource(id = R.color.blue_text)
@@ -122,121 +242,41 @@ fun CountryItem(server: Server, category: String) {
                                     .padding(end = 30.dp, bottom = 18.dp)
                                     .align(Alignment.CenterVertically)
                             )
-//            Spacer(modifier = Modifier.weight(1F))
+                            var isFavorite by rememberSaveable { mutableStateOf(server.isFavourited) }
 
-                            Icon(
+                            IconButton(
                                 modifier = Modifier
-                                    .padding(bottom = 18.dp, end = 0.dp)
-                                    .size(12.dp, 7.dp)
-                                    .align(Alignment.CenterVertically)
-                                    .clickable(
-                                        indication = null,
-                                        interactionSource = remember { MutableInteractionSource() }
-                                    ) { isServerExpanded = !isServerExpanded },
-
-                                painter = if (isServerExpanded) painterResource(
-                                    id = R.drawable.dragarrow3x) else painterResource(
-                                    id = R.drawable.downarrow3x),
-
-                                contentDescription = "Server Logo",
-                                tint = MaterialTheme.colorScheme.primary,
+                                    .padding(bottom = 18.dp, end = 8.dp)
+                                    .size(21.dp, 20.dp)
+                                    .align(Alignment.CenterVertically),
+                                onClick = {
+                                    isFavorite = !isFavorite!!
+                                    serverListViewModel.favAndUnFav(server)
+                                }
                             )
-                        }
-
-                        /* Country Expandable's Row */
-                        if (isServerExpanded) {
-                            ExpandableRow(server = server)
-                        }
-                    }
-                }
-                else {
-
-//                    Log.d("test_servers_count", "${server.server_name} ${server.countryServers?.size}")
-                    /* Country Location's Row -> 1 Location() */
-
-                    var ping by remember { mutableIntStateOf(0) }
-                    Ping.onAddress(server.ip as String).setTimeOutMillis(1000).doPing(
-                        object : Ping.PingListener{
-                            override fun onResult(pingResult: PingResult?) {
-                                android.os.Handler(Looper.getMainLooper()).post {
-                                    ping = pingResult?.timeTaken?.toInt()!!
-                                    Log.d("test_ping", "ping = $ping")
+                            {
+                                val favResponse = serverListViewModel.mutableLiveDataFavUnFav.observeAsState().value
+                                favResponse?.let {
+                                    Log.d("test_fav_response", it.message.toString())
+                                    splashViewModel.serverDataApi()
+                                    serverListViewModel.mutableLiveDataFavUnFav.value = null
                                 }
-                            }
 
-                            override fun onError(e: Exception?) {}
-                            override fun onFinished(pingStats: PingStats?) {}
-                        }
-                    )
+                                Icon(
+//                                    .clickable(
+//                                        indication = null,
+//                                        interactionSource = remember { MutableInteractionSource() }
+//                                    ) {  },
 
-                    Row(
-                        verticalAlignment = Alignment.Top,
-                        horizontalArrangement = Arrangement.Start,
-                        modifier = Modifier
-                            .fillMaxWidth()
-                            .padding(start = 16.dp, end = 7.dp, top = 12.dp)
-                            .clickable(
-                                indication = null,
-                                interactionSource = remember { MutableInteractionSource() }
-                            ) {
-                                Toast
-                                    .makeText(
-                                        context,
-                                        server.country,
-                                        Toast.LENGTH_SHORT
-                                    )
-                                    .show()
-                            }
-                    ) {
-                        val icon = Utils.getDrawable(context, server.iso)
-                        Icon(
-                            painter = painterResource(id = icon),
-                            contentDescription = "Server Logo",
-                            tint = Color.Unspecified,
-                            modifier = Modifier
-                                .padding(bottom = 16.dp)
-                                .size(24.dp)
-                        )
-                        val serverTitle = if (category.lowercase().toString() == "servers") server.country else server.server_name
-                        Text(text = serverTitle!!,
-                            style = TextStyle(
-                                fontSize = 16.sp,
-                                color = MaterialTheme.colorScheme.primary
-                            ),
-                            modifier = Modifier
-                                .padding(start = 16.dp, bottom = 18.dp)
-                                .align(Alignment.CenterVertically)
-                        )
-                        Spacer(modifier = Modifier.weight(1F))
-                        Text(
-                            text = "$ping ms",
-                            style = TextStyle(
-                                fontSize = 16.sp,
-                                color = colorResource(id = R.color.blue_text)
-                            ),
-                            modifier = Modifier
-                                .padding(end = 30.dp, bottom = 18.dp)
-                                .align(Alignment.CenterVertically)
-                        )
-                        var isFavorite by rememberSaveable { mutableStateOf(false) }
-
-                        Icon(
-                            modifier = Modifier
-                                .padding(bottom = 18.dp, end = 8.dp)
-                                .size(21.dp, 20.dp)
-                                .align(Alignment.CenterVertically)
-                                .clickable(
-                                    indication = null,
-                                    interactionSource = remember { MutableInteractionSource() }
-                                ) { isFavorite = !isFavorite },
-
-                            painter = if (isFavorite) painterResource(
-                                id = R.drawable.fav_server3x) else painterResource(
-                                id = R.drawable.unfav_server3x),
+                                    painter = if (isFavorite == true) painterResource(
+                                        id = R.drawable.fav_server3x) else painterResource(
+                                        id = R.drawable.unfav_server3x),
 
-                            contentDescription = "Server Logo",
-                            tint = Color.Unspecified,
-                        )
+                                    contentDescription = "Server Logo",
+                                    tint = Color.Unspecified,
+                                )
+                            }
+                        }
                     }
                 }
             }
@@ -258,6 +298,12 @@ fun CountryItem(server: Server, category: String) {
 @Composable
 fun ColumnScope.ExpandableRow(server: Server) {
     val context = LocalContext.current
+    val serverListViewModel: ServerListViewModel = viewModel{
+        ServerListViewModel(context)
+    }
+    val splashViewModel: SplashViewModel = viewModel{
+        SplashViewModel(context)
+    }
 
     Column(
         modifier = Modifier
@@ -282,6 +328,8 @@ fun ColumnScope.ExpandableRow(server: Server) {
             }
         )
 
+        // Expandable Row
+
             server.countryServers?.let { serverData ->
                 serverData.forEachIndexed { index, serverInfo ->
                     Row(
@@ -326,25 +374,42 @@ fun ColumnScope.ExpandableRow(server: Server) {
                                 .padding(start = 0.dp, end = 30.dp)
                                 .align(Alignment.CenterVertically)
                         )
-                        var isFavorite by rememberSaveable { mutableStateOf(false) }
+                        var isFavorite by rememberSaveable {
+                            mutableStateOf(serverInfo.isFavourited)
+                        }
 
-                        Icon(
+                        IconButton(
                             modifier = Modifier
                                 .padding(bottom = 0.dp, end = 16.dp)
                                 .size(21.dp, 20.dp)
-                                .align(Alignment.CenterVertically)
-                                .clickable(
-                                    indication = null,
-                                    interactionSource = remember { MutableInteractionSource() }
-                                ) { isFavorite = !isFavorite },
+                                .align(Alignment.CenterVertically),
+                            onClick = {
+                            isFavorite = !isFavorite!!
+                            serverListViewModel.favAndUnFav(serverInfo)
+                        }
+                        )
+                        {
+
+                            val favResponse = serverListViewModel.mutableLiveDataFavUnFav.observeAsState().value
+                            favResponse?.let {
+                                Log.d("test_fav_response", it.message.toString())
+                                splashViewModel.serverDataApi()
+                                serverListViewModel.mutableLiveDataFavUnFav.value = null
+                            }
+                            Icon(
+//                                    .clickable(
+//                                        indication = null,
+//                                        interactionSource = remember { MutableInteractionSource() }
+//                                    ) {  },
 
-                            painter = if (isFavorite) painterResource(
-                                id = R.drawable.fav_server3x) else painterResource(
-                                id = R.drawable.unfav_server3x),
+                                painter = if (isFavorite == true) painterResource(
+                                    id = R.drawable.fav_server3x) else painterResource(
+                                    id = R.drawable.unfav_server3x),
 
-                            contentDescription = "Server Logo",
-                            tint = Color.Unspecified,
-                        )
+                                contentDescription = "Server Logo",
+                                tint = Color.Unspecified,
+                            )
+                        }
                     }
 
                     Surface(

+ 61 - 0
app/src/main/java/com/vpn/fastestvpnservice/customItems/NotificationItem.kt

@@ -0,0 +1,61 @@
+package com.vpn.fastestvpnservice.customItems
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.Text
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.text.TextStyle
+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.Notification
+
+@Composable
+fun NotificationItem(item: Notification) {
+    Box(modifier = Modifier
+        .background(MaterialTheme.colorScheme.background)
+        .fillMaxWidth()
+    ) {
+        Column(
+            
+        ) {
+            Text(
+                text = item.title,
+                style = TextStyle(
+                    fontSize = 16.sp,
+                    color = MaterialTheme.colorScheme.primary
+                ),
+                modifier = Modifier
+                    .padding(start = 16.dp, bottom = 5.dp)
+                    .fillMaxWidth(),
+                maxLines = 2
+            )
+            Text(
+                text = item.html,
+                style = TextStyle(
+                    fontSize = 16.sp,
+                    color = MaterialTheme.colorScheme.primary
+                ),
+                modifier = Modifier
+                    .padding(start = 16.dp, bottom = 0.dp)
+                    .fillMaxWidth(),
+                maxLines = 2
+            )
+        }
+    }
+}
+
+@Preview
+@Composable
+fun NotificationItemPreview() {
+    NotificationItem(Notification("0", "Title", "Description"))
+}

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

@@ -2,9 +2,12 @@ package com.vpn.fastestvpnservice.customItems
 
 import android.content.res.Configuration
 import android.os.Looper
+import android.util.Log
 import android.widget.Toast
+import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
+import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Arrangement
@@ -18,11 +21,13 @@ import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
 import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -32,9 +37,11 @@ import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.paint
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.res.painterResource
@@ -42,6 +49,7 @@ import androidx.compose.ui.text.TextStyle
 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 com.stealthcopter.networktools.Ping
 import com.stealthcopter.networktools.ping.PingResult
 import com.stealthcopter.networktools.ping.PingStats
@@ -50,7 +58,11 @@ import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.ServerList
 import com.vpn.fastestvpnservice.beans.favList
 import com.vpn.fastestvpnservice.beans.favListServer
+import com.vpn.fastestvpnservice.helpers.UIHelper
 import com.vpn.fastestvpnservice.utils.Utils
+import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
+import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 import java.lang.Exception
 
 @Composable
@@ -62,6 +74,12 @@ fun ServerItem(server: Server) {
             .padding(bottom = 1.dp)
     ) {
         val context = LocalContext.current
+        val serverListViewModel: ServerListViewModel = viewModel{
+            ServerListViewModel(context)
+        }
+        val splashViewModel: SplashViewModel = viewModel{
+            SplashViewModel(context)
+        }
 
         Row(
             verticalAlignment = Alignment.Top,
@@ -124,24 +142,47 @@ fun ServerItem(server: Server) {
                     .align(Alignment.CenterVertically)
             )
 //            Spacer(modifier = Modifier.weight(1F))
-            var isFavorite by rememberSaveable { mutableStateOf(false) }
+            var isFavorite by rememberSaveable { mutableStateOf(server.isFavourited) }
 
-            Icon(
+            IconButton(
                 modifier = Modifier
                     .padding(bottom = 18.dp, end = 8.dp)
-                    .size(22.dp, 21.dp)
-                    .clickable(
-                        indication = null,
-                        interactionSource = remember { MutableInteractionSource() }
-                    ) { isFavorite = !isFavorite },
-
-                painter = if (isFavorite) painterResource(
-                    id = R.drawable.fav_server3x) else painterResource(
-                    id = R.drawable.unfav_server3x),
+                    .size(22.dp, 21.dp),
+                onClick = {
+                    isFavorite = !isFavorite!!
+                    serverListViewModel.favAndUnFav(server)
+//                    serverListViewModel.updateFavServer(server)
+                }
+            ) {
+                val favResponse = serverListViewModel.mutableLiveDataFavUnFav.observeAsState().value
+                favResponse?.let {
+                    Log.d("test_fav_response", it.message.toString())
+                    splashViewModel.serverDataApi()
+                    serverListViewModel.mutableLiveDataFavUnFav.value = null
+                }
+                Icon(
+                    modifier = Modifier
+//                        .padding(bottom = 18.dp, end = 8.dp)
+//                        .size(22.dp, 21.dp)
+//                        .clickable(
+//                            indication = null,
+//                            interactionSource = remember { MutableInteractionSource() }
+//                        ) {
+////                            isFavorite = !isFavorite!!
+////                        serverListViewModel.updateFavServer(server)
+////                        serverListViewModel.favAndUnFav(server)
+//                        }
+                        ,
+
+                    painter = if (isFavorite == true) painterResource(
+                        id = R.drawable.fav_server3x) else painterResource(
+                        id = R.drawable.unfav_server3x),
+
+                    contentDescription = "Server Logo",
+                    tint = Color.Unspecified,
+                )
+            }
 
-                contentDescription = "Server Logo",
-                tint = Color.Unspecified,
-            )
 
 //            IconButton(
 //                onClick = { isFavorite = !isFavorite },
@@ -174,14 +215,20 @@ fun ServerItem(server: Server) {
 
 @Composable
 fun FavoriteServerItem(server: Server) {
+    val context = LocalContext.current
+    var serverListViewModel: ServerListViewModel = viewModel {
+        ServerListViewModel(context = context)
+    }
+    val splashViewModel: SplashViewModel = viewModel{
+        SplashViewModel(context)
+    }
+
     Box(
         modifier = Modifier
             .fillMaxWidth()
             .background(MaterialTheme.colorScheme.background)
             .padding(bottom = 1.dp)
     ) {
-        val context = LocalContext.current
-
         Row(
             verticalAlignment = Alignment.Top,
             horizontalArrangement = Arrangement.Start,
@@ -223,6 +270,12 @@ fun FavoriteServerItem(server: Server) {
                 modifier = Modifier
                     .padding(bottom = 16.dp)
                     .size(24.dp)
+                    .clip(CircleShape)
+                    .paint(
+                        painter = painterResource(id = icon),
+                        contentScale = ContentScale.FillHeight
+                    )
+
             )
 
             Text(text = server.server_name!!,
@@ -245,39 +298,41 @@ fun FavoriteServerItem(server: Server) {
                     .align(Alignment.CenterVertically)
             )
 //            Spacer(modifier = Modifier.weight(1F))
-            var isFavorite by rememberSaveable {
-                mutableStateOf(true) }
+            var isFavorite by rememberSaveable { mutableStateOf(server.isFavourited) }
 
-            Icon(
+
+
+            IconButton(
+                onClick = {
+                    isFavorite = !isFavorite!!
+                    serverListViewModel.favAndUnFav(server)
+                          },
                 modifier = Modifier
                     .padding(bottom = 18.dp, end = 0.dp)
                     .size(22.dp, 21.dp)
-                    .clickable(
-                        indication = null,
-                        interactionSource = remember { MutableInteractionSource() }
-                    ) { isFavorite = !isFavorite },
+//                    .clickable(
+//                        indication = null,
+//                        interactionSource = remember { MutableInteractionSource() }
+//                    ) {  },
+            ) {
+
+                val favResponse = serverListViewModel.mutableLiveDataFavUnFav.observeAsState().value
+                favResponse?.let {
+                    Log.d("test_fav_response", it.message.toString())
+                    splashViewModel.serverDataApi()
+                    serverListViewModel.mutableLiveDataFavUnFav.value = null
+                }
 
-                painter = if (isFavorite) painterResource(
-                    id = R.drawable.fav_server3x) else painterResource(
-                    id = R.drawable.unfav_server3x),
+                Icon(
 
-                contentDescription = "Server Logo",
-                tint = Color.Unspecified,
-            )
+                    painter = if (isFavorite == true) painterResource(
+                        id = R.drawable.fav_server3x) else painterResource(
+                        id = R.drawable.unfav_server3x),
 
-//            IconButton(
-//                onClick = { isFavorite = !isFavorite },
-//                modifier = Modifier
-//                    .clickable(
-//                        indication = null,
-//                        interactionSource = remember { MutableInteractionSource() },
-//                        ) {
-//                        isFavorite = !isFavorite
-//                    }
-//            ) {
-//
-//
-//            }
+                    contentDescription = "Server Logo",
+                    tint = Color.Unspecified,
+                )
+            }
 
         }
 
@@ -296,14 +351,22 @@ fun FavoriteServerItem(server: Server) {
 
 @Composable
 fun ServerSearchItem(server: Server) {
+    val context = LocalContext.current
+    var serverListViewModel: ServerListViewModel = viewModel {
+        ServerListViewModel(context = context)
+    }
+    val splashViewModel: SplashViewModel = viewModel{
+        SplashViewModel(context)
+    }
+    val searchListViewModel: SearchListViewModel = viewModel{
+        SearchListViewModel(context, serverListViewModel, splashViewModel)
+    }
     Box(
         modifier = Modifier
             .fillMaxWidth()
-            .background(color = MaterialTheme.colorScheme.background)
+            .background(color = Color.White)
             .padding(bottom = 1.dp)
-
     ) {
-        val context = LocalContext.current
 
         Row(
             verticalAlignment = Alignment.Top,
@@ -349,7 +412,7 @@ fun ServerSearchItem(server: Server) {
             Text(text = server.server_name!!,
                 style = TextStyle(
                     fontSize = 16.sp,
-                    color = MaterialTheme.colorScheme.primary
+                    color = colorResource(id = R.color.dark_blue_gray_text)
                 ),
                 modifier = Modifier
                     .padding(start = 16.dp, bottom = 18.dp)
@@ -366,24 +429,35 @@ fun ServerSearchItem(server: Server) {
                     .align(Alignment.CenterVertically)
             )
 //            Spacer(modifier = Modifier.weight(1F))
-            var isFavorite by rememberSaveable { mutableStateOf(false) }
+            var isFavorite by rememberSaveable { mutableStateOf(server.isFavourited) }
 
-            Icon(
+            IconButton(
                 modifier = Modifier
                     .padding(bottom = 18.dp, end = 8.dp)
                     .size(22.dp, 21.dp)
-                    .clickable(
-                        indication = null,
-                        interactionSource = remember { MutableInteractionSource() }
-                    ) { isFavorite = !isFavorite },
+                ,
+                onClick = {
+                isFavorite = !isFavorite!!
+                serverListViewModel.favAndUnFav(server)
+//                        searchListViewModel.updateFavUnFavServerState(server)
+            }) {
+                val favResponse = serverListViewModel.mutableLiveDataFavUnFav.observeAsState().value
+                favResponse?.let {
+                    Log.d("test_fav_response", it.message.toString())
+                    splashViewModel.serverDataApi()
+                    serverListViewModel.mutableLiveDataFavUnFav.value = null
+                }
+                Icon(
+                    painter = if (isFavorite == true) painterResource(
+                        id = R.drawable.fav_server3x) else painterResource(
+                        id = R.drawable.unfav_server3x),
+
+                    contentDescription = "Server Logo",
+                    tint = Color.Unspecified,
+                )
+            }
 
-                painter = if (isFavorite) painterResource(
-                    id = R.drawable.fav_server3x) else painterResource(
-                    id = R.drawable.unfav_server3x),
 
-                contentDescription = "Server Logo",
-                tint = Color.Unspecified,
-            )
 
 //            IconButton(
 //                onClick = { isFavorite = !isFavorite },

+ 4 - 3
app/src/main/java/com/vpn/fastestvpnservice/customItems/SubscriptionDataItem.kt

@@ -40,12 +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.Features
 import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.SubscriptionDataList
 import com.vpn.fastestvpnservice.beans.subscriptionList
 
 @Composable
-fun SubscriptionDataItem(item: SubscriptionDataList) {
+fun SubscriptionDataItem(item: Features) {
     Box(
         modifier = Modifier
             .fillMaxWidth()
@@ -87,7 +88,7 @@ fun SubscriptionDataItem(item: SubscriptionDataList) {
                 modifier = Modifier
                     .padding(start = 16.dp)
             ) {
-                Text(text = item.title,
+                Text(text = item.title!!,
                     style = TextStyle(
                         fontSize = 16.sp,
                         fontWeight = FontWeight.Medium,
@@ -98,7 +99,7 @@ fun SubscriptionDataItem(item: SubscriptionDataList) {
                     modifier = Modifier
                         .padding(start = 0.dp, bottom = 0.dp)
                 )
-                Text(text = item.desc,
+                Text(text = item.details!!,
                     style = TextStyle(
                         fontSize = 14.sp,
                         color = MaterialTheme.colorScheme.primary

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

@@ -91,9 +91,9 @@ class BasePreferenceHelper(private val context: Context) : PreferencesHelper() {
         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>>(
+    fun getServerData(): ArrayList<ServerData> {
+        val type = object : TypeToken<ArrayList<ServerData?>?>() {}.type
+        return Gson().fromJson<ArrayList<ServerData>>(
             getStringPreference(
                 context, KEY_FILENAME, KEY_SERVERS_DATA
             ), type

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

@@ -5,6 +5,7 @@ import com.vpn.fastestvpnservice.beans.UserResponse
 import retrofit2.Call
 import retrofit2.http.Field
 import retrofit2.http.FormUrlEncoded
+import retrofit2.http.GET
 import retrofit2.http.POST
 
 interface Api {
@@ -40,4 +41,24 @@ interface Api {
     fun setFavUnfav(
         @Field("server_id") serverId: String?
     ): Call<Any>
+
+    @GET("http://ip-api.com/json")
+    fun getIp(): Call<Any>
+
+    @GET("servers")
+    fun serverDataApi(): Call<Any>
+
+    @GET("notifications")
+    fun getNotifications(): Call<Any>
+
+    @FormUrlEncoded
+    @POST("validate")
+    fun validatePassword(
+        @Field("email") email: String?, @Field("password") password: String?,
+        @Field("platform") platform: String?, @Field("version") version: String?
+    ): Call<Any>?
+
+    @GET("products")
+    fun getProducts(): Call<Any>
+
 }

+ 216 - 119
app/src/main/java/com/vpn/fastestvpnservice/screens/ServerListScreen.kt

@@ -1,7 +1,10 @@
 package com.vpn.fastestvpnservice.screens
 
 import android.content.res.Configuration
+import android.location.Location
 import android.util.Log
+import android.view.animation.Animation
+import android.view.animation.AnimationUtils
 import androidx.compose.animation.Animatable
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.LocalOverscrollConfiguration
@@ -19,6 +22,7 @@ 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.wrapContentHeight
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
 import androidx.compose.foundation.pager.HorizontalPager
@@ -71,6 +75,7 @@ import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.res.painterResource
 import androidx.lifecycle.viewmodel.compose.viewModel
 import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.customItems.CountryItem
 import com.vpn.fastestvpnservice.customItems.ServerItem
 import com.vpn.fastestvpnservice.customItems.ServerSearchItem
@@ -79,6 +84,7 @@ import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.AddTextSettings
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
 import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 import kotlinx.coroutines.launch
 
 @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@@ -257,11 +263,73 @@ fun BoxScope.HeaderRowSL(
 @Composable
 fun ColumnScope.ShowRecommendedList(
     serverListViewModel: ServerListViewModel,
-    basePreferenceHelper: BasePreferenceHelper
+    prefHelper: BasePreferenceHelper
 ) {
     CompositionLocalProvider(
         LocalOverscrollConfiguration provides null
     ) {
+        val recommendedList: MutableList<Server> = ArrayList<Server>()
+        val smartLocationList: MutableList<Server> = ArrayList<Server>()
+
+        prefHelper.getServerData().get(0).servers?.let {
+            val serverDataLocation = it
+
+            val distinctdatanotnull =
+                serverDataLocation.filter {   // servers's lt and lt not be null
+                    it.lt != null && it.lg != null
+                }
+
+            val distinctdata =
+                distinctdatanotnull.distinctBy { // servers's lt filter, no same lt of a server
+                    it.lt
+                }
+
+            val result = FloatArray(1)
+            val ipinfo = prefHelper.getIpinfo()
+
+            distinctdata.forEachIndexed { index, server ->
+                val lat1 = ipinfo?.latitute
+                val lon1 = ipinfo?.longitude
+                val lat2 = server.lt
+                val lon2 = server.lg
+
+                if (lat1 != null && lat2 != null && lon1 != null && lon2 != null) {
+                    Location.distanceBetween(lat1, lon1, lat2, lon2, result)
+                }
+
+                val distance: Float = result[0]
+                distinctdata.get(index).distance = distance
+
+            }
+
+            val sortedDistance = distinctdata.sortedBy {
+                it.distance
+            }
+
+            if (sortedDistance.isNotEmpty()) {
+                for (i in 0..2) {
+                    recommendedList.add(sortedDistance.get(i))
+                }
+            }
+
+            if (sortedDistance.isNotEmpty()) {
+                for (i in 0..0) {
+                    smartLocationList.add(sortedDistance.get(i))
+                }
+            }
+
+        }
+
+        recommendedList.forEachIndexed { index, server ->
+            Log.d("test_server recm", "$index ${server.server_name}")
+        }
+
+        smartLocationList.forEachIndexed { index, server ->
+            Log.d("test_server smart", "$index ${server.server_name}")
+        }
+
+        val favList = serverListViewModel.liveDataGetFavList.observeAsState().value
+
         LazyColumn(
             modifier = Modifier
                 .padding(top = 14.dp),
@@ -295,17 +363,26 @@ fun ColumnScope.ShowRecommendedList(
                     )
                 }
             }
-                val fav = basePreferenceHelper.getServerData()
-                val filterData1 = fav.get(2).servers?.let {
-                    serverListViewModel.filterServersByStreamingServers(
-                        it
-                    )
+                val fav = prefHelper.getServerData()
+                fav.forEachIndexed { index, serverData ->
+                    Log.d("getServerData", serverData.name.toString())
                 }
+//                val filterData1 = fav.get(2).servers?.let {
+//                    serverListViewModel.filterServersByStreamingServers(
+//                        it
+//                    )
+//                }
 
-            items(items = filterData1!!) { server ->
-                ServerItem(server)
+//            val favList = serverListViewModel.getFavList()
+
+
+            favList?.let {
+                items(items = favList) { server ->
+                    ServerItem(server)
+                }
             }
 
+
             /* Smart List */
             item {
                 Row(
@@ -336,14 +413,14 @@ fun ColumnScope.ShowRecommendedList(
                 }
             }
 
-            val smart = basePreferenceHelper.getServerData()
-            val filterData2 = smart.get(1).servers?.let {
-                serverListViewModel.filterServersByStreamingServers(
-                    it
-                )
-            }
+//            val smart = prefHelper.getServerData()
+//            val filterData2 = smart.get(1).servers?.let {
+//                serverListViewModel.filterServersByStreamingServers(
+//                    it
+//                )
+//            }
 
-            items(items = filterData2!!) { server ->
+            items(items = smartLocationList) { server ->
                 ServerItem(server)
             }
 
@@ -377,14 +454,18 @@ fun ColumnScope.ShowRecommendedList(
                     )
                 }
             }
-            val recent = basePreferenceHelper.getServerData()
-            val filterData3 = recent.get(1).servers?.let {
-                serverListViewModel.filterServersByStreamingServers(
-                    it
-                )
+//            val recent = prefHelper.getServerData()
+//            val filterData3 = recent.get(1).servers?.let {
+//                serverListViewModel.filterServersByStreamingServers(
+//                    it
+//                )
+//            }
+
+            val recentLocation: ArrayList<Server> = ArrayList<Server>()
+            prefHelper.getServerObject()?.let {
+                recentLocation.add(it)
             }
-
-            items(items = filterData3!!) { server ->
+            items(items = recentLocation) { server ->
                 ServerItem(server)
             }
 
@@ -419,14 +500,14 @@ fun ColumnScope.ShowRecommendedList(
                 }
             }
 
-            val recommend = basePreferenceHelper.getServerData()
-            val filterData4 = recommend.get(1).servers?.let {
-                serverListViewModel.filterServersByStreamingServers(
-                    it
-                )
-            }
+//            val recommend = prefHelper.getServerData()
+//            val filterData4 = recommend.get(1).servers?.let {
+//                serverListViewModel.filterServersByStreamingServers(
+//                    it
+//                )
+//            }
 
-            items(items = filterData4!!) { server ->
+            items(items = recommendedList) { server ->
                 ServerItem(server)
             }
         }
@@ -454,11 +535,9 @@ fun ColumnScope.ShowAllLocationsList(
     val selectedIndex by remember { derivedStateOf { pagerState.currentPage } }
     val scope = rememberCoroutineScope()
 
-
-
-    serverData.forEachIndexed { index, server ->
-        Log.d("test_data", "${server.name} ${server.servers?.size} -> ${serverData.size}")
-    }
+//    serverData.forEachIndexed { index, server ->
+//        Log.d("test_data", "${server.name} ${server.servers?.size} -> ${serverData.size}")
+//    }
 
     androidx.compose.material3.ScrollableTabRow(
         selectedTabIndex = selectedIndex,
@@ -527,10 +606,15 @@ fun ColumnScope.ShowAllLocationsList(
 
 
     var isServersListExpanded by rememberSaveable { mutableStateOf(List(data.size) {true}) }
+
+//    var isServersListExpanded = List(data.size) { true }
+
     var isStreamingExpanded by rememberSaveable { mutableStateOf(true) }
     var isDvpnExpanded by rememberSaveable { mutableStateOf(true) }
     var isP2PExpanded by rememberSaveable { mutableStateOf(true) }
 
+    var isServersShown by rememberSaveable { mutableStateOf(true) }
+
     val isServersTabExpanded by rememberSaveable { mutableStateOf(listOf(true)) }
 
 //    val rotationState by animateFloatAsState(
@@ -592,6 +676,7 @@ fun ColumnScope.ShowAllLocationsList(
                         it[serverTabPager] = !isServersListExpanded[serverTabPager]
                     }
 
+
                     //                    when (serverTabPager) {
 //                        0 -> {
 //                            isCountriesExpanded = !isCountriesExpanded
@@ -635,92 +720,13 @@ fun ColumnScope.ShowAllLocationsList(
                                 CountryItem(server = country, data[serverTabPager].name!!)
                             }
                         }
+
+
+
                     }
                 }
 
-//                when (serverTabPager) {
-//                    0 -> {
-//                        if (isCountriesExpanded) {
-//                            CompositionLocalProvider(
-//                                LocalOverscrollConfiguration provides null
-//                            ) {
-//                                val country = basePreferenceHelper.getServerData()
-//                                val filterData = country.get(0).servers?.let {
-//                                    serverListViewModel.filterServersByISO(
-//                                        it
-//                                    )
-//                                }
-//
-//                                LazyColumn() {
-//                                    items(items = filterData!!) { country ->
-//                                        CountryItem(server = country)
-//                                    }
-//                                }
-//                            }
-//
-//                        }
-//                    }
-//                    1 -> {
-//                        if (isStreamingExpanded) {
-//                            CompositionLocalProvider(
-//                                LocalOverscrollConfiguration provides null
-//                            ) {
-//                                val streaming = basePreferenceHelper.getServerData()
-//                                val filterData = streaming.get(1).servers?.let {
-//                                    serverListViewModel.filterServersByStreamingServers(
-//                                        it
-//                                    )
-//                                }
-//                                LazyColumn() {
-//                                    items(items = filterData!!) { streaming ->
-//                                        ServerItem(server = streaming)
-//                                    }
-//                                }
-//                            }
-//                        }
-//                    }
-//                    2 -> {
-//                        if (isDvpnExpanded) {
-//                            CompositionLocalProvider(
-//                                LocalOverscrollConfiguration provides null
-//                            ) {
-//                                val dvpn = basePreferenceHelper.getServerData()
-//                                val filterData = dvpn.get(2).servers?.let {
-//                                    serverListViewModel.filterServersByISO(
-//                                        it
-//                                    )
-//                                }
-//
-//                                LazyColumn() {
-//                                    items(items = filterData!!) { dvpn ->
-//                                        ServerItem(server = dvpn)
-//                                    }
-//                                }
-//                            }
-//
-//                        }
-//                    }
-//                    3 -> {
-//                        if (isP2PExpanded) {
-//                            CompositionLocalProvider(
-//                                LocalOverscrollConfiguration provides null
-//                            ) {
-//                                val p2p = basePreferenceHelper.getServerData()
-//                                val filterData = p2p.get(3).servers?.let {
-//                                    serverListViewModel.filterServersByISO(
-//                                        it
-//                                    )
-//                                }
-//
-//                                LazyColumn() {
-//                                    items(items = filterData!!) { p2p ->
-//                                        ServerItem(server = p2p)
-//                                    }
-//                                }
-//                            }
-//                        }
-//                    }
-//                }
+
             }
         }
 
@@ -807,8 +813,11 @@ fun ColumnScope.ShowSearchBar(
     basePreferenceHelper: BasePreferenceHelper) {
 
     val context = LocalContext.current
+    val splashViewModel: SplashViewModel = viewModel{
+        SplashViewModel(context)
+    }
     val searchListViewModel: SearchListViewModel = viewModel{
-        SearchListViewModel(context, serverListViewModel)
+        SearchListViewModel(context, serverListViewModel, splashViewModel)
     }
 
 //    var searchText by remember { mutableStateOf("") }
@@ -968,4 +977,92 @@ fun ColumnScope.ShowSearchBar(
 @Composable
 fun ServerListPreview() {
     ServerList(rememberNavController(), false)
-}
+}
+
+
+
+
+
+//                when (serverTabPager) {
+//                    0 -> {
+//                        if (isCountriesExpanded) {
+//                            CompositionLocalProvider(
+//                                LocalOverscrollConfiguration provides null
+//                            ) {
+//                                val country = basePreferenceHelper.getServerData()
+//                                val filterData = country.get(0).servers?.let {
+//                                    serverListViewModel.filterServersByISO(
+//                                        it
+//                                    )
+//                                }
+//
+//                                LazyColumn() {
+//                                    items(items = filterData!!) { country ->
+//                                        CountryItem(server = country)
+//                                    }
+//                                }
+//                            }
+//
+//                        }
+//                    }
+//                    1 -> {
+//                        if (isStreamingExpanded) {
+//                            CompositionLocalProvider(
+//                                LocalOverscrollConfiguration provides null
+//                            ) {
+//                                val streaming = basePreferenceHelper.getServerData()
+//                                val filterData = streaming.get(1).servers?.let {
+//                                    serverListViewModel.filterServersByStreamingServers(
+//                                        it
+//                                    )
+//                                }
+//                                LazyColumn() {
+//                                    items(items = filterData!!) { streaming ->
+//                                        ServerItem(server = streaming)
+//                                    }
+//                                }
+//                            }
+//                        }
+//                    }
+//                    2 -> {
+//                        if (isDvpnExpanded) {
+//                            CompositionLocalProvider(
+//                                LocalOverscrollConfiguration provides null
+//                            ) {
+//                                val dvpn = basePreferenceHelper.getServerData()
+//                                val filterData = dvpn.get(2).servers?.let {
+//                                    serverListViewModel.filterServersByISO(
+//                                        it
+//                                    )
+//                                }
+//
+//                                LazyColumn() {
+//                                    items(items = filterData!!) { dvpn ->
+//                                        ServerItem(server = dvpn)
+//                                    }
+//                                }
+//                            }
+//
+//                        }
+//                    }
+//                    3 -> {
+//                        if (isP2PExpanded) {
+//                            CompositionLocalProvider(
+//                                LocalOverscrollConfiguration provides null
+//                            ) {
+//                                val p2p = basePreferenceHelper.getServerData()
+//                                val filterData = p2p.get(3).servers?.let {
+//                                    serverListViewModel.filterServersByISO(
+//                                        it
+//                                    )
+//                                }
+//
+//                                LazyColumn() {
+//                                    items(items = filterData!!) { p2p ->
+//                                        ServerItem(server = p2p)
+//                                    }
+//                                }
+//                            }
+//                        }
+//                    }
+//                }

+ 8 - 1
app/src/main/java/com/vpn/fastestvpnservice/screens/SplashScreen.kt

@@ -43,22 +43,28 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.UiMode
 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.SplashViewModel
 import kotlinx.coroutines.delay
 
 @Composable
 fun Splash(navHostController: NavHostController) {
     val context = LocalContext.current
     val basePreferenceHelper = BasePreferenceHelper(context)
+    val splashViewModel: SplashViewModel = viewModel{
+        SplashViewModel(context)
+    }
 
     Box(modifier = Modifier
         .paint(
             painter = painterResource(id = R.drawable.bg_img3),
-            contentScale = ContentScale.FillBounds)
+            contentScale = ContentScale.FillBounds
+        )
 //        .background(if (isSystemInDarkTheme()) Color.Black
 //        else colorResource(id = R.color.transparent))
         .fillMaxSize(),
@@ -96,6 +102,7 @@ fun Splash(navHostController: NavHostController) {
     val isLoggedIn = basePreferenceHelper.getLoggedInState()
 
     LaunchedEffect(key1 = true) {
+        splashViewModel.serverDataApi()
         delay(3000)
 
         if (isLoggedIn) {

+ 28 - 12
app/src/main/java/com/vpn/fastestvpnservice/screens/accountScreensAll/FavoriteServersScreen.kt

@@ -2,6 +2,8 @@ package com.vpn.fastestvpnservice.screens.accountScreensAll
 
 import android.content.res.Configuration
 import android.util.Log
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.LocalOverscrollConfiguration
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -20,6 +22,8 @@ import androidx.compose.material.Surface
 import androidx.compose.material.Text
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.livedata.observeAsState
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -42,6 +46,7 @@ import com.vpn.fastestvpnservice.customItems.ServerItem
 import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 fun FavoriteServers(navHostController: NavHostController) {
     val context = LocalContext.current
@@ -69,19 +74,30 @@ fun FavoriteServers(navHostController: NavHostController) {
                 .fillMaxSize()
                 .background(Color.Transparent)
         ) {
-            LazyColumn() {
-                val favoriteServers = basePreferenceHelper.getServerData().get(0)
-                val filterFavoriteServers = favoriteServers.servers?.let {
-                    serverListViewModel.filterServersByISO(
-                        it
-                    )
-                }
+            val favoriteServers = serverListViewModel.liveDataGetFavList.observeAsState().value
+
+            CompositionLocalProvider(
+                LocalOverscrollConfiguration provides null
+            ) {
+                LazyColumn {
+//                    val favoriteServers = basePreferenceHelper.getServerData().get(0)
+//                    val filterFavoriteServers = favoriteServers.servers?.let {
+//                        serverListViewModel.filterServersByISO(
+//                            it
+//                        )
+//                    }
+
+
+//                    favoriteServers?.forEachIndexed { index, server ->
+//                        Log.d("filterFavoriteServers", "${server.country} ${server.server_name}")
+//                    }
+
+                    favoriteServers?.let {
+                        items(items = favoriteServers) {server ->
+                            FavoriteServerItem(server = server)
+                        }
+                    }
 
-                filterFavoriteServers?.forEachIndexed { index, server ->
-                    Log.d("filterFavoriteServers", "${server.country} ${server.server_name}")
-                }
-                items(items = filterFavoriteServers!!) {server ->
-                    FavoriteServerItem(server = server)
                 }
             }
         }

+ 60 - 3
app/src/main/java/com/vpn/fastestvpnservice/screens/accountScreensAll/SubscriptionScreen.kt

@@ -1,5 +1,6 @@
 package com.vpn.fastestvpnservice.screens.accountScreensAll
 
+import android.os.Build
 import android.util.Log
 import android.widget.Toast
 import androidx.compose.foundation.ExperimentalFoundationApi
@@ -29,10 +30,15 @@ import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLifecycleOwner
 import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.TextStyle
@@ -42,25 +48,46 @@ import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.viewmodel.compose.viewModel
 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.ProductFeatures
+import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.subscriptionList
 import com.vpn.fastestvpnservice.beans.subscriptionPackageList
 import com.vpn.fastestvpnservice.customItems.SubscriptionDataItem
 import com.vpn.fastestvpnservice.customItems.SubscriptionPackageItem
 import com.vpn.fastestvpnservice.customItems.getSelectedPosition
+import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.OnLifecycleEvent
 import com.vpn.fastestvpnservice.sealedClass.Screen
+import com.vpn.fastestvpnservice.utils.Utils
+import com.vpn.fastestvpnservice.viewmodels.SubscriptionViewModel
 
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 fun SubscriptionScreen(navHostController: NavHostController) {
+
+    val context = LocalContext.current
+    val subscriptionViewModel: SubscriptionViewModel = viewModel{
+        SubscriptionViewModel(context = context)
+    }
     var selectedPosition: Int = 0
+
     Box(
         modifier = Modifier
             .fillMaxSize()
             .background(MaterialTheme.colorScheme.background)
     ) {
+
+        LaunchedEffect(key1 = true) {
+            subscriptionViewModel.getProducts()
+        }
+
         HeaderRowSS(navHostController = navHostController)
 
         Column(
@@ -91,10 +118,20 @@ fun SubscriptionScreen(navHostController: NavHostController) {
                 CompositionLocalProvider(
                     LocalOverscrollConfiguration provides null
                 ) {
+                    val productsData = subscriptionViewModel.liveDataProducts.observeAsState().value
+
                     LazyColumn() {
-                        items(items = subscriptionList) {item ->
-                            SubscriptionDataItem(item = item)
+
+                        productsData?.let {
+                            Log.d("test_api_response p", "Products screen = ${it.message}")
+
+                            items(items = it.data?.get(0)?.features!!) {item ->
+                                SubscriptionDataItem(item = item)
+                            }
+
                         }
+
+
                         item { Spacer(modifier = Modifier.height(20.dp)) }
                         itemsIndexed(items = subscriptionPackageList) {position, plan ->
                             SubscriptionPackageItem(item = plan, position)
@@ -105,7 +142,6 @@ fun SubscriptionScreen(navHostController: NavHostController) {
             }
         }
 
-        val context = LocalContext.current
         Button(
             onClick = {
                 Log.d("test_button", "onClick")
@@ -148,6 +184,27 @@ fun SubscriptionScreen(navHostController: NavHostController) {
 }
 
 @Composable
+fun OnLifecycleEventSS(onEvent: (
+    owner: LifecycleOwner,
+    event: Lifecycle.Event
+) -> Unit) {
+    val eventHandler = rememberUpdatedState(onEvent)
+    val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
+
+    DisposableEffect(lifecycleOwner.value) {
+        val lifecycle = lifecycleOwner.value.lifecycle
+        val observer = LifecycleEventObserver { owner, event ->
+            eventHandler.value(owner, event)
+        }
+
+        lifecycle.addObserver(observer)
+        onDispose {
+            lifecycle.removeObserver(observer)
+        }
+    }
+}
+
+@Composable
 fun BoxScope.HeaderRowSS(navHostController: NavHostController) {
     IconButton(
         onClick = {

+ 104 - 2
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/HomeScreen.kt

@@ -46,6 +46,7 @@ import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -68,16 +69,27 @@ import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import  androidx.compose.runtime.setValue
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
+import com.vpn.fastestvpnservice.beans.Server
 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
+import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
+import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
@@ -85,7 +97,66 @@ fun Home(navHostController: NavHostController) {
 
     val context = LocalContext.current
     var isConnect by remember { mutableStateOf(false) }
-    val basePreferenceHelper = BasePreferenceHelper(context)
+    val prefHelper = BasePreferenceHelper(context)
+    val homeViewModel: HomeViewModel = viewModel{
+        HomeViewModel(context)
+    }
+    val serverViewModel: ServerListViewModel = viewModel{
+        ServerListViewModel(context)
+    }
+    val splashViewModel: SplashViewModel = viewModel{
+        SplashViewModel(context)
+    }
+    var server: Server = Server()
+
+    OnLifecycleEvent{owner, event ->
+        when(event) {
+            Lifecycle.Event.ON_RESUME -> {
+                Log.d("test_home_resume", "ON_RESUME: Home Screen!")
+                homeViewModel.getIp()
+
+                var filterServerByConnectionCount = Server()
+                if (prefHelper.getServerObject() != null) {
+                    prefHelper.getServerObject()?.let {
+                        filterServerByConnectionCount = it
+                    }
+                } else {
+                    prefHelper.getServerData().get(0).servers?.let {
+
+                        val temp = it.filter { server ->
+                            server.protocol.equals(prefHelper.getProtocol().title, ignoreCase = true)
+                        }
+
+                        if (temp.isNotEmpty()) {
+                            filterServerByConnectionCount = serverViewModel.filterServerByConnectionCount(
+                                it
+                            )
+                        }
+                    }
+                }
+                prefHelper.setServerObject(filterServerByConnectionCount)
+
+                server = filterServerByConnectionCount
+
+//                splashViewModel.serverDataApi()
+                homeViewModel.validatePassword(
+                    prefHelper.getUser()?.userinfo?.email.toString(),
+                    prefHelper.getPassword().toString(),
+                    "android",
+                    android.os.Build.VERSION.RELEASE
+                )
+            }
+            else -> {
+                Log.d("test_home_resume", "else: Home Screen!")
+            }
+        }
+    }
+
+    val ip = homeViewModel.mutableLiveDataIpInfo.observeAsState().value
+    ip?.let {
+        Log.d("test_api_response", "ip home = ${it.country}")
+    }
+
     Box(
         modifier = Modifier
             .background(MaterialTheme.colorScheme.background)
@@ -112,10 +183,19 @@ fun Home(navHostController: NavHostController) {
             )
         }
 
+
+
         IconButton(
             onClick = {
                 isConnect = !isConnect
-                val status = basePreferenceHelper.getAdBlockState()
+//                homeViewModel.getIp()
+
+//                server.let {
+//                    serverViewModel.updateFavServer(server)
+//                }
+
+
+
             },
             modifier = Modifier
                 .align(Alignment.TopCenter)
@@ -136,6 +216,7 @@ fun Home(navHostController: NavHostController) {
                     contentScale = ContentScale.FillWidth,
                 )
             }
+
         }
         Column(
             verticalArrangement = Arrangement.SpaceEvenly,
@@ -415,6 +496,27 @@ fun Home(navHostController: NavHostController) {
 }
 
 @Composable
+fun OnLifecycleEvent(onEvent: (
+    owner: LifecycleOwner,
+    event: Lifecycle.Event
+) -> Unit) {
+    val eventHandler = rememberUpdatedState(onEvent)
+    val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
+
+    DisposableEffect(lifecycleOwner.value) {
+        val lifecycle = lifecycleOwner.value.lifecycle
+        val observer = LifecycleEventObserver { owner, event ->
+            eventHandler.value(owner, event)
+        }
+
+        lifecycle.addObserver(observer)
+        onDispose {
+            lifecycle.removeObserver(observer)
+        }
+    }
+}
+
+@Composable
 fun ColumnScope.ColumnText(text: String, color: Color, size: TextUnit) {
     Surface(
         modifier = Modifier.padding(start = 0.dp),

+ 28 - 0
app/src/main/java/com/vpn/fastestvpnservice/screens/settingsScreenAll/NotificationsScreen.kt

@@ -4,11 +4,14 @@ import androidx.compose.foundation.background
 import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
 import androidx.compose.material.Icon
 import androidx.compose.material.IconButton
 import androidx.compose.material.Surface
@@ -17,8 +20,10 @@ import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.automirrored.filled.ArrowBack
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.res.painterResource
@@ -28,12 +33,16 @@ import androidx.compose.ui.text.style.TextAlign
 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.customItems.NotificationItem
+import com.vpn.fastestvpnservice.viewmodels.NotificationViewModel
 
 @Composable
 fun Notifications(navHostController: NavHostController) {
+    val notificationViewModel: NotificationViewModel = viewModel()
     Box(
         modifier = Modifier
             .fillMaxSize()
@@ -41,7 +50,26 @@ fun Notifications(navHostController: NavHostController) {
                 color = MaterialTheme.colorScheme.background
             )
     ) {
+        notificationViewModel.getNotifications()
         HeaderRowNS(navHostController = navHostController)
+
+        Column(
+            modifier = Modifier
+                .padding(top = 100.dp)
+                .fillMaxSize()
+        ) {
+            val notifications = notificationViewModel.liveDataNotification.observeAsState().value
+
+            LazyColumn() {
+
+                notifications?.let {
+                    items(it) { item ->
+                        NotificationItem(item = item)
+                    }
+                }
+
+            }
+        }
     }
 }
 

+ 28 - 0
app/src/main/java/com/vpn/fastestvpnservice/utils/Utils.kt

@@ -2,6 +2,13 @@ package com.vpn.fastestvpnservice.utils
 
 import android.content.Context
 import android.graphics.drawable.Drawable
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
 import java.util.*
 
 class Utils {
@@ -19,6 +26,27 @@ class Utils {
             return context.resources.getIdentifier(iso_gray, "drawable", context.packageName)
         }
 
+//        @Composable
+//        fun OnLifecycleEvent(onEvent: (
+//            owner: LifecycleOwner,
+//            event: Lifecycle.Event
+//        ) -> Unit) {
+//            val eventHandler = rememberUpdatedState(onEvent)
+//            val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
+//
+//            DisposableEffect(lifecycleOwner.value) {
+//                val lifecycle = lifecycleOwner.value.lifecycle
+//                val observer = LifecycleEventObserver { owner, event ->
+//                    eventHandler.value(owner, event)
+//                }
+//
+//                lifecycle.addObserver(observer)
+//                onDispose {
+//                    lifecycle.removeObserver(observer)
+//                }
+//            }
+//        }
+
         /*  fun openWebActivity(contexts: Activity, url: String, title: String) {
               val intent = Intent(contexts, WebViwActivity::class.java)
               intent.putExtra(WebViwActivity.PARAM_WEB_VIEW_URL, url)

+ 98 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/HomeViewModel.kt

@@ -0,0 +1,98 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.content.Context
+import android.util.Log
+import androidx.compose.ui.platform.LocalContext
+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.IpInfo
+import com.vpn.fastestvpnservice.beans.TokenResponse
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+
+class HomeViewModel constructor(context: Context): ViewModel() {
+    var prefHelper: BasePreferenceHelper? = null
+    val mutableLiveDataIpInfo = MutableLiveData<IpInfo?>()
+
+    var _mutableLiveDataValidate = MutableLiveData<DataResponse<TokenResponse>>()
+    var liveDataValidate : LiveData<DataResponse<TokenResponse>> = _mutableLiveDataValidate
+    var mutableLiveDataValidateError = MutableLiveData<String>()
+
+    init {
+        prefHelper = BasePreferenceHelper(context)
+    }
+    fun getIp() {
+        WebServiceFactory.getInstance().getIp()
+            .enqueue(RetrofitNetworkHandling<Any>(object :
+                RetrofitNetworkHandling.ResponseCallback<Any> {
+                override fun onSuccess(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "ip = onSuccess")
+                    try {
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<IpInfo>() {}.type
+                        val data = gson.fromJson<IpInfo>(jsonString, type)
+                        mutableLiveDataIpInfo.value = data
+                        if (data != null) {
+                            prefHelper?.saveIpInfo(data)
+                        }
+                    Log.d("test_api_response", "ip = " + data?.country.toString() + " " + data?.countryCode)
+                    } catch (ex: Exception) { }
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "ip: = onFail")
+                    mutableLiveDataIpInfo.value = null
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "ip: = onError")
+                    mutableLiveDataIpInfo.value = null
+                }
+            }))
+    }
+
+    fun validatePassword(
+        email: String,
+        password: String,
+        platform: String,
+        version: String
+    ) {
+
+        WebServiceFactory.getInstance().validatePassword(email, password, platform, version)?.enqueue(
+            RetrofitNetworkHandling<Any>(object :
+                RetrofitNetworkHandling.ResponseCallback<Any> {
+                override fun onSuccess(call: Call<Any>?, response: Any?) {
+                    try {
+                        Log.d("test_api_response", "validatePassword onSuccess: try")
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<DataResponse<TokenResponse?>?>() {}.type
+                        val data = gson.fromJson<DataResponse<TokenResponse>>(jsonString, type)
+                        _mutableLiveDataValidate.value = data
+
+                    } catch (ex: Exception) {
+                        Log.d("test_api_response", "validatePassword onSuccess: catch")
+                    }
+
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "validatePassword onFail")
+                    mutableLiveDataValidateError.value = "Something went wrong. Please try again"
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "validatePassword onError")
+                    mutableLiveDataValidateError.value = "Something went wrong. Please try again"
+                }
+            })
+        )
+    }
+}

+ 53 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/NotificationViewModel.kt

@@ -0,0 +1,53 @@
+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.Notification
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+
+class NotificationViewModel: ViewModel() {
+
+    val _mutableLiveDataNotification = MutableLiveData<List<Notification>?>()
+    val liveDataNotification: LiveData<List<Notification>?> = _mutableLiveDataNotification
+
+    fun getNotifications() {
+        WebServiceFactory.getInstance().getNotifications()
+            .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<List<Notification>>>() {}.type
+                        val data = gson.fromJson<DataResponse<List<Notification>>>(jsonString, type)
+
+                    Log.d("test_api_response", "notification = ${data.message}")
+
+                        _mutableLiveDataNotification.value = data.data
+                    } catch (ex: Exception) {
+
+                    }
+
+
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    _mutableLiveDataNotification.value = null
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    _mutableLiveDataNotification.value = null
+                }
+
+            }))
+
+    }
+}

+ 44 - 1
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SearchListViewModel.kt

@@ -8,15 +8,30 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewmodel.compose.viewModel
+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 SearchListViewModel constructor(context: Context, serverListViewModel: ServerListViewModel): ViewModel() {
+class SearchListViewModel constructor(
+    context: Context,
+    serverListViewModel: ServerListViewModel,
+    splashViewModel: SplashViewModel
+    ): ViewModel() {
 
     private var serverListViewModel: ServerListViewModel
+    private var splashViewModel: SplashViewModel
+    val mutableLiveDataFavUnFav = MutableLiveData<ServerResponse?>()
+
 
     init {
         this.serverListViewModel = serverListViewModel
+        this.splashViewModel = splashViewModel
     }
 
     private var _searchText = MutableLiveData<String>("")
@@ -78,4 +93,32 @@ class SearchListViewModel constructor(context: Context, serverListViewModel: Ser
 
     }
 
+    fun updateFavUnFavServerState(server: Server) {
+        server.isFavourited = server.isFavourited != true
+        val serverData = basePreferenceHelper.getServerData()
+        val allServers: ArrayList<Server> = ArrayList<Server>()
+
+        serverData.forEachIndexed { i, serverDataList ->
+            serverDataList.servers?.let {serverList ->
+                serverList.forEachIndexed { index, obj ->
+                    if (obj.id == server.id) {
+                        obj.isFavourited = server.isFavourited
+                        serverList.set(index, obj)
+                    }
+                }
+            }
+        }
+
+        serverData.forEachIndexed { index1, serverData1 ->
+            serverData1.servers?.forEachIndexed { indexes, server ->
+                allServers.add(indexes, server)
+            }
+        }
+
+        val searchServersList = serverListViewModel.filterServersAllCategory(allServers)
+        _countriesList.value = searchServersList
+
+        basePreferenceHelper.saveServerData(serverData)
+    }
+
 }

+ 78 - 31
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/ServerListViewModel.kt

@@ -2,6 +2,7 @@ package com.vpn.fastestvpnservice.viewmodels
 
 import android.content.Context
 import android.util.Log
+import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
@@ -11,46 +12,31 @@ 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.helpers.UIHelper
 import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
 import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
 import retrofit2.Call
 
 class ServerListViewModel(context: Context): ViewModel() {
 
+    private var preferencesHelper = BasePreferenceHelper(context)
+
     val mutableLiveData = MutableLiveData<List<ServerData>>()
     val mutableLiveDataFavourite = MutableLiveData<List<Server>>()
     val mutableLiveDataFavUnFav = MutableLiveData<ServerResponse?>()
-    private var preferencesHelper: BasePreferenceHelper
 
-    init {
-        preferencesHelper = BasePreferenceHelper(context)
-    }
+    var mutableLiveDataCountrySize = MutableLiveData<Int>()
 
-    fun getFavList(): ArrayList<Server> {
-        var tempList = ArrayList<Server>()
-        preferencesHelper.getServerData().let {
-            it.forEach {
-                tempList.addAll(it.servers?.filter {
-                    it.isFavourited == true
-                }!!)
-            }
-        }
-        return tempList
-    }
+    private var _mutableLiveDataGetFavList = MutableLiveData<ArrayList<Server>>(getFavList())
+    var liveDataGetFavList: LiveData<ArrayList<Server>> = _mutableLiveDataGetFavList
 
-    fun updateFavServer(server: Server) {
-        server.isFavourited = server.isFavourited != true
-        val serverData = preferencesHelper.getServerData()
+//    init {
+//        preferencesHelper = BasePreferenceHelper(context)
+//    }
 
-        serverData.forEach {
-            it.servers?.forEachIndexed { index, obj ->
-                if (server.id == obj.id) {
-                    it.servers.set(index, server)
 
-                }
-            }
-        }
-        preferencesHelper.saveServerData(serverData as ArrayList<ServerData>)
+    fun setCountrySize(server: Server) {
+        mutableLiveDataCountrySize.value = server.totalServers
     }
 
     fun filterServersByISO(serverlist: ArrayList<Server>): ArrayList<Server> {
@@ -261,9 +247,9 @@ class ServerListViewModel(context: Context): ViewModel() {
         Log.d("streaming_servers t", distinctBy.size.toString())
 
 
-        serverprotocol.groupBy(Server::country).mapValues { entry ->
+        serverprotocol.groupBy(Server::server_name).mapValues { entry ->
             for ((index, value) in distinctBy.withIndex()) {
-                if (entry.key == value.country) {
+                if (entry.key == value.server_name) {
 //                    distinctBy.get(index).totalServers = entry.value.sumBy { it.totalServers }
                     distinctBy.get(index).totalServers = 1
 
@@ -372,7 +358,7 @@ class ServerListViewModel(context: Context): ViewModel() {
     }
 
     fun favAndUnFav(server: Server) {
-        updateFavServer(server)
+//        updateFavServer(server)
         WebServiceFactory.getInstance().setFavUnfav("${server.id}")
             .enqueue(RetrofitNetworkHandling<Any>(object :
                 RetrofitNetworkHandling.ResponseCallback<Any> {
@@ -388,7 +374,8 @@ class ServerListViewModel(context: Context): ViewModel() {
                         if (data.error == 0)
                         {
                             mutableLiveDataFavUnFav.value = data
-//                        UIHelper.showToast(data.message)
+
+                        UIHelper.showToast(data.message)
                         }
                         else {
                             mutableLiveDataFavUnFav.value = null
@@ -410,4 +397,64 @@ class ServerListViewModel(context: Context): ViewModel() {
             }))
 
     }
-}
+
+    fun getFavList(): ArrayList<Server> {
+        val 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.forEachIndexed { i, serverDataList ->
+            serverDataList.servers?.let {serverList ->
+                serverList.forEachIndexed { index, obj ->
+                    if (obj.id == server.id) {
+                        Log.d("test_serverData_Fav","if => index[$i]:: obj.id ${obj.id} , server = ${server.server_name}")
+//                        obj.isFavourited = obj.isFavourited != true
+                        serverList.set(index, server)
+                    }
+                }
+            }
+        }
+
+//        serverData.forEachIndexed { i, serverDataList ->
+//            serverDataList.servers?.let {serverList ->
+//                serverList.forEachIndexed { index, obj ->
+//                    if (obj.id == server.id) {
+//                        Log.d("test_serverData_Fav","if => index[$i]:: obj.id ${obj.id} , server_id = ${server.id}")
+//                        obj.isFavourited = server.isFavourited
+//                        serverList[index] = obj
+//                    }
+//                }
+//            }
+//        }
+
+        preferencesHelper.saveServerData(serverData)
+    }
+
+}
+
+//serverData.let {
+//            it.forEach {serverDataList ->
+//                Log.d("test_serverData_Fav","data = " + serverDataList.name)
+//
+//                serverDataList.servers?.let { serversList ->
+//                    serversList.forEachIndexed { index, obj ->
+//                        if (obj.id == server.id){
+//                            obj.isFavourited = server.isFavourited
+//                            it.set(index, serverDataList)
+//                        }
+//                    }
+//                }
+//            }
+//        }

+ 78 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SplashViewModel.kt

@@ -0,0 +1,78 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.content.Context
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.beans.DataResponseServers
+import com.vpn.fastestvpnservice.beans.ServerData
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+
+class SplashViewModel constructor(context: Context): ViewModel() {
+    val mutableLiveDataServerData = MutableLiveData<DataResponseServers<ArrayList<ServerData>>>()
+    var preferenceHelper: BasePreferenceHelper
+
+    init {
+        preferenceHelper = BasePreferenceHelper(context)
+    }
+    fun serverDataApi() {
+        WebServiceFactory.getInstance().serverDataApi().enqueue(
+            RetrofitNetworkHandling<Any>(object :
+                RetrofitNetworkHandling.ResponseCallback<Any> {
+                override fun onSuccess(call: Call<Any>?, response: Any?) {
+                    try {
+                        Log.d("test_api_response", "server try = $response")
+                        val gson = Gson()
+                        val jsonString = gson.toJson(response)
+                        val type = object : TypeToken<DataResponseServers<ArrayList<ServerData>>>() {}.type
+                        val data = gson.fromJson<DataResponseServers<ArrayList<ServerData>>>(jsonString, type)
+                        Log.d("test_api_response", "server try After = $response")
+
+                        if (data?.status == true) {
+                            Log.d("test_fav_response", "Splash Res: ${data.message}")
+
+                            mutableLiveDataServerData.value = data
+                            data.data?.let { preferenceHelper.saveServerData(it)
+                            }
+                            data.wireguard?.let {
+                                preferenceHelper.saveWireGuard(it)
+                            }
+                            data.product?.let {
+//                            Log.d("test_api_response", it.productName.toString())
+                                preferenceHelper.saveProduct(it)
+                            }
+                            data.available_protocols.let {
+                                preferenceHelper.saveAvailableProtocols(it)
+                            }
+                            data.enabled_protocols.let {
+                                preferenceHelper.saveEnabledProtocols(it)
+                            }
+//                        Log.d("test_api_response", data.data.toString())
+//                        Log.d("test_api_response", data.enabled_protocols.toString())
+//                        Log.d("test_api_response", data.available_protocols.toString())
+                        }
+                    } catch (ex: Exception) {
+                        Log.d("test_api_response", "server catch")
+                    }
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "server onFail = $response")
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "server onError = $response")
+                }
+
+            }
+            )
+        )
+
+    }
+
+}

+ 69 - 0
app/src/main/java/com/vpn/fastestvpnservice/viewmodels/SubscriptionViewModel.kt

@@ -0,0 +1,69 @@
+package com.vpn.fastestvpnservice.viewmodels
+
+import android.content.Context
+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.ProductFeatures
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
+import retrofit2.Call
+
+class SubscriptionViewModel constructor(context: Context): ViewModel() {
+
+    var mutableLiveDataProducts = MutableLiveData<DataResponse<ArrayList<ProductFeatures>>>()
+    var liveDataProducts: LiveData<DataResponse<ArrayList<ProductFeatures>>> = mutableLiveDataProducts
+
+    var mutableLiveDataProductsErrorStatus = MutableLiveData<Boolean>()
+
+    var preferenceHelper: BasePreferenceHelper
+
+    init {
+        preferenceHelper = BasePreferenceHelper(context)
+    }
+    fun getProducts(){
+        WebServiceFactory.getInstance().getProducts().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<ArrayList<ProductFeatures>>>() {}.type
+                        val data = gson.fromJson<DataResponse<ArrayList<ProductFeatures>>>(jsonString, type)
+
+                        Log.d("test_api_response p", "Products try = ${data.status} ${data.message}")
+
+                        data?.data?.let {
+                            preferenceHelper.saveFeaturesData(it)
+                        }
+                        mutableLiveDataProducts.value = data
+                        mutableLiveDataProductsErrorStatus.value = false
+
+                    } catch (ex: Exception) {
+                        Log.d("test_api_response", "Products catch:")
+                        mutableLiveDataProductsErrorStatus.value = true
+                    }
+                }
+
+                override fun onFail(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "Products onFail: ")
+                    mutableLiveDataProductsErrorStatus.value = true
+                }
+
+                override fun onError(call: Call<Any>?, response: Any?) {
+                    Log.d("test_api_response", "Products onError: ")
+                    mutableLiveDataProductsErrorStatus.value = true
+                }
+            }
+            )
+        )
+    }
+
+}