From 6073a522861c4fd95442b94bf61bd1b9388fba5e Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Thu, 13 Jun 2024 17:50:44 +0300 Subject: [PATCH 1/6] loop through list to find reachable url --- .../ole/planet/myplanet/MainApplication.kt | 2 +- .../ui/dashboard/BellDashboardFragment.kt | 71 +++++++++++-------- .../ui/dashboard/BellDashboardViewModel.kt | 2 +- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt b/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt index b0939e1ce0..129ca9eedc 100644 --- a/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt +++ b/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt @@ -118,7 +118,7 @@ class MainApplication : Application(), Application.ActivityLifecycleCallbacks { applyThemeMode(themeMode) } - suspend fun isServerReachable(urlString: String): Boolean { + suspend fun isServerReachable(urlString: String?): Boolean { return try { val url = URL(urlString) val connection = withContext(Dispatchers.IO) { diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt index cee92bcfe0..6cf9618a6c 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt @@ -1,6 +1,7 @@ package org.ole.planet.myplanet.ui.dashboard import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -36,6 +37,8 @@ import org.ole.planet.myplanet.ui.submission.MySubmissionFragment import org.ole.planet.myplanet.ui.team.TeamFragment import org.ole.planet.myplanet.utilities.DialogUtils.guestDialog import org.ole.planet.myplanet.utilities.TimeUtils +import java.net.HttpURLConnection +import java.net.URL import java.util.Date class BellDashboardFragment : BaseDashboardFragment() { @@ -58,7 +61,9 @@ class BellDashboardFragment : BaseDashboardFragment() { super.onViewCreated(view, savedInstanceState) fragmentHomeBellBinding.cardProfileBell.txtDate.text = TimeUtils.formatDate(Date().time, "") fragmentHomeBellBinding.cardProfileBell.txtCommunityName.text = model?.planetCode + setupNetworkStatusMonitoring() + (activity as DashboardActivity?)?.supportActionBar?.hide() showBadges() checkPendingSurveys() @@ -75,39 +80,49 @@ class BellDashboardFragment : BaseDashboardFragment() { } } - private suspend fun updateNetworkIndicator(status: NetworkStatus) { - if (!isAdded) return - val context = context ?: return + private suspend fun updateNetworkIndicator(status: NetworkStatus) = coroutineScope { + val serverUrl = settings?.getString("serverURL", "") + val lastReachableServer = settings?.getString("last_reachable_server", "") + val defaultServerUrls = listOf( + "https://example.com/server1", + "https://example.com/server2", + "https://example.com/server3", + "https://example.com/server4", + "https://example.com/server5", + "https://example.com/server6", + "https://example.com/server7", + serverUrl, + "https://example.com/server8", + "https://example.com/server9" + ).filterNotNull() // Filter out null values if serverUrl is null - when (status) { - is NetworkStatus.Disconnected -> { - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(context, R.color.md_red_700) - } - is NetworkStatus.Connecting -> { - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(context, R.color.md_yellow_600) - - val serverUrl = settings?.getString("serverURL", "") - if (!serverUrl.isNullOrEmpty()) { - try { - val canReachServer = viewModel.checkServerConnection(serverUrl) - if (isAdded && view?.isAttachedToWindow == true) { - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(context, if (canReachServer) R.color.green else R.color.md_yellow_600) - } - } catch (e: Exception) { - e.printStackTrace() - if (isAdded && view?.isAttachedToWindow == true) { - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(context, R.color.md_yellow_600) - } + val serverUrls = listOfNotNull(lastReachableServer) + defaultServerUrls.filter { it != lastReachableServer } + + if (!isAdded) return@coroutineScope + val context = context ?: return@coroutineScope + + // Set initial color to yellow as we're checking servers + fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = + ContextCompat.getColor(context, R.color.md_yellow_600) + + val reachableServerFound = serverUrls.map { url -> + async { + viewModel.checkServerConnection(url).also { canReachServer -> + if (canReachServer) { + editor?.putString("last_reachable_server", url)?.apply() } } } - is NetworkStatus.Connected -> { - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = ContextCompat.getColor(context, R.color.green) + }.awaitAll().any { it } + + if (isAdded && view?.isAttachedToWindow == true) { + val colorRes = when { + reachableServerFound -> R.color.green + status is NetworkStatus.Disconnected -> R.color.md_red_700 + else -> R.color.md_yellow_600 } + fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = + ContextCompat.getColor(context, colorRes) } } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt index fb830a081d..4404bfdedf 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt @@ -32,7 +32,7 @@ class BellDashboardViewModel : ViewModel() { } } - suspend fun checkServerConnection(serverUrl: String): Boolean { + suspend fun checkServerConnection(serverUrl: String?): Boolean { return withContext(Dispatchers.IO) { isServerReachable(serverUrl) } From 01590a4ccfbee7b8883f2d170288d1833935922d Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Wed, 7 Aug 2024 13:24:43 +0300 Subject: [PATCH 2/6] fix tag --- .../planet/myplanet/ui/dashboard/BellDashboardFragment.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt index 6cf9618a6c..139a75a093 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt @@ -94,8 +94,9 @@ class BellDashboardFragment : BaseDashboardFragment() { serverUrl, "https://example.com/server8", "https://example.com/server9" - ).filterNotNull() // Filter out null values if serverUrl is null + ).filterNotNull() // Filter out null values + // Reorder servers to check last reachable server first val serverUrls = listOfNotNull(lastReachableServer) + defaultServerUrls.filter { it != lastReachableServer } if (!isAdded) return@coroutineScope @@ -107,14 +108,17 @@ class BellDashboardFragment : BaseDashboardFragment() { val reachableServerFound = serverUrls.map { url -> async { + Log.d("NetworkIndicator", "Checking connection to: $url") viewModel.checkServerConnection(url).also { canReachServer -> if (canReachServer) { + Log.d("NetworkIndicator", "Server is reachable: $url") editor?.putString("last_reachable_server", url)?.apply() } } } }.awaitAll().any { it } + // Update UI based on the result of the reachability checks if (isAdded && view?.isAttachedToWindow == true) { val colorRes = when { reachableServerFound -> R.color.green From 0f4ef68b2d6f28298ee1e12c2382291377449ba9 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 26 Nov 2024 19:04:53 +0300 Subject: [PATCH 3/6] attempt to sync to clone server --- .../ole/planet/myplanet/MainApplication.kt | 10 +- .../ui/dashboard/BellDashboardFragment.kt | 126 ++++++++++++------ .../ui/sync/DashboardElementActivity.kt | 3 + .../planet/myplanet/ui/sync/LoginActivity.kt | 4 +- .../ui/sync/ProcessUserDataActivity.kt | 103 +++++++------- .../planet/myplanet/ui/sync/SyncActivity.kt | 7 +- 6 files changed, 150 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt b/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt index ced3d56e8c..8b622e538c 100644 --- a/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt +++ b/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt @@ -121,7 +121,15 @@ class MainApplication : Application(), Application.ActivityLifecycleCallbacks { suspend fun isServerReachable(urlString: String?): Boolean { return try { - val url = URL(urlString) + if (urlString.isNullOrBlank()) return false + + val formattedUrl = if (!urlString.startsWith("http://") && !urlString.startsWith("https://")) { + "http://$urlString" + } else { + urlString + } + + val url = URL(formattedUrl) val connection = withContext(Dispatchers.IO) { url.openConnection() } as HttpURLConnection diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt index 9a19d27d13..770bee4cb0 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt @@ -1,7 +1,6 @@ package org.ole.planet.myplanet.ui.dashboard import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -18,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView import io.realm.Case import io.realm.Realm import kotlinx.coroutines.* +import kotlinx.coroutines.flow.filter import org.ole.planet.myplanet.R import org.ole.planet.myplanet.databinding.FragmentHomeBellBinding import org.ole.planet.myplanet.model.RealmCertification @@ -34,16 +34,19 @@ import org.ole.planet.myplanet.ui.mylife.LifeFragment import org.ole.planet.myplanet.ui.resources.ResourcesFragment import org.ole.planet.myplanet.ui.submission.AdapterMySubmission import org.ole.planet.myplanet.ui.submission.MySubmissionFragment +import org.ole.planet.myplanet.ui.sync.ProcessUserDataActivity import org.ole.planet.myplanet.ui.team.TeamFragment import org.ole.planet.myplanet.utilities.DialogUtils.guestDialog import org.ole.planet.myplanet.utilities.TimeUtils -import java.net.HttpURLConnection -import java.net.URL import java.util.Date +import java.util.concurrent.ConcurrentHashMap class BellDashboardFragment : BaseDashboardFragment() { private lateinit var fragmentHomeBellBinding: FragmentHomeBellBinding private var networkStatusJob: Job? = null + private val serverCheckCache = ConcurrentHashMap() + private val cacheDuration = 5 * 60 * 1000L + private val serverCheckTimeout = 3000L private val viewModel: BellDashboardViewModel by viewModels() var user: RealmUserModel? = null @@ -69,64 +72,103 @@ class BellDashboardFragment : BaseDashboardFragment() { checkPendingSurveys() } + private fun getOptimizedServerUrls(): List { + val primaryServer = settings?.getString("serverURL", "") + val lastReachableServer = settings?.getString("last_reachable_server", "") + + return listOfNotNull( + lastReachableServer, + primaryServer + ) + listOf( + "http://example.com/server1", + "http://35.231.161.29", + "https://example.com/server3", + "http://example.com/server4", + "https://example.com/server5", + "https://example.com/server6", + "http://example.com/server7", + "https://example.com/server8", + "https://example.com/server9" + ).filterNot { it == lastReachableServer || it == primaryServer } + } + + private suspend fun checkServerWithCache(url: String): Boolean { + val currentTime = System.currentTimeMillis() + return serverCheckCache[url]?.let { lastChecked -> + if (currentTime - lastChecked < cacheDuration) { + true + } else { + viewModel.checkServerConnection(url).also { + serverCheckCache[url] = currentTime + } + } + } ?: viewModel.checkServerConnection(url).also { + serverCheckCache[url] = currentTime + } + } + private fun setupNetworkStatusMonitoring() { networkStatusJob?.cancel() - networkStatusJob = viewLifecycleOwner.lifecycleScope.launch { + networkStatusJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) { + var lastEmittedStatus: NetworkStatus? = null viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.networkStatus.collect { status -> - updateNetworkIndicator(status) - } + viewModel.networkStatus + .filter { status -> + status != lastEmittedStatus.also { + lastEmittedStatus = status + } + } + .collect { status -> + withContext(Dispatchers.Main) { + updateNetworkIndicator(status) + } + } } } } private suspend fun updateNetworkIndicator(status: NetworkStatus) = coroutineScope { - val serverUrl = settings?.getString("serverURL", "") - val lastReachableServer = settings?.getString("last_reachable_server", "") - val defaultServerUrls = listOf( - "https://example.com/server1", - "https://example.com/server2", - "https://example.com/server3", - "https://example.com/server4", - "https://example.com/server5", - "https://example.com/server6", - "https://example.com/server7", - serverUrl, - "https://example.com/server8", - "https://example.com/server9" - ).filterNotNull() // Filter out null values + // Validate fragment and context + if (!isAdded || context == null) return@coroutineScope - // Reorder servers to check last reachable server first - val serverUrls = listOfNotNull(lastReachableServer) + defaultServerUrls.filter { it != lastReachableServer } + // Get optimized server URLs + val serverUrls = getOptimizedServerUrls() - if (!isAdded) return@coroutineScope - val context = context ?: return@coroutineScope - - // Set initial color to yellow as we're checking servers + // Set initial color to yellow while checking fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(context, R.color.md_yellow_600) - - val reachableServerFound = serverUrls.map { url -> - async { - Log.d("NetworkIndicator", "Checking connection to: $url") - viewModel.checkServerConnection(url).also { canReachServer -> - if (canReachServer) { - Log.d("NetworkIndicator", "Server is reachable: $url") - editor?.putString("last_reachable_server", url)?.apply() - } + ContextCompat.getColor(requireContext(), R.color.md_yellow_600) + + // Find reachable server with timeout + val reachableServer = try { + withTimeout(serverCheckTimeout) { + serverUrls.firstNotNullOfOrNull { url -> + async { + if (checkServerWithCache(url)) url else null + }.await() } } - }.awaitAll().any { it } + } catch (e: TimeoutCancellationException) { + e.printStackTrace() + null + } - // Update UI based on the result of the reachability checks + // Update last reachable server in settings + reachableServer?.let { + editor?.putString("last_reachable_server", it)?.apply() + } + + // Determine color based on server reachability if (isAdded && view?.isAttachedToWindow == true) { val colorRes = when { - reachableServerFound -> R.color.green + reachableServer != null -> { + val processedUrl = ProcessUserDataActivity.setUrlParts(reachableServer, settings?.getString("serverPin", "") ?: "") + if (processedUrl.isNotEmpty()) R.color.green else R.color.md_red_700 + } status is NetworkStatus.Disconnected -> R.color.md_red_700 else -> R.color.md_yellow_600 } - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(context, colorRes) + + fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = ContextCompat.getColor(requireContext(), colorRes) } } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/sync/DashboardElementActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/sync/DashboardElementActivity.kt index f4e213c23d..ddb19452c2 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/sync/DashboardElementActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/sync/DashboardElementActivity.kt @@ -10,6 +10,7 @@ import android.os.Bundle import android.os.Handler import android.os.Looper import android.provider.Settings +import android.util.Log import android.view.Menu import android.view.MenuItem import android.widget.Toast @@ -122,6 +123,8 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack fun logSyncInSharedPrefs() { lifecycleScope.launch { + Log.d("DashboardActivity 1", "Syncing: ${Utilities.getUrl()}") + Log.d("DashboardActivity 2", "Syncing: ${isServerReachable(Utilities.getUrl())}") if (isServerReachable(Utilities.getUrl())) { startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt index 1432276248..37ee132f47 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt @@ -415,7 +415,7 @@ class LoginActivity : SyncActivity(), TeamListAdapter.OnItemClickListener { val editor = settings.edit() editor.putString("loginUserName", name) editor.putString("loginUserPassword", password) - val isLoggedIn = authenticateUser(settings, name, password, false) + val isLoggedIn = authenticateUser(name, password, false) if (isLoggedIn) { Toast.makeText(applicationContext, getString(R.string.thank_you), Toast.LENGTH_SHORT).show() onLogin() @@ -429,7 +429,7 @@ class LoginActivity : SyncActivity(), TeamListAdapter.OnItemClickListener { override fun onSyncComplete() { customProgressDialog?.dismiss() - val log = authenticateUser(settings, name, password, true) + val log = authenticateUser(name, password, true) if (log) { Toast.makeText(applicationContext, getString(R.string.thank_you), Toast.LENGTH_SHORT).show() onLogin() diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/sync/ProcessUserDataActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/sync/ProcessUserDataActivity.kt index 6243b8c66c..64d00a3d33 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/sync/ProcessUserDataActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/sync/ProcessUserDataActivity.kt @@ -21,12 +21,7 @@ import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.ContextCompat -import androidx.lifecycle.lifecycleScope import com.google.android.material.textfield.TextInputLayout -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import org.ole.planet.myplanet.MainApplication.Companion.context import org.ole.planet.myplanet.R import org.ole.planet.myplanet.base.PermissionActivity @@ -43,7 +38,6 @@ import org.ole.planet.myplanet.utilities.FileUtils.installApk import kotlin.math.roundToInt abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { - lateinit var settings: SharedPreferences var customProgressDialog: DialogUtils.CustomProgressDialog? = null @JvmField @@ -130,36 +124,58 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { } } - fun setUrlParts(url: String, password: String): String { - val editor = settings.edit() - val uri = Uri.parse(url) - var couchdbURL: String - val urlUser: String - val urlPwd: String - if (url.contains("@")) { - val userinfo = getUserInfo(uri) - urlUser = userinfo[0] - urlPwd = userinfo[1] - couchdbURL = url - } else if (TextUtils.isEmpty(password)) { - showAlert(this, "", getString(R.string.pin_is_required)) - return "" - } else { - urlUser = "satellite" - urlPwd = password - couchdbURL = uri.scheme + "://" + urlUser + ":" + urlPwd + "@" + uri.host + ":" + if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port + companion object { + lateinit var settings: SharedPreferences + + fun setUrlParts(url: String, password: String): String { + val editor = settings.edit() + val uri = Uri.parse(url) + var couchdbURL: String + val urlUser: String + val urlPwd: String + if (url.contains("@")) { + val userinfo = getUserInfo(uri) + urlUser = userinfo[0] + urlPwd = userinfo[1] + couchdbURL = url + } else if (TextUtils.isEmpty(password)) { + showAlert(context, "", context.getString(R.string.pin_is_required)) + return "" + } else { + urlUser = "satellite" + urlPwd = password + couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else "${uri.port}"}" + } + editor.putString("serverPin", password) + saveUrlScheme(editor, uri, url, couchdbURL) + editor.putString("url_user", urlUser) + editor.putString("url_pwd", urlPwd) + editor.putString("url_Scheme", uri.scheme) + editor.putString("url_Host", uri.host) + editor.apply() + if (!couchdbURL.endsWith("db")) { + couchdbURL += "/db" + } + return couchdbURL } - editor.putString("serverPin", password) - saveUrlScheme(editor, uri, url, couchdbURL) - editor.putString("url_user", urlUser) - editor.putString("url_pwd", urlPwd) - editor.putString("url_Scheme", uri.scheme) - editor.putString("url_Host", uri.host) - editor.apply() - if (!couchdbURL.endsWith("db")) { - couchdbURL += "/db" + + fun getUserInfo(uri: Uri): Array { + val ar = arrayOf("", "") + val info = uri.userInfo?.split(":".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray() + if ((info?.size ?: 0) > 1) { + ar[0] = "${info?.get(0)}" + ar[1] = "${info?.get(1)}" + } + return ar + } + + fun saveUrlScheme(editor: SharedPreferences.Editor, uri: Uri, url: String?, couchdbURL: String?) { + editor.putString("url_Scheme", uri.scheme) + editor.putString("url_Host", uri.host) + editor.putInt("url_Port", if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port) + editor.putString("serverURL", url) + editor.putString("couchdbURL", couchdbURL) } - return couchdbURL } fun isUrlValid(url: String): Boolean { @@ -208,7 +224,6 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { } fun saveUserInfoPref(settings: SharedPreferences, password: String?, user: RealmUserModel) { - this.settings = settings val editor = settings.edit() editor.putString("userId", user.id) editor.putString("name", user.name) @@ -229,22 +244,4 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { val alert11 = builder1.create() alert11.show() } - - private fun getUserInfo(uri: Uri): Array { - val ar = arrayOf("", "") - val info = uri.userInfo?.split(":".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray() - if ((info?.size ?: 0) > 1) { - ar[0] = "${info?.get(0)}" - ar[1] = "${info?.get(1)}" - } - return ar - } - - private fun saveUrlScheme(editor: SharedPreferences.Editor, uri: Uri, url: String?, couchdbURL: String?) { - editor.putString("url_Scheme", uri.scheme) - editor.putString("url_Host", uri.host) - editor.putInt("url_Port", if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port) - editor.putString("serverURL", url) - editor.putString("couchdbURL", couchdbURL) - } } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/sync/SyncActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/sync/SyncActivity.kt index 10b8f3f4db..a79eaab087 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/sync/SyncActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/sync/SyncActivity.kt @@ -263,11 +263,8 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers editor.apply() } - fun authenticateUser(settings: SharedPreferences?, username: String?, password: String?, isManagerMode: Boolean): Boolean { + fun authenticateUser(username: String?, password: String?, isManagerMode: Boolean): Boolean { return try { - if (settings != null) { - this.settings = settings - } if (mRealm.isEmpty) { alertDialogOkay(getString(R.string.server_not_configured_properly_connect_this_device_with_planet_server)) false @@ -839,7 +836,7 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers .setTitle(R.string.please_enter_your_password) .setPositiveButton(R.string.login) { _: DialogInterface?, _: Int -> val password = "${layoutChildLoginBinding.etChildPassword.text}" - if (authenticateUser(settings, userModel.name, password, false)) { + if (authenticateUser(userModel.name, password, false)) { Toast.makeText(applicationContext, getString(R.string.thank_you), Toast.LENGTH_SHORT).show() onLogin() } else { From 7a29770dd1469f8366f5bbdc488b48aa27bb1db3 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 26 Nov 2024 21:23:03 +0300 Subject: [PATCH 4/6] fix active url search --- .../ui/dashboard/BellDashboardFragment.kt | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt index 770bee4cb0..0720336144 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt @@ -1,6 +1,7 @@ package org.ole.planet.myplanet.ui.dashboard import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -76,10 +77,8 @@ class BellDashboardFragment : BaseDashboardFragment() { val primaryServer = settings?.getString("serverURL", "") val lastReachableServer = settings?.getString("last_reachable_server", "") - return listOfNotNull( - lastReachableServer, - primaryServer - ) + listOf( + // Default server list + val defaultServers = listOf( "http://example.com/server1", "http://35.231.161.29", "https://example.com/server3", @@ -89,7 +88,27 @@ class BellDashboardFragment : BaseDashboardFragment() { "http://example.com/server7", "https://example.com/server8", "https://example.com/server9" - ).filterNot { it == lastReachableServer || it == primaryServer } + ) + + // Create a prioritized list + return buildList { + // First, try the last reachable server if it's different from primary + if (lastReachableServer != null && lastReachableServer != primaryServer) { + add(lastReachableServer) + } + + // Then add the primary server + if (primaryServer != null) { + add(primaryServer) + } + + // Add remaining default servers, excluding already added servers + addAll( + defaultServers.filterNot { + it == lastReachableServer || it == primaryServer + } + ) + } } private suspend fun checkServerWithCache(url: String): Boolean { @@ -162,6 +181,7 @@ class BellDashboardFragment : BaseDashboardFragment() { val colorRes = when { reachableServer != null -> { val processedUrl = ProcessUserDataActivity.setUrlParts(reachableServer, settings?.getString("serverPin", "") ?: "") + Log.d("BellDashboardFragment", "Server reachable: $processedUrl") if (processedUrl.isNotEmpty()) R.color.green else R.color.md_red_700 } status is NetworkStatus.Disconnected -> R.color.md_red_700 From b47845cdf9f4457dea1f1a3cf9536f6f44f9570b Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Wed, 27 Nov 2024 20:03:08 +0300 Subject: [PATCH 5/6] check url for available server --- .../ui/dashboard/BellDashboardFragment.kt | 74 +++++++++---------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt index 0720336144..f2809d34b6 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardFragment.kt @@ -19,6 +19,7 @@ import io.realm.Case import io.realm.Realm import kotlinx.coroutines.* import kotlinx.coroutines.flow.filter +import org.ole.planet.myplanet.BuildConfig import org.ole.planet.myplanet.R import org.ole.planet.myplanet.databinding.FragmentHomeBellBinding import org.ole.planet.myplanet.model.RealmCertification @@ -77,37 +78,33 @@ class BellDashboardFragment : BaseDashboardFragment() { val primaryServer = settings?.getString("serverURL", "") val lastReachableServer = settings?.getString("last_reachable_server", "") - // Default server list - val defaultServers = listOf( - "http://example.com/server1", - "http://35.231.161.29", - "https://example.com/server3", - "http://example.com/server4", - "https://example.com/server5", - "https://example.com/server6", - "http://example.com/server7", - "https://example.com/server8", - "https://example.com/server9" + val serverMappings = mapOf( + "http://${BuildConfig.PLANET_URIUR_URL}" to "http://35.231.161.29", + "http://192.168.1.202" to "http://34.35.29.147", + "https://${BuildConfig.PLANET_GUATEMALA_URL}" to "http://guatemala.com/cloudserver", + "http://${BuildConfig.PLANET_XELA_URL}" to "http://xela.com/cloudserver", + "http://${BuildConfig.PLANET_SANPABLO_URL}" to "http://sanpablo.com/cloudserver", + "http://${BuildConfig.PLANET_EMBAKASI_URL}" to "http://embakasi.com/cloudserver", + "https://${BuildConfig.PLANET_VI_URL}" to "http://vi.com/cloudserver" ) - // Create a prioritized list return buildList { - // First, try the last reachable server if it's different from primary + // Add last reachable server if different from primary if (lastReachableServer != null && lastReachableServer != primaryServer) { add(lastReachableServer) } - // Then add the primary server + // Add primary server if (primaryServer != null) { add(primaryServer) } - // Add remaining default servers, excluding already added servers - addAll( - defaultServers.filterNot { - it == lastReachableServer || it == primaryServer + // Add ONLY the mapped fallback server for the primary server + serverMappings[primaryServer]?.let { fallbackServer -> + if (fallbackServer !in this) { + add(fallbackServer) } - ) + } } } @@ -131,52 +128,53 @@ class BellDashboardFragment : BaseDashboardFragment() { networkStatusJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) { var lastEmittedStatus: NetworkStatus? = null viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.networkStatus - .filter { status -> - status != lastEmittedStatus.also { - lastEmittedStatus = status - } + viewModel.networkStatus.filter { status -> + status != lastEmittedStatus.also { + lastEmittedStatus = status } - .collect { status -> - withContext(Dispatchers.Main) { - updateNetworkIndicator(status) - } + }.collect { status -> + withContext(Dispatchers.Main) { + updateNetworkIndicator(status) } + } } } } private suspend fun updateNetworkIndicator(status: NetworkStatus) = coroutineScope { - // Validate fragment and context if (!isAdded || context == null) return@coroutineScope - // Get optimized server URLs val serverUrls = getOptimizedServerUrls() - // Set initial color to yellow while checking - fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = - ContextCompat.getColor(requireContext(), R.color.md_yellow_600) + // Log the full list of servers being attempted + Log.d("NetworkIndicator", "Attempting to connect to servers in order: $serverUrls") + + fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = ContextCompat.getColor(requireContext(), R.color.md_yellow_600) - // Find reachable server with timeout val reachableServer = try { withTimeout(serverCheckTimeout) { serverUrls.firstNotNullOfOrNull { url -> async { - if (checkServerWithCache(url)) url else null + Log.d("NetworkIndicator", "Checking server connection to: $url") + if (checkServerWithCache(url)) { + Log.d("NetworkIndicator", "Server successful: $url") + url + } else { + Log.d("NetworkIndicator", "Server failed: $url") + null + } }.await() } } } catch (e: TimeoutCancellationException) { - e.printStackTrace() + Log.e("NetworkIndicator", "Server connection timeout", e) null } - // Update last reachable server in settings reachableServer?.let { editor?.putString("last_reachable_server", it)?.apply() } - // Determine color based on server reachability if (isAdded && view?.isAttachedToWindow == true) { val colorRes = when { reachableServer != null -> { From f8f093f630fd0f8043c88f1d4015fa0733681530 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Thu, 5 Dec 2024 12:44:48 +0300 Subject: [PATCH 6/6] resolve build fail --- app/src/main/java/org/ole/planet/myplanet/MainApplication.kt | 2 +- .../ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt b/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt index 45d77600e1..bbd764997f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt +++ b/app/src/main/java/org/ole/planet/myplanet/MainApplication.kt @@ -119,7 +119,7 @@ class MainApplication : Application(), Application.ActivityLifecycleCallbacks { applyThemeMode(themeMode) } - suspend fun isServerReachable(urlString: String?): Boolean { + suspend fun isServerReachable(urlString: String): Boolean { return try { if (urlString.isBlank()) return false diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt index 4404bfdedf..fb830a081d 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BellDashboardViewModel.kt @@ -32,7 +32,7 @@ class BellDashboardViewModel : ViewModel() { } } - suspend fun checkServerConnection(serverUrl: String?): Boolean { + suspend fun checkServerConnection(serverUrl: String): Boolean { return withContext(Dispatchers.IO) { isServerReachable(serverUrl) }