From a90ccec7077e270aef677946e772b954ea2b6e59 Mon Sep 17 00:00:00 2001
From: Amine <amine.bouabdallaoui@pm.me>
Date: Thu, 27 Feb 2025 21:40:06 +0100
Subject: [PATCH] fix: url can be empty ?

---
 .../android/fragments/ArticleFragment.kt      | 12 ++++----
 .../android/utils/AppUtils.kt                 | 30 ++++++++++---------
 .../android/utils/LinksUtils.kt               | 23 +++++++-------
 .../readerforselfossv2/model/SelfossModel.kt  | 10 ++-----
 4 files changed, 38 insertions(+), 37 deletions(-)

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 2093b6a..893dd34 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
@@ -75,7 +75,7 @@ class ArticleFragment :
     private var colorSurface: Int = 0
     private var fontSize: Int = DEFAULT_FONT_SIZE
     private lateinit var item: SelfossModel.Item
-    private lateinit var url: String
+    private var url: String? = null
     private lateinit var contentText: String
     private lateinit var contentSource: String
     private lateinit var contentImage: String
@@ -168,8 +168,8 @@ class ArticleFragment :
 
     private fun handleContent() {
         if (contentText.isEmptyOrNullOrNullString()) {
-            if (repository.isNetworkAvailable()) {
-                getContentFromMercury()
+            if (repository.isNetworkAvailable() && url.isUrlValid()) {
+                getContentFromMercury(url!!)
             }
         } else {
             binding.titleView.text = contentTitle
@@ -271,7 +271,7 @@ class ArticleFragment :
     }
 
     @Suppress("detekt:SwallowedException")
-    private fun getContentFromMercury() {
+    private fun getContentFromMercury(url: String) {
         binding.progressBar.visibility = View.VISIBLE
 
         CoroutineScope(Dispatchers.Main).launch {
@@ -424,10 +424,10 @@ class ArticleFragment :
 
         var baseUrl: String? = null
         try {
-            val itemUrl = URL(url)
+            val itemUrl = URL(url.orEmpty())
             baseUrl = itemUrl.protocol + "://" + itemUrl.host
         } catch (e: MalformedURLException) {
-            e.sendSilentlyWithAcraWithName("htmlToWebview > $url")
+            e.sendSilentlyWithAcraWithName("htmlToWebview > ${url.orEmpty()}")
         }
 
         val fontName: String =
diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt
index 77d0311..23df1f1 100644
--- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt
+++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt
@@ -11,22 +11,24 @@ import bou.amine.apps.readerforselfossv2.android.utils.acra.sendSilentlyWithAcra
 import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp
 
 fun Context.shareLink(
-    itemUrl: String,
+    itemUrl: String?,
     itemTitle: String,
 ) {
-    val sendIntent = Intent()
-    sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
-    sendIntent.action = Intent.ACTION_SEND
-    sendIntent.putExtra(Intent.EXTRA_TEXT, itemUrl.toStringUriWithHttp())
-    sendIntent.putExtra(Intent.EXTRA_SUBJECT, itemTitle)
-    sendIntent.type = "text/plain"
-    startActivity(
-        Intent
-            .createChooser(
-                sendIntent,
-                getString(R.string.share),
-            ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
-    )
+    if (itemUrl.isUrlValid()) {
+        val sendIntent = Intent()
+        sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+        sendIntent.action = Intent.ACTION_SEND
+        sendIntent.putExtra(Intent.EXTRA_TEXT, itemUrl!!.toStringUriWithHttp())
+        sendIntent.putExtra(Intent.EXTRA_SUBJECT, itemTitle)
+        sendIntent.type = "text/plain"
+        startActivity(
+            Intent
+                .createChooser(
+                    sendIntent,
+                    getString(R.string.share),
+                ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+        )
+    }
 }
 
 @ColorInt
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 1df697f..2e71ee7 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
@@ -15,12 +15,12 @@ import android.widget.Toast
 import bou.amine.apps.readerforselfossv2.android.R
 import bou.amine.apps.readerforselfossv2.android.ReaderActivity
 import bou.amine.apps.readerforselfossv2.model.SelfossModel
-import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp
+import bou.amine.apps.readerforselfossv2.utils.isEmptyOrNullOrNullString
 import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
 
 fun Context.openItemUrl(
     currentItem: Int,
-    linkDecoded: String,
+    linkDecoded: String?,
     articleViewer: Boolean,
     app: Activity,
 ) {
@@ -37,12 +37,13 @@ fun Context.openItemUrl(
             intent.putExtra("currentItem", currentItem)
             app.startActivity(intent)
         } else {
-            this.openUrlInBrowserAsNewTask(linkDecoded)
+            this.openUrlInBrowserAsNewTask(linkDecoded!!)
         }
     }
 }
 
-fun String.isUrlValid(): Boolean = this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches()
+fun String?.isUrlValid(): Boolean =
+    !this.isEmptyOrNullOrNullString() && this!!.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches()
 
 fun String.isBaseUrlInvalid(): Boolean {
     val baseUrl = this.toHttpUrlOrNull()
@@ -56,14 +57,16 @@ fun String.isBaseUrlInvalid(): Boolean {
 }
 
 fun Context.openItemUrlInBrowserAsNewTask(i: SelfossModel.Item) {
-    this.openUrlInBrowserAsNewTask(i.getLinkDecoded().toStringUriWithHttp())
+    this.openUrlInBrowserAsNewTask(i.getLinkDecoded())
 }
 
-fun Context.openUrlInBrowserAsNewTask(url: String) {
-    val intent = Intent(Intent.ACTION_VIEW)
-    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
-    intent.data = Uri.parse(url)
-    this.mayBeStartActivity(intent)
+fun Context.openUrlInBrowserAsNewTask(url: String?) {
+    if (url.isUrlValid()) {
+        val intent = Intent(Intent.ACTION_VIEW)
+        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+        intent.data = Uri.parse(url)
+        this.mayBeStartActivity(intent)
+    }
 }
 
 fun Context.openUrlInBrowser(url: String) {
diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt
index 8f1f74c..085d52d 100644
--- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt
+++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt
@@ -127,8 +127,8 @@ class SelfossModel {
         val tags: List<String>,
         val author: String? = null,
     ) {
-        fun getLinkDecoded(): String {
-            var stringUrl: String
+        fun getLinkDecoded(): String? {
+            var stringUrl: String?
             stringUrl =
                 if (link.contains("//news.google.com/news/") && link.contains("&amp;url=")) {
                     link.substringAfter("&amp;url=")
@@ -146,11 +146,7 @@ class SelfossModel {
                 stringUrl = "http:$stringUrl"
             }
 
-            if (stringUrl.isEmptyOrNullOrNullString()) {
-                throw ModelException("Link $link was translated to $stringUrl, but was empty. Handle this.")
-            }
-
-            return stringUrl
+            return if (stringUrl.isEmptyOrNullOrNullString()) null else stringUrl
         }
 
         fun sourceAuthorAndDate(): String {