Attention guides for gemtext

This commit is contained in:
Corewala 2022-05-24 15:38:47 -04:00
parent a7877cfc41
commit 0b7e24e764
11 changed files with 102 additions and 57 deletions

View File

@ -20,6 +20,8 @@ Buran is a simple Gemini protocol browser for Android.
- [X] Inline rendering of images
- [ ] Page navigation feature
- [X] Update notifier
- [X] Attention guide mode
## Statement about Ariane

View File

@ -50,15 +50,4 @@ class BuranKeyManager(val context: Context, val onKeyError: (error: String) -> U
}
}
}
//Working example with cert packaged with app
fun getFactoryDemo(context: Context): KeyManagerFactory? {
val keyStore: KeyStore = KeyStore.getInstance("pkcs12")
keyStore.load(context.resources.openRawResource(R.raw.cert), "PASSWORD".toCharArray())
val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("X509")
keyManagerFactory.init(keyStore, "PASSWORD".toCharArray())
return keyManagerFactory
}
}

View File

@ -7,7 +7,6 @@ import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.os.Bundle
import android.text.InputType
@ -182,11 +181,10 @@ class GemActivity : AppCompatActivity() {
)
}
val isSideLoaded = packageManager.getInstallerPackageName(BuildConfig.APPLICATION_ID).isNullOrEmpty()
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
"check_for_updates",
false
) and isSideLoaded) {
)){
val updates = BuranUpdates()
val latestVersion = updates.getLatestVersion()
@ -331,14 +329,7 @@ class GemActivity : AppCompatActivity() {
binding.pullToRefresh.setOnRefreshListener {
if(getInternetStatus()){
if(initialised){
refresh()
}else{
val intent = baseContext.packageManager.getLaunchIntentForPackage(baseContext.packageName)
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
finish()
startActivity(intent)
}
refresh()
}else{
binding.pullToRefresh.isRefreshing = false
Snackbar.make(binding.root, getString(R.string.no_internet), Snackbar.LENGTH_LONG).show()
@ -380,6 +371,12 @@ class GemActivity : AppCompatActivity() {
)
adapter.linkButtons(showLinkButtons)
val useAttentionGuides = prefs.getBoolean(
"use_attention_guides",
false
)
adapter.attentionGuides(useAttentionGuides)
val showInlineImages = prefs.getBoolean(
"show_inline_images",
@ -784,18 +781,13 @@ class GemActivity : AppCompatActivity() {
private fun getInternetStatus(): Boolean {
val connectivityManager = this.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
if (capabilities != null) {
return if(capabilities != null){
println("Internet access found")
if(capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return true
}else if(capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return true
}else if(capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return true
}
true
}else{
println("No internet access found")
false
}
println("No internet access found")
return false
}
private fun isHostSigned(uri: URI): Boolean{

View File

@ -11,6 +11,7 @@ abstract class AbstractGemtextAdapter(
var showInlineIcons: Boolean = false
var showLinkButtons: Boolean = false
var useAttentionGuides: Boolean = false
var showInlineImages: Boolean = false
abstract fun render(lines: List<String>)
@ -18,7 +19,7 @@ abstract class AbstractGemtextAdapter(
abstract fun inlineIcons(visible: Boolean)
abstract fun inlineImages(visible: Boolean)
abstract fun linkButtons(visible: Boolean)
abstract fun attentionGuides(enabled: Boolean)
abstract fun inferTitle(): String?
companion object{

View File

@ -2,16 +2,19 @@ package corewala.buran.ui.gemtext_adapter
import android.annotation.SuppressLint
import android.net.Uri
import android.text.SpannableStringBuilder
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.gemtext_code_block.view.*
import kotlinx.android.synthetic.main.gemtext_image_link.view.*
import kotlinx.android.synthetic.main.gemtext_link.view.gemtext_text_link
import kotlinx.android.synthetic.main.gemtext_text.view.*
import androidx.core.text.bold
import corewala.buran.R
import corewala.endsWithImage
import corewala.visible
import kotlinx.android.synthetic.main.gemtext_code_block.view.*
import kotlinx.android.synthetic.main.gemtext_image_link.view.*
import kotlinx.android.synthetic.main.gemtext_link.view.gemtext_text_link
import kotlinx.android.synthetic.main.gemtext_quote.view.*
import kotlinx.android.synthetic.main.gemtext_text.view.*
import java.net.URI
class GemtextAdapter(
@ -80,16 +83,25 @@ class GemtextAdapter(
val line = lines[position]
when(holder){
is GmiViewHolder.Text -> holder.itemView.gemtext_text_textview.text = line
is GmiViewHolder.Text -> {
when {
useAttentionGuides -> holder.itemView.gemtext_text_textview.text = getAttentionGuideText(line)
else -> holder.itemView.gemtext_text_textview.text = line
}
}
is GmiViewHolder.Code -> {
if(line.startsWith("```<|ALT|>")){
holder.itemView.gemtext_text_monospace_textview.text = line.substring(line.indexOf("</|ALT>") + 7)
}else{
holder.itemView.gemtext_text_monospace_textview.text = line.substring(3)
}
}
is GmiViewHolder.Quote -> holder.itemView.gemtext_text_monospace_textview.text = line.substring(1).trim()
is GmiViewHolder.Quote -> {
when {
useAttentionGuides -> holder.itemView.gemtext_quote_textview.text = getAttentionGuideText(line.substring(1).trim())
else -> holder.itemView.gemtext_quote_textview.text = line.substring(1).trim()
}
}
is GmiViewHolder.H1 -> {
when {
line.length > 2 -> holder.itemView.gemtext_text_textview.text = line.substring(2).trim()
@ -108,7 +120,12 @@ class GemtextAdapter(
else -> holder.itemView.gemtext_text_textview.text = ""
}
}
is GmiViewHolder.ListItem -> holder.itemView.gemtext_text_textview.text = "${line.substring(1)}".trim()
is GmiViewHolder.ListItem -> {
when {
useAttentionGuides -> holder.itemView.gemtext_text_textview.text = getAttentionGuideText("${line.substring(1)}".trim())
else -> holder.itemView.gemtext_text_textview.text = "${line.substring(1)}".trim()
}
}
is GmiViewHolder.Link -> {
val linkParts = line.substring(2).trim().split("\\s+".toRegex(), 2)
var linkName = linkParts[0]
@ -184,11 +201,11 @@ class GemtextAdapter(
holder.itemView.gemtext_link_button.visible(true)
holder.itemView.gemtext_link_button.text = displayText
} else -> {
holder.itemView.gemtext_link_button.visible(false)
holder.itemView.gemtext_text_link.visible(true)
holder.itemView.gemtext_text_link.text = displayText
holder.itemView.gemtext_text_link.paint.isUnderlineText = true
}
holder.itemView.gemtext_link_button.visible(false)
holder.itemView.gemtext_text_link.visible(true)
holder.itemView.gemtext_text_link.text = displayText
holder.itemView.gemtext_text_link.paint.isUnderlineText = true
}
}
holder.itemView.gemtext_text_link.setOnClickListener {
@ -265,6 +282,35 @@ class GemtextAdapter(
return URI.create(linkParts.first())
}
private fun getAttentionGuideText(text: String): SpannableStringBuilder {
val wordList = text.split(" ")
val attentionGuideText = SpannableStringBuilder()
for(word in wordList){
if(word.length > 1){
if(word.first().isLetterOrDigit()){
val index = word.length/2
attentionGuideText
.bold{append(word.substring(0, index))}
.append("${word.substring(index)} ")
}else{
var offset = 1
while(!word.substring(offset).first().isLetterOrDigit()){
offset += 1
}
val index = (word.length - offset)/2
attentionGuideText
.append(word.substring(0, offset))
.bold{append(word.substring(offset, index + offset))}
.append("${word.substring(index + offset)} ")
}
}else{
attentionGuideText.append("$word ")
}
}
return attentionGuideText
}
override fun inferTitle(): String? {
lines.forEach { line ->
if(line.startsWith("#")) return line.replace("#", "").trim()
@ -288,6 +334,11 @@ class GemtextAdapter(
notifyDataSetChanged()
}
override fun attentionGuides(enabled: Boolean){
this.useAttentionGuides = enabled
notifyDataSetChanged()
}
override fun inlineImages(visible: Boolean){
this.showInlineImages = visible
notifyDataSetChanged()

View File

@ -14,7 +14,6 @@ import android.view.inputmethod.EditorInfo
import androidx.appcompat.app.AppCompatDelegate
import androidx.biometric.BiometricPrompt
import androidx.preference.*
import corewala.buran.BuildConfig
import corewala.buran.Buran
import corewala.buran.R
import corewala.buran.io.keymanager.BuranBiometricManager
@ -93,18 +92,18 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
appCategory.addPreference(searchPreference)
//Updates ---------------------------------------------
val aboutUpdater = Preference(context)
aboutUpdater.summary = getString(R.string.self_update_summary)
aboutUpdater.isPersistent = false
aboutUpdater.isSelectable = false
appCategory.addPreference(aboutUpdater)
val checkForUpdates = SwitchPreferenceCompat(context)
checkForUpdates.setDefaultValue(true)
checkForUpdates.key = "check_for_updates"
checkForUpdates.title = getString(R.string.check_for_updates)
appCategory.addPreference(checkForUpdates)
val isSideLoaded = context.packageManager.getInstallerPackageName(BuildConfig.APPLICATION_ID).isNullOrEmpty()
checkForUpdates.isVisible = isSideLoaded
if(!isSideLoaded){
checkForUpdates.equals(false)
}
//Certificates
buildClientCertificateSection(context, screen)
@ -232,6 +231,13 @@ class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChang
showLinkButtonsPreference.key = "show_link_buttons"
showLinkButtonsPreference.title = getString(R.string.show_link_buttons)
accessibilityCategory.addPreference(showLinkButtonsPreference)
//Accessibility - gemtext attention guides
val focusGuidingText = SwitchPreferenceCompat(context)
focusGuidingText.setDefaultValue(false)
focusGuidingText.key = "use_attention_guides"
focusGuidingText.title = getString(R.string.use_attention_guides)
accessibilityCategory.addPreference(focusGuidingText)
}
private fun buildClientCertificateSection(context: Context?, screen: PreferenceScreen) {

View File

@ -21,7 +21,7 @@
android:textSize="@dimen/code_text_size"
android:typeface="monospace"
android:textColor="@color/stroke"
android:id="@id/gemtext_text_monospace_textview"
android:id="@+id/gemtext_text_monospace_textview"
android:paddingLeft="@dimen/default_margin_big"
android:paddingTop="@dimen/default_margin_big"
android:paddingRight="@dimen/default_margin_big"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gemtext_text_monospace_textview"
android:id="@+id/gemtext_quote_textview"
android:textSize="@dimen/default_text_size"
android:textColor="@color/stroke"
android:layout_marginLeft="@dimen/screen_margin"

Binary file not shown.

View File

@ -63,7 +63,7 @@
<string name="web_content_label">Ouvrir les sites web en interne en utilisant des \'Onglets Personnalisés\', plutôt que d\'utiliser le navigateur par défaut. Cela pourrait vous aider à rester dans le Geminispace plutôt que d\'être distrait·e par le vaste web. Cela requiert un navigateur par défaut compatible.</string>
<string name="web_content_switch_label">Ouvrir en interne</string>
<string name="show_inline_images">Images locales en ligne</string>
<string name="pkcs_notice">Seuls les magasins de clés client PKCS12 sont actuellement supportés</string>
<string name="pkcs_notice">Seuls les magasins de clés client PKCS12 sont actuellement supportés.</string>
<string name="client_certificate">Certificat Client</string>
<string name="tap_to_select_client_certificate">Cliquez pour sélectionner un certificat client</string>
<string name="client_certificate_password">Mot de passe du Certificat Client</string>
@ -79,12 +79,14 @@
<string name="cert_unloaded">Certificat dechargé</string>
<string name="set_home_capsule">Choisir comme capsule d\'accueil</string>
<string name="check_for_updates">Vérifier pour des mises à jour</string>
<string name="self_update_summary">L\'instalation automatique des mises à jour ne fonctionne que si Bourane est installée manuellement.</string>
<string name="new_version_available">Nouvelle version disponible</string>
<string name="no_internet">Aucun accès internet</string>
<string name="history_cleared">Historique vidé</string>
<string name="runtime_cache_cleared">Cache d\'exécution vidé</string>
<string name="show_inline_icons">Icônes de lien en ligne</string>
<string name="show_link_buttons">Boutons de lien</string>
<string name="use_attention_guides">Utiliser des guides d\'attention</string>
<string name="bookmarks_empty">Vous n\'avez encore aucun marque-pages</string>
<string name="import_bookmarks">Importer des marque-pages</string>
<string name="export_bookmarks">Exporter des marque-pages</string>

View File

@ -63,7 +63,7 @@
<string name="web_content_label">Open websites internally using \'Custom Tabs\', instead of using the default browser. This might help you stay in Geminispace instead of being distracted by the wider web. Requires compatible default browser.</string>
<string name="web_content_switch_label">Open internally</string>
<string name="show_inline_images">Inline local images</string>
<string name="pkcs_notice">Only PKCS12 client keystores are currently supported</string>
<string name="pkcs_notice">Only PKCS12 client keystores are currently supported.</string>
<string name="client_certificate">Client Certificate</string>
<string name="tap_to_select_client_certificate">Tap to select client certificate</string>
<string name="client_certificate_password">Client Certificate Password</string>
@ -79,12 +79,14 @@
<string name="cert_unloaded">Certificate unloaded</string>
<string name="set_home_capsule">Set home capsule</string>
<string name="check_for_updates">Check for updates</string>
<string name="self_update_summary">Automatic update installation will only work if Buran is sideloaded.</string>
<string name="new_version_available">New version available</string>
<string name="no_internet">No internet access</string>
<string name="history_cleared">History cleared</string>
<string name="runtime_cache_cleared">Runtime cache cleared</string>
<string name="show_inline_icons">Inline link icons</string>
<string name="show_link_buttons">Show link buttons</string>
<string name="use_attention_guides">Use attention guides</string>
<string name="bookmarks_empty">You don\'t have any bookmarks yet</string>
<string name="import_bookmarks">Import bookmarks</string>
<string name="export_bookmarks">Export bookmarks</string>