From c0e7b1fa0e035fddb91fec447ec947961ca96a4a Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 18 Jul 2022 01:28:56 +0200 Subject: [PATCH 01/48] Initial Dependency Injection implementation --- androidApp/build.gradle.kts | 3 + .../android/AddSourceActivity.kt | 13 +-- .../android/HomeActivity.kt | 6 +- .../android/LoginActivity.kt | 30 +++--- .../apps/readerforselfossv2/android/MyApp.kt | 12 ++- .../android/ReaderActivity.kt | 6 +- .../android/SourcesActivity.kt | 8 +- .../android/adapters/ItemCardAdapter.kt | 4 +- .../android/adapters/ItemListAdapter.kt | 4 +- .../android/adapters/ItemsAdapter.kt | 4 +- .../android/adapters/SourcesListAdapter.kt | 4 +- .../android/background/background.kt | 4 +- .../android/fragments/ArticleFragment.kt | 6 +- .../service/AndroidApiDetailsService.kt | 12 ++- shared/build.gradle.kts | 6 ++ .../rest/{SelfossApi.kt => SelfossApiImpl.kt} | 102 +++++++++++++----- .../service/ApiDetailsService.kt | 1 + 17 files changed, 146 insertions(+), 79 deletions(-) rename shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/{SelfossApi.kt => SelfossApiImpl.kt} (76%) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index f675617..c2c5c6a 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -170,6 +170,9 @@ dependencies { implementation("me.relex:circleindicator:2.1.6") implementation("androidx.viewpager2:viewpager2:1.1.0-beta01") + //Dependency Injection + implementation("org.kodein.di:kodein-di:7.12.0") + //PhotoView implementation("com.github.chrisbanes:PhotoView:2.3.0") 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 681b285..eeedf5f 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 @@ -19,13 +19,10 @@ import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid import com.ftinc.scoop.Scoop -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import kotlinx.coroutines.CoroutineScope @@ -37,7 +34,7 @@ class AddSourceActivity : AppCompatActivity() { private lateinit var apiDetailsService: ApiDetailsService private var mSpoutsValue: String? = null - private lateinit var api: SelfossApi + private lateinit var api: SelfossApiImpl private lateinit var appColors: AppColors private lateinit var binding: ActivityAddSourceBinding @@ -81,7 +78,7 @@ class AddSourceActivity : AppCompatActivity() { val settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) apiDetailsService = AndroidApiDetailsService(this@AddSourceActivity) - api = SelfossApi( + api = SelfossApiImpl( // this, // this@AddSourceActivity, // settings.getBoolean("isSelfSignedCert", false), @@ -114,7 +111,7 @@ class AddSourceActivity : AppCompatActivity() { private fun handleSpoutsSpinner( spoutsSpinner: Spinner, - api: SelfossApi?, + api: SelfossApiImpl?, mProgress: ProgressBar, formContainer: ConstraintLayout ) { @@ -182,7 +179,7 @@ class AddSourceActivity : AppCompatActivity() { finish() } - private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApi) { + private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApiImpl) { val sourceDetailsUnavailable = title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty() 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 81fd1b9..ad657ab 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 @@ -54,7 +54,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.persistence.toEntity import bou.amine.apps.readerforselfossv2.android.utils.persistence.toView import bou.amine.apps.readerforselfossv2.utils.DateUtils -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.service.SearchService @@ -129,7 +129,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { private lateinit var tabNewBadge: TextBadgeItem private lateinit var tabArchiveBadge: TextBadgeItem private lateinit var tabStarredBadge: TextBadgeItem - private lateinit var api: SelfossApi + private lateinit var api: SelfossApiImpl private lateinit var customTabActivityHelper: CustomTabActivityHelper private lateinit var editor: SharedPreferences.Editor private lateinit var sharedPref: SharedPreferences @@ -196,7 +196,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) apiDetailsService = AndroidApiDetailsService(applicationContext) - api = SelfossApi( + api = SelfossApiImpl( // this, // this@HomeActivity, // settings.getBoolean("isSelfSignedCert", false), 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 a1eadc2..1b3e222 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 @@ -15,24 +15,19 @@ import android.view.View import android.view.inputmethod.EditorInfo import android.widget.TextView import androidx.preference.PreferenceManager -import androidx.work.Logger import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.themes.AppColors -import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.mikepenz.aboutlibraries.LibsBuilder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import org.kodein.di.* -class LoginActivity : AppCompatActivity() { +class LoginActivity() : AppCompatActivity(), DIAware { private var inValidCount: Int = 0 private var isWithSelfSignedCert = false @@ -45,6 +40,10 @@ class LoginActivity : AppCompatActivity() { private lateinit var appColors: AppColors private lateinit var binding: ActivityLoginBinding + override val diContext: DIContext<*> = diContext(this) + override val di by lazy { (application as MyApp).di } + private val apiDetailsService : ApiDetailsService by instance() + override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@LoginActivity) @@ -139,7 +138,6 @@ class LoginActivity : AppCompatActivity() { binding.passwordView.error = getString(R.string.wrong_infos) binding.httpLoginView.error = getString(R.string.wrong_infos) binding.httpPasswordView.error = getString(R.string.wrong_infos) - showProgress(false) } private fun attemptLogin() { @@ -219,9 +217,9 @@ class LoginActivity : AppCompatActivity() { editor.putString("httpPassword", httpPassword) editor.putBoolean("isSelfSignedCert", isWithSelfSignedCert) editor.apply() + apiDetailsService.refresh() - val apiDetailsService = AndroidApiDetailsService(this@LoginActivity) - val api = SelfossApi( + val api = SelfossApiImpl( // this, // this@LoginActivity, // isWithSelfSignedCert, @@ -236,15 +234,17 @@ class LoginActivity : AppCompatActivity() { if (result != null && result.isSuccess) { goToMain() } else { - preferenceError(Exception("Not success")) + CoroutineScope(Dispatchers.Main).launch { + preferenceError(Exception("Not success")) + } } } catch (cause: Throwable) { - Log.e("1", "LOL") + Log.e("1", cause.message!!) + Log.e("1", cause.stackTraceToString()) } } - } else { - showProgress(false) } + showProgress(false) } } 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 7d19deb..b18a683 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 @@ -9,16 +9,26 @@ import android.os.Build import androidx.preference.PreferenceManager import android.widget.ImageView import androidx.multidex.MultiDexApplication +import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.ftinc.scoop.Scoop import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader import com.mikepenz.materialdrawer.util.DrawerImageLoader +import org.kodein.di.* import java.util.UUID.randomUUID -class MyApp : MultiDexApplication() { +class MyApp : MultiDexApplication(), DIAware { + + override val di by DI.lazy { + bind() with instance(this@MyApp.applicationContext) + + bind() with singleton { AndroidApiDetailsService(instance()) } + } + private lateinit var config: Config override fun onCreate() { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index 7a945bd..dea9ffe 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -25,7 +25,7 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.toggleStar -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.ftinc.scoop.Scoop @@ -40,7 +40,7 @@ class ReaderActivity : AppCompatActivity() { private lateinit var userIdentifier: String private lateinit var appColors: AppColors - private lateinit var api: SelfossApi + private lateinit var api: SelfossApiImpl private lateinit var toolbarMenu: Menu @@ -101,7 +101,7 @@ class ReaderActivity : AppCompatActivity() { markOnScroll = prefs.getBoolean("mark_on_scroll", false) activeAlignment = prefs.getInt("text_align", JUSTIFY) - api = SelfossApi( + api = SelfossApiImpl( // this, // this@ReaderActivity, // settings.getBoolean("isSelfSignedCert", false), 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 eb949e0..b2580c5 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 @@ -15,16 +15,12 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.ftinc.scoop.Scoop import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response import java.util.ArrayList class SourcesActivity : AppCompatActivity() { @@ -67,7 +63,7 @@ class SourcesActivity : AppCompatActivity() { val prefs = PreferenceManager.getDefaultSharedPreferences(this) val apiDetailsService = AndroidApiDetailsService(this@SourcesActivity) - val api = SelfossApi( + val api = SelfossApiImpl( // this, // this@SourcesActivity, // settings.getBoolean("isSelfSignedCert", false), 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 368e7d7..8fad61e 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 @@ -17,7 +17,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActiv import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.service.SearchService @@ -32,7 +32,7 @@ import kotlinx.coroutines.launch class ItemCardAdapter( override val app: Activity, override var items: ArrayList, - override val api: SelfossApi, + override val api: SelfossApiImpl, override val apiDetailsService: ApiDetailsService, override val db: AppDatabase, private val helper: CustomTabActivityHelper, 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 e4c52fd..f440180 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 @@ -13,7 +13,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.* import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.service.SearchService @@ -24,7 +24,7 @@ import com.amulyakhare.textdrawable.util.ColorGenerator class ItemListAdapter( override val app: Activity, override var items: ArrayList, - override val api: SelfossApi, + override val api: SelfossApiImpl, override val apiDetailsService: ApiDetailsService, override val db: AppDatabase, private val helper: CustomTabActivityHelper, diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index 82a3cd1..c7f8da0 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -8,7 +8,7 @@ import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.persistence.database.AppDatabase import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.Config -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.service.SearchService @@ -19,7 +19,7 @@ import kotlinx.coroutines.launch abstract class ItemsAdapter : RecyclerView.Adapter() { abstract var items: ArrayList - abstract val api: SelfossApi + abstract val api: SelfossApiImpl abstract val apiDetailsService: ApiDetailsService abstract val db: AppDatabase abstract val userIdentifier: String diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt index b49168e..aaff569 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt @@ -16,7 +16,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.android.utils.toTextDrawableString -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.amulyakhare.textdrawable.TextDrawable @@ -28,7 +28,7 @@ import kotlinx.coroutines.launch class SourcesListAdapter( private val app: Activity, private val items: ArrayList, - private val api: SelfossApi, + private val api: SelfossApiImpl, private val apiDetailsService: ApiDetailsService ) : RecyclerView.Adapter() { private val c: Context = app.baseContext 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 e929f99..4cc9028 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 @@ -26,7 +26,7 @@ import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsServic import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable -import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.SearchService import bou.amine.apps.readerforselfossv2.service.SelfossService @@ -48,7 +48,7 @@ override fun doWork(): Result { val periodicRefresh = sharedPref.getBoolean("periodic_refresh", false) if (periodicRefresh) { val apiDetailsService = AndroidApiDetailsService(this.context) - val api = SelfossApi( + val api = SelfossApiImpl( // this.context, // null, // settings.getBoolean("isSelfSignedCert", false), 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 c9628aa..b1297b7 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 @@ -40,7 +40,7 @@ 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.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.service.SearchService @@ -109,7 +109,7 @@ class ArticleFragment : Fragment() { dbService = AndroidDeviceDatabaseService(AndroidDeviceDatabase(requireContext()), SearchService(DateUtils(apiDetailsService))) - service = SelfossService(SelfossApi(apiDetailsService), dbService, SearchService(DateUtils(apiDetailsService))) + service = SelfossService(SelfossApiImpl(apiDetailsService), dbService, SearchService(DateUtils(apiDetailsService))) val pi: ParecelableItem = requireArguments().getParcelable(ARG_ITEMS)!! @@ -157,7 +157,7 @@ class ArticleFragment : Fragment() { val settings = requireActivity().getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - val api = SelfossApi( + val api = SelfossApiImpl( // requireContext(), // requireActivity(), // settings.getBoolean("isSelfSignedCert", false), diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt index 77e6e31..8e64e10 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt @@ -19,8 +19,8 @@ class AndroidApiDetailsService(c: Context) : ApiDetailsService { override fun getApiVersion(): Int { if (_apiVersion == -1) { - _apiVersion = settings.getInt("apiVersionMajor", -1)!! - return settings.getInt("apiVersionMajor", -1)!! + _apiVersion = settings.getInt("apiVersionMajor", -1) + return _apiVersion } return _apiVersion } @@ -45,4 +45,12 @@ class AndroidApiDetailsService(c: Context) : ApiDetailsService { } return _password } + + override fun refresh() { + _password = settings.getString("password", "")!! + _userName = settings.getString("login", "")!! + _baseUrl = settings.getString("url", "")!! + _baseUrl = settings.getString("url", "")!! + _apiVersion = settings.getInt("apiVersionMajor", -1) + } } \ No newline at end of file diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index f09de7c..ee7aa5b 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -27,6 +27,9 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") implementation("io.ktor:ktor-client-auth:2.0.1") implementation("org.jsoup:jsoup:1.14.3") + + //Dependency Injection + implementation("org.kodein.di:kodein-di:7.12.0") } } val commonTest by getting { @@ -38,6 +41,9 @@ kotlin { val androidMain by getting { dependencies { implementation("io.ktor:ktor-client-android:2.0.1") + + //Dependency Injection + implementation("org.kodein.di:kodein-di:7.12.0") } } val androidTest by getting { diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt similarity index 76% rename from shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt index 23fc2bd..d01fc94 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt @@ -3,10 +3,6 @@ package bou.amine.apps.readerforselfossv2.rest import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import io.ktor.client.* import io.ktor.client.call.* -import io.ktor.client.engine.* -import io.ktor.client.engine.ProxyBuilder.http -import io.ktor.client.plugins.auth.* -import io.ktor.client.plugins.auth.providers.* import io.ktor.client.plugins.cache.* import io.ktor.client.request.* import io.ktor.client.request.forms.* @@ -16,9 +12,59 @@ import io.ktor.client.plugins.logging.* import io.ktor.serialization.kotlinx.json.* import kotlinx.serialization.json.Json -class SelfossApi(private val apiDetailsService: ApiDetailsService) { +interface SelfossApi { + val client: HttpClient + fun url(path: String): String - private val client = HttpClient() { + suspend fun login(): SelfossModel.SuccessResponse? + + suspend fun getItems( + type: String, + items: Int, + offset: Int, + tag: String? = "", + source: Long? = null, + search: String? = "", + updatedSince: String? = "" + ): List? + + suspend fun stats(): SelfossModel.Stats? + + suspend fun tags(): List? + + suspend fun update(): SelfossModel.SuccessResponse? + + suspend fun spouts(): Map? + + suspend fun sources(): ArrayList? + + suspend fun version(): SelfossModel.ApiVersion? + + suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? + + suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? + + suspend fun starr(id: String): SelfossModel.SuccessResponse? + + suspend fun unstarr(id: String): SelfossModel.SuccessResponse? + + suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? + + suspend fun createSourceForVersion( + title: String, + url: String, + spout: String, + tags: String, + filter: String, + version: Int + ): SelfossModel.SuccessResponse? + + suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? +} + +class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : SelfossApi { + + override val client = HttpClient() { install(ContentNegotiation) { install(HttpCache) json(Json { @@ -52,24 +98,24 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { expectSuccess = false } - private fun url(path: String) = + override fun url(path: String) = "${apiDetailsService.getBaseUrl()}$path" - suspend fun login(): SelfossModel.SuccessResponse? = + override suspend fun login(): SelfossModel.SuccessResponse? = client.get(url("/login")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun getItems( + override suspend fun getItems( type: String, items: Int, offset: Int, - tag: String? = "", - source: Long? = null, - search: String? = "", - updatedSince: String? = "" + tag: String?, + source: Long?, + search: String?, + updatedSince: String? ): List? = client.get(url("/items")) { parameter("username", apiDetailsService.getUserName()) @@ -83,64 +129,64 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { parameter("offset", offset) }.body() - suspend fun stats(): SelfossModel.Stats? = + override suspend fun stats(): SelfossModel.Stats? = client.get(url("/stats")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun tags(): List? = + override suspend fun tags(): List? = client.get(url("/tags")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun update(): SelfossModel.SuccessResponse? = + override suspend fun update(): SelfossModel.SuccessResponse? = client.get(url("/update")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun spouts(): Map? = + override suspend fun spouts(): Map? = client.get(url("/sources/spouts")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun sources(): ArrayList? = + override suspend fun sources(): ArrayList? = client.get(url("/sources/list")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun version(): SelfossModel.ApiVersion? = + override suspend fun version(): SelfossModel.ApiVersion? = client.get(url("/api/about")).body() - suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? = + override suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? = client.post(url("/mark/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? = + override suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? = client.post(url("/unmark/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun starr(id: String): SelfossModel.SuccessResponse? = + override suspend fun starr(id: String): SelfossModel.SuccessResponse? = client.post(url("/starr/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun unstarr(id: String): SelfossModel.SuccessResponse? = + override suspend fun unstarr(id: String): SelfossModel.SuccessResponse? = client.post(url("/unstarr/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? = + override suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? = client.submitForm( url = url("/mark"), formParameters = Parameters.build { @@ -150,7 +196,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { } ).body() - suspend fun createSourceForVersion( + override suspend fun createSourceForVersion( title: String, url: String, spout: String, @@ -164,7 +210,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { createSource(title, url, spout, tags, filter) } - private suspend fun createSource( + suspend fun createSource( title: String, url: String, spout: String, @@ -182,7 +228,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { } ).body() - private suspend fun createSource2( + suspend fun createSource2( title: String, url: String, spout: String, @@ -200,7 +246,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { } ).body() - suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? = + override suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? = client.delete(url("/source/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsService.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsService.kt index 77214c9..48e477e 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsService.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsService.kt @@ -6,4 +6,5 @@ interface ApiDetailsService { fun getBaseUrl(): String fun getUserName(): String fun getPassword(): String + fun refresh() } \ No newline at end of file From 21f39d64b3bed283586ccbdb70176d67c751adf3 Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 18 Jul 2022 14:05:47 +0200 Subject: [PATCH 02/48] Inject the Api Details Service --- androidApp/build.gradle.kts | 1 + .../readerforselfossv2/android/AddSourceActivity.kt | 11 +++++++---- .../apps/readerforselfossv2/android/HomeActivity.kt | 11 +++++++---- .../apps/readerforselfossv2/android/LoginActivity.kt | 4 ++-- .../apps/readerforselfossv2/android/ReaderActivity.kt | 11 ++++++++--- .../readerforselfossv2/android/SourcesActivity.kt | 11 ++++++++--- .../android/background/background.kt | 11 ++++++++--- .../android/fragments/ArticleFragment.kt | 11 ++++++----- shared/build.gradle.kts | 1 + 9 files changed, 48 insertions(+), 24 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index c2c5c6a..cabb1c2 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -172,6 +172,7 @@ dependencies { //Dependency Injection implementation("org.kodein.di:kodein-di:7.12.0") + implementation("org.kodein.di:kodein-di-framework-android-x:7.12.0") //PhotoView implementation("com.github.chrisbanes:PhotoView:2.3.0") 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 eeedf5f..d8908f6 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 @@ -20,7 +20,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid import com.ftinc.scoop.Scoop import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel @@ -28,17 +27,22 @@ import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DIAware +import org.kodein.di.android.closestDI +import org.kodein.di.instance -class AddSourceActivity : AppCompatActivity() { +class AddSourceActivity : AppCompatActivity(), DIAware { - private lateinit var apiDetailsService: ApiDetailsService private var mSpoutsValue: String? = null private lateinit var api: SelfossApiImpl private lateinit var appColors: AppColors private lateinit var binding: ActivityAddSourceBinding + override val di by closestDI() + private val apiDetailsService : ApiDetailsService by instance() + override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@AddSourceActivity) @@ -77,7 +81,6 @@ class AddSourceActivity : AppCompatActivity() { val prefs = PreferenceManager.getDefaultSharedPreferences(this) val settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - apiDetailsService = AndroidApiDetailsService(this@AddSourceActivity) api = SelfossApiImpl( // this, // this@AddSourceActivity, 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 ad657ab..24e79f7 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 @@ -41,7 +41,6 @@ import bou.amine.apps.readerforselfossv2.android.persistence.entities.AndroidIte 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 -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings @@ -83,15 +82,17 @@ import com.mikepenz.materialdrawer.widget.AccountHeaderView import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DIAware +import org.kodein.di.android.closestDI +import org.kodein.di.instance import java.util.concurrent.TimeUnit import kotlin.concurrent.thread -class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { +class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware { private lateinit var dataBase: AndroidDeviceDatabase private lateinit var dbService: AndroidDeviceDatabaseService private lateinit var searchService: SearchService - private lateinit var apiDetailsService: ApiDetailsService private lateinit var service: SelfossService private val MENU_PREFERENCES = 12302 private val DRAWER_ID_TAGS = 100101L @@ -151,6 +152,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { private lateinit var config: Config + override val di by closestDI() + private val apiDetailsService : ApiDetailsService by instance() + data class DrawerData(val tags: List?, val sources: List?) override fun onStart() { @@ -195,7 +199,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener { sharedPref = PreferenceManager.getDefaultSharedPreferences(this) settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - apiDetailsService = AndroidApiDetailsService(applicationContext) api = SelfossApiImpl( // this, // this@HomeActivity, 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 1b3e222..b4d7b22 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 @@ -26,6 +26,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.kodein.di.* +import org.kodein.di.android.closestDI class LoginActivity() : AppCompatActivity(), DIAware { @@ -40,8 +41,7 @@ class LoginActivity() : AppCompatActivity(), DIAware { private lateinit var appColors: AppColors private lateinit var binding: ActivityLoginBinding - override val diContext: DIContext<*> = diContext(this) - override val di by lazy { (application as MyApp).di } + override val di by closestDI() private val apiDetailsService : ApiDetailsService by instance() override fun onCreate(savedInstanceState: Bundle?) { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index dea9ffe..2b490d5 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -20,7 +20,6 @@ import bou.amine.apps.readerforselfossv2.android.persistence.database.AppDatabas 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 -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config @@ -32,8 +31,11 @@ import com.ftinc.scoop.Scoop import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DIAware +import org.kodein.di.android.closestDI +import org.kodein.di.instance -class ReaderActivity : AppCompatActivity() { +class ReaderActivity : AppCompatActivity(), DIAware { private var markOnScroll: Boolean = false private var currentItem: Int = 0 @@ -52,6 +54,9 @@ class ReaderActivity : AppCompatActivity() { private val JUSTIFY = 1 private val ALIGN_LEFT = 2 + override val di by closestDI() + private val apiDetailsService : ApiDetailsService by instance() + private fun showMenuItem(willAddToFavorite: Boolean) { if (willAddToFavorite) { toolbarMenu.findItem(R.id.star).icon.setTint(Color.WHITE) @@ -106,7 +111,7 @@ class ReaderActivity : AppCompatActivity() { // this@ReaderActivity, // settings.getBoolean("isSelfSignedCert", false), // prefs.getString("api_timeout", "-1")!!.toLong() - AndroidApiDetailsService(this@ReaderActivity) + apiDetailsService ) if (allItems.isEmpty()) { 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 b2580c5..e2217ed 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 @@ -10,24 +10,30 @@ import androidx.recyclerview.widget.LinearLayoutManager import android.widget.Toast import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.ftinc.scoop.Scoop import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DIAware +import org.kodein.di.android.closestDI +import org.kodein.di.instance import java.util.ArrayList -class SourcesActivity : AppCompatActivity() { +class SourcesActivity : AppCompatActivity(), DIAware { private lateinit var appColors: AppColors private lateinit var binding: ActivitySourcesBinding + override val di by closestDI() + private val apiDetailsService : ApiDetailsService by instance() + override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@SourcesActivity) binding = ActivitySourcesBinding.inflate(layoutInflater) @@ -62,7 +68,6 @@ class SourcesActivity : AppCompatActivity() { getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) val prefs = PreferenceManager.getDefaultSharedPreferences(this) - val apiDetailsService = AndroidApiDetailsService(this@SourcesActivity) val api = SelfossApiImpl( // this, // this@SourcesActivity, 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 4cc9028..0b97ffb 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 @@ -13,6 +13,7 @@ import androidx.room.Room import androidx.work.Worker import androidx.work.WorkerParameters import bou.amine.apps.readerforselfossv2.android.MainActivity +import bou.amine.apps.readerforselfossv2.android.MyApp import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.model.preloadImages import bou.amine.apps.readerforselfossv2.android.persistence.AndroidDeviceDatabase @@ -22,32 +23,36 @@ import bou.amine.apps.readerforselfossv2.android.persistence.entities.ActionEnti 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 -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl 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 kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DIAware +import org.kodein.di.instance import java.util.* import kotlin.concurrent.schedule import kotlin.concurrent.thread -class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(context, params) { +class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(context, params), DIAware { lateinit var db: AppDatabase + override val di by lazy { (applicationContext as MyApp).di } + private val apiDetailsService : ApiDetailsService by instance() + override fun doWork(): Result { val settings = this.context.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) val sharedPref = PreferenceManager.getDefaultSharedPreferences(this.context) val periodicRefresh = sharedPref.getBoolean("periodic_refresh", false) if (periodicRefresh) { - val apiDetailsService = AndroidApiDetailsService(this.context) val api = SelfossApiImpl( // this.context, // null, 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 b1297b7..66f987c 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 @@ -33,7 +33,6 @@ import bou.amine.apps.readerforselfossv2.android.persistence.entities.AndroidIte 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 -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.* import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper @@ -55,6 +54,8 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.* +import org.kodein.di.android.x.closestDI import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -63,9 +64,8 @@ import java.net.URL import java.util.* import java.util.concurrent.ExecutionException -class ArticleFragment : Fragment() { +class ArticleFragment : Fragment(), DIAware { private lateinit var dbService: AndroidDeviceDatabaseService - private lateinit var apiDetailsService: ApiDetailsService private lateinit var service: SelfossService private var fontSize: Int = 16 private lateinit var item: SelfossModel.Item @@ -85,6 +85,9 @@ class ArticleFragment : Fragment() { private var _binding: FragmentArticleBinding? = null private val binding get() = _binding!! + override val di : DI by closestDI() + private val apiDetailsService : ApiDetailsService by instance() + private lateinit var prefs: SharedPreferences private var typeface: Typeface? = null @@ -105,8 +108,6 @@ class ArticleFragment : Fragment() { super.onCreate(savedInstanceState) - apiDetailsService = AndroidApiDetailsService(requireContext()) - dbService = AndroidDeviceDatabaseService(AndroidDeviceDatabase(requireContext()), SearchService(DateUtils(apiDetailsService))) service = SelfossService(SelfossApiImpl(apiDetailsService), dbService, SearchService(DateUtils(apiDetailsService))) diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index ee7aa5b..a66811d 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -44,6 +44,7 @@ kotlin { //Dependency Injection implementation("org.kodein.di:kodein-di:7.12.0") + implementation("org.kodein.di:kodein-di-framework-android-x:7.12.0") } } val androidTest by getting { From e4fbdce30e9c06fe421d06eff5c72bda6509033b Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 18 Jul 2022 22:07:46 +0200 Subject: [PATCH 03/48] Remove unnecessary implementation import --- shared/build.gradle.kts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index a66811d..4eaed04 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -41,10 +41,6 @@ kotlin { val androidMain by getting { dependencies { implementation("io.ktor:ktor-client-android:2.0.1") - - //Dependency Injection - implementation("org.kodein.di:kodein-di:7.12.0") - implementation("org.kodein.di:kodein-di-framework-android-x:7.12.0") } } val androidTest by getting { From bbec7745feec7d98a01eb73fcf5a4ae68afbb6a4 Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 18 Jul 2022 23:25:10 +0200 Subject: [PATCH 04/48] Implement multiplatform settings --- androidApp/build.gradle.kts | 3 + .../android/AddSourceActivity.kt | 11 ++- .../android/HomeActivity.kt | 68 ++++++++----------- .../android/LoginActivity.kt | 37 ++++------ .../apps/readerforselfossv2/android/MyApp.kt | 20 +++--- .../android/ReaderActivity.kt | 26 ++----- .../android/SourcesActivity.kt | 10 +-- .../android/adapters/SourcesListAdapter.kt | 2 +- .../android/background/background.kt | 10 ++- .../android/fragments/ArticleFragment.kt | 26 +++---- .../android/settings/SettingsActivity.kt | 15 ++-- .../android/themes/AppColors.kt | 14 ++-- .../android/utils/Config.kt | 22 +++--- .../utils/glide/SelfSignedGlideModule.kt | 6 +- shared/build.gradle.kts | 6 ++ .../service/ApiDetailsServiceImpl.kt | 29 ++++---- 16 files changed, 126 insertions(+), 179 deletions(-) rename androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt => shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt (50%) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index cabb1c2..d4a17f7 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -174,6 +174,9 @@ dependencies { implementation("org.kodein.di:kodein-di:7.12.0") implementation("org.kodein.di:kodein-di-framework-android-x:7.12.0") + //Settings + implementation("com.russhwolf:multiplatform-settings-no-arg:0.9") + //PhotoView implementation("com.github.chrisbanes:PhotoView:2.3.0") 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 d8908f6..75d1631 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 @@ -1,9 +1,7 @@ package bou.amine.apps.readerforselfossv2.android -import android.content.Context import android.content.Intent import android.os.Bundle -import androidx.preference.PreferenceManager import androidx.constraintlayout.widget.ConstraintLayout import androidx.appcompat.app.AppCompatActivity import android.view.View @@ -24,6 +22,7 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBi import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -39,6 +38,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { private lateinit var appColors: AppColors private lateinit var binding: ActivityAddSourceBinding + private val settings = Settings() override val di by closestDI() private val apiDetailsService : ApiDetailsService by instance() @@ -78,9 +78,6 @@ class AddSourceActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayShowHomeEnabled(true) try { - val prefs = PreferenceManager.getDefaultSharedPreferences(this) - val settings = - getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) api = SelfossApiImpl( // this, // this@AddSourceActivity, @@ -103,7 +100,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { override fun onResume() { super.onResume() - val config = Config(this) + val config = Config() if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid(this@AddSourceActivity)) { mustLoginToAddSource() @@ -199,7 +196,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { mSpoutsValue!!, tags.text.toString(), "", - PreferenceManager.getDefaultSharedPreferences(this@AddSourceActivity).getInt("apiVersionMajor", 0) + settings.getInt("apiVersionMajor", 0) ) if (response != null) { finish() 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 24e79f7..b72f211 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 @@ -1,14 +1,11 @@ package bou.amine.apps.readerforselfossv2.android -import android.content.Context import android.content.Intent -import android.content.SharedPreferences import android.graphics.Color import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.net.Uri import android.os.Bundle -import androidx.preference.PreferenceManager import android.view.Menu import android.view.MenuItem import android.view.View @@ -79,6 +76,7 @@ import com.mikepenz.materialdrawer.util.DrawerImageLoader import com.mikepenz.materialdrawer.util.addStickyFooterItem import com.mikepenz.materialdrawer.util.updateBadge import com.mikepenz.materialdrawer.widget.AccountHeaderView +import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -132,13 +130,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var tabStarredBadge: TextBadgeItem private lateinit var api: SelfossApiImpl private lateinit var customTabActivityHelper: CustomTabActivityHelper - private lateinit var editor: SharedPreferences.Editor - private lateinit var sharedPref: SharedPreferences private lateinit var appColors: AppColors private var offset: Int = 0 private var firstVisible: Int = 0 private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener - private lateinit var settings: SharedPreferences + private var settings = Settings() private lateinit var binding: ActivityHomeBinding private var recyclerAdapter: RecyclerView.Adapter<*>? = null @@ -164,7 +160,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@HomeActivity) - config = Config(this@HomeActivity) + config = Config() super.onCreate(savedInstanceState) binding = ActivityHomeBinding.inflate(layoutInflater) @@ -196,9 +192,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper = CustomTabActivityHelper() - sharedPref = PreferenceManager.getDefaultSharedPreferences(this) - settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - api = SelfossApiImpl( // this, // this@HomeActivity, @@ -219,7 +212,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar handleSwipeRefreshLayout() - handleSharedPrefs() + handleSettings() getApiMajorVersion() @@ -358,7 +351,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar val version = api.version() if (version != null) { apiVersionMajor = version.getApiMajorVersion() - sharedPref.edit().putInt("apiVersionMajor", apiVersionMajor).apply() + settings.putInt("apiVersionMajor", apiVersionMajor) } } } @@ -369,10 +362,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar // TODO: Make this the only appcolors init appColors = AppColors(this@HomeActivity) - sharedPref = PreferenceManager.getDefaultSharedPreferences(this) - - editor = settings.edit() - handleDrawerItems() handleThemeUpdate() @@ -399,34 +388,34 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper.unbindCustomTabsService(this) } - private fun handleSharedPrefs() { - internalBrowser = sharedPref.getBoolean("prefer_internal_browser", true) - articleViewer = sharedPref.getBoolean("prefer_article_viewer", true) - shouldBeCardView = sharedPref.getBoolean("card_view_active", false) - displayUnreadCount = sharedPref.getBoolean("display_unread_count", true) - displayAllCount = sharedPref.getBoolean("display_other_count", false) - fullHeightCards = sharedPref.getBoolean("full_height_cards", false) - itemsNumber = sharedPref.getString("prefer_api_items_number", "200")!!.toInt() - userIdentifier = sharedPref.getString("unique_id", "")!! - displayAccountHeader = sharedPref.getBoolean("account_header_displaying", false) - infiniteScroll = sharedPref.getBoolean("infinite_loading", false) - searchService.itemsCaching = sharedPref.getBoolean("items_caching", false) - updateSources = sharedPref.getBoolean("update_sources", true) - markOnScroll = sharedPref.getBoolean("mark_on_scroll", false) - hiddenTags = if (sharedPref.getString("hidden_tags", "")!!.isNotEmpty()) { - sharedPref.getString("hidden_tags", "")!!.replace("\\s".toRegex(), "").split(",") + private fun handleSettings() { + internalBrowser = settings.getBoolean("prefer_internal_browser", true) + articleViewer = settings.getBoolean("prefer_article_viewer", true) + shouldBeCardView = settings.getBoolean("card_view_active", false) + displayUnreadCount = settings.getBoolean("display_unread_count", true) + displayAllCount = settings.getBoolean("display_other_count", false) + fullHeightCards = settings.getBoolean("full_height_cards", false) + itemsNumber = settings.getString("prefer_api_items_number", "200").toInt() + userIdentifier = settings.getString("unique_id", "") + displayAccountHeader = settings.getBoolean("account_header_displaying", false) + infiniteScroll = settings.getBoolean("infinite_loading", false) + searchService.itemsCaching = settings.getBoolean("items_caching", false) + updateSources = settings.getBoolean("update_sources", true) + markOnScroll = settings.getBoolean("mark_on_scroll", false) + hiddenTags = if (settings.getString("hidden_tags", "").isNotEmpty()) { + settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",") } else { emptyList() } - periodicRefresh = sharedPref.getBoolean("periodic_refresh", false) - refreshWhenChargingOnly = sharedPref.getBoolean("refresh_when_charging", false) - refreshMinutes = sharedPref.getString("periodic_refresh_minutes", "360")!!.toLong() + periodicRefresh = settings.getBoolean("periodic_refresh", false) + refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false) + refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong() if (refreshMinutes <= 15) { refreshMinutes = 15 } - apiVersionMajor = sharedPref.getInt("apiVersionMajor", 0) + apiVersionMajor = settings.getInt("apiVersionMajor", 0) } private fun handleThemeBinding() { @@ -481,8 +470,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.drawerContainer.addDrawerListener(drawerListener) displayAccountHeader = - PreferenceManager.getDefaultSharedPreferences(this) - .getBoolean("account_header_displaying", false) + settings.getBoolean("account_header_displaying", false) binding.mainDrawer.addStickyFooterItem( PrimaryDrawerItem().apply { @@ -512,7 +500,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar attachToSliderView(binding.mainDrawer) addProfiles( ProfileDrawerItem().apply { - nameText = settings.getString("url", "").toString() + nameText = settings.getString("url", "") setBackgroundResource(R.drawable.bg) iconRes = R.mipmap.ic_launcher selectionListEnabledForSingleProfile = false @@ -1211,7 +1199,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar return true } R.id.action_disconnect -> { - return Config.logoutAndRedirect(this, this@HomeActivity, editor) + return Config.logoutAndRedirect(this, this@HomeActivity) } else -> return super.onOptionsItemSelected(item) } 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 b4d7b22..519b758 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 @@ -3,7 +3,6 @@ package bou.amine.apps.readerforselfossv2.android import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.content.Intent -import android.content.SharedPreferences import android.os.Bundle import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity @@ -14,7 +13,6 @@ import android.view.MenuItem import android.view.View import android.view.inputmethod.EditorInfo import android.widget.TextView -import androidx.preference.PreferenceManager import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid @@ -22,6 +20,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailabl import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.mikepenz.aboutlibraries.LibsBuilder +import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -35,8 +34,7 @@ class LoginActivity() : AppCompatActivity(), DIAware { private var isWithLogin = false private var isWithHTTPLogin = false - private lateinit var settings: SharedPreferences - private lateinit var editor: SharedPreferences.Editor + private val settings = Settings() private lateinit var userIdentifier: String private lateinit var appColors: AppColors private lateinit var binding: ActivityLoginBinding @@ -57,12 +55,9 @@ class LoginActivity() : AppCompatActivity(), DIAware { handleBaseUrlFail() - settings = PreferenceManager.getDefaultSharedPreferences(applicationContext) - userIdentifier = settings.getString("unique_id", "")!! + userIdentifier = settings.getString("unique_id", "") - editor = settings.edit() - - if (settings.getString("url", "")!!.isNotEmpty()) { + if (settings.getString("url", "").isNotEmpty()) { goToMain() } @@ -127,12 +122,11 @@ class LoginActivity() : AppCompatActivity(), DIAware { } private fun preferenceError(t: Throwable) { - editor.remove("url") - editor.remove("login") - editor.remove("httpUserName") - editor.remove("password") - editor.remove("httpPassword") - editor.apply() + settings.remove("url") + settings.remove("login") + settings.remove("httpUserName") + settings.remove("password") + settings.remove("httpPassword") binding.urlView.error = getString(R.string.wrong_infos) binding.loginView.error = getString(R.string.wrong_infos) binding.passwordView.error = getString(R.string.wrong_infos) @@ -210,13 +204,12 @@ class LoginActivity() : AppCompatActivity(), DIAware { } else { showProgress(true) - editor.putString("url", url) - editor.putString("login", login) - editor.putString("httpUserName", httpLogin) - editor.putString("password", password) - editor.putString("httpPassword", httpPassword) - editor.putBoolean("isSelfSignedCert", isWithSelfSignedCert) - editor.apply() + settings.putString("url", url) + settings.putString("login", login) + settings.putString("httpUserName", httpLogin) + settings.putString("password", password) + settings.putString("httpPassword", httpPassword) + settings.putBoolean("isSelfSignedCert", isWithSelfSignedCert) apiDetailsService.refresh() val api = SelfossApiImpl( 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 b18a683..65bc23b 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 @@ -6,40 +6,38 @@ import android.content.Context import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build -import androidx.preference.PreferenceManager import android.widget.ImageView import androidx.multidex.MultiDexApplication -import bou.amine.apps.readerforselfossv2.android.service.AndroidApiDetailsService +import androidx.preference.PreferenceManager import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.ApiDetailsServiceImpl import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.ftinc.scoop.Scoop import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader import com.mikepenz.materialdrawer.util.DrawerImageLoader +import com.russhwolf.settings.Settings import org.kodein.di.* import java.util.UUID.randomUUID class MyApp : MultiDexApplication(), DIAware { override val di by DI.lazy { - bind() with instance(this@MyApp.applicationContext) - - bind() with singleton { AndroidApiDetailsService(instance()) } + bind() with singleton { ApiDetailsServiceImpl() } } private lateinit var config: Config + private lateinit var settings : Settings override fun onCreate() { super.onCreate() - config = Config(baseContext) + config = Config() + settings = Settings() - val prefs = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - if (prefs.getString("unique_id", "")!!.isEmpty()) { - val editor = prefs.edit() - editor.putString("unique_id", randomUUID().toString()) - editor.apply() + if (settings.getString("unique_id", "").isEmpty()) { + settings.putString("unique_id", randomUUID().toString()) } initDrawerImageLoader() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index 2b490d5..2da8e05 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -1,7 +1,5 @@ package bou.amine.apps.readerforselfossv2.android -import android.content.Context -import android.content.SharedPreferences import android.graphics.Color import android.os.Bundle import android.view.KeyEvent @@ -10,7 +8,6 @@ import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity -import androidx.preference.PreferenceManager import androidx.room.Room import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.widget.ViewPager2 @@ -22,12 +19,12 @@ 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.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings -import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.toggleStar import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.ftinc.scoop.Scoop +import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -47,7 +44,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { private lateinit var toolbarMenu: Menu private lateinit var db: AppDatabase - private lateinit var prefs: SharedPreferences private lateinit var binding: ActivityReaderBinding private var activeAlignment: Int = 1 @@ -73,7 +69,7 @@ class ReaderActivity : AppCompatActivity(), DIAware { showMenuItem(false) } - private lateinit var editor: SharedPreferences.Editor + private var settings = Settings() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -96,15 +92,9 @@ class ReaderActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - val settings = - getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - - prefs = PreferenceManager.getDefaultSharedPreferences(this) - editor = prefs.edit() - - userIdentifier = prefs.getString("unique_id", "")!! - markOnScroll = prefs.getBoolean("mark_on_scroll", false) - activeAlignment = prefs.getInt("text_align", JUSTIFY) + userIdentifier = settings.getString("unique_id", "") + markOnScroll = settings.getBoolean("mark_on_scroll", false) + activeAlignment = settings.getInt("text_align", JUSTIFY) api = SelfossApiImpl( // this, @@ -246,14 +236,12 @@ class ReaderActivity : AppCompatActivity(), DIAware { } } R.id.align_left -> { - editor.putInt("text_align", ALIGN_LEFT) - editor.apply() + settings.putInt("text_align", ALIGN_LEFT) alignmentMenu(true) refreshFragment() } R.id.align_justify -> { - editor.putInt("text_align", JUSTIFY) - editor.apply() + settings.putInt("text_align", JUSTIFY) alignmentMenu(false) refreshFragment() } 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 e2217ed..22869df 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 @@ -1,18 +1,15 @@ package bou.amine.apps.readerforselfossv2.android -import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.os.Bundle -import androidx.preference.PreferenceManager +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager -import android.widget.Toast import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings -import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.rest.SelfossModel @@ -24,7 +21,6 @@ import kotlinx.coroutines.launch import org.kodein.di.DIAware import org.kodein.di.android.closestDI import org.kodein.di.instance -import java.util.ArrayList class SourcesActivity : AppCompatActivity(), DIAware { @@ -64,10 +60,6 @@ class SourcesActivity : AppCompatActivity(), DIAware { super.onResume() val mLayoutManager = LinearLayoutManager(this) - val settings = - getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - val prefs = PreferenceManager.getDefaultSharedPreferences(this) - val api = SelfossApiImpl( // this, // this@SourcesActivity, diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt index aaff569..6357863 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt @@ -43,7 +43,7 @@ class SourcesListAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val itm = items[position] - config = Config(c) + config = Config() if (itm.getIcon(apiDetailsService.getBaseUrl()).isEmpty()) { val color = generator.getColor(itm.getTitleDecoded()) 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 0b97ffb..ad502e9 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 @@ -5,7 +5,6 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.os.Build -import androidx.preference.PreferenceManager import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat.PRIORITY_DEFAULT import androidx.core.app.NotificationCompat.PRIORITY_LOW @@ -32,6 +31,7 @@ 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 com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -48,10 +48,8 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con private val apiDetailsService : ApiDetailsService by instance() override fun doWork(): Result { - val settings = - this.context.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - val sharedPref = PreferenceManager.getDefaultSharedPreferences(this.context) - val periodicRefresh = sharedPref.getBoolean("periodic_refresh", false) + val settings = Settings() + val periodicRefresh = settings.getBoolean("periodic_refresh", false) if (periodicRefresh) { val api = SelfossApiImpl( // this.context, @@ -82,7 +80,7 @@ override fun doWork(): Result { notificationManager.notify(1, notification.build()) - val notifyNewItems = sharedPref.getBoolean("notify_new_items", false) + val notifyNewItems = settings.getBoolean("notify_new_items", false) db = Room.databaseBuilder( applicationContext, 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 66f987c..518c59f 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 @@ -1,8 +1,6 @@ package bou.amine.apps.readerforselfossv2.android.fragments -import android.content.Context import android.content.Intent -import android.content.SharedPreferences import android.content.res.ColorStateList import android.content.res.TypedArray import android.graphics.Bitmap @@ -18,7 +16,6 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.core.content.res.ResourcesCompat import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment -import androidx.preference.PreferenceManager import androidx.room.Room import bou.amine.apps.readerforselfossv2.android.ImageActivity import bou.amine.apps.readerforselfossv2.android.R @@ -51,6 +48,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.request.RequestOptions import com.github.rubensousa.floatingtoolbar.FloatingToolbar import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -76,7 +74,6 @@ class ArticleFragment : Fragment(), DIAware { private lateinit var contentImage: String private lateinit var contentTitle: String private lateinit var allImages : ArrayList - private lateinit var editor: SharedPreferences.Editor private lateinit var fab: FloatingActionButton private lateinit var appColors: AppColors private lateinit var db: AppDatabase @@ -88,7 +85,7 @@ class ArticleFragment : Fragment(), DIAware { override val di : DI by closestDI() private val apiDetailsService : ApiDetailsService by instance() - private lateinit var prefs: SharedPreferences + private var settings = Settings() private var typeface: Typeface? = null private var resId: Int = 0 @@ -104,7 +101,7 @@ class ArticleFragment : Fragment(), DIAware { override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(requireActivity()) - config = Config(requireActivity()) + config = Config() super.onCreate(savedInstanceState) @@ -137,12 +134,10 @@ class ArticleFragment : Fragment(), DIAware { contentSource = item.sourceAndDateText(DateUtils(apiDetailsService)) allImages = item.getImages() - prefs = PreferenceManager.getDefaultSharedPreferences(activity) - editor = prefs.edit() - fontSize = prefs.getString("reader_font_size", "16")!!.toInt() - staticBar = prefs.getBoolean("reader_static_bar", false) + fontSize = settings.getString("reader_font_size", "16").toInt() + staticBar = settings.getBoolean("reader_static_bar", false) - font = prefs.getString("reader_font", "")!! + font = settings.getString("reader_font", "") if (font.isNotEmpty()) { resId = requireContext().resources.getIdentifier(font, "font", requireContext().packageName) typeface = try { @@ -156,8 +151,6 @@ class ArticleFragment : Fragment(), DIAware { refreshAlignment() - val settings = requireActivity().getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - val api = SelfossApiImpl( // requireContext(), // requireActivity(), @@ -277,10 +270,7 @@ class ArticleFragment : Fragment(), DIAware { .setTitle(requireContext().getString(R.string.webview_dialog_issue_title)) .setPositiveButton(android.R.string.ok ) { _, _ -> - val sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext()) - val editor = sharedPref.edit() - editor.putBoolean("prefer_article_viewer", false) - editor.apply() + settings.putBoolean("prefer_article_viewer", false) requireActivity().finish() } .create() @@ -296,7 +286,7 @@ class ArticleFragment : Fragment(), DIAware { } private fun refreshAlignment() { - textAlignment = when (prefs.getInt("text_align", 1)) { + textAlignment = when (settings.getInt("text_align", 1)) { 1 -> "justify" 2 -> "left" else -> "justify" 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 aa708e7..f4382ce 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 @@ -17,6 +17,7 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBin import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config import com.ftinc.scoop.Scoop +import com.russhwolf.settings.Settings import java.lang.NumberFormatException private const val TITLE_TAG = "settingsActivityTitle" @@ -173,14 +174,12 @@ class SettingsActivity : AppCompatActivity(), override fun onOptionsItemSelected(item: MenuItem): Boolean { val id = item.itemId if (id == R.id.clear) { - val pref = PreferenceManager.getDefaultSharedPreferences(activity) - val editor = pref.edit() - editor.remove("color_primary") - editor.remove("color_primary_dark") - editor.remove("color_accent") - editor.remove("color_accent_dark") - editor.remove("dark_theme") - editor.apply() + val settings = Settings() + settings.remove("color_primary") + settings.remove("color_primary_dark") + settings.remove("color_accent") + settings.remove("color_accent_dark") + settings.remove("dark_theme") requireActivity().recreate() } return super.onOptionsItemSelected(item) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/themes/AppColors.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/themes/AppColors.kt index 321c400..9c10e52 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/themes/AppColors.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/themes/AppColors.kt @@ -2,8 +2,8 @@ package bou.amine.apps.readerforselfossv2.android.themes import android.app.Activity import androidx.annotation.ColorInt -import androidx.preference.PreferenceManager import bou.amine.apps.readerforselfossv2.android.R +import com.russhwolf.settings.Settings class AppColors(a: Activity) { @@ -16,30 +16,30 @@ class AppColors(a: Activity) { val isDarkTheme: Boolean init { - val sharedPref = PreferenceManager.getDefaultSharedPreferences(a) + val settings = Settings() colorPrimary = - sharedPref.getInt( + settings.getInt( "color_primary", a.resources.getColor(R.color.colorPrimary) ) colorPrimaryDark = - sharedPref.getInt( + settings.getInt( "color_primary_dark", a.resources.getColor(R.color.colorPrimaryDark) ) colorAccent = - sharedPref.getInt( + settings.getInt( "color_accent", a.resources.getColor(R.color.colorAccent) ) colorAccentDark = - sharedPref.getInt( + settings.getInt( "color_accent_dark", a.resources.getColor(R.color.colorAccentDark) ) isDarkTheme = - sharedPref.getBoolean( + settings.getBoolean( "dark_theme", false ) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/Config.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/Config.kt index 849c261..ba81e76 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/Config.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/Config.kt @@ -3,28 +3,27 @@ package bou.amine.apps.readerforselfossv2.android.utils import android.app.Activity import android.content.Context import android.content.Intent -import android.content.SharedPreferences -import androidx.preference.PreferenceManager import bou.amine.apps.readerforselfossv2.android.LoginActivity +import com.russhwolf.settings.Settings -class Config(c: Context) { +class Config { - val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(c) + val settings = Settings() val baseUrl: String - get() = settings.getString("url", "")!! + get() = settings.getString("url", "") val userLogin: String - get() = settings.getString("login", "")!! + get() = settings.getString("login", "") val userPassword: String - get() = settings.getString("password", "")!! + get() = settings.getString("password", "") val httpUserLogin: String - get() = settings.getString("httpUserName", "")!! + get() = settings.getString("httpUserName", "") val httpUserPassword: String - get() = settings.getString("httpPassword", "")!! + get() = settings.getString("httpPassword", "") companion object { const val settingsName = "paramsselfoss" @@ -47,11 +46,10 @@ class Config(c: Context) { fun logoutAndRedirect( c: Context, callingActivity: Activity, - editor: SharedPreferences.Editor, baseUrlFail: Boolean = false ): Boolean { - val settings = PreferenceManager.getDefaultSharedPreferences(c) - settings.edit().clear().commit() + val settings = Settings() + settings.clear() val intent = Intent(c, LoginActivity::class.java) if (baseUrlFail) { intent.putExtra("baseUrlFail", baseUrlFail) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/SelfSignedGlideModule.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/SelfSignedGlideModule.kt index 8449013..999a130 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/SelfSignedGlideModule.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/SelfSignedGlideModule.kt @@ -1,13 +1,13 @@ package bou.amine.apps.readerforselfossv2.android.utils.glide import android.content.Context -import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.getUnsafeHttpClient import com.bumptech.glide.Glide import com.bumptech.glide.GlideBuilder import com.bumptech.glide.Registry import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.module.GlideModule +import com.russhwolf.settings.Settings import java.io.InputStream class SelfSignedGlideModule : GlideModule { @@ -18,8 +18,8 @@ class SelfSignedGlideModule : GlideModule { override fun registerComponents(context: Context?, glide: Glide?, registry: Registry?) { if (context != null) { - val pref = context?.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - if (pref.getBoolean("isSelfSignedCert", false)) { + val settings = Settings() + if (settings.getBoolean("isSelfSignedCert", false)) { val client = getUnsafeHttpClient().build() registry?.append( diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 4eaed04..d5062d4 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -30,6 +30,12 @@ kotlin { //Dependency Injection implementation("org.kodein.di:kodein-di:7.12.0") + + //Settings + implementation("com.russhwolf:multiplatform-settings-no-arg:0.9") + + //Logging + implementation("io.github.aakira:napier:2.6.1") } } val commonTest by getting { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt similarity index 50% rename from androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt index 8e64e10..a09a8dc 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/service/AndroidApiDetailsService.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt @@ -1,19 +1,16 @@ -package bou.amine.apps.readerforselfossv2.android.service +package bou.amine.apps.readerforselfossv2.service -import android.content.Context -import android.content.SharedPreferences -import android.util.Log -import androidx.preference.PreferenceManager -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import com.russhwolf.settings.Settings +import io.github.aakira.napier.Napier -class AndroidApiDetailsService(c: Context) : ApiDetailsService { - val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(c) +class ApiDetailsServiceImpl : ApiDetailsService { + val settings: Settings = Settings() private var _apiVersion: Int = -1 private var _baseUrl: String = "" private var _userName: String = "" private var _password: String = "" override fun logApiCalls(message: String) { - Log.d("LogApiCalls", message) + Napier.d(message, tag = "LogApiCalls") } @@ -27,30 +24,30 @@ class AndroidApiDetailsService(c: Context) : ApiDetailsService { override fun getBaseUrl(): String { if (_baseUrl.isEmpty()) { - _baseUrl = settings.getString("url", "")!! + _baseUrl = settings.getString("url", "") } return _baseUrl } override fun getUserName(): String { if (_userName.isEmpty()) { - _userName = settings.getString("login", "")!! + _userName = settings.getString("login", "") } return _userName } override fun getPassword(): String { if (_password.isEmpty()) { - _password = settings.getString("password", "")!! + _password = settings.getString("password", "") } return _password } override fun refresh() { - _password = settings.getString("password", "")!! - _userName = settings.getString("login", "")!! - _baseUrl = settings.getString("url", "")!! - _baseUrl = settings.getString("url", "")!! + _password = settings.getString("password", "") + _userName = settings.getString("login", "") + _baseUrl = settings.getString("url", "") + _baseUrl = settings.getString("url", "") _apiVersion = settings.getInt("apiVersionMajor", -1) } } \ No newline at end of file From 3be942a80766b60712f6b064db0203f6529d1b41 Mon Sep 17 00:00:00 2001 From: davide Date: Wed, 20 Jul 2022 11:04:08 +0200 Subject: [PATCH 05/48] DI Repository setup --- .../repository/Repository.kt | 32 ++++++++ .../repository/RepositoryImpl.kt | 82 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt create mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt 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 new file mode 100644 index 0000000..36d795d --- /dev/null +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt @@ -0,0 +1,32 @@ +package bou.amine.apps.readerforselfossv2.repository + +import bou.amine.apps.readerforselfossv2.rest.SelfossModel + +interface Repository { + + // TODO: remove the items variables in favor of storing everything in the database + var items: List + var selectedItems: List + + // API + fun getItems(): List + fun getMoreItems(): List + fun stats(): SelfossModel.Stats + fun getTags(): List + fun getSpouts(): List + fun getSources(): List + fun markAsRead(id: String): Boolean + fun unmarkAsRead(id: String): Boolean + fun starr(id: String): Boolean + fun unstarr(id: String): Boolean + fun markAllAsRead(ids: List): Boolean + fun createSource(title: String, + url: String, + spout: String, + tags: String, + filter: String): Boolean + fun deleteSource(id: Int): Boolean + fun updateRemote(): Boolean + fun login(): Boolean + fun refreshLoginInformation(): Boolean +} \ No newline at end of file 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 new file mode 100644 index 0000000..d1b5a5e --- /dev/null +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt @@ -0,0 +1,82 @@ +package bou.amine.apps.readerforselfossv2.repository + +import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossModel +import com.russhwolf.settings.Settings + +class RepositoryImpl(api: SelfossApi) : Repository { + val settings = Settings() + + override lateinit var items: List + override lateinit var selectedItems: List + + override fun getItems(): List { + return items + } + + override fun getMoreItems(): List { + TODO("Not yet implemented") + } + + override fun stats(): SelfossModel.Stats { + TODO("Not yet implemented") + } + + override fun getTags(): List { + TODO("Not yet implemented") + } + + override fun getSpouts(): List { + TODO("Not yet implemented") + } + + override fun getSources(): List { + TODO("Not yet implemented") + } + + override fun markAsRead(id: String): Boolean { + TODO("Not yet implemented") + } + + override fun unmarkAsRead(id: String): Boolean { + TODO("Not yet implemented") + } + + override fun starr(id: String): Boolean { + TODO("Not yet implemented") + } + + override fun unstarr(id: String): Boolean { + TODO("Not yet implemented") + } + + override fun markAllAsRead(ids: List): Boolean { + TODO("Not yet implemented") + } + + override fun createSource( + title: String, + url: String, + spout: String, + tags: String, + filter: String + ): Boolean { + TODO("Not yet implemented") + } + + override fun deleteSource(id: Int): Boolean { + TODO("Not yet implemented") + } + + override fun updateRemote(): Boolean { + TODO("Not yet implemented") + } + + override fun login(): Boolean { + TODO("Not yet implemented") + } + + override fun refreshLoginInformation(): Boolean { + TODO("Not yet implemented") + } +} \ No newline at end of file From dc10cafb1bf6cd11efe245671fe023ee322774d5 Mon Sep 17 00:00:00 2001 From: davide Date: Wed, 20 Jul 2022 13:43:00 +0200 Subject: [PATCH 06/48] Use the repository for the login --- .../android/LoginActivity.kt | 40 ++++------- .../apps/readerforselfossv2/android/MyApp.kt | 8 ++- .../apps/readerforselfossv2/DI/modules.kt | 15 +++++ .../repository/Repository.kt | 5 +- .../repository/RepositoryImpl.kt | 25 ++++--- .../readerforselfossv2/rest/SelfossApiImpl.kt | 66 +++++++++++-------- 6 files changed, 89 insertions(+), 70 deletions(-) create mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt 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 519b758..e78f2e1 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 @@ -4,28 +4,27 @@ import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.content.Intent import android.os.Bundle -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity import android.text.TextUtils -import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View import android.view.inputmethod.EditorInfo import android.widget.TextView +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable -import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.repository.Repository import com.mikepenz.aboutlibraries.LibsBuilder 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.DIAware import org.kodein.di.android.closestDI +import org.kodein.di.instance class LoginActivity() : AppCompatActivity(), DIAware { @@ -40,7 +39,7 @@ class LoginActivity() : AppCompatActivity(), DIAware { private lateinit var binding: ActivityLoginBinding override val di by closestDI() - private val apiDetailsService : ApiDetailsService by instance() + private val repository : Repository by instance() override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@LoginActivity) @@ -210,30 +209,17 @@ class LoginActivity() : AppCompatActivity(), DIAware { settings.putString("password", password) settings.putString("httpPassword", httpPassword) settings.putBoolean("isSelfSignedCert", isWithSelfSignedCert) - apiDetailsService.refresh() - - val api = SelfossApiImpl( -// this, -// this@LoginActivity, -// isWithSelfSignedCert, -// -1L - apiDetailsService - ) + repository.refreshLoginInformation() if (this@LoginActivity.isNetworkAvailable(this@LoginActivity.findViewById(R.id.loginForm))) { CoroutineScope(Dispatchers.IO).launch { - try { - val result = api.login() - if (result != null && result.isSuccess) { - goToMain() - } else { - CoroutineScope(Dispatchers.Main).launch { - preferenceError(Exception("Not success")) - } + val result = repository.login() + if (result) { + goToMain() + } else { + CoroutineScope(Dispatchers.Main).launch { + preferenceError(Exception("Not success")) } - } catch (cause: Throwable) { - Log.e("1", cause.message!!) - Log.e("1", cause.stackTraceToString()) } } } 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 65bc23b..c9b2052 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 @@ -9,10 +9,11 @@ import android.os.Build import android.widget.ImageView import androidx.multidex.MultiDexApplication import androidx.preference.PreferenceManager +import bou.amine.apps.readerforselfossv2.DI.networkModule import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService -import bou.amine.apps.readerforselfossv2.service.ApiDetailsServiceImpl +import bou.amine.apps.readerforselfossv2.repository.Repository +import bou.amine.apps.readerforselfossv2.repository.RepositoryImpl import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.ftinc.scoop.Scoop @@ -25,7 +26,8 @@ import java.util.UUID.randomUUID class MyApp : MultiDexApplication(), DIAware { override val di by DI.lazy { - bind() with singleton { ApiDetailsServiceImpl() } + import(networkModule) + bind() with singleton { RepositoryImpl(instance()) } } private lateinit var config: Config diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt new file mode 100644 index 0000000..c18e33d --- /dev/null +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt @@ -0,0 +1,15 @@ +package bou.amine.apps.readerforselfossv2.DI + +import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.ApiDetailsServiceImpl +import org.kodein.di.DI +import org.kodein.di.bind +import org.kodein.di.instance +import org.kodein.di.singleton + +val networkModule by DI.Module { + bind() with singleton { ApiDetailsServiceImpl() } + bind() with singleton { SelfossApiImpl(instance()) } +} \ No newline at end of file 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 36d795d..d9ad93b 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 @@ -9,7 +9,6 @@ interface Repository { var selectedItems: List // API - fun getItems(): List fun getMoreItems(): List fun stats(): SelfossModel.Stats fun getTags(): List @@ -27,6 +26,6 @@ interface Repository { filter: String): Boolean fun deleteSource(id: Int): Boolean fun updateRemote(): Boolean - fun login(): Boolean - fun refreshLoginInformation(): Boolean + suspend fun login(): Boolean + fun refreshLoginInformation() } \ No newline at end of file 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 d1b5a5e..3432dde 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 @@ -3,17 +3,14 @@ package bou.amine.apps.readerforselfossv2.repository import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.rest.SelfossModel import com.russhwolf.settings.Settings +import io.github.aakira.napier.Napier -class RepositoryImpl(api: SelfossApi) : Repository { +class RepositoryImpl(private val api: SelfossApi) : Repository { val settings = Settings() override lateinit var items: List override lateinit var selectedItems: List - override fun getItems(): List { - return items - } - override fun getMoreItems(): List { TODO("Not yet implemented") } @@ -72,11 +69,21 @@ class RepositoryImpl(api: SelfossApi) : Repository { TODO("Not yet implemented") } - override fun login(): Boolean { - TODO("Not yet implemented") + override suspend fun login(): Boolean { + var result = false + try { + val response = api.login() + if (response != null && response.isSuccess) { + result = true + } + } catch (cause: Throwable) { + Napier.e(cause.message!!, tag = "1") + Napier.e(cause.stackTraceToString(),tag = "1") + } + return result } - override fun refreshLoginInformation(): Boolean { - TODO("Not yet implemented") + override fun refreshLoginInformation() { + api.refreshLoginInformation() } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt index d01fc94..1bfa932 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt @@ -16,6 +16,8 @@ interface SelfossApi { val client: HttpClient fun url(path: String): String + fun refreshLoginInformation() + suspend fun login(): SelfossModel.SuccessResponse? suspend fun getItems( @@ -64,43 +66,51 @@ interface SelfossApi { class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : SelfossApi { - override val client = HttpClient() { - install(ContentNegotiation) { - install(HttpCache) - json(Json { - prettyPrint = true - isLenient = true - ignoreUnknownKeys = true - }) - } - install(Logging) { - logger = object: Logger { - override fun log(message: String) { - apiDetailsService.logApiCalls(message) - } - } - level = LogLevel.ALL - } - /* TODO: Auth as basic - if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) { + override var client = createHttpClient() - install(Auth) { - basic { - credentials { - BasicAuthCredentials(username = apiDetailsService.getUserName(), password = apiDetailsService.getPassword()) - } - sendWithoutRequest { - true + private fun createHttpClient(): HttpClient { + return HttpClient { + install(ContentNegotiation) { + install(HttpCache) + json(Json { + prettyPrint = true + isLenient = true + ignoreUnknownKeys = true + }) + } + install(Logging) { + logger = object : Logger { + override fun log(message: String) { + apiDetailsService.logApiCalls(message) } } + level = LogLevel.ALL } - }*/ - expectSuccess = false + /* TODO: Auth as basic + if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) { + + install(Auth) { + basic { + credentials { + BasicAuthCredentials(username = apiDetailsService.getUserName(), password = apiDetailsService.getPassword()) + } + sendWithoutRequest { + true + } + } + } + }*/ + expectSuccess = false + } } override fun url(path: String) = "${apiDetailsService.getBaseUrl()}$path" + override fun refreshLoginInformation() { + apiDetailsService.refresh() + client = createHttpClient() + } override suspend fun login(): SelfossModel.SuccessResponse? = client.get(url("/login")) { From 9373024147cb2c5c6cbaab5c53c4e6aeb46ed4d6 Mon Sep 17 00:00:00 2001 From: davide Date: Wed, 20 Jul 2022 14:41:27 +0200 Subject: [PATCH 07/48] Strip Selfoss API from Items Adapters --- .../android/HomeActivity.kt | 2 -- .../android/adapters/ItemCardAdapter.kt | 17 +++++++----- .../android/adapters/ItemListAdapter.kt | 9 +++++-- .../android/adapters/ItemsAdapter.kt | 11 ++++---- .../repository/Repository.kt | 8 +++--- .../repository/RepositoryImpl.kt | 27 ++++++++++++------- 6 files changed, 45 insertions(+), 29 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 b72f211..427ee28 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 @@ -1012,7 +1012,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ItemCardAdapter( this, items, - api, apiDetailsService, db, customTabActivityHelper, @@ -1031,7 +1030,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ItemListAdapter( this, items, - api, apiDetailsService, db, customTabActivityHelper, 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 8fad61e..c1ca4b9 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 @@ -17,7 +17,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActiv import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable 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 @@ -28,11 +28,13 @@ import com.bumptech.glide.Glide import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DI +import org.kodein.di.android.closestDI +import org.kodein.di.instance class ItemCardAdapter( override val app: Activity, override var items: ArrayList, - override val api: SelfossApiImpl, override val apiDetailsService: ApiDetailsService, override val db: AppDatabase, private val helper: CustomTabActivityHelper, @@ -50,6 +52,9 @@ class ItemCardAdapter( private val imageMaxHeight: Int = c.resources.getDimension(R.dimen.card_image_max_height).toInt() + override val di: DI by closestDI(app) + override val repository : Repository by instance() + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding) @@ -114,15 +119,15 @@ class ItemCardAdapter( if (c.isNetworkAvailable()) { if (item.starred) { CoroutineScope(Dispatchers.IO).launch { - api.unstarr(item.id.toString()) - // TODO: save to db + repository.unstarr(item.id.toString()) + // TODO: Handle failure } item.starred = false binding.favButton.isSelected = false } else { CoroutineScope(Dispatchers.IO).launch { - api.starr(item.id.toString()) - // TODO: save to db + repository.starr(item.id.toString()) + // TODO: Handle failure } item.starred = true binding.favButton.isSelected = true 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 f440180..cacbe45 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 @@ -13,18 +13,20 @@ import bou.amine.apps.readerforselfossv2.android.utils.* import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable -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.utils.DateUtils import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.util.ColorGenerator +import org.kodein.di.DI +import org.kodein.di.android.closestDI +import org.kodein.di.instance class ItemListAdapter( override val app: Activity, override var items: ArrayList, - override val api: SelfossApiImpl, override val apiDetailsService: ApiDetailsService, override val db: AppDatabase, private val helper: CustomTabActivityHelper, @@ -39,6 +41,9 @@ class ItemListAdapter( private val generator: ColorGenerator = ColorGenerator.MATERIAL private val c: Context = app.baseContext + override val di: DI by closestDI(app) + override val repository : Repository by instance() + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index c7f8da0..168b944 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -8,7 +8,7 @@ import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.persistence.database.AppDatabase import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.Config -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 @@ -16,11 +16,12 @@ import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DIAware -abstract class ItemsAdapter : RecyclerView.Adapter() { +abstract class ItemsAdapter : RecyclerView.Adapter(), DIAware { abstract var items: ArrayList - abstract val api: SelfossApiImpl abstract val apiDetailsService: ApiDetailsService + abstract val repository: Repository abstract val db: AppDatabase abstract val userIdentifier: String abstract val app: Activity @@ -82,7 +83,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte private fun readItemAtIndex(position: Int, showSnackbar: Boolean = true) { val i = items[position] CoroutineScope(Dispatchers.IO).launch { - api.markAsRead(i.id.toString()) + repository.markAsRead(i.id.toString()) // TODO: update db } @@ -101,7 +102,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) { CoroutineScope(Dispatchers.IO).launch { - api.unmarkAsRead(items[position].id.toString()) + repository.unmarkAsRead(items[position].id.toString()) // Todo: SharedItems.unreadItem(app, api, db, items[position]) // TODO: update db 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 d9ad93b..0e23bcd 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 @@ -14,10 +14,10 @@ interface Repository { fun getTags(): List fun getSpouts(): List fun getSources(): List - fun markAsRead(id: String): Boolean - fun unmarkAsRead(id: String): Boolean - fun starr(id: String): Boolean - fun unstarr(id: String): Boolean + suspend fun markAsRead(id: String): Boolean + suspend fun unmarkAsRead(id: String): Boolean + suspend fun starr(id: String): Boolean + suspend fun unstarr(id: String): Boolean fun markAllAsRead(ids: List): Boolean fun createSource(title: String, url: String, 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 3432dde..62e49dd 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 @@ -31,20 +31,27 @@ class RepositoryImpl(private val api: SelfossApi) : Repository { TODO("Not yet implemented") } - override fun markAsRead(id: String): Boolean { - TODO("Not yet implemented") + override suspend fun markAsRead(id: String): Boolean { + // TODO: Check success, store in DB + api.markAsRead(id) + return true } - override fun unmarkAsRead(id: String): Boolean { - TODO("Not yet implemented") + override suspend fun unmarkAsRead(id: String): Boolean { + // TODO: Check success, store in DB + api.unmarkAsRead(id) + return true } + + override suspend fun starr(id: String): Boolean { + // TODO: Check success, store in DB + api.starr(id) + return true } - override fun starr(id: String): Boolean { - TODO("Not yet implemented") - } - - override fun unstarr(id: String): Boolean { - TODO("Not yet implemented") + override suspend fun unstarr(id: String): Boolean { + // TODO: Check success, store in DB + api.unstarr(id) + return true } override fun markAllAsRead(ids: List): Boolean { From 7221f11f8021c710a210f169940441aeaeb83d79 Mon Sep 17 00:00:00 2001 From: davide Date: Thu, 21 Jul 2022 15:19:22 +0200 Subject: [PATCH 08/48] 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) From 8898e85f02d751ece95b8b8ad21c34e402007b23 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 23 Jul 2022 01:28:19 +0200 Subject: [PATCH 09/48] Remove Selfoss Api from the AddSourceActivity All network calls of AddSourceActivity are now done through the repository. --- .../android/AddSourceActivity.kt | 66 +++++++------------ .../repository/Repository.kt | 12 ++-- .../repository/RepositoryImpl.kt | 24 +++++-- 3 files changed, 48 insertions(+), 54 deletions(-) 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 75d1631..0edd1c2 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 @@ -2,27 +2,17 @@ package bou.amine.apps.readerforselfossv2.android import android.content.Intent import android.os.Bundle -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.appcompat.app.AppCompatActivity import android.view.View -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.EditText -import android.widget.ProgressBar -import android.widget.Spinner -import android.widget.TextView -import android.widget.Toast +import android.widget.* +import androidx.appcompat.app.AppCompatActivity +import androidx.constraintlayout.widget.ConstraintLayout +import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid +import bou.amine.apps.readerforselfossv2.repository.Repository import com.ftinc.scoop.Scoop -import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding - -import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl -import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService -import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -34,14 +24,12 @@ import org.kodein.di.instance class AddSourceActivity : AppCompatActivity(), DIAware { private var mSpoutsValue: String? = null - private lateinit var api: SelfossApiImpl private lateinit var appColors: AppColors private lateinit var binding: ActivityAddSourceBinding - private val settings = Settings() override val di by closestDI() - private val apiDetailsService : ApiDetailsService by instance() + private val repository : Repository by instance() override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@AddSourceActivity) @@ -77,24 +65,16 @@ class AddSourceActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - try { - api = SelfossApiImpl( -// this, -// this@AddSourceActivity, -// settings.getBoolean("isSelfSignedCert", false), -// prefs.getString("api_timeout", "-1")!!.toLong() - apiDetailsService - ) - } catch (e: IllegalArgumentException) { - mustLoginToAddSource() - } - maybeGetDetailsFromIntentSharing(intent, binding.sourceUri, binding.nameInput) binding.saveBtn.setTextColor(appColors.colorAccent) binding.saveBtn.setOnClickListener { - handleSaveSource(binding.tags, binding.nameInput.text.toString(), binding.sourceUri.text.toString(), api) + handleSaveSource( + binding.tags, + binding.nameInput.text.toString(), + binding.sourceUri.text.toString() + ) } } @@ -105,13 +85,12 @@ class AddSourceActivity : AppCompatActivity(), DIAware { if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid(this@AddSourceActivity)) { mustLoginToAddSource() } else { - handleSpoutsSpinner(binding.spoutsSpinner, api, binding.progress, binding.formContainer) + handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer) } } private fun handleSpoutsSpinner( spoutsSpinner: Spinner, - api: SelfossApiImpl?, mProgress: ProgressBar, formContainer: ConstraintLayout ) { @@ -131,7 +110,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { CoroutineScope(Dispatchers.Main).launch { - var items = api!!.spouts() + val items = repository.getSpouts() if (items != null) { val itemsStrings = items.map { it.value.name } @@ -179,7 +158,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { finish() } - private fun handleSaveSource(tags: EditText, title: String, url: String, api: SelfossApiImpl) { + private fun handleSaveSource(tags: EditText, title: String, url: String) { val sourceDetailsUnavailable = title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty() @@ -190,15 +169,14 @@ class AddSourceActivity : AppCompatActivity(), DIAware { } else -> { CoroutineScope(Dispatchers.Main).launch { - val response: SelfossModel.SuccessResponse? = api.createSourceForVersion( - title, - url, - mSpoutsValue!!, - tags.text.toString(), - "", - settings.getInt("apiVersionMajor", 0) - ) - if (response != null) { + val successfullyAddedSource = repository.createSource( + title, + url, + mSpoutsValue!!, + tags.text.toString(), + "", + ) + if (successfullyAddedSource) { finish() } else { 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 b49a885..505e226 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 @@ -15,18 +15,18 @@ interface Repository { fun getMoreItems(): List fun stats(): SelfossModel.Stats fun getTags(): List - fun getSpouts(): List + suspend fun getSpouts(): Map? fun getSources(): List suspend fun markAsRead(id: String): Boolean suspend fun unmarkAsRead(id: String): Boolean suspend fun starr(id: String): Boolean suspend fun unstarr(id: String): Boolean fun markAllAsRead(ids: List): Boolean - fun createSource(title: String, - url: String, - spout: String, - tags: String, - filter: String): Boolean + suspend fun createSource(title: String, + url: String, + spout: String, + tags: String, + filter: String): Boolean fun deleteSource(id: Int): Boolean fun updateRemote(): Boolean suspend fun login(): Boolean 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 cde13c5..8456c74 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 @@ -37,8 +37,9 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet TODO("Not yet implemented") } - override fun getSpouts(): List { - TODO("Not yet implemented") + override suspend fun getSpouts(): Map? { + // TODO: Check success, store in DB + return api.spouts() } override fun getSources(): List { @@ -72,14 +73,29 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet TODO("Not yet implemented") } - override fun createSource( + override suspend fun createSource( title: String, url: String, spout: String, tags: String, filter: String ): Boolean { - TODO("Not yet implemented") + // TODO: Check connectivity + var result = false + val response = api.createSourceForVersion( + title, + url, + spout, + tags, + filter, + apiMajorVersion + ) + + if (response != null) { + result = true + } + + return result } override fun deleteSource(id: Int): Boolean { From 12e174dacd439bb8b446fdb6d73cc0ee12fd292d Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 23 Jul 2022 01:44:47 +0200 Subject: [PATCH 10/48] Remove SelfossApi from SourcesActivity All network calls to access sources go through the repository --- .../android/SourcesActivity.kt | 18 ++++---------- .../android/adapters/SourcesListAdapter.kt | 24 +++++++++++-------- .../repository/Repository.kt | 4 ++-- .../repository/RepositoryImpl.kt | 16 +++++++++---- 4 files changed, 33 insertions(+), 29 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 22869df..fe94cf3 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 @@ -11,9 +11,8 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBind import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings 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 com.ftinc.scoop.Scoop import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -28,7 +27,7 @@ class SourcesActivity : AppCompatActivity(), DIAware { private lateinit var binding: ActivitySourcesBinding override val di by closestDI() - private val apiDetailsService : ApiDetailsService by instance() + private val repository : Repository by instance() override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@SourcesActivity) @@ -60,13 +59,6 @@ class SourcesActivity : AppCompatActivity(), DIAware { super.onResume() val mLayoutManager = LinearLayoutManager(this) - val api = SelfossApiImpl( -// this, -// this@SourcesActivity, -// settings.getBoolean("isSelfSignedCert", false), -// prefs.getString("api_timeout", "-1")!!.toLong() - apiDetailsService - ) var items: ArrayList binding.recyclerView.setHasFixedSize(true) @@ -74,11 +66,11 @@ class SourcesActivity : AppCompatActivity(), DIAware { if (this@SourcesActivity.isNetworkAvailable(binding.recyclerView)) { CoroutineScope(Dispatchers.Main).launch { - val response = api.sources() + val response = repository.getSources() if (response != null) { items = response - val mAdapter = SourcesListAdapter(this@SourcesActivity, items, api, - apiDetailsService + val mAdapter = SourcesListAdapter( + this@SourcesActivity, items ) binding.recyclerView.adapter = mAdapter mAdapter.notifyDataSetChanged() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt index 6357863..30c9260 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/SourcesListAdapter.kt @@ -16,26 +16,30 @@ import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.android.utils.toTextDrawableString -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 com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.util.ColorGenerator import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.kodein.di.DI +import org.kodein.di.DIAware +import org.kodein.di.android.closestDI +import org.kodein.di.instance class SourcesListAdapter( private val app: Activity, - private val items: ArrayList, - private val api: SelfossApiImpl, - private val apiDetailsService: ApiDetailsService -) : RecyclerView.Adapter() { + private val items: ArrayList +) : RecyclerView.Adapter(), DIAware { private val c: Context = app.baseContext private val generator: ColorGenerator = ColorGenerator.MATERIAL private lateinit var config: Config private lateinit var binding: SourceListItemBinding + override val di: DI by closestDI(app) + private val repository : Repository by instance() + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { binding = SourceListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding.root) @@ -45,7 +49,7 @@ class SourcesListAdapter( val itm = items[position] config = Config() - if (itm.getIcon(apiDetailsService.getBaseUrl()).isEmpty()) { + if (itm.getIcon(repository.baseUrl).isEmpty()) { val color = generator.getColor(itm.getTitleDecoded()) val drawable = @@ -55,7 +59,7 @@ class SourcesListAdapter( .build(itm.getTitleDecoded().toTextDrawableString(c), color) binding.itemImage.setImageDrawable(drawable) } else { - c.circularBitmapDrawable(config, itm.getIcon(apiDetailsService.getBaseUrl()), binding.itemImage) + c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.itemImage) } binding.sourceTitle.text = itm.getTitleDecoded() @@ -77,8 +81,8 @@ class SourcesListAdapter( if (c.isNetworkAvailable(null)) { val (id) = items[adapterPosition] CoroutineScope(Dispatchers.IO).launch { - val action = api.deleteSource(id) - if (action != null && action.isSuccess) { + val successfullyDeletedSource = repository.deleteSource(id) + if (successfullyDeletedSource) { items.removeAt(adapterPosition) notifyItemRemoved(adapterPosition) notifyItemRangeChanged(adapterPosition, itemCount) 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 505e226..dc5fe14 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 @@ -16,7 +16,7 @@ interface Repository { fun stats(): SelfossModel.Stats fun getTags(): List suspend fun getSpouts(): Map? - fun getSources(): List + suspend fun getSources(): ArrayList? suspend fun markAsRead(id: String): Boolean suspend fun unmarkAsRead(id: String): Boolean suspend fun starr(id: String): Boolean @@ -27,7 +27,7 @@ interface Repository { spout: String, tags: String, filter: String): Boolean - fun deleteSource(id: Int): Boolean + suspend fun deleteSource(id: Int): Boolean fun updateRemote(): Boolean suspend fun login(): Boolean fun refreshLoginInformation() 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 8456c74..6f055eb 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 @@ -42,8 +42,9 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return api.spouts() } - override fun getSources(): List { - TODO("Not yet implemented") + override suspend fun getSources(): ArrayList? { + // TODO: Check success + return api.sources() } override suspend fun markAsRead(id: String): Boolean { @@ -98,8 +99,15 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return result } - override fun deleteSource(id: Int): Boolean { - TODO("Not yet implemented") + override suspend fun deleteSource(id: Int): Boolean { + // TODO: Check connectivity, store in DB + var success = false + val response = api.deleteSource(id) + if (response != null) { + success = response.isSuccess + } + + return success } override fun updateRemote(): Boolean { From b14a6427da4a06fe37756150a9b9861c91df0131 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 23 Jul 2022 17:36:34 +0200 Subject: [PATCH 11/48] Inject the Repository in the Reader Activity Removed ApiDetailsService and SelfossApi from the activity --- .../android/ReaderActivity.kt | 27 ++++++------------- .../android/adapters/ItemCardAdapter.kt | 4 +-- .../repository/Repository.kt | 4 +-- .../repository/RepositoryImpl.kt | 8 +++--- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index 2da8e05..01a7aa3 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -20,9 +20,8 @@ import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATIO import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.toggleStar -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 com.ftinc.scoop.Scoop import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope @@ -39,8 +38,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { private lateinit var userIdentifier: String private lateinit var appColors: AppColors - private lateinit var api: SelfossApiImpl - private lateinit var toolbarMenu: Menu private lateinit var db: AppDatabase @@ -51,7 +48,7 @@ class ReaderActivity : AppCompatActivity(), DIAware { private val ALIGN_LEFT = 2 override val di by closestDI() - private val apiDetailsService : ApiDetailsService by instance() + private val repository : Repository by instance() private fun showMenuItem(willAddToFavorite: Boolean) { if (willAddToFavorite) { @@ -96,14 +93,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { markOnScroll = settings.getBoolean("mark_on_scroll", false) activeAlignment = settings.getInt("text_align", JUSTIFY) - api = SelfossApiImpl( -// this, -// this@ReaderActivity, -// settings.getBoolean("isSelfSignedCert", false), -// prefs.getString("api_timeout", "-1")!!.toLong() - apiDetailsService - ) - if (allItems.isEmpty()) { finish() } @@ -125,8 +114,8 @@ class ReaderActivity : AppCompatActivity(), DIAware { private fun readItem(item: SelfossModel.Item) { if (markOnScroll) { CoroutineScope(Dispatchers.IO).launch { - api.markAsRead(item.id.toString()) - // TODO: update item in DB + repository.markAsRead(item.id.toString()) + // TODO: Handle failure } } } @@ -223,14 +212,14 @@ class ReaderActivity : AppCompatActivity(), DIAware { R.id.star -> { if (allItems[binding.pager.currentItem].starred) { CoroutineScope(Dispatchers.IO).launch { - api.unstarr(allItems[binding.pager.currentItem].id.toString()) - // TODO: update in DB + repository.unstarr(allItems[binding.pager.currentItem].id) + // TODO: Handle failure } afterUnsave() } else { CoroutineScope(Dispatchers.IO).launch { - api.starr(allItems[binding.pager.currentItem].id.toString()) - // TODO: update in DB + repository.starr(allItems[binding.pager.currentItem].id) + // TODO: Handle failure } afterSave() } 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 2428217..949acfc 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 @@ -119,14 +119,14 @@ class ItemCardAdapter( if (c.isNetworkAvailable()) { if (item.starred) { CoroutineScope(Dispatchers.IO).launch { - repository.unstarr(item.id.toString()) + repository.unstarr(item.id) // TODO: Handle failure } item.starred = false binding.favButton.isSelected = false } else { CoroutineScope(Dispatchers.IO).launch { - repository.starr(item.id.toString()) + repository.starr(item.id) // TODO: Handle failure } item.starred = true 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 dc5fe14..f43c451 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 @@ -19,8 +19,8 @@ interface Repository { suspend fun getSources(): ArrayList? suspend fun markAsRead(id: String): Boolean suspend fun unmarkAsRead(id: String): Boolean - suspend fun starr(id: String): Boolean - suspend fun unstarr(id: String): Boolean + suspend fun starr(id: Int): Boolean + suspend fun unstarr(id: Int): Boolean fun markAllAsRead(ids: List): Boolean suspend fun createSource(title: String, url: String, 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 6f055eb..fa6ef71 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 @@ -58,15 +58,15 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet api.unmarkAsRead(id) return true } - override suspend fun starr(id: String): Boolean { + override suspend fun starr(id: Int): Boolean { // TODO: Check success, store in DB - api.starr(id) + api.starr(id.toString()) return true } - override suspend fun unstarr(id: String): Boolean { + override suspend fun unstarr(id: Int): Boolean { // TODO: Check success, store in DB - api.unstarr(id) + api.unstarr(id.toString()) return true } From c0137ea5e7f18d1ae08ae07fc836c0e1cd340a5a Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 23 Jul 2022 17:40:27 +0200 Subject: [PATCH 12/48] Accept article IDs as Int in the Repository It's cleaner to accept ints and not strings, because the ID is internally stored as an Int --- .../apps/readerforselfossv2/android/ReaderActivity.kt | 2 +- .../android/adapters/ItemsAdapter.kt | 4 ++-- .../android/fragments/ArticleFragment.kt | 4 ++-- .../apps/readerforselfossv2/repository/Repository.kt | 6 +++--- .../readerforselfossv2/repository/RepositoryImpl.kt | 10 +++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index 01a7aa3..f283e3e 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -114,7 +114,7 @@ class ReaderActivity : AppCompatActivity(), DIAware { private fun readItem(item: SelfossModel.Item) { if (markOnScroll) { CoroutineScope(Dispatchers.IO).launch { - repository.markAsRead(item.id.toString()) + repository.markAsRead(item.id) // TODO: Handle failure } } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index 168b944..58cc99d 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -83,7 +83,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte private fun readItemAtIndex(position: Int, showSnackbar: Boolean = true) { val i = items[position] CoroutineScope(Dispatchers.IO).launch { - repository.markAsRead(i.id.toString()) + repository.markAsRead(i.id) // TODO: update db } @@ -102,7 +102,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) { CoroutineScope(Dispatchers.IO).launch { - repository.unmarkAsRead(items[position].id.toString()) + repository.unmarkAsRead(items[position].id) // Todo: SharedItems.unreadItem(app, api, db, items[position]) // TODO: update db 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 43a9013..06e4904 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 @@ -170,7 +170,7 @@ class ArticleFragment : Fragment(), DIAware { R.id.unread_action -> if (context != null) { if (this@ArticleFragment.item.unread) { CoroutineScope(Dispatchers.IO).launch { - repository.markAsRead(this@ArticleFragment.item.id.toString()) + repository.markAsRead(this@ArticleFragment.item.id) } this@ArticleFragment.item.unread = false Toast.makeText( @@ -180,7 +180,7 @@ class ArticleFragment : Fragment(), DIAware { ).show() } else { CoroutineScope(Dispatchers.IO).launch { - repository.unmarkAsRead(this@ArticleFragment.item.id.toString()) + repository.unmarkAsRead(this@ArticleFragment.item.id) } 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 f43c451..acfb4f6 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 @@ -17,11 +17,11 @@ interface Repository { fun getTags(): List suspend fun getSpouts(): Map? suspend fun getSources(): ArrayList? - suspend fun markAsRead(id: String): Boolean - suspend fun unmarkAsRead(id: String): Boolean + suspend fun markAsRead(id: Int): Boolean + suspend fun unmarkAsRead(id: Int): Boolean suspend fun starr(id: Int): Boolean suspend fun unstarr(id: Int): Boolean - fun markAllAsRead(ids: List): Boolean + fun markAllAsRead(ids: List): Boolean suspend fun createSource(title: String, url: String, spout: String, 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 fa6ef71..52fcfcd 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 @@ -47,15 +47,15 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return api.sources() } - override suspend fun markAsRead(id: String): Boolean { + override suspend fun markAsRead(id: Int): Boolean { // TODO: Check success, store in DB - api.markAsRead(id) + api.markAsRead(id.toString()) return true } - override suspend fun unmarkAsRead(id: String): Boolean { + override suspend fun unmarkAsRead(id: Int): Boolean { // TODO: Check success, store in DB - api.unmarkAsRead(id) + api.unmarkAsRead(id.toString()) return true } override suspend fun starr(id: Int): Boolean { @@ -70,7 +70,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return true } - override fun markAllAsRead(ids: List): Boolean { + override fun markAllAsRead(ids: List): Boolean { TODO("Not yet implemented") } From e3d35bd65332011b097fc95ffc4f8d929168b940 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 23 Jul 2022 19:09:43 +0200 Subject: [PATCH 13/48] Implement initial Items storage in Repository --- .../repository/Repository.kt | 7 ++- .../repository/RepositoryImpl.kt | 63 +++++++++++++++++-- 2 files changed, 63 insertions(+), 7 deletions(-) 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 acfb4f6..51abb07 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 @@ -5,14 +5,15 @@ import bou.amine.apps.readerforselfossv2.rest.SelfossModel interface Repository { // TODO: remove the items variables in favor of storing everything in the database - var items: List - var selectedItems: List + var items: ArrayList + var selectedItems: ArrayList var baseUrl: String // API var apiMajorVersion: Int - fun getMoreItems(): List + suspend fun getNewerItems(): ArrayList + suspend fun getOlderItems(): ArrayList fun stats(): SelfossModel.Stats fun getTags(): List suspend fun getSpouts(): Map? 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 52fcfcd..a4d9030 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 @@ -3,6 +3,7 @@ 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 bou.amine.apps.readerforselfossv2.utils.DateUtils import com.russhwolf.settings.Settings import io.github.aakira.napier.Napier import kotlinx.coroutines.CoroutineScope @@ -12,10 +13,22 @@ import kotlinx.coroutines.launch 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 items = ArrayList() + get() { return ArrayList(field) } + set(value) { field = ArrayList(value) } + + override var selectedItems = ArrayList() + get() { return ArrayList(field) } + set(value) { field = ArrayList(value) } + override var baseUrl = apiDetails.getBaseUrl() + // TODO: Validate the string in the setter + private var selectedType = "new" + private var selectedTag: SelfossModel.Tag? = null + private var selectedSource: SelfossModel.Source? = null + private var search: String? = null + override var apiMajorVersion = 0 init { @@ -25,8 +38,50 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } } - override fun getMoreItems(): List { - TODO("Not yet implemented") + override suspend fun getNewerItems(): ArrayList { + // TODO: Check connectivity + val fetchedItems = api.getItems(selectedType, + settings.getInt("prefer_api_items_number", 200), + offset = 0, + selectedTag?.tag, + selectedSource?.id?.toLong(), + search) + + if (fetchedItems != null) { + storeItems(fetchedItems) + } + return selectedItems + } + + override suspend fun getOlderItems(): ArrayList { + // TODO: Check connectivity + val offset = selectedItems.size + val fetchedItems = api.getItems(selectedType, + settings.getInt("prefer_api_items_number", 200), + offset, + selectedTag?.tag, + selectedSource?.id?.toLong(), + search) + + if (fetchedItems != null) { + storeItems(fetchedItems) + } + return selectedItems + } + + private fun storeItems(fetchedItems: List) { + // TODO: Store in DB + val fetchedIDS = fetchedItems.map { it.id } + val tmpItems = ArrayList(items) + tmpItems.removeAll{ it.id in fetchedIDS } + tmpItems.addAll(fetchedItems) + sortItems(tmpItems) + items = tmpItems + } + + private fun sortItems(items: ArrayList) { + val dateUtils = DateUtils(apiMajorVersion) + items.sortBy { dateUtils.parseDate(it.datetime) } } override fun stats(): SelfossModel.Stats { From e37eae8d167094856826c1132c4869130e3df1b0 Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 03:32:58 +0200 Subject: [PATCH 14/48] Fetch items through the repository Items are stored and filtered locally in the repository --- .../android/HomeActivity.kt | 25 ++++++++--------- .../repository/Repository.kt | 2 ++ .../repository/RepositoryImpl.kt | 27 ++++++++++++++----- 3 files changed, 36 insertions(+), 18 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 e110dab..218a67d 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 @@ -937,6 +937,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ) { fun doGetAccordingToTab() { when (elementsShown) { + // TODO: These three functions are not required, one is enough UNREAD_SHOWN -> getUnRead(appendResults) READ_SHOWN -> getRead(appendResults) FAV_SHOWN -> getStarred(appendResults) @@ -957,11 +958,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getUnRead(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - val apiItems = service.getUnreadItems(itemsNumber, offset, applicationContext.isNetworkAvailable()) - if (appendResults) { - apiItems?.let { items.addAll(it) } + repository.selectedType = "unread" + items = if (appendResults) { + repository.getNewerItems() } else { - items = apiItems.orEmpty() as ArrayList + repository.getOlderItems() } binding.swipeRefreshLayout.isRefreshing = false handleListResult() @@ -971,11 +972,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getRead(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - val apiItems = service.getReadItems(itemsNumber, offset, applicationContext.isNetworkAvailable()) - if (appendResults) { - apiItems?.let { items.addAll(it) } + repository.selectedType = "all" + items = if (appendResults) { + repository.getNewerItems() } else { - items = apiItems.orEmpty() as ArrayList + repository.getOlderItems() } binding.swipeRefreshLayout.isRefreshing = false handleListResult() @@ -985,11 +986,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getStarred(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - val apiItems = service.getStarredItems(itemsNumber, offset, applicationContext.isNetworkAvailable()) - if (appendResults) { - apiItems?.let { items.addAll(it) } + repository.selectedType = "starred" + items = if (appendResults) { + repository.getNewerItems() } else { - items = apiItems.orEmpty() as ArrayList + repository.getOlderItems() } binding.swipeRefreshLayout.isRefreshing = false handleListResult() 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 51abb07..3bc6c95 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 @@ -9,6 +9,8 @@ interface Repository { var selectedItems: ArrayList var baseUrl: String + var selectedType: String + // API var apiMajorVersion: Int 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 a4d9030..f4db7f8 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 @@ -24,7 +24,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override var baseUrl = apiDetails.getBaseUrl() // TODO: Validate the string in the setter - private var selectedType = "new" + override var selectedType = "read" private var selectedTag: SelfossModel.Tag? = null private var selectedSource: SelfossModel.Source? = null private var search: String? = null @@ -41,7 +41,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun getNewerItems(): ArrayList { // TODO: Check connectivity val fetchedItems = api.getItems(selectedType, - settings.getInt("prefer_api_items_number", 200), + settings.getString("prefer_api_items_number", "200").toInt(), offset = 0, selectedTag?.tag, selectedSource?.id?.toLong(), @@ -50,14 +50,14 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet if (fetchedItems != null) { storeItems(fetchedItems) } - return selectedItems + return filterSelectedItems(items) } override suspend fun getOlderItems(): ArrayList { // TODO: Check connectivity val offset = selectedItems.size val fetchedItems = api.getItems(selectedType, - settings.getInt("prefer_api_items_number", 200), + settings.getString("prefer_api_items_number", "200").toInt(), offset, selectedTag?.tag, selectedSource?.id?.toLong(), @@ -66,7 +66,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet if (fetchedItems != null) { storeItems(fetchedItems) } - return selectedItems + return filterSelectedItems(items) } private fun storeItems(fetchedItems: List) { @@ -81,7 +81,22 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet private fun sortItems(items: ArrayList) { val dateUtils = DateUtils(apiMajorVersion) - items.sortBy { dateUtils.parseDate(it.datetime) } + items.sortByDescending { dateUtils.parseDate(it.datetime) } + } + + private fun filterSelectedItems(items: ArrayList): ArrayList { + val tmpItems = ArrayList(items) + if (selectedType == "unread") { + tmpItems.removeAll { !it.unread } + } else if (selectedType == "starred") { + tmpItems.removeAll { !it.starred } + } + + if (selectedTag != null) { + tmpItems.removeAll { !it.tags.contains(selectedTag!!.tag) } + } + + return tmpItems } override fun stats(): SelfossModel.Stats { From dbbc191704d1244e97cb8a86deea92f58d48dc2b Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 03:38:46 +0200 Subject: [PATCH 15/48] Remove unused items variables --- .../amine/apps/readerforselfossv2/android/HomeActivity.kt | 8 -------- .../apps/readerforselfossv2/repository/Repository.kt | 1 - .../apps/readerforselfossv2/repository/RepositoryImpl.kt | 6 +----- 3 files changed, 1 insertion(+), 14 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 218a67d..af91908 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 @@ -103,7 +103,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private val FAV_SHOWN = 3 private var items: ArrayList = ArrayList() - private var allItems: ArrayList = ArrayList() private var internalBrowser = false private var articleViewer = false @@ -206,8 +205,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar searchService = SearchService(DateUtils(repository.apiMajorVersion)) dbService = AndroidDeviceDatabaseService(dataBase, searchService) service = SelfossService(api, dbService, searchService) - items = ArrayList() - allItems = ArrayList() handleBottomBar() handleDrawer() @@ -229,7 +226,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ) binding.swipeRefreshLayout.setOnRefreshListener { offlineShortcut = false - allItems = ArrayList() lastFetchDone = false handleDrawerItems() CoroutineScope(Dispatchers.Main).launch { @@ -549,7 +545,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar textColor = ColorHolder.fromColor(Color.WHITE) color = ColorHolder.fromColor(appColors.colorAccent) } onDrawerItemClickListener = { _,_,_ -> - allItems = ArrayList() searchService.tagFilter = it.tag searchService.sourceFilter = null searchService.sourceIDFilter = null @@ -602,7 +597,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar textColor = ColorHolder.fromColor(Color.WHITE) color = ColorHolder.fromColor(appColors.colorAccent) } onDrawerItemClickListener = { _,_,_ -> - allItems = ArrayList() searchService.tagFilter = it.tag searchService.sourceFilter = null searchService.sourceIDFilter = null @@ -638,7 +632,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar identifier = source.id.toLong() iconUrl = source.getIcon(apiDetailsService.getBaseUrl()) onDrawerItemClickListener = { _,_,_ -> - allItems = ArrayList() searchService.sourceIDFilter = source.id.toLong() searchService.sourceFilter = source.title searchService.tagFilter = null @@ -661,7 +654,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar identifier = DRAWER_ID_FILTERS badgeRes = R.string.drawer_action_clear onDrawerItemClickListener = { _,_,_ -> - allItems = ArrayList() searchService.sourceFilter = null searchService.sourceIDFilter = null searchService.tagFilter = null 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 3bc6c95..a1cb199 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 @@ -6,7 +6,6 @@ interface Repository { // TODO: remove the items variables in favor of storing everything in the database var items: ArrayList - var selectedItems: ArrayList var baseUrl: String var selectedType: String 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 f4db7f8..ed7bbbd 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 @@ -17,10 +17,6 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet get() { return ArrayList(field) } set(value) { field = ArrayList(value) } - override var selectedItems = ArrayList() - get() { return ArrayList(field) } - set(value) { field = ArrayList(value) } - override var baseUrl = apiDetails.getBaseUrl() // TODO: Validate the string in the setter @@ -55,7 +51,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun getOlderItems(): ArrayList { // TODO: Check connectivity - val offset = selectedItems.size + val offset = filterSelectedItems(items).size val fetchedItems = api.getItems(selectedType, settings.getString("prefer_api_items_number", "200").toInt(), offset, From da088ec89e9223b919c1adab3796962870dde5ba Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 03:45:54 +0200 Subject: [PATCH 16/48] Use the repository to fetch the api Version --- .../apps/readerforselfossv2/android/HomeActivity.kt | 12 +----------- 1 file changed, 1 insertion(+), 11 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 af91908..485d834 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 @@ -213,7 +213,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar handleSettings() - getApiMajorVersion() + apiVersionMajor = repository.apiMajorVersion getElementsAccordingToTab() } @@ -344,16 +344,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } } - private fun getApiMajorVersion() { - CoroutineScope(Dispatchers.IO).launch { - val version = api.version() - if (version != null) { - apiVersionMajor = version.getApiMajorVersion() - settings.putInt("apiVersionMajor", apiVersionMajor) - } - } - } - override fun onResume() { super.onResume() From 08598546101b2d8edbb77ac8306735fe2615e8b1 Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 14:01:50 +0200 Subject: [PATCH 17/48] Setter for a valid selectedType --- .../readerforselfossv2/repository/RepositoryImpl.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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 ed7bbbd..0cbe107 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 @@ -19,8 +19,17 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override var baseUrl = apiDetails.getBaseUrl() - // TODO: Validate the string in the setter - override var selectedType = "read" + override var selectedType = "unread" + set(value) { + field = when (value) { + "all" -> "all" + "unread" -> "unread" + "read" -> "read" + "starred" -> "starred" + else -> "all" + } + } + private var selectedTag: SelfossModel.Tag? = null private var selectedSource: SelfossModel.Source? = null private var search: String? = null From 77fada1b026e89f74c8fd1b0cf8e17b7a661dd9e Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 14:02:48 +0200 Subject: [PATCH 18/48] Home Activity, use the Repository --- .../android/HomeActivity.kt | 24 +++++++++---------- .../repository/Repository.kt | 2 +- .../repository/RepositoryImpl.kt | 10 ++++++-- 3 files changed, 20 insertions(+), 16 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 485d834..84e1360 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 @@ -747,7 +747,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar fun sourcesApiCall() { if (this@HomeActivity.isNetworkAvailable(null, offlineShortcut) && updateSources) { CoroutineScope(Dispatchers.Main).launch { - val response = api.sources() + val response = repository.getSources() if (response != null) { sources = response val apiDrawerData = DrawerData(tags, sources) @@ -766,10 +766,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar if (this@HomeActivity.isNetworkAvailable(null, offlineShortcut) && updateSources) { CoroutineScope(Dispatchers.IO).launch { - val response = api.tags() - if (response != null) { - tags = response - } + val tags = repository.getTags() sourcesApiCall() } } @@ -1125,9 +1122,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar if (this@HomeActivity.isNetworkAvailable(null, offlineShortcut)) { needsConfirmation(R.string.menu_home_refresh, R.string.refresh_dialog_message) { Toast.makeText(this, R.string.refresh_in_progress, Toast.LENGTH_SHORT).show() + // TODO: Use Dispatchers.IO CoroutineScope(Dispatchers.Main).launch { - val status = api.update() - if (status != null && status.isSuccess) { + val updatedRemote = repository.updateRemote() + if (updatedRemote) { Toast.makeText( this@HomeActivity, R.string.refresh_success_response, Toast.LENGTH_LONG @@ -1219,8 +1217,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } private fun handleOfflineActions() { - fun doAndReportOnFail(call: SelfossModel.SuccessResponse?, action: ActionEntity) { - if (call != null && call.isSuccess) { + fun doAndReportOnFail(success: Boolean, action: ActionEntity) { + if (success) { thread { db.actionsDao().delete(action) } @@ -1233,10 +1231,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar actions.forEach { action -> when { - action.read -> doAndReportOnFail(api.markAsRead(action.articleId), action) - action.unread -> doAndReportOnFail(api.unmarkAsRead(action.articleId), action) - action.starred -> doAndReportOnFail(api.starr(action.articleId), action) - action.unstarred -> doAndReportOnFail(api.unstarr(action.articleId), action) + action.read -> doAndReportOnFail(repository.markAsRead(action.articleId.toInt()), action) + action.unread -> doAndReportOnFail(repository.markAsRead(action.articleId.toInt()), action) + action.starred -> doAndReportOnFail(repository.markAsRead(action.articleId.toInt()), action) + action.unstarred -> doAndReportOnFail(repository.markAsRead(action.articleId.toInt()), action) } } } 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 a1cb199..ad780c8 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 @@ -30,7 +30,7 @@ interface Repository { tags: String, filter: String): Boolean suspend fun deleteSource(id: Int): Boolean - fun updateRemote(): Boolean + suspend fun updateRemote(): Boolean suspend fun login(): Boolean fun refreshLoginInformation() } \ No newline at end of file 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 0cbe107..e5f38f1 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 @@ -185,8 +185,14 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override fun updateRemote(): Boolean { - TODO("Not yet implemented") + override suspend fun updateRemote(): Boolean { + // TODO: Handle connectivity issues + val response = api.update() + return if (response != null) { + response.isSuccess + } else { + false + } } override suspend fun login(): Boolean { From 11eac7b1418b72d00b24aed949017a3c94282e61 Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 14:14:04 +0200 Subject: [PATCH 19/48] Get badges through the repository --- .../android/HomeActivity.kt | 12 ++++++----- .../repository/Repository.kt | 5 ++++- .../repository/RepositoryImpl.kt | 21 +++++++++++++++++-- 3 files changed, 30 insertions(+), 8 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 84e1360..d0963ae 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 @@ -1044,8 +1044,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun reloadBadges() { if (displayUnreadCount || displayAllCount) { CoroutineScope(Dispatchers.Main).launch { - service.reloadBadges(applicationContext.isNetworkAvailable()) - reloadBadgeContent() + if (applicationContext.isNetworkAvailable()) { + repository.reloadBadges() + reloadBadgeContent() + } } } } @@ -1053,15 +1055,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun reloadBadgeContent() { if (displayUnreadCount) { tabNewBadge - .setText(searchService.badgeUnread.toString()) + .setText(repository.badgeUnread.toString()) .maybeShow() } if (displayAllCount) { tabArchiveBadge - .setText(searchService.badgeAll.toString()) + .setText(repository.badgeAll.toString()) .maybeShow() tabStarredBadge - .setText(searchService.badgeStarred.toString()) + .setText(repository.badgeStarred.toString()) .maybeShow() } } 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 ad780c8..a1e6ec2 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 @@ -12,10 +12,13 @@ interface Repository { // API var apiMajorVersion: Int + var badgeUnread: Int + var badgeAll: Int + var badgeStarred: Int suspend fun getNewerItems(): ArrayList suspend fun getOlderItems(): ArrayList - fun stats(): SelfossModel.Stats + suspend fun reloadBadges(): Boolean fun getTags(): List suspend fun getSpouts(): Map? suspend fun getSources(): ArrayList? 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 e5f38f1..3714a56 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 @@ -35,11 +35,15 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet private var search: String? = null override var apiMajorVersion = 0 + override var badgeUnread = 0 + override var badgeAll = 0 + override var badgeStarred = 0 init { // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found CoroutineScope(Dispatchers.Main).launch { updateApiVersion() + reloadBadges() } } @@ -104,8 +108,17 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return tmpItems } - override fun stats(): SelfossModel.Stats { - TODO("Not yet implemented") + override suspend fun reloadBadges(): Boolean { + // TODO: Check connectivity, calculate from DB + var success = false + val response = api.stats() + if (response != null) { + badgeUnread = response.unread + badgeAll = response.total + badgeStarred = response.starred + success = true + } + return success } override fun getTags(): List { @@ -125,23 +138,27 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun markAsRead(id: Int): Boolean { // TODO: Check success, store in DB api.markAsRead(id.toString()) + badgeUnread -= 1 return true } override suspend fun unmarkAsRead(id: Int): Boolean { // TODO: Check success, store in DB api.unmarkAsRead(id.toString()) + badgeUnread += 1 return true } override suspend fun starr(id: Int): Boolean { // TODO: Check success, store in DB api.starr(id.toString()) + badgeStarred += 1 return true } override suspend fun unstarr(id: Int): Boolean { // TODO: Check success, store in DB api.unstarr(id.toString()) + badgeStarred -= 1 return true } From 924f4da1ec71cba27d2e247e4e767d248ce10fc7 Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 24 Jul 2022 14:32:40 +0200 Subject: [PATCH 20/48] Remove Selfoss Service from Home Activity Initial implementation of the missing functions in the repository --- .../android/HomeActivity.kt | 9 +---- .../repository/Repository.kt | 4 +- .../repository/RepositoryImpl.kt | 39 +++++++++++++++---- 3 files changed, 36 insertions(+), 16 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 d0963ae..89f0558 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 @@ -34,7 +34,6 @@ import bou.amine.apps.readerforselfossv2.android.persistence.AndroidDeviceDataba 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.ActionEntity -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 @@ -49,13 +48,11 @@ import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailabl 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 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.longHash import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationItem @@ -92,7 +89,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var dataBase: AndroidDeviceDatabase private lateinit var dbService: AndroidDeviceDatabaseService private lateinit var searchService: SearchService - private lateinit var service: SelfossService private val MENU_PREFERENCES = 12302 private val DRAWER_ID_TAGS = 100101L private val DRAWER_ID_HIDDEN_TAGS = 101100L @@ -204,7 +200,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar dataBase = AndroidDeviceDatabase(applicationContext) searchService = SearchService(DateUtils(repository.apiMajorVersion)) dbService = AndroidDeviceDatabaseService(dataBase, searchService) - service = SelfossService(api, dbService, searchService) handleBottomBar() handleDrawer() @@ -1154,7 +1149,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar if (this@HomeActivity.isNetworkAvailable(null, offlineShortcut)) { CoroutineScope(Dispatchers.Main).launch { - val success = service.readAll(items.map { it.id.toString() }, applicationContext.isNetworkAvailable()) + val success = repository.markAllAsRead(items.map { it.id }) if (success) { Toast.makeText( this@HomeActivity, 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 a1e6ec2..40d22e2 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 @@ -19,14 +19,14 @@ interface Repository { suspend fun getNewerItems(): ArrayList suspend fun getOlderItems(): ArrayList suspend fun reloadBadges(): Boolean - fun getTags(): List + suspend fun getTags(): List? suspend fun getSpouts(): Map? suspend fun getSources(): ArrayList? suspend fun markAsRead(id: Int): Boolean suspend fun unmarkAsRead(id: Int): Boolean suspend fun starr(id: Int): Boolean suspend fun unstarr(id: Int): Boolean - fun markAllAsRead(ids: List): Boolean + suspend fun markAllAsRead(ids: List): Boolean suspend fun createSource(title: String, url: String, spout: String, 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 3714a56..fb04f4d 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 @@ -36,8 +36,11 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override var apiMajorVersion = 0 override var badgeUnread = 0 + set(value) {field = if (value < 0) { 0 } else { value } } override var badgeAll = 0 + set(value) {field = if (value < 0) { 0 } else { value } } override var badgeStarred = 0 + set(value) {field = if (value < 0) { 0 } else { value } } init { // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found @@ -121,8 +124,9 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override fun getTags(): List { - TODO("Not yet implemented") + override suspend fun getTags(): List? { + // TODO: Check success, store in DB + return api.tags() } override suspend fun getSpouts(): Map? { @@ -144,9 +148,13 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun unmarkAsRead(id: Int): Boolean { // TODO: Check success, store in DB - api.unmarkAsRead(id.toString()) - badgeUnread += 1 - return true } + val success = api.unmarkAsRead(id.toString())?.isSuccess == true + + if (success) { + markAsReadLocally(id) + } + return success + } override suspend fun starr(id: Int): Boolean { // TODO: Check success, store in DB @@ -162,8 +170,25 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return true } - override fun markAllAsRead(ids: List): Boolean { - TODO("Not yet implemented") + override suspend fun markAllAsRead(ids: List): Boolean { + // TODO: Check Internet connectivity, store in DB + + val success = api.markAllAsRead(ids.map { it.toString() })?.isSuccess == true + + if (success) { + for (id in ids) { + markAsReadLocally(id) + } + } + return success + } + + private fun markAsReadLocally(id: Int) { + // TODO: Mark also in the database + if (items.first {it.id == id}.unread) { + items.first {it.id == id}.unread = false + badgeUnread -= 1 + } } override suspend fun createSource( From 73e6742ceef8913c29edcd0e66fa6923032ff542 Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 25 Jul 2022 14:08:57 +0200 Subject: [PATCH 21/48] Register edits locally through the repository --- .../repository/RepositoryImpl.kt | 65 ++++++++++++++----- 1 file changed, 49 insertions(+), 16 deletions(-) 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 fb04f4d..874a289 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 @@ -140,15 +140,8 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } override suspend fun markAsRead(id: Int): Boolean { - // TODO: Check success, store in DB - api.markAsRead(id.toString()) - badgeUnread -= 1 - return true - } - - override suspend fun unmarkAsRead(id: Int): Boolean { - // TODO: Check success, store in DB - val success = api.unmarkAsRead(id.toString())?.isSuccess == true + // TODO: Check internet connection + val success = api.markAsRead(id.toString())?.isSuccess == true if (success) { markAsReadLocally(id) @@ -156,18 +149,34 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } + override suspend fun unmarkAsRead(id: Int): Boolean { + // TODO: Check internet connection + val success = api.unmarkAsRead(id.toString())?.isSuccess == true + + if (success) { + unmarkAsReadLocally(id) + } + return success + } + override suspend fun starr(id: Int): Boolean { // TODO: Check success, store in DB - api.starr(id.toString()) - badgeStarred += 1 - return true + val success = api.starr(id.toString())?.isSuccess == true + + if (success) { + starrLocally(id) + } + return success } override suspend fun unstarr(id: Int): Boolean { - // TODO: Check success, store in DB - api.unstarr(id.toString()) - badgeStarred -= 1 - return true + // TODO: Check internet connection + val success = api.unstarr(id.toString())?.isSuccess == true + + if (success) { + unstarrLocally(id) + } + return success } override suspend fun markAllAsRead(ids: List): Boolean { @@ -191,6 +200,30 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } } + private fun unmarkAsReadLocally(id: Int) { + // TODO: Mark also in the database + if (!items.first {it.id == id}.unread) { + items.first {it.id == id}.unread = true + badgeUnread += 1 + } + } + + private fun starrLocally(id: Int) { + // TODO: Mark also in the database + if (!items.first {it.id == id}.starred) { + items.first {it.id == id}.starred = true + badgeStarred += 1 + } + } + + private fun unstarrLocally(id: Int) { + // TODO: Mark also in the database + if (items.first {it.id == id}.starred) { + items.first {it.id == id}.starred = false + badgeStarred -= 1 + } + } + override suspend fun createSource( title: String, url: String, From da4bdd2355bd8623f5bc2434b10d4f466b09fda9 Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 25 Jul 2022 14:10:50 +0200 Subject: [PATCH 22/48] Simplify boolean returns --- .../readerforselfossv2/repository/RepositoryImpl.kt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) 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 874a289..34cdbcc 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 @@ -232,7 +232,6 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet filter: String ): Boolean { // TODO: Check connectivity - var result = false val response = api.createSourceForVersion( title, url, @@ -242,11 +241,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet apiMajorVersion ) - if (response != null) { - result = true - } - - return result + return response != null } override suspend fun deleteSource(id: Int): Boolean { @@ -263,11 +258,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun updateRemote(): Boolean { // TODO: Handle connectivity issues val response = api.update() - return if (response != null) { - response.isSuccess - } else { - false - } + return response?.isSuccess ?: false } override suspend fun login(): Boolean { From b14b34441b93aff950bfaeae64ae48ed7ceeb0ff Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 25 Jul 2022 15:20:36 +0200 Subject: [PATCH 23/48] Update api login information with user input --- .../apps/readerforselfossv2/android/LoginActivity.kt | 8 +------- .../apps/readerforselfossv2/repository/Repository.kt | 4 +++- .../readerforselfossv2/repository/RepositoryImpl.kt | 12 ++++++++++-- .../service/ApiDetailsServiceImpl.kt | 1 - 4 files changed, 14 insertions(+), 11 deletions(-) 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 e78f2e1..62e11ae 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 @@ -203,13 +203,7 @@ class LoginActivity() : AppCompatActivity(), DIAware { } else { showProgress(true) - settings.putString("url", url) - settings.putString("login", login) - settings.putString("httpUserName", httpLogin) - settings.putString("password", password) - settings.putString("httpPassword", httpPassword) - settings.putBoolean("isSelfSignedCert", isWithSelfSignedCert) - repository.refreshLoginInformation() + repository.refreshLoginInformation(url, login, password, httpLogin, httpPassword, isWithSelfSignedCert) if (this@LoginActivity.isNetworkAvailable(this@LoginActivity.findViewById(R.id.loginForm))) { CoroutineScope(Dispatchers.IO).launch { 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 40d22e2..2df1995 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 @@ -35,5 +35,7 @@ interface Repository { suspend fun deleteSource(id: Int): Boolean suspend fun updateRemote(): Boolean suspend fun login(): Boolean - fun refreshLoginInformation() + fun refreshLoginInformation(url: String, login: String, password: String, + httpLogin: String, httpPassword: String, + isSelfSignedCert: Boolean) } \ No newline at end of file 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 34cdbcc..de0375c 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 @@ -275,9 +275,17 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return result } - override fun refreshLoginInformation() { + override fun refreshLoginInformation(url: String, login: String, password: String, + httpLogin: String, httpPassword: String, + isSelfSignedCert: Boolean) { + settings.putString("url", url) + settings.putString("login", login) + settings.putString("httpUserName", httpLogin) + settings.putString("password", password) + settings.putString("httpPassword", httpPassword) + settings.putBoolean("isSelfSignedCert", isSelfSignedCert) + baseUrl = url api.refreshLoginInformation() - baseUrl = apiDetails.getBaseUrl() } private suspend fun updateApiVersion() { diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt index a09a8dc..6256094 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt @@ -47,7 +47,6 @@ class ApiDetailsServiceImpl : ApiDetailsService { _password = settings.getString("password", "") _userName = settings.getString("login", "") _baseUrl = settings.getString("url", "") - _baseUrl = settings.getString("url", "") _apiVersion = settings.getInt("apiVersionMajor", -1) } } \ No newline at end of file From 442e4bf87674d36956fef618173d502eddc30879 Mon Sep 17 00:00:00 2001 From: davide Date: Wed, 27 Jul 2022 19:15:04 +0200 Subject: [PATCH 24/48] Do not store articles if connectivity is available. --- .../readerforselfossv2/repository/RepositoryImpl.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 de0375c..e933ff6 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 @@ -60,14 +60,14 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet search) if (fetchedItems != null) { - storeItems(fetchedItems) + items = ArrayList(fetchedItems) } - return filterSelectedItems(items) + return items } override suspend fun getOlderItems(): ArrayList { // TODO: Check connectivity - val offset = filterSelectedItems(items).size + val offset = items.size val fetchedItems = api.getItems(selectedType, settings.getString("prefer_api_items_number", "200").toInt(), offset, @@ -76,9 +76,9 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet search) if (fetchedItems != null) { - storeItems(fetchedItems) + items = ArrayList(fetchedItems) } - return filterSelectedItems(items) + return items } private fun storeItems(fetchedItems: List) { From 554b8df9d0898501e942fa1b0277104763555681 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 17:11:07 +0200 Subject: [PATCH 25/48] Remove direct api access from the home activity --- .../readerforselfossv2/android/HomeActivity.kt | 16 +--------------- .../android/adapters/ItemCardAdapter.kt | 10 ++++------ .../android/adapters/ItemListAdapter.kt | 10 ++++------ .../android/adapters/ItemsAdapter.kt | 2 -- 4 files changed, 9 insertions(+), 29 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 89f0558..7aa54df 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,9 +48,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailabl 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.rest.SelfossApiImpl 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.utils.DateUtils import bou.amine.apps.readerforselfossv2.utils.longHash @@ -124,7 +122,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var tabNewBadge: TextBadgeItem private lateinit var tabArchiveBadge: TextBadgeItem private lateinit var tabStarredBadge: TextBadgeItem - private lateinit var api: SelfossApiImpl private lateinit var customTabActivityHelper: CustomTabActivityHelper private lateinit var appColors: AppColors private var offset: Int = 0 @@ -145,7 +142,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var config: Config 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?) @@ -189,14 +185,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper = CustomTabActivityHelper() - api = SelfossApiImpl( -// this, -// this@HomeActivity, -// settings.getBoolean("isSelfSignedCert", false), -// sharedPref.getString("api_timeout", "-1")!!.toLong() - apiDetailsService - ) - dataBase = AndroidDeviceDatabase(applicationContext) searchService = SearchService(DateUtils(repository.apiMajorVersion)) dbService = AndroidDeviceDatabaseService(dataBase, searchService) @@ -615,7 +603,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar val item = PrimaryDrawerItem().apply { nameText = source.getTitleDecoded() identifier = source.id.toLong() - iconUrl = source.getIcon(apiDetailsService.getBaseUrl()) + iconUrl = source.getIcon(repository.baseUrl) onDrawerItemClickListener = { _,_,_ -> searchService.sourceIDFilter = source.id.toLong() searchService.sourceFilter = source.title @@ -989,7 +977,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ItemCardAdapter( this, items, - apiDetailsService, db, customTabActivityHelper, internalBrowser, @@ -1007,7 +994,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar ItemListAdapter( this, items, - apiDetailsService, db, customTabActivityHelper, internalBrowser, 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 949acfc..146df82 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 @@ -19,7 +19,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawa import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable 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.utils.DateUtils import com.amulyakhare.textdrawable.TextDrawable @@ -35,7 +34,6 @@ import org.kodein.di.instance class ItemCardAdapter( override val app: Activity, override var items: ArrayList, - override val apiDetailsService: ApiDetailsService, override val db: AppDatabase, private val helper: CustomTabActivityHelper, private val internalBrowser: Boolean, @@ -78,16 +76,16 @@ class ItemCardAdapter( binding.itemImage.scaleType = ScaleType.CENTER_CROP } - if (itm.getThumbnail(apiDetailsService.getBaseUrl()).isEmpty()) { + if (itm.getThumbnail(repository.baseUrl).isEmpty()) { binding.itemImage.visibility = View.GONE Glide.with(c).clear(binding.itemImage) binding.itemImage.setImageDrawable(null) } else { binding.itemImage.visibility = View.VISIBLE - c.bitmapCenterCrop(config, itm.getThumbnail(apiDetailsService.getBaseUrl()), binding.itemImage) + c.bitmapCenterCrop(config, itm.getThumbnail(repository.baseUrl), binding.itemImage) } - if (itm.getIcon(apiDetailsService.getBaseUrl()).isEmpty()) { + if (itm.getIcon(repository.baseUrl).isEmpty()) { val color = generator.getColor(itm.getSourceTitle()) val drawable = @@ -97,7 +95,7 @@ class ItemCardAdapter( .build(itm.getSourceTitle().toTextDrawableString(c), color) binding.sourceImage.setImageDrawable(drawable) } else { - c.circularBitmapDrawable(config, itm.getIcon(apiDetailsService.getBaseUrl()), binding.sourceImage) + c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.sourceImage) } } } 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 c656d6a..f6358bd 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 @@ -15,7 +15,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable 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.utils.DateUtils import com.amulyakhare.textdrawable.TextDrawable @@ -27,7 +26,6 @@ import org.kodein.di.instance class ItemListAdapter( override val app: Activity, override var items: ArrayList, - override val apiDetailsService: ApiDetailsService, override val db: AppDatabase, private val helper: CustomTabActivityHelper, private val internalBrowser: Boolean, @@ -61,9 +59,9 @@ class ItemListAdapter( binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(repository.apiMajorVersion)) - if (itm.getThumbnail(apiDetailsService.getBaseUrl()).isEmpty()) { + if (itm.getThumbnail(repository.baseUrl).isEmpty()) { - if (itm.getIcon(apiDetailsService.getBaseUrl()).isEmpty()) { + if (itm.getIcon(repository.baseUrl).isEmpty()) { val color = generator.getColor(itm.getSourceTitle()) val drawable = @@ -74,10 +72,10 @@ class ItemListAdapter( binding.itemImage.setImageDrawable(drawable) } else { - c.circularBitmapDrawable(config, itm.getIcon(apiDetailsService.getBaseUrl()), binding.itemImage) + c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.itemImage) } } else { - c.bitmapCenterCrop(config, itm.getThumbnail(apiDetailsService.getBaseUrl()), binding.itemImage) + c.bitmapCenterCrop(config, itm.getThumbnail(repository.baseUrl), binding.itemImage) } } } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index 58cc99d..6ec5237 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -10,7 +10,6 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.Config 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 com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.CoroutineScope @@ -20,7 +19,6 @@ import org.kodein.di.DIAware abstract class ItemsAdapter : RecyclerView.Adapter(), DIAware { abstract var items: ArrayList - abstract val apiDetailsService: ApiDetailsService abstract val repository: Repository abstract val db: AppDatabase abstract val userIdentifier: String From e6c70c66fc488c5cd5b9468ffb2012e4e671f406 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 17:34:09 +0200 Subject: [PATCH 26/48] Remove searchService from the home activity --- .../android/HomeActivity.kt | 51 ++++++++----------- .../android/adapters/ItemCardAdapter.kt | 5 +- .../android/adapters/ItemListAdapter.kt | 4 +- .../android/adapters/ItemsAdapter.kt | 2 - .../android/utils/LinksUtils.kt | 13 ++--- .../repository/Repository.kt | 9 +++- .../repository/RepositoryImpl.kt | 34 +++++++------ 7 files changed, 52 insertions(+), 66 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 7aa54df..133e622 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 @@ -49,8 +49,6 @@ 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.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.SearchService -import bou.amine.apps.readerforselfossv2.utils.DateUtils import bou.amine.apps.readerforselfossv2.utils.longHash import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationItem @@ -86,7 +84,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var dataBase: AndroidDeviceDatabase private lateinit var dbService: AndroidDeviceDatabaseService - private lateinit var searchService: SearchService private val MENU_PREFERENCES = 12302 private val DRAWER_ID_TAGS = 100101L private val DRAWER_ID_HIDDEN_TAGS = 101100L @@ -186,8 +183,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper = CustomTabActivityHelper() dataBase = AndroidDeviceDatabase(applicationContext) - searchService = SearchService(DateUtils(repository.apiMajorVersion)) - dbService = AndroidDeviceDatabaseService(dataBase, searchService) + //dbService = AndroidDeviceDatabaseService(dataBase, searchService) handleBottomBar() handleDrawer() @@ -370,7 +366,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar userIdentifier = settings.getString("unique_id", "") displayAccountHeader = settings.getBoolean("account_header_displaying", false) infiniteScroll = settings.getBoolean("infinite_loading", false) - searchService.itemsCaching = settings.getBoolean("items_caching", false) updateSources = settings.getBoolean("update_sources", true) markOnScroll = settings.getBoolean("mark_on_scroll", false) hiddenTags = if (settings.getString("hidden_tags", "").isNotEmpty()) { @@ -518,9 +513,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar textColor = ColorHolder.fromColor(Color.WHITE) color = ColorHolder.fromColor(appColors.colorAccent) } onDrawerItemClickListener = { _,_,_ -> - searchService.tagFilter = it.tag - searchService.sourceFilter = null - searchService.sourceIDFilter = null + repository.tagFilter = it + repository.sourceFilter = null getElementsAccordingToTab() fetchOnEmptyList() false @@ -570,9 +564,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar textColor = ColorHolder.fromColor(Color.WHITE) color = ColorHolder.fromColor(appColors.colorAccent) } onDrawerItemClickListener = { _,_,_ -> - searchService.tagFilter = it.tag - searchService.sourceFilter = null - searchService.sourceIDFilter = null + repository.tagFilter = it + repository.sourceFilter = null getElementsAccordingToTab() fetchOnEmptyList() false @@ -605,9 +598,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar identifier = source.id.toLong() iconUrl = source.getIcon(repository.baseUrl) onDrawerItemClickListener = { _,_,_ -> - searchService.sourceIDFilter = source.id.toLong() - searchService.sourceFilter = source.title - searchService.tagFilter = null + repository.sourceFilter = source + repository.tagFilter = null getElementsAccordingToTab() fetchOnEmptyList() false @@ -627,9 +619,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar identifier = DRAWER_ID_FILTERS badgeRes = R.string.drawer_action_clear onDrawerItemClickListener = { _,_,_ -> - searchService.sourceFilter = null - searchService.sourceIDFilter = null - searchService.tagFilter = null + repository.sourceFilter = null + repository.tagFilter = null binding.mainDrawer.setSelectionAtPosition(-1) getElementsAccordingToTab() fetchOnEmptyList() @@ -920,7 +911,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getUnRead(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.selectedType = "unread" + repository.displayedItems = "unread" items = if (appendResults) { repository.getNewerItems() } else { @@ -934,7 +925,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getRead(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.selectedType = "all" + repository.displayedItems = "all" items = if (appendResults) { repository.getNewerItems() } else { @@ -948,7 +939,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getStarred(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.selectedType = "starred" + repository.displayedItems = "starred" items = if (appendResults) { repository.getNewerItems() } else { @@ -984,8 +975,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar fullHeightCards, appColors, userIdentifier, - config, - searchService + config ) { updateItems(it) } @@ -1000,8 +990,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar articleViewer, userIdentifier, appColors, - config, - searchService + config ) { updateItems(it) } @@ -1064,7 +1053,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override fun onQueryTextChange(p0: String?): Boolean { if (p0.isNullOrBlank()) { - searchService.searchFilter = null + repository.searchFilter = null getElementsAccordingToTab() fetchOnEmptyList() } @@ -1072,7 +1061,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } override fun onQueryTextSubmit(p0: String?): Boolean { - searchService.searchFilter = p0 + repository.searchFilter = p0 getElementsAccordingToTab() fetchOnEmptyList() return false @@ -1171,10 +1160,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun maxItemNumber(): Int = when (elementsShown) { - UNREAD_SHOWN -> searchService.badgeUnread - READ_SHOWN -> searchService.badgeAll - FAV_SHOWN -> searchService.badgeStarred - else -> searchService.badgeUnread // if !elementsShown then unread are fetched. + UNREAD_SHOWN -> repository.badgeUnread + READ_SHOWN -> repository.badgeAll + FAV_SHOWN -> repository.badgeStarred + else -> repository.badgeUnread // if !elementsShown then unread are fetched. } private fun updateItems(adapterItems: ArrayList) { 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 146df82..0e9bf0f 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 @@ -19,7 +19,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawa import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.SearchService import bou.amine.apps.readerforselfossv2.utils.DateUtils import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.util.ColorGenerator @@ -42,7 +41,6 @@ class ItemCardAdapter( override val appColors: AppColors, override val userIdentifier: String, override val config: Config, - override val searchService: SearchService, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { private val c: Context = app.baseContext @@ -155,8 +153,7 @@ class ItemCardAdapter( customTabsIntent, internalBrowser, articleViewer, - app, - searchService + app ) } } 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 f6358bd..94fa9dc 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 @@ -33,7 +33,6 @@ class ItemListAdapter( override val userIdentifier: String, override val appColors: AppColors, override val config: Config, - override val searchService: SearchService, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { private val generator: ColorGenerator = ColorGenerator.MATERIAL @@ -100,8 +99,7 @@ class ItemListAdapter( customTabsIntent, internalBrowser, articleViewer, - app, - searchService + app ) } } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index 6ec5237..c905b38 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -10,7 +10,6 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.SearchService import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -25,7 +24,6 @@ abstract class ItemsAdapter : RecyclerView.Adapte abstract val app: Activity abstract val appColors: AppColors abstract val config: Config - abstract val searchService: SearchService abstract val updateItems: (ArrayList) -> Unit fun updateAllItems(items: ArrayList) { 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 b642c70..7e0200a 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 @@ -10,18 +10,17 @@ import android.net.Uri import android.os.Build import android.text.Spannable import android.text.style.ClickableSpan -import androidx.browser.customtabs.CustomTabsIntent import android.util.Patterns import android.view.MotionEvent import android.view.View import android.widget.TextView import android.widget.Toast +import androidx.browser.customtabs.CustomTabsIntent import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.ReaderActivity import bou.amine.apps.readerforselfossv2.android.model.getLinkDecoded import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.SearchService import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp import okhttp3.HttpUrl.Companion.toHttpUrlOrNull @@ -79,12 +78,10 @@ fun Context.openItemUrlInternally( linkDecoded: String, customTabsIntent: CustomTabsIntent, articleViewer: Boolean, - app: Activity, - searchService: SearchService + app: Activity ) { if (articleViewer) { ReaderActivity.allItems = allItems - searchService.position = currentItem val intent = Intent(this, ReaderActivity::class.java) intent.putExtra("currentItem", currentItem) app.startActivity(intent) @@ -123,8 +120,7 @@ fun Context.openItemUrl( customTabsIntent: CustomTabsIntent, internalBrowser: Boolean, articleViewer: Boolean, - app: Activity, - searchService: SearchService + app: Activity ) { if (!linkDecoded.isUrlValid()) { @@ -143,8 +139,7 @@ fun Context.openItemUrl( linkDecoded, customTabsIntent, articleViewer, - app, - searchService + app ) } else { this.openItemUrlInternalBrowser( 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 2df1995..be225f8 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 @@ -8,7 +8,10 @@ interface Repository { var items: ArrayList var baseUrl: String - var selectedType: String + var displayedItems: String + + // Settings + var itemsCaching: Boolean // API var apiMajorVersion: Int @@ -16,6 +19,10 @@ interface Repository { var badgeAll: Int var badgeStarred: Int + var tagFilter: SelfossModel.Tag? + var sourceFilter: SelfossModel.Source? + var searchFilter: String? + suspend fun getNewerItems(): ArrayList suspend fun getOlderItems(): ArrayList suspend fun reloadBadges(): Boolean 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 e933ff6..07752d8 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 @@ -19,7 +19,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override var baseUrl = apiDetails.getBaseUrl() - override var selectedType = "unread" + override var displayedItems = "unread" set(value) { field = when (value) { "all" -> "all" @@ -30,9 +30,11 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } } - private var selectedTag: SelfossModel.Tag? = null - private var selectedSource: SelfossModel.Source? = null - private var search: String? = null + override var tagFilter: SelfossModel.Tag? = null + override var sourceFilter: SelfossModel.Source? = null + override var searchFilter: String? = null + + override var itemsCaching = settings.getBoolean("items_caching", false) override var apiMajorVersion = 0 override var badgeUnread = 0 @@ -52,12 +54,12 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun getNewerItems(): ArrayList { // TODO: Check connectivity - val fetchedItems = api.getItems(selectedType, + val fetchedItems = api.getItems(displayedItems, settings.getString("prefer_api_items_number", "200").toInt(), offset = 0, - selectedTag?.tag, - selectedSource?.id?.toLong(), - search) + tagFilter?.tag, + sourceFilter?.id?.toLong(), + searchFilter) if (fetchedItems != null) { items = ArrayList(fetchedItems) @@ -68,12 +70,12 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun getOlderItems(): ArrayList { // TODO: Check connectivity val offset = items.size - val fetchedItems = api.getItems(selectedType, + val fetchedItems = api.getItems(displayedItems, settings.getString("prefer_api_items_number", "200").toInt(), offset, - selectedTag?.tag, - selectedSource?.id?.toLong(), - search) + tagFilter?.tag, + sourceFilter?.id?.toLong(), + searchFilter) if (fetchedItems != null) { items = ArrayList(fetchedItems) @@ -98,14 +100,14 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet private fun filterSelectedItems(items: ArrayList): ArrayList { val tmpItems = ArrayList(items) - if (selectedType == "unread") { + if (displayedItems == "unread") { tmpItems.removeAll { !it.unread } - } else if (selectedType == "starred") { + } else if (displayedItems == "starred") { tmpItems.removeAll { !it.starred } } - if (selectedTag != null) { - tmpItems.removeAll { !it.tags.contains(selectedTag!!.tag) } + if (tagFilter != null) { + tmpItems.removeAll { !it.tags.contains(tagFilter!!.tag) } } return tmpItems From 5ea75a5352b7ddc4aebc9833915ca8df7797c4ab Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 17:35:50 +0200 Subject: [PATCH 27/48] Correctly show tags in side pane --- .../bou/amine/apps/readerforselfossv2/android/HomeActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 133e622..5567af3 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 @@ -740,7 +740,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar if (this@HomeActivity.isNetworkAvailable(null, offlineShortcut) && updateSources) { CoroutineScope(Dispatchers.IO).launch { - val tags = repository.getTags() + tags = repository.getTags() sourcesApiCall() } } From 8c5f4268a411cb5d8c0073c9fef3f49be483b6f1 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 17:41:41 +0200 Subject: [PATCH 28/48] Remove unused variable --- .../amine/apps/readerforselfossv2/android/HomeActivity.kt | 5 ----- 1 file changed, 5 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 5567af3..cfd1720 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 @@ -110,7 +110,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private var updateSources: Boolean = true private var markOnScroll: Boolean = false private var hiddenTags: List = emptyList() - private var apiVersionMajor: Int = 0 private var periodicRefresh = false private var refreshMinutes: Long = 360L @@ -192,8 +191,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar handleSettings() - apiVersionMajor = repository.apiMajorVersion - getElementsAccordingToTab() } @@ -380,8 +377,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar if (refreshMinutes <= 15) { refreshMinutes = 15 } - - apiVersionMajor = settings.getInt("apiVersionMajor", 0) } private fun handleThemeBinding() { From 5377e6c0f8648170b988c0cbeb75f0b2824a0440 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 17:48:13 +0200 Subject: [PATCH 29/48] Make items read by swiping disappear --- .../android/adapters/ItemsAdapter.kt | 17 +++++++---------- .../repository/RepositoryImpl.kt | 2 ++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index c905b38..5ba7463 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -80,17 +80,14 @@ abstract class ItemsAdapter : RecyclerView.Adapte val i = items[position] CoroutineScope(Dispatchers.IO).launch { repository.markAsRead(i.id) - // TODO: update db - } - // Todo: -// if (SharedItems.displayedItems == "unread") { -// items.remove(i) -// notifyItemRemoved(position) -// updateItems(items) -// } else { -// notifyItemChanged(position) -// } + if (repository.displayedItems == "unread") { + items.remove(i) + notifyItemRemoved(position) + updateItems(items) + } else { + notifyItemChanged(position) + } if (showSnackbar) { unmarkSnackbar(i, position) } 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 07752d8..e7b36b8 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 @@ -300,4 +300,6 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet apiMajorVersion = settings.getInt("apiVersionMajor", 0) } } + + // TODO: Handle offline actions } \ No newline at end of file From 3e97ee30a134bc62c1332114f4d480fa0a9aaa80 Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 17:57:52 +0200 Subject: [PATCH 30/48] More informative log message --- .../amine/apps/readerforselfossv2/repository/RepositoryImpl.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 e7b36b8..2779e7c 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 @@ -271,8 +271,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet result = true } } catch (cause: Throwable) { - Napier.e(cause.message!!, tag = "1") - Napier.e(cause.stackTraceToString(),tag = "1") + Napier.e(cause.stackTraceToString(),tag = "RepositoryImpl.updateRemote") } return result } From 88c5c6ff4bba1d81155948e46b86d6d73920ff0e Mon Sep 17 00:00:00 2001 From: davide Date: Sat, 13 Aug 2022 18:00:51 +0200 Subject: [PATCH 31/48] Don't regenerate dateutils each time it's needed --- .../amine/apps/readerforselfossv2/repository/RepositoryImpl.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 2779e7c..abc6e8e 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 @@ -18,6 +18,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet set(value) { field = ArrayList(value) } override var baseUrl = apiDetails.getBaseUrl() + private lateinit var dateUtils: DateUtils override var displayedItems = "unread" set(value) { @@ -48,6 +49,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found CoroutineScope(Dispatchers.Main).launch { updateApiVersion() + dateUtils = DateUtils(apiMajorVersion) reloadBadges() } } @@ -94,7 +96,6 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } private fun sortItems(items: ArrayList) { - val dateUtils = DateUtils(apiMajorVersion) items.sortByDescending { dateUtils.parseDate(it.datetime) } } From 22f0ff664c1104ebcb21d278859ffdbeae309ff5 Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 14 Aug 2022 12:39:20 +0200 Subject: [PATCH 32/48] Append older articles fetched --- .../readerforselfossv2/repository/RepositoryImpl.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 abc6e8e..56fdfac 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 @@ -80,15 +80,15 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet searchFilter) if (fetchedItems != null) { - items = ArrayList(fetchedItems) + appendItems(fetchedItems) } return items } - private fun storeItems(fetchedItems: List) { - // TODO: Store in DB + private fun appendItems(fetchedItems: List) { + // TODO: Store in DB if enabled by user val fetchedIDS = fetchedItems.map { it.id } - val tmpItems = ArrayList(items) + val tmpItems = items tmpItems.removeAll{ it.id in fetchedIDS } tmpItems.addAll(fetchedItems) sortItems(tmpItems) @@ -100,7 +100,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } private fun filterSelectedItems(items: ArrayList): ArrayList { - val tmpItems = ArrayList(items) + val tmpItems = items if (displayedItems == "unread") { tmpItems.removeAll { !it.unread } } else if (displayedItems == "starred") { From 1890297c9d35e657f3707f975548c0ab167ce924 Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 14 Aug 2022 12:40:20 +0200 Subject: [PATCH 33/48] Remove commented declaration --- .../bou/amine/apps/readerforselfossv2/android/HomeActivity.kt | 1 - 1 file changed, 1 deletion(-) 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 cfd1720..2b68e9b 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 @@ -182,7 +182,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper = CustomTabActivityHelper() dataBase = AndroidDeviceDatabase(applicationContext) - //dbService = AndroidDeviceDatabaseService(dataBase, searchService) handleBottomBar() handleDrawer() From 7f8d04618a786074aa68572517b94de2b29ca2bd Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 14 Aug 2022 12:52:23 +0200 Subject: [PATCH 34/48] Simplify local item changes --- .../repository/RepositoryImpl.kt | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) 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 56fdfac..cc651d9 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 @@ -147,7 +147,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet val success = api.markAsRead(id.toString())?.isSuccess == true if (success) { - markAsReadLocally(id) + markAsReadLocally(items.first {it.id == id}) } return success } @@ -157,7 +157,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet val success = api.unmarkAsRead(id.toString())?.isSuccess == true if (success) { - unmarkAsReadLocally(id) + unmarkAsReadLocally(items.first {it.id == id}) } return success } @@ -167,7 +167,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet val success = api.starr(id.toString())?.isSuccess == true if (success) { - starrLocally(id) + starrLocally(items.first {it.id == id}) } return success } @@ -177,7 +177,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet val success = api.unstarr(id.toString())?.isSuccess == true if (success) { - unstarrLocally(id) + unstarrLocally(items.first {it.id == id}) } return success } @@ -188,41 +188,42 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet val success = api.markAllAsRead(ids.map { it.toString() })?.isSuccess == true if (success) { - for (id in ids) { - markAsReadLocally(id) + val itemsToMark = items.filter { it.id in ids } + for (item in itemsToMark) { + markAsReadLocally(item) } } return success } - private fun markAsReadLocally(id: Int) { + private fun markAsReadLocally(item: SelfossModel.Item) { // TODO: Mark also in the database - if (items.first {it.id == id}.unread) { - items.first {it.id == id}.unread = false + if (item.unread) { + item.unread = false badgeUnread -= 1 } } - private fun unmarkAsReadLocally(id: Int) { + private fun unmarkAsReadLocally(item: SelfossModel.Item) { // TODO: Mark also in the database - if (!items.first {it.id == id}.unread) { - items.first {it.id == id}.unread = true + if (!item.unread) { + item.unread = true badgeUnread += 1 } } - private fun starrLocally(id: Int) { + private fun starrLocally(item: SelfossModel.Item) { // TODO: Mark also in the database - if (!items.first {it.id == id}.starred) { - items.first {it.id == id}.starred = true + if (!item.starred) { + item.starred = true badgeStarred += 1 } } - private fun unstarrLocally(id: Int) { + private fun unstarrLocally(item: SelfossModel.Item) { // TODO: Mark also in the database - if (items.first {it.id == id}.starred) { - items.first {it.id == id}.starred = false + if (item.starred) { + item.starred = false badgeStarred -= 1 } } From baa4b81e77677c251a28090de67f8559c86d68aa Mon Sep 17 00:00:00 2001 From: davide Date: Sun, 14 Aug 2022 13:00:37 +0200 Subject: [PATCH 35/48] Inject dateUtils --- .../readerforselfossv2/android/adapters/ItemCardAdapter.kt | 3 +-- .../readerforselfossv2/android/adapters/ItemListAdapter.kt | 4 +--- .../readerforselfossv2/android/fragments/ArticleFragment.kt | 3 +-- .../amine/apps/readerforselfossv2/repository/Repository.kt | 2 ++ .../apps/readerforselfossv2/repository/RepositoryImpl.kt | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) 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 0e9bf0f..2cdd01b 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 @@ -19,7 +19,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawa import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.utils.DateUtils import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.util.ColorGenerator import com.bumptech.glide.Glide @@ -67,7 +66,7 @@ class ItemCardAdapter( binding.title.setLinkTextColor(appColors.colorAccent) - binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(repository.apiMajorVersion)) + binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils) 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 94fa9dc..8efbc7f 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 @@ -15,8 +15,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.service.SearchService -import bou.amine.apps.readerforselfossv2.utils.DateUtils import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.util.ColorGenerator import org.kodein.di.DI @@ -56,7 +54,7 @@ class ItemListAdapter( binding.title.setLinkTextColor(appColors.colorAccent) - binding.sourceTitleAndDate.text = itm.sourceAndDateText(DateUtils(repository.apiMajorVersion)) + binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils) if (itm.getThumbnail(repository.baseUrl).isEmpty()) { 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 06e4904..0deb6a1 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 @@ -38,7 +38,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailable import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.utils.DateUtils import bou.amine.apps.readerforselfossv2.utils.isEmptyOrNullOrNullString import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy @@ -124,7 +123,7 @@ class ArticleFragment : Fragment(), DIAware { contentText = item.content contentTitle = item.getTitleDecoded() contentImage = item.getThumbnail(repository.baseUrl) - contentSource = item.sourceAndDateText(DateUtils(repository.apiMajorVersion)) + contentSource = item.sourceAndDateText(repository.dateUtils) allImages = item.getImages() fontSize = settings.getString("reader_font_size", "16").toInt() 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 be225f8..c1dc7b1 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 @@ -1,12 +1,14 @@ package bou.amine.apps.readerforselfossv2.repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel +import bou.amine.apps.readerforselfossv2.utils.DateUtils interface Repository { // TODO: remove the items variables in favor of storing everything in the database var items: ArrayList var baseUrl: String + var dateUtils: DateUtils var displayedItems: String 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 cc651d9..dc70a30 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 @@ -18,7 +18,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet set(value) { field = ArrayList(value) } override var baseUrl = apiDetails.getBaseUrl() - private lateinit var dateUtils: DateUtils + override lateinit var dateUtils: DateUtils override var displayedItems = "unread" set(value) { From fe59177efb57399c48772df31e95b96b86fe423d Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 15 Aug 2022 15:07:10 +0200 Subject: [PATCH 36/48] Do not create a new ArrayList every time the items are accessed --- .../amine/apps/readerforselfossv2/repository/RepositoryImpl.kt | 2 -- 1 file changed, 2 deletions(-) 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 dc70a30..2832e23 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 @@ -14,8 +14,6 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet val settings = Settings() override var items = ArrayList() - get() { return ArrayList(field) } - set(value) { field = ArrayList(value) } override var baseUrl = apiDetails.getBaseUrl() override lateinit var dateUtils: DateUtils From d47cca2f5a1e2e99185cbd2bb9b8ffc45b745986 Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 15 Aug 2022 15:16:57 +0200 Subject: [PATCH 37/48] Use an enum to represent item type --- .../android/HomeActivity.kt | 7 ++++--- .../android/adapters/ItemsAdapter.kt | 3 ++- .../repository/Repository.kt | 3 ++- .../repository/RepositoryImpl.kt | 20 ++++++------------- .../apps/readerforselfossv2/utils/Enums.kt | 7 +++++++ 5 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt 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 2b68e9b..39bf335 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 @@ -49,6 +49,7 @@ 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.rest.SelfossModel +import bou.amine.apps.readerforselfossv2.utils.ItemType import bou.amine.apps.readerforselfossv2.utils.longHash import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationItem @@ -905,7 +906,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getUnRead(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.displayedItems = "unread" + repository.displayedItems = ItemType.UNREAD items = if (appendResults) { repository.getNewerItems() } else { @@ -919,7 +920,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getRead(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.displayedItems = "all" + repository.displayedItems = ItemType.ALL items = if (appendResults) { repository.getNewerItems() } else { @@ -933,7 +934,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getStarred(appendResults: Boolean = false) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.displayedItems = "starred" + repository.displayedItems = ItemType.STARRED items = if (appendResults) { repository.getNewerItems() } else { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index 5ba7463..ff24461 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -10,6 +10,7 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel +import bou.amine.apps.readerforselfossv2.utils.ItemType import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -81,7 +82,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte CoroutineScope(Dispatchers.IO).launch { repository.markAsRead(i.id) } - if (repository.displayedItems == "unread") { + if (repository.displayedItems == ItemType.UNREAD) { items.remove(i) notifyItemRemoved(position) updateItems(items) 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 c1dc7b1..a64393e 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 @@ -2,6 +2,7 @@ package bou.amine.apps.readerforselfossv2.repository import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.utils.DateUtils +import bou.amine.apps.readerforselfossv2.utils.ItemType interface Repository { @@ -10,7 +11,7 @@ interface Repository { var baseUrl: String var dateUtils: DateUtils - var displayedItems: String + var displayedItems: ItemType // Settings var itemsCaching: Boolean 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 2832e23..2208fb6 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 @@ -4,6 +4,7 @@ import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.rest.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.utils.DateUtils +import bou.amine.apps.readerforselfossv2.utils.ItemType import com.russhwolf.settings.Settings import io.github.aakira.napier.Napier import kotlinx.coroutines.CoroutineScope @@ -18,16 +19,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override var baseUrl = apiDetails.getBaseUrl() override lateinit var dateUtils: DateUtils - override var displayedItems = "unread" - set(value) { - field = when (value) { - "all" -> "all" - "unread" -> "unread" - "read" -> "read" - "starred" -> "starred" - else -> "all" - } - } + override var displayedItems = ItemType.UNREAD override var tagFilter: SelfossModel.Tag? = null override var sourceFilter: SelfossModel.Source? = null @@ -54,7 +46,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun getNewerItems(): ArrayList { // TODO: Check connectivity - val fetchedItems = api.getItems(displayedItems, + val fetchedItems = api.getItems(displayedItems.type, settings.getString("prefer_api_items_number", "200").toInt(), offset = 0, tagFilter?.tag, @@ -70,7 +62,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet override suspend fun getOlderItems(): ArrayList { // TODO: Check connectivity val offset = items.size - val fetchedItems = api.getItems(displayedItems, + val fetchedItems = api.getItems(displayedItems.type, settings.getString("prefer_api_items_number", "200").toInt(), offset, tagFilter?.tag, @@ -99,9 +91,9 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet private fun filterSelectedItems(items: ArrayList): ArrayList { val tmpItems = items - if (displayedItems == "unread") { + if (displayedItems == ItemType.UNREAD) { tmpItems.removeAll { !it.unread } - } else if (displayedItems == "starred") { + } else if (displayedItems == ItemType.STARRED) { tmpItems.removeAll { !it.starred } } 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 new file mode 100644 index 0000000..d8390cc --- /dev/null +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt @@ -0,0 +1,7 @@ +package bou.amine.apps.readerforselfossv2.utils + +enum class ItemType(val type: String) { + UNREAD("unread"), + ALL("all"), + STARRED("starred") +} \ No newline at end of file From bb5c5213871c3f7095f876727f4d5d5916897c79 Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 15 Aug 2022 15:22:32 +0200 Subject: [PATCH 38/48] Remove redundant functions to fetch items --- .../android/HomeActivity.kt | 40 +++---------------- 1 file changed, 6 insertions(+), 34 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 39bf335..173f3b1 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 @@ -886,10 +886,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar fun doGetAccordingToTab() { when (elementsShown) { // TODO: These three functions are not required, one is enough - UNREAD_SHOWN -> getUnRead(appendResults) - READ_SHOWN -> getRead(appendResults) - FAV_SHOWN -> getStarred(appendResults) - else -> getUnRead(appendResults) + UNREAD_SHOWN -> getItems(appendResults, ItemType.UNREAD) + READ_SHOWN -> getItems(appendResults, ItemType.ALL) + FAV_SHOWN -> getItems(appendResults, ItemType.STARRED) + else -> getItems(appendResults, ItemType.UNREAD) } } @@ -903,38 +903,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar doGetAccordingToTab() } - private fun getUnRead(appendResults: Boolean = false) { + private fun getItems(appendResults: Boolean, itemType: ItemType) { CoroutineScope(Dispatchers.Main).launch { binding.swipeRefreshLayout.isRefreshing = true - repository.displayedItems = ItemType.UNREAD - items = if (appendResults) { - repository.getNewerItems() - } else { - repository.getOlderItems() - } - binding.swipeRefreshLayout.isRefreshing = false - handleListResult() - } - } - - private fun getRead(appendResults: Boolean = false) { - CoroutineScope(Dispatchers.Main).launch { - binding.swipeRefreshLayout.isRefreshing = true - repository.displayedItems = ItemType.ALL - items = if (appendResults) { - repository.getNewerItems() - } else { - repository.getOlderItems() - } - binding.swipeRefreshLayout.isRefreshing = false - handleListResult() - } - } - - private fun getStarred(appendResults: Boolean = false) { - CoroutineScope(Dispatchers.Main).launch { - binding.swipeRefreshLayout.isRefreshing = true - repository.displayedItems = ItemType.STARRED + repository.displayedItems = itemType items = if (appendResults) { repository.getNewerItems() } else { From 29619e1b2b640ba1737630eb38fd79dbad16dd0e Mon Sep 17 00:00:00 2001 From: davide Date: Mon, 15 Aug 2022 20:42:14 +0200 Subject: [PATCH 39/48] Use an enum to represent the selected items --- .../android/HomeActivity.kt | 33 ++++++------------- .../apps/readerforselfossv2/utils/Enums.kt | 12 ++++--- 2 files changed, 18 insertions(+), 27 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 173f3b1..e060bdd 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 @@ -90,9 +90,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private val DRAWER_ID_HIDDEN_TAGS = 101100L private val DRAWER_ID_SOURCES = 100110L private val DRAWER_ID_FILTERS = 100111L - private val UNREAD_SHOWN = 1 - private val READ_SHOWN = 2 - private val FAV_SHOWN = 3 private var items: ArrayList = ArrayList() @@ -103,7 +100,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private var displayAllCount = false private var fullHeightCards: Boolean = false private var itemsNumber: Int = 200 - private var elementsShown: Int = 1 + private var elementsShown: ItemType = ItemType.UNREAD private var userIdentifier: String = "" private var displayAccountHeader: Boolean = false private var infiniteScroll: Boolean = false @@ -160,7 +157,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar offlineShortcut = intent.getBooleanExtra("startOffline", false) if (fromTabShortcut) { - elementsShown = intent.getIntExtra("shortcutTab", UNREAD_SHOWN) + elementsShown = ItemType.fromInt(intent.getIntExtra("shortcutTab", ItemType.UNREAD.position)) } setContentView(view) @@ -219,7 +216,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder ): Int = - if (elementsShown == FAV_SHOWN) { + if (elementsShown == ItemType.STARRED) { 0 } else { super.getSwipeDirs( @@ -316,7 +313,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.bottomBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC) if (fromTabShortcut) { - binding.bottomBar.selectTab(elementsShown - 1) + binding.bottomBar.selectTab(elementsShown.position - 1) } } @@ -830,7 +827,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar offset = 0 lastFetchDone = false - elementsShown = position + 1 + elementsShown = ItemType.fromInt(position + 1) getElementsAccordingToTab() binding.recyclerView.scrollToPosition(0) @@ -883,16 +880,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun getElementsAccordingToTab( appendResults: Boolean = false ) { - fun doGetAccordingToTab() { - when (elementsShown) { - // TODO: These three functions are not required, one is enough - UNREAD_SHOWN -> getItems(appendResults, ItemType.UNREAD) - READ_SHOWN -> getItems(appendResults, ItemType.ALL) - FAV_SHOWN -> getItems(appendResults, ItemType.STARRED) - else -> getItems(appendResults, ItemType.UNREAD) - } - } - offset = if (appendResults && items.size > 0) { items.size - 1 } else { @@ -900,7 +887,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } firstVisible = if (appendResults) firstVisible else 0 - doGetAccordingToTab() + getItems(appendResults, elementsShown) } private fun getItems(appendResults: Boolean, itemType: ItemType) { @@ -1085,7 +1072,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } } R.id.readAll -> { - if (elementsShown == UNREAD_SHOWN) { + if (elementsShown == ItemType.UNREAD) { needsConfirmation(R.string.readAll, R.string.markall_dialog_message) { binding.swipeRefreshLayout.isRefreshing = true @@ -1127,9 +1114,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun maxItemNumber(): Int = when (elementsShown) { - UNREAD_SHOWN -> repository.badgeUnread - READ_SHOWN -> repository.badgeAll - FAV_SHOWN -> repository.badgeStarred + ItemType.UNREAD -> repository.badgeUnread + ItemType.ALL -> repository.badgeAll + ItemType.STARRED -> repository.badgeStarred else -> repository.badgeUnread // if !elementsShown then unread are fetched. } 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 d8390cc..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 @@ -1,7 +1,11 @@ package bou.amine.apps.readerforselfossv2.utils -enum class ItemType(val type: String) { - UNREAD("unread"), - ALL("all"), - STARRED("starred") +enum class ItemType(val position: Int, val type: String) { + UNREAD(1, "unread"), + ALL(2, "all"), + STARRED(3, "starred"); + + companion object { + fun fromInt(value: Int) = values().first { it.position == value } + } } \ No newline at end of file From 1fb16bcbdddc7cf47ca2cdcc32a3c49a376e10d7 Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 10:55:22 +0200 Subject: [PATCH 40/48] Remove unused user identifier --- .../bou/amine/apps/readerforselfossv2/android/HomeActivity.kt | 4 ---- .../amine/apps/readerforselfossv2/android/LoginActivity.kt | 3 --- .../java/bou/amine/apps/readerforselfossv2/android/MyApp.kt | 4 ---- .../amine/apps/readerforselfossv2/android/ReaderActivity.kt | 2 -- .../readerforselfossv2/android/adapters/ItemCardAdapter.kt | 1 - .../readerforselfossv2/android/adapters/ItemListAdapter.kt | 1 - .../apps/readerforselfossv2/android/adapters/ItemsAdapter.kt | 1 - 7 files changed, 16 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 e060bdd..5e460e6 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 @@ -101,7 +101,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private var fullHeightCards: Boolean = false private var itemsNumber: Int = 200 private var elementsShown: ItemType = ItemType.UNREAD - private var userIdentifier: String = "" private var displayAccountHeader: Boolean = false private var infiniteScroll: Boolean = false private var lastFetchDone: Boolean = false @@ -357,7 +356,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar displayAllCount = settings.getBoolean("display_other_count", false) fullHeightCards = settings.getBoolean("full_height_cards", false) itemsNumber = settings.getString("prefer_api_items_number", "200").toInt() - userIdentifier = settings.getString("unique_id", "") displayAccountHeader = settings.getBoolean("account_header_displaying", false) infiniteScroll = settings.getBoolean("infinite_loading", false) updateSources = settings.getBoolean("update_sources", true) @@ -928,7 +926,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar articleViewer, fullHeightCards, appColors, - userIdentifier, config ) { updateItems(it) @@ -942,7 +939,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper, internalBrowser, articleViewer, - userIdentifier, appColors, config ) { 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 62e11ae..3ef0544 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 @@ -34,7 +34,6 @@ class LoginActivity() : AppCompatActivity(), DIAware { private var isWithHTTPLogin = false private val settings = Settings() - private lateinit var userIdentifier: String private lateinit var appColors: AppColors private lateinit var binding: ActivityLoginBinding @@ -54,8 +53,6 @@ class LoginActivity() : AppCompatActivity(), DIAware { handleBaseUrlFail() - userIdentifier = settings.getString("unique_id", "") - if (settings.getString("url", "").isNotEmpty()) { goToMain() } 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 82c9b0f..53bb28e 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 @@ -38,10 +38,6 @@ class MyApp : MultiDexApplication(), DIAware { config = Config() settings = Settings() - if (settings.getString("unique_id", "").isEmpty()) { - settings.putString("unique_id", randomUUID().toString()) - } - initDrawerImageLoader() initTheme() diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index f283e3e..021ffde 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -35,7 +35,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { private var markOnScroll: Boolean = false private var currentItem: Int = 0 - private lateinit var userIdentifier: String private lateinit var appColors: AppColors private lateinit var toolbarMenu: Menu @@ -89,7 +88,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - userIdentifier = settings.getString("unique_id", "") markOnScroll = settings.getBoolean("mark_on_scroll", false) activeAlignment = settings.getInt("text_align", JUSTIFY) 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 2cdd01b..c0b8db6 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 @@ -38,7 +38,6 @@ class ItemCardAdapter( private val articleViewer: Boolean, private val fullHeightCards: Boolean, override val appColors: AppColors, - override val userIdentifier: String, override val config: Config, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { 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 8efbc7f..b48d358 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 @@ -28,7 +28,6 @@ class ItemListAdapter( private val helper: CustomTabActivityHelper, private val internalBrowser: Boolean, private val articleViewer: Boolean, - override val userIdentifier: String, override val appColors: AppColors, override val config: Config, override val updateItems: (ArrayList) -> Unit diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index ff24461..07d3d80 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -21,7 +21,6 @@ abstract class ItemsAdapter : RecyclerView.Adapte abstract var items: ArrayList abstract val repository: Repository abstract val db: AppDatabase - abstract val userIdentifier: String abstract val app: Activity abstract val appColors: AppColors abstract val config: Config From 38f1dbd34dd497a8293a57628766cc64152858a3 Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:13:26 +0200 Subject: [PATCH 41/48] Strip direct api access from background --- .../android/background/background.kt | 40 +++++-------------- .../repository/Repository.kt | 1 + .../repository/RepositoryImpl.kt | 3 ++ 3 files changed, 15 insertions(+), 29 deletions(-) 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 e853ee6..860d2c1 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 @@ -15,8 +15,6 @@ import bou.amine.apps.readerforselfossv2.android.MainActivity import bou.amine.apps.readerforselfossv2.android.MyApp import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.model.preloadImages -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.ActionEntity import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATION_1_2 @@ -25,13 +23,8 @@ import bou.amine.apps.readerforselfossv2.android.persistence.migrations.MIGRATIO 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 -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.ItemType import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -46,24 +39,12 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con lateinit var db: AppDatabase 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() val periodicRefresh = settings.getBoolean("periodic_refresh", false) if (periodicRefresh) { - val api = SelfossApiImpl( -// this.context, -// null, -// settings.getBoolean("isSelfSignedCert", false), -// sharedPref.getString("api_timeout", "-1")!!.toLong() - apiDetailsService - ) - - val dateUtils = DateUtils(repository.apiMajorVersion) - val searchService = SearchService(dateUtils) - val service = SelfossService(api, AndroidDeviceDatabaseService(AndroidDeviceDatabase(applicationContext), searchService), searchService) if (context.isNetworkAvailable()) { @@ -95,19 +76,19 @@ override fun doWork(): Result { actions.forEach { action -> when { action.read -> doAndReportOnFail( - api.markAsRead(action.articleId), + repository.markAsRead(action.articleId.toInt()), action ) action.unread -> doAndReportOnFail( - api.unmarkAsRead(action.articleId), + repository.unmarkAsRead(action.articleId.toInt()), action ) action.starred -> doAndReportOnFail( - api.starr(action.articleId), + repository.starr(action.articleId.toInt()), action ) action.unstarred -> doAndReportOnFail( - api.unstarr(action.articleId), + repository.unstarr(action.articleId.toInt()), action ) } @@ -116,10 +97,10 @@ override fun doWork(): Result { if (context.isNetworkAvailable()) { launch { try { - val newItems = service.allNewItems() + val newItems = repository.allItems(ItemType.UNREAD) handleNewItemsNotification(newItems, notifyNewItems, notificationManager) - val readItems = service.allReadItems() - val starredItems = service.allStarredItems() + val readItems = repository.allItems(ItemType.ALL) + val starredItems = repository.allItems(ItemType.STARRED) // TODO: save all to DB } catch (e: Throwable) {} } @@ -178,8 +159,9 @@ override fun doWork(): Result { } } - private fun doAndReportOnFail(result: SelfossModel.SuccessResponse?, action: ActionEntity) { - if (result != null && result.isSuccess) { + private fun doAndReportOnFail(result: Boolean, action: ActionEntity) { + // TODO: Failures should be reported + if (result) { thread { db.actionsDao().delete(action) } 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 a64393e..e926a0b 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 @@ -28,6 +28,7 @@ interface Repository { suspend fun getNewerItems(): ArrayList suspend fun getOlderItems(): ArrayList + suspend fun allItems(itemType: ItemType): List? suspend fun reloadBadges(): Boolean suspend fun getTags(): List? suspend fun getSpouts(): Map? 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 2208fb6..f053b42 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 @@ -75,6 +75,9 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return items } + override suspend fun allItems(itemType: ItemType): List? = + api.getItems(itemType.type, 200, 0, tagFilter?.tag, sourceFilter?.id?.toLong(), searchFilter) + private fun appendItems(fetchedItems: List) { // TODO: Store in DB if enabled by user val fetchedIDS = fetchedItems.map { it.id } From f624a35fe260b9321cec40df33f05f7eb3300ab6 Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:18:13 +0200 Subject: [PATCH 42/48] Remove unused SelfossApi interface --- .../apps/readerforselfossv2/DI/modules.kt | 3 +- .../rest/{SelfossApiImpl.kt => SelfossApi.kt} | 90 ++++--------------- 2 files changed, 20 insertions(+), 73 deletions(-) rename shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/{SelfossApiImpl.kt => SelfossApi.kt} (76%) diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt index c18e33d..2beba39 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt @@ -1,7 +1,6 @@ package bou.amine.apps.readerforselfossv2.DI import bou.amine.apps.readerforselfossv2.rest.SelfossApi -import bou.amine.apps.readerforselfossv2.rest.SelfossApiImpl import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.service.ApiDetailsServiceImpl import org.kodein.di.DI @@ -11,5 +10,5 @@ import org.kodein.di.singleton val networkModule by DI.Module { bind() with singleton { ApiDetailsServiceImpl() } - bind() with singleton { SelfossApiImpl(instance()) } + bind() with singleton { SelfossApi(instance()) } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt similarity index 76% rename from shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt index 1bfa932..90ba822 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApiImpl.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt @@ -12,61 +12,9 @@ import io.ktor.client.plugins.logging.* import io.ktor.serialization.kotlinx.json.* import kotlinx.serialization.json.Json -interface SelfossApi { - val client: HttpClient - fun url(path: String): String +class SelfossApi(private val apiDetailsService: ApiDetailsService) { - fun refreshLoginInformation() - - suspend fun login(): SelfossModel.SuccessResponse? - - suspend fun getItems( - type: String, - items: Int, - offset: Int, - tag: String? = "", - source: Long? = null, - search: String? = "", - updatedSince: String? = "" - ): List? - - suspend fun stats(): SelfossModel.Stats? - - suspend fun tags(): List? - - suspend fun update(): SelfossModel.SuccessResponse? - - suspend fun spouts(): Map? - - suspend fun sources(): ArrayList? - - suspend fun version(): SelfossModel.ApiVersion? - - suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? - - suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? - - suspend fun starr(id: String): SelfossModel.SuccessResponse? - - suspend fun unstarr(id: String): SelfossModel.SuccessResponse? - - suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? - - suspend fun createSourceForVersion( - title: String, - url: String, - spout: String, - tags: String, - filter: String, - version: Int - ): SelfossModel.SuccessResponse? - - suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? -} - -class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : SelfossApi { - - override var client = createHttpClient() + var client = createHttpClient() private fun createHttpClient(): HttpClient { return HttpClient { @@ -104,21 +52,21 @@ class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : Selfoss } } - override fun url(path: String) = + fun url(path: String) = "${apiDetailsService.getBaseUrl()}$path" - override fun refreshLoginInformation() { + fun refreshLoginInformation() { apiDetailsService.refresh() client = createHttpClient() } - override suspend fun login(): SelfossModel.SuccessResponse? = + suspend fun login(): SelfossModel.SuccessResponse? = client.get(url("/login")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun getItems( + suspend fun getItems( type: String, items: Int, offset: Int, @@ -139,64 +87,64 @@ class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : Selfoss parameter("offset", offset) }.body() - override suspend fun stats(): SelfossModel.Stats? = + suspend fun stats(): SelfossModel.Stats? = client.get(url("/stats")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun tags(): List? = + suspend fun tags(): List? = client.get(url("/tags")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun update(): SelfossModel.SuccessResponse? = + suspend fun update(): SelfossModel.SuccessResponse? = client.get(url("/update")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun spouts(): Map? = + suspend fun spouts(): Map? = client.get(url("/sources/spouts")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun sources(): ArrayList? = + suspend fun sources(): ArrayList? = client.get(url("/sources/list")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun version(): SelfossModel.ApiVersion? = + suspend fun version(): SelfossModel.ApiVersion? = client.get(url("/api/about")).body() - override suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? = + suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? = client.post(url("/mark/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? = + suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? = client.post(url("/unmark/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun starr(id: String): SelfossModel.SuccessResponse? = + suspend fun starr(id: String): SelfossModel.SuccessResponse? = client.post(url("/starr/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun unstarr(id: String): SelfossModel.SuccessResponse? = + suspend fun unstarr(id: String): SelfossModel.SuccessResponse? = client.post(url("/unstarr/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) }.body() - override suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? = + suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? = client.submitForm( url = url("/mark"), formParameters = Parameters.build { @@ -206,7 +154,7 @@ class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : Selfoss } ).body() - override suspend fun createSourceForVersion( + suspend fun createSourceForVersion( title: String, url: String, spout: String, @@ -256,7 +204,7 @@ class SelfossApiImpl(private val apiDetailsService: ApiDetailsService) : Selfoss } ).body() - override suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? = + suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? = client.delete(url("/source/$id")) { parameter("username", apiDetailsService.getUserName()) parameter("password", apiDetailsService.getPassword()) From 0556500c5df0c7a3c7a59bc61393d92260e9fe4d Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:19:56 +0200 Subject: [PATCH 43/48] Remove unused function --- .../repository/RepositoryImpl.kt | 15 --------------- 1 file changed, 15 deletions(-) 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 f053b42..6c6b0ef 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 @@ -92,21 +92,6 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet items.sortByDescending { dateUtils.parseDate(it.datetime) } } - private fun filterSelectedItems(items: ArrayList): ArrayList { - val tmpItems = items - if (displayedItems == ItemType.UNREAD) { - tmpItems.removeAll { !it.unread } - } else if (displayedItems == ItemType.STARRED) { - tmpItems.removeAll { !it.starred } - } - - if (tagFilter != null) { - tmpItems.removeAll { !it.tags.contains(tagFilter!!.tag) } - } - - return tmpItems - } - override suspend fun reloadBadges(): Boolean { // TODO: Check connectivity, calculate from DB var success = false From bcaa6624c95f511dfcfea0259de9549c7ee23267 Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:22:14 +0200 Subject: [PATCH 44/48] Add missing parameter --- .../readerforselfossv2/repository/RepositoryImpl.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 6c6b0ef..bd8f552 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 @@ -45,13 +45,14 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } override suspend fun getNewerItems(): ArrayList { - // TODO: Check connectivity + // TODO: Check connectivity, use the updatedSince parameter val fetchedItems = api.getItems(displayedItems.type, settings.getString("prefer_api_items_number", "200").toInt(), offset = 0, tagFilter?.tag, sourceFilter?.id?.toLong(), - searchFilter) + searchFilter, + null) if (fetchedItems != null) { items = ArrayList(fetchedItems) @@ -67,7 +68,8 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet offset, tagFilter?.tag, sourceFilter?.id?.toLong(), - searchFilter) + searchFilter, + null) if (fetchedItems != null) { appendItems(fetchedItems) @@ -76,7 +78,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } override suspend fun allItems(itemType: ItemType): List? = - api.getItems(itemType.type, 200, 0, tagFilter?.tag, sourceFilter?.id?.toLong(), searchFilter) + api.getItems(itemType.type, 200, 0, tagFilter?.tag, sourceFilter?.id?.toLong(), searchFilter, null) private fun appendItems(fetchedItems: List) { // TODO: Store in DB if enabled by user From edc705ec8e65d59e75516e81d6b37ac1bfac7e84 Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:23:03 +0200 Subject: [PATCH 45/48] Remove unused class --- .../service/SelfossService.kt | 109 ------------------ 1 file changed, 109 deletions(-) delete mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/SelfossService.kt diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/SelfossService.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/SelfossService.kt deleted file mode 100644 index 365abe9..0000000 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/SelfossService.kt +++ /dev/null @@ -1,109 +0,0 @@ -package bou.amine.apps.readerforselfossv2.service - - -import bou.amine.apps.readerforselfossv2.rest.SelfossApi -import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import kotlinx.coroutines.* - -class SelfossService(val api: SelfossApi, private val dbService: DeviceDataBaseService, private val searchService: SearchService) { - - suspend fun getReadItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean): List? = withContext( - Dispatchers.Default) { - if (isNetworkAvailable) { - val apiItems = readItems( itemsNumber, offset) - // SAVE OR UPDATE IN DB - return@withContext apiItems - } else { - // GET FROM DB - return@withContext emptyList() - } - } - - suspend fun getUnreadItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean): List? = withContext( - Dispatchers.Default) { - if (isNetworkAvailable) { - val apiItems = newItems(itemsNumber, offset) - // SAVE OR UPDATE IN DB - return@withContext apiItems - } else { - // GET FROM DB - return@withContext emptyList() - } - } - - suspend fun getStarredItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean): List? = withContext( - Dispatchers.Default) { - if (isNetworkAvailable) { - val apiItems = starredItems(itemsNumber, offset) - // SAVE OR UPDATE IN DB - return@withContext apiItems - } else { - // GET FROM DB - return@withContext emptyList() - } - } - - suspend fun readAll(ids: List, isNetworkAvailable: Boolean): Boolean { - // Add ids params - var success = false - if (isNetworkAvailable) { - success = api.markAllAsRead(ids)?.isSuccess == true - // SAVE OR UPDATE IN DB - } - // refresh view - return success - } - - suspend fun reloadBadges(isNetworkAvailable: Boolean) = withContext(Dispatchers.Default) { - if (isNetworkAvailable) { - try { - val response = api.stats() - if (response != null) { - searchService.badgeUnread = response.unread - searchService.badgeAll = response.total - searchService.badgeStarred = response.starred - } - } catch (e: Throwable) {} - } else { - dbService.computeBadges() - } - } - - private fun enqueueArticles(response: List?, clearDatabase: Boolean) { - if (response != null) { - if (clearDatabase) { - CoroutineScope(Dispatchers.Default).launch { - dbService.clearDBItems() - } - } - dbService.appendNewItems(response) - } - } - - suspend fun allNewItems(): List? = - readItems(200, 0) - - suspend fun allReadItems(): List? = - newItems(200, 0) - - suspend fun allStarredItems(): List? = - starredItems(200, 0) - - private suspend fun readItems( - itemsNumber: Int, - offset: Int - ): List? = - api.getItems("read", itemsNumber, offset, searchService.tagFilter, searchService.sourceIDFilter, searchService.searchFilter) - - private suspend fun newItems( - itemsNumber: Int, - offset: Int - ): List? = - api.getItems("unread", itemsNumber, offset, searchService.tagFilter, searchService.sourceIDFilter, searchService.searchFilter) - - private suspend fun starredItems( - itemsNumber: Int, - offset: Int - ): List? = - api.getItems("starred", itemsNumber, offset, searchService.tagFilter, searchService.sourceIDFilter, searchService.searchFilter) -} \ No newline at end of file From 7fb7e4509354b2a3c164d9271b4aecc7fe192344 Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:41:43 +0200 Subject: [PATCH 46/48] Simplify items appending operation --- .../bou/amine/apps/readerforselfossv2/android/HomeActivity.kt | 4 ++-- .../apps/readerforselfossv2/repository/RepositoryImpl.kt | 3 +-- 2 files changed, 3 insertions(+), 4 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 5e460e6..2d7e628 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 @@ -893,9 +893,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.swipeRefreshLayout.isRefreshing = true repository.displayedItems = itemType items = if (appendResults) { - repository.getNewerItems() - } else { repository.getOlderItems() + } else { + repository.getNewerItems() } binding.swipeRefreshLayout.isRefreshing = false handleListResult() 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 bd8f552..1c5fe54 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 @@ -83,8 +83,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet private fun appendItems(fetchedItems: List) { // TODO: Store in DB if enabled by user val fetchedIDS = fetchedItems.map { it.id } - val tmpItems = items - tmpItems.removeAll{ it.id in fetchedIDS } + val tmpItems = ArrayList(items.filterNot { it.id in fetchedIDS }) tmpItems.addAll(fetchedItems) sortItems(tmpItems) items = tmpItems From 00ef93f0c561302f5d420fcdca7d658033541fdd Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 11:49:53 +0200 Subject: [PATCH 47/48] Remove unused repository interface --- .../apps/readerforselfossv2/android/MyApp.kt | 4 +- .../repository/Repository.kt | 52 ---------------- .../repository/RepositoryImpl.kt | 60 +++++++++---------- 3 files changed, 31 insertions(+), 85 deletions(-) delete mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt 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 53bb28e..d0e190e 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 @@ -13,7 +13,6 @@ import bou.amine.apps.readerforselfossv2.DI.networkModule import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth import bou.amine.apps.readerforselfossv2.repository.Repository -import bou.amine.apps.readerforselfossv2.repository.RepositoryImpl import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.ftinc.scoop.Scoop @@ -21,13 +20,12 @@ import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader import com.mikepenz.materialdrawer.util.DrawerImageLoader import com.russhwolf.settings.Settings import org.kodein.di.* -import java.util.UUID.randomUUID class MyApp : MultiDexApplication(), DIAware { override val di by DI.lazy { import(networkModule) - bind() with singleton { RepositoryImpl(instance(), instance()) } + bind() with singleton { Repository(instance(), instance()) } } private lateinit var config: Config 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 deleted file mode 100644 index e926a0b..0000000 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt +++ /dev/null @@ -1,52 +0,0 @@ -package bou.amine.apps.readerforselfossv2.repository - -import bou.amine.apps.readerforselfossv2.rest.SelfossModel -import bou.amine.apps.readerforselfossv2.utils.DateUtils -import bou.amine.apps.readerforselfossv2.utils.ItemType - -interface Repository { - - // TODO: remove the items variables in favor of storing everything in the database - var items: ArrayList - var baseUrl: String - var dateUtils: DateUtils - - var displayedItems: ItemType - - // Settings - var itemsCaching: Boolean - - // API - var apiMajorVersion: Int - var badgeUnread: Int - var badgeAll: Int - var badgeStarred: Int - - var tagFilter: SelfossModel.Tag? - var sourceFilter: SelfossModel.Source? - var searchFilter: String? - - suspend fun getNewerItems(): ArrayList - suspend fun getOlderItems(): ArrayList - suspend fun allItems(itemType: ItemType): List? - suspend fun reloadBadges(): Boolean - suspend fun getTags(): List? - suspend fun getSpouts(): Map? - suspend fun getSources(): ArrayList? - suspend fun markAsRead(id: Int): Boolean - suspend fun unmarkAsRead(id: Int): Boolean - suspend fun starr(id: Int): Boolean - suspend fun unstarr(id: Int): Boolean - suspend fun markAllAsRead(ids: List): Boolean - suspend fun createSource(title: String, - url: String, - spout: String, - tags: String, - filter: String): Boolean - suspend fun deleteSource(id: Int): Boolean - suspend fun updateRemote(): Boolean - suspend fun login(): Boolean - fun refreshLoginInformation(url: String, login: String, password: String, - httpLogin: String, httpPassword: String, - isSelfSignedCert: Boolean) -} \ No newline at end of file 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 1c5fe54..c9fed74 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 @@ -11,28 +11,28 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDetailsService) : Repository { +class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService) { val settings = Settings() - override var items = ArrayList() + var items = ArrayList() - override var baseUrl = apiDetails.getBaseUrl() - override lateinit var dateUtils: DateUtils + var baseUrl = apiDetails.getBaseUrl() + lateinit var dateUtils: DateUtils - override var displayedItems = ItemType.UNREAD + var displayedItems = ItemType.UNREAD - override var tagFilter: SelfossModel.Tag? = null - override var sourceFilter: SelfossModel.Source? = null - override var searchFilter: String? = null + var tagFilter: SelfossModel.Tag? = null + var sourceFilter: SelfossModel.Source? = null + var searchFilter: String? = null - override var itemsCaching = settings.getBoolean("items_caching", false) + var itemsCaching = settings.getBoolean("items_caching", false) - override var apiMajorVersion = 0 - override var badgeUnread = 0 + var apiMajorVersion = 0 + var badgeUnread = 0 set(value) {field = if (value < 0) { 0 } else { value } } - override var badgeAll = 0 + var badgeAll = 0 set(value) {field = if (value < 0) { 0 } else { value } } - override var badgeStarred = 0 + var badgeStarred = 0 set(value) {field = if (value < 0) { 0 } else { value } } init { @@ -44,7 +44,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } } - override suspend fun getNewerItems(): ArrayList { + suspend fun getNewerItems(): ArrayList { // TODO: Check connectivity, use the updatedSince parameter val fetchedItems = api.getItems(displayedItems.type, settings.getString("prefer_api_items_number", "200").toInt(), @@ -60,7 +60,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return items } - override suspend fun getOlderItems(): ArrayList { + suspend fun getOlderItems(): ArrayList { // TODO: Check connectivity val offset = items.size val fetchedItems = api.getItems(displayedItems.type, @@ -77,7 +77,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return items } - override suspend fun allItems(itemType: ItemType): List? = + suspend fun allItems(itemType: ItemType): List? = api.getItems(itemType.type, 200, 0, tagFilter?.tag, sourceFilter?.id?.toLong(), searchFilter, null) private fun appendItems(fetchedItems: List) { @@ -93,7 +93,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet items.sortByDescending { dateUtils.parseDate(it.datetime) } } - override suspend fun reloadBadges(): Boolean { + suspend fun reloadBadges(): Boolean { // TODO: Check connectivity, calculate from DB var success = false val response = api.stats() @@ -106,22 +106,22 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override suspend fun getTags(): List? { + suspend fun getTags(): List? { // TODO: Check success, store in DB return api.tags() } - override suspend fun getSpouts(): Map? { + suspend fun getSpouts(): Map? { // TODO: Check success, store in DB return api.spouts() } - override suspend fun getSources(): ArrayList? { + suspend fun getSources(): ArrayList? { // TODO: Check success return api.sources() } - override suspend fun markAsRead(id: Int): Boolean { + suspend fun markAsRead(id: Int): Boolean { // TODO: Check internet connection val success = api.markAsRead(id.toString())?.isSuccess == true @@ -131,7 +131,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override suspend fun unmarkAsRead(id: Int): Boolean { + suspend fun unmarkAsRead(id: Int): Boolean { // TODO: Check internet connection val success = api.unmarkAsRead(id.toString())?.isSuccess == true @@ -141,7 +141,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override suspend fun starr(id: Int): Boolean { + suspend fun starr(id: Int): Boolean { // TODO: Check success, store in DB val success = api.starr(id.toString())?.isSuccess == true @@ -151,7 +151,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override suspend fun unstarr(id: Int): Boolean { + suspend fun unstarr(id: Int): Boolean { // TODO: Check internet connection val success = api.unstarr(id.toString())?.isSuccess == true @@ -161,7 +161,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override suspend fun markAllAsRead(ids: List): Boolean { + suspend fun markAllAsRead(ids: List): Boolean { // TODO: Check Internet connectivity, store in DB val success = api.markAllAsRead(ids.map { it.toString() })?.isSuccess == true @@ -207,7 +207,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet } } - override suspend fun createSource( + suspend fun createSource( title: String, url: String, spout: String, @@ -227,7 +227,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return response != null } - override suspend fun deleteSource(id: Int): Boolean { + suspend fun deleteSource(id: Int): Boolean { // TODO: Check connectivity, store in DB var success = false val response = api.deleteSource(id) @@ -238,13 +238,13 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return success } - override suspend fun updateRemote(): Boolean { + suspend fun updateRemote(): Boolean { // TODO: Handle connectivity issues val response = api.update() return response?.isSuccess ?: false } - override suspend fun login(): Boolean { + suspend fun login(): Boolean { var result = false try { val response = api.login() @@ -257,7 +257,7 @@ class RepositoryImpl(private val api: SelfossApi, private val apiDetails: ApiDet return result } - override fun refreshLoginInformation(url: String, login: String, password: String, + fun refreshLoginInformation(url: String, login: String, password: String, httpLogin: String, httpPassword: String, isSelfSignedCert: Boolean) { settings.putString("url", url) From 32e7a8f19cc4faa3a0b16fe4ff1fbe17363a6bce Mon Sep 17 00:00:00 2001 From: davide Date: Tue, 16 Aug 2022 12:02:20 +0200 Subject: [PATCH 48/48] Simplify alignment menu logic --- .../android/ReaderActivity.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt index 021ffde..f4eb03d 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ReaderActivity.kt @@ -150,7 +150,8 @@ class ReaderActivity : AppCompatActivity(), DIAware { } } - private fun alignmentMenu(showJustify: Boolean) { + private fun alignmentMenu() { + val showJustify = activeAlignment == ALIGN_LEFT toolbarMenu.findItem(R.id.align_left).isVisible = !showJustify toolbarMenu.findItem(R.id.align_justify).isVisible = showJustify } @@ -165,11 +166,7 @@ class ReaderActivity : AppCompatActivity(), DIAware { } else { canFavorite() } - if (activeAlignment == JUSTIFY) { - alignmentMenu(false) - } else { - alignmentMenu(true) - } + alignmentMenu() binding.pager.registerOnPageChangeCallback( object : ViewPager2.OnPageChangeCallback() { @@ -223,19 +220,24 @@ class ReaderActivity : AppCompatActivity(), DIAware { } } R.id.align_left -> { - settings.putInt("text_align", ALIGN_LEFT) - alignmentMenu(true) + activeAlignment = ALIGN_LEFT + switchAlignmentSetting() refreshFragment() } R.id.align_justify -> { - settings.putInt("text_align", JUSTIFY) - alignmentMenu(false) + activeAlignment = JUSTIFY + switchAlignmentSetting() refreshFragment() } } return super.onOptionsItemSelected(item) } + private fun switchAlignmentSetting() { + settings.putInt("text_align", activeAlignment) + alignmentMenu() + } + private fun refreshFragment() { finish() overridePendingTransition(0, 0)