process text implementation

This commit is contained in:
Jonathan Fisher 2020-11-09 19:30:53 +00:00
parent 19bbd1e303
commit 29f1ccc00e
12 changed files with 124 additions and 48 deletions

View File

@ -10,7 +10,8 @@ A Gemini protocol browser for Android based OS. Formerly called Två, and briefl
## Releases
See the project page on Öppenlab.net for latest download: [oppenlab.net/pr/ariane](https://oppenlab.net/pr/ariane/)
* See the project page on Öppenlab.net for latest download: [oppenlab.net/pr/ariane](https://oppenlab.net/pr/ariane/)
* Install on [Google Play](https://play.google.com/store/apps/details?id=oppen.gemini.ariane)
## Issue tracker

View File

@ -60,7 +60,6 @@ dependencies {
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

View File

@ -18,4 +18,19 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class * extends com.bumptech.glide.module.AppGlideModule {
<init>(...);
}
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
*** rewind();
}
# for DexGuard only
# -keepresourcexmlelements manifest/application/meta-data@value=GlideModule

View File

@ -14,17 +14,19 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="oppen.ariane.ui.ProcessTextActivity" android:label="Open in Ariane" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="oppen.ariane.ui.GemActivity"
android:label="Open in Ariane">
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />

View File

@ -193,7 +193,7 @@ class GeminiDatasource(val context: Context): Datasource {
val bufferedReader = BufferedReader(headerInputReader)
val headerLine = bufferedReader.readLine()
println("Tva: header: $headerLine")
println("Ariane: response header: $headerLine")
val header = GeminiResponse.parseHeader(headerLine)
@ -246,8 +246,6 @@ class GeminiDatasource(val context: Context): Datasource {
val filenameRegex = Regex("[^A-Za-z0-9]")
val cacheFile = File(context.cacheDir, filenameRegex.replace(uri.path, "_"))
when {
cacheFile.exists() -> {
when {

View File

@ -55,10 +55,13 @@ class GemActivity : AppCompatActivity() {
private val model by viewModels<GemViewModel>()
private lateinit var binding: ActivityGemBinding
private lateinit var history: HistoryInterface
private val adapter = GemtextAdapter { uri, longTap, view ->
private val adapter = GemtextAdapter { adapter, uri, longTap, position: Int, view ->
if(longTap){
LinkPopup.show(view){ menuId ->
LinkPopup.show(view, uri){ menuId ->
when (menuId) {
R.id.link_menu_load_image -> {
adapter.loadImage(position)
}
R.id.link_menu_copy -> {
Intent().apply {
action = Intent.ACTION_SEND
@ -219,7 +222,15 @@ class GemActivity : AppCompatActivity() {
model.request(address)
}
checkIntentExtras()
checkIntentExtras(intent)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.let{
checkIntentExtras(intent)
}
}
/**
@ -227,39 +238,23 @@ class GemActivity : AppCompatActivity() {
* Checks intent to see if Activity was opened to handle selected text
*
*/
private fun checkIntentExtras() {
private fun checkIntentExtras(intent: Intent) {
//First check if there's a uri from a web link or other
//Via ProcessTextActivity from selected text in another app
if(intent.hasExtra("process_text")){
val processText = intent.getStringExtra("process_text")
binding.addressEdit.setText(processText)
model.request(processText ?: "")
return
}
//From clicking a gemini:// address
val uri = intent.data
if(uri != null){
binding.addressEdit.setText(uri.toString())
model.request(uri.toString())
return
}
//Then check if we've arrived here via some selected text
val processText = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
intent.hasExtra(Intent.EXTRA_PROCESS_TEXT) -> {
intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT).toString()
}
else -> {
null
}
}
processText?.let { text ->
if (text.startsWith("gemini://")) {
binding.addressEdit.setText(text)
model.request(text)
} else {
Snackbar.make(binding.root, "$text is not a valid Gemini address", Snackbar.LENGTH_SHORT).show()
}
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.data.toString().let{model.request(it)}
}
private fun showAlert(message: String) = runOnUiThread{

View File

@ -9,12 +9,15 @@ import kotlinx.android.synthetic.main.gemtext_code_block.view.*
import kotlinx.android.synthetic.main.gemtext_link.view.*
import kotlinx.android.synthetic.main.gemtext_text.view.gemtext_text_textview
import oppen.ariane.R
import oppen.visible
import java.net.URI
class GemtextAdapter(val onLink: (link: URI, longTap: Boolean, view: View?) -> Unit): RecyclerView.Adapter<GemtextAdapter.ViewHolder>() {
class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: Boolean, adapterPosition: Int, view: View?) -> Unit): RecyclerView.Adapter<GemtextAdapter.ViewHolder>() {
var lines = mutableListOf<String>()
var imageIndexes = arrayListOf<Int>()
private val typeText = 0
private val typeH1 = 1
private val typeH2 = 2
@ -110,14 +113,21 @@ class GemtextAdapter(val onLink: (link: URI, longTap: Boolean, view: View?) -> U
holder.itemView.gemtext_text_link.setOnClickListener {
val uri = getUri(lines[holder.adapterPosition])
println("User click link: $uri")
onLink(uri, false, null)
onLink(this, uri, false, holder.adapterPosition, null)
}
holder.itemView.gemtext_text_link.setOnLongClickListener {view ->
val uri = getUri(lines[holder.adapterPosition])
println("User click link: $uri")
onLink(uri, true, view)
onLink(this, uri, true, holder.adapterPosition, view)
true
}
if(imageIndexes.contains(holder.adapterPosition)){
holder.itemView.gemtext_inline_image.visible(true)
//todo - need to download the image...
}
}
}
}
@ -134,4 +144,9 @@ class GemtextAdapter(val onLink: (link: URI, longTap: Boolean, view: View?) -> U
return null
}
fun loadImage(position: Int){
imageIndexes.add(position)
notifyItemChanged(position)
}
}

View File

@ -0,0 +1,24 @@
package oppen.ariane.ui
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class ProcessTextActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val processText = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && intent.hasExtra(Intent.EXTRA_PROCESS_TEXT) -> intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT).toString()
else -> null
}
Intent(this, GemActivity::class.java).run {
putExtra("process_text", processText)
startActivity(this)
finish()
}
}
}

View File

@ -4,15 +4,23 @@ import android.view.MenuInflater
import android.view.View
import androidx.appcompat.widget.PopupMenu
import oppen.ariane.R
import java.net.URI
object LinkPopup {
fun show(view: View?, onMenuOption: (menuId: Int) -> Unit){
fun show(view: View?, uri: URI, onMenuOption: (menuId: Int) -> Unit){
if(view != null) {
val popup = PopupMenu(view.context, view)
val inflater: MenuInflater = popup.menuInflater
inflater.inflate(R.menu.link_menu, popup.menu)
val path = uri.toString().toLowerCase()
if(path.endsWith(".png") || path.endsWith(".jpg") || path.endsWith(".jpeg")){
inflater.inflate(R.menu.image_link_menu, popup.menu)
}else{
inflater.inflate(R.menu.link_menu, popup.menu)
}
popup.setOnMenuItemClickListener { menuItem ->
onMenuOption(menuItem.itemId)
true

View File

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatTextView
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/gemtext_text_link"
android:textColor="@color/stroke"
android:textSize="@dimen/default_text_size"
@ -10,4 +13,12 @@
android:layout_marginLeft="@dimen/screen_margin"
android:layout_marginRight="@dimen/screen_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_height="wrap_content" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/gemtext_inline_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_below="@+id/gemtext_text_link"/>
</RelativeLayout>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/link_menu_load_image"
android:title="@string/load_image" />
<item android:id="@+id/link_menu_copy"
android:title="@string/copy_address" />
</menu>

View File

@ -4,6 +4,7 @@
<string name="main_input_hint">Enter gemini:// address</string>
<string name="main_input_search_hint">Enter search term</string>
<string name="copy_address">Copy address</string>
<string name="load_image">Load image</string>
<string name="about">About</string>
<string name="address_copied_to_clipboard">Address copied to clipboard</string>
<string name="gemini_address">Gemini address</string>