diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/oppen/tva/io/GeminiDatasource.kt b/app/src/main/java/oppen/tva/io/GeminiDatasource.kt
index 0e68d39..39e4845 100644
--- a/app/src/main/java/oppen/tva/io/GeminiDatasource.kt
+++ b/app/src/main/java/oppen/tva/io/GeminiDatasource.kt
@@ -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")
diff --git a/app/src/main/java/oppen/tva/io/history/BasicCache.kt b/app/src/main/java/oppen/tva/io/history/BasicCache.kt
new file mode 100644
index 0000000..ac730cc
--- /dev/null
+++ b/app/src/main/java/oppen/tva/io/history/BasicCache.kt
@@ -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, 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, 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()
+ 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)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/oppen/tva/io/history/CacheInterface.kt b/app/src/main/java/oppen/tva/io/history/CacheInterface.kt
index 2d357ae..0323e21 100644
--- a/app/src/main/java/oppen/tva/io/history/CacheInterface.kt
+++ b/app/src/main/java/oppen/tva/io/history/CacheInterface.kt
@@ -8,7 +8,7 @@ interface CacheInterface {
companion object{
fun default(context: Context): CacheInterface{
- return SimplePrefsCache(context)
+ return BasicCache(context)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/oppen/tva/io/history/SimplePrefsCache.kt b/app/src/main/java/oppen/tva/io/history/SimplePrefsCache.kt
deleted file mode 100644
index 06c5579..0000000
--- a/app/src/main/java/oppen/tva/io/history/SimplePrefsCache.kt
+++ /dev/null
@@ -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, activeIndex: Int) -> Unit) {
- val activeIndex = prefs.getInt(prefsActiveIndexKey, 0)
- when (val rawJson = prefs.getString(prefsCacheKey, null)) {
- null -> onTabs(arrayListOf(), activeIndex)
- else -> {
- val tabs = mutableListOf()
- 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, activeIndex: Int) {
- val edit = prefs.edit()
- edit.putInt(prefsActiveIndexKey, activeIndex)
- edit.putString(prefsCacheKey, tabsToJson(tabs))
- edit.apply()
- }
-
- private fun tabsToJson(tabs: List): 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
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/oppen/tva/io/history/Tab.kt b/app/src/main/java/oppen/tva/io/history/Tab.kt
index 224facb..d5778a3 100644
--- a/app/src/main/java/oppen/tva/io/history/Tab.kt
+++ b/app/src/main/java/oppen/tva/io/history/Tab.kt
@@ -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)
diff --git a/app/src/main/java/oppen/tva/ui/TvaActivity.kt b/app/src/main/java/oppen/tva/ui/TvaActivity.kt
index baa3bbe..483be20 100644
--- a/app/src/main/java/oppen/tva/ui/TvaActivity.kt
+++ b/app/src/main/java/oppen/tva/ui/TvaActivity.kt
@@ -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()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/oppen/tva/ui/TvaViewModel.kt b/app/src/main/java/oppen/tva/ui/TvaViewModel.kt
index 8a3e0e3..e2ffc91 100644
--- a/app/src/main/java/oppen/tva/ui/TvaViewModel.kt
+++ b/app/src/main/java/oppen/tva/ui/TvaViewModel.kt
@@ -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)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/oppen/tva/ui/gemtext/GemtextAdapter.kt b/app/src/main/java/oppen/tva/ui/gemtext/GemtextAdapter.kt
index fc64a94..ec23e0f 100644
--- a/app/src/main/java/oppen/tva/ui/gemtext/GemtextAdapter.kt
+++ b/app/src/main/java/oppen/tva/ui/gemtext/GemtextAdapter.kt
@@ -81,7 +81,9 @@ class GemtextAdapter(val onLink: (link: URI) -> Unit): RecyclerView.Adapter
-
-
-
-
-
-
-
@@ -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"/>