Parcourir la source

Resolved crashes of uninitialize viewmodels objects on splash screen, handle server list of 0 size which was crashing app

Khubaib il y a 8 mois
Parent
commit
441774b4b9

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

@@ -1,7 +1,6 @@
 package com.vpn.fastestvpnservice.customItems
 
 import android.content.res.Configuration
-import android.os.Looper
 import android.util.Log
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
@@ -22,13 +21,10 @@ 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.mutableIntStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -45,9 +41,6 @@ import androidx.compose.ui.unit.dp
 import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.rememberNavController
-import com.stealthcopter.networktools.Ping
-import com.stealthcopter.networktools.ping.PingResult
-import com.stealthcopter.networktools.ping.PingStats
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.Server
 import com.vpn.fastestvpnservice.beans.favListServer
@@ -60,9 +53,6 @@ import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import com.vpn.fastestvpnservice.utils.Utils
 import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
-import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
-import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
-import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 
 @Composable
 fun ServerItem(server: Server, navHostController: NavHostController, serverPing: Int = 0) {

+ 39 - 20
app/src/main/java/com/vpn/fastestvpnservice/screens/ServerListScreen.kt

@@ -77,6 +77,7 @@ import androidx.compose.ui.res.painterResource
 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
@@ -91,7 +92,9 @@ import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.AddTextSettings
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import com.vpn.fastestvpnservice.ui.theme.customTypography2
 import com.vpn.fastestvpnservice.utils.isTablet
+import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
 import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 
@@ -111,7 +114,21 @@ fun ServerList(
     val serverListViewModel = serverListViewModelSplash
     val basePreferenceHelper = BasePreferenceHelper(context)
     isAlphabetList.value = basePreferenceHelper.getFilterList() != filterList[0]
-    searchListViewModelSplash.setCountriesListEmpty()
+
+    if (isSearchModelInitialized) {
+        searchListViewModelSplash.setCountriesListEmpty()
+    } else {
+        splashViewModelSplash = viewModel {
+            SplashViewModel(context)
+        }
+        serverListViewModelSplash = viewModel {
+            ServerListViewModel(context = context)
+        }
+        searchListViewModelSplash = viewModel {
+            SearchListViewModel(context, serverListViewModelSplash, splashViewModelSplash)
+        }
+    }
+
     Box(
         modifier = Modifier
             .fillMaxSize()
@@ -627,10 +644,10 @@ fun ColumnScope.ShowAllLocationsList(
                         }
 
                         serverListViewModelSplash.mutableLiveDataGroupServers.value = groupServers
-                    } else {
+                    }
+                    else {
                         if (countries != null) {
                             countriesFilter = countries
-
                             countriesFilter.get(selectedTabIndex)?.servers?.let {
                                 if (selectedTabIndex == 0) {
                                     it.sortBy {server ->
@@ -642,30 +659,32 @@ fun ColumnScope.ShowAllLocationsList(
                                     }
                                 }
                             }
-
                             groupServers?.sortBy {
                                 it?.country_sort
                             }
-
                             serverListViewModelSplash.mutableLiveDataGroupServers.value = groupServers
                         }
                     }
                     when (selectedTabIndex) {
                         0 -> {
-                            LazyColumn() {
+                            if (countriesFilter.size != 0) {
                                 countriesFilter?.get(selectedTabIndex)?.servers?.let {
-                                    itemsIndexed(items = it, itemContent = {index, country ->
-                                        CountryItem(server = country, "servers", country.totalServers, navHostController, index)
-                                    })
+                                    LazyColumn() {
+                                        itemsIndexed(items = it, itemContent = {index, country ->
+                                            CountryItem(server = country, "servers", country.totalServers, navHostController, index)
+                                        })
+                                    }
                                 }
                             }
                         }
                         else -> {
-                            LazyColumn() {
+                            if (countriesFilter.size != 0) {
                                 countriesFilter?.get(selectedTabIndex)?.servers?.let {
-                                    items(items = it, itemContent = {country ->
-                                        ServerItem(server = country, navHostController, country.ping)
-                                    })
+                                    LazyColumn() {
+                                        items(items = it, itemContent = {country ->
+                                            ServerItem(server = country, navHostController, country.ping)
+                                        })
+                                    }
                                 }
                             }
                         }
@@ -758,10 +777,10 @@ fun ColumnScope.ShowSearchBar(
 
     val keyboardController = LocalSoftwareKeyboardController.current
     val focusManager = LocalFocusManager.current
-    val searchListViewModel = searchListViewModelSplash
+//    val searchListViewModel = searchListViewModelSplash
     val scope = rememberCoroutineScope()
     var searchText1 by remember { mutableStateOf("") }
-    val isActive = searchListViewModel.isActive.observeAsState().value
+    val isActive = searchListViewModelSplash.isActive.observeAsState().value
     var isFilter by remember { mutableStateOf(false) }
     val sheetState = rememberModalBottomSheetState()
     var selectedFilterList by remember { mutableStateOf(basePreferenceHelper.getFilterList()) }
@@ -770,7 +789,7 @@ fun ColumnScope.ShowSearchBar(
         Log.d("test_search_logic", "LaunchedEffect $searchText1")
         val delay = if (searchText1.isEmpty()) 0L else 300L
         delay(delay)
-        searchListViewModel.getCountries(searchText1, true)
+        searchListViewModelSplash.getCountries(searchText1, true)
     }
 //    if (isActive == false) {
 //        searchText1 = ""
@@ -780,12 +799,12 @@ fun ColumnScope.ShowSearchBar(
         onQueryChange = {
             searchText1 = it
 //            scope.launch {
-//                searchListViewModel.searchTextChange(it)
+//                searchListViewModelSplash.searchTextChange(it)
 //            }
         },
         onSearch = {
 //            scope.launch {
-//                searchListViewModel.isActiveChange(false)
+//                searchListViewModelSplash.isActiveChange(false)
 //            }
 //            focusManager.clearFocus()
             keyboardController?.hide()
@@ -793,7 +812,7 @@ fun ColumnScope.ShowSearchBar(
         active = isActive!!,
         onActiveChange = {
             scope.launch {
-                searchListViewModel.isActiveChange(it)
+                searchListViewModelSplash.isActiveChange(it)
             }
         },
         placeholder = {
@@ -845,7 +864,7 @@ fun ColumnScope.ShowSearchBar(
     CompositionLocalProvider(
         LocalOverscrollConfiguration provides null
     ) {
-        val searchServersList = searchListViewModel.countriesList.observeAsState().value
+        val searchServersList = searchListViewModelSplash.countriesList.observeAsState().value
         searchServersList?.forEachIndexed { index, server ->
             Log.d("test_search", "SLS_ ${server.server_name} ${server.ping}")
         }

+ 3 - 0
app/src/main/java/com/vpn/fastestvpnservice/screens/SplashScreen.kt

@@ -51,6 +51,9 @@ lateinit var splashViewModelSplash: SplashViewModel
 lateinit var serverListViewModelSplash: ServerListViewModel
 lateinit var searchListViewModelSplash: SearchListViewModel
 
+val isServerModelInitialized get() = ::serverListViewModelSplash.isInitialized
+val isSearchModelInitialized get() = ::searchListViewModelSplash.isInitialized
+
 @Composable
 fun Splash(navHostController: NavHostController) {
     val context = LocalContext.current

+ 11 - 3
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/HomeScreen.kt

@@ -101,6 +101,7 @@ import com.vpn.fastestvpnservice.constants.smartConnect
 import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
 import com.vpn.fastestvpnservice.interfaces.NetworkSpeedCallback
 import com.vpn.fastestvpnservice.interfaces.ServerCallbacks
+import com.vpn.fastestvpnservice.screens.isServerModelInitialized
 import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import com.vpn.fastestvpnservice.ui.theme.customTypography
@@ -275,7 +276,14 @@ fun Home(
 //    val serverListViewModel: ServerListViewModel = viewModel{
 //        ServerListViewModel(context)
 //    }
-    val serverListViewModel = serverListViewModelSplash
+//    val serverListViewModel = serverListViewModelSplash
+
+    if (!isServerModelInitialized) {
+        serverListViewModelSplash = viewModel{
+            ServerListViewModel(context)
+        }
+    }
+
     vpnConnectionsUtil = VPNConnectionsUtil(context, activity, homeViewModel)
     homeViewModel1 = homeViewModel
     var isConnect: Int? = homeViewModel.isConnect.observeAsState().value
@@ -390,7 +398,7 @@ fun Home(
             ShowProtocolDialog(
                 basePreferenceHelper,
                 vpnConnectionsUtil,
-                serverListViewModel
+                serverListViewModelSplash
             )
         }
 
@@ -712,7 +720,7 @@ fun Home(
                                     Log.d("isConnect_State_vpn", "startVPN")
                                     basePreferenceHelper.setConnectedServer(smartServer)
                                     if (smartServer != null) {
-                                        serverListViewModel.setRecentlyConnectedServer(smartServer)
+                                        serverListViewModelSplash.setRecentlyConnectedServer(smartServer)
                                     }
                                     vpnConnectionsUtil.startVpn()
                                 }

+ 24 - 15
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/SettingsScreen.kt

@@ -9,10 +9,8 @@ import android.os.Build
 import android.os.Bundle
 import android.os.Handler
 import android.os.LocaleList
-import android.os.Looper
 import android.provider.Settings
 import android.util.Log
-import android.widget.Toast
 import androidx.activity.ComponentActivity
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.Image
@@ -22,7 +20,6 @@ import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
@@ -40,7 +37,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.DarkMode
-import androidx.compose.material.icons.filled.Language
 import androidx.compose.material.icons.filled.RocketLaunch
 import androidx.compose.material3.AlertDialog
 import androidx.compose.material3.BottomSheetDefaults
@@ -74,7 +70,6 @@ import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.draw.scale
-import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.ColorFilter
@@ -97,7 +92,6 @@ import androidx.compose.ui.window.DialogProperties
 import androidx.core.content.ContextCompat.startActivity
 import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavHostController
-import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.MainActivity
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.Protocol
@@ -108,15 +102,17 @@ import com.vpn.fastestvpnservice.constants.AppEnum
 import com.vpn.fastestvpnservice.constants.smartConnect
 import com.vpn.fastestvpnservice.customItems.ServerSpecificItem
 import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.screens.isSearchModelInitialized
 import com.vpn.fastestvpnservice.screens.searchListViewModelSplash
 import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
+import com.vpn.fastestvpnservice.screens.splashViewModelSplash
 import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
 import com.vpn.fastestvpnservice.sealedClass.Screen
 import com.vpn.fastestvpnservice.ui.theme.customTypography
-import com.vpn.fastestvpnservice.utils.VPNConnectionsUtil
-import com.vpn.fastestvpnservice.viewmodels.AccountViewModel
 import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
+import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
 import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
 import de.blinkt.openvpn.core.App
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
@@ -1432,10 +1428,23 @@ fun ColumnScope.AddRowSettingsSmart(
 
     if (isAnySpecificSheetOpen) {
         val sheetStateAny = rememberModalBottomSheetState(skipPartiallyExpanded = true)
-        val searchListViewModel = searchListViewModelSplash
+//        val searchListViewModel = searchListViewModelSplash
 //        val searchText = searchListViewModel.searchText.observeAsState().value
+
+        if (!isSearchModelInitialized) {
+            splashViewModelSplash = viewModel {
+                SplashViewModel(context)
+            }
+            serverListViewModelSplash = viewModel {
+                ServerListViewModel(context = context)
+            }
+            searchListViewModelSplash = viewModel {
+                SearchListViewModel(context, serverListViewModelSplash, splashViewModelSplash)
+            }
+        }
+
         var searchText1 by remember { mutableStateOf("") }
-        val isActive = searchListViewModel.isActive.observeAsState().value
+        val isActive = searchListViewModelSplash.isActive.observeAsState().value
         val scope = rememberCoroutineScope()
 
         ModalBottomSheet(
@@ -1473,7 +1482,7 @@ fun ColumnScope.AddRowSettingsSmart(
                             val delay = if (searchText1.isEmpty()) 0L else 300L
                             delay(delay)
                             val query = searchText1.ifEmpty { "settings_screen" }
-                            searchListViewModel.getCountries(query, true)
+                            searchListViewModelSplash.getCountries(query, true)
                         }
 //                        if (isActive == false) {
 //                            searchText1 = ""
@@ -1483,19 +1492,19 @@ fun ColumnScope.AddRowSettingsSmart(
                             onQueryChange = {
                                 searchText1 = it
 //                                scope.launch {
-//                                    searchListViewModel.searchTextChange(it)
+//                                    searchListViewModelSplash.searchTextChange(it)
 //                                }
                             },
                             onSearch = {
                                 scope.launch {
-                                    searchListViewModel.isActiveChange(state = false, true)
+                                    searchListViewModelSplash.isActiveChange(state = false, true)
                                 }
 //                                keyboardController?.hide()
                             },
                             active = isActive!!,
                             onActiveChange = {
                                 scope.launch {
-                                    searchListViewModel.isActiveChange(it, isFromSettings = true)
+                                    searchListViewModelSplash.isActiveChange(it, isFromSettings = true)
                                 }
                             },
                             placeholder = {
@@ -1533,7 +1542,7 @@ fun ColumnScope.AddRowSettingsSmart(
                                 .background(Color.Transparent)
                         ) {}
 
-                        val searchServersList = searchListViewModel.countriesListSettings.observeAsState().value
+                        val searchServersList = searchListViewModelSplash.countriesListSettings.observeAsState().value
                         LazyColumn(
                             modifier = Modifier
                                 .padding(top = 20.dp, bottom = 40.dp)

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

@@ -647,43 +647,43 @@ class ServerListViewModel(context: Context): ViewModel() {
 
     fun favAndUnFav(server: Server) {
         updateFavServer(server)
-        WebServiceFactory.getInstance().setFavUnfav("${server.id}")
-            .enqueue(RetrofitNetworkHandling<Any>(object :
-                RetrofitNetworkHandling.ResponseCallback<Any> {
-                override fun onSuccess(call: Call<Any>?, response: Any?) {
-                    try {
-//                        Log.d("test_api_response","Response favAndUnFav = " + response.toString())
-                        val gson = Gson()
-                        val jsonString = gson.toJson(response)
-                        val type = object : TypeToken<ServerResponse>() {}.type
-                        val data = gson.fromJson<ServerResponse>(jsonString, type)
-//                        Log.d("test_api_response","favAndUnFav = " + response.toString())
-
-                        if (data.error == 0)
-                        {
-                            mutableLiveDataFavUnFav.value = data
-
-//                        UIHelper.showToast(data.message)
-                        }
-                        else {
-                            mutableLiveDataFavUnFav.value = null
-                        }
-                    } catch (ex: Exception) {
-//                        Log.d("test_api_response","favAndUnFav catch = " + response.toString())
-
-                    }
-                }
-
-                override fun onFail(call: Call<Any>?, response: Any?) {
-                    mutableLiveDataFavUnFav.value = null
-                }
-
-                override fun onError(call: Call<Any>?, response: Any?) {
-                    mutableLiveDataFavUnFav.value = null
-                }
-
-            }))
 
+//        WebServiceFactory.getInstance().setFavUnfav("${server.id}")
+//            .enqueue(RetrofitNetworkHandling<Any>(object :
+//                RetrofitNetworkHandling.ResponseCallback<Any> {
+//                override fun onSuccess(call: Call<Any>?, response: Any?) {
+//                    try {
+////                        Log.d("test_api_response","Response favAndUnFav = " + response.toString())
+//                        val gson = Gson()
+//                        val jsonString = gson.toJson(response)
+//                        val type = object : TypeToken<ServerResponse>() {}.type
+//                        val data = gson.fromJson<ServerResponse>(jsonString, type)
+////                        Log.d("test_api_response","favAndUnFav = " + response.toString())
+//
+//                        if (data.error == 0)
+//                        {
+//                            mutableLiveDataFavUnFav.value = data
+//
+////                        UIHelper.showToast(data.message)
+//                        }
+//                        else {
+//                            mutableLiveDataFavUnFav.value = null
+//                        }
+//                    } catch (ex: Exception) {
+////                        Log.d("test_api_response","favAndUnFav catch = " + response.toString())
+//
+//                    }
+//                }
+//
+//                override fun onFail(call: Call<Any>?, response: Any?) {
+//                    mutableLiveDataFavUnFav.value = null
+//                }
+//
+//                override fun onError(call: Call<Any>?, response: Any?) {
+//                    mutableLiveDataFavUnFav.value = null
+//                }
+//
+//            }))
     }
 
     fun getFavList(toReturn: Boolean = false): ArrayList<Server> {