From 8fc81d41c75f7575bd33ffb01776c158915d7195 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Wed, 4 Dec 2024 18:51:22 +0300 Subject: [PATCH 01/14] check available url --- .../planet/myplanet/datamanager/Service.kt | 267 +++++++++++++----- .../planet/myplanet/ui/sync/SyncActivity.kt | 3 + 2 files changed, 205 insertions(+), 65 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index 18a2b916af..f82a6b614b 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -6,18 +6,23 @@ import android.content.DialogInterface import android.content.SharedPreferences import android.net.Uri import android.text.TextUtils +import android.util.Log import com.google.gson.Gson import com.google.gson.JsonObject import io.realm.Realm import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.async import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import okhttp3.ResponseBody +import org.ole.planet.myplanet.BuildConfig import org.ole.planet.myplanet.MainApplication +import org.ole.planet.myplanet.MainApplication.Companion.applicationScope import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable import org.ole.planet.myplanet.R import org.ole.planet.myplanet.callback.SuccessListener @@ -319,86 +324,218 @@ class Service(private val context: Context) { } fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) { - val customProgressDialog = CustomProgressDialog(context).apply { - setText(context.getString(R.string.check_apk_version)) - show() + // Create a list of URLs to try, starting with the original URL + val urlsToTry = mutableListOf(url) + + 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" + ) + + // Add alternative URL from serverMappings if available + serverMappings[url]?.let { alternativeUrl -> + urlsToTry.add(alternativeUrl) } - retrofitInterface?.getConfiguration("$url/versions")?.enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful) { - response.body()?.let { jsonObject -> - val currentVersion = "${context.resources.getText(R.string.app_version)}" - val minApkVersion = jsonObject.get("minapk").asString - if (isVersionAllowed(currentVersion, minApkVersion)) { - customProgressDialog.setText(context.getString(R.string.checking_server)) - val uri = Uri.parse(url) - val couchdbURL: String - if (url.contains("@")) { - getUserInfo(uri) - couchdbURL = url - } else { - val urlUser = "satellite" - couchdbURL = "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" - } - retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful) { - val jsonObjectResponse = response.body() - val rows = jsonObjectResponse?.getAsJsonArray("rows") - if (rows != null && rows.size() > 0) { - val firstRow = rows.get(0).asJsonObject - val id = firstRow.getAsJsonPrimitive("id").asString - val doc = firstRow.getAsJsonObject("doc") - val code = doc.getAsJsonPrimitive("code").asString - listener?.onConfigurationIdReceived(id, code) - activity.setSyncFailed(false) + // Use coroutine scope to perform concurrent URL checks + applicationScope.launch { + val customProgressDialog = withContext(Dispatchers.Main) { + CustomProgressDialog(context).apply { + setText(context.getString(R.string.check_apk_version)) + show() + } + } + + try { + // Use withContext(Dispatchers.IO) for network operations + val result = withContext(Dispatchers.IO) { + // Create a list of deferred jobs for concurrent network calls + val deferredResults = urlsToTry.map { currentUrl -> + async { + try { + Log.d("Service", "Checking URL: $currentUrl") + // Check versions concurrently + val versionsResponse = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() + + if (versionsResponse?.isSuccessful == true) { + val jsonObject = versionsResponse.body() + val currentVersion = "${context.resources.getText(R.string.app_version)}" + val minApkVersion = jsonObject?.get("minapk")?.asString + Log.d("okuro", "first config check is successful") + + // Version check + if (minApkVersion != null && isVersionAllowed(currentVersion, minApkVersion)) { + // Perform configuration check for this URL + val uri = Uri.parse(currentUrl) + val couchdbURL = if (currentUrl.contains("@")) { + getUserInfo(uri) + currentUrl } else { - activity.setSyncFailed(true) - showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false) + val urlUser = "satellite" + "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" + } + withContext(Dispatchers.Main) { + customProgressDialog.setText(context.getString(R.string.checking_server)) + } + val configResponse = retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").execute() + + if (configResponse.isSuccessful) { + Log.d("okuro", "second config check is successful") + val rows = configResponse.body()?.getAsJsonArray("rows") + if (rows != null && rows.size() > 0) { + val firstRow = rows.get(0).asJsonObject + val id = firstRow.getAsJsonPrimitive("id").asString + val doc = firstRow.getAsJsonObject("doc") + val code = doc.getAsJsonPrimitive("code").asString + return@async UrlCheckResult.Success(id, code, currentUrl) + } } - } else { - activity.setSyncFailed(true) - showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false) - } - customProgressDialog.dismiss() - } - - override fun onFailure(call: Call, t: Throwable) { - activity.setSyncFailed(true) - customProgressDialog.dismiss() - if (getUrl(couchdbURL) == context.getString(R.string.http_protocol)) { - showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) - } else if (getUrl(couchdbURL) == context.getString(R.string.https_protocol)) { - showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false) } } - }) - } else { - activity.setSyncFailed(true) - customProgressDialog.dismiss() - showAlertDialog(context.getString(R.string.below_min_apk), true) + return@async UrlCheckResult.Failure(currentUrl) + } catch (e: Exception) { + e.printStackTrace() + return@async UrlCheckResult.Failure(currentUrl) + } } } - } else { - activity.setSyncFailed(true) - customProgressDialog.dismiss() - showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) + + // Wait for the first successful result + deferredResults.awaitFirst { it is UrlCheckResult.Success } } - } - override fun onFailure(call: Call, t: Throwable) { + // Handle the result + when (result) { + is UrlCheckResult.Success -> { + listener?.onConfigurationIdReceived(result.id, result.code) + activity.setSyncFailed(false) + Log.d("Service", "Successfully connected to URL: ${result.url}") + } + is UrlCheckResult.Failure -> { + activity.setSyncFailed(true) + val errorMessage = when (extractProtocol(url)) { + context.getString(R.string.http_protocol) -> context.getString(R.string.device_couldn_t_reach_local_server) + context.getString(R.string.https_protocol) -> context.getString(R.string.device_couldn_t_reach_nation_server) + else -> context.getString(R.string.device_couldn_t_reach_local_server) + } + showAlertDialog(errorMessage, false) + } + } + } catch (e: Exception) { + e.printStackTrace() activity.setSyncFailed(true) + showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) + } finally { customProgressDialog.dismiss() - if (extractProtocol(url) == context.getString(R.string.http_protocol)) { - showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) - } else if (extractProtocol(url) == context.getString(R.string.https_protocol)) { - showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false) - } } - }) + } + } + + // Sealed class to represent URL check results + sealed class UrlCheckResult { + data class Success(val id: String, val code: String, val url: String) : UrlCheckResult() + data class Failure(val url: String) : UrlCheckResult() } + // Extension function to await the first successful result + private suspend fun List>.awaitFirst(predicate: (T) -> Boolean): T { + return firstOrNull { job -> + try { + val result = job.await() + predicate(result) + } catch (e: Exception) { + e.printStackTrace() + false + } + }?.await() ?: throw NoSuchElementException("No matching result found") + } + +// fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) { +// val customProgressDialog = CustomProgressDialog(context).apply { +// setText(context.getString(R.string.check_apk_version)) +// show() +// } +// +// retrofitInterface?.getConfiguration("$url/versions")?.enqueue(object : Callback { +// override fun onResponse(call: Call, response: Response) { +// if (response.isSuccessful) { +// response.body()?.let { jsonObject -> +// val currentVersion = "${context.resources.getText(R.string.app_version)}" +// val minApkVersion = jsonObject.get("minapk").asString +// if (isVersionAllowed(currentVersion, minApkVersion)) { +// customProgressDialog.setText(context.getString(R.string.checking_server)) +// val uri = Uri.parse(url) +// val couchdbURL: String +// if (url.contains("@")) { +// getUserInfo(uri) +// couchdbURL = url +// } else { +// val urlUser = "satellite" +// couchdbURL = "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" +// } +// retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").enqueue(object : Callback { +// override fun onResponse(call: Call, response: Response) { +// if (response.isSuccessful) { +// val jsonObjectResponse = response.body() +// val rows = jsonObjectResponse?.getAsJsonArray("rows") +// if (rows != null && rows.size() > 0) { +// val firstRow = rows.get(0).asJsonObject +// val id = firstRow.getAsJsonPrimitive("id").asString +// val doc = firstRow.getAsJsonObject("doc") +// val code = doc.getAsJsonPrimitive("code").asString +// listener?.onConfigurationIdReceived(id, code) +// activity.setSyncFailed(false) +// } else { +// activity.setSyncFailed(true) +// showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false) +// } +// } else { +// activity.setSyncFailed(true) +// showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false) +// } +// customProgressDialog.dismiss() +// } +// +// override fun onFailure(call: Call, t: Throwable) { +// activity.setSyncFailed(true) +// customProgressDialog.dismiss() +// if (getUrl(couchdbURL) == context.getString(R.string.http_protocol)) { +// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) +// } else if (getUrl(couchdbURL) == context.getString(R.string.https_protocol)) { +// showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false) +// } +// } +// }) +// } else { +// activity.setSyncFailed(true) +// customProgressDialog.dismiss() +// showAlertDialog(context.getString(R.string.below_min_apk), true) +// } +// } +// } else { +// activity.setSyncFailed(true) +// customProgressDialog.dismiss() +// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) +// } +// } +// +// override fun onFailure(call: Call, t: Throwable) { +// activity.setSyncFailed(true) +// customProgressDialog.dismiss() +// if (extractProtocol(url) == context.getString(R.string.http_protocol)) { +// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) +// } else if (extractProtocol(url) == context.getString(R.string.https_protocol)) { +// showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false) +// } +// } +// }) +// } + private fun isVersionAllowed(currentVersion: String, minApkVersion: String): Boolean { return compareVersions(currentVersion, minApkVersion) >= 0 } 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 6f6efc9145..9b0e71375f 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 @@ -111,6 +111,8 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers } override fun onConfigurationIdReceived(id: String, code:String) { + Log.d("SyncActivity", "onConfigurationIdReceived: $id") + Log.d("SyncActivity", "onConfigurationIdReceived: $code") val savedId = settings.getString("configurationId", null) if (serverConfigAction == "sync") { if (savedId == null) { @@ -721,6 +723,7 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers } private fun continueSync(dialog: MaterialDialog) { + Log.d("SyncActivity", "continueSync: $processedUrl") processedUrl = saveConfigAndContinue(dialog) if (TextUtils.isEmpty(processedUrl)) return isSync = true From 6d3e7899df48f8119fb4932d6af74fb594e293ae Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Wed, 4 Dec 2024 19:55:56 +0300 Subject: [PATCH 02/14] save alternative urls used and process it --- .../planet/myplanet/datamanager/Service.kt | 5 ++- .../ui/sync/ProcessUserDataActivity.kt | 4 +- .../planet/myplanet/ui/sync/SyncActivity.kt | 37 ++++++++++++++++--- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index f82a6b614b..446ebc7d28 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -412,7 +412,8 @@ class Service(private val context: Context) { // Handle the result when (result) { is UrlCheckResult.Success -> { - listener?.onConfigurationIdReceived(result.id, result.code) + val isAlternativeUrl = result.url != url + listener?.onConfigurationIdReceived(result.id, result.code, result.url, isAlternativeUrl) activity.setSyncFailed(false) Log.d("Service", "Successfully connected to URL: ${result.url}") } @@ -607,6 +608,6 @@ class Service(private val context: Context) { } interface ConfigurationIdListener { - fun onConfigurationIdReceived(id: String, code: String) + fun onConfigurationIdReceived(id: String, code: String, url: String, isAlternativeUrl: Boolean) } } 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..239f52b842 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 @@ -147,7 +147,7 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { } 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 + 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) @@ -230,7 +230,7 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { alert11.show() } - private fun getUserInfo(uri: Uri): Array { + fun getUserInfo(uri: Uri): Array { val ar = arrayOf("", "") val info = uri.userInfo?.split(":".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray() if ((info?.size ?: 0) > 1) { 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 9b0e71375f..5e7f17d119 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 @@ -3,6 +3,7 @@ package org.ole.planet.myplanet.ui.sync import android.Manifest import android.content.* import android.graphics.drawable.AnimationDrawable +import android.net.Uri import android.os.Build import android.os.Bundle import android.text.* @@ -110,17 +111,19 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers processedUrl = Utilities.getUrl() } - override fun onConfigurationIdReceived(id: String, code:String) { + override fun onConfigurationIdReceived(id: String, code: String, url: String, isAlternativeUrl: Boolean) { Log.d("SyncActivity", "onConfigurationIdReceived: $id") Log.d("SyncActivity", "onConfigurationIdReceived: $code") + Log.d("SyncActivity", "onConfigurationIdReceived: $url") + Log.d("SyncActivity", "onConfigurationIdReceived: $isAlternativeUrl") val savedId = settings.getString("configurationId", null) if (serverConfigAction == "sync") { if (savedId == null) { editor.putString("configurationId", id).apply() editor.putString("communityName", code).apply() - currentDialog?.let { continueSync(it) } + currentDialog?.let { continueSync(it, url, isAlternativeUrl) } } else if (id == savedId) { - currentDialog?.let { continueSync(it) } + currentDialog?.let { continueSync(it, url, isAlternativeUrl) } } else { clearDataDialog(getString(R.string.you_want_to_connect_to_a_different_server), false) } @@ -722,9 +725,33 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers return modifiedUrl } - private fun continueSync(dialog: MaterialDialog) { + private fun continueSync(dialog: MaterialDialog, url: String, isAlternativeUrl: Boolean) { + if (isAlternativeUrl) { + val password = "${(dialog.customView?.findViewById(R.id.input_server_Password) as EditText).text}" + 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 { + 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("alternativeUrl", url).apply() + editor.putString("processedAlternativeUrl", couchdbURL).apply() + editor.putBoolean("isAlternativeUrl", true).apply() + + processedUrl = couchdbURL + } else { + processedUrl = saveConfigAndContinue(dialog) + } Log.d("SyncActivity", "continueSync: $processedUrl") - processedUrl = saveConfigAndContinue(dialog) + if (TextUtils.isEmpty(processedUrl)) return isSync = true if (checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) && settings.getBoolean("firstRun", true)) { From 36b6983a199e8e041428c48c1860260349cea719 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Wed, 4 Dec 2024 21:23:58 +0300 Subject: [PATCH 03/14] sync to cloud url --- .../planet/myplanet/datamanager/Service.kt | 16 ++++++-- .../planet/myplanet/service/SyncManager.kt | 2 + .../service/TransactionSyncManager.kt | 10 +++-- .../planet/myplanet/ui/sync/SyncActivity.kt | 21 +++++++++-- .../planet/myplanet/utilities/Utilities.kt | 37 ++++++++++++++----- 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index 446ebc7d28..3e76e47f30 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -106,18 +106,24 @@ class Service(private val context: Context) { } fun checkVersion(callback: CheckVersionCallback, settings: SharedPreferences) { - if (settings.getString("couchdbURL", "")?.isEmpty() == true) { - callback.onError(context.getString(R.string.config_not_available), true) - return + Log.d("Service", "checkVersion: ${Utilities.getUpdateUrl(settings)}") + if (!settings.getBoolean("isAlternativeUrl", false)){ + if (settings.getString("couchdbURL", "")?.isEmpty() == true) { + callback.onError(context.getString(R.string.config_not_available), true) + return + } } + retrofitInterface?.checkVersion(Utilities.getUpdateUrl(settings))?.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { preferences.edit().putInt("LastWifiID", NetworkUtils.getCurrentNetworkId(context)).apply() if (response.body() != null) { val p = response.body() preferences.edit().putString("versionDetail", Gson().toJson(response.body())).apply() + Log.d("Service", "checkVersion onResponse: ${response.body()}") retrofitInterface.getApkVersion(Utilities.getApkVersionUrl(settings)).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { + Log.d("Service", "getApkVersion onResponse: $response") val responses: String? try { responses = Gson().fromJson(response.body()?.string(), String::class.java) @@ -144,6 +150,7 @@ class Service(private val context: Context) { if (p != null) { if (currentVersion < p.minapkcode && apkVersion < p.minapkcode) { callback.onUpdateAvailable(p, true) + Log.d("Service", "checkVersion: Planet up to date") } else { callback.onError("Planet up to date", false) } @@ -168,12 +175,15 @@ class Service(private val context: Context) { } fun isPlanetAvailable(callback: PlanetAvailableListener?) { + Log.d("Service", "isPlanetAvailable: ${Utilities.getUpdateUrl(preferences)}") retrofitInterface?.isPlanetAvailable(Utilities.getUpdateUrl(preferences))?.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { if (callback != null && response.code() == 200) { callback.isAvailable() + Log.d("Service", "isAvailable: true") } else { callback?.notAvailable() + Log.d("Service", "isAvailable: false") } } diff --git a/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt b/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt index 4766a88e3f..fa7c645fb8 100644 --- a/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt +++ b/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt @@ -5,6 +5,7 @@ import android.content.SharedPreferences import android.net.wifi.SupplicantState import android.net.wifi.WifiManager import android.text.TextUtils +import android.util.Log import com.google.gson.Gson import com.google.gson.JsonArray import com.google.gson.JsonNull @@ -76,6 +77,7 @@ class SyncManager private constructor(private val context: Context) { private fun authenticateAndSync() { td = Thread { + Log.d("authenticateAndSync", "${TransactionSyncManager.authenticate()}") if (TransactionSyncManager.authenticate()) { startSync() } else { diff --git a/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt b/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt index b7284adc50..a61df45cde 100644 --- a/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt +++ b/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.SharedPreferences import android.text.TextUtils import android.util.Base64 +import android.util.Log import com.google.gson.Gson import com.google.gson.JsonArray import com.google.gson.JsonObject @@ -50,13 +51,16 @@ object TransactionSyncManager { fun authenticate(): Boolean { val apiInterface = client?.create(ApiInterface::class.java) try { - val response: Response? = apiInterface?.getDocuments(Utilities.header, Utilities.getUrl() + "/tablet_users/_all_docs")?.execute() + Log.d("TransactionSyncManager", "header: ${Utilities.header}, authenticate: ${Utilities.getUrl()}/tablet_users/_all_docs") + val response: Response? = apiInterface?.getDocuments(Utilities.header, "${Utilities.getUrl()}/tablet_users/_all_docs")?.execute() + Log.d("TransactionSyncManager", "response: $response") if (response != null) { return response.code() == 200 } } catch (e: IOException) { e.printStackTrace() } + return false } @@ -64,7 +68,7 @@ object TransactionSyncManager { listener.onSyncStarted() val userName = settings.getString("loginUserName", "") val password = settings.getString("loginUserPassword", "") - val header = "Basic " + Base64.encodeToString("$userName:$password".toByteArray(), Base64.NO_WRAP) + val header = "Basic ${Base64.encodeToString("$userName:$password".toByteArray(), Base64.NO_WRAP)}" mRealm.executeTransactionAsync({ realm: Realm -> val users = realm.where(RealmUserModel::class.java).isNotEmpty("_id").findAll() for (userModel in users) { @@ -76,7 +80,7 @@ object TransactionSyncManager { } private fun syncHealthData(userModel: RealmUserModel?, header: String) { - val table = "userdb-" + userModel?.planetCode?.let { Utilities.toHex(it) } + "-" + userModel?.name?.let { Utilities.toHex(it) } + val table = "userdb-${userModel?.planetCode?.let { Utilities.toHex(it) }}-${userModel?.name?.let { Utilities.toHex(it) }}" val apiInterface = client?.create(ApiInterface::class.java) val response: Response? try { 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 5e7f17d119..551fbd7533 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 @@ -191,7 +191,12 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers return withContext(Dispatchers.IO) { val apiInterface = client?.create(ApiInterface::class.java) try { - val response = apiInterface?.isPlanetAvailable("$processedUrl/_all_dbs")?.execute() + Log.d("SyncActivity", "isServerReachable: $processedUrl") + val response = if (settings.getBoolean("isAlternativeUrl", false)){ + apiInterface?.isPlanetAvailable("$processedUrl/db/_all_dbs")?.execute() + } else { + apiInterface?.isPlanetAvailable("$processedUrl/_all_dbs")?.execute() + } when { response?.isSuccessful == true -> { @@ -742,9 +747,15 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers 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("alternativeUrl", url).apply() - editor.putString("processedAlternativeUrl", couchdbURL).apply() - editor.putBoolean("isAlternativeUrl", true).apply() + editor.putString("serverPin", password) + editor.putString("url_user", urlUser) + editor.putString("url_pwd", urlPwd) + editor.putString("url_Scheme", uri.scheme) + editor.putString("url_Host", uri.host) + editor.putString("alternativeUrl", url) + editor.putString("processedAlternativeUrl", couchdbURL) + editor.putBoolean("isAlternativeUrl", true) + editor.apply() processedUrl = couchdbURL } else { @@ -760,11 +771,13 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers Service(this).isPlanetAvailable(object : PlanetAvailableListener { override fun isAvailable() { Service(context).checkVersion(this@SyncActivity, settings) + Log.d("SyncActivity", "isAvailable: true") } override fun notAvailable() { if (!isFinishing) { syncFailed = true showAlert(context, "Error", getString(R.string.planet_server_not_reachable)) + Log.d("SyncActivity", "isAvailable: false") } } }) diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt index 70d04a90da..fc3f5c7ea1 100644 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt @@ -104,6 +104,7 @@ object Utilities { imageView.setImageResource(R.drawable.ole_logo) } } + fun handleCheck(b: Boolean, i: Int, selectedItems: MutableList, list: List) { if (b) { selectedItems.add(list[i]) @@ -115,20 +116,25 @@ object Utilities { val header: String get() { val settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + Log.d("Basic auth", "${settings.getString("url_user", "")}:${ settings.getString("url_pwd", "") }") + return "Basic ${Base64.encodeToString(("${settings.getString("url_user", "")}:${ settings.getString("url_pwd", "") }").toByteArray(), Base64.NO_WRAP)}" } fun getUrl(): String { val settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - if (settings.contains("couchdbURL")) { - var url = settings.getString("couchdbURL", "") + var url: String? = "" - if (!url?.endsWith("/db")!!) { - url += "/db" - } - return url + url = if (settings.getBoolean("isAlternativeUrl", false)) { + settings.getString("processedAlternativeUrl", "") + } else { + settings.getString("couchdbURL", "") } - return "" + + if (!url?.endsWith("/db")!!) { + url += "/db" + } + return url } val hostUrl: String @@ -149,12 +155,19 @@ object Utilities { } fun getUpdateUrl(settings: SharedPreferences): String { - var url = settings.getString("couchdbURL", "") + var url: String? = "" + url = if (settings.getBoolean("isAlternativeUrl", false)) { + settings.getString("processedAlternativeUrl", "") + } else { + settings.getString("couchdbURL", "") + } + if (url != null) { if (url.endsWith("/db")) { url = url.replace("/db", "") } } + return "$url/versions" } @@ -179,7 +192,13 @@ object Utilities { } fun getApkVersionUrl(settings: SharedPreferences): String { - var url = settings.getString("couchdbURL", "") + var url: String? = "" + url = if (settings.getBoolean("isAlternativeUrl", false)){ + settings.getString("processedAlternativeUrl", "") + } else { + settings.getString("couchdbURL", "") + } + if (url != null) { if (url.endsWith("/db")) { url = url.replace("/db", "") From 4551d07a02b5b93a1674de10c9707568daeb2ea2 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Thu, 5 Dec 2024 20:45:04 +0300 Subject: [PATCH 04/14] succesful alternative url check --- .../ui/dashboard/DashboardActivity.kt | 103 ++++++++++- .../ui/sync/DashboardElementActivity.kt | 166 ++++++++++++++++-- .../planet/myplanet/ui/sync/SyncActivity.kt | 9 + 3 files changed, 263 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt index 386878e70a..f1df538ef1 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt @@ -7,9 +7,11 @@ import android.content.res.Configuration import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable +import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper +import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem @@ -56,6 +58,7 @@ import org.ole.planet.myplanet.model.RealmStepExam import org.ole.planet.myplanet.model.RealmSubmission import org.ole.planet.myplanet.model.RealmTeamTask import org.ole.planet.myplanet.model.RealmUserChallengeActions +import org.ole.planet.myplanet.model.RealmUserChallengeActions.Companion.createAction import org.ole.planet.myplanet.model.RealmUserModel import org.ole.planet.myplanet.service.UserProfileDbHandler import org.ole.planet.myplanet.ui.SettingActivity @@ -176,9 +179,107 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N activityDashboardBinding.appBarBell.bellToolbar.visibility = View.VISIBLE } activityDashboardBinding.appBarBell.ivSync.setOnClickListener { + val url = Utilities.getUrl() + val regex = Regex("^(https?://).*?@(.*?):") + val matchResult = regex.find(url) + + val extractedUrl = if (matchResult != null) { + val protocol = matchResult.groupValues[1] // "http://" + val address = matchResult.groupValues[2] // "192.168.1.202" + "$protocol$address" + } else { + null // Handle invalid URL + } + + 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" + ) + lifecycleScope.launch { - if (isServerReachable(Utilities.getUrl())) { + // Log the original URL being processed + Log.d("URLSync", "Original URL being processed: $url") + Log.d("URLSync", "Extracted base URL: $extractedUrl") + + // Find the first matching URL in serverMappings + val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } + + if (primaryUrlMapping != null) { + val primaryUrl = primaryUrlMapping.key + val alternativeUrl = primaryUrlMapping.value + + // Log the mapped URLs + Log.d("URLSync", "Mapped Primary URL: $primaryUrl") + Log.d("URLSync", "Mapped Alternative URL: $alternativeUrl") + + // Check primary URL first + Log.d("URLSync", "Attempting to reach primary URL: ${Utilities.getUrl()}") + val isPrimaryReachable = isServerReachable(Utilities.getUrl()) + + if (isPrimaryReachable) { + Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") +// processUrlAndStartUpload(Utilities.getUrl()) + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") + + val uri = Uri.parse(alternativeUrl) + var couchdbURL: String + val urlUser: String + val urlPwd: String + if (alternativeUrl.contains("@")) { + val userinfo = getUserInfo(uri) + urlUser = userinfo[0] + urlPwd = userinfo[1] + couchdbURL = alternativeUrl + } else { + urlUser = "satellite" + urlPwd = settings.getString("serverPin", "") ?: "" + couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" + } + editor.putString("url_user", urlUser) + editor.putString("url_pwd", urlPwd) + editor.putString("url_Scheme", uri.scheme) + editor.putString("url_Host", uri.host) + editor.putString("alternativeUrl", url) + editor.putString("processedAlternativeUrl", couchdbURL) + editor.putBoolean("isAlternativeUrl", true) + editor.apply() + + // If primary URL is not reachable, try alternative URL + Log.d("URLSync", "Attempting to reach alternative URL: $couchdbURL") + val isAlternativeReachable = isServerReachable(couchdbURL) + + if (isAlternativeReachable) { +// Log.d("URLSync", "Successfully reached alternative URL: $alternativeUrl") +// +// // Reconstruct URL with alternative base +// val uri = Uri.parse(url) +// val alternativeCouchdbUrl = reconstructUrlWithAlternative(uri, alternativeUrl) +// +// Log.d("URLSync", "Reconstructed alternative CouchDB URL: $alternativeCouchdbUrl") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + // Neither primary nor alternative URL is reachable + Log.e("URLSync", "Both primary and alternative URLs are unreachable") + Log.e("URLSync", "Primary URL failed: $primaryUrl") + Log.e("URLSync", "Alternative URL failed: $alternativeUrl") + } + } + } else { + // If no mapping found, log and proceed with original URL + Log.w("URLSync", "No URL mapping found for: $extractedUrl") + Log.d("URLSync", "Proceeding with original URL") +// processUrlAndStartUpload(url) startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } } } 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 ce46332ea7..6fd911649f 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 @@ -5,11 +5,14 @@ import android.app.AlertDialog import android.content.Intent import android.graphics.PorterDuff import android.net.ConnectivityManager +import android.net.Uri import android.net.wifi.WifiManager import android.os.Bundle import android.os.Handler import android.os.Looper import android.provider.Settings +import android.text.TextUtils +import android.util.Log import android.view.Menu import android.view.MenuItem import android.widget.Toast @@ -26,6 +29,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.ole.planet.myplanet.BuildConfig import org.ole.planet.myplanet.R import org.ole.planet.myplanet.callback.OnRatingChangeListener import org.ole.planet.myplanet.model.RealmUserChallengeActions.Companion.createAction @@ -42,6 +46,7 @@ import org.ole.planet.myplanet.ui.team.TeamFragment import org.ole.planet.myplanet.utilities.Constants import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME import org.ole.planet.myplanet.utilities.Constants.showBetaFeature +import org.ole.planet.myplanet.utilities.DialogUtils.showAlert import org.ole.planet.myplanet.utilities.SharedPrefManager import org.ole.planet.myplanet.utilities.Utilities @@ -151,28 +156,161 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack } fun logSyncInSharedPrefs() { - lifecycleScope.launch(Dispatchers.IO + SupervisorJob()) { - try { - val isReachable = isServerReachable(Utilities.getUrl()) - if (isReachable) { - withContext(Dispatchers.Main) { - startUpload("dashboard") +// lifecycleScope.launch { +// if (isServerReachable(Utilities.getUrl())) { +// startUpload("dashboard") +// createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") +// } +// } + + val url = Utilities.getUrl() + val regex = Regex("^(https?://).*?@(.*?):") + val matchResult = regex.find(url) + + val extractedUrl = if (matchResult != null) { + val protocol = matchResult.groupValues[1] // "http://" + val address = matchResult.groupValues[2] // "192.168.1.202" + "$protocol$address" + } else { + null // Handle invalid URL + } + + 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" + ) + + lifecycleScope.launch { + // Log the original URL being processed + Log.d("URLSync", "Original URL being processed: $url") + Log.d("URLSync", "Extracted base URL: $extractedUrl") + + // Find the first matching URL in serverMappings + val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } + + if (primaryUrlMapping != null) { + val primaryUrl = primaryUrlMapping.key + val alternativeUrl = primaryUrlMapping.value + + // Log the mapped URLs + Log.d("URLSync", "Mapped Primary URL: $primaryUrl") + Log.d("URLSync", "Mapped Alternative URL: $alternativeUrl") + + // Check primary URL first + Log.d("URLSync", "Attempting to reach primary URL: ${Utilities.getUrl()}") + val isPrimaryReachable = isServerReachable(Utilities.getUrl()) + + if (isPrimaryReachable) { + Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") +// processUrlAndStartUpload(Utilities.getUrl()) + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") + + val uri = Uri.parse(alternativeUrl) + var couchdbURL: String + val urlUser: String + val urlPwd: String + if (alternativeUrl.contains("@")) { + val userinfo = getUserInfo(uri) + urlUser = userinfo[0] + urlPwd = userinfo[1] + couchdbURL = alternativeUrl + } else { + urlUser = "satellite" + urlPwd = settings.getString("serverPin", "") ?: "" + couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" } - withContext(Dispatchers.IO) { - Realm.getDefaultInstance().use { realm -> - realm.executeTransaction { - createAction(realm, "${profileDbHandler.userModel?.id}", null, "sync") - } - } + // If primary URL is not reachable, try alternative URL + Log.d("URLSync", "Attempting to reach alternative 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.putString("alternativeUrl", url) + editor.putString("processedAlternativeUrl", couchdbURL) + editor.putBoolean("isAlternativeUrl", true) + editor.apply() + val isAlternativeReachable = isServerReachable(couchdbURL) + + if (isAlternativeReachable) { + +// Log.d("URLSync", "Successfully reached alternative URL: $alternativeUrl") +// +// // Reconstruct URL with alternative base +// val uri = Uri.parse(url) +// val alternativeCouchdbUrl = reconstructUrlWithAlternative(uri, alternativeUrl) +// +// Log.d("URLSync", "Reconstructed alternative CouchDB URL: $alternativeCouchdbUrl") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + // Neither primary nor alternative URL is reachable + Log.e("URLSync", "Both primary and alternative URLs are unreachable") + Log.e("URLSync", "Primary URL failed: $primaryUrl") + Log.e("URLSync", "Alternative URL failed: $alternativeUrl") } } - } catch (e: Exception) { - e.printStackTrace() + } else { + // If no mapping found, log and proceed with original URL + Log.w("URLSync", "No URL mapping found for: $extractedUrl") + Log.d("URLSync", "Proceeding with original URL") +// processUrlAndStartUpload(url) + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } } } + // Helper function to process URL and start upload +// fun processUrlAndStartUpload(url: String) { +// 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 { +// urlUser = "satellite" +// urlPwd = settings.getString("serverPin", "") ?: "" +// couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" +// } +// +// // Log the final CouchDB URL +// Log.d("URLSync", "Final CouchDB URL for upload: $couchdbURL") +// +// // Start upload with the processed URL +// startUpload("dashboard") +// createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") +// } + + // Helper function to reconstruct URL with alternative base + fun reconstructUrlWithAlternative(originalUri: Uri, alternativeBaseUrl: String): String { + val alternativeUri = Uri.parse(alternativeBaseUrl) + + val reconstructedUrl = if (originalUri.userInfo != null) { + // If original URL had user credentials + "${alternativeUri.scheme}://${originalUri.userInfo}@${alternativeUri.host}:${alternativeUri.port}" + } else { + // If original URL did not have user credentials + "${alternativeUri.scheme}://satellite:${settings.getString("serverPin", "")}@${alternativeUri.host}:${alternativeUri.port}" + } + + Log.d("URLSync", "Reconstructed alternative URL: $reconstructedUrl") + return reconstructedUrl + } + @SuppressLint("RestrictedApi") fun wifiStatusSwitch() { val resIcon = ContextCompat.getDrawable(this, R.drawable.goonline) 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 551fbd7533..37129fe823 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 @@ -188,13 +188,16 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers } suspend fun isServerReachable(processedUrl: String?): Boolean { + Log.d("SyncActivity", "isServerReachable: $processedUrl") return withContext(Dispatchers.IO) { val apiInterface = client?.create(ApiInterface::class.java) try { Log.d("SyncActivity", "isServerReachable: $processedUrl") val response = if (settings.getBoolean("isAlternativeUrl", false)){ + Log.d("okuro", "isAlternativeUrl true: $processedUrl/db/_all_dbs") apiInterface?.isPlanetAvailable("$processedUrl/db/_all_dbs")?.execute() } else { + Log.d("okuro", "isAlternativeUrl false: $processedUrl/db/_all_dbs") apiInterface?.isPlanetAvailable("$processedUrl/_all_dbs")?.execute() } @@ -359,6 +362,12 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers createLog("synced successfully") } showSnack(findViewById(android.R.id.content), getString(R.string.sync_completed)) + if (settings.getBoolean("isAlternativeUrl", false)) { + editor.putString("alternativeUrl", "") + editor.putString("processedAlternativeUrl", "") + editor.putBoolean("isAlternativeUrl", false) + editor.apply() + } downloadAdditionalResources() if (defaultPref.getBoolean("beta_auto_download", false)) { backgroundDownload(downloadAllFiles(getAllLibraryList(mRealm))) From b5ac15c6c870d9cb4f7878c5c5bc27e6baae8da8 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Thu, 5 Dec 2024 22:50:21 +0300 Subject: [PATCH 05/14] Update DashboardActivity.kt.lite --- .../ui/dashboard/DashboardActivity.kt.lite | 103 +++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite index 0afa9e382e..c96d5a1afb 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite @@ -7,9 +7,11 @@ import android.content.res.Configuration import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable +import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper +import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem @@ -56,6 +58,7 @@ import org.ole.planet.myplanet.model.RealmStepExam import org.ole.planet.myplanet.model.RealmSubmission import org.ole.planet.myplanet.model.RealmTeamTask import org.ole.planet.myplanet.model.RealmUserChallengeActions +import org.ole.planet.myplanet.model.RealmUserChallengeActions.Companion.createAction import org.ole.planet.myplanet.model.RealmUserModel import org.ole.planet.myplanet.service.UserProfileDbHandler import org.ole.planet.myplanet.ui.SettingActivity @@ -176,9 +179,107 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N activityDashboardBinding.appBarBell.bellToolbar.visibility = View.VISIBLE } activityDashboardBinding.appBarBell.ivSync.setOnClickListener { + val url = Utilities.getUrl() + val regex = Regex("^(https?://).*?@(.*?):") + val matchResult = regex.find(url) + + val extractedUrl = if (matchResult != null) { + val protocol = matchResult.groupValues[1] // "http://" + val address = matchResult.groupValues[2] // "192.168.1.202" + "$protocol$address" + } else { + null // Handle invalid URL + } + + 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" + ) + lifecycleScope.launch { - if (isServerReachable(Utilities.getUrl())) { + // Log the original URL being processed + Log.d("URLSync", "Original URL being processed: $url") + Log.d("URLSync", "Extracted base URL: $extractedUrl") + + // Find the first matching URL in serverMappings + val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } + + if (primaryUrlMapping != null) { + val primaryUrl = primaryUrlMapping.key + val alternativeUrl = primaryUrlMapping.value + + // Log the mapped URLs + Log.d("URLSync", "Mapped Primary URL: $primaryUrl") + Log.d("URLSync", "Mapped Alternative URL: $alternativeUrl") + + // Check primary URL first + Log.d("URLSync", "Attempting to reach primary URL: ${Utilities.getUrl()}") + val isPrimaryReachable = isServerReachable(Utilities.getUrl()) + + if (isPrimaryReachable) { + Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") +// processUrlAndStartUpload(Utilities.getUrl()) + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") + + val uri = Uri.parse(alternativeUrl) + var couchdbURL: String + val urlUser: String + val urlPwd: String + if (alternativeUrl.contains("@")) { + val userinfo = getUserInfo(uri) + urlUser = userinfo[0] + urlPwd = userinfo[1] + couchdbURL = alternativeUrl + } else { + urlUser = "satellite" + urlPwd = settings.getString("serverPin", "") ?: "" + couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" + } + editor.putString("url_user", urlUser) + editor.putString("url_pwd", urlPwd) + editor.putString("url_Scheme", uri.scheme) + editor.putString("url_Host", uri.host) + editor.putString("alternativeUrl", url) + editor.putString("processedAlternativeUrl", couchdbURL) + editor.putBoolean("isAlternativeUrl", true) + editor.apply() + + // If primary URL is not reachable, try alternative URL + Log.d("URLSync", "Attempting to reach alternative URL: $couchdbURL") + val isAlternativeReachable = isServerReachable(couchdbURL) + + if (isAlternativeReachable) { +// Log.d("URLSync", "Successfully reached alternative URL: $alternativeUrl") +// +// // Reconstruct URL with alternative base +// val uri = Uri.parse(url) +// val alternativeCouchdbUrl = reconstructUrlWithAlternative(uri, alternativeUrl) +// +// Log.d("URLSync", "Reconstructed alternative CouchDB URL: $alternativeCouchdbUrl") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + // Neither primary nor alternative URL is reachable + Log.e("URLSync", "Both primary and alternative URLs are unreachable") + Log.e("URLSync", "Primary URL failed: $primaryUrl") + Log.e("URLSync", "Alternative URL failed: $alternativeUrl") + } + } + } else { + // If no mapping found, log and proceed with original URL + Log.w("URLSync", "No URL mapping found for: $extractedUrl") + Log.d("URLSync", "Proceeding with original URL") +// processUrlAndStartUpload(url) startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } } } From e103e589ff8a6552d35d57d28511d6f6c2e68822 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 17 Dec 2024 17:33:09 +0300 Subject: [PATCH 06/14] add logs --- .../planet/myplanet/datamanager/Service.kt | 259 +++++++++++------- 1 file changed, 166 insertions(+), 93 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index 3e76e47f30..04ba51ef55 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -334,6 +334,9 @@ class Service(private val context: Context) { } fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) { + val overallStartTime = System.currentTimeMillis() + Log.d("PerformanceLog", "Starting getMinApk process") + // Create a list of URLs to try, starting with the original URL val urlsToTry = mutableListOf(url) @@ -350,37 +353,67 @@ class Service(private val context: Context) { // Add alternative URL from serverMappings if available serverMappings[url]?.let { alternativeUrl -> urlsToTry.add(alternativeUrl) + Log.d("PerformanceLog", "Added alternative URL: $alternativeUrl") } // Use coroutine scope to perform concurrent URL checks applicationScope.launch { + val dialogStartTime = System.currentTimeMillis() val customProgressDialog = withContext(Dispatchers.Main) { CustomProgressDialog(context).apply { setText(context.getString(R.string.check_apk_version)) show() } } + Log.d("PerformanceLog", "Dialog creation took: ${System.currentTimeMillis() - dialogStartTime}ms") try { // Use withContext(Dispatchers.IO) for network operations + val networkStartTime = System.currentTimeMillis() val result = withContext(Dispatchers.IO) { // Create a list of deferred jobs for concurrent network calls val deferredResults = urlsToTry.map { currentUrl -> async { try { - Log.d("Service", "Checking URL: $currentUrl") + val urlStartTime = System.currentTimeMillis() + Log.d("PerformanceLog", "Starting check for URL: $currentUrl") + // Check versions concurrently - val versionsResponse = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() + val versionCheckStartTime = System.currentTimeMillis() + val versionsResponse = try { + Log.d("NetworkLog", "Attempting to connect to $currentUrl/versions") + val response = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() + val checkDuration = System.currentTimeMillis() - versionCheckStartTime + Log.d("PerformanceLog", "Version check for $currentUrl took: ${checkDuration}ms") + + if (checkDuration >= 60000) { + Log.w("NetworkLog", "Connection to $currentUrl took excessive time (${checkDuration}ms)") + } + response + } catch (e: java.net.ConnectException) { + Log.e("NetworkLog", "Connection failed for $currentUrl: ${e.message}") + Log.d("NetworkLog", "Moving to next URL in fallback list") + null + } catch (e: java.net.SocketTimeoutException) { + Log.e("NetworkLog", "Connection timed out for $currentUrl: ${e.message}") + Log.d("NetworkLog", "Moving to next URL in fallback list") + null + } catch (e: Exception) { + Log.e("NetworkLog", "Unexpected error connecting to $currentUrl", e) + Log.d("NetworkLog", "Moving to next URL in fallback list") + null + } if (versionsResponse?.isSuccessful == true) { val jsonObject = versionsResponse.body() val currentVersion = "${context.resources.getText(R.string.app_version)}" val minApkVersion = jsonObject?.get("minapk")?.asString - Log.d("okuro", "first config check is successful") + Log.d("PerformanceLog", "Version parsing successful for $currentUrl") // Version check if (minApkVersion != null && isVersionAllowed(currentVersion, minApkVersion)) { // Perform configuration check for this URL + val configStartTime = System.currentTimeMillis() val uri = Uri.parse(currentUrl) val couchdbURL = if (currentUrl.contains("@")) { getUserInfo(uri) @@ -389,35 +422,43 @@ class Service(private val context: Context) { val urlUser = "satellite" "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" } + withContext(Dispatchers.Main) { customProgressDialog.setText(context.getString(R.string.checking_server)) } - val configResponse = retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").execute() - if (configResponse.isSuccessful) { - Log.d("okuro", "second config check is successful") + val configResponse = retrofitInterface?.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true")?.execute() + Log.d("PerformanceLog", "Configuration check for $currentUrl took: ${System.currentTimeMillis() - configStartTime}ms") + + if (configResponse?.isSuccessful == true) { val rows = configResponse.body()?.getAsJsonArray("rows") if (rows != null && rows.size() > 0) { val firstRow = rows.get(0).asJsonObject val id = firstRow.getAsJsonPrimitive("id").asString val doc = firstRow.getAsJsonObject("doc") val code = doc.getAsJsonPrimitive("code").asString + Log.d("PerformanceLog", "Total processing time for successful URL $currentUrl: ${System.currentTimeMillis() - urlStartTime}ms") return@async UrlCheckResult.Success(id, code, currentUrl) } } } } + Log.d("PerformanceLog", "URL $currentUrl failed after ${System.currentTimeMillis() - urlStartTime}ms") return@async UrlCheckResult.Failure(currentUrl) } catch (e: Exception) { - e.printStackTrace() + Log.e("PerformanceLog", "Exception while processing $currentUrl", e) return@async UrlCheckResult.Failure(currentUrl) } } } // Wait for the first successful result - deferredResults.awaitFirst { it is UrlCheckResult.Success } + val awaitStartTime = System.currentTimeMillis() + val result = deferredResults.awaitFirst { it is UrlCheckResult.Success } + Log.d("PerformanceLog", "Awaiting first successful result took: ${System.currentTimeMillis() - awaitStartTime}ms") + result } + Log.d("PerformanceLog", "Total network operations took: ${System.currentTimeMillis() - networkStartTime}ms") // Handle the result when (result) { @@ -425,7 +466,7 @@ class Service(private val context: Context) { val isAlternativeUrl = result.url != url listener?.onConfigurationIdReceived(result.id, result.code, result.url, isAlternativeUrl) activity.setSyncFailed(false) - Log.d("Service", "Successfully connected to URL: ${result.url}") + Log.d("PerformanceLog", "Successfully connected to URL: ${result.url}") } is UrlCheckResult.Failure -> { activity.setSyncFailed(true) @@ -438,115 +479,147 @@ class Service(private val context: Context) { } } } catch (e: Exception) { - e.printStackTrace() + Log.e("PerformanceLog", "Exception in main process", e) activity.setSyncFailed(true) showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) } finally { customProgressDialog.dismiss() + Log.d("PerformanceLog", "Total process time: ${System.currentTimeMillis() - overallStartTime}ms") } } } - // Sealed class to represent URL check results - sealed class UrlCheckResult { - data class Success(val id: String, val code: String, val url: String) : UrlCheckResult() - data class Failure(val url: String) : UrlCheckResult() - } - - // Extension function to await the first successful result - private suspend fun List>.awaitFirst(predicate: (T) -> Boolean): T { - return firstOrNull { job -> - try { - val result = job.await() - predicate(result) - } catch (e: Exception) { - e.printStackTrace() - false - } - }?.await() ?: throw NoSuchElementException("No matching result found") - } - // fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) { -// val customProgressDialog = CustomProgressDialog(context).apply { -// setText(context.getString(R.string.check_apk_version)) -// show() +// // Create a list of URLs to try, starting with the original URL +// val urlsToTry = mutableListOf(url) +// +// 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" +// ) +// +// // Add alternative URL from serverMappings if available +// serverMappings[url]?.let { alternativeUrl -> +// urlsToTry.add(alternativeUrl) // } // -// retrofitInterface?.getConfiguration("$url/versions")?.enqueue(object : Callback { -// override fun onResponse(call: Call, response: Response) { -// if (response.isSuccessful) { -// response.body()?.let { jsonObject -> -// val currentVersion = "${context.resources.getText(R.string.app_version)}" -// val minApkVersion = jsonObject.get("minapk").asString -// if (isVersionAllowed(currentVersion, minApkVersion)) { -// customProgressDialog.setText(context.getString(R.string.checking_server)) -// val uri = Uri.parse(url) -// val couchdbURL: String -// if (url.contains("@")) { -// getUserInfo(uri) -// couchdbURL = url -// } else { -// val urlUser = "satellite" -// couchdbURL = "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" -// } -// retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").enqueue(object : Callback { -// override fun onResponse(call: Call, response: Response) { -// if (response.isSuccessful) { -// val jsonObjectResponse = response.body() -// val rows = jsonObjectResponse?.getAsJsonArray("rows") -// if (rows != null && rows.size() > 0) { -// val firstRow = rows.get(0).asJsonObject -// val id = firstRow.getAsJsonPrimitive("id").asString -// val doc = firstRow.getAsJsonObject("doc") -// val code = doc.getAsJsonPrimitive("code").asString -// listener?.onConfigurationIdReceived(id, code) -// activity.setSyncFailed(false) +// // Use coroutine scope to perform concurrent URL checks +// applicationScope.launch { +// val customProgressDialog = withContext(Dispatchers.Main) { +// CustomProgressDialog(context).apply { +// setText(context.getString(R.string.check_apk_version)) +// show() +// } +// } +// +// try { +// // Use withContext(Dispatchers.IO) for network operations +// val result = withContext(Dispatchers.IO) { +// // Create a list of deferred jobs for concurrent network calls +// val deferredResults = urlsToTry.map { currentUrl -> +// async { +// try { +// Log.d("Service", "Checking URL: $currentUrl") +// // Check versions concurrently +// val versionsResponse = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() +// +// if (versionsResponse?.isSuccessful == true) { +// val jsonObject = versionsResponse.body() +// val currentVersion = "${context.resources.getText(R.string.app_version)}" +// val minApkVersion = jsonObject?.get("minapk")?.asString +// Log.d("okuro", "first config check is successful") +// +// // Version check +// if (minApkVersion != null && isVersionAllowed(currentVersion, minApkVersion)) { +// // Perform configuration check for this URL +// val uri = Uri.parse(currentUrl) +// val couchdbURL = if (currentUrl.contains("@")) { +// getUserInfo(uri) +// currentUrl // } else { -// activity.setSyncFailed(true) -// showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false) +// val urlUser = "satellite" +// "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" // } -// } else { -// activity.setSyncFailed(true) -// showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false) -// } -// customProgressDialog.dismiss() -// } +// withContext(Dispatchers.Main) { +// customProgressDialog.setText(context.getString(R.string.checking_server)) +// } +// val configResponse = retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").execute() // -// override fun onFailure(call: Call, t: Throwable) { -// activity.setSyncFailed(true) -// customProgressDialog.dismiss() -// if (getUrl(couchdbURL) == context.getString(R.string.http_protocol)) { -// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) -// } else if (getUrl(couchdbURL) == context.getString(R.string.https_protocol)) { -// showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false) +// if (configResponse.isSuccessful) { +// Log.d("okuro", "second config check is successful") +// val rows = configResponse.body()?.getAsJsonArray("rows") +// if (rows != null && rows.size() > 0) { +// val firstRow = rows.get(0).asJsonObject +// val id = firstRow.getAsJsonPrimitive("id").asString +// val doc = firstRow.getAsJsonObject("doc") +// val code = doc.getAsJsonPrimitive("code").asString +// return@async UrlCheckResult.Success(id, code, currentUrl) +// } +// } // } // } -// }) -// } else { -// activity.setSyncFailed(true) -// customProgressDialog.dismiss() -// showAlertDialog(context.getString(R.string.below_min_apk), true) +// return@async UrlCheckResult.Failure(currentUrl) +// } catch (e: Exception) { +// e.printStackTrace() +// return@async UrlCheckResult.Failure(currentUrl) +// } // } // } -// } else { -// activity.setSyncFailed(true) -// customProgressDialog.dismiss() -// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) +// +// // Wait for the first successful result +// deferredResults.awaitFirst { it is UrlCheckResult.Success } // } -// } // -// override fun onFailure(call: Call, t: Throwable) { +// // Handle the result +// when (result) { +// is UrlCheckResult.Success -> { +// val isAlternativeUrl = result.url != url +// listener?.onConfigurationIdReceived(result.id, result.code, result.url, isAlternativeUrl) +// activity.setSyncFailed(false) +// Log.d("Service", "Successfully connected to URL: ${result.url}") +// } +// is UrlCheckResult.Failure -> { +// activity.setSyncFailed(true) +// val errorMessage = when (extractProtocol(url)) { +// context.getString(R.string.http_protocol) -> context.getString(R.string.device_couldn_t_reach_local_server) +// context.getString(R.string.https_protocol) -> context.getString(R.string.device_couldn_t_reach_nation_server) +// else -> context.getString(R.string.device_couldn_t_reach_local_server) +// } +// showAlertDialog(errorMessage, false) +// } +// } +// } catch (e: Exception) { +// e.printStackTrace() // activity.setSyncFailed(true) +// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) +// } finally { // customProgressDialog.dismiss() -// if (extractProtocol(url) == context.getString(R.string.http_protocol)) { -// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) -// } else if (extractProtocol(url) == context.getString(R.string.https_protocol)) { -// showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false) -// } // } -// }) +// } // } + sealed class UrlCheckResult { + data class Success(val id: String, val code: String, val url: String) : UrlCheckResult() + data class Failure(val url: String) : UrlCheckResult() + } + + private suspend fun List>.awaitFirst(predicate: (T) -> Boolean): T { + return firstOrNull { job -> + try { + val result = job.await() + predicate(result) + } catch (e: Exception) { + e.printStackTrace() + false + } + }?.await() ?: throw NoSuchElementException("No matching result found") + } + private fun isVersionAllowed(currentVersion: String, minApkVersion: String): Boolean { return compareVersions(currentVersion, minApkVersion) >= 0 } From 795c1bdf3a31e906306e2d8f7d18865a0cf7001f Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 17 Dec 2024 19:56:14 +0300 Subject: [PATCH 07/14] cleanup commented code --- .../planet/myplanet/datamanager/Service.kt | 1 + .../ui/dashboard/DashboardActivity.kt | 12 ---- .../ui/sync/DashboardElementActivity.kt | 68 ++----------------- 3 files changed, 5 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index 04ba51ef55..c9471c4935 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -420,6 +420,7 @@ class Service(private val context: Context) { currentUrl } else { val urlUser = "satellite" + Log.d("okuro", "called") "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt index f1df538ef1..0204e44a06 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt @@ -251,33 +251,21 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N editor.putString("processedAlternativeUrl", couchdbURL) editor.putBoolean("isAlternativeUrl", true) editor.apply() - - // If primary URL is not reachable, try alternative URL Log.d("URLSync", "Attempting to reach alternative URL: $couchdbURL") val isAlternativeReachable = isServerReachable(couchdbURL) if (isAlternativeReachable) { -// Log.d("URLSync", "Successfully reached alternative URL: $alternativeUrl") -// -// // Reconstruct URL with alternative base -// val uri = Uri.parse(url) -// val alternativeCouchdbUrl = reconstructUrlWithAlternative(uri, alternativeUrl) -// -// Log.d("URLSync", "Reconstructed alternative CouchDB URL: $alternativeCouchdbUrl") startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } else { - // Neither primary nor alternative URL is reachable Log.e("URLSync", "Both primary and alternative URLs are unreachable") Log.e("URLSync", "Primary URL failed: $primaryUrl") Log.e("URLSync", "Alternative URL failed: $alternativeUrl") } } } else { - // If no mapping found, log and proceed with original URL Log.w("URLSync", "No URL mapping found for: $extractedUrl") Log.d("URLSync", "Proceeding with original URL") -// processUrlAndStartUpload(url) startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } 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 6fd911649f..1d6cee6e36 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 @@ -11,7 +11,6 @@ import android.os.Bundle import android.os.Handler import android.os.Looper import android.provider.Settings -import android.text.TextUtils import android.util.Log import android.view.Menu import android.view.MenuItem @@ -40,13 +39,12 @@ import org.ole.planet.myplanet.ui.courses.CoursesFragment import org.ole.planet.myplanet.ui.dashboard.BellDashboardFragment import org.ole.planet.myplanet.ui.dashboard.DashboardFragment import org.ole.planet.myplanet.ui.feedback.FeedbackFragment -import org.ole.planet.myplanet.ui.resources.ResourcesFragment import org.ole.planet.myplanet.ui.rating.RatingFragment.Companion.newInstance +import org.ole.planet.myplanet.ui.resources.ResourcesFragment import org.ole.planet.myplanet.ui.team.TeamFragment import org.ole.planet.myplanet.utilities.Constants import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME import org.ole.planet.myplanet.utilities.Constants.showBetaFeature -import org.ole.planet.myplanet.utilities.DialogUtils.showAlert import org.ole.planet.myplanet.utilities.SharedPrefManager import org.ole.planet.myplanet.utilities.Utilities @@ -156,23 +154,16 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack } fun logSyncInSharedPrefs() { -// lifecycleScope.launch { -// if (isServerReachable(Utilities.getUrl())) { -// startUpload("dashboard") -// createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") -// } -// } - val url = Utilities.getUrl() val regex = Regex("^(https?://).*?@(.*?):") val matchResult = regex.find(url) val extractedUrl = if (matchResult != null) { - val protocol = matchResult.groupValues[1] // "http://" - val address = matchResult.groupValues[2] // "192.168.1.202" + val protocol = matchResult.groupValues[1] + val address = matchResult.groupValues[2] "$protocol$address" } else { - null // Handle invalid URL + null } val serverMappings = mapOf( @@ -186,7 +177,6 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack ) lifecycleScope.launch { - // Log the original URL being processed Log.d("URLSync", "Original URL being processed: $url") Log.d("URLSync", "Extracted base URL: $extractedUrl") @@ -241,14 +231,6 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack val isAlternativeReachable = isServerReachable(couchdbURL) if (isAlternativeReachable) { - -// Log.d("URLSync", "Successfully reached alternative URL: $alternativeUrl") -// -// // Reconstruct URL with alternative base -// val uri = Uri.parse(url) -// val alternativeCouchdbUrl = reconstructUrlWithAlternative(uri, alternativeUrl) -// -// Log.d("URLSync", "Reconstructed alternative CouchDB URL: $alternativeCouchdbUrl") startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } else { @@ -269,48 +251,6 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack } } - // Helper function to process URL and start upload -// fun processUrlAndStartUpload(url: String) { -// 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 { -// urlUser = "satellite" -// urlPwd = settings.getString("serverPin", "") ?: "" -// couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" -// } -// -// // Log the final CouchDB URL -// Log.d("URLSync", "Final CouchDB URL for upload: $couchdbURL") -// -// // Start upload with the processed URL -// startUpload("dashboard") -// createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") -// } - - // Helper function to reconstruct URL with alternative base - fun reconstructUrlWithAlternative(originalUri: Uri, alternativeBaseUrl: String): String { - val alternativeUri = Uri.parse(alternativeBaseUrl) - - val reconstructedUrl = if (originalUri.userInfo != null) { - // If original URL had user credentials - "${alternativeUri.scheme}://${originalUri.userInfo}@${alternativeUri.host}:${alternativeUri.port}" - } else { - // If original URL did not have user credentials - "${alternativeUri.scheme}://satellite:${settings.getString("serverPin", "")}@${alternativeUri.host}:${alternativeUri.port}" - } - - Log.d("URLSync", "Reconstructed alternative URL: $reconstructedUrl") - return reconstructedUrl - } - @SuppressLint("RestrictedApi") fun wifiStatusSwitch() { val resIcon = ContextCompat.getDrawable(this, R.drawable.goonline) From 18d71c349ba8860240cde9e54eb7b345b059efc3 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 17 Dec 2024 20:35:45 +0300 Subject: [PATCH 08/14] refactor and cleanup --- .../ui/dashboard/DashboardActivity.kt | 115 +++----------- .../ui/dashboard/DashboardActivity.kt.lite | 127 +++------------ .../ui/sync/DashboardElementActivity.kt | 116 ++------------ .../ui/sync/ProcessUserDataActivity.kt | 17 +- .../planet/myplanet/utilities/URLProcessor.kt | 150 ++++++++++++++++++ 5 files changed, 217 insertions(+), 308 deletions(-) create mode 100644 app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt index 0204e44a06..4d7b88cf7f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt @@ -7,15 +7,10 @@ import android.content.res.Configuration import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable -import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper -import android.util.Log -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuItem -import android.view.View +import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatDelegate @@ -86,7 +81,7 @@ import org.ole.planet.myplanet.utilities.KeyboardUtils.setupUI import org.ole.planet.myplanet.utilities.LocaleHelper import org.ole.planet.myplanet.utilities.MarkdownDialog import org.ole.planet.myplanet.utilities.TimeUtils.formatDate -import org.ole.planet.myplanet.utilities.Utilities +import org.ole.planet.myplanet.utilities.URLProcessor import org.ole.planet.myplanet.utilities.Utilities.toast import java.text.SimpleDateFormat import java.time.LocalDate @@ -132,6 +127,15 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N disableShiftMode(navigationView) activityDashboardBinding.appBarBell.bellToolbar.inflateMenu(R.menu.menu_bell_dashboard) tl = findViewById(R.id.tab_layout) + urlProcessor = URLProcessor( + context = this, + lifecycleScope = lifecycleScope, + settings = settings, + editor = editor, + mRealm = mRealm, + profileDbHandler = profileDbHandler + ) + try { val userProfileModel = profileDbHandler.userModel if (userProfileModel != null) { @@ -178,99 +182,20 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N openCallFragment(BellDashboardFragment()) activityDashboardBinding.appBarBell.bellToolbar.visibility = View.VISIBLE } - activityDashboardBinding.appBarBell.ivSync.setOnClickListener { - val url = Utilities.getUrl() - val regex = Regex("^(https?://).*?@(.*?):") - val matchResult = regex.find(url) - - val extractedUrl = if (matchResult != null) { - val protocol = matchResult.groupValues[1] // "http://" - val address = matchResult.groupValues[2] // "192.168.1.202" - "$protocol$address" - } else { - null // Handle invalid URL - } - - 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" - ) + activityDashboardBinding.appBarBell.ivSync.setOnClickListener { lifecycleScope.launch { - // Log the original URL being processed - Log.d("URLSync", "Original URL being processed: $url") - Log.d("URLSync", "Extracted base URL: $extractedUrl") - - // Find the first matching URL in serverMappings - val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } - - if (primaryUrlMapping != null) { - val primaryUrl = primaryUrlMapping.key - val alternativeUrl = primaryUrlMapping.value - - // Log the mapped URLs - Log.d("URLSync", "Mapped Primary URL: $primaryUrl") - Log.d("URLSync", "Mapped Alternative URL: $alternativeUrl") - - // Check primary URL first - Log.d("URLSync", "Attempting to reach primary URL: ${Utilities.getUrl()}") - val isPrimaryReachable = isServerReachable(Utilities.getUrl()) - - if (isPrimaryReachable) { - Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") -// processUrlAndStartUpload(Utilities.getUrl()) - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") - - val uri = Uri.parse(alternativeUrl) - var couchdbURL: String - val urlUser: String - val urlPwd: String - if (alternativeUrl.contains("@")) { - val userinfo = getUserInfo(uri) - urlUser = userinfo[0] - urlPwd = userinfo[1] - couchdbURL = alternativeUrl - } else { - urlUser = "satellite" - urlPwd = settings.getString("serverPin", "") ?: "" - couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" - } - editor.putString("url_user", urlUser) - editor.putString("url_pwd", urlPwd) - editor.putString("url_Scheme", uri.scheme) - editor.putString("url_Host", uri.host) - editor.putString("alternativeUrl", url) - editor.putString("processedAlternativeUrl", couchdbURL) - editor.putBoolean("isAlternativeUrl", true) - editor.apply() - Log.d("URLSync", "Attempting to reach alternative URL: $couchdbURL") - val isAlternativeReachable = isServerReachable(couchdbURL) - - if (isAlternativeReachable) { - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - Log.e("URLSync", "Both primary and alternative URLs are unreachable") - Log.e("URLSync", "Primary URL failed: $primaryUrl") - Log.e("URLSync", "Alternative URL failed: $alternativeUrl") - } + urlProcessor.processSyncURL( + onStartUpload = { source -> + startUpload(source) + }, + onCreateAction = { realm, id, type, action -> + createAction(realm, "${profileDbHandler.userModel?.id}", type, action) } - } else { - Log.w("URLSync", "No URL mapping found for: $extractedUrl") - Log.d("URLSync", "Proceeding with original URL") - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } + ) } } + activityDashboardBinding.appBarBell.imgLogo.setOnClickListener { result?.openDrawer() } activityDashboardBinding.appBarBell.bellToolbar.setOnMenuItemClickListener { item -> when (item.itemId) { diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite index c96d5a1afb..491242afe7 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite @@ -7,15 +7,10 @@ import android.content.res.Configuration import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable -import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper -import android.util.Log -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuItem -import android.view.View +import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatDelegate @@ -86,7 +81,7 @@ import org.ole.planet.myplanet.utilities.KeyboardUtils.setupUI import org.ole.planet.myplanet.utilities.LocaleHelper import org.ole.planet.myplanet.utilities.MarkdownDialog import org.ole.planet.myplanet.utilities.TimeUtils.formatDate -import org.ole.planet.myplanet.utilities.Utilities +import org.ole.planet.myplanet.utilities.URLProcessor import org.ole.planet.myplanet.utilities.Utilities.toast import java.text.SimpleDateFormat import java.time.LocalDate @@ -132,6 +127,15 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N disableShiftMode(navigationView) activityDashboardBinding.appBarBell.bellToolbar.inflateMenu(R.menu.menu_bell_dashboard) tl = findViewById(R.id.tab_layout) + urlProcessor = URLProcessor( + context = this, + lifecycleScope = lifecycleScope, + settings = settings, + editor = editor, + mRealm = mRealm, + profileDbHandler = profileDbHandler + ) + try { val userProfileModel = profileDbHandler.userModel if (userProfileModel != null) { @@ -178,111 +182,20 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N openCallFragment(BellDashboardFragment()) activityDashboardBinding.appBarBell.bellToolbar.visibility = View.VISIBLE } - activityDashboardBinding.appBarBell.ivSync.setOnClickListener { - val url = Utilities.getUrl() - val regex = Regex("^(https?://).*?@(.*?):") - val matchResult = regex.find(url) - - val extractedUrl = if (matchResult != null) { - val protocol = matchResult.groupValues[1] // "http://" - val address = matchResult.groupValues[2] // "192.168.1.202" - "$protocol$address" - } else { - null // Handle invalid URL - } - - 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" - ) + activityDashboardBinding.appBarBell.ivSync.setOnClickListener { lifecycleScope.launch { - // Log the original URL being processed - Log.d("URLSync", "Original URL being processed: $url") - Log.d("URLSync", "Extracted base URL: $extractedUrl") - - // Find the first matching URL in serverMappings - val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } - - if (primaryUrlMapping != null) { - val primaryUrl = primaryUrlMapping.key - val alternativeUrl = primaryUrlMapping.value - - // Log the mapped URLs - Log.d("URLSync", "Mapped Primary URL: $primaryUrl") - Log.d("URLSync", "Mapped Alternative URL: $alternativeUrl") - - // Check primary URL first - Log.d("URLSync", "Attempting to reach primary URL: ${Utilities.getUrl()}") - val isPrimaryReachable = isServerReachable(Utilities.getUrl()) - - if (isPrimaryReachable) { - Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") -// processUrlAndStartUpload(Utilities.getUrl()) - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") - - val uri = Uri.parse(alternativeUrl) - var couchdbURL: String - val urlUser: String - val urlPwd: String - if (alternativeUrl.contains("@")) { - val userinfo = getUserInfo(uri) - urlUser = userinfo[0] - urlPwd = userinfo[1] - couchdbURL = alternativeUrl - } else { - urlUser = "satellite" - urlPwd = settings.getString("serverPin", "") ?: "" - couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" - } - editor.putString("url_user", urlUser) - editor.putString("url_pwd", urlPwd) - editor.putString("url_Scheme", uri.scheme) - editor.putString("url_Host", uri.host) - editor.putString("alternativeUrl", url) - editor.putString("processedAlternativeUrl", couchdbURL) - editor.putBoolean("isAlternativeUrl", true) - editor.apply() - - // If primary URL is not reachable, try alternative URL - Log.d("URLSync", "Attempting to reach alternative URL: $couchdbURL") - val isAlternativeReachable = isServerReachable(couchdbURL) - - if (isAlternativeReachable) { -// Log.d("URLSync", "Successfully reached alternative URL: $alternativeUrl") -// -// // Reconstruct URL with alternative base -// val uri = Uri.parse(url) -// val alternativeCouchdbUrl = reconstructUrlWithAlternative(uri, alternativeUrl) -// -// Log.d("URLSync", "Reconstructed alternative CouchDB URL: $alternativeCouchdbUrl") - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - // Neither primary nor alternative URL is reachable - Log.e("URLSync", "Both primary and alternative URLs are unreachable") - Log.e("URLSync", "Primary URL failed: $primaryUrl") - Log.e("URLSync", "Alternative URL failed: $alternativeUrl") - } + urlProcessor.processSyncURL( + onStartUpload = { source -> + startUpload(source) + }, + onCreateAction = { realm, id, type, action -> + createAction(realm, "${profileDbHandler.userModel?.id}", type, action) } - } else { - // If no mapping found, log and proceed with original URL - Log.w("URLSync", "No URL mapping found for: $extractedUrl") - Log.d("URLSync", "Proceeding with original URL") -// processUrlAndStartUpload(url) - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } + ) } } + activityDashboardBinding.appBarBell.imgLogo.setOnClickListener { result?.openDrawer() } activityDashboardBinding.appBarBell.bellToolbar.setOnMenuItemClickListener { item -> when (item.itemId) { 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 1d6cee6e36..a6c64c5219 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 @@ -5,13 +5,11 @@ import android.app.AlertDialog import android.content.Intent import android.graphics.PorterDuff import android.net.ConnectivityManager -import android.net.Uri import android.net.wifi.WifiManager 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 @@ -22,13 +20,9 @@ import androidx.fragment.app.FragmentManager import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.android.material.bottomnavigation.BottomNavigationView -import io.realm.Realm import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.ole.planet.myplanet.BuildConfig import org.ole.planet.myplanet.R import org.ole.planet.myplanet.callback.OnRatingChangeListener import org.ole.planet.myplanet.model.RealmUserChallengeActions.Companion.createAction @@ -46,19 +40,28 @@ import org.ole.planet.myplanet.utilities.Constants import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME import org.ole.planet.myplanet.utilities.Constants.showBetaFeature import org.ole.planet.myplanet.utilities.SharedPrefManager -import org.ole.planet.myplanet.utilities.Utilities +import org.ole.planet.myplanet.utilities.URLProcessor abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBackStackChangedListener { lateinit var navigationView: BottomNavigationView var doubleBackToExitPressedOnce = false private lateinit var goOnline: MenuItem var c = 0 + lateinit var urlProcessor: URLProcessor override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) profileDbHandler = UserProfileDbHandler(this) settings = applicationContext.getSharedPreferences(PREFS_NAME, MODE_PRIVATE) prefData = SharedPrefManager(this) + urlProcessor = URLProcessor( + context = this, + lifecycleScope = lifecycleScope, + settings = settings, + editor = editor, + mRealm = mRealm, + profileDbHandler = profileDbHandler + ) } fun onClickTabItems(position: Int) { @@ -154,100 +157,15 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack } fun logSyncInSharedPrefs() { - val url = Utilities.getUrl() - val regex = Regex("^(https?://).*?@(.*?):") - val matchResult = regex.find(url) - - val extractedUrl = if (matchResult != null) { - val protocol = matchResult.groupValues[1] - val address = matchResult.groupValues[2] - "$protocol$address" - } else { - null - } - - 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" - ) - lifecycleScope.launch { - Log.d("URLSync", "Original URL being processed: $url") - Log.d("URLSync", "Extracted base URL: $extractedUrl") - - // Find the first matching URL in serverMappings - val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } - - if (primaryUrlMapping != null) { - val primaryUrl = primaryUrlMapping.key - val alternativeUrl = primaryUrlMapping.value - - // Log the mapped URLs - Log.d("URLSync", "Mapped Primary URL: $primaryUrl") - Log.d("URLSync", "Mapped Alternative URL: $alternativeUrl") - - // Check primary URL first - Log.d("URLSync", "Attempting to reach primary URL: ${Utilities.getUrl()}") - val isPrimaryReachable = isServerReachable(Utilities.getUrl()) - - if (isPrimaryReachable) { - Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") -// processUrlAndStartUpload(Utilities.getUrl()) - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") - - val uri = Uri.parse(alternativeUrl) - var couchdbURL: String - val urlUser: String - val urlPwd: String - if (alternativeUrl.contains("@")) { - val userinfo = getUserInfo(uri) - urlUser = userinfo[0] - urlPwd = userinfo[1] - couchdbURL = alternativeUrl - } else { - urlUser = "satellite" - urlPwd = settings.getString("serverPin", "") ?: "" - couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" - } - - // If primary URL is not reachable, try alternative URL - Log.d("URLSync", "Attempting to reach alternative 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.putString("alternativeUrl", url) - editor.putString("processedAlternativeUrl", couchdbURL) - editor.putBoolean("isAlternativeUrl", true) - editor.apply() - val isAlternativeReachable = isServerReachable(couchdbURL) - - if (isAlternativeReachable) { - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - // Neither primary nor alternative URL is reachable - Log.e("URLSync", "Both primary and alternative URLs are unreachable") - Log.e("URLSync", "Primary URL failed: $primaryUrl") - Log.e("URLSync", "Alternative URL failed: $alternativeUrl") - } + urlProcessor.processSyncURL( + onStartUpload = { source -> + startUpload(source) + }, + onCreateAction = { realm, id, type, action -> + createAction(realm, "${profileDbHandler.userModel?.id}", type, action) } - } else { - // If no mapping found, log and proceed with original URL - Log.w("URLSync", "No URL mapping found for: $extractedUrl") - Log.d("URLSync", "Proceeding with original URL") -// processUrlAndStartUpload(url) - startUpload("dashboard") - createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } + ) } } 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 239f52b842..ea078096b9 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 @@ -230,14 +230,17 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener { alert11.show() } - 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)}" + companion object { + 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 } - return ar } private fun saveUrlScheme(editor: SharedPreferences.Editor, uri: Uri, url: String?, couchdbURL: String?) { diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt new file mode 100644 index 0000000000..187557e412 --- /dev/null +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt @@ -0,0 +1,150 @@ +package org.ole.planet.myplanet.utilities + +import android.content.Context +import android.content.SharedPreferences +import android.net.Uri +import android.util.Log +import io.realm.Realm +import kotlinx.coroutines.CoroutineScope +import org.ole.planet.myplanet.BuildConfig +import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable +import org.ole.planet.myplanet.service.UserProfileDbHandler +import org.ole.planet.myplanet.ui.sync.ProcessUserDataActivity + +class URLProcessor(private val context: Context, private val lifecycleScope: CoroutineScope, private val settings: SharedPreferences, private val editor: SharedPreferences.Editor, private val mRealm: Realm, private val profileDbHandler: UserProfileDbHandler) { + companion object { + private const val TAG = "URLProcessor" + + private 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" + ) + } + + suspend fun processSyncURL(onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { + val startTime = System.currentTimeMillis() + val url = Utilities.getUrl() + Log.d(TAG, "Starting URL resolution process") + Log.d(TAG, "Original URL: $url") + + val extractedUrl = extractBaseUrl(url) + val primaryUrlMapping = findServerMapping(extractedUrl) + + if (primaryUrlMapping != null) { + handleMappedUrls(primaryUrlMapping, url, onStartUpload, onCreateAction) + } else { + Log.w(TAG, "No mapping found for URL: $extractedUrl, using original") + proceedWithOriginalUrl(url, onStartUpload, onCreateAction) + } + + val totalDuration = System.currentTimeMillis() - startTime + Log.d(TAG, "URL resolution process completed in ${totalDuration}ms") + } + + private fun extractBaseUrl(url: String): String? { + val regex = Regex("^(https?://).*?@(.*?):") + return regex.find(url)?.let { matchResult -> + val protocol = matchResult.groupValues[1] + val address = matchResult.groupValues[2] + "$protocol$address".also { + Log.d(TAG, "URL components extracted - Protocol: $protocol, Address: $address") + } + }.also { + if (it == null) Log.w(TAG, "Failed to extract URL components from: $url") + } + } + + private fun findServerMapping(extractedUrl: String?): Map.Entry? { + return serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } + .also { mapping -> + if (mapping != null) { + Log.d(TAG, "Found mapping - Primary: ${mapping.key}, Alternative: ${mapping.value}") + } + } + } + + private suspend fun handleMappedUrls(mapping: Map.Entry, originalUrl: String, onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { + val primaryUrl = mapping.key + val alternativeUrl = mapping.value + + val isPrimaryReachable = checkPrimaryUrl(Utilities.getUrl()) + if (isPrimaryReachable) { + Log.d(TAG, "Primary URL is reachable, proceeding with sync") + proceedWithOriginalUrl(originalUrl, onStartUpload, onCreateAction) + } else { + handleAlternativeUrl(alternativeUrl, originalUrl, onStartUpload, onCreateAction) + } + } + + private suspend fun checkPrimaryUrl(url: String): Boolean { + Log.d(TAG, "Testing primary URL reachability: $url") + val startTime = System.currentTimeMillis() + val isReachable = isServerReachable(url) + val duration = System.currentTimeMillis() - startTime + Log.d(TAG, "Primary URL check took ${duration}ms, Result: $isReachable") + return isReachable + } + + private suspend fun handleAlternativeUrl(alternativeUrl: String, originalUrl: String, onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { + Log.w(TAG, "Primary URL unreachable, attempting alternative") + val uri = Uri.parse(alternativeUrl) + Log.d(TAG, "Parsed alternative URI - Scheme: ${uri.scheme}, Host: ${uri.host}, Port: ${uri.port}") + + val (couchdbURL, urlUser, urlPwd) = processAlternativeUrl(uri, alternativeUrl) + saveUrlPreferences(uri, originalUrl, couchdbURL, urlUser, urlPwd) + + val isAlternativeReachable = checkAlternativeUrl(couchdbURL) + if (isAlternativeReachable) { + proceedWithOriginalUrl(originalUrl, onStartUpload, onCreateAction) + } else { + Log.e(TAG, "Both URLs are unreachable") + } + } + + private fun processAlternativeUrl(uri: Uri, alternativeUrl: String): Triple { + return if (alternativeUrl.contains("@")) { + Log.d(TAG, "Alternative URL contains credentials, extracting") + val userinfo = ProcessUserDataActivity.getUserInfo(uri) + Triple(alternativeUrl, userinfo[0], userinfo[1]) + } else { + Log.d(TAG, "Building alternative URL with default credentials") + val user = "satellite" + val pwd = settings.getString("serverPin", "") ?: "" + val url = "${uri.scheme}://$user:$pwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" + Triple(url, user, pwd) + } + } + + private fun saveUrlPreferences(uri: Uri, originalUrl: String, couchdbURL: String, urlUser: String, urlPwd: String) { + editor.apply { + putString("url_user", urlUser) + putString("url_pwd", urlPwd) + putString("url_Scheme", uri.scheme) + putString("url_Host", uri.host) + putString("alternativeUrl", originalUrl) + putString("processedAlternativeUrl", couchdbURL) + putBoolean("isAlternativeUrl", true) + apply() + } + Log.d(TAG, "Saved alternative URL settings to preferences") + } + + private suspend fun checkAlternativeUrl(url: String): Boolean { + Log.d(TAG, "Testing alternative URL reachability") + val startTime = System.currentTimeMillis() + val isReachable = isServerReachable(url) + val duration = System.currentTimeMillis() - startTime + Log.d(TAG, "Alternative URL check took ${duration}ms, Result: $isReachable") + return isReachable + } + + private fun proceedWithOriginalUrl(url: String, onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { + onStartUpload("dashboard") + onCreateAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } +} \ No newline at end of file From d93485af1e63cd9ebd4df6964f95984a0f1b4983 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 17 Dec 2024 20:46:45 +0300 Subject: [PATCH 09/14] resolve log error --- .../main/java/org/ole/planet/myplanet/ui/sync/SyncActivity.kt | 1 + 1 file changed, 1 insertion(+) 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 37129fe823..42299f6535 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 @@ -7,6 +7,7 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.text.* +import android.util.Log import android.view.* import android.webkit.URLUtil import android.widget.* From 54b08e2a2fb9472bbc6f2b1b3f4b0be7889d2764 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Thu, 19 Dec 2024 17:06:35 +0300 Subject: [PATCH 10/14] update urls --- app/build.gradle | 9 +++- .../planet/myplanet/datamanager/Service.kt | 41 ++++++++++--------- .../planet/myplanet/utilities/URLProcessor.kt | 9 +--- gradle.properties | 6 ++- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 300f5b24fd..c53bea96d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -87,10 +87,14 @@ android { def planetXelaPin = project.findProperty('PLANET_XELA_PIN') ?: "" def planetUriurUrl = project.findProperty('PLANET_URIUR_URL') ?: "" def planetUriurPin = project.findProperty('PLANET_URIUR_PIN') ?: "" + def planetUriurCloneUrl = project.findProperty('PLANET_URIUR_CLONE_URL') ?: "" + def planetUriurClonePin = project.findProperty('PLANET_URIUR_CLONE_PIN') ?: "" def planetRuiruUrl = project.findProperty('PLANET_RUIRU_URL') ?: "" def planetRuiruPin = project.findProperty('PLANET_RUIRU_PIN') ?: "" def planetEmbakasiUrl = project.findProperty('PLANET_EMBAKASI_URL') ?: "" def planetEmbakasiPin = project.findProperty('PLANET_EMBAKASI_PIN') ?: "" + def planetEmbakasiCloneUrl = project.findProperty('PLANET_EMBAKASI_CLONE_URL') ?: "" + def planetEmbakasiClonePin = project.findProperty('PLANET_EMBAKASI_CLONE_PIN') ?: "" def planetCambridgeUrl = project.findProperty('PLANET_CAMBRIDGE_URL') ?: "" def planetCambridgePin = project.findProperty('PLANET_CAMBRIDGE_PIN') ?: "" //def planetEgdirbmacUrl = project.findProperty('PLANET_EGDIRBMAC_URL') ?: "" @@ -98,7 +102,6 @@ android { def planetPalmBayUrl = project.findProperty('PLANET_PALMBAY_URL') ?: "" def planetPalmBayPin = project.findProperty('PLANET_PALMBAY_PIN') ?: "" - buildTypes.each { it.buildConfigField 'String', 'PLANET_LEARNING_URL', "\"$planetLearningUrl\"" it.buildConfigField 'String', 'PLANET_LEARNING_PIN', "\"${planetLearningPin}\"" @@ -116,10 +119,14 @@ android { it.buildConfigField 'String', 'PLANET_XELA_PIN', "\"${planetXelaPin}\"" it.buildConfigField 'String', 'PLANET_URIUR_URL', "\"${planetUriurUrl}\"" it.buildConfigField 'String', 'PLANET_URIUR_PIN', "\"${planetUriurPin}\"" + it.buildConfigField 'String', 'PLANET_URIUR_CLONE_URL', "\"${planetUriurCloneUrl}\"" + it.buildConfigField 'String', 'PLANET_URIUR_CLONE_PIN', "\"${planetUriurClonePin}\"" it.buildConfigField 'String', 'PLANET_RUIRU_URL', "\"${planetRuiruUrl}\"" it.buildConfigField 'String', 'PLANET_RUIRU_PIN', "\"${planetRuiruPin}\"" it.buildConfigField 'String', 'PLANET_EMBAKASI_URL', "\"${planetEmbakasiUrl}\"" it.buildConfigField 'String', 'PLANET_EMBAKASI_PIN', "\"${planetEmbakasiPin}\"" + it.buildConfigField 'String', 'PLANET_EMBAKASI_CLONE_URL', "\"${planetEmbakasiCloneUrl}\"" + it.buildConfigField 'String', 'PLANET_EMBAKASI_CLONE_PIN', "\"${planetEmbakasiClonePin}\"" it.buildConfigField 'String', 'PLANET_CAMBRIDGE_URL', "\"${planetCambridgeUrl}\"" it.buildConfigField 'String', 'PLANET_CAMBRIDGE_PIN', "\"${planetCambridgePin}\"" //it.buildConfigField 'String', 'PLANET_EGDIRBMAC_URL', "\"${planetEgdirbmacUrl}\"" diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index c9471c4935..6aa7b26562 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -341,13 +341,8 @@ class Service(private val context: Context) { val urlsToTry = mutableListOf(url) 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" + "https://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", + "https://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}", ) // Add alternative URL from serverMappings if available @@ -476,13 +471,20 @@ class Service(private val context: Context) { context.getString(R.string.https_protocol) -> context.getString(R.string.device_couldn_t_reach_nation_server) else -> context.getString(R.string.device_couldn_t_reach_local_server) } - showAlertDialog(errorMessage, false) + withContext(Dispatchers.Main) { + showAlertDialog(errorMessage, false) + } } } } catch (e: Exception) { Log.e("PerformanceLog", "Exception in main process", e) activity.setSyncFailed(true) - showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) + withContext(Dispatchers.Main) { + showAlertDialog( + context.getString(R.string.device_couldn_t_reach_local_server), + false + ) + } } finally { customProgressDialog.dismiss() Log.d("PerformanceLog", "Total process time: ${System.currentTimeMillis() - overallStartTime}ms") @@ -638,18 +640,19 @@ class Service(private val context: Context) { } fun showAlertDialog(message: String?, playStoreRedirect: Boolean) { - val builder = AlertDialog.Builder(context, R.style.CustomAlertDialog) - builder.setMessage(message) - builder.setCancelable(true) - builder.setNegativeButton(R.string.okay) { - dialog: DialogInterface, _: Int -> - if (playStoreRedirect) { - Utilities.openPlayStore() + applicationScope.launch(Dispatchers.Main) { + val builder = AlertDialog.Builder(context, R.style.CustomAlertDialog) + builder.setMessage(message) + builder.setCancelable(true) + builder.setNegativeButton(R.string.okay) { dialog: DialogInterface, _: Int -> + if (playStoreRedirect) { + Utilities.openPlayStore() + } + dialog.cancel() } - dialog.cancel() + val alert = builder.create() + alert.show() } - val alert = builder.create() - alert.show() } private fun getUrl(couchdbURL: String): String { diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt index 187557e412..cff7bc7568 100644 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt @@ -16,13 +16,8 @@ class URLProcessor(private val context: Context, private val lifecycleScope: Cor private const val TAG = "URLProcessor" private 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" + "https://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", + "https://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}", ) } diff --git a/gradle.properties b/gradle.properties index 39f4d0c687..bf5a59d9ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,10 +39,14 @@ PLANET_XELA_URL=10.82.1.150 PLANET_XELA_PIN=4324 PLANET_URIUR_URL=planet.uriur.ole.org PLANET_URIUR_PIN=4025 +PLANET_URIUR_CLONE_URL=clone.uriur.ole.org +PLANET_URIUR_CLONE_PIN=4025 PLANET_RUIRU_URL=192.168.100.178 PLANET_RUIRU_PIN=8925 PLANET_EMBAKASI_URL=planet.embakasi.ole.org -PLANET_EMBAKASI_PIN=8658 +PLANET_EMBAKASI_PIN=1848 +PLANET_EMBAKASI_CLONE_URL=clone.embakasi.ole.org +PLANET_EMBAKASI_CLONE_PIN=1848 PLANET_CAMBRIDGE_URL=192.168.68.126 PLANET_CAMBRIDGE_PIN=6407 # took egdirbmac cause planet on cambridge is at 8080 From 2287202dfa78a165732a77e9027c6e56e1091d1e Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Fri, 20 Dec 2024 13:48:40 +0300 Subject: [PATCH 11/14] update urls --- gradle.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index bf5a59d9ef..06ec0f77c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -37,15 +37,15 @@ PLANET_VI_URL=planet.vi.ole.org PLANET_VI_PIN=0660 PLANET_XELA_URL=10.82.1.150 PLANET_XELA_PIN=4324 -PLANET_URIUR_URL=planet.uriur.ole.org +PLANET_URIUR_URL=192.168.1.68 PLANET_URIUR_PIN=4025 -PLANET_URIUR_CLONE_URL=clone.uriur.ole.org +PLANET_URIUR_CLONE_URL=uriur.planet.gt PLANET_URIUR_CLONE_PIN=4025 PLANET_RUIRU_URL=192.168.100.178 PLANET_RUIRU_PIN=8925 -PLANET_EMBAKASI_URL=planet.embakasi.ole.org +PLANET_EMBAKASI_URL=192.168.1.202 PLANET_EMBAKASI_PIN=1848 -PLANET_EMBAKASI_CLONE_URL=clone.embakasi.ole.org +PLANET_EMBAKASI_CLONE_URL=embakasi.planet.gt PLANET_EMBAKASI_CLONE_PIN=1848 PLANET_CAMBRIDGE_URL=192.168.68.126 PLANET_CAMBRIDGE_PIN=6407 From e00e76fc1a8660f09ab47c1665e5dba7d48f5333 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Mon, 6 Jan 2025 03:38:45 +0300 Subject: [PATCH 12/14] resolve sync fail caused by protocol --- .../main/java/org/ole/planet/myplanet/datamanager/Service.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index 6aa7b26562..ce82987a6d 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -341,8 +341,8 @@ class Service(private val context: Context) { val urlsToTry = mutableListOf(url) val serverMappings = mapOf( - "https://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", - "https://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}", + "http://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", + "http://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}", ) // Add alternative URL from serverMappings if available From 3951ea223a3ac6511e758c65171cc4d5695d1618 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Mon, 6 Jan 2025 04:55:11 +0300 Subject: [PATCH 13/14] resolve alternative url check and sync --- .../planet/myplanet/datamanager/Service.kt | 28 +-- .../ui/dashboard/DashboardActivity.kt | 50 ++++-- .../ui/dashboard/DashboardActivity.kt.lite | 50 ++++-- .../ui/sync/DashboardElementActivity.kt | 41 +++-- .../myplanet/utilities/ServerUrlMapper.kt | 169 ++++++++++++++++++ .../planet/myplanet/utilities/URLProcessor.kt | 145 --------------- 6 files changed, 269 insertions(+), 214 deletions(-) create mode 100644 app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt delete mode 100644 app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index ce82987a6d..4e1f314cfd 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -20,7 +20,6 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import okhttp3.ResponseBody -import org.ole.planet.myplanet.BuildConfig import org.ole.planet.myplanet.MainApplication import org.ole.planet.myplanet.MainApplication.Companion.applicationScope import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable @@ -45,6 +44,7 @@ import org.ole.planet.myplanet.utilities.JsonUtils import org.ole.planet.myplanet.utilities.NetworkUtils import org.ole.planet.myplanet.utilities.NetworkUtils.extractProtocol import org.ole.planet.myplanet.utilities.NetworkUtils.isNetworkConnectedFlow +import org.ole.planet.myplanet.utilities.ServerUrlMapper import org.ole.planet.myplanet.utilities.Sha256Utils import org.ole.planet.myplanet.utilities.Utilities import org.ole.planet.myplanet.utilities.VersionUtils @@ -337,19 +337,12 @@ class Service(private val context: Context) { val overallStartTime = System.currentTimeMillis() Log.d("PerformanceLog", "Starting getMinApk process") - // Create a list of URLs to try, starting with the original URL - val urlsToTry = mutableListOf(url) - - val serverMappings = mapOf( - "http://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", - "http://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}", - ) + val serverUrlMapper = ServerUrlMapper(context) + val mapping = serverUrlMapper.processUrl(url) - // Add alternative URL from serverMappings if available - serverMappings[url]?.let { alternativeUrl -> - urlsToTry.add(alternativeUrl) - Log.d("PerformanceLog", "Added alternative URL: $alternativeUrl") - } + // Create list of URLs to try + val urlsToTry = mutableListOf(url) + mapping.alternativeUrl?.let { urlsToTry.add(it) } // Use coroutine scope to perform concurrent URL checks applicationScope.launch { @@ -471,19 +464,14 @@ class Service(private val context: Context) { context.getString(R.string.https_protocol) -> context.getString(R.string.device_couldn_t_reach_nation_server) else -> context.getString(R.string.device_couldn_t_reach_local_server) } - withContext(Dispatchers.Main) { - showAlertDialog(errorMessage, false) - } + showAlertDialog(errorMessage, false) } } } catch (e: Exception) { Log.e("PerformanceLog", "Exception in main process", e) activity.setSyncFailed(true) withContext(Dispatchers.Main) { - showAlertDialog( - context.getString(R.string.device_couldn_t_reach_local_server), - false - ) + showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) } } finally { customProgressDialog.dismiss() diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt index 4d7b88cf7f..61dd1b171d 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt @@ -7,9 +7,11 @@ import android.content.res.Configuration import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable +import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper +import android.util.Log import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback @@ -80,8 +82,9 @@ import org.ole.planet.myplanet.utilities.FileUtils.totalAvailableMemoryRatio import org.ole.planet.myplanet.utilities.KeyboardUtils.setupUI import org.ole.planet.myplanet.utilities.LocaleHelper import org.ole.planet.myplanet.utilities.MarkdownDialog +import org.ole.planet.myplanet.utilities.ServerUrlMapper import org.ole.planet.myplanet.utilities.TimeUtils.formatDate -import org.ole.planet.myplanet.utilities.URLProcessor +import org.ole.planet.myplanet.utilities.Utilities import org.ole.planet.myplanet.utilities.Utilities.toast import java.text.SimpleDateFormat import java.time.LocalDate @@ -127,14 +130,6 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N disableShiftMode(navigationView) activityDashboardBinding.appBarBell.bellToolbar.inflateMenu(R.menu.menu_bell_dashboard) tl = findViewById(R.id.tab_layout) - urlProcessor = URLProcessor( - context = this, - lifecycleScope = lifecycleScope, - settings = settings, - editor = editor, - mRealm = mRealm, - profileDbHandler = profileDbHandler - ) try { val userProfileModel = profileDbHandler.userModel @@ -184,15 +179,38 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N } activityDashboardBinding.appBarBell.ivSync.setOnClickListener { + val serverUrlMapper = ServerUrlMapper(this) + val url = Utilities.getUrl() + val mapping = serverUrlMapper.processUrl(url) + lifecycleScope.launch { - urlProcessor.processSyncURL( - onStartUpload = { source -> - startUpload(source) - }, - onCreateAction = { realm, id, type, action -> - createAction(realm, "${profileDbHandler.userModel?.id}", type, action) + val isPrimaryReachable = isServerReachable(Utilities.getUrl()) + + if (isPrimaryReachable) { + Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else if (mapping.alternativeUrl != null) { + Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") + val uri = Uri.parse(mapping.alternativeUrl) + + serverUrlMapper.updateUrlPreferences(editor, uri, mapping.alternativeUrl, url, settings) + val processedUrl = settings.getString("processedAlternativeUrl", "") + + Log.d("URLSync", "Attempting to reach alternative URL: $processedUrl") + val isAlternativeReachable = isServerReachable(processedUrl ?: "") + + if (isAlternativeReachable) { + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + Log.e("URLSync", "Both primary and alternative URLs are unreachable") } - ) + } else { + Log.d("URLSync", "Proceeding with original URL") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } } } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite index 491242afe7..a5f54fa87a 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite @@ -7,9 +7,11 @@ import android.content.res.Configuration import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable +import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper +import android.util.Log import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback @@ -80,8 +82,9 @@ import org.ole.planet.myplanet.utilities.FileUtils.totalAvailableMemoryRatio import org.ole.planet.myplanet.utilities.KeyboardUtils.setupUI import org.ole.planet.myplanet.utilities.LocaleHelper import org.ole.planet.myplanet.utilities.MarkdownDialog +import org.ole.planet.myplanet.utilities.ServerUrlMapper import org.ole.planet.myplanet.utilities.TimeUtils.formatDate -import org.ole.planet.myplanet.utilities.URLProcessor +import org.ole.planet.myplanet.utilities.Utilities import org.ole.planet.myplanet.utilities.Utilities.toast import java.text.SimpleDateFormat import java.time.LocalDate @@ -127,14 +130,6 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N disableShiftMode(navigationView) activityDashboardBinding.appBarBell.bellToolbar.inflateMenu(R.menu.menu_bell_dashboard) tl = findViewById(R.id.tab_layout) - urlProcessor = URLProcessor( - context = this, - lifecycleScope = lifecycleScope, - settings = settings, - editor = editor, - mRealm = mRealm, - profileDbHandler = profileDbHandler - ) try { val userProfileModel = profileDbHandler.userModel @@ -184,15 +179,38 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N } activityDashboardBinding.appBarBell.ivSync.setOnClickListener { + val serverUrlMapper = ServerUrlMapper(this) + val url = Utilities.getUrl() + val mapping = serverUrlMapper.processUrl(url) + lifecycleScope.launch { - urlProcessor.processSyncURL( - onStartUpload = { source -> - startUpload(source) - }, - onCreateAction = { realm, id, type, action -> - createAction(realm, "${profileDbHandler.userModel?.id}", type, action) + val isPrimaryReachable = isServerReachable(Utilities.getUrl()) + + if (isPrimaryReachable) { + Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else if (mapping.alternativeUrl != null) { + Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") + val uri = Uri.parse(mapping.alternativeUrl) + + serverUrlMapper.updateUrlPreferences(editor, uri, mapping.alternativeUrl, url, settings) + val processedUrl = settings.getString("processedAlternativeUrl", "") + + Log.d("URLSync", "Attempting to reach alternative URL: $processedUrl") + val isAlternativeReachable = isServerReachable(processedUrl ?: "") + + if (isAlternativeReachable) { + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } else { + Log.e("URLSync", "Both primary and alternative URLs are unreachable") } - ) + } else { + Log.d("URLSync", "Proceeding with original URL") + startUpload("dashboard") + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } } } 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 a6c64c5219..1719e0b932 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 @@ -20,9 +21,12 @@ import androidx.fragment.app.FragmentManager import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.android.material.bottomnavigation.BottomNavigationView +import io.realm.Realm import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.ole.planet.myplanet.R import org.ole.planet.myplanet.callback.OnRatingChangeListener import org.ole.planet.myplanet.model.RealmUserChallengeActions.Companion.createAction @@ -39,29 +43,21 @@ import org.ole.planet.myplanet.ui.team.TeamFragment import org.ole.planet.myplanet.utilities.Constants import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME import org.ole.planet.myplanet.utilities.Constants.showBetaFeature +import org.ole.planet.myplanet.utilities.ServerUrlMapper import org.ole.planet.myplanet.utilities.SharedPrefManager -import org.ole.planet.myplanet.utilities.URLProcessor +import org.ole.planet.myplanet.utilities.Utilities abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBackStackChangedListener { lateinit var navigationView: BottomNavigationView var doubleBackToExitPressedOnce = false private lateinit var goOnline: MenuItem var c = 0 - lateinit var urlProcessor: URLProcessor override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) profileDbHandler = UserProfileDbHandler(this) settings = applicationContext.getSharedPreferences(PREFS_NAME, MODE_PRIVATE) prefData = SharedPrefManager(this) - urlProcessor = URLProcessor( - context = this, - lifecycleScope = lifecycleScope, - settings = settings, - editor = editor, - mRealm = mRealm, - profileDbHandler = profileDbHandler - ) } fun onClickTabItems(position: Int) { @@ -157,15 +153,26 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack } fun logSyncInSharedPrefs() { + val serverUrlMapper = ServerUrlMapper(this, settings, editor) + val url = Utilities.getUrl() + lifecycleScope.launch { - urlProcessor.processSyncURL( - onStartUpload = { source -> - startUpload(source) - }, - onCreateAction = { realm, id, type, action -> - createAction(realm, "${profileDbHandler.userModel?.id}", type, action) + when (val result = serverUrlMapper.performUrlSync( + url = url, + onStartSync = { startUpload("dashboard") }, + onLogSync = { + createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") + } + )) { + is ServerUrlMapper.ConnectionResult.Success -> { + // Connection successful, sync operations completed } - ) + is ServerUrlMapper.ConnectionResult.Failure -> { + Log.e("URLSync", "Both primary and alternative URLs are unreachable") + Log.e("URLSync", "Primary URL failed: ${result.primaryUrl}") + Log.e("URLSync", "Alternative URL failed: ${result.alternativeUrl}") + } + } } } diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt new file mode 100644 index 0000000000..ebeeb3ee03 --- /dev/null +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt @@ -0,0 +1,169 @@ +package org.ole.planet.myplanet.utilities + +import android.content.Context +import android.content.SharedPreferences +import android.net.Uri +import android.util.Log +import org.ole.planet.myplanet.BuildConfig +import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable +import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME + +class ServerUrlMapper( + private val context: Context, + private val settings: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE), + private val editor: SharedPreferences.Editor = settings.edit() +) { + private val serverMappings = mapOf( + "http://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", + "http://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}" + ) + + val validUrls = listOf( + "https://${BuildConfig.PLANET_GUATEMALA_URL}", + "http://${BuildConfig.PLANET_XELA_URL}", + "http://${BuildConfig.PLANET_URIUR_URL}", + "http://${BuildConfig.PLANET_SANPABLO_URL}", + "http://${BuildConfig.PLANET_EMBAKASI_URL}", + "https://${BuildConfig.PLANET_VI_URL}" + ) + + data class UrlMapping( + val primaryUrl: String, + val alternativeUrl: String? = null, + val extractedBaseUrl: String? = null + ) + + private fun extractBaseUrl(url: String): String? { + val regex = Regex("^(https?://).*?@(.*?):") + return regex.find(url)?.let { + val protocol = it.groupValues[1] + val address = it.groupValues[2] + "$protocol$address" + } + } + + fun processUrl(url: String): UrlMapping { + val extractedUrl = extractBaseUrl(url) + Log.d("URLMapping", "Original URL being processed: $url") + Log.d("URLMapping", "Extracted base URL: $extractedUrl") + + val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } + + return if (primaryUrlMapping != null) { + val primaryUrl = primaryUrlMapping.key + val alternativeUrl = primaryUrlMapping.value + + Log.d("URLMapping", "Mapped Primary URL: $primaryUrl") + Log.d("URLMapping", "Mapped Alternative URL: $alternativeUrl") + + UrlMapping(url, alternativeUrl, extractedUrl) + } else { + Log.w("URLMapping", "No URL mapping found for: $extractedUrl") + UrlMapping(url, null, extractedUrl) + } + } + + fun updateUrlPreferences(editor: SharedPreferences.Editor, uri: Uri, alternativeUrl: String, url: String, settings: SharedPreferences) { + val urlUser: String + val urlPwd: String + + if (alternativeUrl.contains("@")) { + val userinfo = getUserInfo(uri) + urlUser = userinfo[0] + urlPwd = userinfo[1] + } else { + urlUser = "satellite" + urlPwd = settings.getString("serverPin", "") ?: "" + } + + val couchdbURL = if (alternativeUrl.contains("@")) { + alternativeUrl + } else { + "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" + } + + editor.apply { + putString("url_user", urlUser) + putString("url_pwd", urlPwd) + putString("url_Scheme", uri.scheme) + putString("url_Host", uri.host) + putString("alternativeUrl", url) + putString("processedAlternativeUrl", couchdbURL) + putBoolean("isAlternativeUrl", true) + apply() + } + } + + private fun getUserInfo(uri: Uri): Array { + val defaultInfo = arrayOf("", "") + val info = uri.userInfo?.split(":")?.dropLastWhile { it.isEmpty() }?.toTypedArray() + + return if ((info?.size ?: 0) > 1) { + arrayOf(info!![0], info[1]) + } else { + defaultInfo + } + } + + sealed class ConnectionResult { + data class Success(val url: String) : ConnectionResult() + data class Failure(val primaryUrl: String, val alternativeUrl: String? = null) : ConnectionResult() + } + + suspend fun performUrlSync(url: String, onStartSync: () -> Unit, onLogSync: () -> Unit): ConnectionResult { + val mapping = processUrl(url) + + // Try primary URL first + Log.d(TAG, "Attempting to reach primary URL: $url") + val isPrimaryReachable = isServerReachable(url) + + if (isPrimaryReachable) { + Log.d(TAG, "Successfully reached primary URL: $url") + onStartSync() + onLogSync() + return ConnectionResult.Success(url) + } + + // If primary fails and we have an alternative, try that + if (mapping.alternativeUrl != null) { + Log.w(TAG, "Failed to reach primary URL: $url") + val uri = Uri.parse(mapping.alternativeUrl) + updateUrlPreferences(editor, uri, mapping.alternativeUrl, url, settings) + + val processedUrl = settings.getString("processedAlternativeUrl", "") + if (!processedUrl.isNullOrEmpty()) { + Log.d(TAG, "Attempting to reach alternative URL: $processedUrl") + val isAlternativeReachable = isServerReachable(processedUrl) + + if (isAlternativeReachable) { + onStartSync() + onLogSync() + return ConnectionResult.Success(processedUrl) + } + } + + return ConnectionResult.Failure(url, mapping.alternativeUrl) + } + + // If no alternative URL exists, try original URL one last time + Log.d(TAG, "No alternative URL available, proceeding with original URL") + onStartSync() + onLogSync() + return ConnectionResult.Success(url) + } + + fun createAuthenticatedUrl(baseUrl: String): String { + val uri = Uri.parse(baseUrl) + return if (baseUrl.contains("@")) { + baseUrl + } else { + val urlUser = "satellite" + val urlPwd = settings.getString("serverPin", "") ?: "" + "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" + } + } + + companion object { + private const val TAG = "ServerUrlMapper" + } +} diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt deleted file mode 100644 index cff7bc7568..0000000000 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/URLProcessor.kt +++ /dev/null @@ -1,145 +0,0 @@ -package org.ole.planet.myplanet.utilities - -import android.content.Context -import android.content.SharedPreferences -import android.net.Uri -import android.util.Log -import io.realm.Realm -import kotlinx.coroutines.CoroutineScope -import org.ole.planet.myplanet.BuildConfig -import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable -import org.ole.planet.myplanet.service.UserProfileDbHandler -import org.ole.planet.myplanet.ui.sync.ProcessUserDataActivity - -class URLProcessor(private val context: Context, private val lifecycleScope: CoroutineScope, private val settings: SharedPreferences, private val editor: SharedPreferences.Editor, private val mRealm: Realm, private val profileDbHandler: UserProfileDbHandler) { - companion object { - private const val TAG = "URLProcessor" - - private val serverMappings = mapOf( - "https://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", - "https://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}", - ) - } - - suspend fun processSyncURL(onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { - val startTime = System.currentTimeMillis() - val url = Utilities.getUrl() - Log.d(TAG, "Starting URL resolution process") - Log.d(TAG, "Original URL: $url") - - val extractedUrl = extractBaseUrl(url) - val primaryUrlMapping = findServerMapping(extractedUrl) - - if (primaryUrlMapping != null) { - handleMappedUrls(primaryUrlMapping, url, onStartUpload, onCreateAction) - } else { - Log.w(TAG, "No mapping found for URL: $extractedUrl, using original") - proceedWithOriginalUrl(url, onStartUpload, onCreateAction) - } - - val totalDuration = System.currentTimeMillis() - startTime - Log.d(TAG, "URL resolution process completed in ${totalDuration}ms") - } - - private fun extractBaseUrl(url: String): String? { - val regex = Regex("^(https?://).*?@(.*?):") - return regex.find(url)?.let { matchResult -> - val protocol = matchResult.groupValues[1] - val address = matchResult.groupValues[2] - "$protocol$address".also { - Log.d(TAG, "URL components extracted - Protocol: $protocol, Address: $address") - } - }.also { - if (it == null) Log.w(TAG, "Failed to extract URL components from: $url") - } - } - - private fun findServerMapping(extractedUrl: String?): Map.Entry? { - return serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } - .also { mapping -> - if (mapping != null) { - Log.d(TAG, "Found mapping - Primary: ${mapping.key}, Alternative: ${mapping.value}") - } - } - } - - private suspend fun handleMappedUrls(mapping: Map.Entry, originalUrl: String, onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { - val primaryUrl = mapping.key - val alternativeUrl = mapping.value - - val isPrimaryReachable = checkPrimaryUrl(Utilities.getUrl()) - if (isPrimaryReachable) { - Log.d(TAG, "Primary URL is reachable, proceeding with sync") - proceedWithOriginalUrl(originalUrl, onStartUpload, onCreateAction) - } else { - handleAlternativeUrl(alternativeUrl, originalUrl, onStartUpload, onCreateAction) - } - } - - private suspend fun checkPrimaryUrl(url: String): Boolean { - Log.d(TAG, "Testing primary URL reachability: $url") - val startTime = System.currentTimeMillis() - val isReachable = isServerReachable(url) - val duration = System.currentTimeMillis() - startTime - Log.d(TAG, "Primary URL check took ${duration}ms, Result: $isReachable") - return isReachable - } - - private suspend fun handleAlternativeUrl(alternativeUrl: String, originalUrl: String, onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { - Log.w(TAG, "Primary URL unreachable, attempting alternative") - val uri = Uri.parse(alternativeUrl) - Log.d(TAG, "Parsed alternative URI - Scheme: ${uri.scheme}, Host: ${uri.host}, Port: ${uri.port}") - - val (couchdbURL, urlUser, urlPwd) = processAlternativeUrl(uri, alternativeUrl) - saveUrlPreferences(uri, originalUrl, couchdbURL, urlUser, urlPwd) - - val isAlternativeReachable = checkAlternativeUrl(couchdbURL) - if (isAlternativeReachable) { - proceedWithOriginalUrl(originalUrl, onStartUpload, onCreateAction) - } else { - Log.e(TAG, "Both URLs are unreachable") - } - } - - private fun processAlternativeUrl(uri: Uri, alternativeUrl: String): Triple { - return if (alternativeUrl.contains("@")) { - Log.d(TAG, "Alternative URL contains credentials, extracting") - val userinfo = ProcessUserDataActivity.getUserInfo(uri) - Triple(alternativeUrl, userinfo[0], userinfo[1]) - } else { - Log.d(TAG, "Building alternative URL with default credentials") - val user = "satellite" - val pwd = settings.getString("serverPin", "") ?: "" - val url = "${uri.scheme}://$user:$pwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" - Triple(url, user, pwd) - } - } - - private fun saveUrlPreferences(uri: Uri, originalUrl: String, couchdbURL: String, urlUser: String, urlPwd: String) { - editor.apply { - putString("url_user", urlUser) - putString("url_pwd", urlPwd) - putString("url_Scheme", uri.scheme) - putString("url_Host", uri.host) - putString("alternativeUrl", originalUrl) - putString("processedAlternativeUrl", couchdbURL) - putBoolean("isAlternativeUrl", true) - apply() - } - Log.d(TAG, "Saved alternative URL settings to preferences") - } - - private suspend fun checkAlternativeUrl(url: String): Boolean { - Log.d(TAG, "Testing alternative URL reachability") - val startTime = System.currentTimeMillis() - val isReachable = isServerReachable(url) - val duration = System.currentTimeMillis() - startTime - Log.d(TAG, "Alternative URL check took ${duration}ms, Result: $isReachable") - return isReachable - } - - private fun proceedWithOriginalUrl(url: String, onStartUpload: (String) -> Unit, onCreateAction: (Realm, String?, String?, String) -> Unit) { - onStartUpload("dashboard") - onCreateAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } -} \ No newline at end of file From 4119195fce7ad3090f11e81028f5aaa43a077a43 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Wed, 8 Jan 2025 16:46:58 +0300 Subject: [PATCH 14/14] cleanup --- .../planet/myplanet/datamanager/Service.kt | 197 ++---------------- .../planet/myplanet/service/SyncManager.kt | 2 - .../service/TransactionSyncManager.kt | 4 - .../ui/dashboard/DashboardActivity.kt | 8 - .../ui/dashboard/DashboardActivity.kt.lite | 8 - .../ui/sync/DashboardElementActivity.kt | 8 +- .../planet/myplanet/ui/sync/SyncActivity.kt | 12 -- .../myplanet/utilities/ServerUrlMapper.kt | 54 +---- .../planet/myplanet/utilities/Utilities.kt | 2 - 9 files changed, 23 insertions(+), 272 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt index 4e1f314cfd..c710a93d61 100644 --- a/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt +++ b/app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt @@ -6,7 +6,6 @@ import android.content.DialogInterface import android.content.SharedPreferences import android.net.Uri import android.text.TextUtils -import android.util.Log import com.google.gson.Gson import com.google.gson.JsonObject import io.realm.Realm @@ -21,7 +20,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import okhttp3.ResponseBody import org.ole.planet.myplanet.MainApplication -import org.ole.planet.myplanet.MainApplication.Companion.applicationScope import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable import org.ole.planet.myplanet.R import org.ole.planet.myplanet.callback.SuccessListener @@ -106,7 +104,6 @@ class Service(private val context: Context) { } fun checkVersion(callback: CheckVersionCallback, settings: SharedPreferences) { - Log.d("Service", "checkVersion: ${Utilities.getUpdateUrl(settings)}") if (!settings.getBoolean("isAlternativeUrl", false)){ if (settings.getString("couchdbURL", "")?.isEmpty() == true) { callback.onError(context.getString(R.string.config_not_available), true) @@ -120,10 +117,8 @@ class Service(private val context: Context) { if (response.body() != null) { val p = response.body() preferences.edit().putString("versionDetail", Gson().toJson(response.body())).apply() - Log.d("Service", "checkVersion onResponse: ${response.body()}") retrofitInterface.getApkVersion(Utilities.getApkVersionUrl(settings)).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { - Log.d("Service", "getApkVersion onResponse: $response") val responses: String? try { responses = Gson().fromJson(response.body()?.string(), String::class.java) @@ -150,7 +145,6 @@ class Service(private val context: Context) { if (p != null) { if (currentVersion < p.minapkcode && apkVersion < p.minapkcode) { callback.onUpdateAvailable(p, true) - Log.d("Service", "checkVersion: Planet up to date") } else { callback.onError("Planet up to date", false) } @@ -175,15 +169,12 @@ class Service(private val context: Context) { } fun isPlanetAvailable(callback: PlanetAvailableListener?) { - Log.d("Service", "isPlanetAvailable: ${Utilities.getUpdateUrl(preferences)}") retrofitInterface?.isPlanetAvailable(Utilities.getUpdateUrl(preferences))?.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { if (callback != null && response.code() == 200) { callback.isAvailable() - Log.d("Service", "isAvailable: true") } else { callback?.notAvailable() - Log.d("Service", "isAvailable: false") } } @@ -334,81 +325,52 @@ class Service(private val context: Context) { } fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) { - val overallStartTime = System.currentTimeMillis() - Log.d("PerformanceLog", "Starting getMinApk process") - val serverUrlMapper = ServerUrlMapper(context) val mapping = serverUrlMapper.processUrl(url) - // Create list of URLs to try val urlsToTry = mutableListOf(url) mapping.alternativeUrl?.let { urlsToTry.add(it) } - // Use coroutine scope to perform concurrent URL checks - applicationScope.launch { - val dialogStartTime = System.currentTimeMillis() + MainApplication.applicationScope.launch { val customProgressDialog = withContext(Dispatchers.Main) { CustomProgressDialog(context).apply { setText(context.getString(R.string.check_apk_version)) show() } } - Log.d("PerformanceLog", "Dialog creation took: ${System.currentTimeMillis() - dialogStartTime}ms") try { - // Use withContext(Dispatchers.IO) for network operations - val networkStartTime = System.currentTimeMillis() val result = withContext(Dispatchers.IO) { - // Create a list of deferred jobs for concurrent network calls val deferredResults = urlsToTry.map { currentUrl -> async { try { - val urlStartTime = System.currentTimeMillis() - Log.d("PerformanceLog", "Starting check for URL: $currentUrl") - - // Check versions concurrently - val versionCheckStartTime = System.currentTimeMillis() - val versionsResponse = try { - Log.d("NetworkLog", "Attempting to connect to $currentUrl/versions") - val response = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() - val checkDuration = System.currentTimeMillis() - versionCheckStartTime - Log.d("PerformanceLog", "Version check for $currentUrl took: ${checkDuration}ms") - - if (checkDuration >= 60000) { - Log.w("NetworkLog", "Connection to $currentUrl took excessive time (${checkDuration}ms)") + val versionsResponse = + try { + val response = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() + response + } catch (e: java.net.ConnectException) { + e.printStackTrace() + null + } catch (e: java.net.SocketTimeoutException) { + e.printStackTrace() + null + } catch (e: Exception) { + e.printStackTrace() + null } - response - } catch (e: java.net.ConnectException) { - Log.e("NetworkLog", "Connection failed for $currentUrl: ${e.message}") - Log.d("NetworkLog", "Moving to next URL in fallback list") - null - } catch (e: java.net.SocketTimeoutException) { - Log.e("NetworkLog", "Connection timed out for $currentUrl: ${e.message}") - Log.d("NetworkLog", "Moving to next URL in fallback list") - null - } catch (e: Exception) { - Log.e("NetworkLog", "Unexpected error connecting to $currentUrl", e) - Log.d("NetworkLog", "Moving to next URL in fallback list") - null - } if (versionsResponse?.isSuccessful == true) { val jsonObject = versionsResponse.body() val currentVersion = "${context.resources.getText(R.string.app_version)}" val minApkVersion = jsonObject?.get("minapk")?.asString - Log.d("PerformanceLog", "Version parsing successful for $currentUrl") - // Version check if (minApkVersion != null && isVersionAllowed(currentVersion, minApkVersion)) { - // Perform configuration check for this URL - val configStartTime = System.currentTimeMillis() val uri = Uri.parse(currentUrl) val couchdbURL = if (currentUrl.contains("@")) { getUserInfo(uri) currentUrl } else { val urlUser = "satellite" - Log.d("okuro", "called") "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" } @@ -417,7 +379,6 @@ class Service(private val context: Context) { } val configResponse = retrofitInterface?.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true")?.execute() - Log.d("PerformanceLog", "Configuration check for $currentUrl took: ${System.currentTimeMillis() - configStartTime}ms") if (configResponse?.isSuccessful == true) { val rows = configResponse.body()?.getAsJsonArray("rows") @@ -426,36 +387,27 @@ class Service(private val context: Context) { val id = firstRow.getAsJsonPrimitive("id").asString val doc = firstRow.getAsJsonObject("doc") val code = doc.getAsJsonPrimitive("code").asString - Log.d("PerformanceLog", "Total processing time for successful URL $currentUrl: ${System.currentTimeMillis() - urlStartTime}ms") return@async UrlCheckResult.Success(id, code, currentUrl) } } } } - Log.d("PerformanceLog", "URL $currentUrl failed after ${System.currentTimeMillis() - urlStartTime}ms") return@async UrlCheckResult.Failure(currentUrl) } catch (e: Exception) { - Log.e("PerformanceLog", "Exception while processing $currentUrl", e) + e.printStackTrace() return@async UrlCheckResult.Failure(currentUrl) } } } - - // Wait for the first successful result - val awaitStartTime = System.currentTimeMillis() val result = deferredResults.awaitFirst { it is UrlCheckResult.Success } - Log.d("PerformanceLog", "Awaiting first successful result took: ${System.currentTimeMillis() - awaitStartTime}ms") result } - Log.d("PerformanceLog", "Total network operations took: ${System.currentTimeMillis() - networkStartTime}ms") - // Handle the result when (result) { is UrlCheckResult.Success -> { val isAlternativeUrl = result.url != url listener?.onConfigurationIdReceived(result.id, result.code, result.url, isAlternativeUrl) activity.setSyncFailed(false) - Log.d("PerformanceLog", "Successfully connected to URL: ${result.url}") } is UrlCheckResult.Failure -> { activity.setSyncFailed(true) @@ -468,132 +420,17 @@ class Service(private val context: Context) { } } } catch (e: Exception) { - Log.e("PerformanceLog", "Exception in main process", e) + e.printStackTrace() activity.setSyncFailed(true) withContext(Dispatchers.Main) { showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) } } finally { customProgressDialog.dismiss() - Log.d("PerformanceLog", "Total process time: ${System.currentTimeMillis() - overallStartTime}ms") } } } -// fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) { -// // Create a list of URLs to try, starting with the original URL -// val urlsToTry = mutableListOf(url) -// -// 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" -// ) -// -// // Add alternative URL from serverMappings if available -// serverMappings[url]?.let { alternativeUrl -> -// urlsToTry.add(alternativeUrl) -// } -// -// // Use coroutine scope to perform concurrent URL checks -// applicationScope.launch { -// val customProgressDialog = withContext(Dispatchers.Main) { -// CustomProgressDialog(context).apply { -// setText(context.getString(R.string.check_apk_version)) -// show() -// } -// } -// -// try { -// // Use withContext(Dispatchers.IO) for network operations -// val result = withContext(Dispatchers.IO) { -// // Create a list of deferred jobs for concurrent network calls -// val deferredResults = urlsToTry.map { currentUrl -> -// async { -// try { -// Log.d("Service", "Checking URL: $currentUrl") -// // Check versions concurrently -// val versionsResponse = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute() -// -// if (versionsResponse?.isSuccessful == true) { -// val jsonObject = versionsResponse.body() -// val currentVersion = "${context.resources.getText(R.string.app_version)}" -// val minApkVersion = jsonObject?.get("minapk")?.asString -// Log.d("okuro", "first config check is successful") -// -// // Version check -// if (minApkVersion != null && isVersionAllowed(currentVersion, minApkVersion)) { -// // Perform configuration check for this URL -// val uri = Uri.parse(currentUrl) -// val couchdbURL = if (currentUrl.contains("@")) { -// getUserInfo(uri) -// currentUrl -// } else { -// val urlUser = "satellite" -// "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}" -// } -// withContext(Dispatchers.Main) { -// customProgressDialog.setText(context.getString(R.string.checking_server)) -// } -// val configResponse = retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").execute() -// -// if (configResponse.isSuccessful) { -// Log.d("okuro", "second config check is successful") -// val rows = configResponse.body()?.getAsJsonArray("rows") -// if (rows != null && rows.size() > 0) { -// val firstRow = rows.get(0).asJsonObject -// val id = firstRow.getAsJsonPrimitive("id").asString -// val doc = firstRow.getAsJsonObject("doc") -// val code = doc.getAsJsonPrimitive("code").asString -// return@async UrlCheckResult.Success(id, code, currentUrl) -// } -// } -// } -// } -// return@async UrlCheckResult.Failure(currentUrl) -// } catch (e: Exception) { -// e.printStackTrace() -// return@async UrlCheckResult.Failure(currentUrl) -// } -// } -// } -// -// // Wait for the first successful result -// deferredResults.awaitFirst { it is UrlCheckResult.Success } -// } -// -// // Handle the result -// when (result) { -// is UrlCheckResult.Success -> { -// val isAlternativeUrl = result.url != url -// listener?.onConfigurationIdReceived(result.id, result.code, result.url, isAlternativeUrl) -// activity.setSyncFailed(false) -// Log.d("Service", "Successfully connected to URL: ${result.url}") -// } -// is UrlCheckResult.Failure -> { -// activity.setSyncFailed(true) -// val errorMessage = when (extractProtocol(url)) { -// context.getString(R.string.http_protocol) -> context.getString(R.string.device_couldn_t_reach_local_server) -// context.getString(R.string.https_protocol) -> context.getString(R.string.device_couldn_t_reach_nation_server) -// else -> context.getString(R.string.device_couldn_t_reach_local_server) -// } -// showAlertDialog(errorMessage, false) -// } -// } -// } catch (e: Exception) { -// e.printStackTrace() -// activity.setSyncFailed(true) -// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false) -// } finally { -// customProgressDialog.dismiss() -// } -// } -// } - sealed class UrlCheckResult { data class Success(val id: String, val code: String, val url: String) : UrlCheckResult() data class Failure(val url: String) : UrlCheckResult() @@ -628,7 +465,7 @@ class Service(private val context: Context) { } fun showAlertDialog(message: String?, playStoreRedirect: Boolean) { - applicationScope.launch(Dispatchers.Main) { + MainApplication.applicationScope.launch(Dispatchers.Main) { val builder = AlertDialog.Builder(context, R.style.CustomAlertDialog) builder.setMessage(message) builder.setCancelable(true) diff --git a/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt b/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt index fa7c645fb8..4766a88e3f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt +++ b/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt @@ -5,7 +5,6 @@ import android.content.SharedPreferences import android.net.wifi.SupplicantState import android.net.wifi.WifiManager import android.text.TextUtils -import android.util.Log import com.google.gson.Gson import com.google.gson.JsonArray import com.google.gson.JsonNull @@ -77,7 +76,6 @@ class SyncManager private constructor(private val context: Context) { private fun authenticateAndSync() { td = Thread { - Log.d("authenticateAndSync", "${TransactionSyncManager.authenticate()}") if (TransactionSyncManager.authenticate()) { startSync() } else { diff --git a/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt b/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt index a61df45cde..607e118887 100644 --- a/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt +++ b/app/src/main/java/org/ole/planet/myplanet/service/TransactionSyncManager.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.SharedPreferences import android.text.TextUtils import android.util.Base64 -import android.util.Log import com.google.gson.Gson import com.google.gson.JsonArray import com.google.gson.JsonObject @@ -51,16 +50,13 @@ object TransactionSyncManager { fun authenticate(): Boolean { val apiInterface = client?.create(ApiInterface::class.java) try { - Log.d("TransactionSyncManager", "header: ${Utilities.header}, authenticate: ${Utilities.getUrl()}/tablet_users/_all_docs") val response: Response? = apiInterface?.getDocuments(Utilities.header, "${Utilities.getUrl()}/tablet_users/_all_docs")?.execute() - Log.d("TransactionSyncManager", "response: $response") if (response != null) { return response.code() == 200 } } catch (e: IOException) { e.printStackTrace() } - return false } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt index 61dd1b171d..c9b464334f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt @@ -11,7 +11,6 @@ import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper -import android.util.Log import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback @@ -130,7 +129,6 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N disableShiftMode(navigationView) activityDashboardBinding.appBarBell.bellToolbar.inflateMenu(R.menu.menu_bell_dashboard) tl = findViewById(R.id.tab_layout) - try { val userProfileModel = profileDbHandler.userModel if (userProfileModel != null) { @@ -187,27 +185,21 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N val isPrimaryReachable = isServerReachable(Utilities.getUrl()) if (isPrimaryReachable) { - Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } else if (mapping.alternativeUrl != null) { - Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") val uri = Uri.parse(mapping.alternativeUrl) serverUrlMapper.updateUrlPreferences(editor, uri, mapping.alternativeUrl, url, settings) val processedUrl = settings.getString("processedAlternativeUrl", "") - Log.d("URLSync", "Attempting to reach alternative URL: $processedUrl") val isAlternativeReachable = isServerReachable(processedUrl ?: "") if (isAlternativeReachable) { startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - Log.e("URLSync", "Both primary and alternative URLs are unreachable") } } else { - Log.d("URLSync", "Proceeding with original URL") startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite index a5f54fa87a..b1ef91f248 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite @@ -11,7 +11,6 @@ import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper -import android.util.Log import android.view.* import android.widget.TextView import androidx.activity.OnBackPressedCallback @@ -130,7 +129,6 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N disableShiftMode(navigationView) activityDashboardBinding.appBarBell.bellToolbar.inflateMenu(R.menu.menu_bell_dashboard) tl = findViewById(R.id.tab_layout) - try { val userProfileModel = profileDbHandler.userModel if (userProfileModel != null) { @@ -187,27 +185,21 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N val isPrimaryReachable = isServerReachable(Utilities.getUrl()) if (isPrimaryReachable) { - Log.d("URLSync", "Successfully reached primary URL: ${Utilities.getUrl()}") startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } else if (mapping.alternativeUrl != null) { - Log.w("URLSync", "Failed to reach primary URL: ${Utilities.getUrl()}") val uri = Uri.parse(mapping.alternativeUrl) serverUrlMapper.updateUrlPreferences(editor, uri, mapping.alternativeUrl, url, settings) val processedUrl = settings.getString("processedAlternativeUrl", "") - Log.d("URLSync", "Attempting to reach alternative URL: $processedUrl") val isAlternativeReachable = isServerReachable(processedUrl ?: "") if (isAlternativeReachable) { startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") - } else { - Log.e("URLSync", "Both primary and alternative URLs are unreachable") } } else { - Log.d("URLSync", "Proceeding with original URL") startUpload("dashboard") createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync") } 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 1719e0b932..8a09f3ba91 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,7 +10,6 @@ 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 @@ -21,12 +20,9 @@ import androidx.fragment.app.FragmentManager import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.android.material.bottomnavigation.BottomNavigationView -import io.realm.Realm import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import org.ole.planet.myplanet.R import org.ole.planet.myplanet.callback.OnRatingChangeListener import org.ole.planet.myplanet.model.RealmUserChallengeActions.Companion.createAction @@ -168,9 +164,7 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack // Connection successful, sync operations completed } is ServerUrlMapper.ConnectionResult.Failure -> { - Log.e("URLSync", "Both primary and alternative URLs are unreachable") - Log.e("URLSync", "Primary URL failed: ${result.primaryUrl}") - Log.e("URLSync", "Alternative URL failed: ${result.alternativeUrl}") + // Both primary and alternative URLs are unreachable } } } 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 42299f6535..9a685ca943 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 @@ -7,7 +7,6 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.text.* -import android.util.Log import android.view.* import android.webkit.URLUtil import android.widget.* @@ -113,10 +112,6 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers } override fun onConfigurationIdReceived(id: String, code: String, url: String, isAlternativeUrl: Boolean) { - Log.d("SyncActivity", "onConfigurationIdReceived: $id") - Log.d("SyncActivity", "onConfigurationIdReceived: $code") - Log.d("SyncActivity", "onConfigurationIdReceived: $url") - Log.d("SyncActivity", "onConfigurationIdReceived: $isAlternativeUrl") val savedId = settings.getString("configurationId", null) if (serverConfigAction == "sync") { if (savedId == null) { @@ -189,16 +184,12 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers } suspend fun isServerReachable(processedUrl: String?): Boolean { - Log.d("SyncActivity", "isServerReachable: $processedUrl") return withContext(Dispatchers.IO) { val apiInterface = client?.create(ApiInterface::class.java) try { - Log.d("SyncActivity", "isServerReachable: $processedUrl") val response = if (settings.getBoolean("isAlternativeUrl", false)){ - Log.d("okuro", "isAlternativeUrl true: $processedUrl/db/_all_dbs") apiInterface?.isPlanetAvailable("$processedUrl/db/_all_dbs")?.execute() } else { - Log.d("okuro", "isAlternativeUrl false: $processedUrl/db/_all_dbs") apiInterface?.isPlanetAvailable("$processedUrl/_all_dbs")?.execute() } @@ -771,7 +762,6 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers } else { processedUrl = saveConfigAndContinue(dialog) } - Log.d("SyncActivity", "continueSync: $processedUrl") if (TextUtils.isEmpty(processedUrl)) return isSync = true @@ -781,13 +771,11 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers Service(this).isPlanetAvailable(object : PlanetAvailableListener { override fun isAvailable() { Service(context).checkVersion(this@SyncActivity, settings) - Log.d("SyncActivity", "isAvailable: true") } override fun notAvailable() { if (!isFinishing) { syncFailed = true showAlert(context, "Error", getString(R.string.planet_server_not_reachable)) - Log.d("SyncActivity", "isAvailable: false") } } }) diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt index ebeeb3ee03..490d544e01 100644 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/ServerUrlMapper.kt @@ -3,30 +3,16 @@ package org.ole.planet.myplanet.utilities import android.content.Context import android.content.SharedPreferences import android.net.Uri -import android.util.Log import org.ole.planet.myplanet.BuildConfig -import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable +import org.ole.planet.myplanet.MainApplication import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME -class ServerUrlMapper( - private val context: Context, - private val settings: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE), - private val editor: SharedPreferences.Editor = settings.edit() -) { +class ServerUrlMapper(private val context: Context, private val settings: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE), private val editor: SharedPreferences.Editor = settings.edit()) { private val serverMappings = mapOf( "http://${BuildConfig.PLANET_URIUR_URL}" to "https://${BuildConfig.PLANET_URIUR_CLONE_URL}", "http://${BuildConfig.PLANET_EMBAKASI_URL}" to "https://${BuildConfig.PLANET_EMBAKASI_CLONE_URL}" ) - val validUrls = listOf( - "https://${BuildConfig.PLANET_GUATEMALA_URL}", - "http://${BuildConfig.PLANET_XELA_URL}", - "http://${BuildConfig.PLANET_URIUR_URL}", - "http://${BuildConfig.PLANET_SANPABLO_URL}", - "http://${BuildConfig.PLANET_EMBAKASI_URL}", - "https://${BuildConfig.PLANET_VI_URL}" - ) - data class UrlMapping( val primaryUrl: String, val alternativeUrl: String? = null, @@ -44,21 +30,13 @@ class ServerUrlMapper( fun processUrl(url: String): UrlMapping { val extractedUrl = extractBaseUrl(url) - Log.d("URLMapping", "Original URL being processed: $url") - Log.d("URLMapping", "Extracted base URL: $extractedUrl") val primaryUrlMapping = serverMappings.entries.find { it.key.contains(extractedUrl ?: "") } return if (primaryUrlMapping != null) { - val primaryUrl = primaryUrlMapping.key val alternativeUrl = primaryUrlMapping.value - - Log.d("URLMapping", "Mapped Primary URL: $primaryUrl") - Log.d("URLMapping", "Mapped Alternative URL: $alternativeUrl") - UrlMapping(url, alternativeUrl, extractedUrl) } else { - Log.w("URLMapping", "No URL mapping found for: $extractedUrl") UrlMapping(url, null, extractedUrl) } } @@ -113,27 +91,22 @@ class ServerUrlMapper( suspend fun performUrlSync(url: String, onStartSync: () -> Unit, onLogSync: () -> Unit): ConnectionResult { val mapping = processUrl(url) - // Try primary URL first - Log.d(TAG, "Attempting to reach primary URL: $url") - val isPrimaryReachable = isServerReachable(url) + val isPrimaryReachable = MainApplication.isServerReachable(url) if (isPrimaryReachable) { - Log.d(TAG, "Successfully reached primary URL: $url") onStartSync() onLogSync() return ConnectionResult.Success(url) } - // If primary fails and we have an alternative, try that if (mapping.alternativeUrl != null) { - Log.w(TAG, "Failed to reach primary URL: $url") + val uri = Uri.parse(mapping.alternativeUrl) updateUrlPreferences(editor, uri, mapping.alternativeUrl, url, settings) val processedUrl = settings.getString("processedAlternativeUrl", "") if (!processedUrl.isNullOrEmpty()) { - Log.d(TAG, "Attempting to reach alternative URL: $processedUrl") - val isAlternativeReachable = isServerReachable(processedUrl) + val isAlternativeReachable = MainApplication.isServerReachable(processedUrl) if (isAlternativeReachable) { onStartSync() @@ -145,25 +118,8 @@ class ServerUrlMapper( return ConnectionResult.Failure(url, mapping.alternativeUrl) } - // If no alternative URL exists, try original URL one last time - Log.d(TAG, "No alternative URL available, proceeding with original URL") onStartSync() onLogSync() return ConnectionResult.Success(url) } - - fun createAuthenticatedUrl(baseUrl: String): String { - val uri = Uri.parse(baseUrl) - return if (baseUrl.contains("@")) { - baseUrl - } else { - val urlUser = "satellite" - val urlPwd = settings.getString("serverPin", "") ?: "" - "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port}" - } - } - - companion object { - private const val TAG = "ServerUrlMapper" - } } diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt index fc3f5c7ea1..f6c9fa1aeb 100644 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/Utilities.kt @@ -116,8 +116,6 @@ object Utilities { val header: String get() { val settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - Log.d("Basic auth", "${settings.getString("url_user", "")}:${ settings.getString("url_pwd", "") }") - return "Basic ${Base64.encodeToString(("${settings.getString("url_user", "")}:${ settings.getString("url_pwd", "") }").toByteArray(), Base64.NO_WRAP)}" }