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
This commit is contained in:
davide 2022-07-21 15:19:22 +02:00
parent 9373024147
commit 7221f11f80
9 changed files with 54 additions and 39 deletions

View File

@ -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.network.isNetworkAvailable
import bou.amine.apps.readerforselfossv2.android.utils.persistence.toEntity import bou.amine.apps.readerforselfossv2.android.utils.persistence.toEntity
import bou.amine.apps.readerforselfossv2.android.utils.persistence.toView 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.utils.DateUtils
import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl
@ -150,6 +151,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
override val di by closestDI() override val di by closestDI()
private val apiDetailsService : ApiDetailsService by instance() private val apiDetailsService : ApiDetailsService by instance()
private val repository : Repository by instance()
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?) data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
@ -201,7 +203,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
) )
dataBase = AndroidDeviceDatabase(applicationContext) dataBase = AndroidDeviceDatabase(applicationContext)
searchService = SearchService(DateUtils(apiDetailsService)) searchService = SearchService(DateUtils(repository.apiMajorVersion))
dbService = AndroidDeviceDatabaseService(dataBase, searchService) dbService = AndroidDeviceDatabaseService(dataBase, searchService)
service = SelfossService(api, dbService, searchService) service = SelfossService(api, dbService, searchService)
items = ArrayList() items = ArrayList()

View File

