fix ./ relative url linking, add inline image feature

This commit is contained in:
Jonathan Fisher 2020-11-12 23:04:15 +00:00
parent e4669d9592
commit e5a26ce3a2
9 changed files with 46 additions and 25 deletions

View File

@ -9,6 +9,6 @@ class Ariane: Application() {
const val GEMINI_USER_SEARCH_BASE = "gemini://gus.guru/search?" const val GEMINI_USER_SEARCH_BASE = "gemini://gus.guru/search?"
const val GEMINI_BACKLINK_BASE = "gemini://gus.guru/backlinks?" const val GEMINI_BACKLINK_BASE = "gemini://gus.guru/backlinks?"
const val FEATURE_INLINE_IMAGES = false const val FEATURE_INLINE_IMAGES = true
} }
} }

View File

@ -22,8 +22,7 @@ const val GEMINI_SCHEME = "gemini"
* *
*/ */
class GeminiDatasource( class GeminiDatasource(
private val context: Context private val context: Context): Datasource {
): Datasource {
private val prefs = PreferenceManager.getDefaultSharedPreferences(context) private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
private var last: URI? = null private var last: URI? = null
@ -65,10 +64,15 @@ class GeminiDatasource(
URI.create("gemini:$address") URI.create("gemini:$address")
} }
address.startsWith("/") -> { address.startsWith("/") -> {
//internal navigation //internal navigation/relative link
val internalNav = "gemini://${last?.host}$address" val internalNav = "gemini://${last?.host}$address"
URI.create(internalNav) URI.create(internalNav)
} }
address.startsWith("./") -> {
//internal navigation/relative link - with dot
val internalNav = "gemini://${last?.host}${address.substring(1)}"
URI.create(internalNav)
}
!address.contains("://") -> { !address.contains("://") -> {
//looks like a relative link //looks like a relative link
val lastAddress = last.toString() val lastAddress = last.toString()

View File

@ -1,12 +1,9 @@
package oppen.ariane.ui package oppen.ariane.ui
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.media.MediaPlayer import android.media.MediaPlayer
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.activity.viewModels import androidx.activity.viewModels
@ -35,7 +32,6 @@ import oppen.ariane.ui.modals_menus.about.AboutDialog
import oppen.ariane.ui.modals_menus.history.HistoryDialog import oppen.ariane.ui.modals_menus.history.HistoryDialog
import oppen.ariane.ui.modals_menus.input.InputDialog import oppen.ariane.ui.modals_menus.input.InputDialog
import oppen.ariane.ui.modals_menus.overflow.OverflowPopup import oppen.ariane.ui.modals_menus.overflow.OverflowPopup
import oppen.ariane.ui.modals_menus.set_home.SetHomeDialog
import oppen.ariane.ui.settings.SettingsActivity import oppen.ariane.ui.settings.SettingsActivity
import oppen.hideKeyboard import oppen.hideKeyboard
import oppen.visibleRetainingSpace import oppen.visibleRetainingSpace
@ -63,7 +59,15 @@ class GemActivity : AppCompatActivity() {
LinkPopup.show(view, uri){ menuId -> LinkPopup.show(view, uri){ menuId ->
when (menuId) { when (menuId) {
R.id.link_menu_load_image -> { R.id.link_menu_load_image -> {
adapter.loadImage(position) loadingView(true)
model.requestInlineImage(uri){ imageUri ->
imageUri?.let{
runOnUiThread {
loadingView(false)
adapter.loadImage(position, imageUri)
}
}
}
} }
R.id.link_menu_copy -> { R.id.link_menu_copy -> {
Intent().apply { Intent().apply {

View File

@ -1,5 +1,6 @@
package oppen.ariane.ui package oppen.ariane.ui
import android.net.Uri
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import oppen.ariane.Ariane import oppen.ariane.Ariane
import oppen.ariane.io.gemini.Datasource import oppen.ariane.io.gemini.Datasource
@ -42,6 +43,15 @@ class GemViewModel: ViewModel() {
} }
} }
fun requestInlineImage(uri: URI, onImageReady: (cacheUri: Uri?) -> Unit){
gemini.request(uri){ state ->
when (state) {
is GemState.ResponseImage -> onImageReady(state.cacheUri)
else -> onState(state)
}
}
}
fun canGoBack(): Boolean = history.size > 1 fun canGoBack(): Boolean = history.size > 1
@ExperimentalStdlibApi @ExperimentalStdlibApi

View File

@ -1,6 +1,7 @@
package oppen.ariane.ui package oppen.ariane.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.net.Uri
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -15,8 +16,7 @@ import java.net.URI
class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: Boolean, adapterPosition: Int, 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 lines = mutableListOf<String>()
var inlineImages = HashMap<Int, Uri>()
var imageIndexes = arrayListOf<Int>()
private val typeText = 0 private val typeText = 0
private val typeH1 = 1 private val typeH1 = 1
@ -39,6 +39,7 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B
} }
fun render(lines: List<String>){ fun render(lines: List<String>){
this.inlineImages.clear()
this.lines.clear() this.lines.clear()
this.lines.addAll(lines) this.lines.addAll(lines)
notifyDataSetChanged() notifyDataSetChanged()
@ -114,6 +115,7 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B
val uri = getUri(lines[holder.adapterPosition]) val uri = getUri(lines[holder.adapterPosition])
println("User click link: $uri") println("User click link: $uri")
onLink(this, uri, false, holder.adapterPosition, null) onLink(this, uri, false, holder.adapterPosition, null)
} }
holder.itemView.gemtext_text_link.setOnLongClickListener {view -> holder.itemView.gemtext_text_link.setOnLongClickListener {view ->
val uri = getUri(lines[holder.adapterPosition]) val uri = getUri(lines[holder.adapterPosition])
@ -122,12 +124,10 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B
true true
} }
if(imageIndexes.contains(holder.adapterPosition)){ if(inlineImages.containsKey(position)){
holder.itemView.gemtext_inline_image.visible(true) holder.itemView.gemtext_inline_image.visible(true)
holder.itemView.gemtext_inline_image.setImageURI(inlineImages[position])
//todo - need to download the image... }
}
} }
} }
} }
@ -145,8 +145,8 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B
return null return null
} }
fun loadImage(position: Int){ fun loadImage(position: Int, cacheUri: Uri){
imageIndexes.add(position) inlineImages[position] = cacheUri
notifyItemChanged(position) notifyItemChanged(position)
} }
} }

