mirror of https://git.sr.ht/~oppen/ariane
working history and back action
This commit is contained in:
parent
49956456e0
commit
61199d91db
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -11,6 +11,7 @@ const val GEMINI_SCHEME = "gemini"
|
||||||
|
|
||||||
class GeminiDatasource: Datasource{
|
class GeminiDatasource: Datasource{
|
||||||
|
|
||||||
|
private var last: URI? = null
|
||||||
override fun request(uri: URI, onUpdate: (state: TvaState) -> Unit) {
|
override fun request(uri: URI, onUpdate: (state: TvaState) -> Unit) {
|
||||||
|
|
||||||
//Any inputted uri starting with a colon is an app-specific command, eg. :prefs :settings
|
//Any inputted uri starting with a colon is an app-specific command, eg. :prefs :settings
|
||||||
|
@ -29,7 +30,30 @@ class GeminiDatasource: Datasource{
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else -> onUpdate(TvaState.NotGeminiRequest(uri))
|
else -> {
|
||||||
|
val address = uri.toString()
|
||||||
|
when {
|
||||||
|
address.startsWith("//") -> {
|
||||||
|
//just missing protocol
|
||||||
|
request(URI.create("gemini:$address"), onUpdate)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
address.startsWith("/") -> {
|
||||||
|
//internal navigation
|
||||||
|
val internalNav = "gemini://${last?.host}$address"
|
||||||
|
request(URI.create(internalNav), onUpdate)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
!address.contains("://") -> {
|
||||||
|
//looks like a relative link
|
||||||
|
val lastAddress = last.toString()
|
||||||
|
val relAddress = "${lastAddress.substring(0, lastAddress.lastIndexOf("/") + 1)}$address"
|
||||||
|
request(URI.create(relAddress), onUpdate)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else -> onUpdate(TvaState.NotGeminiRequest(uri))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +63,7 @@ class GeminiDatasource: Datasource{
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private fun geminiRequest(uri: URI, onUpdate: (state: TvaState) -> Unit){
|
private fun geminiRequest(uri: URI, onUpdate: (state: TvaState) -> Unit){
|
||||||
|
last = uri
|
||||||
val port = if(uri.port == -1) 1965 else uri.port
|
val port = if(uri.port == -1) 1965 else uri.port
|
||||||
|
|
||||||
val sslContext = SSLContext.getInstance("TLSv1.2")
|
val sslContext = SSLContext.getInstance("TLSv1.2")
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package oppen.tva.io.history
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import java.net.URI
|
||||||
|
import kotlin.text.StringBuilder
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This is slow, unsafe, awful, and synchronous but I don't want get bogged down implementing Room just yet
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class BasicCache(context: Context): CacheInterface {
|
||||||
|
|
||||||
|
private val DELIM = "||"
|
||||||
|
private val prefsKey = "oppen.tva.io.history.BasicCache.PREFS_KEY"
|
||||||
|
private val prefsCacheKey = "oppen.tva.io.history.BasicCache.PREFS_CACHE_KEY"
|
||||||
|
private val prefsActiveIndexKey = "oppen.tva.io.history.BasicCache.PREFS_ACTIVE_INDEX_KEY"
|
||||||
|
private val prefs = context.getSharedPreferences(prefsKey, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
override fun update(tabs: List<Tab>, activeIndex: Int) {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
tabs.forEach { tab ->
|
||||||
|
sb.append("${tab.index}$DELIM")
|
||||||
|
tab.history.forEach { uri ->
|
||||||
|
sb.append("$uri$DELIM")
|
||||||
|
}
|
||||||
|
sb.append("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
val edit = prefs.edit()
|
||||||
|
val raw = sb.toString()
|
||||||
|
|
||||||
|
println("------------------------------------")
|
||||||
|
println(raw)
|
||||||
|
println("------------------------------------")
|
||||||
|
|
||||||
|
edit.putString(prefsCacheKey, sb.toString())
|
||||||
|
edit.putInt(prefsActiveIndexKey, activeIndex)
|
||||||
|
edit.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTabs(onTabs: (tabs: MutableList<Tab>, activeIndex: Int) -> Unit) {
|
||||||
|
val raw = prefs.getString(prefsCacheKey, null)
|
||||||
|
|
||||||
|
println("====================================")
|
||||||
|
println(raw)
|
||||||
|
println("====================================")
|
||||||
|
|
||||||
|
if (raw == null) {
|
||||||
|
onTabs(arrayListOf(), 0)
|
||||||
|
} else {
|
||||||
|
val activeIndex = prefs.getInt(prefsActiveIndexKey, 0)
|
||||||
|
val tabs = mutableListOf<Tab>()
|
||||||
|
raw.lines().forEach { line ->
|
||||||
|
if (line.trim().isNotEmpty()) {
|
||||||
|
val segs = line.split(DELIM)
|
||||||
|
val tabIndex = segs.first()
|
||||||
|
val tab = Tab(tabIndex.toInt())
|
||||||
|
for (index in 1 until segs.size) {
|
||||||
|
val address = segs[index]
|
||||||
|
if (address.isNotBlank()) {
|
||||||
|
tab.history.add(URI.create(address))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabs.add(tab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTabs(tabs, activeIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ interface CacheInterface {
|
||||||
|
|
||||||
companion object{
|
companion object{
|
||||||
fun default(context: Context): CacheInterface{
|
fun default(context: Context): CacheInterface{
|
||||||
return SimplePrefsCache(context)
|
return BasicCache(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
package oppen.tva.io.history
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This is a simple SharedPreferences based store for now because I don't want to get bogged down setting up Room at this point
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class SimplePrefsCache(context: Context): CacheInterface {
|
|
||||||
|
|
||||||
private val prefsKey = "oppen.tva.io.history.SimplePrefsCache.PREFS_KEY"
|
|
||||||
private val prefsCacheKey = "oppen.tva.io.history.SimplePrefsCache.PREFS_CACHE_KEY"
|
|
||||||
private val prefsActiveIndexKey = "oppen.tva.io.history.SimplePrefsCache.PREFS_ACTIVE_INDEX_KEY"
|
|
||||||
private val prefs = context.getSharedPreferences(prefsKey, Context.MODE_PRIVATE)
|
|
||||||
|
|
||||||
override fun getTabs(onTabs: (tabs: MutableList<Tab>, activeIndex: Int) -> Unit) {
|
|
||||||
val activeIndex = prefs.getInt(prefsActiveIndexKey, 0)
|
|
||||||
when (val rawJson = prefs.getString(prefsCacheKey, null)) {
|
|
||||||
null -> onTabs(arrayListOf(), activeIndex)
|
|
||||||
else -> {
|
|
||||||
val tabs = mutableListOf<Tab>()
|
|
||||||
val tabsJsonArray = JSONArray(rawJson)
|
|
||||||
val tabCount = tabsJsonArray.length()
|
|
||||||
for(index in 0 until tabCount){
|
|
||||||
val jsonTabObject = tabsJsonArray.getJSONObject(index)
|
|
||||||
val tabIndex = jsonTabObject.getInt("index")
|
|
||||||
val tab = Tab(tabIndex)
|
|
||||||
val jsonTabHistory = jsonTabObject.getJSONArray("history")
|
|
||||||
val historySize = jsonTabHistory.length()
|
|
||||||
for(historyIndex in 0 until historySize){
|
|
||||||
tab.add(jsonTabHistory.getString(historyIndex))
|
|
||||||
}
|
|
||||||
tabs.add(tab)
|
|
||||||
}
|
|
||||||
|
|
||||||
onTabs(tabs, activeIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(tabs: List<Tab>, activeIndex: Int) {
|
|
||||||
val edit = prefs.edit()
|
|
||||||
edit.putInt(prefsActiveIndexKey, activeIndex)
|
|
||||||
edit.putString(prefsCacheKey, tabsToJson(tabs))
|
|
||||||
edit.apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun tabsToJson(tabs: List<Tab>): String {
|
|
||||||
val jsonArray = JSONArray()
|
|
||||||
tabs.forEach { tab ->
|
|
||||||
val jsonTab = JSONObject()
|
|
||||||
jsonTab.put("index", tab.index)
|
|
||||||
|
|
||||||
val jsonHistoryArray = JSONArray()
|
|
||||||
tab.history.forEach { uri ->
|
|
||||||
jsonHistoryArray.put(uri.toString())
|
|
||||||
}
|
|
||||||
jsonTab.put("history", jsonHistoryArray)
|
|
||||||
jsonArray.put(jsonTab)
|
|
||||||
}
|
|
||||||
val rawJsonArray = jsonArray.toString(5)
|
|
||||||
println("Raw tabs json to store:\n$rawJsonArray")
|
|
||||||
return rawJsonArray
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,6 +13,21 @@ class Tab(val index: Int) {
|
||||||
history.add(URI.create(address))
|
history.add(URI.create(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPrevious(): URI? {
|
||||||
|
return when {
|
||||||
|
history.size > 1 -> {
|
||||||
|
history[history.size-2]
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun popHistory(){
|
||||||
|
history.dropLast(1)
|
||||||
|
}
|
||||||
|
|
||||||
companion object{
|
companion object{
|
||||||
fun new(index: Int, address: String): Tab {
|
fun new(index: Int, address: String): Tab {
|
||||||
val tab = Tab(index)
|
val tab = Tab(index)
|
||||||
|
|
|
@ -54,4 +54,13 @@ class TvaActivity : AppCompatActivity() {
|
||||||
binding.addressEdit.setText(state.uri.toString())
|
binding.addressEdit.setText(state.uri.toString())
|
||||||
adapter.render(state.lines)
|
adapter.render(state.lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
override fun onBackPressed() {
|
||||||
|
if(model.canGoBack()){
|
||||||
|
model.goBack()
|
||||||
|
}else{
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -59,4 +59,26 @@ class TvaViewModel: ViewModel() {
|
||||||
onState(state)
|
onState(state)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun canGoBack(): Boolean {
|
||||||
|
println("canGoBack()...")
|
||||||
|
tabs[activeTab].history.forEachIndexed{ index, uri ->
|
||||||
|
println("canGoBack history $index: $uri")
|
||||||
|
}
|
||||||
|
return tabs[activeTab].history.size > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
fun goBack(){
|
||||||
|
val previous = tabs[activeTab].getPrevious()
|
||||||
|
|
||||||
|
if(previous == null){
|
||||||
|
println("Previous history URI is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tabs[activeTab].history.removeLast()
|
||||||
|
cache.update(tabs, activeTab)
|
||||||
|
request(previous)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -81,7 +81,9 @@ class GemtextAdapter(val onLink: (link: URI) -> Unit): RecyclerView.Adapter<Gemt
|
||||||
holder.itemView.gemtext_text_textview.text = displayText
|
holder.itemView.gemtext_text_textview.text = displayText
|
||||||
holder.itemView.gemtext_text_textview.paint.isUnderlineText = true
|
holder.itemView.gemtext_text_textview.paint.isUnderlineText = true
|
||||||
holder.itemView.gemtext_link.setOnClickListener {
|
holder.itemView.gemtext_link.setOnClickListener {
|
||||||
onLink(getUri(lines[holder.adapterPosition]))
|
val uri = getUri(lines[holder.adapterPosition])
|
||||||
|
println("User click link: $uri")
|
||||||
|
onLink(uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,13 +75,6 @@
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<!-- <androidx.appcompat.widget.Toolbar-->
|
|
||||||
<!-- android:id="@+id/toolbar"-->
|
|
||||||
<!-- android:layout_width="match_parent"-->
|
|
||||||
<!-- android:layout_height="?attr/actionBarSize"-->
|
|
||||||
<!-- app:layout_collapseMode="pin"-->
|
|
||||||
<!-- app:popupTheme="@style/AppTheme.PopupOverlay" />-->
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
@ -90,6 +83,9 @@
|
||||||
android:id="@+id/gemtext_recycler"
|
android:id="@+id/gemtext_recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingTop="@dimen/default_margin"
|
||||||
|
android:paddingBottom="@dimen/default_margin"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
Loading…
Reference in New Issue