MainActivity: handle redirections

This commit is contained in:
dece 2021-12-13 16:14:41 +01:00
parent f8cfe2ad09
commit a6e910c3fa
2 changed files with 33 additions and 17 deletions

View file

@ -80,7 +80,12 @@ class MainActivity : AppCompatActivity(), ContentAdapter.ContentAdapterListen {
openUrl(url, base = if (currentUrl.isNotEmpty()) currentUrl else null) openUrl(url, base = if (currentUrl.isNotEmpty()) currentUrl else null)
} }
private fun openUrl(url: String, base: String? = null) { private fun openUrl(url: String, base: String? = null, redirections: Int = 0) {
if (redirections >= 5) {
alert("Too many redirections.")
return
}
var uri = Uri.parse(url) var uri = Uri.parse(url)
if (!uri.isAbsolute) { if (!uri.isAbsolute) {
uri = if (!base.isNullOrEmpty()) joinUrls(base, url) else toGeminiUri(uri) uri = if (!base.isNullOrEmpty()) joinUrls(base, url) else toGeminiUri(uri)
@ -120,24 +125,17 @@ class MainActivity : AppCompatActivity(), ContentAdapter.ContentAdapterListen {
Log.d(TAG, "handleEvent: $event") Log.d(TAG, "handleEvent: $event")
if (!event.handled) { if (!event.handled) {
when (event) { when (event) {
is PageViewModel.SuccessEvent -> { is PageViewModel.SuccessEvent -> visitedUrls.add(event.uri)
visitedUrls.add(event.uri) is PageViewModel.RedirectEvent -> openUrl(event.uri, redirections = event.redirects)
} is PageViewModel.FailureEvent -> alert(event.message)
is PageViewModel.FailureEvent -> {
alert(event.message)
}
} }
event.handled = true event.handled = true
} }
} }
private fun alert(message: String, title: String? = null) { private fun alert(message: String) {
val builder = AlertDialog.Builder(this) AlertDialog.Builder(this)
if (title != null) .setTitle(R.string.error_alert_title)
builder.setTitle(title)
else
builder.setTitle(title ?: R.string.alert_title)
builder
.setMessage(message) .setMessage(message)
.create() .create()
.show() .show()
@ -164,6 +162,7 @@ class MainActivity : AppCompatActivity(), ContentAdapter.ContentAdapterListen {
abstract class Event(var handled: Boolean = false) abstract class Event(var handled: Boolean = false)
data class SuccessEvent(val uri: String) : Event() data class SuccessEvent(val uri: String) : Event()
data class RedirectEvent(val uri: String, val redirects: Int) : Event()
data class FailureEvent(val message: String) : Event() data class FailureEvent(val message: String) : Event()
/** /**
@ -171,7 +170,7 @@ class MainActivity : AppCompatActivity(), ContentAdapter.ContentAdapterListen {
* *
* The URI must be valid, absolute and with a gemini scheme. * The URI must be valid, absolute and with a gemini scheme.
*/ */
fun sendGeminiRequest(uri: Uri) { fun sendGeminiRequest(uri: Uri, redirects: Int = 0) {
Log.d(TAG, "sendRequest: URI \"$uri\"") Log.d(TAG, "sendRequest: URI \"$uri\"")
state.postValue(State.CONNECTING) state.postValue(State.CONNECTING)
requestJob?.apply { if (isActive) cancel() } requestJob?.apply { if (isActive) cancel() }
@ -203,8 +202,9 @@ class MainActivity : AppCompatActivity(), ContentAdapter.ContentAdapterListen {
} }
Log.i(TAG, "sendRequest: got ${response.code} with meta \"${response.meta}\"") Log.i(TAG, "sendRequest: got ${response.code} with meta \"${response.meta}\"")
when (response.code) { when (response.code.getCategory()) {
Response.Code.SUCCESS -> handleRequestSuccess(response, uri) Response.Code.Category.SUCCESS -> handleRequestSuccess(response, uri)
Response.Code.Category.REDIRECT -> handleRedirect(response, redirects = redirects + 1)
else -> signalError("Can't handle code ${response.code}.") else -> signalError("Can't handle code ${response.code}.")
} }
} }
@ -241,6 +241,10 @@ class MainActivity : AppCompatActivity(), ContentAdapter.ContentAdapterListen {
event.postValue(SuccessEvent(uri.toString())) event.postValue(SuccessEvent(uri.toString()))
state.postValue(State.IDLE) state.postValue(State.IDLE)
} }
private fun handleRedirect(response: Response, redirects: Int) {
event.postValue(RedirectEvent(response.meta, redirects))
}
} }
companion object { companion object {

View file

@ -31,6 +31,18 @@ class Response(val code: Code, val meta: String, val data: Channel<ByteArray>) {
CERTIFICATE_NOT_AUTHORISED(61), CERTIFICATE_NOT_AUTHORISED(61),
CERTIFICATE_NOT_VALID(62); CERTIFICATE_NOT_VALID(62);
enum class Category(val value: Int) {
UNKNOWN(0),
INPUT(1),
SUCCESS(2),
REDIRECT(3),
SERVER_ERROR(4),
CLIENT_ERROR(5),
CERTIFICATE(6);
}
fun getCategory(): Category? = Category.values().associateBy(Category::value)[value / 10]
companion object { companion object {
private val MAP = values().associateBy(Code::value) private val MAP = values().associateBy(Code::value)
fun fromInt(type: Int) = MAP[type] fun fromInt(type: Int) = MAP[type]