mirror of
https://github.com/Corewala/Buran
synced 2025-03-11 22:53:08 +00:00
Attention guides for gemtext
This commit is contained in:
parent
a7877cfc41
commit
0b7e24e764
11 changed files with 102 additions and 57 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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{
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue