working history and back action

This commit is contained in:
Öppen 2020-08-15 21:20:15 +01:00
parent 49956456e0
commit 61199d91db
10 changed files with 157 additions and 78 deletions

6
.idea/vcs.xml Normal file
View File

@ -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>

View File

@ -11,6 +11,7 @@ const val GEMINI_SCHEME = "gemini"
class GeminiDatasource: Datasource{
private var last: URI? = null
override fun request(uri: URI, onUpdate: (state: TvaState) -> Unit) {
//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){
last = uri
val port = if(uri.port == -1) 1965 else uri.port
val sslContext = SSLContext.getInstance("TLSv1.2")

View File

@ -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)
}
}
}

View File

@ -8,7 +8,7 @@ interface CacheInterface {
companion object{
fun default(context: Context): CacheInterface{
return SimplePrefsCache(context)
return BasicCache(context)
}
}
}

View File

@ -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
}
}

View File

@ -13,6 +13,21 @@ class Tab(val index: Int) {
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{
fun new(index: Int, address: String): Tab {
val tab = Tab(index)

View File

@ -54,4 +54,13 @@ class TvaActivity : AppCompatActivity() {
binding.addressEdit.setText(state.uri.toString())
adapter.render(state.lines)
}
@ExperimentalStdlibApi
override fun onBackPressed() {
if(model.canGoBack()){
model.goBack()
}else{
super.onBackPressed()
}
}
}

View File

@ -59,4 +59,26 @@ class TvaViewModel: ViewModel() {
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)
}
}

View File

@ -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.paint.isUnderlineText = true
holder.itemView.gemtext_link.setOnClickListener {
onLink(getUri(lines[holder.adapterPosition]))
val uri = getUri(lines[holder.adapterPosition])
println("User click link: $uri")
onLink(uri)
}
}
}

View File

@ -75,13 +75,6 @@
</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.AppBarLayout>
@ -90,6 +83,9 @@
android:id="@+id/gemtext_recycler"
android:layout_width="match_parent"
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"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>