@ -27,7 +27,7 @@ class MyApp : MultiDexApplication(), DIAware {
override val di by DI.lazy { override val di by DI.lazy {
import(networkModule) import(networkModule)
bind<Repository>() with singleton { RepositoryImpl(instance()) } bind<Repository>() with singleton { RepositoryImpl(instance(), instance()) }
} }
private lateinit var config: Config private lateinit var config: Config

View File

@ -71,7 +71,7 @@ class ItemCardAdapter(
binding.title.setLinkTextColor(appColors.colorAccent) binding.title.setLinkTextColor(appColors.colorAccent)
binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(apiDetailsService)) binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(repository.apiMajorVersion))
if (!fullHeightCards) { if (!fullHeightCards) {
binding.itemImage.maxHeight = imageMaxHeight binding.itemImage.maxHeight = imageMaxHeight

View File

@ -59,7 +59,7 @@ class ItemListAdapter(
binding.title.setLinkTextColor(appColors.colorAccent) 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()) { if (itm.getThumbnail(apiDetailsService.getBaseUrl()).isEmpty()) {

View File

@ -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.persistence.migrations.MIGRATION_3_4
import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.Config
import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable 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.SelfossApiImpl
import bou.amine.apps.readerforselfossv2.rest.SelfossModel 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 } override val di by lazy { (applicationContext as MyApp).di }
private val apiDetailsService : ApiDetailsService by instance() private val apiDetailsService : ApiDetailsService by instance()
private val repository : Repository by instance()
override fun doWork(): Result { override fun doWork(): Result {
val settings = Settings() val settings = Settings()
@ -59,7 +61,7 @@ override fun doWork(): Result {
apiDetailsService apiDetailsService
) )
val dateUtils = DateUtils(apiDetailsService) val dateUtils = DateUtils(repository.apiMajorVersion)
val searchService = SearchService(dateUtils) val searchService = SearchService(dateUtils)
val service = SelfossService(api, AndroidDeviceDatabaseService(AndroidDeviceDatabase(applicationContext), searchService), searchService) val service = SelfossService(api, AndroidDeviceDatabaseService(AndroidDeviceDatabase(applicationContext), searchService), searchService)

View File

@ -9,7 +9,10 @@ import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.* 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 android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.browser.customtabs.CustomTabsIntent 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.api.mercury.ParsedContent
import bou.amine.apps.readerforselfossv2.android.databinding.FragmentArticleBinding import bou.amine.apps.readerforselfossv2.android.databinding.FragmentArticleBinding
import bou.amine.apps.readerforselfossv2.android.model.* 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.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_1_2
import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_2_3 import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_2_3
import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_3_4 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.getBitmapInputStream
import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth
import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable 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.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.DateUtils
import bou.amine.apps.readerforselfossv2.utils.isEmptyOrNullOrNullString import bou.amine.apps.readerforselfossv2.utils.isEmptyOrNullOrNullString
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -52,8 +49,10 @@ import com.russhwolf.settings.Settings
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch 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.android.x.closestDI
import org.kodein.di.instance
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -63,8 +62,6 @@ import java.util.*
import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutionException
class ArticleFragment : Fragment(), DIAware { class ArticleFragment : Fragment(), DIAware {
private lateinit var dbService: AndroidDeviceDatabaseService
private lateinit var service: SelfossService<AndroidItemEntity>
private var fontSize: Int = 16 private var fontSize: Int = 16
private lateinit var item: SelfossModel.Item private lateinit var item: SelfossModel.Item
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null private var mCustomTabActivityHelper: CustomTabActivityHelper? = null
@ -83,7 +80,7 @@ class ArticleFragment : Fragment(), DIAware {
private val binding get() = _binding!! private val binding get() = _binding!!
override val di : DI by closestDI() override val di : DI by closestDI()
private val apiDetailsService : ApiDetailsService by instance() private val repository: Repository by instance()
private var settings = Settings() private var settings = Settings()
@ -105,10 +102,6 @@ class ArticleFragment : Fragment(), DIAware {
super.onCreate(savedInstanceState) 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)!! val pi: ParecelableItem = requireArguments().getParcelable(ARG_ITEMS)!!
item = pi.toModel() item = pi.toModel()
@ -130,8 +123,8 @@ class ArticleFragment : Fragment(), DIAware {
url = item.getLinkDecoded() url = item.getLinkDecoded()
contentText = item.content contentText = item.content
contentTitle = item.getTitleDecoded() contentTitle = item.getTitleDecoded()
contentImage = item.getThumbnail(apiDetailsService.getBaseUrl()) contentImage = item.getThumbnail(repository.baseUrl)
contentSource = item.sourceAndDateText(DateUtils(apiDetailsService)) contentSource = item.sourceAndDateText(DateUtils(repository.apiMajorVersion))
allImages = item.getImages() allImages = item.getImages()
fontSize = settings.getString("reader_font_size", "16").toInt() fontSize = settings.getString("reader_font_size", "16").toInt()
@ -151,14 +144,6 @@ class ArticleFragment : Fragment(), DIAware {
refreshAlignment() refreshAlignment()
val api = SelfossApiImpl(
// requireContext(),
// requireActivity(),
// settings.getBoolean("isSelfSignedCert", false),
// prefs.getString("api_timeout", "-1")!!.toLong()
apiDetailsService
)
fab = binding.fab fab = binding.fab
fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent) fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
@ -185,8 +170,7 @@ class ArticleFragment : Fragment(), DIAware {
R.id.unread_action -> if (context != null) { R.id.unread_action -> if (context != null) {
if (this@ArticleFragment.item.unread) { if (this@ArticleFragment.item.unread) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
api.markAsRead(this@ArticleFragment.item.id.toString()) repository.markAsRead(this@ArticleFragment.item.id.toString())
// TODO: Update in DB
} }
this@ArticleFragment.item.unread = false this@ArticleFragment.item.unread = false
Toast.makeText( Toast.makeText(
@ -196,8 +180,7 @@ class ArticleFragment : Fragment(), DIAware {
).show() ).show()
} else { } else {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
api.unmarkAsRead(this@ArticleFragment.item.id.toString()) repository.unmarkAsRead(this@ArticleFragment.item.id.toString())
// TODO: Update in DB
} }
this@ArticleFragment.item.unread = true this@ArticleFragment.item.unread = true
Toast.makeText( Toast.makeText(

View File

@ -7,8 +7,11 @@ interface Repository {
// TODO: remove the items variables in favor of storing everything in the database // TODO: remove the items variables in favor of storing everything in the database
var items: List<SelfossModel.Item> var items: List<SelfossModel.Item>
var selectedItems: List<SelfossModel.Item> var selectedItems: List<SelfossModel.Item>
var baseUrl: String
// API // API
var apiMajorVersion: Int
fun getMoreItems(): List<SelfossModel.Item> fun getMoreItems(): List<SelfossModel.Item>
fun stats(): SelfossModel.Stats fun stats(): SelfossModel.Stats
fun getTags(): List<SelfossModel.Tag> fun getTags(): List<SelfossModel.Tag>

View File

@ -2,14 +2,28 @@ package bou.amine.apps.readerforselfossv2.repository
import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.rest.SelfossModel
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
import com.russhwolf.settings.Settings import com.russhwolf.settings.Settings
import io.github.aakira.napier.Napier 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() val settings = Settings()
override lateinit var items: List<SelfossModel.Item> override lateinit var items: List<SelfossModel.Item>
override lateinit var selectedItems: List<SelfossModel.Item> override lateinit var selectedItems: List<SelfossModel.Item>
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<SelfossModel.Item> { override fun getMoreItems(): List<SelfossModel.Item> {
TODO("Not yet implemented") TODO("Not yet implemented")
@ -92,5 +106,17 @@ class RepositoryImpl(private val api: SelfossApi) : Repository {
override fun refreshLoginInformation() { override fun refreshLoginInformation() {
api.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)
}
} }
} }

View File

@ -2,7 +2,6 @@ package bou.amine.apps.readerforselfossv2.utils
import android.text.format.DateUtils import android.text.format.DateUtils
import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.rest.SelfossModel
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
import java.time.Instant import java.time.Instant
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.OffsetDateTime 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 = fun SelfossModel.Item.parseRelativeDate(dateUtils: bou.amine.apps.readerforselfossv2.utils.DateUtils): String =
dateUtils.parseRelativeDate(this.datetime) dateUtils.parseRelativeDate(this.datetime)
class DateUtils(private val apiDetailsService: ApiDetailsService) { class DateUtils(private val apiMajorVersion: Int) {
fun parseDate(dateString: String): Instant { fun parseDate(dateString: String): Instant {
val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss" val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss"
return if (apiDetailsService.getApiVersion() >= 4) { return if (apiMajorVersion >= 4) {
OffsetDateTime.parse(dateString).toInstant() OffsetDateTime.parse(dateString).toInstant()
} else { } else {
LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant(ZoneOffset.UTC) LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant(ZoneOffset.UTC)