Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiple urls #3612

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class MainApplication : Application(), Application.ActivityLifecycleCallbacks {
suspend fun isServerReachable(urlString: String): Boolean {
return try {
if (urlString.isBlank()) return false

val formattedUrl = if (!urlString.startsWith("http://") && !urlString.startsWith("https://")) {
"http://$urlString"
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.ole.planet.myplanet.ui.dashboard

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -17,6 +18,8 @@ import androidx.recyclerview.widget.RecyclerView
import io.realm.Case
import io.realm.Realm
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.filter
import org.ole.planet.myplanet.BuildConfig
import org.ole.planet.myplanet.R
import org.ole.planet.myplanet.databinding.FragmentHomeBellBinding
import org.ole.planet.myplanet.model.RealmCertification
Expand All @@ -33,14 +36,19 @@ import org.ole.planet.myplanet.ui.mylife.LifeFragment
import org.ole.planet.myplanet.ui.resources.ResourcesFragment
import org.ole.planet.myplanet.ui.submission.AdapterMySubmission
import org.ole.planet.myplanet.ui.submission.MySubmissionFragment
import org.ole.planet.myplanet.ui.sync.ProcessUserDataActivity
import org.ole.planet.myplanet.ui.team.TeamFragment
import org.ole.planet.myplanet.utilities.DialogUtils.guestDialog
import org.ole.planet.myplanet.utilities.TimeUtils
import java.util.Date
import java.util.concurrent.ConcurrentHashMap

class BellDashboardFragment : BaseDashboardFragment() {
private lateinit var fragmentHomeBellBinding: FragmentHomeBellBinding
private var networkStatusJob: Job? = null
private val serverCheckCache = ConcurrentHashMap<String, Long>()
private val cacheDuration = 5 * 60 * 1000L
private val serverCheckTimeout = 3000L
private val viewModel: BellDashboardViewModel by viewModels()
var user: RealmUserModel? = null

Expand All @@ -58,56 +66,127 @@ class BellDashboardFragment : BaseDashboardFragment() {
super.onViewCreated(view, savedInstanceState)
fragmentHomeBellBinding.cardProfileBell.txtDate.text = TimeUtils.formatDate(Date().time, "")
fragmentHomeBellBinding.cardProfileBell.txtCommunityName.text = model?.planetCode

setupNetworkStatusMonitoring()

(activity as DashboardActivity?)?.supportActionBar?.hide()
showBadges()
checkPendingSurveys()
}

private fun getOptimizedServerUrls(): List<String> {
val primaryServer = settings?.getString("serverURL", "")
val lastReachableServer = settings?.getString("last_reachable_server", "")

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"
)

return buildList {
// Add last reachable server if different from primary
if (lastReachableServer != null && lastReachableServer != primaryServer) {
add(lastReachableServer)
}

// Add primary server
if (primaryServer != null) {
add(primaryServer)
}

// Add ONLY the mapped fallback server for the primary server
serverMappings[primaryServer]?.let { fallbackServer ->
if (fallbackServer !in this) {
add(fallbackServer)
}
}
}
}

private suspend fun checkServerWithCache(url: String): Boolean {
val currentTime = System.currentTimeMillis()
return serverCheckCache[url]?.let { lastChecked ->
if (currentTime - lastChecked < cacheDuration) {
true
} else {
viewModel.checkServerConnection(url).also {
serverCheckCache[url] = currentTime
}
}
} ?: viewModel.checkServerConnection(url).also {
serverCheckCache[url] = currentTime
}
}

private fun setupNetworkStatusMonitoring() {
networkStatusJob?.cancel()
networkStatusJob = viewLifecycleOwner.lifecycleScope.launch {
networkStatusJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
var lastEmittedStatus: NetworkStatus? = null
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.networkStatus.collect { status ->
updateNetworkIndicator(status)
viewModel.networkStatus.filter { status ->
status != lastEmittedStatus.also {
lastEmittedStatus = status
}
}.collect { status ->
withContext(Dispatchers.Main) {
updateNetworkIndicator(status)
}
}
}
}
}

private suspend fun updateNetworkIndicator(status: NetworkStatus) {
if (!isAdded) return
val context = context ?: return
private suspend fun updateNetworkIndicator(status: NetworkStatus) = coroutineScope {
if (!isAdded || context == null) return@coroutineScope

when (status) {
is NetworkStatus.Disconnected -> {
fragmentHomeBellBinding.cardProfileBell.imageView.borderColor =
ContextCompat.getColor(context, R.color.md_red_700)
}
is NetworkStatus.Connecting -> {
fragmentHomeBellBinding.cardProfileBell.imageView.borderColor =
ContextCompat.getColor(context, R.color.md_yellow_600)

val serverUrl = settings?.getString("serverURL", "")
if (!serverUrl.isNullOrEmpty()) {
try {
val canReachServer = viewModel.checkServerConnection(serverUrl)
if (isAdded && view?.isAttachedToWindow == true) {
fragmentHomeBellBinding.cardProfileBell.imageView.borderColor =
ContextCompat.getColor(context, if (canReachServer) R.color.green else R.color.md_yellow_600)
}
} catch (e: Exception) {
e.printStackTrace()
if (isAdded && view?.isAttachedToWindow == true) {
fragmentHomeBellBinding.cardProfileBell.imageView.borderColor =
ContextCompat.getColor(context, R.color.md_yellow_600)
val serverUrls = getOptimizedServerUrls()

// Log the full list of servers being attempted
Log.d("NetworkIndicator", "Attempting to connect to servers in order: $serverUrls")

fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = ContextCompat.getColor(requireContext(), R.color.md_yellow_600)

val reachableServer = try {
withTimeout(serverCheckTimeout) {
serverUrls.firstNotNullOfOrNull { url ->
async {
Log.d("NetworkIndicator", "Checking server connection to: $url")
if (checkServerWithCache(url)) {
Log.d("NetworkIndicator", "Server successful: $url")
url
} else {
Log.d("NetworkIndicator", "Server failed: $url")
null
}
}
}.await()
}
}
is NetworkStatus.Connected -> {
fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = ContextCompat.getColor(context, R.color.green)
} catch (e: TimeoutCancellationException) {
Log.e("NetworkIndicator", "Server connection timeout", e)
null
}

reachableServer?.let {
editor?.putString("last_reachable_server", it)?.apply()
}

if (isAdded && view?.isAttachedToWindow == true) {
val colorRes = when {
reachableServer != null -> {
val processedUrl = ProcessUserDataActivity.setUrlParts(reachableServer, settings?.getString("serverPin", "") ?: "")
Log.d("BellDashboardFragment", "Server reachable: $processedUrl")
if (processedUrl.isNotEmpty()) R.color.green else R.color.md_red_700
}
status is NetworkStatus.Disconnected -> R.color.md_red_700
else -> R.color.md_yellow_600
}

fragmentHomeBellBinding.cardProfileBell.imageView.borderColor = ContextCompat.getColor(requireContext(), colorRes)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -122,6 +123,8 @@ abstract class DashboardElementActivity : SyncActivity(), FragmentManager.OnBack

fun logSyncInSharedPrefs() {
lifecycleScope.launch {
Log.d("DashboardActivity 1", "Syncing: ${Utilities.getUrl()}")
Log.d("DashboardActivity 2", "Syncing: ${isServerReachable(Utilities.getUrl())}")
if (isServerReachable(Utilities.getUrl())) {
startUpload("dashboard")
createAction(mRealm, "${profileDbHandler.userModel?.id}", null, "sync")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ class LoginActivity : SyncActivity(), TeamListAdapter.OnItemClickListener {
val editor = settings.edit()
editor.putString("loginUserName", name)
editor.putString("loginUserPassword", password)
val isLoggedIn = authenticateUser(settings, name, password, false)
val isLoggedIn = authenticateUser(name, password, false)
if (isLoggedIn) {
Toast.makeText(applicationContext, getString(R.string.thank_you), Toast.LENGTH_SHORT).show()
onLogin()
Expand All @@ -429,7 +429,7 @@ class LoginActivity : SyncActivity(), TeamListAdapter.OnItemClickListener {

override fun onSyncComplete() {
customProgressDialog?.dismiss()
val log = authenticateUser(settings, name, password, true)
val log = authenticateUser(name, password, true)
if (log) {
Toast.makeText(applicationContext, getString(R.string.thank_you), Toast.LENGTH_SHORT).show()
onLogin()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputLayout
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.ole.planet.myplanet.MainApplication.Companion.context
import org.ole.planet.myplanet.R
import org.ole.planet.myplanet.base.PermissionActivity
Expand All @@ -43,7 +38,6 @@ import org.ole.planet.myplanet.utilities.FileUtils.installApk
import kotlin.math.roundToInt

abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener {
lateinit var settings: SharedPreferences
var customProgressDialog: DialogUtils.CustomProgressDialog? = null

@JvmField
Expand Down Expand Up @@ -130,36 +124,58 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener {
}
}

fun setUrlParts(url: String, password: String): String {
val editor = settings.edit()
val uri = Uri.parse(url)
var couchdbURL: String
val urlUser: String
val urlPwd: String
if (url.contains("@")) {
val userinfo = getUserInfo(uri)
urlUser = userinfo[0]
urlPwd = userinfo[1]
couchdbURL = url
} else if (TextUtils.isEmpty(password)) {
showAlert(this, "", getString(R.string.pin_is_required))
return ""
} else {
urlUser = "satellite"
urlPwd = password
couchdbURL = uri.scheme + "://" + urlUser + ":" + urlPwd + "@" + uri.host + ":" + if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port
companion object {
lateinit var settings: SharedPreferences

fun setUrlParts(url: String, password: String): String {
val editor = settings.edit()
val uri = Uri.parse(url)
var couchdbURL: String
val urlUser: String
val urlPwd: String
if (url.contains("@")) {
val userinfo = getUserInfo(uri)
urlUser = userinfo[0]
urlPwd = userinfo[1]
couchdbURL = url
} else if (TextUtils.isEmpty(password)) {
showAlert(context, "", context.getString(R.string.pin_is_required))
return ""
} else {
urlUser = "satellite"
urlPwd = password
couchdbURL = "${uri.scheme}://$urlUser:$urlPwd@${uri.host}:${if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else "${uri.port}"}"
}
editor.putString("serverPin", password)
saveUrlScheme(editor, uri, url, couchdbURL)
editor.putString("url_user", urlUser)
editor.putString("url_pwd", urlPwd)
editor.putString("url_Scheme", uri.scheme)
editor.putString("url_Host", uri.host)
editor.apply()
if (!couchdbURL.endsWith("db")) {
couchdbURL += "/db"
}
return couchdbURL
}
editor.putString("serverPin", password)
saveUrlScheme(editor, uri, url, couchdbURL)
editor.putString("url_user", urlUser)
editor.putString("url_pwd", urlPwd)
editor.putString("url_Scheme", uri.scheme)
editor.putString("url_Host", uri.host)
editor.apply()
if (!couchdbURL.endsWith("db")) {
couchdbURL += "/db"

fun getUserInfo(uri: Uri): Array<String> {
val ar = arrayOf("", "")
val info = uri.userInfo?.split(":".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray()
if ((info?.size ?: 0) > 1) {
ar[0] = "${info?.get(0)}"
ar[1] = "${info?.get(1)}"
}
return ar
}

fun saveUrlScheme(editor: SharedPreferences.Editor, uri: Uri, url: String?, couchdbURL: String?) {
editor.putString("url_Scheme", uri.scheme)
editor.putString("url_Host", uri.host)
editor.putInt("url_Port", if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port)
editor.putString("serverURL", url)
editor.putString("couchdbURL", couchdbURL)
}
return couchdbURL
}

fun isUrlValid(url: String): Boolean {
Expand Down Expand Up @@ -208,7 +224,6 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener {
}

fun saveUserInfoPref(settings: SharedPreferences, password: String?, user: RealmUserModel) {
this.settings = settings
val editor = settings.edit()
editor.putString("userId", user.id)
editor.putString("name", user.name)
Expand All @@ -229,22 +244,4 @@ abstract class ProcessUserDataActivity : PermissionActivity(), SuccessListener {
val alert11 = builder1.create()
alert11.show()
}

private fun getUserInfo(uri: Uri): Array<String> {
val ar = arrayOf("", "")
val info = uri.userInfo?.split(":".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray()
if ((info?.size ?: 0) > 1) {
ar[0] = "${info?.get(0)}"
ar[1] = "${info?.get(1)}"
}
return ar
}

private fun saveUrlScheme(editor: SharedPreferences.Editor, uri: Uri, url: String?, couchdbURL: String?) {
editor.putString("url_Scheme", uri.scheme)
editor.putString("url_Host", uri.host)
editor.putInt("url_Port", if (uri.port == -1) (if (uri.scheme == "http") 80 else 443) else uri.port)
editor.putString("serverURL", url)
editor.putString("couchdbURL", couchdbURL)
}
}
Loading
Loading