View File

@ -16,10 +16,10 @@ object LinkPopup {
val inflater: MenuInflater = popup.menuInflater val inflater: MenuInflater = popup.menuInflater
val path = uri.toString().toLowerCase() val path = uri.toString().toLowerCase()
if(Ariane.Companion.FEATURE_INLINE_IMAGES && if(Ariane.FEATURE_INLINE_IMAGES &&
path.endsWith(".png") || (path.endsWith(".png") ||
path.endsWith(".jpg") || path.endsWith(".jpg") ||
path.endsWith(".jpeg")){ path.endsWith(".jpeg"))){
inflater.inflate(R.menu.image_link_menu, popup.menu) inflater.inflate(R.menu.image_link_menu, popup.menu)
}else{ }else{
inflater.inflate(R.menu.link_menu, popup.menu) inflater.inflate(R.menu.link_menu, popup.menu)

View File

@ -51,7 +51,7 @@ object OverflowPopup {
* Converts the given MenuItem's title into a Spannable containing both its icon and title. * Converts the given MenuItem's title into a Spannable containing both its icon and title.
*/ */
private fun insertMenuItemIcon(context: Context, menuItem: MenuItem) { private fun insertMenuItemIcon(context: Context, menuItem: MenuItem) {
var icon: Drawable = menuItem.icon val icon: Drawable = menuItem.icon
val iconSize = context.resources.getDimensionPixelSize(R.dimen.menu_item_icon_size) val iconSize = context.resources.getDimensionPixelSize(R.dimen.menu_item_icon_size)
icon.setBounds(0, 0, iconSize, iconSize) icon.setBounds(0, 0, iconSize, iconSize)
icon.setTint(Color.WHITE) icon.setTint(Color.WHITE)

View File

@ -19,6 +19,10 @@
android:id="@+id/gemtext_inline_image" android:id="@+id/gemtext_inline_image"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/screen_margin"
android:layout_marginRight="@dimen/screen_margin"
android:layout_marginTop="@dimen/default_margin"
android:visibility="gone" android:visibility="gone"
android:adjustViewBounds="true"
android:layout_below="@+id/gemtext_text_link"/> android:layout_below="@+id/gemtext_text_link"/>
</RelativeLayout> </RelativeLayout>

View File

@ -3,15 +3,14 @@
<string name="gemini_protocol">gemini://</string> <string name="gemini_protocol">gemini://</string>
<string name="main_input_hint">Enter gemini:// address</string> <string name="main_input_hint">Enter gemini:// address</string>
<string name="main_input_search_hint">Enter search term</string> <string name="main_input_search_hint">Enter search term</string>
<string name="copy_address">Copy address</string> <string name="copy_address">Share address</string>
<string name="load_image">Load image</string> <string name="load_image">Display inline</string>
<string name="about">About</string> <string name="about">About</string>
<string name="address_copied_to_clipboard">Address copied to clipboard</string> <string name="address_copied_to_clipboard">Address copied to clipboard</string>
<string name="gemini_address">Gemini address</string> <string name="gemini_address">Gemini address</string>
<string name="share">Share</string> <string name="share">Share</string>
<string name="set_home">Set Home</string> <string name="set_home">Set Home</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="home_icon_attribution">Home icon by Icongeek26 on FlatIcon.com</string>
<string name="about_body">Ariane: Gemini protocol client from Öppenlab</string> <string name="about_body">Ariane: Gemini protocol client from Öppenlab</string>
<string name="gnu_link">GPL v3</string> <string name="gnu_link">GPL v3</string>
<string name="copyright">Copyright © 2020 Öppenlab</string> <string name="copyright">Copyright © 2020 Öppenlab</string>