diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index e76add7..cfed35a 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -54,9 +54,13 @@ fun versionNameFromGit(): String { android { compileOptions { // Flag to enable support for the new language APIs - isCoreLibraryDesugaringEnabled = true - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + // For Kotlin projects + kotlinOptions { + jvmTarget = "11" } compileSdk = 32 buildToolsVersion = "31.0.0" @@ -130,8 +134,6 @@ dependencies { implementation("androidx.constraintlayout:constraintlayout:2.1.3") implementation("org.jsoup:jsoup:1.14.3") - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") - //multidex implementation("androidx.multidex:multidex:2.0.1") @@ -140,9 +142,6 @@ dependencies { implementation("com.mikepenz:aboutlibraries:8.9.4") implementation("com.mikepenz:aboutlibraries-definitions:8.9.4") - // Async - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0") - // Retrofit + http logging + okhttp implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.3") diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/AddSourceActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/AddSourceActivity.kt index 26b1239..b0bbf82 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/AddSourceActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/AddSourceActivity.kt @@ -94,7 +94,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { CoroutineScope(Dispatchers.Main).launch { try { val items = repository.getSpouts() - if (items != null) { + if (items.isNotEmpty()) { val itemsStrings = items.map { it.value.name } for ((key, value) in items) { spoutsKV[value.name] = key diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt index a5ad48e..376ec0e 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/LoginActivity.kt @@ -101,7 +101,7 @@ class LoginActivity : AppCompatActivity(), DIAware { finish() } - private fun preferenceError(t: Throwable) { + private fun preferenceError() { appSettingsService.resetLoginInformation() binding.urlView.error = getString(R.string.wrong_infos) @@ -169,7 +169,7 @@ class LoginActivity : AppCompatActivity(), DIAware { goToMain() } else { CoroutineScope(Dispatchers.Main).launch { - preferenceError(Exception("Not success")) + preferenceError() } } } 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 4a99f96..4cce83e 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 @@ -56,7 +56,7 @@ class SourcesActivity : AppCompatActivity(), DIAware { CoroutineScope(Dispatchers.Main).launch { val response = repository.getSources() - if (response != null) { + if (response.isNotEmpty()) { items = response val mAdapter = SourcesListAdapter( this@SourcesActivity, items diff --git a/androidApp/src/test/kotlin/RepositoryTest.kt b/androidApp/src/test/kotlin/RepositoryTest.kt index 6033d25..32f98b9 100644 --- a/androidApp/src/test/kotlin/RepositoryTest.kt +++ b/androidApp/src/test/kotlin/RepositoryTest.kt @@ -64,14 +64,14 @@ class RepositoryTest { } @Test - fun Instantiate_repository() { + fun instantiate_repository() { initializeRepository() coVerify(exactly = 1) { api.version() } } @Test - fun Instantiate_repository_without_api_version() { + fun instantiate_repository_without_api_version() { every { appSettingsService.getApiVersion() } returns -1 initializeRepository(MutableStateFlow(false)) @@ -81,7 +81,7 @@ class RepositoryTest { } @Test - fun Get_api_4_date_with_api_1_version_stored() { + fun get_api_4_date_with_api_1_version_stored() { every { appSettingsService.getApiVersion() } returns 1 coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -97,7 +97,7 @@ class RepositoryTest { } @Test - fun Get_api_1_date_with_api_4_version_stored() { + fun get_api_1_date_with_api_4_version_stored() { every { appSettingsService.getApiVersion() } returns 4 coEvery { api.version() } returns SelfossModel.StatusAndData(success = false, null) val itemParameters = FakeItemParameters() @@ -117,7 +117,7 @@ class RepositoryTest { } @Test - fun Get_newer_items() { + fun get_newer_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -132,7 +132,7 @@ class RepositoryTest { } @Test - fun Get_all_newer_items() { + fun get_all_newer_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -148,7 +148,7 @@ class RepositoryTest { } @Test - fun Get_newer_starred_items() { + fun get_newer_starred_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -164,7 +164,7 @@ class RepositoryTest { } @Test - fun Get_newer_items_without_connectivity() { + fun get_newer_items_without_connectivity() { every { appSettingsService.isItemCachingEnabled() } returns true initializeRepository(MutableStateFlow(false)) @@ -178,7 +178,7 @@ class RepositoryTest { } @Test - fun Get_newer_items_without_connectivity_and_tag_filter() { + fun get_newer_items_without_connectivity_and_tag_filter() { val itemParameter1 = FakeItemParameters() val itemParameter2 = FakeItemParameters() val itemParameter3 = FakeItemParameters() @@ -206,7 +206,7 @@ class RepositoryTest { } @Test - fun Get_newer_items_without_connectivity_and_source_filter() { + fun get_newer_items_without_connectivity_and_source_filter() { val itemParameter1 = FakeItemParameters() val itemParameter2 = FakeItemParameters() val itemParameter3 = FakeItemParameters() @@ -241,7 +241,7 @@ class RepositoryTest { } @Test - fun Get_older_items() { + fun get_older_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -257,7 +257,7 @@ class RepositoryTest { } @Test - fun Get_all_older_items() { + fun get_all_older_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -274,7 +274,7 @@ class RepositoryTest { } @Test - fun Get_older_starred_items() { + fun get_older_starred_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) @@ -291,8 +291,8 @@ class RepositoryTest { } @Test - fun Reload_badges() { - var success = false + fun reload_badges() { + var success: Boolean initializeRepository() runBlocking { @@ -308,10 +308,10 @@ class RepositoryTest { } @Test - fun Reload_badges_without_response() { + fun reload_badges_without_response() { coEvery { api.stats() } returns SelfossModel.StatusAndData(success = false, data = null) - var success = false + var success: Boolean initializeRepository() runBlocking { @@ -327,11 +327,11 @@ class RepositoryTest { } @Test - fun Reload_badges_without_connection() { + fun reload_badges_without_connection() { every { appSettingsService.isItemCachingEnabled() } returns true every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() - var success = false + var success: Boolean initializeRepository(MutableStateFlow(false)) runBlocking { @@ -347,11 +347,11 @@ class RepositoryTest { } @Test - fun Reload_badges_without_connection_and_items_caching_disabled() { + fun reload_badges_without_connection_and_items_caching_disabled() { every { appSettingsService.isItemCachingEnabled() } returns false every { appSettingsService.isUpdateSourcesEnabled() } returns true - var success = false + var success: Boolean initializeRepository(MutableStateFlow(false)) runBlocking { @@ -367,7 +367,7 @@ class RepositoryTest { } @Test - fun Get_tags() { + fun get_tags() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -383,7 +383,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns true initializeRepository() - var testTags: List? = null + var testTags: List? runBlocking { testTags = repository.getTags() } @@ -394,7 +394,7 @@ class RepositoryTest { } @Test - fun Get_tags_with_sources_update_disabled() { + fun get_tags_with_sources_update_disabled() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -410,7 +410,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns true initializeRepository() - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() // Tags will be fetched from the database on the second call, thus testTags != tags @@ -424,7 +424,7 @@ class RepositoryTest { } @Test - fun Get_tags_with_items_caching_disabled() { + fun get_tags_with_items_caching_disabled() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -440,7 +440,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns false initializeRepository() - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() } @@ -451,7 +451,7 @@ class RepositoryTest { } @Test - fun Get_tags_with_sources_update_and_items_caching_disabled() { + fun get_tags_with_sources_update_and_items_caching_disabled() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -467,7 +467,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns false initializeRepository() - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() testTags = repository.getTags() @@ -480,7 +480,7 @@ class RepositoryTest { } @Test - fun Get_tags_without_connection() { + fun get_tags_without_connection() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -496,7 +496,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns true initializeRepository(MutableStateFlow(false)) - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() } @@ -508,7 +508,7 @@ class RepositoryTest { } @Test - fun Get_tags_without_connection_and_items_caching_disabled() { + fun get_tags_without_connection_and_items_caching_disabled() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -524,7 +524,7 @@ class RepositoryTest { every { appSettingsService.isUpdateSourcesEnabled() } returns true initializeRepository(MutableStateFlow(false)) - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() } @@ -535,7 +535,7 @@ class RepositoryTest { } @Test - fun Get_tags_without_connection_and_sources_update_disabled() { + fun get_tags_without_connection_and_sources_update_disabled() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -551,7 +551,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns true initializeRepository(MutableStateFlow(false)) - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() } @@ -563,7 +563,7 @@ class RepositoryTest { } @Test - fun Get_tags_without_connection_and_sources_update_and_items_caching_disabled() { + fun get_tags_without_connection_and_sources_update_and_items_caching_disabled() { val tags = listOf( SelfossModel.Tag("test", "red", 6), SelfossModel.Tag("second", "yellow", 0) @@ -579,7 +579,7 @@ class RepositoryTest { every { appSettingsService.isItemCachingEnabled() } returns false initializeRepository(MutableStateFlow(false)) - var testTags: List = emptyList() + var testTags: List runBlocking { testTags = repository.getTags() } @@ -631,7 +631,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository() - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -685,7 +685,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository() - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() // Sources will be fetched from the database on the second call, thus testSources != sources @@ -742,7 +742,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository() - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -796,7 +796,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository() - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -848,7 +848,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository(MutableStateFlow(false)) - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -902,7 +902,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository(MutableStateFlow(false)) - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -956,7 +956,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository(MutableStateFlow(false)) - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -1010,7 +1010,7 @@ class RepositoryTest { coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB initializeRepository(MutableStateFlow(false)) - var testSources: List? = null + var testSources: List? runBlocking { testSources = repository.getSources() } @@ -1026,7 +1026,7 @@ class RepositoryTest { SelfossModel.SuccessResponse(true) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.createSource( "test", @@ -1056,7 +1056,7 @@ class RepositoryTest { SelfossModel.SuccessResponse(false) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.createSource( "test", @@ -1086,7 +1086,7 @@ class RepositoryTest { SelfossModel.SuccessResponse(true) initializeRepository(MutableStateFlow(false)) - var response = false + var response: Boolean runBlocking { response = repository.createSource( "test", @@ -1115,7 +1115,7 @@ class RepositoryTest { coEvery { api.deleteSource(any()) } returns SelfossModel.SuccessResponse(true) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.deleteSource(5) } @@ -1129,7 +1129,7 @@ class RepositoryTest { coEvery { api.deleteSource(any()) } returns SelfossModel.SuccessResponse(false) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.deleteSource(5) } @@ -1143,7 +1143,7 @@ class RepositoryTest { coEvery { api.deleteSource(any()) } returns SelfossModel.SuccessResponse(false) initializeRepository(MutableStateFlow(false)) - var response = false + var response: Boolean runBlocking { response = repository.deleteSource(5) } @@ -1160,7 +1160,7 @@ class RepositoryTest { ) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.updateRemote() } @@ -1177,7 +1177,7 @@ class RepositoryTest { ) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.updateRemote() } @@ -1194,7 +1194,7 @@ class RepositoryTest { ) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.updateRemote() } @@ -1211,7 +1211,7 @@ class RepositoryTest { ) initializeRepository(MutableStateFlow(false)) - var response = false + var response: Boolean runBlocking { response = repository.updateRemote() } @@ -1225,7 +1225,7 @@ class RepositoryTest { coEvery { api.login() } returns SelfossModel.SuccessResponse(success = true) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.login() } @@ -1239,7 +1239,7 @@ class RepositoryTest { coEvery { api.login() } returns SelfossModel.SuccessResponse(success = false) initializeRepository() - var response = false + var response: Boolean runBlocking { response = repository.login() } @@ -1253,7 +1253,7 @@ class RepositoryTest { coEvery { api.login() } returns SelfossModel.SuccessResponse(success = true) initializeRepository(MutableStateFlow(false)) - var response = false + var response: Boolean runBlocking { response = repository.login() } diff --git a/gradle.properties b/gradle.properties index 900f643..a7c8941 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,4 +34,3 @@ org.gradle.caching=true ignoreGitVersion=false kotlin.native.cacheKind.iosX64=none pushCache=true - diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index c650e50..a835343 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -58,6 +58,7 @@ kotlin { val androidMain by getting { dependencies { implementation("io.ktor:ktor-client-okhttp:2.1.1") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") // Sql implementation(SqlDelight.android) 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 8ff8dda..a65d70c 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 @@ -1,49 +1,26 @@ package bou.amine.apps.readerforselfossv2.utils -import android.os.Build import android.text.format.DateUtils import bou.amine.apps.readerforselfossv2.service.AppSettingsService -import java.time.Instant -import java.time.LocalDateTime -import java.time.OffsetDateTime -import java.time.ZoneOffset -import java.time.format.DateTimeFormatter +import kotlinx.datetime.Clock +import kotlinx.datetime.Instant + actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) { actual fun parseDate(dateString: String): Long { - - val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss" - - return if (appSettingsService.getApiVersion() >= 4) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - OffsetDateTime.parse(dateString).toInstant().toEpochMilli() - } else { - TODO("VERSION.SDK_INT < O") - } - } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant( - ZoneOffset.UTC).toEpochMilli() - } else { - TODO("VERSION.SDK_INT < O") - } - } + return Instant.parse(dateString).toEpochMilliseconds() } actual fun parseRelativeDate(dateString: String): String { val date = parseDate(dateString) - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - " " + DateUtils.getRelativeTimeSpanString( - date, - Instant.now().toEpochMilli(), - DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE - ) - } else { - TODO("VERSION.SDK_INT < O") - } + return " " + DateUtils.getRelativeTimeSpanString( + date, + Clock.System.now().toEpochMilliseconds(), + DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE + ) } } \ No newline at end of file