diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt index 5b63a33..84a85e8 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt @@ -1,7 +1,6 @@ package bou.amine.apps.readerforselfossv2.android import android.content.Intent -import android.net.Uri import android.os.Bundle import android.view.Menu import android.view.MenuItem @@ -32,6 +31,7 @@ import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity import bou.amine.apps.readerforselfossv2.android.testing.CountingIdlingResourceSingleton import bou.amine.apps.readerforselfossv2.android.utils.bottombar.maybeShow import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge +import bou.amine.apps.readerforselfossv2.android.utils.openUrlInBrowser import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.service.AppSettingsService @@ -589,9 +589,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.issue_tracker -> { - val browserIntent = - Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl)) - startActivity(browserIntent) + baseContext.openUrlInBrowser(AppSettingsService.trackerUrl) return true } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt index 2175fd7..ec54db8 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemCardAdapter.kt @@ -12,7 +12,7 @@ import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularDrawable -import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask +import bou.amine.apps.readerforselfossv2.android.utils.openItemUrlInBrowserAsNewTask import bou.amine.apps.readerforselfossv2.android.utils.shareLink import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository @@ -71,7 +71,7 @@ class ItemCardAdapter( } binding.browserBtn.setOnClickListener { - c.openInBrowserAsNewTask(items[position]) + c.openItemUrlInBrowserAsNewTask(items[position]) } } @@ -126,4 +126,4 @@ class ItemCardAdapter( } inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) -} +} \ No newline at end of file diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt index 4f052e6..749ca41 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt @@ -1,16 +1,20 @@ package bou.amine.apps.readerforselfossv2.android.fragments -import android.content.ActivityNotFoundException import android.content.Intent import android.content.res.ColorStateList import android.content.res.TypedArray import android.graphics.Bitmap import android.graphics.Typeface import android.graphics.drawable.ColorDrawable -import android.net.Uri import android.os.Bundle import android.util.TypedValue -import android.view.* +import android.view.GestureDetector +import android.view.InflateException +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup import android.webkit.WebResourceResponse import android.webkit.WebSettings import android.webkit.WebView @@ -28,7 +32,8 @@ import bou.amine.apps.readerforselfossv2.android.model.toParcelable import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream import bou.amine.apps.readerforselfossv2.android.utils.isUrlValid -import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask +import bou.amine.apps.readerforselfossv2.android.utils.openItemUrlInBrowserAsNewTask +import bou.amine.apps.readerforselfossv2.android.utils.openUrlInBrowser import bou.amine.apps.readerforselfossv2.android.utils.shareLink import bou.amine.apps.readerforselfossv2.model.MercuryModel import bou.amine.apps.readerforselfossv2.model.SelfossModel @@ -53,7 +58,7 @@ import org.kodein.di.android.x.closestDI import org.kodein.di.instance import java.net.MalformedURLException import java.net.URL -import java.util.* +import java.util.Locale import java.util.concurrent.ExecutionException private const val IMAGE_JPG = "image/jpg" @@ -211,7 +216,7 @@ class ArticleFragment : Fragment(), DIAware { override fun onItemClick(item: MenuItem) { when (item.itemId) { R.id.share_action -> requireActivity().shareLink(url, contentTitle) - R.id.open_action -> requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item) + R.id.open_action -> requireActivity().openItemUrlInBrowserAsNewTask(this@ArticleFragment.item) R.id.unread_action -> if (context != null) { if (this@ArticleFragment.item.unread) { @@ -236,6 +241,7 @@ class ArticleFragment : Fragment(), DIAware { ).show() } } + else -> Unit } } @@ -288,7 +294,7 @@ class ArticleFragment : Fragment(), DIAware { contentText = data.content.orEmpty() htmlToWebview() - handleLeadImage(data?.lead_image_url) + handleLeadImage(data.lead_image_url) binding.nestedScrollView.scrollTo(0, 0) binding.progressBar.visibility = View.GONE @@ -320,11 +326,7 @@ class ArticleFragment : Fragment(), DIAware { url: String, ): Boolean { return if (context != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { - try { - requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) - } catch (e: ActivityNotFoundException) { - e.sendSilentlyWithAcraWithName("activityNotFound > $url") - } + requireContext().openUrlInBrowser(url) true } else { false @@ -343,7 +345,8 @@ class ArticleFragment : Fragment(), DIAware { ) { try { val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() + Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() + .get() return WebResourceResponse( IMAGE_JPG, "UTF-8", @@ -355,7 +358,8 @@ class ArticleFragment : Fragment(), DIAware { } else if (url.lowercase(Locale.US).contains(".png")) { try { val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() + Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() + .get() return WebResourceResponse( IMAGE_JPG, "UTF-8", @@ -367,7 +371,8 @@ class ArticleFragment : Fragment(), DIAware { } else if (url.lowercase(Locale.US).contains(".webp")) { try { val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() + Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() + .get() return WebResourceResponse( IMAGE_JPG, "UTF-8", @@ -545,7 +550,7 @@ class ArticleFragment : Fragment(), DIAware { private fun openInBrowserAfterFailing() { binding.progressBar.visibility = View.GONE if (context != null) { - requireContext().openInBrowserAsNewTask(this@ArticleFragment.item) + requireContext().openItemUrlInBrowserAsNewTask(this@ArticleFragment.item) } else { Exception("openInBrowserAfterFailing context is null").sendSilentlyWithAcraWithName("openInBrowserAfterFailing > $context") } @@ -565,9 +570,9 @@ class ArticleFragment : Fragment(), DIAware { fun performClick(): Boolean { if (allImages != null && ( - binding.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || - binding.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE - ) + binding.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || + binding.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE + ) ) { val position: Int = allImages.indexOf(binding.webcontent.hitTestResult.extra) @@ -579,4 +584,4 @@ class ArticleFragment : Fragment(), DIAware { } return false } -} +} \ No newline at end of file diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/settings/SettingsActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/settings/SettingsActivity.kt index c6034a1..9c6caa2 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/settings/SettingsActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/settings/SettingsActivity.kt @@ -1,7 +1,5 @@ package bou.amine.apps.readerforselfossv2.android.settings -import android.content.Intent -import android.net.Uri import android.os.Bundle import android.text.Editable import android.text.InputFilter @@ -17,6 +15,7 @@ import androidx.preference.PreferenceFragmentCompat import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName +import bou.amine.apps.readerforselfossv2.android.utils.openUrlInBrowser import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.mikepenz.aboutlibraries.LibsBuilder import org.kodein.di.DIAware @@ -237,9 +236,8 @@ class SettingsActivity : } class LinksPreferenceFragment : PreferenceFragmentCompat() { - private fun openUrl(uri: Uri?) { - val browserIntent = Intent(Intent.ACTION_VIEW, uri) - startActivity(browserIntent) + private fun openUrl(url: String) { + context?.openUrlInBrowser(url) } override fun onCreatePreferences( @@ -250,19 +248,19 @@ class SettingsActivity : preferenceManager.findPreference("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(AppSettingsService.trackerUrl)) + openUrl(AppSettingsService.trackerUrl) true } preferenceManager.findPreference("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(AppSettingsService.sourceUrl)) + openUrl(AppSettingsService.sourceUrl) false } preferenceManager.findPreference("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(AppSettingsService.translationUrl)) + openUrl(AppSettingsService.translationUrl) false } } @@ -276,4 +274,4 @@ class SettingsActivity : setPreferencesFromResource(R.xml.pref_experimental, rootKey) } } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt index a5e6d2a..ddc4752 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt @@ -1,6 +1,7 @@ package bou.amine.apps.readerforselfossv2.android.utils import android.app.Activity +import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.net.Uri @@ -17,6 +18,7 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp import okhttp3.HttpUrl.Companion.toHttpUrlOrNull + fun Context.openItemUrl( currentItem: Int, linkDecoded: String, @@ -35,15 +37,13 @@ fun Context.openItemUrl( intent.putExtra("currentItem", currentItem) app.startActivity(intent) } else { - val intent = Intent(Intent.ACTION_VIEW) - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - intent.data = Uri.parse(linkDecoded.toStringUriWithHttp()) - startActivity(intent) + this.openUrlInBrowserAsNewTask(linkDecoded) } } } -fun String.isUrlValid(): Boolean = this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches() +fun String.isUrlValid(): Boolean = + this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches() fun String.isBaseUrlInvalid(): Boolean { val baseUrl = this.toHttpUrlOrNull() @@ -56,11 +56,31 @@ fun String.isBaseUrlInvalid(): Boolean { return !(Patterns.WEB_URL.matcher(this).matches() && existsAndEndsWithSlash) } -fun Context.openInBrowserAsNewTask(i: SelfossModel.Item) { +fun Context.openItemUrlInBrowserAsNewTask(i: SelfossModel.Item) { + this.openUrlInBrowserAsNewTask(i.getLinkDecoded().toStringUriWithHttp()) +} + +fun Context.openUrlInBrowserAsNewTask(url: String) { + val intent = Intent(Intent.ACTION_VIEW) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - intent.data = Uri.parse(i.getLinkDecoded().toStringUriWithHttp()) - startActivity(intent) + intent.data = Uri.parse(url) + this.mayBeStartActivity(intent) +} + +fun Context.openUrlInBrowser(url: String) { + val intent = Intent(Intent.ACTION_VIEW) + intent.data = Uri.parse(url) + this.mayBeStartActivity(intent) +} + +fun Context.mayBeStartActivity(intent: Intent) { + try { + this.startActivity(intent) + } catch (e: ActivityNotFoundException) { + Toast.makeText(this, getString(R.string.no_browser), Toast.LENGTH_SHORT).show() + } + } class LinkOnTouchListener : View.OnTouchListener { @@ -102,4 +122,4 @@ class LinkOnTouchListener : View.OnTouchListener { } return ret } -} +} \ No newline at end of file