mirror of
https://git.sr.ht/~oppen/ariane
synced 2024-12-21 23:44:30 +00:00
working history and back action
This commit is contained in:
parent
49956456e0
commit
61199d91db
10 changed files with 157 additions and 78 deletions
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal 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>
|
|
@ -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")
|
||||
|
|
72
app/src/main/java/oppen/tva/io/history/BasicCache.kt
Normal file
72
app/src/main/java/oppen/tva/io/history/BasicCache.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ interface CacheInterface {
|
|||
|
||||
companion object{
|
||||
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))
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue