diff --git a/app/src/main/java/oppen/ariane/Ariane.kt b/app/src/main/java/oppen/ariane/Ariane.kt index 0519758..4041339 100644 --- a/app/src/main/java/oppen/ariane/Ariane.kt +++ b/app/src/main/java/oppen/ariane/Ariane.kt @@ -9,6 +9,6 @@ class Ariane: Application() { const val GEMINI_USER_SEARCH_BASE = "gemini://gus.guru/search?" const val GEMINI_BACKLINK_BASE = "gemini://gus.guru/backlinks?" - const val FEATURE_INLINE_IMAGES = false + const val FEATURE_INLINE_IMAGES = true } } \ No newline at end of file diff --git a/app/src/main/java/oppen/ariane/io/gemini/GeminiDatasource.kt b/app/src/main/java/oppen/ariane/io/gemini/GeminiDatasource.kt index d8046fa..2fdd3df 100644 --- a/app/src/main/java/oppen/ariane/io/gemini/GeminiDatasource.kt +++ b/app/src/main/java/oppen/ariane/io/gemini/GeminiDatasource.kt @@ -22,8 +22,7 @@ const val GEMINI_SCHEME = "gemini" * */ class GeminiDatasource( - private val context: Context -): Datasource { + private val context: Context): Datasource { private val prefs = PreferenceManager.getDefaultSharedPreferences(context) private var last: URI? = null @@ -65,10 +64,15 @@ class GeminiDatasource( URI.create("gemini:$address") } address.startsWith("/") -> { - //internal navigation + //internal navigation/relative link val internalNav = "gemini://${last?.host}$address" URI.create(internalNav) } + address.startsWith("./") -> { + //internal navigation/relative link - with dot + val internalNav = "gemini://${last?.host}${address.substring(1)}" + URI.create(internalNav) + } !address.contains("://") -> { //looks like a relative link val lastAddress = last.toString() diff --git a/app/src/main/java/oppen/ariane/ui/GemActivity.kt b/app/src/main/java/oppen/ariane/ui/GemActivity.kt index ac7a216..998caa6 100644 --- a/app/src/main/java/oppen/ariane/ui/GemActivity.kt +++ b/app/src/main/java/oppen/ariane/ui/GemActivity.kt @@ -1,12 +1,9 @@ package oppen.ariane.ui import android.content.ActivityNotFoundException -import android.content.Context import android.content.Intent -import android.content.SharedPreferences import android.media.MediaPlayer import android.net.Uri -import android.os.Build import android.os.Bundle import android.view.inputmethod.EditorInfo 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.input.InputDialog 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.hideKeyboard import oppen.visibleRetainingSpace @@ -63,7 +59,15 @@ class GemActivity : AppCompatActivity() { LinkPopup.show(view, uri){ menuId -> when (menuId) { 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 -> { Intent().apply { diff --git a/app/src/main/java/oppen/ariane/ui/GemViewModel.kt b/app/src/main/java/oppen/ariane/ui/GemViewModel.kt index 2c08bfd..4f39477 100644 --- a/app/src/main/java/oppen/ariane/ui/GemViewModel.kt +++ b/app/src/main/java/oppen/ariane/ui/GemViewModel.kt @@ -1,5 +1,6 @@ package oppen.ariane.ui +import android.net.Uri import androidx.lifecycle.ViewModel import oppen.ariane.Ariane 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 @ExperimentalStdlibApi diff --git a/app/src/main/java/oppen/ariane/ui/GemtextAdapter.kt b/app/src/main/java/oppen/ariane/ui/GemtextAdapter.kt index a537180..2ba8e1e 100644 --- a/app/src/main/java/oppen/ariane/ui/GemtextAdapter.kt +++ b/app/src/main/java/oppen/ariane/ui/GemtextAdapter.kt @@ -1,6 +1,7 @@ package oppen.ariane.ui import android.annotation.SuppressLint +import android.net.Uri import android.view.LayoutInflater import android.view.View 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() { var lines = mutableListOf() - - var imageIndexes = arrayListOf() + var inlineImages = HashMap() private val typeText = 0 private val typeH1 = 1 @@ -39,6 +39,7 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B } fun render(lines: List){ + this.inlineImages.clear() this.lines.clear() this.lines.addAll(lines) notifyDataSetChanged() @@ -114,6 +115,7 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B val uri = getUri(lines[holder.adapterPosition]) println("User click link: $uri") onLink(this, uri, false, holder.adapterPosition, null) + } holder.itemView.gemtext_text_link.setOnLongClickListener {view -> val uri = getUri(lines[holder.adapterPosition]) @@ -122,12 +124,10 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B true } - if(imageIndexes.contains(holder.adapterPosition)){ + if(inlineImages.containsKey(position)){ holder.itemView.gemtext_inline_image.visible(true) - - //todo - need to download the image... - - } + holder.itemView.gemtext_inline_image.setImageURI(inlineImages[position]) + } } } } @@ -145,8 +145,8 @@ class GemtextAdapter(val onLink: (adapter: GemtextAdapter, link: URI, longTap: B return null } - fun loadImage(position: Int){ - imageIndexes.add(position) + fun loadImage(position: Int, cacheUri: Uri){ + inlineImages[position] = cacheUri notifyItemChanged(position) } } \ No newline at end of file diff --git a/app/src/main/java/oppen/ariane/ui/modals_menus/LinkPopup.kt b/app/src/main/java/oppen/ariane/ui/modals_menus/LinkPopup.kt index 01420bf..cccc32e 100644 --- a/app/src/main/java/oppen/ariane/ui/modals_menus/LinkPopup.kt +++ b/app/src/main/java/oppen/ariane/ui/modals_menus/LinkPopup.kt @@ -16,10 +16,10 @@ object LinkPopup { val inflater: MenuInflater = popup.menuInflater val path = uri.toString().toLowerCase() - if(Ariane.Companion.FEATURE_INLINE_IMAGES && - path.endsWith(".png") || + if(Ariane.FEATURE_INLINE_IMAGES && + (path.endsWith(".png") || path.endsWith(".jpg") || - path.endsWith(".jpeg")){ + path.endsWith(".jpeg"))){ inflater.inflate(R.menu.image_link_menu, popup.menu) }else{ inflater.inflate(R.menu.link_menu, popup.menu) diff --git a/app/src/main/java/oppen/ariane/ui/modals_menus/overflow/OverflowPopup.kt b/app/src/main/java/oppen/ariane/ui/modals_menus/overflow/OverflowPopup.kt index 54b08d6..60921c6 100644 --- a/app/src/main/java/oppen/ariane/ui/modals_menus/overflow/OverflowPopup.kt +++ b/app/src/main/java/oppen/ariane/ui/modals_menus/overflow/OverflowPopup.kt @@ -51,7 +51,7 @@ object OverflowPopup { * Converts the given MenuItem's title into a Spannable containing both its icon and title. */ 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) icon.setBounds(0, 0, iconSize, iconSize) icon.setTint(Color.WHITE) diff --git a/app/src/main/res/layout/gemtext_link.xml b/app/src/main/res/layout/gemtext_link.xml index a0a9f45..30782ad 100644 --- a/app/src/main/res/layout/gemtext_link.xml +++ b/app/src/main/res/layout/gemtext_link.xml @@ -19,6 +19,10 @@ android:id="@+id/gemtext_inline_image" android:layout_width="match_parent" 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:adjustViewBounds="true" android:layout_below="@+id/gemtext_text_link"/> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74d6024..8e23692 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,15 +3,14 @@ gemini:// Enter gemini:// address Enter search term - Copy address - Load image + Share address + Display inline About Address copied to clipboard Gemini address Share Set Home Settings - Home icon by Icongeek26 on FlatIcon.com Ariane: Gemini protocol client from Öppenlab GPL v3 Copyright © 2020 Öppenlab