From 553103408664bb5b34907cde6e92a303ea72edf5 Mon Sep 17 00:00:00 2001 From: aminecmi Date: Wed, 24 Aug 2022 22:15:42 +0200 Subject: [PATCH 1/8] WIP: Big settings cleaning. --- .../readerforselfoss/AddSourceEspressoTest.kt | 3 - .../HomeActivityEspressoTest.kt | 102 ---------- .../LoginActivityEspressoTest.kt | 180 ------------------ .../MainActivityEspressoTest.kt | 81 -------- .../apps/amine/bou/readerforselfoss/Utils.kt | 29 --- .../android/AddSourceActivity.kt | 7 +- .../android/HomeActivity.kt | 40 ++-- .../apps/readerforselfossv2/android/MyApp.kt | 11 +- .../android/adapters/ItemCardAdapter.kt | 5 +- .../android/adapters/ItemListAdapter.kt | 5 +- .../android/adapters/ItemsAdapter.kt | 2 - .../android/adapters/SourcesListAdapter.kt | 5 +- .../android/background/background.kt | 12 +- .../android/fragments/ArticleFragment.kt | 8 +- .../android/settings/SettingsActivity.kt | 8 +- .../android/utils/Config.kt | 62 ------ .../android/utils/glide/GlideUtils.kt | 37 +--- .../readerforselfossv2/utils/DateUtils.kt | 7 +- .../apps/readerforselfossv2/DI/modules.kt | 3 +- .../repository/RepositoryImpl.kt | 18 +- .../readerforselfossv2/rest/SelfossApi.kt | 10 +- .../service/ApiDetailsService.kt | 101 +++++++++- .../service/ApiDetailsServiceImpl.kt | 52 ----- .../readerforselfossv2/utils/DateUtils.kt | 3 +- .../readerforselfossv2/utils/DateUtils.kt | 4 +- .../readerforselfossv2/utils/DateUtils.kt | 4 +- 26 files changed, 170 insertions(+), 629 deletions(-) delete mode 100644 androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/AddSourceEspressoTest.kt delete mode 100644 androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/HomeActivityEspressoTest.kt delete mode 100644 androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/LoginActivityEspressoTest.kt delete mode 100644 androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/MainActivityEspressoTest.kt delete mode 100644 androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/Utils.kt delete mode 100644 androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/Config.kt delete mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt diff --git a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/AddSourceEspressoTest.kt b/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/AddSourceEspressoTest.kt deleted file mode 100644 index 11a8688..0000000 --- a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/AddSourceEspressoTest.kt +++ /dev/null @@ -1,3 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android - -// TODO: test source adding \ No newline at end of file diff --git a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/HomeActivityEspressoTest.kt b/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/HomeActivityEspressoTest.kt deleted file mode 100644 index 79cd207..0000000 --- a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/HomeActivityEspressoTest.kt +++ /dev/null @@ -1,102 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android - -import android.content.Context -import android.content.Intent -import androidx.test.InstrumentationRegistry -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.action.ViewActions.closeSoftKeyboard -import androidx.test.espresso.action.ViewActions.pressKey -import androidx.test.espresso.action.ViewActions.typeText -import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.Intents.intended -import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed -import androidx.test.espresso.matcher.ViewMatchers.withContentDescription -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText -import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 -import android.view.KeyEvent -import androidx.test.espresso.matcher.RootMatchers.isDialog -import bou.amine.apps.readerforselfossv2.android.HomeActivity -import bou.amine.apps.readerforselfossv2.android.LoginActivity -import bou.amine.apps.readerforselfossv2.android.utils.Config -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class HomeActivityEspressoTest { - lateinit var context: Context - - @Rule @JvmField - val rule = ActivityTestRule(HomeActivity::class.java, true, false) - - @Before - fun clearData() { - context = InstrumentationRegistry.getInstrumentation().targetContext - - val editor = - context - .getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - .edit() - editor.clear() - - editor.putString("url", BuildConfig.LOGIN_URL) - editor.putString("login", BuildConfig.LOGIN_USERNAME) - editor.putString("password", BuildConfig.LOGIN_PASSWORD) - - editor.commit() - - Intents.init() - } - - @Test - fun menuItems() { - - rule.launchActivity(Intent()) - - onView( - withMenu( - id = R.id.action_search, - titleId = R.string.menu_home_search - ) - ).perform(click()) - - onView(withId(R.id.search_bar)).check(matches(isDisplayed())) - - onView(withId(R.id.search_src_text)).perform( - typeText("android"), - pressKey(KeyEvent.KEYCODE_SEARCH), - closeSoftKeyboard() - ) - - onView(withContentDescription(R.string.abc_toolbar_collapse_description)).perform(click()) - - openActionBarOverflowOrOptionsMenu(context) - - onView(withMenu(id = R.id.refresh, titleId = R.string.menu_home_refresh)) - .perform(click()) - - onView(withText(android.R.string.ok)) - .inRoot(isDialog()).check(matches(isDisplayed())).perform(click()) - - openActionBarOverflowOrOptionsMenu(context) - - onView(withText(R.string.action_disconnect)).perform(click()) - - intended(hasComponent(LoginActivity::class.java.name)) - } - - // TODO: test articles opening and actions for cards and lists - - @After - fun releaseIntents() { - Intents.release() - } -} \ No newline at end of file diff --git a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/LoginActivityEspressoTest.kt b/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/LoginActivityEspressoTest.kt deleted file mode 100644 index e64adb3..0000000 --- a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/LoginActivityEspressoTest.kt +++ /dev/null @@ -1,180 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android - -import android.content.Context -import android.content.Intent -import androidx.test.InstrumentationRegistry -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.action.ViewActions.closeSoftKeyboard -import androidx.test.espresso.action.ViewActions.pressBack -import androidx.test.espresso.action.ViewActions.typeText -import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.Intents.intended -import androidx.test.espresso.intent.Intents.times -import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent -import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.espresso.matcher.ViewMatchers.isRoot -import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText -import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 -import bou.amine.apps.readerforselfossv2.android.HomeActivity -import bou.amine.apps.readerforselfossv2.android.LoginActivity -import bou.amine.apps.readerforselfossv2.android.utils.Config -import com.mikepenz.aboutlibraries.ui.LibsActivity -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class LoginActivityEspressoTest { - - @Rule @JvmField - val rule = ActivityTestRule(LoginActivity::class.java, true, false) - - private lateinit var context: Context - private lateinit var url: String - private lateinit var username: String - private lateinit var password: String - - @Before - fun setUp() { - context = InstrumentationRegistry.getInstrumentation().targetContext - val editor = - context - .getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE) - .edit() - editor.clear() - editor.commit() - - - url = BuildConfig.LOGIN_URL - username = BuildConfig.LOGIN_USERNAME - password = BuildConfig.LOGIN_PASSWORD - - Intents.init() - } - - @Test - fun menuItems() { - - rule.launchActivity(Intent()) - - openActionBarOverflowOrOptionsMenu(context) - - onView(withText(R.string.action_about)).perform(click()) - - intended(hasComponent(LibsActivity::class.java.name), times(1)) - - onView(isRoot()).perform(pressBack()) - - intended(hasComponent(LoginActivity::class.java.name)) - } - - @Test - fun wrongLoginUrl() { - rule.launchActivity(Intent()) - - onView(withId(R.id.loginProgress)) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))) - - onView(withId(R.id.urlView)).perform(click()).perform(typeText("WRONGURL")) - - onView(withId(R.id.signInButton)).perform(click()) - - onView(withId(R.id.urlView)).check(matches(isHintOrErrorEnabled())) - } - - // TODO: Add tests for multiple false urls with dialog - - @Test - fun emptyAuthData() { - - rule.launchActivity(Intent()) - - onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard()) - - onView(withId(R.id.withLogin)).perform(click()) - - onView(withId(R.id.signInButton)).perform(click()) - - onView(withId(R.id.loginView)).check(matches(isHintOrErrorEnabled())) - onView(withId(R.id.passwordView)).check(matches(isHintOrErrorEnabled())) - - onView(withId(R.id.loginView)).perform(click()).perform( - typeText(username), - closeSoftKeyboard() - ) - - onView(withId(R.id.passwordView)).check(matches(isHintOrErrorEnabled())) - - onView(withId(R.id.signInButton)).perform(click()) - - onView(withId(R.id.passwordView)).check( - matches( - isHintOrErrorEnabled() - ) - ) - } - - @Test - fun wrongAuthData() { - - rule.launchActivity(Intent()) - - onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard()) - - onView(withId(R.id.withLogin)).perform(click()) - - onView(withId(R.id.loginView)).perform(click()).perform( - typeText(username), - closeSoftKeyboard() - ) - - onView(withId(R.id.passwordView)).perform(click()).perform( - typeText("WRONGPASS"), - closeSoftKeyboard() - ) - - onView(withId(R.id.signInButton)).perform(click()) - - onView(withId(R.id.urlView)).check(matches(isHintOrErrorEnabled())) - onView(withId(R.id.loginView)).check(matches(isHintOrErrorEnabled())) - onView(withId(R.id.passwordView)).check(matches(isHintOrErrorEnabled())) - } - - @Test - fun workingAuth() { - - rule.launchActivity(Intent()) - - onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard()) - - onView(withId(R.id.withLogin)).perform(click()) - - onView(withId(R.id.loginView)).perform(click()).perform( - typeText(username), - closeSoftKeyboard() - ) - - onView(withId(R.id.passwordView)).perform(click()).perform( - typeText(password), - closeSoftKeyboard() - ) - - onView(withId(R.id.signInButton)).perform(click()) - - Thread.sleep(2000) - intended(hasComponent(HomeActivity::class.java.name)) - } - - @After - fun releaseIntents() { - Intents.release() - } -} \ No newline at end of file diff --git a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/MainActivityEspressoTest.kt b/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/MainActivityEspressoTest.kt deleted file mode 100644 index 1400a0e..0000000 --- a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/MainActivityEspressoTest.kt +++ /dev/null @@ -1,81 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android - -import android.content.Context -import android.content.Intent -import android.content.SharedPreferences -import androidx.test.InstrumentationRegistry.getInstrumentation -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.Intents.intended -import androidx.test.espresso.intent.Intents.times -import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent -import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 -import bou.amine.apps.readerforselfossv2.android.HomeActivity -import bou.amine.apps.readerforselfossv2.android.LoginActivity -import bou.amine.apps.readerforselfossv2.android.MainActivity -import bou.amine.apps.readerforselfossv2.android.utils.Config -import org.junit.After - -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class MainActivityEspressoTest { - - lateinit var intent: Intent - lateinit var preferencesEditor: SharedPreferences.Editor - private lateinit var url: String - private lateinit var username: String - private lateinit var password: String - - @Rule @JvmField - val rule = ActivityTestRule(MainActivity::class.java, true, false) - - @Before - fun setUp() { - intent = Intent() - val context = getInstrumentation().targetContext - - // create a SharedPreferences editor - preferencesEditor = context.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE).edit() - - url = BuildConfig.LOGIN_URL - username = BuildConfig.LOGIN_USERNAME - password = BuildConfig.LOGIN_PASSWORD - - Intents.init() - } - - @Test - fun checkFirstOpenLaunchesIntro() { - preferencesEditor.putString("url", "") - preferencesEditor.putString("password", "") - preferencesEditor.putString("login", "") - preferencesEditor.commit() - - rule.launchActivity(intent) - - intended(hasComponent(LoginActivity::class.java.name)) - intended(hasComponent(HomeActivity::class.java.name), times(0)) - } - - @Test - fun checkNotFirstOpenLaunchesLogin() { - preferencesEditor.putString("url", url) - preferencesEditor.putString("password", password) - preferencesEditor.putString("login", username) - preferencesEditor.commit() - - rule.launchActivity(intent) - - intended(hasComponent(MainActivity::class.java.name)) - intended(hasComponent(HomeActivity::class.java.name)) - } - - @After - fun releaseIntents() { - Intents.release() - } -} \ No newline at end of file diff --git a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/Utils.kt b/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/Utils.kt deleted file mode 100644 index b8fd12a..0000000 --- a/androidApp/src/androidTest/java/apps/amine/bou/readerforselfoss/Utils.kt +++ /dev/null @@ -1,29 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android - -import androidx.test.espresso.matcher.ViewMatchers -import android.view.View -import android.widget.EditText -import org.hamcrest.Description -import org.hamcrest.Matcher -import org.hamcrest.Matchers -import org.hamcrest.TypeSafeMatcher - -fun isHintOrErrorEnabled(): Matcher = - object : TypeSafeMatcher() { - override fun describeTo(description: Description?) { - } - - override fun matchesSafely(item: View?): Boolean { - if (item !is EditText) { - return false - } - - return item.error.isNotEmpty() - } - } - -fun withMenu(id: Int, titleId: Int): Matcher = - Matchers.anyOf( - ViewMatchers.withId(id), - ViewMatchers.withText(titleId) - ) 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 7df13e1..fc9acb5 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 @@ -9,10 +9,10 @@ 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.model.NetworkUnavailableException import bou.amine.apps.readerforselfossv2.repository.Repository +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.ftinc.scoop.Scoop import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -31,6 +31,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { override val di by closestDI() private val repository : Repository by instance() + private val apiDetailsService : ApiDetailsService by instance() override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@AddSourceActivity) @@ -81,9 +82,9 @@ class AddSourceActivity : AppCompatActivity(), DIAware { override fun onResume() { super.onResume() - val config = Config() - if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid(this@AddSourceActivity)) { + val baseUrl = apiDetailsService.getBaseUrl() + if (baseUrl.isEmpty() || !baseUrl.isBaseUrlValid(this@AddSourceActivity)) { mustLoginToAddSource() } else { handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer) 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 87b5b67..51e32ca 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 @@ -30,13 +30,12 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityHomeBinding import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity 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.bottombar.maybeShow import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper -import bou.amine.apps.readerforselfossv2.dao.ACTION import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import bou.amine.apps.readerforselfossv2.utils.* import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationItem @@ -84,10 +83,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private var displayUnreadCount = false private var displayAllCount = false private var fullHeightCards: Boolean = false - private var itemsNumber: Int = 200 private var elementsShown: ItemType = ItemType.UNREAD - private var displayAccountHeader: Boolean = false - private var infiniteScroll: Boolean = false private var lastFetchDone: Boolean = false private var updateSources: Boolean = true private var markOnScroll: Boolean = false @@ -114,8 +110,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private lateinit var tagsBadge: Map - private lateinit var config: Config - override val di by closestDI() private val repository : Repository by instance() @@ -128,7 +122,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@HomeActivity) - config = Config() super.onCreate(savedInstanceState) binding = ActivityHomeBinding.inflate(layoutInflater) @@ -308,7 +301,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar reloadLayoutManager() - if (!infiniteScroll) { + if (!settings.getBoolean("infinite_loading", false)) { binding.recyclerView.setHasFixedSize(true) } else { handleInfiniteScroll() @@ -331,15 +324,14 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } private fun handleSettings() { + // TODO : clean this 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() - displayAccountHeader = settings.getBoolean("account_header_displaying", false) - infiniteScroll = settings.getBoolean("infinite_loading", false) + updateSources = settings.getBoolean("update_sources", true) markOnScroll = settings.getBoolean("mark_on_scroll", false) hiddenTags = if (settings.getString("hidden_tags", "").isNotEmpty()) { @@ -409,7 +401,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.drawerContainer.addDrawerListener(drawerListener) - displayAccountHeader = + val displayAccountHeader = settings.getBoolean("account_header_displaying", false) binding.mainDrawer.addStickyFooterItem( @@ -418,7 +410,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar iconRes = R.drawable.ic_bug_report_black_24dp isIconTinted = true onDrawerItemClickListener = { _, _, _ -> - val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(Config.trackerUrl)) + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(ApiDetailsService.trackerUrl)) startActivity(browserIntent) false } @@ -451,6 +443,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } // TODO: refactor this. + // TODO: use updateSources private fun handleDrawerItems() { tagsBadge = emptyMap() fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) { @@ -875,11 +868,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar this, items, customTabActivityHelper, - internalBrowser, - articleViewer, - fullHeightCards, + internalBrowser, // TODO remove and use from apidetailsservice + articleViewer, // TODO remove and use from apidetailsservice + fullHeightCards, // TODO remove and use from apidetailsservice appColors, - config ) { updateItems(it) } @@ -889,10 +881,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar this, items, customTabActivityHelper, - internalBrowser, - articleViewer, + internalBrowser, // TODO remove and use from apidetailsservice + articleViewer, // TODO remove and use from apidetailsservice appColors, - config ) { updateItems(it) } @@ -1047,7 +1038,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar return true } R.id.action_disconnect -> { - return Config.logoutAndRedirect(this, this@HomeActivity) + val settings = Settings() + settings.clear() + val intent = Intent(this, LoginActivity::class.java) + this.startActivity(intent) + this@HomeActivity.finish() + return true } else -> return super.onOptionsItemSelected(item) } 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 3345124..9ad4e7e 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 @@ -14,12 +14,11 @@ import androidx.lifecycle.ProcessLifecycleOwner 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.android.viewmodel.AppViewModel import bou.amine.apps.readerforselfossv2.dao.DriverFactory import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB import bou.amine.apps.readerforselfossv2.repository.Repository +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.ftinc.scoop.Scoop @@ -49,13 +48,11 @@ class MyApp : MultiDexApplication(), DIAware { private val viewModel: AppViewModel by instance() private val connectivityStatus: ConnectivityStatus by instance() private val driverFactory: DriverFactory by instance() - private lateinit var config: Config private lateinit var settings : Settings override fun onCreate() { super.onCreate() Napier.base(DebugAntilog()) - config = Config() settings = Settings() initDrawerImageLoader() @@ -93,11 +90,11 @@ class MyApp : MultiDexApplication(), DIAware { val name = getString(R.string.notification_channel_sync) val importance = NotificationManager.IMPORTANCE_LOW - val mChannel = NotificationChannel(Config.syncChannelId, name, importance) + val mChannel = NotificationChannel(ApiDetailsService.syncChannelId, name, importance) val newItemsChannelname = getString(R.string.new_items_channel_sync) val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT - val newItemsChannelmChannel = NotificationChannel(Config.newItemsChannelId, newItemsChannelname, newItemsChannelimportance) + val newItemsChannelmChannel = NotificationChannel(ApiDetailsService.newItemsChannelId, newItemsChannelname, newItemsChannelimportance) notificationManager.createNotificationChannel(mChannel) notificationManager.createNotificationChannel(newItemsChannelmChannel) @@ -108,7 +105,7 @@ class MyApp : MultiDexApplication(), DIAware { DrawerImageLoader.init(object : AbstractDrawerImageLoader() { override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) { Glide.with(imageView.context) - .loadMaybeBasicAuth(config, uri.toString()) + .load(uri.toString()) .apply(RequestOptions.fitCenterTransform().placeholder(placeholder)) .into(imageView) } 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 a7b42d6..36ef496 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 config: Config, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { private val c: Context = app.baseContext @@ -78,7 +77,7 @@ class ItemCardAdapter( binding.itemImage.setImageDrawable(null) } else { binding.itemImage.visibility = View.VISIBLE - c.bitmapCenterCrop(config, itm.getThumbnail(repository.baseUrl), binding.itemImage) + c.bitmapCenterCrop(itm.getThumbnail(repository.baseUrl), binding.itemImage) } if (itm.getIcon(repository.baseUrl).isEmpty()) { @@ -91,7 +90,7 @@ class ItemCardAdapter( .build(itm.title.getHtmlDecoded().toTextDrawableString(), color) binding.sourceImage.setImageDrawable(drawable) } else { - c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.sourceImage) + c.circularBitmapDrawable(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 27839a4..6a9f30a 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 @@ -30,7 +30,6 @@ class ItemListAdapter( private val internalBrowser: Boolean, private val articleViewer: Boolean, override val appColors: AppColors, - override val config: Config, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { private val generator: ColorGenerator = ColorGenerator.MATERIAL @@ -69,10 +68,10 @@ class ItemListAdapter( binding.itemImage.setImageDrawable(drawable) } else { - c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.itemImage) + c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.itemImage) } } else { - c.bitmapCenterCrop(config, itm.getThumbnail(repository.baseUrl), binding.itemImage) + c.bitmapCenterCrop(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 7dea71a..99b8002 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 @@ -6,7 +6,6 @@ import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R 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.model.SelfossModel import bou.amine.apps.readerforselfossv2.utils.ItemType @@ -21,7 +20,6 @@ abstract class ItemsAdapter : RecyclerView.Adapte abstract val repository: Repository abstract val app: Activity abstract val appColors: AppColors - abstract val config: Config abstract val updateItems: (ArrayList) -> Unit fun updateAllItems(items: ArrayList) { 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 187af5a..7d10979 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 @@ -11,7 +11,6 @@ import androidx.recyclerview.widget.RecyclerView import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.SourceListItemBinding import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString -import bou.amine.apps.readerforselfossv2.android.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel @@ -33,7 +32,6 @@ class SourcesListAdapter( ) : 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) @@ -46,7 +44,6 @@ class SourcesListAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val itm = items[position] - config = Config() if (itm.getIcon(repository.baseUrl).isEmpty()) { val color = generator.getColor(itm.title.getHtmlDecoded()) @@ -58,7 +55,7 @@ class SourcesListAdapter( .build(itm.title.getHtmlDecoded().toTextDrawableString(), color) binding.itemImage.setImageDrawable(drawable) } else { - c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.itemImage) + c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.itemImage) } binding.sourceTitle.text = itm.title.getHtmlDecoded() 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 907338d..c86de60 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 @@ -14,11 +14,10 @@ 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.utils.Config import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAccessible -import bou.amine.apps.readerforselfossv2.dao.ACTION import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -27,7 +26,6 @@ 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), DIAware { @@ -44,12 +42,12 @@ override fun doWork(): Result { applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notification = - NotificationCompat.Builder(applicationContext, Config.syncChannelId) + NotificationCompat.Builder(applicationContext, ApiDetailsService.syncChannelId) .setContentTitle(context.getString(R.string.loading_notification_title)) .setContentText(context.getString(R.string.loading_notification_text)) .setOngoing(true) .setPriority(PRIORITY_LOW) - .setChannelId(Config.syncChannelId) + .setChannelId(ApiDetailsService.syncChannelId) .setSmallIcon(R.drawable.ic_stat_cloud_download_black_24dp) notificationManager.notify(1, notification.build()) @@ -89,7 +87,7 @@ override fun doWork(): Result { val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, pflags) val newItemsNotification = - NotificationCompat.Builder(applicationContext, Config.newItemsChannelId) + NotificationCompat.Builder(applicationContext, ApiDetailsService.newItemsChannelId) .setContentTitle(context.getString(R.string.new_items_notification_title)) .setContentText( context.getString( @@ -98,7 +96,7 @@ override fun doWork(): Result { ) ) .setPriority(PRIORITY_DEFAULT) - .setChannelId(Config.newItemsChannelId) + .setChannelId(ApiDetailsService.newItemsChannelId) .setContentIntent(pendingIntent) .setAutoCancel(true) .setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp) 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 7c9f602..c893954 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 @@ -29,7 +29,6 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.* import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream -import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded @@ -70,7 +69,6 @@ class ArticleFragment : Fragment(), DIAware { private lateinit var fab: FloatingActionButton private lateinit var appColors: AppColors private lateinit var textAlignment: String - private lateinit var config: Config private var _binding: FragmentArticleBinding? = null private val binding get() = _binding!! @@ -93,7 +91,6 @@ class ArticleFragment : Fragment(), DIAware { override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(requireActivity()) - config = Config() super.onCreate(savedInstanceState) @@ -213,7 +210,7 @@ class ArticleFragment : Fragment(), DIAware { Glide .with(requireContext()) .asBitmap() - .loadMaybeBasicAuth(config, contentImage) + .load(contentImage) .apply(RequestOptions.fitCenterTransform()) .into(binding.imageView) } else { @@ -307,8 +304,7 @@ class ArticleFragment : Fragment(), DIAware { Glide .with(requireContext()) .asBitmap() - .loadMaybeBasicAuth( - config, + .load( response.body()!!.lead_image_url.orEmpty() ) .apply(RequestOptions.fitCenterTransform()) 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 f4382ce..050e6a8 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 @@ -15,7 +15,7 @@ import androidx.preference.PreferenceFragmentCompat import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding import bou.amine.apps.readerforselfossv2.android.themes.Toppings -import bou.amine.apps.readerforselfossv2.android.utils.Config +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import com.ftinc.scoop.Scoop import com.russhwolf.settings.Settings import java.lang.NumberFormatException @@ -196,17 +196,17 @@ class SettingsActivity : AppCompatActivity(), setPreferencesFromResource(R.xml.pref_links, rootKey) preferenceManager.findPreference("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(Config.trackerUrl)) + openUrl(Uri.parse(ApiDetailsService.trackerUrl)) true } preferenceManager.findPreference("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(Config.sourceUrl)) + openUrl(Uri.parse(ApiDetailsService.sourceUrl)) false } preferenceManager.findPreference("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(Config.translationUrl)) + openUrl(Uri.parse(ApiDetailsService.translationUrl)) 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 deleted file mode 100644 index 9ce7ede..0000000 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/Config.kt +++ /dev/null @@ -1,62 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android.utils - -import android.app.Activity -import android.content.Context -import android.content.Intent -import bou.amine.apps.readerforselfossv2.android.LoginActivity -import com.russhwolf.settings.Settings - -class Config { - - val settings = Settings() - - val baseUrl: String - get() = settings.getString("url", "") - - val userLogin: String - get() = settings.getString("login", "") - - val userPassword: String - get() = settings.getString("password", "") - - val httpUserLogin: String - get() = settings.getString("httpUserName", "") - - val httpUserPassword: String - get() = settings.getString("httpPassword", "") - - companion object { - const val settingsName = "paramsselfoss" - - const val feedbackEmail = "aminecmi@pm.me.com" - - const val translationUrl = "https://crwd.in/readerforselfoss" - - const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform" - - const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" - - const val syncChannelId = "sync-channel-id" - - const val newItemsChannelId = "new-items-channel-id" - - var apiVersion = 0 - - /* Execute logout and clear all settings to default */ - fun logoutAndRedirect( - c: Context, - callingActivity: Activity, - baseUrlFail: Boolean = false - ): Boolean { - val settings = Settings() - settings.clear() - val intent = Intent(c, LoginActivity::class.java) - if (baseUrlFail) { - intent.putExtra("baseUrlFail", baseUrlFail) - } - c.startActivity(intent) - callingActivity.finish() - return true - } - } -} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/GlideUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/GlideUtils.kt index be63485..5d91e62 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/GlideUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/GlideUtils.kt @@ -2,33 +2,26 @@ package bou.amine.apps.readerforselfossv2.android.utils.glide import android.content.Context import android.graphics.Bitmap -import android.graphics.drawable.Drawable -import android.util.Base64 -import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import android.widget.ImageView -import bou.amine.apps.readerforselfossv2.android.utils.Config +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import com.bumptech.glide.Glide -import com.bumptech.glide.RequestBuilder -import com.bumptech.glide.RequestManager -import com.bumptech.glide.load.model.GlideUrl -import com.bumptech.glide.load.model.LazyHeaders import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.BitmapImageViewTarget import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream -fun Context.bitmapCenterCrop(config: Config, url: String, iv: ImageView) = +fun Context.bitmapCenterCrop(url: String, iv: ImageView) = Glide.with(this) .asBitmap() - .loadMaybeBasicAuth(config, url) + .load(url) .apply(RequestOptions.centerCropTransform()) .into(iv) -fun Context.circularBitmapDrawable(config: Config, url: String, iv: ImageView) = +fun Context.circularBitmapDrawable(url: String, iv: ImageView) = Glide.with(this) .asBitmap() - .loadMaybeBasicAuth(config, url) + .load(url) .apply(RequestOptions.centerCropTransform()) .into(object : BitmapImageViewTarget(iv) { override fun setResource(resource: Bitmap?) { @@ -41,26 +34,6 @@ fun Context.circularBitmapDrawable(config: Config, url: String, iv: ImageView) = } }) -fun RequestBuilder.loadMaybeBasicAuth(config: Config, url: String): RequestBuilder { - val builder: LazyHeaders.Builder = LazyHeaders.Builder() - if (config.httpUserLogin.isNotEmpty() || config.httpUserPassword.isNotEmpty()) { - val basicAuth = "Basic " + Base64.encodeToString("${config.httpUserLogin}:${config.httpUserPassword}".toByteArray(), Base64.NO_WRAP) - builder.addHeader("Authorization", basicAuth) - } - val glideUrl = GlideUrl(url, builder.build()) - return this.load(glideUrl) -} - -fun RequestManager.loadMaybeBasicAuth(config: Config, url: String): RequestBuilder { - val builder: LazyHeaders.Builder = LazyHeaders.Builder() - if (config.httpUserLogin.isNotEmpty() || config.httpUserPassword.isNotEmpty()) { - val basicAuth = "Basic " + Base64.encodeToString("${config.httpUserLogin}:${config.httpUserPassword}".toByteArray(), Base64.NO_WRAP) - builder.addHeader("Authorization", basicAuth) - } - val glideUrl = GlideUrl(url, builder.build()) - return this.load(glideUrl) -} - fun getBitmapInputStream(bitmap:Bitmap,compressFormat: Bitmap.CompressFormat): InputStream { val byteArrayOutputStream = ByteArrayOutputStream() bitmap.compress(compressFormat, 80, byteArrayOutputStream) diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 064ff81..7eee3b2 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,18 +1,21 @@ package bou.amine.apps.readerforselfossv2.utils import android.text.format.DateUtils +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import java.time.Instant import java.time.LocalDateTime import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter -actual class DateUtils actual constructor(private val apiMajorVersion: Int) { +actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) { + val ads: ApiDetailsService = apiDetailsService // TODO: why is this needed now ? + actual fun parseDate(dateString: String): Long { val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss" - return if (apiMajorVersion >= 4) { + return if (ads.getApiVersion() >= 4) { OffsetDateTime.parse(dateString).toInstant().toEpochMilli() } else { LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant( 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 2beba39..ebcb8f1 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 @@ -2,13 +2,12 @@ package bou.amine.apps.readerforselfossv2.DI import bou.amine.apps.readerforselfossv2.rest.SelfossApi 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 { ApiDetailsService() } bind() with singleton { SelfossApi(instance()) } } \ 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 cc8a878..d9e4254 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 @@ -32,7 +32,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails var itemsCaching = settings.getBoolean("items_caching", false) var offlineOverride = false - var apiMajorVersion = 0 var badgeUnread = 0 set(value) {field = if (value < 0) { 0 } else { value } } var badgeAll = 0 @@ -44,6 +43,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found CoroutineScope(Dispatchers.Main).launch { updateApiVersion() + dateUtils = DateUtils(apiDetails) reloadBadges() } } @@ -54,7 +54,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails if (isNetworkAvailable()) { fetchedItems = api.getItems( displayedItems.type, - settings.getString("prefer_api_items_number", "200").toInt(), offset = 0, tagFilter?.tag, sourceFilter?.id?.toLong(), @@ -84,7 +83,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails val offset = items.size fetchedItems = api.getItems( displayedItems.type, - settings.getString("prefer_api_items_number", "200").toInt(), offset, tagFilter?.tag, sourceFilter?.id?.toLong(), @@ -104,12 +102,12 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return if (isNetworkAvailable()) { api.getItems( itemType.type, - 200, 0, tagFilter?.tag, sourceFilter?.id?.toLong(), searchFilter, - null + null, + 200 ) } else { emptyList() @@ -309,7 +307,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails spout, tags, filter, - apiMajorVersion + apiDetails.getApiVersion() )?.isSuccess == true } @@ -366,13 +364,13 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails } private suspend fun updateApiVersion() { - apiMajorVersion = settings.getInt("apiVersionMajor", 0) + val apiMajorVersion = apiDetails.getApiVersion() if (isNetworkAvailable()) { val fetchedVersion = api.version() - if (fetchedVersion != null) { - apiMajorVersion = fetchedVersion.getApiMajorVersion() - settings.putInt("apiVersionMajor", apiMajorVersion) + if (fetchedVersion != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) { + settings.putInt("apiVersionMajor", fetchedVersion.getApiMajorVersion()) + apiDetails.refreshApiVersion() } } dateUtils = DateUtils(apiMajorVersion) diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt index 084d987..1a2c56e 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt @@ -4,6 +4,7 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.service.ApiDetailsService import io.ktor.client.* import io.ktor.client.call.* +import io.ktor.client.plugins.* import io.ktor.client.plugins.cache.* import io.ktor.client.request.* import io.ktor.client.request.forms.* @@ -35,6 +36,9 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { } level = LogLevel.ALL } + install(HttpTimeout) { + requestTimeoutMillis = apiDetailsService.getApiTimeout() + } /* TODO: Auth as basic if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) { @@ -69,12 +73,12 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { suspend fun getItems( type: String, - items: Int, offset: Int, tag: String?, source: Long?, search: String?, - updatedSince: String? + updatedSince: String?, + items: Int? = null ): List? = client.get(url("/items")) { parameter("username", apiDetailsService.getUserName()) @@ -84,7 +88,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { parameter("source", source) parameter("search", search) parameter("updatedsince", updatedSince) - parameter("items", items) + parameter("items", items ?: apiDetailsService.getItemsNumber()) parameter("offset", offset) }.body() 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 48e477e..6a48792 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 @@ -1,10 +1,97 @@ package bou.amine.apps.readerforselfossv2.service -interface ApiDetailsService { - fun logApiCalls(message: String) - fun getApiVersion(): Int - fun getBaseUrl(): String - fun getUserName(): String - fun getPassword(): String - fun refresh() +import com.russhwolf.settings.Settings +import io.github.aakira.napier.Napier +import io.ktor.client.plugins.* + +class ApiDetailsService { + val settings: Settings = Settings() + private var _apiVersion: Int = -1 + private var _baseUrl: String = "" + private var _userName: String = "" + private var _password: String = "" + private var _itemsNumber: Int? = null + private var _apiTimeout: Long? = null + + fun logApiCalls(message: String) { + Napier.d(message, tag = "LogApiCalls") + } + + + fun getApiVersion(): Int { + if (_apiVersion == -1) { + refreshApiVersion() + return _apiVersion + } + return _apiVersion + } + + fun refreshApiVersion() { + _apiVersion = settings.getInt("apiVersionMajor", -1) + } + + fun getBaseUrl(): String { + if (_baseUrl.isEmpty()) { + _baseUrl = settings.getString("url", "") + } + return _baseUrl + } + + fun getUserName(): String { + if (_userName.isEmpty()) { + _userName = settings.getString("login", "") + } + return _userName + } + + fun getPassword(): String { + if (_password.isEmpty()) { + _password = settings.getString("password", "") + } + return _password + } + + fun getItemsNumber(): Int { + if (_itemsNumber == null) { + refreshItemsNumber() + } + return _itemsNumber!! + } + + fun refreshItemsNumber() { + _itemsNumber = settings.getString("prefer_api_items_number", "200").toInt() + } + + fun getApiTimeout(): Long { + if (_apiTimeout == null) { + refreshApiTimeout() + } + return _apiTimeout!! + } + + fun refreshApiTimeout() { + val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS) + _apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS + } + + fun refresh() { + _password = settings.getString("password", "") + _userName = settings.getString("login", "") + _baseUrl = settings.getString("url", "") + refreshApiVersion() + refreshItemsNumber() + refreshApiTimeout() + } + + companion object { + const val translationUrl = "https://crwd.in/readerforselfoss" + + const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform" + + const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" + + const val syncChannelId = "sync-channel-id" + + const val newItemsChannelId = "new-items-channel-id" + } } \ No newline at end of file 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 deleted file mode 100644 index 6256094..0000000 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsServiceImpl.kt +++ /dev/null @@ -1,52 +0,0 @@ -package bou.amine.apps.readerforselfossv2.service - -import com.russhwolf.settings.Settings -import io.github.aakira.napier.Napier - -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) { - Napier.d(message, tag = "LogApiCalls") - } - - - override fun getApiVersion(): Int { - if (_apiVersion == -1) { - _apiVersion = settings.getInt("apiVersionMajor", -1) - return _apiVersion - } - return _apiVersion - } - - override fun getBaseUrl(): String { - if (_baseUrl.isEmpty()) { - _baseUrl = settings.getString("url", "") - } - return _baseUrl - } - - override fun getUserName(): String { - if (_userName.isEmpty()) { - _userName = settings.getString("login", "") - } - return _userName - } - - override fun getPassword(): String { - if (_password.isEmpty()) { - _password = settings.getString("password", "") - } - return _password - } - - override fun refresh() { - _password = settings.getString("password", "") - _userName = settings.getString("login", "") - _baseUrl = settings.getString("url", "") - _apiVersion = settings.getInt("apiVersionMajor", -1) - } -} \ 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 95518ba..41ae126 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 @@ -1,12 +1,13 @@ package bou.amine.apps.readerforselfossv2.utils import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long = dateUtils.parseDate(this.datetime) -expect class DateUtils(apiMajorVersion: Int) { +expect class DateUtils(apiDetailsService: ApiDetailsService) { fun parseDate(dateString: String): Long fun parseRelativeDate(dateString: String): String diff --git a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 69a287b..ec6fc1f 100644 --- a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,6 +1,8 @@ package bou.amine.apps.readerforselfossv2.utils -actual class DateUtils actual constructor(apiMajorVersion: Int) { +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService + +actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) { actual fun parseDate(dateString: String): Long { TODO("Not yet implemented") } diff --git a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 69a287b..ec6fc1f 100644 --- a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,6 +1,8 @@ package bou.amine.apps.readerforselfossv2.utils -actual class DateUtils actual constructor(apiMajorVersion: Int) { +import bou.amine.apps.readerforselfossv2.service.ApiDetailsService + +actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) { actual fun parseDate(dateString: String): Long { TODO("Not yet implemented") } From a99286a9b7b1d31b3fca69b9982c9d62c6ac937b Mon Sep 17 00:00:00 2001 From: aminecmi Date: Fri, 26 Aug 2022 22:30:34 +0200 Subject: [PATCH 2/8] Really big settings cleaning. --- androidApp/src/main/AndroidManifest.xml | 4 - .../android/AddSourceActivity.kt | 6 +- .../android/HomeActivity.kt | 101 +---- .../android/LoginActivity.kt | 17 +- .../apps/readerforselfossv2/android/MyApp.kt | 8 +- .../android/ReaderActivity.kt | 28 +- .../android/adapters/ItemCardAdapter.kt | 11 +- .../android/adapters/ItemListAdapter.kt | 8 +- .../android/adapters/ItemsAdapter.kt | 4 +- .../android/background/background.kt | 26 +- .../android/fragments/ArticleFragment.kt | 14 +- .../android/settings/SettingsActivity.kt | 16 +- .../android/themes/AppColors.kt | 11 + .../utils/glide/SelfSignedGlideModule.kt | 33 -- .../readerforselfossv2/utils/DateUtils.kt | 6 +- .../apps/readerforselfossv2/DI/modules.kt | 4 +- .../repository/RepositoryImpl.kt | 48 +- .../readerforselfossv2/rest/SelfossApi.kt | 70 +-- .../service/ApiDetailsService.kt | 97 ---- .../service/AppSettingsService.kt | 428 ++++++++++++++++++ .../readerforselfossv2/utils/DateUtils.kt | 4 +- .../readerforselfossv2/utils/DateUtils.kt | 4 +- .../readerforselfossv2/utils/DateUtils.kt | 4 +- 23 files changed, 586 insertions(+), 366 deletions(-) delete mode 100644 androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/SelfSignedGlideModule.kt delete mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsService.kt create mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt diff --git a/androidApp/src/main/AndroidManifest.xml b/androidApp/src/main/AndroidManifest.xml index f2e3130..5ef39dd 100644 --- a/androidApp/src/main/AndroidManifest.xml +++ b/androidApp/src/main/AndroidManifest.xml @@ -68,10 +68,6 @@ android:name=".ImageActivity"> - - 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 fc9acb5..0c7093c 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 @@ -12,7 +12,7 @@ import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException import bou.amine.apps.readerforselfossv2.repository.Repository -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.ftinc.scoop.Scoop import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -31,7 +31,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { override val di by closestDI() private val repository : Repository by instance() - private val apiDetailsService : ApiDetailsService by instance() + private val appSettingsService : AppSettingsService by instance() override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@AddSourceActivity) @@ -83,7 +83,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware { override fun onResume() { super.onResume() - val baseUrl = apiDetailsService.getBaseUrl() + val baseUrl = appSettingsService.getBaseUrl() if (baseUrl.isEmpty() || !baseUrl.isBaseUrlValid(this@AddSourceActivity)) { mustLoginToAddSource() } else { 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 51e32ca..8d35cdd 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 @@ -35,7 +35,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.* import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationItem @@ -69,7 +69,6 @@ import kotlin.concurrent.thread class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware { - private val MENU_PREFERENCES = 12302 private val DRAWER_ID_TAGS = 100101L private val DRAWER_ID_HIDDEN_TAGS = 101100L private val DRAWER_ID_SOURCES = 100110L @@ -77,21 +76,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private var items: ArrayList = ArrayList() - private var internalBrowser = false - private var articleViewer = false - private var shouldBeCardView = false - private var displayUnreadCount = false - private var displayAllCount = false - private var fullHeightCards: Boolean = false private var elementsShown: ItemType = ItemType.UNREAD private var lastFetchDone: Boolean = false - private var updateSources: Boolean = true - private var markOnScroll: Boolean = false - private var hiddenTags: List = emptyList() - - private var periodicRefresh = false - private var refreshMinutes: Long = 360L - private var refreshWhenChargingOnly = false private lateinit var tabNewBadge: TextBadgeItem private lateinit var tabArchiveBadge: TextBadgeItem @@ -101,7 +87,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private var offset: Int = 0 private var firstVisible: Int = 0 private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener - private var settings = Settings() private lateinit var binding: ActivityHomeBinding private var recyclerAdapter: RecyclerView.Adapter<*>? = null @@ -112,6 +97,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override val di by closestDI() private val repository : Repository by instance() + private val appSettingsService : AppSettingsService by instance() data class DrawerData(val tags: List?, val sources: List?) @@ -121,6 +107,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } override fun onCreate(savedInstanceState: Bundle?) { + + // Add appcolors to DI appColors = AppColors(this@HomeActivity) super.onCreate(savedInstanceState) @@ -152,8 +140,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar handleSwipeRefreshLayout() - handleSettings() - getElementsAccordingToTab() @@ -292,7 +278,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override fun onResume() { super.onResume() - // TODO: Make this the only appcolors init appColors = AppColors(this@HomeActivity) handleDrawerItems() @@ -301,10 +286,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar reloadLayoutManager() - if (!settings.getBoolean("infinite_loading", false)) { - binding.recyclerView.setHasFixedSize(true) - } else { + if (appSettingsService.isInfiniteLoadingEnabled()) { handleInfiniteScroll() + } else { + binding.recyclerView.setHasFixedSize(true) } handleBottomBarActions() @@ -323,31 +308,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar customTabActivityHelper.unbindCustomTabsService(this) } - private fun handleSettings() { - // TODO : clean this - 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) - - 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 = 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 - } - } - private fun handleThemeBinding() { val scoop = Scoop.getInstance() scoop.bind(this, Toppings.PRIMARY.value, binding.toolBar) @@ -401,16 +361,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.drawerContainer.addDrawerListener(drawerListener) - val displayAccountHeader = - settings.getBoolean("account_header_displaying", false) - binding.mainDrawer.addStickyFooterItem( PrimaryDrawerItem().apply { nameRes = R.string.drawer_report_bug iconRes = R.drawable.ic_bug_report_black_24dp isIconTinted = true onDrawerItemClickListener = { _, _, _ -> - val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(ApiDetailsService.trackerUrl)) + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl)) startActivity(browserIntent) false } @@ -427,12 +384,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } }) - if (displayAccountHeader) { + if (appSettingsService.isDisplayAccountHeaderEnabled()) { AccountHeaderView(this).apply { attachToSliderView(binding.mainDrawer) addProfiles( ProfileDrawerItem().apply { - nameText = settings.getString("url", "") + nameText = appSettingsService.getBaseUrl() setBackgroundResource(R.drawable.bg) iconRes = R.mipmap.ic_launcher selectionListEnabledForSingleProfile = false @@ -496,7 +453,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } } else { val filteredTags = maybeTags - .filterNot { hiddenTags.contains(it.tag) } + .filterNot { appSettingsService.getHiddenTags().contains(it.tag) } .sortedBy { it.unread == 0 } tagsBadge = filteredTags.map { createDrawerItem(it) @@ -518,7 +475,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } } else { val filteredHiddenTags: List = - maybeTags.filter { hiddenTags.contains(it.tag) } + maybeTags.filter { appSettingsService.getHiddenTags().contains(it.tag) } tagsBadge = filteredHiddenTags.map { createDrawerItem(it) @@ -574,7 +531,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } } ) - if (hiddenTags.isNotEmpty()) { + if (appSettingsService.getHiddenTags().isNotEmpty()) { binding.mainDrawer.itemAdapter.add( DividerDrawerItem(), SecondaryDrawerItem().apply { @@ -707,7 +664,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar // This will only update the layout manager if settings changed when (currentManager) { is StaggeredGridLayoutManager -> - if (!shouldBeCardView) { + if (!appSettingsService.isCardViewEnabled()) { layoutManager = GridLayoutManager( this, calculateNoOfColumns() @@ -715,7 +672,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.recyclerView.layoutManager = layoutManager } is GridLayoutManager -> - if (shouldBeCardView) { + if (appSettingsService.isCardViewEnabled()) { layoutManager = StaggeredGridLayoutManager( calculateNoOfColumns(), StaggeredGridLayoutManager.VERTICAL @@ -726,7 +683,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } else -> if (currentManager == null) { - if (!shouldBeCardView) { + if (!appSettingsService.isCardViewEnabled()) { layoutManager = GridLayoutManager( this, calculateNoOfColumns() @@ -862,15 +819,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } if (recyclerAdapter == null) { - if (shouldBeCardView) { + if (appSettingsService.isCardViewEnabled()) { recyclerAdapter = ItemCardAdapter( this, items, customTabActivityHelper, - internalBrowser, // TODO remove and use from apidetailsservice - articleViewer, // TODO remove and use from apidetailsservice - fullHeightCards, // TODO remove and use from apidetailsservice appColors, ) { updateItems(it) @@ -881,8 +835,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar this, items, customTabActivityHelper, - internalBrowser, // TODO remove and use from apidetailsservice - articleViewer, // TODO remove and use from apidetailsservice appColors, ) { updateItems(it) @@ -905,7 +857,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } private fun reloadBadges() { - if (displayUnreadCount || displayAllCount) { + if (appSettingsService.isDisplayUnreadCountEnabled() || appSettingsService.isDisplayAllCountEnabled()) { CoroutineScope(Dispatchers.Main).launch { repository.reloadBadges() reloadBadgeContent() @@ -914,12 +866,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } private fun reloadBadgeContent() { - if (displayUnreadCount) { + if (appSettingsService.isDisplayUnreadCountEnabled()) { tabNewBadge .setText(repository.badgeUnread.toString()) .maybeShow() } - if (displayAllCount) { + if (appSettingsService.isDisplayAllCountEnabled()) { tabArchiveBadge .setText(repository.badgeAll.toString()) .maybeShow() @@ -1038,8 +990,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar return true } R.id.action_disconnect -> { - val settings = Settings() - settings.clear() + appSettingsService.clearAll() val intent = Intent(this, LoginActivity::class.java) this.startActivity(intent) this@HomeActivity.finish() @@ -1062,15 +1013,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar } private fun handleRecurringTask() { - if (periodicRefresh) { + if (appSettingsService.isPeriodicRefreshEnabled()) { val myConstraints = Constraints.Builder() .setRequiresBatteryNotLow(true) - .setRequiresCharging(refreshWhenChargingOnly) + .setRequiresCharging(appSettingsService.isRefreshWhenChargingOnlyEnabled()) .setRequiresStorageNotLow(true) .build() val backgroundWork = - PeriodicWorkRequestBuilder(refreshMinutes, TimeUnit.MINUTES) + PeriodicWorkRequestBuilder(appSettingsService.getRefreshMinutes(), TimeUnit.MINUTES) .setConstraints(myConstraints) .addTag("selfoss-loading") .build() @@ -1078,9 +1029,5 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar WorkManager.getInstance(baseContext).enqueueUniquePeriodicWork("selfoss-loading", ExistingPeriodicWorkPolicy.KEEP, backgroundWork) } } - - private fun handleOfflineActions() { - - } } 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 544325f..9edfc96 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 @@ -16,8 +16,8 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBindin import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid import bou.amine.apps.readerforselfossv2.repository.Repository +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.mikepenz.aboutlibraries.LibsBuilder -import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -25,19 +25,19 @@ import org.kodein.di.DIAware import org.kodein.di.android.closestDI import org.kodein.di.instance -class LoginActivity() : AppCompatActivity(), DIAware { +class LoginActivity : AppCompatActivity(), DIAware { private var inValidCount: Int = 0 private var isWithSelfSignedCert = false private var isWithLogin = false private var isWithHTTPLogin = false - private val settings = Settings() private lateinit var appColors: AppColors private lateinit var binding: ActivityLoginBinding override val di by closestDI() private val repository : Repository by instance() + private val appSettingsService : AppSettingsService by instance() override fun onCreate(savedInstanceState: Bundle?) { appColors = AppColors(this@LoginActivity) @@ -52,7 +52,7 @@ class LoginActivity() : AppCompatActivity(), DIAware { handleBaseUrlFail() - if (settings.getString("url", "").isNotEmpty()) { + if (appSettingsService.getBaseUrl().isNotEmpty()) { goToMain() } @@ -117,11 +117,8 @@ class LoginActivity() : AppCompatActivity(), DIAware { } private fun preferenceError(t: Throwable) { - settings.remove("url") - settings.remove("login") - settings.remove("httpUserName") - settings.remove("password") - settings.remove("httpPassword") + appSettingsService.resetLoginInformation() + binding.urlView.error = getString(R.string.wrong_infos) binding.loginView.error = getString(R.string.wrong_infos) binding.passwordView.error = getString(R.string.wrong_infos) @@ -199,7 +196,7 @@ class LoginActivity() : AppCompatActivity(), DIAware { } else { showProgress(true) - repository.refreshLoginInformation(url, login, password, httpLogin, httpPassword, isWithSelfSignedCert) + repository.refreshLoginInformation(url, login, password, isWithSelfSignedCert) CoroutineScope(Dispatchers.IO).launch { val result = repository.login() 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 9ad4e7e..8acb314 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 @@ -18,7 +18,7 @@ import bou.amine.apps.readerforselfossv2.android.viewmodel.AppViewModel import bou.amine.apps.readerforselfossv2.dao.DriverFactory import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB import bou.amine.apps.readerforselfossv2.repository.Repository -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.ftinc.scoop.Scoop @@ -48,12 +48,10 @@ class MyApp : MultiDexApplication(), DIAware { private val viewModel: AppViewModel by instance() private val connectivityStatus: ConnectivityStatus by instance() private val driverFactory: DriverFactory by instance() - private lateinit var settings : Settings override fun onCreate() { super.onCreate() Napier.base(DebugAntilog()) - settings = Settings() initDrawerImageLoader() @@ -90,11 +88,11 @@ class MyApp : MultiDexApplication(), DIAware { val name = getString(R.string.notification_channel_sync) val importance = NotificationManager.IMPORTANCE_LOW - val mChannel = NotificationChannel(ApiDetailsService.syncChannelId, name, importance) + val mChannel = NotificationChannel(AppSettingsService.syncChannelId, name, importance) val newItemsChannelname = getString(R.string.new_items_channel_sync) val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT - val newItemsChannelmChannel = NotificationChannel(ApiDetailsService.newItemsChannelId, newItemsChannelname, newItemsChannelimportance) + val newItemsChannelmChannel = NotificationChannel(AppSettingsService.newItemsChannelId, newItemsChannelname, newItemsChannelimportance) notificationManager.createNotificationChannel(mChannel) notificationManager.createNotificationChannel(newItemsChannelmChannel) 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 125940e..e87aa44 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 @@ -16,8 +16,8 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.ftinc.scoop.Scoop -import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -27,7 +27,6 @@ import org.kodein.di.instance class ReaderActivity : AppCompatActivity(), DIAware { - private var markOnScroll: Boolean = false private var currentItem: Int = 0 private lateinit var appColors: AppColors @@ -35,12 +34,9 @@ class ReaderActivity : AppCompatActivity(), DIAware { private lateinit var binding: ActivityReaderBinding - private var activeAlignment: Int = 1 - private val JUSTIFY = 1 - private val ALIGN_LEFT = 2 - override val di by closestDI() private val repository: Repository by instance() + private val appSettingsService: AppSettingsService by instance() private fun showMenuItem(willAddToFavorite: Boolean) { if (willAddToFavorite) { @@ -58,8 +54,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { showMenuItem(false) } - private var settings = Settings() - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) appColors = AppColors(this) @@ -76,9 +70,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - markOnScroll = settings.getBoolean("mark_on_scroll", false) - activeAlignment = settings.getInt("text_align", JUSTIFY) - if (allItems.isEmpty()) { finish() } @@ -98,10 +89,9 @@ class ReaderActivity : AppCompatActivity(), DIAware { } private fun readItem(item: SelfossModel.Item) { - if (markOnScroll) { + if (appSettingsService.isMarkOnScrollEnabled()) { CoroutineScope(Dispatchers.IO).launch { repository.markAsRead(item) - // TODO: Handle failure } } } @@ -142,7 +132,7 @@ class ReaderActivity : AppCompatActivity(), DIAware { } private fun alignmentMenu() { - val showJustify = activeAlignment == ALIGN_LEFT + val showJustify = appSettingsService.getActiveAllignment() == AppSettingsService.ALIGN_LEFT toolbarMenu.findItem(R.id.align_left).isVisible = !showJustify toolbarMenu.findItem(R.id.align_justify).isVisible = showJustify } @@ -211,21 +201,19 @@ class ReaderActivity : AppCompatActivity(), DIAware { } } R.id.align_left -> { - activeAlignment = ALIGN_LEFT - switchAlignmentSetting() + switchAlignmentSetting(AppSettingsService.ALIGN_LEFT) refreshFragment() } R.id.align_justify -> { - activeAlignment = JUSTIFY - switchAlignmentSetting() + switchAlignmentSetting(AppSettingsService.JUSTIFY) refreshFragment() } } return super.onOptionsItemSelected(item) } - private fun switchAlignmentSetting() { - settings.putInt("text_align", activeAlignment) + private fun switchAlignmentSetting(allignment: Int) { + appSettingsService.changeAllignment(allignment) alignmentMenu() } 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 36ef496..94f004c 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,6 +17,7 @@ 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.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getIcon import bou.amine.apps.readerforselfossv2.utils.getThumbnail @@ -34,9 +35,6 @@ class ItemCardAdapter( override val app: Activity, override var items: ArrayList, private val helper: CustomTabActivityHelper, - private val internalBrowser: Boolean, - private val articleViewer: Boolean, - private val fullHeightCards: Boolean, override val appColors: AppColors, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { @@ -47,6 +45,7 @@ class ItemCardAdapter( override val di: DI by closestDI(app) override val repository : Repository by instance() + override val appSettingsService : AppSettingsService by instance() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -66,7 +65,7 @@ class ItemCardAdapter( binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils) - if (!fullHeightCards) { + if (!appSettingsService.isFullHeightCardsEnabled()) { binding.itemImage.maxHeight = imageMaxHeight binding.itemImage.scaleType = ScaleType.CENTER_CROP } @@ -146,8 +145,8 @@ class ItemCardAdapter( bindingAdapterPosition, items[bindingAdapterPosition].getLinkDecoded(), customTabsIntent, - internalBrowser, - articleViewer, + appSettingsService.isInternalBrowserEnabled(), + appSettingsService.isArticleViewerEnabled(), 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 6a9f30a..1cee1ff 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 @@ -14,6 +14,7 @@ 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.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getIcon import bou.amine.apps.readerforselfossv2.utils.getThumbnail @@ -27,8 +28,6 @@ class ItemListAdapter( override val app: Activity, override var items: ArrayList, private val helper: CustomTabActivityHelper, - private val internalBrowser: Boolean, - private val articleViewer: Boolean, override val appColors: AppColors, override val updateItems: (ArrayList) -> Unit ) : ItemsAdapter() { @@ -37,6 +36,7 @@ class ItemListAdapter( override val di: DI by closestDI(app) override val repository : Repository by instance() + override val appSettingsService : AppSettingsService by instance() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -94,8 +94,8 @@ class ItemListAdapter( bindingAdapterPosition, items[bindingAdapterPosition].getLinkDecoded(), customTabsIntent, - internalBrowser, - articleViewer, + appSettingsService.isInternalBrowserEnabled(), + appSettingsService.isArticleViewerEnabled(), 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 99b8002..e72c9b8 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,6 +8,7 @@ import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.ItemType import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.CoroutineScope @@ -18,6 +19,7 @@ import org.kodein.di.DIAware abstract class ItemsAdapter : RecyclerView.Adapter(), DIAware { abstract var items: ArrayList abstract val repository: Repository + abstract val appSettingsService: AppSettingsService abstract val app: Activity abstract val appColors: AppColors abstract val updateItems: (ArrayList) -> Unit @@ -92,8 +94,6 @@ abstract class ItemsAdapter : RecyclerView.Adapte private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) { CoroutineScope(Dispatchers.IO).launch { repository.unmarkAsRead(items[position]) - // Todo: SharedItems.unreadItem(app, api, db, items[position]) - // TODO: update db } notifyItemChanged(position) 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 c86de60..82c4476 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 @@ -17,7 +17,7 @@ import bou.amine.apps.readerforselfossv2.android.model.preloadImages import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAccessible import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.repository.Repository -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.russhwolf.settings.Settings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -31,33 +31,32 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con override val di by lazy { (applicationContext as MyApp).di } private val repository : Repository by instance() + private val appSettingsService : AppSettingsService by instance() override fun doWork(): Result { - val settings = Settings() - val periodicRefresh = settings.getBoolean("periodic_refresh", false) - if (periodicRefresh && isNetworkAccessible(context)) { + if (appSettingsService.isPeriodicRefreshEnabled() && isNetworkAccessible(context)) { CoroutineScope(Dispatchers.IO).launch { val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notification = - NotificationCompat.Builder(applicationContext, ApiDetailsService.syncChannelId) + NotificationCompat.Builder(applicationContext, AppSettingsService.syncChannelId) .setContentTitle(context.getString(R.string.loading_notification_title)) .setContentText(context.getString(R.string.loading_notification_text)) .setOngoing(true) .setPriority(PRIORITY_LOW) - .setChannelId(ApiDetailsService.syncChannelId) + .setChannelId(AppSettingsService.syncChannelId) .setSmallIcon(R.drawable.ic_stat_cloud_download_black_24dp) notificationManager.notify(1, notification.build()) - val notifyNewItems = settings.getBoolean("notify_new_items", false) - repository.handleDBActions() - launch { - handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notifyNewItems, notificationManager) + if (appSettingsService.isNotifyNewItemsEnabled()) { + launch { + handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notificationManager) + } } } } @@ -66,7 +65,6 @@ override fun doWork(): Result { private fun handleNewItemsNotification( newItems: List?, - notifyNewItems: Boolean, notificationManager: NotificationManager ) { CoroutineScope(Dispatchers.IO).launch { @@ -74,7 +72,7 @@ override fun doWork(): Result { val newSize = apiItems.filter { it.unread }.size - if (notifyNewItems && newSize > 0) { + if (newSize > 0) { val intent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK @@ -87,7 +85,7 @@ override fun doWork(): Result { val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, pflags) val newItemsNotification = - NotificationCompat.Builder(applicationContext, ApiDetailsService.newItemsChannelId) + NotificationCompat.Builder(applicationContext, AppSettingsService.newItemsChannelId) .setContentTitle(context.getString(R.string.new_items_notification_title)) .setContentText( context.getString( @@ -96,7 +94,7 @@ override fun doWork(): Result { ) ) .setPriority(PRIORITY_DEFAULT) - .setChannelId(ApiDetailsService.newItemsChannelId) + .setChannelId(AppSettingsService.newItemsChannelId) .setContentIntent(pendingIntent) .setAutoCancel(true) .setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp) 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 c893954..2eee8b1 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 @@ -31,6 +31,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActiv import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getImages import bou.amine.apps.readerforselfossv2.utils.getThumbnail @@ -74,8 +75,7 @@ class ArticleFragment : Fragment(), DIAware { override val di : DI by closestDI() private val repository: Repository by instance() - - private var settings = Settings() + private val appSettingsService: AppSettingsService by instance() private var typeface: Typeface? = null private var resId: Int = 0 @@ -114,10 +114,10 @@ class ArticleFragment : Fragment(), DIAware { contentSource = item.sourceAndDateText(repository.dateUtils) allImages = item.getImages() - fontSize = settings.getString("reader_font_size", "16").toInt() - staticBar = settings.getBoolean("reader_static_bar", false) + fontSize = appSettingsService.getFontSize() + staticBar = appSettingsService.isStaticBarEnabled() + font = appSettingsService.getFont() - font = settings.getString("reader_font", "") if (font.isNotEmpty()) { resId = requireContext().resources.getIdentifier(font, "font", requireContext().packageName) typeface = try { @@ -239,7 +239,7 @@ class ArticleFragment : Fragment(), DIAware { .setTitle(requireContext().getString(R.string.webview_dialog_issue_title)) .setPositiveButton(android.R.string.ok ) { _, _ -> - settings.putBoolean("prefer_article_viewer", false) + appSettingsService.disableArticleViewer() requireActivity().finish() } .create() @@ -255,7 +255,7 @@ class ArticleFragment : Fragment(), DIAware { } private fun refreshAlignment() { - textAlignment = when (settings.getInt("text_align", 1)) { + textAlignment = when (appSettingsService.getActiveAllignment()) { 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 050e6a8..3014dfe 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 @@ -14,8 +14,9 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding +import bou.amine.apps.readerforselfossv2.android.themes.AppColors import bou.amine.apps.readerforselfossv2.android.themes.Toppings -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.ftinc.scoop.Scoop import com.russhwolf.settings.Settings import java.lang.NumberFormatException @@ -174,12 +175,7 @@ class SettingsActivity : AppCompatActivity(), override fun onOptionsItemSelected(item: MenuItem): Boolean { val id = item.itemId if (id == R.id.clear) { - 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") + AppColors.resetColors() requireActivity().recreate() } return super.onOptionsItemSelected(item) @@ -196,17 +192,17 @@ class SettingsActivity : AppCompatActivity(), setPreferencesFromResource(R.xml.pref_links, rootKey) preferenceManager.findPreference("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(ApiDetailsService.trackerUrl)) + openUrl(Uri.parse(AppSettingsService.trackerUrl)) true } preferenceManager.findPreference("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(ApiDetailsService.sourceUrl)) + openUrl(Uri.parse(AppSettingsService.sourceUrl)) false } preferenceManager.findPreference("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(Uri.parse(ApiDetailsService.translationUrl)) + openUrl(Uri.parse(AppSettingsService.translationUrl)) false } } 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 78db5a6..bd01677 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 @@ -58,4 +58,15 @@ class AppColors(a: Activity) { a.resources.getColor(R.color.grey_900) } } + + companion object { + fun resetColors() { + 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") + } + } } 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 deleted file mode 100644 index 999a130..0000000 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/glide/SelfSignedGlideModule.kt +++ /dev/null @@ -1,33 +0,0 @@ -package bou.amine.apps.readerforselfossv2.android.utils.glide - -import android.content.Context -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 { - - override fun applyOptions(context: Context?, builder: GlideBuilder?) { - } - - override fun registerComponents(context: Context?, glide: Glide?, registry: Registry?) { - - if (context != null) { - val settings = Settings() - if (settings.getBoolean("isSelfSignedCert", false)) { - val client = getUnsafeHttpClient().build() - - registry?.append( - GlideUrl::class.java, - InputStream::class.java, - com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client) - ) - } - } - } -} \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 7eee3b2..15cfb94 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,15 +1,15 @@ package bou.amine.apps.readerforselfossv2.utils import android.text.format.DateUtils -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import java.time.Instant import java.time.LocalDateTime import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter -actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) { - val ads: ApiDetailsService = apiDetailsService // TODO: why is this needed now ? +actual class DateUtils actual constructor(appSettingsService: AppSettingsService) { + val ads: AppSettingsService = appSettingsService // TODO: why is this needed now ? actual fun parseDate(dateString: String): Long { 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 ebcb8f1..7888376 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,13 +1,13 @@ package bou.amine.apps.readerforselfossv2.DI import bou.amine.apps.readerforselfossv2.rest.SelfossApi -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService 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 { ApiDetailsService() } + bind() with singleton { AppSettingsService() } bind() with singleton { SelfossApi(instance()) } } \ 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 d9e4254..052783d 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,7 +4,7 @@ import bou.amine.apps.readerforselfossv2.dao.* import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.model.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.utils.* import com.github.ln_12.library.ConnectivityStatus import com.russhwolf.settings.Settings @@ -13,14 +13,13 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService, private val connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) { - val settings = Settings() +class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) { var items = ArrayList() val isConnectionAvailable = connectivityStatus.isNetworkConnected var connectionMonitored = false - var baseUrl = apiDetails.getBaseUrl() + var baseUrl = appSettingsService.getBaseUrl() lateinit var dateUtils: DateUtils var displayedItems = ItemType.UNREAD @@ -29,7 +28,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails var sourceFilter: SelfossModel.Source? = null var searchFilter: String? = null - var itemsCaching = settings.getBoolean("items_caching", false) var offlineOverride = false var badgeUnread = 0 @@ -43,7 +41,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found CoroutineScope(Dispatchers.Main).launch { updateApiVersion() - dateUtils = DateUtils(apiDetails) + dateUtils = DateUtils(appSettingsService) reloadBadges() } } @@ -61,7 +59,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails null ) } else { - if (itemsCaching) { + if (appSettingsService.isItemCachingEnabled()) { fetchedItems = getDBItems().filter { displayedItems == ItemType.ALL || (it.unread && displayedItems == ItemType.UNREAD) || @@ -98,7 +96,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return items } - suspend fun getMaxItemsForBackground(itemType: ItemType): List? { + private suspend fun getMaxItemsForBackground(itemType: ItemType): List? { return if (isNetworkAvailable()) { api.getItems( itemType.type, @@ -172,7 +170,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return success } - suspend fun markAsReadById(id: Int): Boolean { + private suspend fun markAsReadById(id: Int): Boolean { return if (isNetworkAvailable()) { api.markAsRead(id.toString())?.isSuccess == true } else { @@ -191,7 +189,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return success } - suspend fun unmarkAsReadById(id: Int): Boolean { + private suspend fun unmarkAsReadById(id: Int): Boolean { return if (isNetworkAvailable()) { api.unmarkAsRead(id.toString())?.isSuccess == true } else { @@ -209,7 +207,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return success } - suspend fun starrById(id: Int): Boolean { + private suspend fun starrById(id: Int): Boolean { return if (isNetworkAvailable()) { api.starr(id.toString())?.isSuccess == true } else { @@ -227,7 +225,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return success } - suspend fun unstarrById(id: Int): Boolean { + private suspend fun unstarrById(id: Int): Boolean { return if (isNetworkAvailable()) { api.unstarr(id.toString())?.isSuccess == true } else { @@ -307,7 +305,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails spout, tags, filter, - apiDetails.getApiVersion() + appSettingsService.getApiVersion() )?.isSuccess == true } @@ -350,27 +348,19 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails return result } - 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) + fun refreshLoginInformation(url: String, login: String, password: String, isSelfSignedCert: Boolean) { + appSettingsService.refreshLoginInformation(url, login, password, isSelfSignedCert) baseUrl = url api.refreshLoginInformation() } private suspend fun updateApiVersion() { - val apiMajorVersion = apiDetails.getApiVersion() + val apiMajorVersion = appSettingsService.getApiVersion() if (isNetworkAvailable()) { val fetchedVersion = api.version() if (fetchedVersion != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) { - settings.putInt("apiVersionMajor", fetchedVersion.getApiMajorVersion()) - apiDetails.refreshApiVersion() + appSettingsService.updateApiVersion(fetchedVersion.getApiMajorVersion()) } } dateUtils = DateUtils(apiMajorVersion) @@ -378,10 +368,10 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails fun isNetworkAvailable() = isConnectionAvailable.value && !offlineOverride - fun getDBActions(): List = + private fun getDBActions(): List = db.actionsQueries.actions().executeAsList() - fun deleteDBAction(action: ACTION) = + private fun deleteDBAction(action: ACTION) = db.actionsQueries.deleteAction(action.id) fun getDBTags(): List = db.tagsQueries.tags().executeAsList() @@ -432,7 +422,9 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails val starredItems = getMaxItemsForBackground(ItemType.STARRED) insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty()) return newItems - } catch (e: Throwable) {} + } catch (e: Throwable) { + // We do nothing + } return emptyList() } diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt index 1a2c56e..160f2d8 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt @@ -1,7 +1,7 @@ package bou.amine.apps.readerforselfossv2.rest import bou.amine.apps.readerforselfossv2.model.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.plugins.* @@ -14,7 +14,7 @@ import io.ktor.client.plugins.logging.* import io.ktor.serialization.kotlinx.json.* import kotlinx.serialization.json.Json -class SelfossApi(private val apiDetailsService: ApiDetailsService) { +class SelfossApi(private val appSettingsService: AppSettingsService) { var client = createHttpClient() @@ -31,13 +31,13 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { install(Logging) { logger = object : Logger { override fun log(message: String) { - apiDetailsService.logApiCalls(message) + appSettingsService.logApiCalls(message) } } level = LogLevel.ALL } install(HttpTimeout) { - requestTimeoutMillis = apiDetailsService.getApiTimeout() + requestTimeoutMillis = appSettingsService.getApiTimeout() } /* TODO: Auth as basic if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) { @@ -58,17 +58,17 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { } fun url(path: String) = - "${apiDetailsService.getBaseUrl()}$path" + "${appSettingsService.getBaseUrl()}$path" fun refreshLoginInformation() { - apiDetailsService.refresh() + appSettingsService.refreshApiSettings() client = createHttpClient() } suspend fun login(): SelfossModel.SuccessResponse? = client.get(url("/login")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun getItems( @@ -81,45 +81,45 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { items: Int? = null ): List? = client.get(url("/items")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) parameter("type", type) parameter("tag", tag) parameter("source", source) parameter("search", search) parameter("updatedsince", updatedSince) - parameter("items", items ?: apiDetailsService.getItemsNumber()) + parameter("items", items ?: appSettingsService.getItemsNumber()) parameter("offset", offset) }.body() suspend fun stats(): SelfossModel.Stats? = client.get(url("/stats")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun tags(): List? = client.get(url("/tags")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun update(): String? = client.get(url("/update")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun spouts(): Map? = client.get(url("/sources/spouts")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun sources(): ArrayList? = client.get(url("/sources/list")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun version(): SelfossModel.ApiVersion? = @@ -127,34 +127,34 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? = client.post(url("/mark/$id")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? = client.post(url("/unmark/$id")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun starr(id: String): SelfossModel.SuccessResponse? = client.post(url("/starr/$id")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun unstarr(id: String): SelfossModel.SuccessResponse? = client.post(url("/unstarr/$id")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() suspend fun markAllAsRead(ids: List): SelfossModel.SuccessResponse? = client.submitForm( url = url("/mark"), formParameters = Parameters.build { - append("username", apiDetailsService.getUserName()) - append("password", apiDetailsService.getPassword()) + append("username", appSettingsService.getUserName()) + append("password", appSettingsService.getPassword()) ids.map { append("ids[]", it) } } ).body() @@ -181,7 +181,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { filter: String ): SelfossModel.SuccessResponse? = client.submitForm( - url = url("/source?username=${apiDetailsService.getUserName()}&password=${apiDetailsService.getPassword()}"), + url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"), formParameters = Parameters.build { append("title", title) append("url", url) @@ -199,7 +199,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { filter: String ): SelfossModel.SuccessResponse? = client.submitForm( - url = url("/source?username=${apiDetailsService.getUserName()}&password=${apiDetailsService.getPassword()}"), + url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"), formParameters = Parameters.build { append("title", title) append("url", url) @@ -211,7 +211,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) { suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? = client.delete(url("/source/$id")) { - parameter("username", apiDetailsService.getUserName()) - parameter("password", apiDetailsService.getPassword()) + parameter("username", appSettingsService.getUserName()) + parameter("password", appSettingsService.getPassword()) }.body() } \ No newline at end of file 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 deleted file mode 100644 index 6a48792..0000000 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ApiDetailsService.kt +++ /dev/null @@ -1,97 +0,0 @@ -package bou.amine.apps.readerforselfossv2.service - -import com.russhwolf.settings.Settings -import io.github.aakira.napier.Napier -import io.ktor.client.plugins.* - -class ApiDetailsService { - val settings: Settings = Settings() - private var _apiVersion: Int = -1 - private var _baseUrl: String = "" - private var _userName: String = "" - private var _password: String = "" - private var _itemsNumber: Int? = null - private var _apiTimeout: Long? = null - - fun logApiCalls(message: String) { - Napier.d(message, tag = "LogApiCalls") - } - - - fun getApiVersion(): Int { - if (_apiVersion == -1) { - refreshApiVersion() - return _apiVersion - } - return _apiVersion - } - - fun refreshApiVersion() { - _apiVersion = settings.getInt("apiVersionMajor", -1) - } - - fun getBaseUrl(): String { - if (_baseUrl.isEmpty()) { - _baseUrl = settings.getString("url", "") - } - return _baseUrl - } - - fun getUserName(): String { - if (_userName.isEmpty()) { - _userName = settings.getString("login", "") - } - return _userName - } - - fun getPassword(): String { - if (_password.isEmpty()) { - _password = settings.getString("password", "") - } - return _password - } - - fun getItemsNumber(): Int { - if (_itemsNumber == null) { - refreshItemsNumber() - } - return _itemsNumber!! - } - - fun refreshItemsNumber() { - _itemsNumber = settings.getString("prefer_api_items_number", "200").toInt() - } - - fun getApiTimeout(): Long { - if (_apiTimeout == null) { - refreshApiTimeout() - } - return _apiTimeout!! - } - - fun refreshApiTimeout() { - val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS) - _apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS - } - - fun refresh() { - _password = settings.getString("password", "") - _userName = settings.getString("login", "") - _baseUrl = settings.getString("url", "") - refreshApiVersion() - refreshItemsNumber() - refreshApiTimeout() - } - - companion object { - const val translationUrl = "https://crwd.in/readerforselfoss" - - const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform" - - const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" - - const val syncChannelId = "sync-channel-id" - - const val newItemsChannelId = "new-items-channel-id" - } -} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt new file mode 100644 index 0000000..398323f --- /dev/null +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt @@ -0,0 +1,428 @@ +package bou.amine.apps.readerforselfossv2.service + +import com.russhwolf.settings.Settings +import io.github.aakira.napier.Napier +import io.ktor.client.plugins.* + +class AppSettingsService { + val settings: Settings = Settings() + + // Api related + private var _apiVersion: Int = -1 + private var _baseUrl: String = "" + private var _userName: String = "" + private var _password: String = "" + + // User settings related + private var _itemsCaching: Boolean? = null + private var _internalBrowser: Boolean? = null + private var _articleViewer: Boolean? = null + private var _shouldBeCardView: Boolean? = null + private var _displayUnreadCount: Boolean? = null + private var _displayAllCount: Boolean? = null + private var _fullHeightCards: Boolean? = null + private var _updateSources: Boolean? = null + private var _periodicRefresh: Boolean? = null + private var _refreshWhenChargingOnly: Boolean? = null + private var _infiniteLoading: Boolean? = null + private var _displayAccountHeader: Boolean? = null + private var _notifyNewItems: Boolean? = null + private var _itemsNumber: Int? = null + private var _apiTimeout: Long? = null + private var _hiddenTags: List? = null + private var _refreshMinutes: Long = 360 + private var _markOnScroll: Boolean? = null + private var _activeAlignment: Int? = null + + private var _fontSize: Int? = null // settings.getString("reader_font_size", "16").toInt() + private var _staticBar: Boolean? = null // settings.getBoolean("reader_static_bar", false) + private var _font: String = "" // settings.getString("reader_font", "") + + + init { + refreshApiSettings() + refreshUserSettings() + } + + fun logApiCalls(message: String) { + Napier.d(message, tag = "LogApiCalls") + } + + fun getApiVersion(): Int { + if (_apiVersion == -1) { + refreshApiVersion() + return _apiVersion + } + return _apiVersion + } + + fun refreshApiVersion() { + _apiVersion = settings.getInt("apiVersionMajor", -1) + } + + fun getBaseUrl(): String { + if (_baseUrl.isEmpty()) { + refreshBaseUrl() + } + return _baseUrl + } + + fun getUserName(): String { + if (_userName.isEmpty()) { + refrershUsername() + } + return _userName + } + + fun getPassword(): String { + if (_password.isEmpty()) { + refreshPassword() + } + return _password + } + + fun getItemsNumber(): Int { + if (_itemsNumber == null) { + refreshItemsNumber() + } + return _itemsNumber!! + } + + fun refreshItemsNumber() { + _itemsNumber = settings.getString("prefer_api_items_number", "200").toInt() + } + + fun getApiTimeout(): Long { + if (_apiTimeout == null) { + refreshApiTimeout() + } + return _apiTimeout!! + } + + private fun refreshApiTimeout() { + val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS) + _apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS + } + + private fun refreshBaseUrl() { + _baseUrl = settings.getString("url", "") + } + + private fun refrershUsername() { + _userName = settings.getString("login", "") + } + + private fun refreshPassword() { + _password = settings.getString("password", "") + } + + private fun refreshInternalBrowserEnabled() { + _internalBrowser = settings.getBoolean("prefer_internal_browser", true) + } + + fun isInternalBrowserEnabled(): Boolean { + if (_internalBrowser != null) { + refreshInternalBrowserEnabled() + } + return _internalBrowser == true + } + + private fun refreshArticleViewerEnabled() { + _articleViewer = settings.getBoolean("prefer_article_viewer", true) + } + + fun isArticleViewerEnabled(): Boolean { + if (_articleViewer != null) { + refreshArticleViewerEnabled() + } + return _articleViewer == true + } + private fun refreshShouldBeCardViewEnabled() { + _shouldBeCardView = settings.getBoolean("card_view_active", false) + } + + fun isCardViewEnabled(): Boolean { + if (_shouldBeCardView != null) { + refreshShouldBeCardViewEnabled() + } + return _shouldBeCardView == true + } + private fun refreshDisplayUnreadCountEnabled() { + _displayUnreadCount = settings.getBoolean("display_unread_count", true) + } + + fun isDisplayUnreadCountEnabled(): Boolean { + if (_displayUnreadCount != null) { + refreshDisplayUnreadCountEnabled() + } + return _displayUnreadCount == true + } + private fun refreshDisplayAllCountEnabled() { + _displayAllCount = settings.getBoolean("display_other_count", false) + } + + fun isDisplayAllCountEnabled(): Boolean { + if (_displayAllCount != null) { + refreshDisplayAllCountEnabled() + } + return _displayAllCount == true + } + private fun refreshFullHeightCardsEnabled() { + _fullHeightCards = settings.getBoolean("full_height_cards", false) + } + + fun isFullHeightCardsEnabled(): Boolean { + if (_fullHeightCards != null) { + refreshFullHeightCardsEnabled() + } + return _fullHeightCards == true + } + private fun refreshUpdateSourcesEnabled() { + _updateSources = settings.getBoolean("update_sources", true) + } + + fun isUpdateSourcesEnabled(): Boolean { + if (_updateSources != null) { + refreshUpdateSourcesEnabled() + } + return _updateSources == true + } + private fun refreshPeriodicRefreshEnabled() { + _periodicRefresh = settings.getBoolean("periodic_refresh", false) + } + + fun isPeriodicRefreshEnabled(): Boolean { + if (_periodicRefresh != null) { + refreshPeriodicRefreshEnabled() + } + return _periodicRefresh == true + } + + private fun refreshRefreshWhenChargingOnlyEnabled() { + _refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false) + } + + fun isRefreshWhenChargingOnlyEnabled(): Boolean { + if (_refreshWhenChargingOnly != null) { + refreshRefreshWhenChargingOnlyEnabled() + } + return _refreshWhenChargingOnly == true + } + + private fun refreshRefreshMinutes() { + _refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong() + if (_refreshMinutes <= 15) { + _refreshMinutes = 15 + } + } + + fun getRefreshMinutes(): Long { + if (_refreshMinutes != null) { + refreshRefreshMinutes() + } + return _refreshMinutes + } + + private fun refreshHiddenTags() { + if (settings.getString("hidden_tags", "").isNotEmpty()) { + _hiddenTags = settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",") + } + } + + fun getHiddenTags(): List { + if (_hiddenTags != null) { + refreshHiddenTags() + } + return _hiddenTags.orEmpty() + } + + private fun refreshInfiniteLoadingEnabled() { + _infiniteLoading = settings.getBoolean("infinite_loading", false) + } + + fun isInfiniteLoadingEnabled(): Boolean { + if (_infiniteLoading != null) { + refreshInfiniteLoadingEnabled() + } + return _infiniteLoading == true + } + + private fun refreshDisplayAccountHeaderEnabled() { + _displayAccountHeader = settings.getBoolean("account_header_displaying", false) + } + + fun isDisplayAccountHeaderEnabled(): Boolean { + if (_displayAccountHeader != null) { + refreshDisplayAccountHeaderEnabled() + } + return _displayAccountHeader == true + } + + private fun refreshItemCachingEnabled() { + _itemsCaching = settings.getBoolean("items_caching", false) + } + + fun isItemCachingEnabled(): Boolean { + if (_itemsCaching != null) { + refreshItemCachingEnabled() + } + return _itemsCaching == true + } + + private fun refreshNotifyNewItemsEnabled() { + _notifyNewItems = settings.getBoolean("notify_new_items", false) + } + + fun isNotifyNewItemsEnabled(): Boolean { + if (_notifyNewItems != null) { + refreshNotifyNewItemsEnabled() + } + return _notifyNewItems == true + } + + + private fun refreshMarkOnScrollEnabled() { + _markOnScroll = settings.getBoolean("mark_on_scroll", false) + } + + fun isMarkOnScrollEnabled(): Boolean { + if (_markOnScroll != null) { + refreshMarkOnScrollEnabled() + } + return _markOnScroll == true + } + + + private fun refreshActiveAllignment() { + _activeAlignment = settings.getInt("text_align", JUSTIFY) + } + + fun getActiveAllignment(): Int { + if (_activeAlignment != null) { + refreshActiveAllignment() + } + return _activeAlignment ?: JUSTIFY + } + + fun changeAllignment(allignment: Int) { + settings.putInt("text_align", allignment) + _activeAlignment = allignment + } + + private fun refreshFontSize() { + _fontSize = settings.getString("reader_font_size", "16").toInt() + } + + fun getFontSize(): Int { + if (_fontSize != null) { + refreshFontSize() + } + return _fontSize ?: 16 + } + + private fun refreshStaticBarEnabled() { + _staticBar = settings.getBoolean("reader_static_bar", false) + } + + fun isStaticBarEnabled(): Boolean { + if (_staticBar != null) { + refreshStaticBarEnabled() + } + return _staticBar == true + } + + private fun refreshFont() { + _font = settings.getString("reader_font", "") + } + + fun getFont(): String { + if (_font != null) { + refreshFont() + } + return _font + } + + fun refreshApiSettings() { + refreshPassword() + refrershUsername() + refreshBaseUrl() + refreshApiVersion() + } + + fun refreshUserSettings() { + refreshItemsNumber() + refreshApiTimeout() + refreshInternalBrowserEnabled() + refreshArticleViewerEnabled() + refreshShouldBeCardViewEnabled() + refreshDisplayUnreadCountEnabled() + refreshDisplayAllCountEnabled() + refreshFullHeightCardsEnabled() + refreshUpdateSourcesEnabled() + refreshPeriodicRefreshEnabled() + refreshRefreshWhenChargingOnlyEnabled() + refreshRefreshMinutes() + refreshHiddenTags() + refreshInfiniteLoadingEnabled() + refreshDisplayAccountHeaderEnabled() + refreshItemCachingEnabled() + refreshNotifyNewItemsEnabled() + refreshMarkOnScrollEnabled() + refreshActiveAllignment() + refreshFontSize() + refreshFont() + refreshStaticBarEnabled() + } + + fun refreshLoginInformation( + url: String, + login: String, + password: String, + selfSignedCert: Boolean + ) { + settings.putString("url", url) + settings.putString("login", login) + settings.putString("password", password) + settings.putBoolean("isSelfSignedCert", selfSignedCert) + refreshApiSettings() + } + + fun resetLoginInformation() { + settings.remove("url") + settings.remove("login") + settings.remove("password") + refreshApiSettings() + } + + fun updateApiVersion(apiMajorVersion: Int) { + settings.putInt("apiVersionMajor", apiMajorVersion) + refreshApiVersion() + } + + fun clearAll() { + settings.clear() + refreshApiSettings() + refreshUserSettings() + } + + fun disableArticleViewer() { + settings.putBoolean("prefer_article_viewer", false) + refreshArticleViewerEnabled() + } + + companion object { + const val translationUrl = "https://crwd.in/readerforselfoss" + + const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform" + + const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" + + const val syncChannelId = "sync-channel-id" + + const val newItemsChannelId = "new-items-channel-id" + + const val JUSTIFY = 1 + + const val ALIGN_LEFT = 2 + } +} \ 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 41ae126..35ecfa5 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 @@ -1,13 +1,13 @@ package bou.amine.apps.readerforselfossv2.utils import bou.amine.apps.readerforselfossv2.model.SelfossModel -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long = dateUtils.parseDate(this.datetime) -expect class DateUtils(apiDetailsService: ApiDetailsService) { +expect class DateUtils(appSettingsService: AppSettingsService) { fun parseDate(dateString: String): Long fun parseRelativeDate(dateString: String): String diff --git a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index ec6fc1f..b217356 100644 --- a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,8 +1,8 @@ package bou.amine.apps.readerforselfossv2.utils -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService -actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) { +actual class DateUtils actual constructor(appSettingsService: AppSettingsService) { actual fun parseDate(dateString: String): Long { TODO("Not yet implemented") } diff --git a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index ec6fc1f..b217356 100644 --- a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,8 +1,8 @@ package bou.amine.apps.readerforselfossv2.utils -import bou.amine.apps.readerforselfossv2.service.ApiDetailsService +import bou.amine.apps.readerforselfossv2.service.AppSettingsService -actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) { +actual class DateUtils actual constructor(appSettingsService: AppSettingsService) { actual fun parseDate(dateString: String): Long { TODO("Not yet implemented") } From 17293e5574ab3a05e92832dcef46952a243a574a Mon Sep 17 00:00:00 2001 From: aminecmi Date: Fri, 26 Aug 2022 22:49:19 +0200 Subject: [PATCH 3/8] Removing self signed certificate (Closes #43) and removing http login (Closes #37) --- .../android/LoginActivity.kt | 39 +------------------ .../res/drawable/ic_bug_report_white_24dp.xml | 5 --- .../res/drawable/ic_color_lens_white_24dp.xml | 5 --- .../src/main/res/layout/activity_login.xml | 39 ------------------- .../src/main/res/values-ca-rES/strings.xml | 33 ---------------- .../src/main/res/values-de-rDE/strings.xml | 33 ---------------- .../src/main/res/values-es-rES/strings.xml | 33 ---------------- .../src/main/res/values-fa-rIR/strings.xml | 33 ---------------- .../src/main/res/values-fr-rFR/strings.xml | 33 ---------------- .../src/main/res/values-gl-rES/strings.xml | 33 ---------------- .../src/main/res/values-in-rID/strings.xml | 33 ---------------- .../src/main/res/values-it-rIT/strings.xml | 33 ---------------- .../src/main/res/values-ko-rKR/strings.xml | 33 ---------------- .../src/main/res/values-nl-rNL/strings.xml | 33 ---------------- .../src/main/res/values-pt-rBR/strings.xml | 33 ---------------- .../src/main/res/values-pt-rPT/strings.xml | 33 ---------------- .../src/main/res/values-si-rLK/strings.xml | 33 ---------------- .../src/main/res/values-tr-rTR/strings.xml | 33 ---------------- .../src/main/res/values-zh-rCN/strings.xml | 33 ---------------- .../src/main/res/values-zh-rTW/strings.xml | 33 ---------------- androidApp/src/main/res/values/colors.xml | 8 ---- androidApp/src/main/res/values/strings.xml | 33 ---------------- .../repository/RepositoryImpl.kt | 4 +- .../service/AppSettingsService.kt | 4 +- 24 files changed, 4 insertions(+), 661 deletions(-) delete mode 100644 androidApp/src/main/res/drawable/ic_bug_report_white_24dp.xml delete mode 100644 androidApp/src/main/res/drawable/ic_color_lens_white_24dp.xml 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 9edfc96..cb8c9da 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 @@ -28,9 +28,7 @@ import org.kodein.di.instance class LoginActivity : AppCompatActivity(), DIAware { private var inValidCount: Int = 0 - private var isWithSelfSignedCert = false private var isWithLogin = false - private var isWithHTTPLogin = false private lateinit var appColors: AppColors private lateinit var binding: ActivityLoginBinding @@ -61,13 +59,6 @@ class LoginActivity : AppCompatActivity(), DIAware { private fun handleActions() { - binding.withSelfhostedCert.setOnCheckedChangeListener { _, b -> - isWithSelfSignedCert = !isWithSelfSignedCert - val visi: Int = if (b) View.VISIBLE else View.GONE - - binding.warningText.visibility = visi - } - binding.passwordView.setOnEditorActionListener( TextView.OnEditorActionListener { _, id, _ -> if (id == R.id.loginView || id == EditorInfo.IME_NULL) { @@ -87,14 +78,6 @@ class LoginActivity : AppCompatActivity(), DIAware { binding.loginView.visibility = visi binding.passwordView.visibility = visi } - - binding.withHttpLogin.setOnCheckedChangeListener { _, b -> - isWithHTTPLogin = !isWithHTTPLogin - val visi: Int = if (b) View.VISIBLE else View.GONE - - binding.httpLoginView.visibility = visi - binding.httpPasswordView.visibility = visi - } } private fun handleBaseUrlFail() { @@ -122,8 +105,6 @@ class LoginActivity : AppCompatActivity(), DIAware { binding.urlView.error = getString(R.string.wrong_infos) binding.loginView.error = getString(R.string.wrong_infos) binding.passwordView.error = getString(R.string.wrong_infos) - binding.httpLoginView.error = getString(R.string.wrong_infos) - binding.httpPasswordView.error = getString(R.string.wrong_infos) } private fun attemptLogin() { @@ -131,16 +112,12 @@ class LoginActivity : AppCompatActivity(), DIAware { // Reset errors. binding.urlView.error = null binding.loginView.error = null - binding.httpLoginView.error = null binding.passwordView.error = null - binding.httpPasswordView.error = null // Store values at the time of the login attempt. val url = binding.urlView.text.toString() val login = binding.loginView.text.toString() - val httpLogin = binding.httpLoginView.text.toString() val password = binding.passwordView.text.toString() - val httpPassword = binding.httpPasswordView.text.toString() var cancel = false var focusView: View? = null @@ -177,26 +154,12 @@ class LoginActivity : AppCompatActivity(), DIAware { } } - if (isWithHTTPLogin) { - if (TextUtils.isEmpty(httpPassword)) { - binding.httpPasswordView.error = getString(R.string.error_invalid_password) - focusView = binding.httpPasswordView - cancel = true - } - - if (TextUtils.isEmpty(httpLogin)) { - binding.httpLoginView.error = getString(R.string.error_field_required) - focusView = binding.httpLoginView - cancel = true - } - } - if (cancel) { focusView?.requestFocus() } else { showProgress(true) - repository.refreshLoginInformation(url, login, password, isWithSelfSignedCert) + repository.refreshLoginInformation(url, login, password) CoroutineScope(Dispatchers.IO).launch { val result = repository.login() diff --git a/androidApp/src/main/res/drawable/ic_bug_report_white_24dp.xml b/androidApp/src/main/res/drawable/ic_bug_report_white_24dp.xml deleted file mode 100644 index 5c8f5bc..0000000 --- a/androidApp/src/main/res/drawable/ic_bug_report_white_24dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/androidApp/src/main/res/drawable/ic_color_lens_white_24dp.xml b/androidApp/src/main/res/drawable/ic_color_lens_white_24dp.xml deleted file mode 100644 index 4abeea5..0000000 --- a/androidApp/src/main/res/drawable/ic_color_lens_white_24dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/androidApp/src/main/res/layout/activity_login.xml b/androidApp/src/main/res/layout/activity_login.xml index 7887f3d..4c37ea3 100644 --- a/androidApp/src/main/res/layout/activity_login.xml +++ b/androidApp/src/main/res/layout/activity_login.xml @@ -82,45 +82,6 @@ android:maxLines="1" android:visibility="gone" /> - - - - - - - - - -