ariane/app/src/main/java/oppen/tva/ui/TvaActivity.kt

132 lines
4.9 KiB
Kotlin

package oppen.tva.ui
import android.R.attr.label
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.inputmethod.EditorInfo
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import oppen.alert
import oppen.tva.R
import oppen.tva.databinding.ActivityTvaBinding
import oppen.tva.io.TvaState
import oppen.tva.io.history.CacheInterface
import oppen.tva.ui.tabs.NewTabPopup
import oppen.tva.ui.tabs.TabsDialog
import oppen.visibleRetainingSpace
class TvaActivity : AppCompatActivity() {
private val model by viewModels<TvaViewModel>()
private lateinit var binding: ActivityTvaBinding
private val adapter = GemtextAdapter { uri, longTap, view ->
if(longTap){
NewTabPopup.show(view){ menuId ->
when (menuId) {
R.id.link_menu_open_in_new_tab -> {
model.newTab(uri)
}
R.id.link_menu_copy -> {
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(getString(R.string.gemini_address), uri.toString())
clipboard.setPrimaryClip(clip)
Snackbar.make(binding.root, getString(R.string.address_copied_to_clipboard), Snackbar.LENGTH_SHORT).setAction(R.string.share) {
Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, uri.toString())
type = "text/plain"
startActivity(Intent.createChooser(this, null))
}
}.show()
}
}
}
}else{
model.request(uri)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_tva)
binding.viewmodel = model
binding.lifecycleOwner = this
binding.gemtextRecycler.layoutManager = LinearLayoutManager(this)
binding.gemtextRecycler.adapter = adapter
model.initialise(CacheInterface.default(this)){ state ->
when(state){
is TvaState.AppQuery -> TODO()
is TvaState.Requesting -> loadingView(true)
is TvaState.NotGeminiRequest -> externalProtocol(state)
is TvaState.GeminiResponse -> renderGemtext(state)
is TvaState.TabChange -> binding.tabCount.text = "${state.count}"
is TvaState.Blank -> {
binding.addressEdit.setText("")
adapter.render(arrayListOf())
}
TvaState.GeminiPrintWriterError -> "Error with socket writer".alert(this)
}
}
binding.addressEdit.setOnEditorActionListener { _, actionId, _ ->
when (actionId) {
EditorInfo.IME_ACTION_GO -> {
model.request(binding.addressEdit.text.toString())
return@setOnEditorActionListener true
}
else -> return@setOnEditorActionListener false
}
}
binding.more.setOnClickListener { "Not implemented yet".alert(this) }
binding.home.setOnClickListener { "Not implemented yet".alert(this) }
binding.tabs.setOnClickListener {
TabsDialog().show(this, model)
}
}
private fun externalProtocol(state: TvaState.NotGeminiRequest) {
loadingView(false)
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(state.uri.toString()))
startActivity(browserIntent)
}
private fun renderGemtext(state: TvaState.GeminiResponse) = runOnUiThread {
loadingView(false)
if(state.header.startsWith("2") && state.header.contains("text/gemini")) {
binding.addressEdit.setText(state.uri.toString())
adapter.render(state.lines)
}else{
"Server returned an error - or non gemtext mimetype not implemented yet: ${state.header}".alert(this)
}
}
private fun loadingView(visible: Boolean) = runOnUiThread {
binding.progressBar.visibleRetainingSpace(visible)
if(visible) binding.appBar.setExpanded(true)
}
@ExperimentalStdlibApi
override fun onBackPressed() {
if(model.canGoBack()){
model.goBack()
}else{
super.onBackPressed()
}
}
override fun onDestroy() {
super.onDestroy()
model.persistTabState()
}
}