From 7221f11f8021c710a210f169940441aeaeb83d79 Mon Sep 17 00:00:00 2001 From: davide Date: Thu, 21 Jul 2022 15:19:22 +0200 Subject: [PATCH] Inject repository in the Article Fragment The Repository is now injected in the Article Fragment and the DateUtils class was modified not to rely on apiDetailsService --- .../android/HomeActivity.kt | 4 +- .../apps/readerforselfossv2/android/MyApp.kt | 2 +- .../android/adapters/ItemCardAdapter.kt | 2 +- .../android/adapters/ItemListAdapter.kt | 2 +- .../android/background/background.kt | 4 +- .../android/fragments/ArticleFragment.kt | 43 ++++++------------- .../repository/Repository.kt | 3 ++ .../repository/RepositoryImpl.kt | 28 +++++++++++- .../readerforselfossv2/utils/DateUtils.kt | 5 +-- 9 files changed, 54 insertions(+), 39 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt index 427ee28..e110dab 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt @@ -48,6 +48,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActiv import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.android.utils.persistence.toEntity import bou.amine.apps.readerforselfossv2.android.utils.persistence.toView +import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.utils.DateUtils import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl @@ -150,6 +151,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override val di by closestDI() private val apiDetailsService : ApiDetailsService by instance() + private val repository : Repository by instance() data class DrawerData(val tags: List?, val sources: List?) @@ -201,7 +203,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ) dataBase = AndroidDeviceDatabase(applicationContext) - searchService = SearchService(DateUtils(apiDetailsService)) + searchService = SearchService(DateUtils(repository.apiMajorVersion)) dbService = AndroidDeviceDatabaseService(dataBase, searchService) service = SelfossService(api, dbService, searchService) items = ArrayList() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/MyApp.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/MyApp.kt index c9b2052..82c9b0f 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/MyApp.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/MyApp.kt @@ -27,7 +27,7 @@ class MyApp : MultiDexApplication(), DIAware { override val di by DI.lazy { import(networkModule) - bind() with singleton { RepositoryImpl(instance()) } + bind() with singleton { RepositoryImpl(instance(), instance()) } } private lateinit var config: Config 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 c1ca4b9..2428217 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 @@ -71,7 +71,7 @@ class ItemCardAdapter( binding.title.setLinkTextColor(appColors.colorAccent) - binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(apiDetailsService)) + binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(repository.apiMajorVersion)) if (!fullHeightCards) { binding.itemImage.maxHeight = imageMaxHeight 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 cacbe45..c656d6a 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 @@ -59,7 +59,7 @@ class ItemListAdapter( binding.title.setLinkTextColor(appColors.colorAccent) - binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(apiDetailsService)) + binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(repository.apiMajorVersion)) if (itm.getThumbnail(apiDetailsService.getBaseUrl()).isEmpty()) { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/background/background.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/background/background.kt index ad502e9..e853ee6 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/background/background.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/background/background.kt @@ -24,6 +24,7 @@ import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATIO import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_3_4 import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable +import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel @@ -46,6 +47,7 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con override val di by lazy { (applicationContext as MyApp).di } private val apiDetailsService : ApiDetailsService by instance() + private val repository : Repository by instance() override fun doWork(): Result { val settings = Settings() @@ -59,7 +61,7 @@ override fun doWork(): Result { apiDetailsService ) - val dateUtils = DateUtils(apiDetailsService) + val dateUtils = DateUtils(repository.apiMajorVersion) val searchService = SearchService(dateUtils) val service = SelfossService(api, AndroidDeviceDatabaseService(AndroidDeviceDatabase(applicationContext), searchService), searchService) 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 518c59f..43a9013 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 @@ -9,7 +9,10 @@ import android.graphics.drawable.ColorDrawable import android.net.Uri import android.os.Bundle import android.view.* -import android.webkit.* +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.browser.customtabs.CustomTabsIntent @@ -23,10 +26,7 @@ import bou.amine.apps.readerforselfossv2.android.api.mercury.MercuryApi import bou.amine.apps.readerforselfossv2.android.api.mercury.ParsedContent import bou.amine.apps.readerforselfossv2.android.databinding.FragmentArticleBinding import bou.amine.apps.readerforselfossv2.android.model.* -import bou.amine.apps.readerforselfossv2.android.persistence.AndroidDeviceDatabase -import bou.amine.apps.readerforselfossv2.android.persistence.AndroidDeviceDatabaseService import bou.amine.apps.readerforselfossv2.android.persistence.database.AppDatabase -import bou.amine.apps.readerforselfossv2.android.persistence.entities.AndroidItemEntity import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_1_2 import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_2_3 import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_3_4 @@ -36,11 +36,8 @@ import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActiv import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable -import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl +import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService -import bou.amine.apps.readerforselfossv2.service.SearchService -import bou.amine.apps.readerforselfossv2.service.SelfossService import bou.amine.apps.readerforselfossv2.utils.DateUtils import bou.amine.apps.readerforselfossv2.utils.isEmptyOrNullOrNullString import com.bumptech.glide.Glide @@ -52,8 +49,10 @@ import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.kodein.di.* +import org.kodein.di.DI +import org.kodein.di.DIAware import org.kodein.di.android.x.closestDI +import org.kodein.di.instance import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -63,8 +62,6 @@ import java.util.* import java.util.concurrent.ExecutionException class ArticleFragment : Fragment(), DIAware { - private lateinit var dbService: AndroidDeviceDatabaseService - private lateinit var service: SelfossService private var fontSize: Int = 16 private lateinit var item: SelfossModel.Item private var mCustomTabActivityHelper: CustomTabActivityHelper? = null @@ -83,7 +80,7 @@ class ArticleFragment : Fragment(), DIAware { private val binding get() = _binding!! override val di : DI by closestDI() - private val apiDetailsService : ApiDetailsService by instance() + private val repository: Repository by instance() private var settings = Settings() @@ -105,10 +102,6 @@ class ArticleFragment : Fragment(), DIAware { super.onCreate(savedInstanceState) - dbService = AndroidDeviceDatabaseService(AndroidDeviceDatabase(requireContext()), SearchService(DateUtils(apiDetailsService))) - - service = SelfossService(SelfossApiImpl(apiDetailsService), dbService, SearchService(DateUtils(apiDetailsService))) - val pi: ParecelableItem = requireArguments().getParcelable(ARG_ITEMS)!! item = pi.toModel() @@ -130,8 +123,8 @@ class ArticleFragment : Fragment(), DIAware { url = item.getLinkDecoded() contentText = item.content contentTitle = item.getTitleDecoded() - contentImage = item.getThumbnail(apiDetailsService.getBaseUrl()) - contentSource = item.sourceAndDateText(DateUtils(apiDetailsService)) + contentImage = item.getThumbnail(repository.baseUrl) + contentSource = item.sourceAndDateText(DateUtils(repository.apiMajorVersion)) allImages = item.getImages() fontSize = settings.getString("reader_font_size", "16").toInt() @@ -151,14 +144,6 @@ class ArticleFragment : Fragment(), DIAware { refreshAlignment() - val api = SelfossApiImpl( -// requireContext(), -// requireActivity(), -// settings.getBoolean("isSelfSignedCert", false), -// prefs.getString("api_timeout", "-1")!!.toLong() - apiDetailsService - ) - fab = binding.fab fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent) @@ -185,8 +170,7 @@ class ArticleFragment : Fragment(), DIAware { R.id.unread_action -> if (context != null) { if (this@ArticleFragment.item.unread) { CoroutineScope(Dispatchers.IO).launch { - api.markAsRead(this@ArticleFragment.item.id.toString()) - // TODO: Update in DB + repository.markAsRead(this@ArticleFragment.item.id.toString()) } this@ArticleFragment.item.unread = false Toast.makeText( @@ -196,8 +180,7 @@ class ArticleFragment : Fragment(), DIAware { ).show() } else { CoroutineScope(Dispatchers.IO).launch { - api.unmarkAsRead(this@ArticleFragment.item.id.toString()) - // TODO: Update in DB + repository.unmarkAsRead(this@ArticleFragment.item.id.toString()) } this@ArticleFragment.item.unread = true Toast.makeText( diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt index 0e23bcd..b49a885 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt @@ -7,8 +7,11 @@ interface Repository { // TODO: remove the items variables in favor of storing everything in the database var items: List var selectedItems: List + var baseUrl: String // API + var apiMajorVersion: Int + fun getMoreItems(): List fun stats(): SelfossModel.Stats fun getTags(): List diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt index 62e49dd..cde13c5 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt @@ -2,14 +2,28 @@ package bou.amine.apps.readerforselfossv2.repository import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.rest.SelfossModel +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.russhwolf.settings.Settings import io.github.aakira.napier.Napier +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch -class RepositoryImpl(private val api: SelfossApi) : Repository { +class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDetailsService) : Repository { val settings = Settings() override lateinit var items: List override lateinit var selectedItems: List + override var baseUrl = apiDetails.getBaseUrl() + + override var apiMajorVersion = 0 + + init { + // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found + CoroutineScope(Dispatchers.Main).launch { + updateApiVersion() + } + } override fun getMoreItems(): List { TODO("Not yet implemented") @@ -92,5 +106,17 @@ class RepositoryImpl(private val api: SelfossApi) : Repository { override fun refreshLoginInformation() { api.refreshLoginInformation() + baseUrl = apiDetails.getBaseUrl() + } + + private suspend fun updateApiVersion() { + // TODO: Handle connectivity issues + val fetchedVersion = api.version() + if (fetchedVersion != null) { + apiMajorVersion = fetchedVersion.getApiMajorVersion() + settings.putInt("apiVersionMajor", apiMajorVersion) + } else { + apiMajorVersion = settings.getInt("apiVersionMajor", 0) + } } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 2bafad3..0af9e4f 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -2,7 +2,6 @@ package bou.amine.apps.readerforselfossv2.utils import android.text.format.DateUtils import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import java.time.Instant import java.time.LocalDateTime import java.time.OffsetDateTime @@ -15,12 +14,12 @@ fun SelfossModel.Item.parseDate(dateUtils: bou.amine.apps.readerforselfossv2.uti fun SelfossModel.Item.parseRelativeDate(dateUtils: bou.amine.apps.readerforselfossv2.utils.DateUtils): String = dateUtils.parseRelativeDate(this.datetime) -class DateUtils(private val apiDetailsService: ApiDetailsService) { +class DateUtils(private val apiMajorVersion: Int) { fun parseDate(dateString: String): Instant { val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss" - return if (apiDetailsService.getApiVersion() >= 4) { + return if (apiMajorVersion >= 4) { OffsetDateTime.parse(dateString).toInstant() } else { LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant(ZoneOffset.UTC)