Uri: add resolveLinkUri with tests

This commit is contained in:
dece 2022-02-16 11:06:26 +01:00
parent fcf12f09d2
commit fd5471b615
4 changed files with 61 additions and 15 deletions

View file

@ -1,14 +1,46 @@
package dev.lowrespalmtree.comet
import dev.lowrespalmtree.comet.utils.*
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
/** Test utils.Uri functions. Runs of the device due to the Uri functions being Android-only .*/
class UriUtilsTest {
@Test
fun resolveLinkUri() {
// Absolute URLs.
assertEquals(
"gemini://example.com/",
resolveLinkUri("gemini://example.com", "gemini://dece.space/").toString()
)
// Relative links.
assertEquals(
"gemini://example.com/",
resolveLinkUri(".", "gemini://example.com/").toString()
)
assertEquals(
"gemini://example.com/",
resolveLinkUri("..", "gemini://example.com/").toString()
)
assertEquals(
"gemini://example.com/page",
resolveLinkUri("./page", "gemini://example.com/").toString()
)
assertEquals(
"gemini://example.com/page",
resolveLinkUri("page", "gemini://example.com/").toString()
)
assertEquals(
"gemini://example.com/page.com",
resolveLinkUri("page.com", "gemini://example.com/").toString()
)
// Scheme-less URLs.
assertEquals(
"gemini://someone.smol.pub/somepage",
resolveLinkUri("//someone.smol.pub/somepage", "gemini://smol.pub/feed").toString()
)
}
@Test
fun joinUrls() {
assertEquals(

View file

@ -20,6 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import dev.lowrespalmtree.comet.databinding.FragmentPageViewBinding
import dev.lowrespalmtree.comet.utils.isConnectedToNetwork
import dev.lowrespalmtree.comet.utils.joinUrls
import dev.lowrespalmtree.comet.utils.resolveLinkUri
import dev.lowrespalmtree.comet.utils.toGeminiUri
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -107,13 +108,7 @@ class PageFragment : Fragment(), PageAdapter.Listener {
return
}
var uri = Uri.parse(url)
if (!uri.isAbsolute) {
uri = if (!base.isNullOrEmpty()) joinUrls(base, url) else toGeminiUri(uri)
} else if (uri.scheme == "gemini" && uri.path.isNullOrEmpty()) {
uri = uri.buildUpon().path("/").build()
}
val uri = resolveLinkUri(url, base)
when (uri.scheme) {
"gemini" -> vm.sendGeminiRequest(uri, requireContext())
else -> openUnknownScheme(uri)

View file

@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import dev.lowrespalmtree.comet.utils.joinUrls
import dev.lowrespalmtree.comet.utils.resolveLinkUri
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.onSuccess
import java.net.ConnectException
@ -163,9 +164,7 @@ class PageViewModel(@Suppress("unused") private val savedStateHandle: SavedState
lineChannelResult.onSuccess { line ->
if (line is LinkLine) {
// Mark visited links here as we have a access to the history.
val fullUrl =
if (Uri.parse(line.url).isAbsolute) line.url
else joinUrls(uriString, line.url).toString()
val fullUrl = resolveLinkUri(line.url, uriString).toString()
if (History.contains(fullUrl))
line.visited = true
}

View file

@ -2,6 +2,26 @@ package dev.lowrespalmtree.comet.utils
import android.net.Uri
/**
* Resolve the URI of a link found on a page.
*
* Links can take various forms: absolute links to a page on a capsule, relative links on the same
* capsule, but also fancy scheme-less absolute URLs (i.e. starting with "//") for cross-protocol
* linking. This function returns the resolved URI from any type of link, opt. using current URL.
*/
fun resolveLinkUri(url: String, base: String?): Uri {
var uri = Uri.parse(url)
if (!uri.isAbsolute) {
uri =
if (url.startsWith("//")) uri.buildUpon().scheme("gemini").build()
else if (!base.isNullOrEmpty()) joinUrls(base, url)
else toGeminiUri(uri)
} else if (uri.scheme == "gemini" && uri.path.isNullOrEmpty()) {
uri = uri.buildUpon().path("/").build()
}
return uri
}
/**
* Transform a relative URI to an absolute Gemini URI
*