From baca7cffed60f9b2c0de398025a8bcdfc0297c9c Mon Sep 17 00:00:00 2001 From: davidoskky Date: Thu, 13 Jul 2023 14:51:17 +0200 Subject: [PATCH 01/12] Upgrade to gradle 8 --- androidApp/build.gradle.kts | 15 +++++------ build.gradle.kts | 10 +++---- gradle.properties | 9 +------ gradle/wrapper/gradle-wrapper.properties | 6 ++--- shared/build.gradle.kts | 33 +++++++++++++----------- 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 63dae0c..f333042 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -8,7 +8,7 @@ plugins { kotlin("android") kotlin("kapt") id("com.mikepenz.aboutlibraries.plugin") - id("org.jetbrains.kotlinx.kover") version "0.6.1" + id("org.jetbrains.kotlinx.kover") } fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { @@ -16,7 +16,7 @@ fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { project.exec { commandLine = cmd.split(" ") standardOutput = outputStream - isIgnoreExitValue = ignore ?: false + isIgnoreExitValue = ignore } outputStream.toString() } @@ -24,9 +24,8 @@ fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { } fun gitVersion(): String { - var process = "" val maybeTagOfCurrentCommit = execWithOutput("git -C ../ describe --contains HEAD", true) - process = if (maybeTagOfCurrentCommit.isEmpty()) { + var process = if (maybeTagOfCurrentCommit.isEmpty()) { println("No tag on current commit. Will take the latest one.") execWithOutput("git -C ../ for-each-ref refs/tags --sort=-refname --format='%(refname:short)' --count=1") } else { @@ -58,13 +57,13 @@ android { compileOptions { isCoreLibraryDesugaringEnabled = true // Flag to enable support for the new language APIs - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } // For Kotlin projects kotlinOptions { - jvmTarget = "11" + jvmTarget = "17" } compileSdk = 33 buildToolsVersion = "33.0.0" @@ -171,7 +170,7 @@ dependencies { //PhotoView implementation("com.github.chrisbanes:PhotoView:2.3.0") - implementation("androidx.core:core-ktx:1.8.0") + implementation("androidx.core:core-ktx:1.10.1") implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") diff --git a/build.gradle.kts b/build.gradle.kts index f20c5f3..814db5b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,12 +7,12 @@ buildscript { plugins { //trick: for the same plugin versions in all sub-modules - id("com.android.application").version("7.4.0").apply(false) - id("com.android.library").version("7.4.0").apply(false) - kotlin("android").version("1.7.20").apply(false) - kotlin("multiplatform").version("1.7.20").apply(false) + id("com.android.application").version("8.1.0").apply(false) + id("com.android.library").version("8.1.0").apply(false) + id("org.jetbrains.kotlin.android").version("1.9.10").apply(false) + kotlin("multiplatform").version("1.9.10").apply(false) id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false) - id("org.jetbrains.kotlinx.kover") version "0.6.1" + id("org.jetbrains.kotlinx.kover").version("0.6.1").apply(true) } allprojects { diff --git a/gradle.properties b/gradle.properties index a7c8941..4bc8df2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,22 +13,15 @@ #Tue Mar 22 16:50:00 CET 2022 #Gradle org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" - #Kotlin kotlin.code.style=official - #Android android.useAndroidX=true -kotlin.native.enableDependencyPropagation=false #android.nonTransitiveRClass=true android.enableJetifier=true - - +android.nonTransitiveRClass=false #MPP kotlin.mpp.enableCInteropCommonization=true -kotlin.mpp.enableGranularSourceSetsMetadata=true - - org.gradle.parallel=true org.gradle.caching=true ignoreGitVersion=false diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 881598f..9100ea2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Jan 23 20:47:46 CET 2023 +#Thu Jul 13 11:41:19 CEST 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 8408522..780615b 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,3 +1,5 @@ +val ktorVersion = "2.3.2" + object SqlDelight { const val runtime = "com.squareup.sqldelight:runtime:1.5.4" const val android = "com.squareup.sqldelight:android-driver:1.5.4" @@ -9,12 +11,12 @@ plugins { kotlin("multiplatform") id("com.android.library") id("com.squareup.sqldelight") - kotlin("plugin.serialization") version "1.4.10" - id("org.jetbrains.kotlinx.kover") version "0.6.1" + kotlin("plugin.serialization") version "1.9.0" + id("org.jetbrains.kotlinx.kover") } kotlin { - android() + androidTarget() listOf( iosX64(), @@ -29,13 +31,14 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - implementation("io.ktor:ktor-client-core:2.1.1") - implementation("io.ktor:ktor-client-content-negotiation:2.1.1") - implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.1") - implementation("io.ktor:ktor-client-logging:2.1.1") + implementation("io.ktor:ktor-client-core:$ktorVersion") + implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") + implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") + implementation("io.ktor:ktor-client-logging:$ktorVersion") + implementation("io.ktor:ktor-client-auth:$ktorVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") - implementation("io.ktor:ktor-client-auth:2.1.1") - implementation("org.jsoup:jsoup:1.14.3") + + implementation("org.jsoup:jsoup:1.15.4") //Dependency Injection implementation("org.kodein.di:kodein-di:7.12.0") @@ -58,14 +61,15 @@ kotlin { } val androidMain by getting { dependencies { - implementation("io.ktor:ktor-client-okhttp:2.1.1") + implementation("com.squareup.okhttp3:okhttp:4.10.0") + implementation("io.ktor:ktor-client-okhttp:2.2.4") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") // Sql implementation(SqlDelight.android) } } - val androidTest by getting { + val androidUnitTest by getting { dependencies { implementation(kotlin("test-junit")) implementation("junit:junit:4.13.2") @@ -98,15 +102,14 @@ kotlin { } android { - compileSdk = 32 + compileSdk = 33 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { minSdk = 21 - targetSdk = 32 } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } namespace = "bou.amine.apps.readerforselfossv2" } -- 2.34.1 From b59b1abc6dba90db31f97e0f167946072bcb79a3 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Sat, 15 Jul 2023 12:51:59 +0200 Subject: [PATCH 02/12] Fix R8 compilation problem --- androidApp/proguard-rules.pro | 1 + .../android/fragments/FilterSheetFragment.kt | 4 ++-- shared/build.gradle.kts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/androidApp/proguard-rules.pro b/androidApp/proguard-rules.pro index 0162f3e..9c9f8ce 100644 --- a/androidApp/proguard-rules.pro +++ b/androidApp/proguard-rules.pro @@ -55,6 +55,7 @@ # maybe remove later ? -keep class * extends androidx.fragment.app.Fragment +-dontwarn org.slf4j.impl.StaticLoggerBinder # Keep `Companion` object fields of serializable classes. # This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects. diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt index 4c31c07..d065932 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt @@ -82,7 +82,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { ) { val sourceGroup = binding.sourcesGroup - repository.getSourcesDetailsOrStats().forEach { source -> + repository.getSourcesDetailsOrStats().forEachIndexed { _, source -> val c = Chip(context) c.ellipsize = TextUtils.TruncateAt.END @@ -144,7 +144,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { val tags = repository.getTags() - tags.forEach { tag -> + tags.forEachIndexed { _, tag -> val c = Chip(context) c.ellipsize = TextUtils.TruncateAt.END c.text = tag.tag diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 780615b..befcb5c 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -61,7 +61,7 @@ kotlin { } val androidMain by getting { dependencies { - implementation("com.squareup.okhttp3:okhttp:4.10.0") + implementation("com.squareup.okhttp3:okhttp:4.11.0") implementation("io.ktor:ktor-client-okhttp:2.2.4") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") -- 2.34.1 From d26f3979cd7fd253f4f21a3dc0cb63e7fc353f7c Mon Sep 17 00:00:00 2001 From: davidoskky Date: Mon, 11 Sep 2023 20:48:01 +0200 Subject: [PATCH 03/12] Upgrade all dependencies --- androidApp/build.gradle.kts | 39 ++++++++++++++++++------------------- build.gradle.kts | 2 +- shared/build.gradle.kts | 4 ++-- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index f333042..91143a2 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -12,7 +12,7 @@ plugins { } fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { - var result: String = ByteArrayOutputStream().use { outputStream -> + val result: String = ByteArrayOutputStream().use { outputStream -> project.exec { commandLine = cmd.split(" ") standardOutput = outputStream @@ -25,7 +25,7 @@ fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String { fun gitVersion(): String { val maybeTagOfCurrentCommit = execWithOutput("git -C ../ describe --contains HEAD", true) - var process = if (maybeTagOfCurrentCommit.isEmpty()) { + val process = if (maybeTagOfCurrentCommit.isEmpty()) { println("No tag on current commit. Will take the latest one.") execWithOutput("git -C ../ for-each-ref refs/tags --sort=-refname --format='%(refname:short)' --count=1") } else { @@ -65,15 +65,14 @@ android { kotlinOptions { jvmTarget = "17" } - compileSdk = 33 - buildToolsVersion = "33.0.0" + compileSdk = 34 buildFeatures { viewBinding = true } defaultConfig { applicationId = "bou.amine.apps.readerforselfossv2.android" minSdk = 21 - targetSdk = 33 + targetSdk = 34 versionCode = versionCodeFromGit() versionName = versionNameFromGit() @@ -86,7 +85,7 @@ android { // tests testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } - packagingOptions { + packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } @@ -115,25 +114,25 @@ dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3") implementation(project(":shared")) - implementation("com.google.android.material:material:1.5.0") - implementation("androidx.appcompat:appcompat:1.4.1") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0") + implementation("com.google.android.material:material:1.9.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1") - implementation("androidx.preference:preference-ktx:1.1.1") + implementation("androidx.preference:preference-ktx:1.2.1") implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs"))) // Android Support - implementation("androidx.appcompat:appcompat:1.4.1") - implementation("com.google.android.material:material:1.5.0") - implementation("androidx.recyclerview:recyclerview:1.3.0-alpha01") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.9.0") + implementation("androidx.recyclerview:recyclerview:1.3.1") implementation("androidx.legacy:legacy-support-v4:1.0.0") - implementation("androidx.vectordrawable:vectordrawable:1.2.0-alpha02") + implementation("androidx.vectordrawable:vectordrawable:1.2.0-beta01") implementation("androidx.cardview:cardview:1.0.0") - implementation("androidx.annotation:annotation:1.3.0") - implementation("androidx.work:work-runtime-ktx:2.7.1") + implementation("androidx.annotation:annotation:1.7.0") + implementation("androidx.work:work-runtime-ktx:2.8.1") implementation("androidx.constraintlayout:constraintlayout:2.1.4") - implementation("org.jsoup:jsoup:1.14.3") + implementation("org.jsoup:jsoup:1.15.4") //multidex implementation("androidx.multidex:multidex:2.0.1") @@ -154,7 +153,7 @@ dependencies { // Pager implementation("me.relex:circleindicator:2.1.6") - implementation("androidx.viewpager2:viewpager2:1.1.0-beta01") + implementation("androidx.viewpager2:viewpager2:1.1.0-beta02") //Dependency Injection implementation("org.kodein.di:kodein-di:7.14.0") @@ -170,7 +169,7 @@ dependencies { //PhotoView implementation("com.github.chrisbanes:PhotoView:2.3.0") - implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") @@ -183,7 +182,7 @@ dependencies { //test testImplementation("junit:junit:4.13.2") testImplementation("io.mockk:mockk:1.12.0") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") implementation("ch.acra:acra-http:$acraVersion") diff --git a/build.gradle.kts b/build.gradle.kts index 814db5b..4452f8d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ buildscript { dependencies { // SqlDelight - classpath("com.squareup.sqldelight:gradle-plugin:1.5.4") + classpath("com.squareup.sqldelight:gradle-plugin:1.5.5") } } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index befcb5c..144e3c0 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -36,12 +36,12 @@ kotlin { implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") implementation("io.ktor:ktor-client-logging:$ktorVersion") implementation("io.ktor:ktor-client-auth:$ktorVersion") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1") implementation("org.jsoup:jsoup:1.15.4") //Dependency Injection - implementation("org.kodein.di:kodein-di:7.12.0") + implementation("org.kodein.di:kodein-di:7.14.0") //Settings implementation("com.russhwolf:multiplatform-settings-no-arg:1.0.0-RC") -- 2.34.1 From bd6b96d09ddb5614166264a95664d48af0de6f40 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Mon, 11 Sep 2023 20:50:07 +0200 Subject: [PATCH 04/12] Remove not required jcenter repository --- build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4452f8d..a254cdf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,6 @@ allprojects { // maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")} google() mavenCentral() - jcenter() maven { url = uri("https://www.jitpack.io") } } } -- 2.34.1 From 990a35422933de64a9cab2e252bb332cdeaccc90 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Mon, 11 Sep 2023 21:09:03 +0200 Subject: [PATCH 05/12] Remove deprecated function and prevent errors in case of a null fragment name --- .../android/settings/SettingsActivity.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) 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 0de8c99..8dd817b 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 @@ -71,23 +71,25 @@ class SettingsActivity : AppCompatActivity(), } override fun onPreferenceStartFragment( - caller: PreferenceFragmentCompat, - pref: Preference + caller: PreferenceFragmentCompat, + pref: Preference ): Boolean { + val fragmentClassName = pref.fragment ?: return false + // Instantiate the new Fragment val args = pref.extras val fragment = supportFragmentManager.fragmentFactory.instantiate( - classLoader, - pref.fragment + classLoader, + fragmentClassName ).apply { arguments = args - setTargetFragment(caller, 0) } + // Replace the existing Fragment with the new Fragment supportFragmentManager.beginTransaction() - .replace(R.id.settings, fragment) - .addToBackStack(null) - .commit() + .replace(R.id.settings, fragment) + .addToBackStack(null) + .commit() title = pref.title supportActionBar?.title = title return true -- 2.34.1 From 776d5d36f61d6f75721008b81a13afc8b24f827b Mon Sep 17 00:00:00 2001 From: davidoskky Date: Mon, 11 Sep 2023 22:55:23 +0200 Subject: [PATCH 06/12] Remove deprecated function calls --- .../android/SourcesActivity.kt | 7 ++-- .../android/adapters/ItemCardAdapter.kt | 3 +- .../android/adapters/ItemListAdapter.kt | 4 ++- .../android/fragments/ArticleFragment.kt | 32 +++++++++++++++---- .../android/fragments/FilterSheetFragment.kt | 14 ++++++-- .../android/utils/LinksUtils.kt | 1 + .../utils/ModelConverters.kt | 8 ++++- .../readerforselfossv2/utils/EntityUtils.kt | 2 +- 8 files changed, 55 insertions(+), 16 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt index ca47080..b1cab6c 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt @@ -5,6 +5,7 @@ import android.content.res.ColorStateList import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding @@ -36,8 +37,10 @@ class SourcesActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - binding.fab.rippleColor = resources.getColor(R.color.colorAccentDark) - binding.fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent)) + binding.fab.rippleColor = ContextCompat.getColor(this, R.color.colorAccentDark) + + binding.fab.backgroundTintList = + ColorStateList.valueOf(ContextCompat.getColor(this, R.color.colorAccent)) } override fun onStop() { 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 11f6f62..e3fcdb2 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 @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView.ScaleType +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding @@ -60,7 +61,7 @@ class ItemCardAdapter( binding.title.setOnTouchListener(LinkOnTouchListener()) - binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) + binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent)) binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt index c557b10..0848c5a 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt @@ -4,6 +4,7 @@ import android.app.Activity import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding @@ -44,7 +45,8 @@ class ItemListAdapter( binding.title.setOnTouchListener(LinkOnTouchListener()) - binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) + binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent)) + binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate() 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 834f32c..b51a0bd 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 @@ -10,13 +10,21 @@ 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.WebResourceRequest import android.webkit.WebResourceResponse import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import androidx.appcompat.app.AlertDialog +import androidx.core.content.ContextCompat import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment import bou.amine.apps.readerforselfossv2.android.ImageActivity @@ -35,6 +43,7 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.MercuryApi import bou.amine.apps.readerforselfossv2.service.AppSettingsService +import bou.amine.apps.readerforselfossv2.utils.ImageMimeType import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getImages import bou.amine.apps.readerforselfossv2.utils.getThumbnail @@ -54,7 +63,7 @@ import org.kodein.di.instance import java.net.MalformedURLException import java.net.SocketTimeoutException import java.net.URL -import java.util.* +import java.util.Locale import java.util.concurrent.ExecutionException @@ -116,9 +125,15 @@ class ArticleFragment : Fragment(), DIAware { fab = binding.fab - fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent)) + fab.backgroundTintList = + ColorStateList.valueOf( + ContextCompat.getColor( + requireContext(), + R.color.colorAccent + ) + ) - fab.rippleColor = resources.getColor(R.color.colorAccentDark) + fab.rippleColor = ContextCompat.getColor(requireContext(), R.color.colorAccentDark) val floatingToolbar: FloatingToolbar = handleFloatingToolbar() @@ -203,7 +218,8 @@ class ArticleFragment : Fragment(), DIAware { } floatingToolbar.attachFab(fab) - floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent)) + floatingToolbar.background = + ColorDrawable(ContextCompat.getColor(requireContext(), R.color.colorAccent)) floatingToolbar.setClickListener( object : FloatingToolbar.ItemClickListener { @@ -288,7 +304,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 @@ -382,6 +398,8 @@ class ArticleFragment : Fragment(), DIAware { binding.webcontent.settings.standardFontFamily = a.getString(0) + a.recycle() + binding.webcontent.visibility = View.VISIBLE val colorOnSurface = TypedValue() @@ -457,7 +475,7 @@ class ArticleFragment : Fragment(), DIAware { | color: ${ String.format( "#%06X", - 0xFFFFFF and resources.getColor(R.color.colorAccent) + 0xFFFFFF and ContextCompat.getColor(requireContext(), R.color.colorAccent) ) } !important; | } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt index d065932..20fc52e 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt @@ -12,6 +12,7 @@ import android.view.View import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup +import androidx.core.content.ContextCompat import bou.amine.apps.readerforselfossv2.android.HomeActivity import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding @@ -20,7 +21,7 @@ import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getIcon import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.ViewTarget +import com.bumptech.glide.request.target.CustomViewTarget import com.bumptech.glide.request.transition.Transition import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.chip.Chip @@ -88,7 +89,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { Glide.with(context) .load(source.getIcon(repository.baseUrl)) - .into(object : ViewTarget(c) { + .into(object : CustomViewTarget(c) { override fun onResourceReady( resource: Drawable, transition: Transition? @@ -100,6 +101,13 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { } } + override fun onLoadFailed(errorDrawable: Drawable?) { + c.chipIcon = errorDrawable + } + + override fun onResourceCleared(placeholder: Drawable?) { + c.chipIcon = placeholder + } }) c.text = source.title.getHtmlDecoded() @@ -156,7 +164,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { Color.parseColor(tag.color) } catch (e: IllegalArgumentException) { e.sendSilentlyWithAcraWithName("color issue " + tag.color) - resources.getColor(R.color.colorPrimary) + ContextCompat.getColor(context, R.color.colorPrimary) } gd.setColor(gdColor) gd.shape = GradientDrawable.RECTANGLE 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 b5db28e..1a30a75 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 @@ -95,6 +95,7 @@ class LinkOnTouchListener : View.OnTouchListener { if (link.isNotEmpty()) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget) + widget.performClick() } ret = true } diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt index 3999b3d..8f9bf88 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt @@ -1,13 +1,19 @@ package bou.amine.apps.readerforselfossv2.utils import android.net.Uri +import android.os.Build import android.text.Html import bou.amine.apps.readerforselfossv2.model.SelfossModel import org.jsoup.Jsoup import java.util.* actual fun String.getHtmlDecoded(): String { - return Html.fromHtml(this).toString() + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Html.fromHtml(this, Html.FROM_HTML_MODE_COMPACT).toString() + } else { + @Suppress("DEPRECATION") + Html.fromHtml(this).toString() + } } actual fun SelfossModel.Item.getIcon(baseUrl: String): String { diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt index 7c1c1af..2dd741c 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt @@ -17,7 +17,7 @@ fun SOURCE.toView(): SelfossModel.SourceDetail = this.id.toInt(), this.title, null, - this.tags?.split(","), + this.tags.split(","), this.spout, this.error, this.icon, -- 2.34.1 From dcb9b1cb1f2fcdb47ddb3fed44f4784ebca0e5e0 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Mon, 11 Sep 2023 23:26:48 +0200 Subject: [PATCH 07/12] Enable non transitive R class --- .../android/fragments/ArticleFragment.kt | 12 ++++++++++-- gradle.properties | 2 +- 2 files changed, 11 insertions(+), 3 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 b51a0bd..e497f9c 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 @@ -403,10 +403,18 @@ class ArticleFragment : Fragment(), DIAware { binding.webcontent.visibility = View.VISIBLE val colorOnSurface = TypedValue() - requireContext().theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true) + requireContext().theme.resolveAttribute( + com.google.android.material.R.attr.colorOnSurface, + colorOnSurface, + true + ) val colorSurface = TypedValue() - requireContext().theme.resolveAttribute(R.attr.colorSurface, colorSurface, true) + requireContext().theme.resolveAttribute( + com.google.android.material.R.attr.colorSurface, + colorSurface, + true + ) binding.webcontent.settings.useWideViewPort = true binding.webcontent.settings.loadWithOverviewMode = true diff --git a/gradle.properties b/gradle.properties index 4bc8df2..27133c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ kotlin.code.style=official android.useAndroidX=true #android.nonTransitiveRClass=true android.enableJetifier=true -android.nonTransitiveRClass=false +android.nonTransitiveRClass=true #MPP kotlin.mpp.enableCInteropCommonization=true org.gradle.parallel=true -- 2.34.1 From 20aab0ea62c9ade648152b60cdee5f7ffd3bf9a1 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Tue, 12 Sep 2023 00:17:41 +0200 Subject: [PATCH 08/12] Improve image handling --- .../android/fragments/ArticleFragment.kt | 82 +++++++++---------- .../utils/ModelConverters.kt | 15 +--- .../apps/readerforselfossv2/utils/Enums.kt | 16 ++++ 3 files changed, 60 insertions(+), 53 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 e497f9c..5ba8e9d 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 @@ -329,11 +329,19 @@ class ArticleFragment : Fragment(), DIAware { private fun handleImageLoading() { binding.webcontent.webViewClient = object : WebViewClient() { - @Deprecated("Deprecated in Java") - override fun shouldOverrideUrlLoading(view: WebView?, url: String): Boolean { - return if (context != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { + override fun shouldOverrideUrlLoading( + view: WebView?, + request: WebResourceRequest? + ): Boolean { + val url = request?.url?.toString() + return if (context != null && url != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { try { - requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + requireContext().startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse(url) + ) + ) } catch (e: ActivityNotFoundException) { e.sendSilentlyWithAcraWithName("activityNotFound > $url") } @@ -343,50 +351,42 @@ class ArticleFragment : Fragment(), DIAware { } } - @Deprecated("Deprecated in Java") - override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? { + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest + ): WebResourceResponse? { + val url = request.url.toString() val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) - if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US) - .contains(".jpeg") - ) { + + val supportedExtensions = ImageMimeType.values().map { it.extension } + + val matchingExtension = supportedExtensions.find { + url.lowercase(Locale.US).contains(it) + } + + matchingExtension?.let { try { - val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() - return WebResourceResponse( - IMAGE_JPG, - "UTF-8", - getBitmapInputStream(image, Bitmap.CompressFormat.JPEG) - ) - } catch (e: ExecutionException) { - // Do nothing - } - } else if (url.lowercase(Locale.US).contains(".png")) { - try { - val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() - return WebResourceResponse( - IMAGE_JPG, - "UTF-8", - getBitmapInputStream(image, Bitmap.CompressFormat.PNG) - ) - } catch (e: ExecutionException) { - // Do nothing - } - } else if (url.lowercase(Locale.US).contains(".webp")) { - try { - val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() - return WebResourceResponse( - IMAGE_JPG, - "UTF-8", - getBitmapInputStream(image, Bitmap.CompressFormat.WEBP) - ) + val image = Glide.with(view) + .asBitmap() + .apply(glideOptions) + .load(url) + .submit() + .get() + + val mimeType = ImageMimeType.findMimeTypeByExtension(it) + if (mimeType != null) { + return WebResourceResponse( + mimeType, + "UTF-8", + getBitmapInputStream(image, Bitmap.CompressFormat.WEBP) + ) + } } catch (e: ExecutionException) { // Do nothing } } - return super.shouldInterceptRequest(view, url) + return super.shouldInterceptRequest(view, request) } } } diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt index 8f9bf88..56f27e7 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt @@ -25,19 +25,10 @@ actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String { } actual fun SelfossModel.Item.getImages(): ArrayList { - val allImages = ArrayList() + val doc = Jsoup.parse(content) + val images = doc.getElementsByTag("img") - for ( image in Jsoup.parse(content).getElementsByTag("img")) { - val url = image.attr("src") - if (url.lowercase(Locale.US).contains(".jpg") || - url.lowercase(Locale.US).contains(".jpeg") || - url.lowercase(Locale.US).contains(".png") || - url.lowercase(Locale.US).contains(".webp")) - { - allImages.add(url) - } - } - return allImages + return ArrayList(images.map { it.attr("src") }) } actual fun SelfossModel.Source.getIcon(baseUrl: String): String { diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt index fd610d2..77e7c59 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt @@ -8,4 +8,20 @@ enum class ItemType(val position: Int, val type: String) { companion object { fun fromInt(value: Int) = values().first { it.position == value } } +} + +enum class ImageMimeType(val extension: String, val mimeType: String) { + JPG(".jpg", "image/jpeg"), + JPEG(".jpeg", "image/jpeg"), + PNG(".png", "image/png"), + WEBP(".webp", "image/webp"), + GIF(".gif", "image/gif"), + SVG(".svg", "image/svg+xml"), + BMP(".bmp", "image/bmp"), + TIFF(".tiff", "image/tiff"), + TIF(".tif", "image/tiff"); + + companion object { + fun findMimeTypeByExtension(ext: String) = values().find { it.extension == ext }?.mimeType + } } \ No newline at end of file -- 2.34.1 From 2b82be61d0fbbb46625d89e799a970d409e9c1f6 Mon Sep 17 00:00:00 2001 From: davidoskky Date: Sat, 16 Sep 2023 14:09:29 +0200 Subject: [PATCH 09/12] Revert changes not related to the gradle upgrade --- .../android/SourcesActivity.kt | 7 +- .../android/adapters/ItemCardAdapter.kt | 3 +- .../android/adapters/ItemListAdapter.kt | 4 +- .../android/fragments/ArticleFragment.kt | 126 +++++++----------- .../android/fragments/FilterSheetFragment.kt | 14 +- .../android/settings/SettingsActivity.kt | 18 ++- .../android/utils/LinksUtils.kt | 1 - gradle.properties | 2 +- .../utils/ModelConverters.kt | 23 ++-- .../readerforselfossv2/utils/EntityUtils.kt | 2 +- .../apps/readerforselfossv2/utils/Enums.kt | 16 --- 11 files changed, 80 insertions(+), 136 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt index b1cab6c..ca47080 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt @@ -5,7 +5,6 @@ import android.content.res.ColorStateList import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding @@ -37,10 +36,8 @@ class SourcesActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - binding.fab.rippleColor = ContextCompat.getColor(this, R.color.colorAccentDark) - - binding.fab.backgroundTintList = - ColorStateList.valueOf(ContextCompat.getColor(this, R.color.colorAccent)) + binding.fab.rippleColor = resources.getColor(R.color.colorAccentDark) + binding.fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent)) } override fun onStop() { 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 e3fcdb2..11f6f62 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 @@ -6,7 +6,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView.ScaleType -import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding @@ -61,7 +60,7 @@ class ItemCardAdapter( binding.title.setOnTouchListener(LinkOnTouchListener()) - binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent)) + binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt index 0848c5a..c557b10 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemListAdapter.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup -import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding @@ -45,8 +44,7 @@ class ItemListAdapter( binding.title.setOnTouchListener(LinkOnTouchListener()) - binding.title.setLinkTextColor(ContextCompat.getColor(c, R.color.colorAccent)) - + binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) binding.sourceTitleAndDate.text = itm.sourceAuthorAndDate() 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 5ba8e9d..834f32c 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 @@ -10,21 +10,13 @@ import android.graphics.drawable.ColorDrawable import android.net.Uri import android.os.Bundle import android.util.TypedValue -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.WebResourceRequest +import android.view.* import android.webkit.WebResourceResponse import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import androidx.appcompat.app.AlertDialog -import androidx.core.content.ContextCompat import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment import bou.amine.apps.readerforselfossv2.android.ImageActivity @@ -43,7 +35,6 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.MercuryApi import bou.amine.apps.readerforselfossv2.service.AppSettingsService -import bou.amine.apps.readerforselfossv2.utils.ImageMimeType import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getImages import bou.amine.apps.readerforselfossv2.utils.getThumbnail @@ -63,7 +54,7 @@ import org.kodein.di.instance import java.net.MalformedURLException import java.net.SocketTimeoutException import java.net.URL -import java.util.Locale +import java.util.* import java.util.concurrent.ExecutionException @@ -125,15 +116,9 @@ class ArticleFragment : Fragment(), DIAware { fab = binding.fab - fab.backgroundTintList = - ColorStateList.valueOf( - ContextCompat.getColor( - requireContext(), - R.color.colorAccent - ) - ) + fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent)) - fab.rippleColor = ContextCompat.getColor(requireContext(), R.color.colorAccentDark) + fab.rippleColor = resources.getColor(R.color.colorAccentDark) val floatingToolbar: FloatingToolbar = handleFloatingToolbar() @@ -218,8 +203,7 @@ class ArticleFragment : Fragment(), DIAware { } floatingToolbar.attachFab(fab) - floatingToolbar.background = - ColorDrawable(ContextCompat.getColor(requireContext(), R.color.colorAccent)) + floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent)) floatingToolbar.setClickListener( object : FloatingToolbar.ItemClickListener { @@ -304,7 +288,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 @@ -329,19 +313,11 @@ class ArticleFragment : Fragment(), DIAware { private fun handleImageLoading() { binding.webcontent.webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading( - view: WebView?, - request: WebResourceRequest? - ): Boolean { - val url = request?.url?.toString() - return if (context != null && url != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { + @Deprecated("Deprecated in Java") + override fun shouldOverrideUrlLoading(view: WebView?, 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) - ) - ) + requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) } catch (e: ActivityNotFoundException) { e.sendSilentlyWithAcraWithName("activityNotFound > $url") } @@ -351,42 +327,50 @@ class ArticleFragment : Fragment(), DIAware { } } - override fun shouldInterceptRequest( - view: WebView, - request: WebResourceRequest - ): WebResourceResponse? { - val url = request.url.toString() + @Deprecated("Deprecated in Java") + override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? { val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) - - val supportedExtensions = ImageMimeType.values().map { it.extension } - - val matchingExtension = supportedExtensions.find { - url.lowercase(Locale.US).contains(it) - } - - matchingExtension?.let { + if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US) + .contains(".jpeg") + ) { try { - val image = Glide.with(view) - .asBitmap() - .apply(glideOptions) - .load(url) - .submit() - .get() - - val mimeType = ImageMimeType.findMimeTypeByExtension(it) - if (mimeType != null) { - return WebResourceResponse( - mimeType, - "UTF-8", - getBitmapInputStream(image, Bitmap.CompressFormat.WEBP) - ) - } + val image = + Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() + return WebResourceResponse( + IMAGE_JPG, + "UTF-8", + getBitmapInputStream(image, Bitmap.CompressFormat.JPEG) + ) + } catch (e: ExecutionException) { + // Do nothing + } + } else if (url.lowercase(Locale.US).contains(".png")) { + try { + val image = + Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() + return WebResourceResponse( + IMAGE_JPG, + "UTF-8", + getBitmapInputStream(image, Bitmap.CompressFormat.PNG) + ) + } catch (e: ExecutionException) { + // Do nothing + } + } else if (url.lowercase(Locale.US).contains(".webp")) { + try { + val image = + Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() + return WebResourceResponse( + IMAGE_JPG, + "UTF-8", + getBitmapInputStream(image, Bitmap.CompressFormat.WEBP) + ) } catch (e: ExecutionException) { // Do nothing } } - return super.shouldInterceptRequest(view, request) + return super.shouldInterceptRequest(view, url) } } } @@ -398,23 +382,13 @@ class ArticleFragment : Fragment(), DIAware { binding.webcontent.settings.standardFontFamily = a.getString(0) - a.recycle() - binding.webcontent.visibility = View.VISIBLE val colorOnSurface = TypedValue() - requireContext().theme.resolveAttribute( - com.google.android.material.R.attr.colorOnSurface, - colorOnSurface, - true - ) + requireContext().theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true) val colorSurface = TypedValue() - requireContext().theme.resolveAttribute( - com.google.android.material.R.attr.colorSurface, - colorSurface, - true - ) + requireContext().theme.resolveAttribute(R.attr.colorSurface, colorSurface, true) binding.webcontent.settings.useWideViewPort = true binding.webcontent.settings.loadWithOverviewMode = true @@ -483,7 +457,7 @@ class ArticleFragment : Fragment(), DIAware { | color: ${ String.format( "#%06X", - 0xFFFFFF and ContextCompat.getColor(requireContext(), R.color.colorAccent) + 0xFFFFFF and resources.getColor(R.color.colorAccent) ) } !important; | } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt index 20fc52e..d065932 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt @@ -12,7 +12,6 @@ import android.view.View import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup -import androidx.core.content.ContextCompat import bou.amine.apps.readerforselfossv2.android.HomeActivity import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding @@ -21,7 +20,7 @@ import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getIcon import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.CustomViewTarget +import com.bumptech.glide.request.target.ViewTarget import com.bumptech.glide.request.transition.Transition import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.chip.Chip @@ -89,7 +88,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { Glide.with(context) .load(source.getIcon(repository.baseUrl)) - .into(object : CustomViewTarget(c) { + .into(object : ViewTarget(c) { override fun onResourceReady( resource: Drawable, transition: Transition? @@ -101,13 +100,6 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { } } - override fun onLoadFailed(errorDrawable: Drawable?) { - c.chipIcon = errorDrawable - } - - override fun onResourceCleared(placeholder: Drawable?) { - c.chipIcon = placeholder - } }) c.text = source.title.getHtmlDecoded() @@ -164,7 +156,7 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { Color.parseColor(tag.color) } catch (e: IllegalArgumentException) { e.sendSilentlyWithAcraWithName("color issue " + tag.color) - ContextCompat.getColor(context, R.color.colorPrimary) + resources.getColor(R.color.colorPrimary) } gd.setColor(gdColor) gd.shape = GradientDrawable.RECTANGLE 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 8dd817b..8d79b83 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 @@ -71,25 +71,23 @@ class SettingsActivity : AppCompatActivity(), } override fun onPreferenceStartFragment( - caller: PreferenceFragmentCompat, - pref: Preference + caller: PreferenceFragmentCompat, + pref: Preference ): Boolean { - val fragmentClassName = pref.fragment ?: return false - // Instantiate the new Fragment val args = pref.extras val fragment = supportFragmentManager.fragmentFactory.instantiate( - classLoader, - fragmentClassName + classLoader, + pref.fragment.toString() ).apply { arguments = args + setTargetFragment(caller, 0) } - // Replace the existing Fragment with the new Fragment supportFragmentManager.beginTransaction() - .replace(R.id.settings, fragment) - .addToBackStack(null) - .commit() + .replace(R.id.settings, fragment) + .addToBackStack(null) + .commit() title = pref.title supportActionBar?.title = title return true 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 1a30a75..b5db28e 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 @@ -95,7 +95,6 @@ class LinkOnTouchListener : View.OnTouchListener { if (link.isNotEmpty()) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget) - widget.performClick() } ret = true } diff --git a/gradle.properties b/gradle.properties index 27133c4..4bc8df2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ kotlin.code.style=official android.useAndroidX=true #android.nonTransitiveRClass=true android.enableJetifier=true -android.nonTransitiveRClass=true +android.nonTransitiveRClass=false #MPP kotlin.mpp.enableCInteropCommonization=true org.gradle.parallel=true diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt index 56f27e7..3999b3d 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt @@ -1,19 +1,13 @@ package bou.amine.apps.readerforselfossv2.utils import android.net.Uri -import android.os.Build import android.text.Html import bou.amine.apps.readerforselfossv2.model.SelfossModel import org.jsoup.Jsoup import java.util.* actual fun String.getHtmlDecoded(): String { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - Html.fromHtml(this, Html.FROM_HTML_MODE_COMPACT).toString() - } else { - @Suppress("DEPRECATION") - Html.fromHtml(this).toString() - } + return Html.fromHtml(this).toString() } actual fun SelfossModel.Item.getIcon(baseUrl: String): String { @@ -25,10 +19,19 @@ actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String { } actual fun SelfossModel.Item.getImages(): ArrayList { - val doc = Jsoup.parse(content) - val images = doc.getElementsByTag("img") + val allImages = ArrayList() - return ArrayList(images.map { it.attr("src") }) + for ( image in Jsoup.parse(content).getElementsByTag("img")) { + val url = image.attr("src") + if (url.lowercase(Locale.US).contains(".jpg") || + url.lowercase(Locale.US).contains(".jpeg") || + url.lowercase(Locale.US).contains(".png") || + url.lowercase(Locale.US).contains(".webp")) + { + allImages.add(url) + } + } + return allImages } actual fun SelfossModel.Source.getIcon(baseUrl: String): String { diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt index 2dd741c..7c1c1af 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt @@ -17,7 +17,7 @@ fun SOURCE.toView(): SelfossModel.SourceDetail = this.id.toInt(), this.title, null, - this.tags.split(","), + this.tags?.split(","), this.spout, this.error, this.icon, diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt index 77e7c59..fd610d2 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt @@ -8,20 +8,4 @@ enum class ItemType(val position: Int, val type: String) { companion object { fun fromInt(value: Int) = values().first { it.position == value } } -} - -enum class ImageMimeType(val extension: String, val mimeType: String) { - JPG(".jpg", "image/jpeg"), - JPEG(".jpeg", "image/jpeg"), - PNG(".png", "image/png"), - WEBP(".webp", "image/webp"), - GIF(".gif", "image/gif"), - SVG(".svg", "image/svg+xml"), - BMP(".bmp", "image/bmp"), - TIFF(".tiff", "image/tiff"), - TIF(".tif", "image/tiff"); - - companion object { - fun findMimeTypeByExtension(ext: String) = values().find { it.extension == ext }?.mimeType - } } \ No newline at end of file -- 2.34.1 From 86a30f647d331ea1f31383ddebf4254c11268c99 Mon Sep 17 00:00:00 2001 From: aminecmi Date: Fri, 6 Oct 2023 21:12:47 +0200 Subject: [PATCH 10/12] fix: Fixed ios build. --- .drone.yml | 49 ++++++++++--------- gradle.properties | 1 - settings.gradle.kts | 13 ----- .../rest/setupInsecureHTTPEngine.kt | 6 +++ .../rest/setupInsecureHTTPEngine.kt | 6 +++ 5 files changed, 38 insertions(+), 37 deletions(-) create mode 100644 shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt create mode 100644 shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt diff --git a/.drone.yml b/.drone.yml index c21cbda..d27f790 100644 --- a/.drone.yml +++ b/.drone.yml @@ -3,35 +3,38 @@ type: docker name: test steps: + - name: Lint + failure: ignore + image: mingc/android-build-box:latest + commands: + - echo "---------------------------------------------------------" + - echo "Install linters..." + - curl -sSLO https://github.com/pinterest/ktlint/releases/download/1.0.0/ktlint && chmod a+x ktlint && mv ktlint /usr/local/bin/ + - curl -sSLO https://github.com/detekt/detekt/releases/download/v1.23.1/detekt-cli-1.23.1.zip && unzip detekt-cli-1.23.1.zip + - echo "---------------------------------------------------------" + - echo "Linting..." + - ktlint || true + - echo "---------------------------------------------------------" + - echo "Detecting..." + - ./detekt-cli-1.23.1/bin/detekt-cli --all-rules || true + - echo "---------------------------------------------------------" + command_timeout: 1m - name: BuildAndTest image: mingc/android-build-box:latest commands: - echo "---------------------------------------------------------" - echo "Configure gradle..." - - mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true\npushCache=false\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties + - mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties - echo "---------------------------------------------------------" - - echo "Building..." - - ./gradlew build -x test + - echo "Configure java..." + - . ~/.bash_profile + - jenv global 17.0 + - java --version + - date - echo "---------------------------------------------------------" - - echo "Testing..." + - echo "Building and testing..." + - ./gradlew build - echo "---------------------------------------------------------" - - ./gradlew koverMergedXmlReport - environment: - TZ: Europe/Paris - SONAR_HOST_URL: - from_secret: sonarScannerHostUrl - SONAR_LOGIN: - from_secret: sonarScannerLogin - - name: Analyse - image: kytay/sonar-node-plugin - settings: - sonar_host: - from_secret: sonarScannerHostUrl - sonar_token: - from_secret: sonarScannerLogin - use_node_version: 16.18.1 - sonar_debug: true - sonar_project_settings: ./sonar-project.properties trigger: event: - push @@ -107,10 +110,10 @@ steps: - git fetch --tags - echo "---------------------------------------------------------" - echo "Configure gradle..." - - mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=false\npushCache=false\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties + - mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=false\nsystemProp.org.gradle.internal.http.connectionTimeout=180000\nsystemProp.org.gradle.internal.http.socketTimeout=180000" >> ~/.gradle/gradle.properties - echo "---------------------------------------------------------" - echo "Generate APK" - - ./gradlew :androidApp:assembleGithubConfigRelease -P pushCache=false + - ./gradlew :androidApp:assembleGithubConfigRelease - echo "---------------------------------------------------------" - echo "Get Key" - wget https://amine-louveau.fr/key diff --git a/gradle.properties b/gradle.properties index 4bc8df2..d40bc34 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,4 +26,3 @@ org.gradle.parallel=true org.gradle.caching=true ignoreGitVersion=false kotlin.native.cacheKind.iosX64=none -pushCache=true diff --git a/settings.gradle.kts b/settings.gradle.kts index 5b7e8e0..2aaa979 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,3 @@ -val pushCache: String by settings - pluginManagement { repositories { // maven { url = uri("https://nexus.amine-louveau.fr/repository/maven-public/")} @@ -17,17 +15,6 @@ dependencyResolutionManagement { } } - -buildCache { - remote { - url = uri("http://18.0.0.7:3071/cache/") - isAllowInsecureProtocol = true - isAllowUntrustedServer = true - isUseExpectContinue = true - isPush = (pushCache == "true") - } -} - rootProject.name = "ReaderForSelfossV2" include(":androidApp") include(":shared") \ No newline at end of file diff --git a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt new file mode 100644 index 0000000..530528c --- /dev/null +++ b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt @@ -0,0 +1,6 @@ +package bou.amine.apps.readerforselfossv2.rest + +import io.ktor.client.engine.cio.CIOEngineConfig + +actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) { +} \ No newline at end of file diff --git a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt new file mode 100644 index 0000000..530528c --- /dev/null +++ b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt @@ -0,0 +1,6 @@ +package bou.amine.apps.readerforselfossv2.rest + +import io.ktor.client.engine.cio.CIOEngineConfig + +actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) { +} \ No newline at end of file -- 2.34.1 From 33cca86383e0f9c2dde44ece0e4465a7ce9c40a3 Mon Sep 17 00:00:00 2001 From: aminecmi Date: Tue, 10 Oct 2023 21:41:34 +0200 Subject: [PATCH 11/12] chore: update versions --- androidApp/build.gradle.kts | 2 +- build.gradle.kts | 4 ++-- shared/build.gradle.kts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 91143a2..c9349bd 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -71,7 +71,7 @@ android { } defaultConfig { applicationId = "bou.amine.apps.readerforselfossv2.android" - minSdk = 21 + minSdk = 25 targetSdk = 34 versionCode = versionCodeFromGit() versionName = versionNameFromGit() diff --git a/build.gradle.kts b/build.gradle.kts index a254cdf..73ec5e4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,8 @@ buildscript { plugins { //trick: for the same plugin versions in all sub-modules - id("com.android.application").version("8.1.0").apply(false) - id("com.android.library").version("8.1.0").apply(false) + id("com.android.application").version("8.1.2").apply(false) + id("com.android.library").version("8.1.2").apply(false) id("org.jetbrains.kotlin.android").version("1.9.10").apply(false) kotlin("multiplatform").version("1.9.10").apply(false) id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false) diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 63e7a88..a019f19 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -103,10 +103,10 @@ kotlin { } android { - compileSdk = 33 + compileSdk = 34 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { - minSdk = 21 + minSdk = 25 } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 -- 2.34.1 From 29d33687b4ea2e46194ee8290d82220fc2985545 Mon Sep 17 00:00:00 2001 From: aminecmi Date: Tue, 10 Oct 2023 22:26:27 +0200 Subject: [PATCH 12/12] fix: Fixing date formats. --- androidApp/src/test/kotlin/DatesTest.kt | 51 +++++++++++-------- .../readerforselfossv2/utils/DateUtils.kt | 25 ++++++--- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/androidApp/src/test/kotlin/DatesTest.kt b/androidApp/src/test/kotlin/DatesTest.kt index 3f373d4..b751969 100644 --- a/androidApp/src/test/kotlin/DatesTest.kt +++ b/androidApp/src/test/kotlin/DatesTest.kt @@ -9,38 +9,49 @@ import org.junit.Test class DatesTest { - private val v3Date = "2013-04-07T13:43:00+01:00" - private val v4Date = "2013-04-07 13:43:00" - private val bug1Date = "2022-12-24T17:00:08+00" + private val newVersionDateVariant = "2022-12-24T17:00:08+00" + private val newVersionDate = "2013-04-07T13:43:00+01:00" + private val oldVersionDate = "2013-05-07 13:46:00" + private val oldVersionDateVariant = "2021-03-21 10:32:00.000000" @Test - fun v3_date_should_be_parsed() { - val date = DateUtils.parseDate(v3Date) - val expected = - LocalDateTime(2013, 4, 7, 14, 43, 0, 0).toInstant(TimeZone.currentSystemDefault()) - .toEpochMilliseconds() - - assertEquals(date, expected) - } - - @Test - fun v4_date_should_be_parsed() { - val date = DateUtils.parseDate(v4Date) + fun new_version_date_should_be_parsed() { + val date = DateUtils.parseDate(newVersionDate) val expected = LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() - assertEquals(date, expected) + assertEquals(expected, date) } @Test - fun bug1_date_should_be_parsed() { - val date = DateUtils.parseDate(bug1Date) + fun old_version_date_should_be_parsed() { + val date = DateUtils.parseDate(oldVersionDate) val expected = - LocalDateTime(2022, 12, 24, 18, 0, 8, 0).toInstant(TimeZone.currentSystemDefault()) + LocalDateTime(2013, 5, 7, 13, 46, 0, 0).toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() - assertEquals(date, expected) + assertEquals(expected, date) + } + + @Test + fun old_version_variant_date_should_be_parsed() { + val date = DateUtils.parseDate(oldVersionDateVariant) + val expected = + LocalDateTime(2021, 3, 21, 10, 32, 0, 0).toInstant(TimeZone.currentSystemDefault()) + .toEpochMilliseconds() + + assertEquals(expected, date) + } + + @Test + fun new_version_variant_date_should_be_parsed() { + val date = DateUtils.parseDate(newVersionDateVariant) + val expected = + LocalDateTime(2022, 12, 24, 17, 0, 8, 0).toInstant(TimeZone.currentSystemDefault()) + .toEpochMilliseconds() + + assertEquals(expected, date) } } diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 2349d3b..5f8ea41 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -6,16 +6,25 @@ import kotlinx.datetime.* actual class DateUtils { actual companion object { + + // Possible formats are + // yyyy-mm-dd hh:mm:ss format + private val oldVersionFormat = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(.()\\d*)?".toRegex() + // yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX (RFC3339) + private val newVersionFormat = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}(:\\d{2})?".toRegex() + + // We may need to consider moving the formatting to platform specific code, even if the tests are doubled + // For now, we handle this in a hacky way, because kotlin only accepts iso formats actual fun parseDate(dateString: String): Long { - return try { - Instant.parse(dateString).toEpochMilliseconds() - } catch (e: Exception) { - var str = dateString.replace(" ", "T") - if (str.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{2}".toRegex())) { - str = str.split("+")[0] - } - LocalDateTime.parse(str).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds() + var isoDateString: String = if (dateString.matches(oldVersionFormat)) { + dateString.replace(" ", "T") + } else if (dateString.matches(newVersionFormat)) { + dateString.split("+")[0] + } else { + throw Exception("Unrecognized format for $dateString") } + + return LocalDateTime.parse(isoDateString).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds() } actual fun parseRelativeDate(dateString: String): String { -- 2.34.1