2021-12-02 18:11:34 +00:00
|
|
|
package corewala.buran.ui
|
|
|
|
|
|
|
|
import android.app.DownloadManager
|
|
|
|
import android.content.ActivityNotFoundException
|
|
|
|
import android.content.Intent
|
|
|
|
import android.content.SharedPreferences
|
|
|
|
import android.graphics.Color
|
|
|
|
import android.graphics.drawable.ColorDrawable
|
2022-05-01 15:31:45 +00:00
|
|
|
import android.net.ConnectivityManager
|
2022-05-30 23:53:44 +00:00
|
|
|
import android.net.NetworkCapabilities
|
2021-12-02 18:11:34 +00:00
|
|
|
import android.net.Uri
|
2022-05-30 23:53:44 +00:00
|
|
|
import android.os.Build
|
2021-12-02 18:11:34 +00:00
|
|
|
import android.os.Bundle
|
2022-05-01 15:44:42 +00:00
|
|
|
import android.text.InputType
|
2022-02-17 01:02:27 +00:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.View
|
2021-12-02 18:11:34 +00:00
|
|
|
import android.view.WindowManager
|
|
|
|
import android.view.inputmethod.EditorInfo
|
2022-02-17 01:02:27 +00:00
|
|
|
import android.widget.EditText
|
2022-05-22 15:43:48 +00:00
|
|
|
import android.widget.Toast
|
2021-12-02 18:11:34 +00:00
|
|
|
import androidx.activity.viewModels
|
|
|
|
import androidx.appcompat.app.AlertDialog
|
|
|
|
import androidx.appcompat.app.AppCompatActivity
|
2022-05-10 14:34:04 +00:00
|
|
|
import androidx.appcompat.app.AppCompatDelegate
|
2022-05-17 17:45:54 +00:00
|
|
|
import androidx.biometric.BiometricPrompt
|
2021-12-02 18:11:34 +00:00
|
|
|
import androidx.browser.customtabs.CustomTabsIntent
|
|
|
|
import androidx.databinding.DataBindingUtil
|
|
|
|
import androidx.preference.PreferenceManager
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager
|
|
|
|
import com.google.android.material.snackbar.Snackbar
|
2022-05-17 23:00:47 +00:00
|
|
|
import corewala.*
|
2022-03-13 20:58:10 +00:00
|
|
|
import corewala.buran.BuildConfig
|
2021-12-02 18:11:34 +00:00
|
|
|
import corewala.buran.Buran
|
|
|
|
import corewala.buran.OmniTerm
|
|
|
|
import corewala.buran.R
|
|
|
|
import corewala.buran.databinding.ActivityGemBinding
|
|
|
|
import corewala.buran.io.GemState
|
|
|
|
import corewala.buran.io.database.BuranDatabase
|
|
|
|
import corewala.buran.io.database.bookmarks.BookmarksDatasource
|
|
|
|
import corewala.buran.io.gemini.Datasource
|
|
|
|
import corewala.buran.io.gemini.GeminiResponse
|
2022-05-17 17:45:54 +00:00
|
|
|
import corewala.buran.io.keymanager.BuranBiometricManager
|
2022-03-13 20:58:10 +00:00
|
|
|
import corewala.buran.io.update.BuranUpdates
|
2021-12-02 18:11:34 +00:00
|
|
|
import corewala.buran.ui.bookmarks.BookmarkDialog
|
|
|
|
import corewala.buran.ui.bookmarks.BookmarksDialog
|
|
|
|
import corewala.buran.ui.content_image.ImageDialog
|
|
|
|
import corewala.buran.ui.content_text.TextDialog
|
2022-05-02 18:49:35 +00:00
|
|
|
import corewala.buran.ui.gemtext_adapter.AbstractGemtextAdapter
|
2021-12-02 18:11:34 +00:00
|
|
|
import corewala.buran.ui.modals_menus.about.AboutDialog
|
|
|
|
import corewala.buran.ui.modals_menus.history.HistoryDialog
|
|
|
|
import corewala.buran.ui.modals_menus.overflow.OverflowPopup
|
|
|
|
import corewala.buran.ui.settings.SettingsActivity
|
|
|
|
import java.io.File
|
|
|
|
import java.io.FileInputStream
|
|
|
|
import java.io.FileOutputStream
|
|
|
|
import java.net.URI
|
|
|
|
|
2022-05-01 15:31:45 +00:00
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
const val CREATE_IMAGE_FILE_REQ = 628
|
|
|
|
const val CREATE_BINARY_FILE_REQ = 630
|
|
|
|
const val CREATE_BOOKMARK_EXPORT_FILE_REQ = 631
|
|
|
|
const val CREATE_BOOKMARK_IMPORT_FILE_REQ = 632
|
|
|
|
|
|
|
|
class GemActivity : AppCompatActivity() {
|
|
|
|
|
|
|
|
lateinit var prefs: SharedPreferences
|
|
|
|
private var inSearch = false
|
|
|
|
private lateinit var bookmarkDatasource: BookmarksDatasource
|
2022-05-30 23:53:44 +00:00
|
|
|
private lateinit var db: BuranDatabase
|
2021-12-02 18:11:34 +00:00
|
|
|
private var bookmarksDialog: BookmarksDialog? = null
|
|
|
|
|
|
|
|
private val model by viewModels<GemViewModel>()
|
|
|
|
private lateinit var binding: ActivityGemBinding
|
|
|
|
|
|
|
|
private val omniTerm = OmniTerm(object : OmniTerm.Listener {
|
|
|
|
override fun request(address: String) {
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(address)
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
|
2022-05-10 16:14:17 +00:00
|
|
|
override fun openExternal(address: String) = openExternalLink(address)
|
2021-12-02 18:11:34 +00:00
|
|
|
})
|
|
|
|
|
2022-05-18 00:45:40 +00:00
|
|
|
private var certPassword: String? = null
|
2022-05-17 22:37:11 +00:00
|
|
|
|
2022-05-02 18:49:35 +00:00
|
|
|
private var initialised: Boolean = false
|
|
|
|
|
2022-06-07 19:36:16 +00:00
|
|
|
private var requesting: Boolean = false
|
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
lateinit var adapter: AbstractGemtextAdapter
|
|
|
|
|
2022-05-26 16:49:30 +00:00
|
|
|
private val onLink: (link: URI, longTap: Boolean, adapterPosition: Int) -> Unit = { uri, longTap, _: Int ->
|
2021-12-02 18:11:34 +00:00
|
|
|
if(longTap){
|
2022-05-16 16:19:41 +00:00
|
|
|
val globalURI = if(!uri.toString().contains("//") and !uri.toString().contains(":")){
|
|
|
|
(omniTerm.getCurrent() + uri.toString()).replace("//", "/").replace("gemini:/", "gemini://")
|
|
|
|
} else {
|
|
|
|
uri.toString()
|
|
|
|
}
|
2022-01-08 16:17:20 +00:00
|
|
|
Intent().apply {
|
|
|
|
action = Intent.ACTION_SEND
|
2022-01-13 14:48:02 +00:00
|
|
|
putExtra(Intent.EXTRA_TEXT, globalURI)
|
2022-01-08 16:17:20 +00:00
|
|
|
type = "text/plain"
|
|
|
|
startActivity(Intent.createChooser(this, null))
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
}else{
|
2022-05-21 23:41:35 +00:00
|
|
|
//Reset input text hint after user has been searching
|
|
|
|
if(inSearch) {
|
|
|
|
binding.addressEdit.hint = getString(R.string.main_input_hint)
|
|
|
|
inSearch = false
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
2022-05-21 23:41:35 +00:00
|
|
|
omniTerm.navigation(uri.toString())
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-09 17:22:36 +00:00
|
|
|
private val inlineImage: (link: URI, adapterPosition: Int) -> Unit = { uri, position: Int ->
|
2022-05-02 16:04:29 +00:00
|
|
|
if(getInternetStatus()){
|
|
|
|
omniTerm.imageAddress(uri.toString())
|
2022-05-18 16:18:59 +00:00
|
|
|
val clientCertPassword = if(isHostSigned(uri)){
|
|
|
|
certPassword
|
|
|
|
}else{
|
|
|
|
null
|
|
|
|
}
|
2022-05-02 16:04:29 +00:00
|
|
|
omniTerm.uri.let{
|
2022-05-18 16:18:59 +00:00
|
|
|
model.requestInlineImage(URI.create(it.toString()), clientCertPassword){ imageUri ->
|
2022-05-02 16:04:29 +00:00
|
|
|
imageUri?.let{
|
|
|
|
runOnUiThread {
|
|
|
|
loadImage(position, imageUri)
|
|
|
|
loadingView(false)
|
|
|
|
}
|
2022-01-09 17:22:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
private fun loadImage(position: Int, uri: Uri) {
|
|
|
|
adapter.loadImage(position, uri)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
|
|
|
|
binding = DataBindingUtil.setContentView(this, R.layout.activity_gem)
|
|
|
|
binding.viewmodel = model
|
|
|
|
binding.lifecycleOwner = this
|
|
|
|
|
|
|
|
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
|
|
|
|
|
|
|
binding.gemtextRecycler.layoutManager = LinearLayoutManager(this)
|
|
|
|
|
|
|
|
prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
|
|
|
|
2022-05-10 14:34:04 +00:00
|
|
|
when (prefs.getString("theme", "theme_FollowSystem")) {
|
|
|
|
"theme_FollowSystem" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
|
|
|
"theme_Light" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
|
|
|
"theme_Dark" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
|
|
|
}
|
|
|
|
|
2022-01-09 17:22:36 +00:00
|
|
|
adapter = AbstractGemtextAdapter.getAdapter(onLink, inlineImage)
|
2021-12-02 18:11:34 +00:00
|
|
|
|
|
|
|
binding.gemtextRecycler.adapter = adapter
|
|
|
|
|
2022-05-30 23:53:44 +00:00
|
|
|
if(getInternetStatus()){
|
|
|
|
initialise()
|
2022-05-01 15:31:45 +00:00
|
|
|
}else{
|
|
|
|
loadingView(false)
|
2022-05-25 21:00:56 +00:00
|
|
|
val home = PreferenceManager.getDefaultSharedPreferences(this).getString(
|
|
|
|
"home_capsule",
|
|
|
|
Buran.DEFAULT_HOME_CAPSULE
|
|
|
|
)
|
|
|
|
val title = "# ${this.getString(R.string.no_internet)}"
|
|
|
|
val link = "=> $home ${this.getString(R.string.retry)}"
|
|
|
|
omniTerm.set(home!!)
|
|
|
|
adapter.render(listOf(title, link))
|
2022-05-01 15:44:42 +00:00
|
|
|
binding.addressEdit.inputType = InputType.TYPE_NULL
|
2022-03-13 20:58:10 +00:00
|
|
|
}
|
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
binding.addressEdit.setOnEditorActionListener { _, actionId, _ ->
|
|
|
|
when (actionId) {
|
|
|
|
EditorInfo.IME_ACTION_GO -> {
|
2022-04-20 19:28:11 +00:00
|
|
|
val searchbase = prefs.getString(
|
|
|
|
"search_base",
|
|
|
|
Buran.DEFAULT_SEARCH_BASE
|
|
|
|
)
|
|
|
|
omniTerm.input(binding.addressEdit.text.toString().trim(), searchbase)
|
2021-12-02 18:11:34 +00:00
|
|
|
binding.addressEdit.clearFocus()
|
|
|
|
return@setOnEditorActionListener true
|
|
|
|
}
|
|
|
|
else -> return@setOnEditorActionListener false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-06 22:26:32 +00:00
|
|
|
binding.addressEdit.setOnClickListener {
|
2022-01-06 22:36:18 +00:00
|
|
|
binding.addressEdit.requestFocus()
|
2022-01-06 22:26:32 +00:00
|
|
|
}
|
|
|
|
|
2022-05-26 16:49:30 +00:00
|
|
|
binding.addressEdit.setOnFocusChangeListener { _, hasFocus ->
|
2021-12-02 18:11:34 +00:00
|
|
|
|
2022-05-19 17:25:58 +00:00
|
|
|
val addressPaddingRight = resources.getDimensionPixelSize(R.dimen.def_address_right_margin)
|
2021-12-02 18:11:34 +00:00
|
|
|
|
2022-01-06 22:26:32 +00:00
|
|
|
if(!hasFocus) {
|
2021-12-02 18:11:34 +00:00
|
|
|
binding.addressEdit.hideKeyboard()
|
|
|
|
}
|
|
|
|
|
|
|
|
binding.addressEdit.setPadding(
|
|
|
|
binding.addressEdit.paddingLeft,
|
|
|
|
binding.addressEdit.paddingTop,
|
|
|
|
addressPaddingRight,
|
|
|
|
binding.addressEdit.paddingBottom,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
binding.more.setOnClickListener {
|
|
|
|
OverflowPopup.show(binding.more){ menuId ->
|
|
|
|
when (menuId) {
|
|
|
|
R.id.overflow_menu_search -> {
|
|
|
|
binding.addressEdit.hint = getString(R.string.main_input_search_hint)
|
|
|
|
binding.addressEdit.text?.clear()
|
|
|
|
binding.addressEdit.requestFocus()
|
|
|
|
inSearch = true
|
|
|
|
}
|
2022-05-18 16:18:59 +00:00
|
|
|
R.id.overflow_menu_sign -> {
|
2022-05-19 17:13:17 +00:00
|
|
|
if (prefs.getBoolean("use_biometrics", false) and certPassword.isNullOrEmpty()) {
|
|
|
|
biometricSecureRequest(binding.addressEdit.text.toString())
|
|
|
|
}else if(certPassword.isNullOrEmpty()){
|
|
|
|
if (certPassword.isNullOrEmpty()) {
|
|
|
|
certPassword = prefs.getString(
|
|
|
|
Buran.PREF_KEY_CLIENT_CERT_PASSWORD,
|
|
|
|
null
|
|
|
|
)
|
2022-05-18 16:18:59 +00:00
|
|
|
}
|
2022-05-19 17:13:17 +00:00
|
|
|
refresh()
|
2022-05-22 15:43:48 +00:00
|
|
|
Toast.makeText(this, this.getString(R.string.cert_loaded), Toast.LENGTH_SHORT).show()
|
2022-05-18 23:13:29 +00:00
|
|
|
}else{
|
2022-05-19 17:13:17 +00:00
|
|
|
certPassword = null
|
|
|
|
refresh()
|
2022-05-22 15:43:48 +00:00
|
|
|
Toast.makeText(this, this.getString(R.string.cert_unloaded), Toast.LENGTH_SHORT).show()
|
2022-05-18 16:18:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
R.id.overflow_menu_bookmark -> {
|
|
|
|
val name = adapter.inferTitle()
|
|
|
|
BookmarkDialog(
|
|
|
|
this,
|
|
|
|
BookmarkDialog.mode_new,
|
|
|
|
bookmarkDatasource,
|
|
|
|
binding.addressEdit.text.toString(),
|
|
|
|
name ?: ""
|
|
|
|
) { _, _ ->
|
|
|
|
}.show()
|
|
|
|
}
|
|
|
|
R.id.overflow_menu_bookmarks -> {
|
|
|
|
bookmarksDialog = BookmarksDialog(this, bookmarkDatasource) { bookmark ->
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(bookmark.uri.toString())
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
bookmarksDialog?.show()
|
|
|
|
}
|
|
|
|
R.id.overflow_menu_share -> {
|
|
|
|
Intent().apply {
|
|
|
|
action = Intent.ACTION_SEND
|
|
|
|
putExtra(Intent.EXTRA_TEXT, binding.addressEdit.text.toString())
|
|
|
|
type = "text/plain"
|
|
|
|
startActivity(Intent.createChooser(this, null))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
R.id.overflow_menu_history -> HistoryDialog.show(
|
|
|
|
this,
|
2022-06-09 15:21:41 +00:00
|
|
|
db.history(),
|
|
|
|
omniTerm
|
2021-12-02 18:11:34 +00:00
|
|
|
) { historyAddress ->
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(historyAddress)
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
R.id.overflow_menu_about -> AboutDialog.show(this)
|
|
|
|
R.id.overflow_menu_settings -> {
|
|
|
|
startActivity(Intent(this, SettingsActivity::class.java))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-19 17:13:17 +00:00
|
|
|
if(!prefs.getString(Buran.PREF_KEY_CLIENT_CERT_URI, null).isNullOrEmpty()){
|
|
|
|
OverflowPopup.setItemVisibility(R.id.overflow_menu_sign, true)
|
|
|
|
if(certPassword.isNullOrEmpty()){
|
|
|
|
OverflowPopup.setItemTitle(R.id.overflow_menu_sign, getString(R.string.load_cert))
|
|
|
|
}else{
|
|
|
|
OverflowPopup.setItemTitle(R.id.overflow_menu_sign, getString(R.string.unload_cert))
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
OverflowPopup.setItemVisibility(R.id.overflow_menu_sign, false)
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
binding.home.setOnClickListener {
|
|
|
|
val home = PreferenceManager.getDefaultSharedPreferences(this).getString(
|
|
|
|
"home_capsule",
|
|
|
|
Buran.DEFAULT_HOME_CAPSULE
|
|
|
|
)
|
|
|
|
omniTerm.history.clear()
|
2022-05-22 14:46:21 +00:00
|
|
|
gemRequest(home!!, false)
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
binding.pullToRefresh.setOnRefreshListener {
|
2022-05-01 16:17:28 +00:00
|
|
|
if(getInternetStatus()){
|
2022-05-24 19:38:47 +00:00
|
|
|
refresh()
|
2022-05-01 16:17:28 +00:00
|
|
|
}else{
|
|
|
|
binding.pullToRefresh.isRefreshing = false
|
|
|
|
Snackbar.make(binding.root, getString(R.string.no_internet), Snackbar.LENGTH_LONG).show()
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
checkIntentExtras(intent)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun refresh(){
|
|
|
|
omniTerm.getCurrent().run{
|
|
|
|
binding.addressEdit.setText(this)
|
|
|
|
focusEnd()
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(this)
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
super.onResume()
|
|
|
|
|
|
|
|
when {
|
|
|
|
prefs.contains("background_colour") -> {
|
|
|
|
when (val backgroundColor = prefs.getString("background_colour", "#XXXXXX")) {
|
|
|
|
"#XXXXXX" -> binding.rootCoord.background = null
|
|
|
|
else -> binding.rootCoord.background = ColorDrawable(Color.parseColor("$backgroundColor"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val showInlineIcons = prefs.getBoolean(
|
|
|
|
"show_inline_icons",
|
|
|
|
true
|
|
|
|
)
|
|
|
|
adapter.inlineIcons(showInlineIcons)
|
|
|
|
|
2022-01-27 01:21:43 +00:00
|
|
|
val showLinkButtons = prefs.getBoolean(
|
|
|
|
"show_link_buttons",
|
2022-05-19 18:08:58 +00:00
|
|
|
false
|
2022-01-27 01:21:43 +00:00
|
|
|
)
|
|
|
|
adapter.linkButtons(showLinkButtons)
|
|
|
|
|
2022-05-24 19:38:47 +00:00
|
|
|
val useAttentionGuides = prefs.getBoolean(
|
|
|
|
"use_attention_guides",
|
|
|
|
false
|
|
|
|
)
|
|
|
|
adapter.attentionGuides(useAttentionGuides)
|
|
|
|
|
2022-01-27 01:21:43 +00:00
|
|
|
|
2022-01-09 17:22:36 +00:00
|
|
|
val showInlineImages = prefs.getBoolean(
|
|
|
|
"show_inline_images",
|
|
|
|
true
|
|
|
|
)
|
|
|
|
adapter.inlineImages(showInlineImages)
|
2021-12-02 18:11:34 +00:00
|
|
|
|
2022-05-30 23:53:44 +00:00
|
|
|
if(getInternetStatus()){
|
2022-05-01 15:31:45 +00:00
|
|
|
model.invalidateDatasource()
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
|
2022-05-18 23:13:29 +00:00
|
|
|
private fun updateClientCertIcon(){
|
|
|
|
if (!prefs.getString(
|
|
|
|
Buran.PREF_KEY_CLIENT_CERT_URI,
|
|
|
|
null
|
|
|
|
).isNullOrEmpty()){
|
|
|
|
if(certPassword.isNullOrEmpty()){
|
|
|
|
binding.addressEdit.setCompoundDrawablesWithIntrinsicBounds(
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
}else{
|
|
|
|
binding.addressEdit.setCompoundDrawablesWithIntrinsicBounds(
|
|
|
|
R.drawable.vector_client_cert,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun handleState(state: GemState) {
|
|
|
|
binding.pullToRefresh.isRefreshing = false
|
|
|
|
|
|
|
|
when (state) {
|
|
|
|
is GemState.AppQuery -> runOnUiThread { showAlert("App backdoor/query not implemented yet") }
|
2022-02-17 01:02:27 +00:00
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
is GemState.ResponseInput -> runOnUiThread {
|
2022-05-03 22:50:27 +00:00
|
|
|
val builder = AlertDialog.Builder(this, R.style.AppDialogTheme)
|
2022-02-17 01:02:27 +00:00
|
|
|
val inflater: LayoutInflater = layoutInflater
|
|
|
|
val dialogLayout: View = inflater.inflate(R.layout.dialog_input_query, null)
|
|
|
|
val editText: EditText = dialogLayout.findViewById(R.id.query_input)
|
|
|
|
editText.requestFocus()
|
|
|
|
editText.showKeyboard()
|
2021-12-02 18:11:34 +00:00
|
|
|
loadingView(false)
|
2022-05-03 22:50:27 +00:00
|
|
|
builder
|
|
|
|
.setTitle(state.header.meta)
|
2022-05-26 16:49:30 +00:00
|
|
|
.setPositiveButton(getString(R.string.confirm).toUpperCase()){ _, _ ->
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest("${state.uri}?${Uri.encode(editText.text.toString())}")
|
2022-02-17 01:02:27 +00:00
|
|
|
editText.hideKeyboard()
|
|
|
|
}
|
2022-05-26 16:49:30 +00:00
|
|
|
.setNegativeButton(getString(R.string.cancel).toUpperCase()){ _, _ ->
|
2022-02-17 01:02:27 +00:00
|
|
|
editText.hideKeyboard()
|
|
|
|
}
|
2022-05-03 22:50:27 +00:00
|
|
|
.setView(dialogLayout)
|
|
|
|
.show()
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
2022-02-17 01:02:27 +00:00
|
|
|
|
2022-05-18 16:18:59 +00:00
|
|
|
is GemState.Redirect -> gemRequest(state.uri)
|
|
|
|
|
2022-05-03 22:29:44 +00:00
|
|
|
is GemState.ClientCertRequired -> runOnUiThread {
|
|
|
|
loadingView(false)
|
2022-05-04 01:24:01 +00:00
|
|
|
val builder = AlertDialog.Builder(this, R.style.AppDialogTheme)
|
|
|
|
builder
|
2022-05-03 22:29:44 +00:00
|
|
|
.setTitle(getString(R.string.client_certificate_required))
|
|
|
|
.setMessage(state.header.meta)
|
2022-05-04 01:24:01 +00:00
|
|
|
|
2022-05-18 00:02:39 +00:00
|
|
|
if(!prefs.getString(Buran.PREF_KEY_CLIENT_CERT_URI, null).isNullOrEmpty()){
|
2022-05-04 01:24:01 +00:00
|
|
|
builder
|
2022-05-05 14:19:03 +00:00
|
|
|
.setPositiveButton(getString(R.string.use_client_certificate).toUpperCase()) { _, _ ->
|
2022-05-18 00:45:40 +00:00
|
|
|
if(prefs.getBoolean("use_biometrics", false) and certPassword.isNullOrEmpty()){
|
2022-05-17 17:45:54 +00:00
|
|
|
biometricSecureRequest(state.uri.toString())
|
|
|
|
}else{
|
2022-05-18 00:45:40 +00:00
|
|
|
if(certPassword.isNullOrEmpty()){
|
|
|
|
certPassword = prefs.getString(
|
|
|
|
Buran.PREF_KEY_CLIENT_CERT_PASSWORD,
|
|
|
|
null
|
|
|
|
)
|
|
|
|
}
|
2022-05-22 14:55:52 +00:00
|
|
|
gemRequest(state.uri.toString(), true)
|
2022-05-22 15:43:48 +00:00
|
|
|
Toast.makeText(this, this.getString(R.string.cert_loaded), Toast.LENGTH_SHORT).show()
|
2022-05-17 17:45:54 +00:00
|
|
|
}
|
2022-05-04 01:24:01 +00:00
|
|
|
}
|
2022-05-05 14:19:03 +00:00
|
|
|
.setNegativeButton(getString(R.string.cancel).toUpperCase()) { _, _ -> }
|
2022-05-04 01:24:01 +00:00
|
|
|
.show()
|
|
|
|
}else{
|
|
|
|
builder
|
2022-05-05 14:19:03 +00:00
|
|
|
.setNegativeButton(getString(R.string.close).toUpperCase()) { _, _ -> }
|
2022-05-04 01:24:01 +00:00
|
|
|
.show()
|
|
|
|
}
|
2022-05-03 22:29:44 +00:00
|
|
|
}
|
|
|
|
|
2022-06-07 19:36:16 +00:00
|
|
|
is GemState.Requesting -> {
|
|
|
|
loadingView(true)
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
is GemState.NotGeminiRequest -> externalProtocol(state)
|
|
|
|
is GemState.ResponseError -> {
|
2022-05-27 16:21:15 +00:00
|
|
|
omniTerm.reset()
|
|
|
|
showAlert("${GeminiResponse.getCodeString(state.header.code)}:\n\n${state.header.meta}")
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
is GemState.ClientCertError -> {
|
2022-05-18 23:13:29 +00:00
|
|
|
certPassword = null
|
|
|
|
updateClientCertIcon()
|
2021-12-02 18:11:34 +00:00
|
|
|
showAlert("${GeminiResponse.getCodeString(state.header.code)}:\n\n${state.header.meta}")
|
|
|
|
}
|
|
|
|
is GemState.ResponseGemtext -> renderGemtext(state)
|
|
|
|
is GemState.ResponseText -> renderText(state)
|
|
|
|
is GemState.ResponseImage -> renderImage(state)
|
|
|
|
is GemState.ResponseBinary -> renderBinary(state)
|
|
|
|
is GemState.Blank -> {
|
|
|
|
binding.addressEdit.setText("")
|
|
|
|
adapter.render(arrayListOf())
|
|
|
|
}
|
|
|
|
is GemState.ResponseUnknownMime -> {
|
|
|
|
runOnUiThread {
|
|
|
|
loadingView(false)
|
|
|
|
|
|
|
|
val download = getString(R.string.download)
|
|
|
|
|
2022-05-02 16:04:29 +00:00
|
|
|
if(getInternetStatus()) {
|
2022-05-18 16:18:59 +00:00
|
|
|
val clientCertPassword = if(isHostSigned(state.uri)){
|
|
|
|
certPassword
|
|
|
|
}else{
|
|
|
|
null
|
|
|
|
}
|
2022-05-02 16:04:29 +00:00
|
|
|
AlertDialog.Builder(this, R.style.AppDialogTheme)
|
|
|
|
.setTitle("$download: ${state.header.meta}")
|
|
|
|
.setMessage("${state.uri}")
|
2022-05-05 14:19:03 +00:00
|
|
|
.setPositiveButton(getString(R.string.download).toUpperCase()) { _, _ ->
|
2022-05-02 16:04:29 +00:00
|
|
|
loadingView(true)
|
2022-05-18 16:18:59 +00:00
|
|
|
model.requestBinaryDownload(state.uri, clientCertPassword)
|
2022-05-02 16:04:29 +00:00
|
|
|
}
|
2022-05-05 14:19:03 +00:00
|
|
|
.setNegativeButton(getString(R.string.cancel).toUpperCase()) { _, _ -> }
|
2022-05-02 16:04:29 +00:00
|
|
|
.show()
|
|
|
|
}else{
|
|
|
|
Snackbar.make(binding.root, getString(R.string.no_internet), Snackbar.LENGTH_LONG).show()
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
is GemState.ResponseUnknownHost -> {
|
2022-06-07 19:36:16 +00:00
|
|
|
omniTerm.reset()
|
2021-12-02 18:11:34 +00:00
|
|
|
runOnUiThread {
|
2022-04-20 19:28:11 +00:00
|
|
|
val searchbase = prefs.getString(
|
|
|
|
"search_base",
|
|
|
|
Buran.DEFAULT_SEARCH_BASE
|
|
|
|
)
|
2021-12-02 18:11:34 +00:00
|
|
|
loadingView(false)
|
|
|
|
AlertDialog.Builder(this, R.style.AppDialogTheme)
|
2022-05-08 21:50:00 +00:00
|
|
|
.setTitle(getString(R.string.unknown_host))
|
|
|
|
.setMessage("${getString(R.string.unknown_host)}: ${state.uri}\n\n${getString(R.string.search_instead)}")
|
2022-05-05 14:19:03 +00:00
|
|
|
.setPositiveButton(getString(R.string.search).toUpperCase()) { _, _ ->
|
2021-12-02 18:11:34 +00:00
|
|
|
loadingView(true)
|
2022-04-20 19:28:11 +00:00
|
|
|
omniTerm.search(state.uri.toString(), searchbase)
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
2022-05-05 14:19:03 +00:00
|
|
|
.setNegativeButton(getString(R.string.cancel).toUpperCase()) { _, _ -> }
|
2021-12-02 18:11:34 +00:00
|
|
|
.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onNewIntent(intent: Intent?) {
|
|
|
|
super.onNewIntent(intent)
|
|
|
|
|
|
|
|
intent?.let{
|
|
|
|
checkIntentExtras(intent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Checks intent to see if Activity was opened to handle selected text
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
private fun checkIntentExtras(intent: Intent) {
|
|
|
|
|
|
|
|
//From clicking a gemini:// address
|
|
|
|
val uri = intent.data
|
|
|
|
if(uri != null){
|
|
|
|
binding.addressEdit.setText(uri.toString())
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(uri.toString())
|
2021-12-02 18:11:34 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-17 17:45:54 +00:00
|
|
|
private fun biometricSecureRequest(address: String){
|
|
|
|
val biometricManager = BuranBiometricManager()
|
|
|
|
|
|
|
|
val callback = object : BiometricPrompt.AuthenticationCallback() {
|
|
|
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
|
|
|
super.onAuthenticationError(errorCode, errString)
|
|
|
|
println("Authentication error: $errorCode: $errString")
|
|
|
|
}
|
|
|
|
override fun onAuthenticationFailed() {
|
|
|
|
super.onAuthenticationFailed()
|
|
|
|
println("Authentication failed")
|
|
|
|
}
|
|
|
|
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
|
|
|
super.onAuthenticationSucceeded(result)
|
|
|
|
println("Authentication succeeded")
|
|
|
|
|
|
|
|
val ciphertext = biometricManager.decodeByteArray(
|
|
|
|
prefs.getString(
|
|
|
|
"password_ciphertext",
|
|
|
|
null
|
|
|
|
)!!
|
|
|
|
)
|
|
|
|
|
2022-05-18 00:45:40 +00:00
|
|
|
certPassword = biometricManager.decryptData(ciphertext, result.cryptoObject?.cipher!!)
|
2022-05-22 14:55:52 +00:00
|
|
|
gemRequest(address, true)
|
2022-05-22 15:43:48 +00:00
|
|
|
Toast.makeText(applicationContext, applicationContext.getString(R.string.cert_loaded), Toast.LENGTH_SHORT).show()
|
2022-05-17 17:45:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val initializationVector = biometricManager.decodeByteArray(
|
|
|
|
prefs.getString(
|
|
|
|
"password_init_vector",
|
|
|
|
null
|
|
|
|
)!!
|
|
|
|
)
|
|
|
|
|
2022-05-19 17:39:10 +00:00
|
|
|
biometricManager.createBiometricPrompt(this, null, this, callback)
|
2022-05-17 19:34:44 +00:00
|
|
|
biometricManager.authenticateToDecryptData(initializationVector)
|
2022-05-17 17:45:54 +00:00
|
|
|
}
|
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
private fun showAlert(message: String) = runOnUiThread{
|
|
|
|
loadingView(false)
|
|
|
|
|
|
|
|
if(message.length > 40){
|
|
|
|
AlertDialog.Builder(this)
|
|
|
|
.setTitle(getString(R.string.error))
|
|
|
|
.setMessage(message)
|
2022-05-05 14:19:03 +00:00
|
|
|
.setPositiveButton(getString(R.string.close).toUpperCase()){ _, _ ->
|
2021-12-02 18:11:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
.show()
|
|
|
|
}else {
|
|
|
|
Snackbar.make(binding.root, message, Snackbar.LENGTH_SHORT).show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun externalProtocol(state: GemState.NotGeminiRequest) = runOnUiThread {
|
|
|
|
loadingView(false)
|
|
|
|
val uri = state.uri.toString()
|
|
|
|
|
|
|
|
when {
|
2022-05-10 16:14:17 +00:00
|
|
|
(uri.startsWith("http://") || uri.startsWith("https://")) -> openExternalLink(uri)
|
2021-12-02 18:11:34 +00:00
|
|
|
else -> {
|
|
|
|
val viewIntent = Intent(Intent.ACTION_VIEW)
|
|
|
|
viewIntent.data = Uri.parse(state.uri.toString())
|
|
|
|
|
|
|
|
try {
|
|
|
|
startActivity(viewIntent)
|
|
|
|
}catch (e: ActivityNotFoundException){
|
|
|
|
showAlert(
|
|
|
|
String.format(
|
2021-12-08 20:46:30 +00:00
|
|
|
getString(R.string.no_app_installed_that_can_open),
|
2021-12-02 18:11:34 +00:00
|
|
|
state.uri
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-10 16:14:17 +00:00
|
|
|
private fun openExternalLink(address: String){
|
2021-12-02 18:11:34 +00:00
|
|
|
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
|
|
|
|
Buran.PREF_KEY_USE_CUSTOM_TAB,
|
|
|
|
true
|
2022-05-10 16:14:17 +00:00
|
|
|
)or !address.startsWith("http")) {
|
2021-12-02 18:11:34 +00:00
|
|
|
val builder = CustomTabsIntent.Builder()
|
|
|
|
val intent = builder.build()
|
2022-05-10 16:14:17 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
intent.launchUrl(this, Uri.parse(address))
|
|
|
|
}catch (e: ActivityNotFoundException){
|
|
|
|
showAlert(
|
|
|
|
String.format(
|
|
|
|
getString(R.string.no_app_installed_that_can_open),
|
|
|
|
address
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
2021-12-02 18:11:34 +00:00
|
|
|
}else{
|
|
|
|
val viewIntent = Intent(Intent.ACTION_VIEW)
|
|
|
|
viewIntent.data = Uri.parse(address)
|
2022-05-10 16:14:17 +00:00
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
startActivity(viewIntent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun renderGemtext(state: GemState.ResponseGemtext) = runOnUiThread {
|
|
|
|
loadingView(false)
|
|
|
|
|
|
|
|
omniTerm.set(state.uri.toString())
|
|
|
|
|
|
|
|
//todo - colours didn't change when switching themes, so disabled for now
|
|
|
|
//val addressSpan = SpannableString(state.uri.toString())
|
|
|
|
//addressSpan.set(0, 9, ForegroundColorSpan(resources.getColor(R.color.protocol_address)))
|
|
|
|
binding.addressEdit.setText(state.uri.toString())
|
|
|
|
|
|
|
|
adapter.render(state.lines)
|
|
|
|
|
|
|
|
//Scroll to top
|
|
|
|
binding.gemtextRecycler.post {
|
|
|
|
binding.gemtextRecycler.scrollToPosition(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
focusEnd()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun renderText(state: GemState.ResponseText) = runOnUiThread {
|
|
|
|
loadingView(false)
|
|
|
|
TextDialog.show(this, state)
|
|
|
|
}
|
|
|
|
|
|
|
|
var imageState: GemState.ResponseImage? = null
|
|
|
|
var binaryState: GemState.ResponseBinary? = null
|
|
|
|
|
|
|
|
private fun renderImage(state: GemState.ResponseImage) = runOnUiThread{
|
|
|
|
loadingView(false)
|
|
|
|
ImageDialog.show(this, state){ state ->
|
|
|
|
imageState = state
|
|
|
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
|
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
|
|
|
intent.type = "image/*"
|
|
|
|
intent.putExtra(Intent.EXTRA_TITLE, File(state.uri.path).name)
|
|
|
|
startActivityForResult(intent, CREATE_IMAGE_FILE_REQ)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun renderBinary(state: GemState.ResponseBinary) = runOnUiThread{
|
|
|
|
loadingView(false)
|
|
|
|
binaryState = state
|
|
|
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
|
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
|
|
|
intent.type = state.header.meta
|
|
|
|
intent.putExtra(Intent.EXTRA_TITLE, File(state.uri.path).name)
|
|
|
|
startActivityForResult(intent, CREATE_BINARY_FILE_REQ)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
|
|
super.onActivityResult(requestCode, resultCode, data)
|
|
|
|
if(resultCode == RESULT_OK && (requestCode == CREATE_IMAGE_FILE_REQ || requestCode == CREATE_BINARY_FILE_REQ)){
|
|
|
|
//todo - tidy this mess up... refactor - none of this should be here
|
|
|
|
if(imageState == null && binaryState == null) return
|
2022-05-16 16:19:41 +00:00
|
|
|
data?.data?.let{ uri ->
|
2021-12-02 18:11:34 +00:00
|
|
|
val cachedFile = when {
|
|
|
|
imageState != null -> File(imageState!!.cacheUri.path ?: "")
|
|
|
|
binaryState != null -> File(binaryState!!.cacheUri.path ?: "")
|
|
|
|
else -> {
|
|
|
|
println("File download error - no state object exists")
|
|
|
|
showAlert(getString(R.string.no_state_object_exists))
|
|
|
|
null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cachedFile?.let{
|
|
|
|
contentResolver.openFileDescriptor(uri, "w")?.use { fileDescriptor ->
|
|
|
|
FileOutputStream(fileDescriptor.fileDescriptor).use { destOutput ->
|
|
|
|
val sourceChannel = FileInputStream(cachedFile).channel
|
|
|
|
val destChannel = destOutput.channel
|
|
|
|
sourceChannel.transferTo(0, sourceChannel.size(), destChannel)
|
|
|
|
sourceChannel.close()
|
|
|
|
destChannel.close()
|
|
|
|
|
|
|
|
cachedFile.deleteOnExit()
|
|
|
|
|
|
|
|
if(binaryState != null){
|
|
|
|
startActivity(Intent(DownloadManager.ACTION_VIEW_DOWNLOADS))
|
|
|
|
}else{
|
|
|
|
Snackbar.make(
|
|
|
|
binding.root,
|
|
|
|
getString(R.string.file_saved_to_device),
|
|
|
|
Snackbar.LENGTH_SHORT
|
|
|
|
).show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
imageState = null
|
|
|
|
binaryState = null
|
|
|
|
}else if(resultCode == RESULT_OK && requestCode == CREATE_BOOKMARK_EXPORT_FILE_REQ){
|
|
|
|
data?.data?.let{ uri ->
|
|
|
|
bookmarksDialog?.bookmarksExportFileReady(uri)
|
|
|
|
}
|
|
|
|
}else if(resultCode == RESULT_OK && requestCode == CREATE_BOOKMARK_IMPORT_FILE_REQ){
|
|
|
|
data?.data?.let{ uri ->
|
|
|
|
bookmarksDialog?.bookmarksImportFileReady(uri)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun loadingView(visible: Boolean) = runOnUiThread {
|
|
|
|
binding.progressBar.visibleRetainingSpace(visible)
|
|
|
|
if(visible) binding.appBar.setExpanded(true)
|
|
|
|
}
|
|
|
|
|
2022-05-01 15:31:45 +00:00
|
|
|
private fun getInternetStatus(): Boolean {
|
|
|
|
val connectivityManager = this.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
2022-05-30 23:53:44 +00:00
|
|
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
|
|
|
|
val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
|
|
|
|
if(capabilities != null){
|
|
|
|
when {
|
|
|
|
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> { return true }
|
|
|
|
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> { return true }
|
|
|
|
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> { return true }
|
|
|
|
}
|
|
|
|
}
|
2022-05-24 19:38:47 +00:00
|
|
|
}else{
|
2022-05-30 23:53:44 +00:00
|
|
|
val activeNetworkInfo = connectivityManager.activeNetworkInfo
|
|
|
|
if(activeNetworkInfo != null && activeNetworkInfo.isConnected){
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun initialise(){
|
|
|
|
db = BuranDatabase(applicationContext)
|
|
|
|
bookmarkDatasource = db.bookmarks()
|
|
|
|
|
|
|
|
if(intent.data == null){
|
|
|
|
model.initialise(
|
|
|
|
home = prefs.getString(
|
|
|
|
"home_capsule",
|
|
|
|
Buran.DEFAULT_HOME_CAPSULE
|
|
|
|
) ?: Buran.DEFAULT_HOME_CAPSULE,
|
|
|
|
gemini = Datasource.factory(this, db.history()),
|
|
|
|
db = db,
|
|
|
|
onState = this::handleState
|
|
|
|
)
|
|
|
|
}else{
|
|
|
|
model.initialise(
|
|
|
|
home = intent.data.toString(),
|
|
|
|
gemini = Datasource.factory(this, db.history()),
|
|
|
|
db = db,
|
|
|
|
onState = this::handleState
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
|
|
|
|
"check_for_updates",
|
|
|
|
false
|
|
|
|
)){
|
|
|
|
val updates = BuranUpdates()
|
|
|
|
val latestVersion = updates.getLatestVersion()
|
|
|
|
|
|
|
|
if (latestVersion == BuildConfig.VERSION_NAME){
|
|
|
|
println("No new version available")
|
|
|
|
} else {
|
|
|
|
println("New version available")
|
|
|
|
|
|
|
|
Snackbar.make(binding.root, getString(R.string.new_version_available), Snackbar.LENGTH_LONG).setAction(getString(R.string.update)) {
|
|
|
|
updates.installUpdate(this, latestVersion)
|
|
|
|
}.show()
|
|
|
|
}
|
2022-05-01 15:31:45 +00:00
|
|
|
}
|
2022-05-30 23:53:44 +00:00
|
|
|
|
|
|
|
initialised = true
|
2022-05-01 15:31:45 +00:00
|
|
|
}
|
|
|
|
|
2022-05-18 16:18:59 +00:00
|
|
|
private fun isHostSigned(uri: URI): Boolean{
|
|
|
|
if((uri.host != omniTerm.getCurrent().toURI().host) && !certPassword.isNullOrEmpty()) {
|
|
|
|
return false
|
2022-05-17 23:00:47 +00:00
|
|
|
}
|
2022-05-18 16:18:59 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-05-22 14:46:21 +00:00
|
|
|
private fun gemRequest(address: String, sign: Boolean?){
|
|
|
|
if(sign == null){
|
|
|
|
if(!isHostSigned(address.toURI())) certPassword = null
|
|
|
|
}else if(!sign){
|
|
|
|
certPassword = null
|
|
|
|
}
|
2022-05-19 17:24:14 +00:00
|
|
|
updateClientCertIcon()
|
2022-05-17 23:00:47 +00:00
|
|
|
|
2022-05-02 16:04:29 +00:00
|
|
|
if(getInternetStatus()){
|
2022-05-02 18:49:35 +00:00
|
|
|
if(initialised){
|
2022-05-18 00:45:40 +00:00
|
|
|
model.request(address, certPassword)
|
2022-05-02 18:49:35 +00:00
|
|
|
}else{
|
2022-05-30 23:53:44 +00:00
|
|
|
initialise()
|
2022-05-02 18:49:35 +00:00
|
|
|
}
|
2022-05-02 16:04:29 +00:00
|
|
|
}else{
|
|
|
|
Snackbar.make(binding.root, getString(R.string.no_internet), Snackbar.LENGTH_LONG).show()
|
|
|
|
loadingView(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-22 14:46:21 +00:00
|
|
|
private fun gemRequest(address: String){
|
|
|
|
gemRequest(address, null)
|
|
|
|
}
|
|
|
|
|
2021-12-02 18:11:34 +00:00
|
|
|
override fun onBackPressed() {
|
2022-06-07 19:36:16 +00:00
|
|
|
if(omniTerm.canGoBack() and model.isRequesting()){
|
|
|
|
model.cancel()
|
2022-06-07 20:38:36 +00:00
|
|
|
loadingView(false)
|
2022-06-07 19:36:16 +00:00
|
|
|
}else if(omniTerm.canGoBack()){
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(omniTerm.goBack())
|
2021-12-02 18:11:34 +00:00
|
|
|
}else{
|
|
|
|
println("Buran history is empty - exiting")
|
|
|
|
super.onBackPressed()
|
|
|
|
cacheDir.deleteRecursively()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun focusEnd(){
|
|
|
|
binding.addressEdit.setSelection(binding.addressEdit.text?.length ?: 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onSaveInstanceState(outState: Bundle) {
|
|
|
|
super.onSaveInstanceState(outState)
|
|
|
|
val uri = binding.addressEdit.text.toString()
|
|
|
|
outState.putString("uri", uri)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
|
|
|
super.onRestoreInstanceState(savedInstanceState)
|
|
|
|
savedInstanceState.getString("uri")?.run {
|
|
|
|
omniTerm.set(this)
|
|
|
|
binding.addressEdit.setText(this)
|
2022-05-17 23:45:31 +00:00
|
|
|
gemRequest(this)
|
2021-12-02 18:11:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|