diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9ba7a88 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,36 @@ +root = true + +[*] +insert_final_newline = true + +[.editorconfig] +insert_final_newline = false +ij_kotlin_line_break_after_multiline_when_entry = false + +[*.{kt,kts}] +# Disable wildcard imports entirely +ij_kotlin_name_count_to_use_star_import = 2147483647 +ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 +end_of_line = lf +ij_kotlin_allow_trailing_comma = true +ij_kotlin_allow_trailing_comma_on_call_site = true +ij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^ +ij_kotlin_indent_before_arrow_on_new_line = false +ij_kotlin_line_break_after_multiline_when_entry = true +ij_kotlin_packages_to_use_import_on_demand = unset +indent_size = 4 +indent_style = space +ktlint_argument_list_wrapping_ignore_when_parameter_count_greater_or_equal_than = unset +ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than = 4 +ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 1 +ktlint_code_style = ktlint_official +ktlint_enum_entry_name_casing = upper_or_camel_cases +ktlint_function_naming_ignore_when_annotated_with = unset +ktlint_function_signature_body_expression_wrapping = multiline +ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 2 +ktlint_ignore_back_ticked_identifier = false +ktlint_property_naming_constant_naming = screaming_snake_case +max_line_length = 140 + +[**/build] +ktlint = disabled \ No newline at end of file diff --git a/.gitea/workflows/on_pr.yml b/.gitea/workflows/on_pr.yml index f29a25c..6451b21 100644 --- a/.gitea/workflows/on_pr.yml +++ b/.gitea/workflows/on_pr.yml @@ -20,9 +20,9 @@ jobs: - name: Install detekt run: curl -sSLO https://github.com/detekt/detekt/releases/download/v1.23.1/detekt-cli-1.23.1.zip && unzip detekt-cli-1.23.1.zip - name: Linting... - run: ktlint 'shared/**/*.kt' 'androidApp/**/*.kt' '!shared/build' || true + run: ktlint 'shared/**/*.kt' 'androidApp/**/*.kt' '!shared/build' - name: Detecting... run: ./detekt-cli-1.23.1/bin/detekt-cli --all-rules --excludes '**/shared/build/**/*.kt' || true build: needs: Lint - uses: ./.gitea/workflows/common_build.yml \ No newline at end of file + uses: ./.gitea/workflows/common_build.yml diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/CommonTests.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/CommonTests.kt index b0e4cad..3e7187c 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/CommonTests.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/CommonTests.kt @@ -20,65 +20,72 @@ import org.hamcrest.Matchers.hasToString fun performLogin(someUrl: String? = null) { onView(withId(R.id.urlView)).perform(click()).perform( typeTextIntoFocusedView( - if (!someUrl.isNullOrEmpty()) someUrl else "http://10.0.2.2:8888" - ) + if (!someUrl.isNullOrEmpty()) someUrl else "http://10.0.2.2:8888", + ), ) onView(withId(R.id.signInButton)).perform(click()) } fun loginAndInitHome() { - performLogin() onView(withText(R.string.gdpr_dialog_title)).check(matches(isDisplayed())) onView(withText("OK")).perform(click()) } -fun changeAndCancelSetting(oldValue: String, newValue: String, openSettingItem: () -> Unit) { +fun changeAndCancelSetting( + oldValue: String, + newValue: String, + openSettingItem: () -> Unit, +) { openSettingItem() onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(replaceText(newValue)) onView( - withId(android.R.id.button2) + withId(android.R.id.button2), ).perform(click()) openSettingItem() onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).check(matches(withText(oldValue))) onView( - withText(newValue) + withText(newValue), ).check(doesNotExist()) onView( - withId(android.R.id.button2) + withId(android.R.id.button2), ).perform(click()) } -fun changeAndSaveSetting(oldValue: String, newValue: String, openSettingItem: () -> Unit) { +fun changeAndSaveSetting( + oldValue: String, + newValue: String, + openSettingItem: () -> Unit, +) { openSettingItem() onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(replaceText(newValue)) onView( - withId(android.R.id.button1) + withId(android.R.id.button1), ).perform(click()) openSettingItem() onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).check(matches(withText(newValue))) if (oldValue.isNotEmpty()) { onView( - withText(oldValue) + withText(oldValue), ).check(doesNotExist()) } onView( - withId(android.R.id.button2) + withId(android.R.id.button2), ).perform(click()) } fun testPreferencesFromArray( context: Context, @ArrayRes arrayRes: Int, - openSettingItem: () -> Unit + openSettingItem: () -> Unit, ) { openSettingItem() context.resources.getStringArray(arrayRes).forEach { res -> @@ -90,20 +97,25 @@ fun testPreferencesFromArray( } } -fun testAddSourceWithUrl(url: String, sourceName: String) { +fun testAddSourceWithUrl( + url: String, + sourceName: String, +) { onView(withId(R.id.fab)) .perform(click()) onView(withId(R.id.nameInput)) - .perform(click()).perform(typeTextIntoFocusedView(sourceName)) + .perform(click()) + .perform(typeTextIntoFocusedView(sourceName)) onView(withId(R.id.sourceUri)) .perform(click()) .perform(typeTextIntoFocusedView(url)) onView(withId(R.id.tags)) - .perform(click()).perform(typeTextIntoFocusedView("tag1,tag2,tag3")) + .perform(click()) + .perform(typeTextIntoFocusedView("tag1,tag2,tag3")) onView(withId(R.id.spoutsSpinner)) .perform(click()) onData(hasToString("RSS Feed")).perform(click()) onView(withId(R.id.saveBtn)) .perform(click()) onView(withText(sourceName)).check(matches(isDisplayed())) -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/helpers.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/Helpers.kt similarity index 78% rename from androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/helpers.kt rename to androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/Helpers.kt index ecca84b..3895a04 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/helpers.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/Helpers.kt @@ -25,8 +25,9 @@ import org.hamcrest.Matcher import org.hamcrest.Matchers import org.hamcrest.TypeSafeMatcher - -fun withError(@StringRes id: Int): TypeSafeMatcher { +fun withError( + @StringRes id: Int, +): TypeSafeMatcher { return object : TypeSafeMatcher() { override fun matchesSafely(view: View?): Boolean { if (view == null) { @@ -48,11 +49,11 @@ fun withError(@StringRes id: Int): TypeSafeMatcher { } } -fun isPopupWindow(): Matcher { - return isPlatformPopup() -} +fun isPopupWindow(): Matcher = isPlatformPopup() -fun withDrawable(@DrawableRes id: Int) = object : TypeSafeMatcher() { +fun withDrawable( + @DrawableRes id: Int, +) = object : TypeSafeMatcher() { override fun describeTo(description: Description) { description.appendText("ImageView with drawable same as drawable with id $id") } @@ -68,43 +69,46 @@ fun withDrawable(@DrawableRes id: Int) = object : TypeSafeMatcher() { } } -fun hasBottombarItemText(@StringRes id: Int): Matcher? { - return allOf( +fun hasBottombarItemText( + @StringRes id: Int, +): Matcher? = + allOf( withResourceName("fixed_bottom_navigation_icon"), withParent( allOf( withResourceName("fixed_bottom_navigation_icon_container"), - hasSibling(withText(id)) - ) - ) + hasSibling(withText(id)), + ), + ), ) -} -fun withSettingsCheckboxWidget(@StringRes id: Int): Matcher? { - return allOf( +fun withSettingsCheckboxWidget( + @StringRes id: Int, +): Matcher? = + allOf( withId(android.R.id.switch_widget), withParent( - withSettingsCheckboxFrame(id) - ) + withSettingsCheckboxFrame(id), + ), ) -} -fun withSettingsCheckboxFrame(@StringRes id: Int): Matcher? { - return allOf( +fun withSettingsCheckboxFrame( + @StringRes id: Int, +): Matcher? = + allOf( withId(android.R.id.widget_frame), hasSibling( allOf( withClassName(Matchers.equalTo(RelativeLayout::class.java.name)), withChild( - withText(id) - ) - ) - ) + withText(id), + ), + ), + ), ) -} fun openMenu() { openActionBarOverflowOrOptionsMenu( - ApplicationProvider.getApplicationContext() + ApplicationProvider.getApplicationContext(), ) -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/HomeActivityTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/HomeActivityTest.kt index eb76219..d52c424 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/HomeActivityTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/HomeActivityTest.kt @@ -23,7 +23,6 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class HomeActivityTest { - @get:Rule val activityRule = ActivityScenarioRule(LoginActivity::class.java) @@ -36,13 +35,13 @@ class HomeActivityTest { fun testMenu() { onView(withId(R.id.action_search)).check(matches(isDisplayed())).check( matches( - isClickable() - ) + isClickable(), + ), ) onView(withId(R.id.action_filter)).check(matches(isDisplayed())).check( matches( - isClickable() - ) + isClickable(), + ), ) openMenu() onView(withText(R.string.readAll)).check(matches(isDisplayed())) @@ -57,19 +56,19 @@ class HomeActivityTest { fun testMenuActions() { onView(withId(R.id.action_search)).perform(click()) onView( - withId(R.id.search_src_text) + withId(R.id.search_src_text), ).check(matches(isFocused())) onView(isRoot()).perform(ViewActions.pressBack()) onView(withId(R.id.action_filter)).perform(click()) onView( - withText(R.string.filter_item_sources) + withText(R.string.filter_item_sources), ).check(matches(isDisplayed())) onView( - withText(R.string.filter_item_tags) + withText(R.string.filter_item_tags), ).check(matches(isDisplayed())) onView( - withId(R.id.floatingActionButton2) + withId(R.id.floatingActionButton2), ).check(matches(isDisplayed())) onView(isRoot()).perform(ViewActions.pressBack()) @@ -107,14 +106,13 @@ class HomeActivityTest { fun testEmptyView() { onView(withId(R.id.emptyText)).check(matches(isDisplayed())) onView( - hasBottombarItemText(R.string.tab_new) + hasBottombarItemText(R.string.tab_new), ).check(matches(isDisplayed())).check(matches(isSelected())) onView( - hasBottombarItemText(R.string.tab_read) + hasBottombarItemText(R.string.tab_read), ).check(matches(isDisplayed())).check(matches(not(isSelected()))) onView( - hasBottombarItemText(R.string.tab_favs) + hasBottombarItemText(R.string.tab_favs), ).check(matches(isDisplayed())).check(matches(not(isSelected()))) } - -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/LoginActivityTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/LoginActivityTest.kt index 43d8343..4ebe150 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/LoginActivityTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/LoginActivityTest.kt @@ -23,7 +23,6 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class LoginActivityTest { - @get:Rule val activityRule = ActivityScenarioRule(LoginActivity::class.java) @@ -37,26 +36,32 @@ class LoginActivityTest { @Before fun registerIdlingResource() { - IdlingRegistry.getInstance() + IdlingRegistry + .getInstance() .register(CountingIdlingResourceSingleton.countingIdlingResource) } @After fun unregisterIdlingResource() { - IdlingRegistry.getInstance() + IdlingRegistry + .getInstance() .unregister(CountingIdlingResourceSingleton.countingIdlingResource) } @Test fun viewIsInitialized() { onView(withId(R.id.urlView)).check(matches(isDisplayed())) - onView(withId(R.id.selfSigned)).check(matches(isDisplayed())).check(matches(isNotChecked())) + onView(withId(R.id.selfSigned)) + .check(matches(isDisplayed())) + .check(matches(isNotChecked())) .check( - matches(isClickable()) + matches(isClickable()), ) - onView(withId(R.id.withLogin)).check(matches(isDisplayed())) - .check(matches(isNotChecked())).check( - matches(isClickable()) + onView(withId(R.id.withLogin)) + .check(matches(isDisplayed())) + .check(matches(isNotChecked())) + .check( + matches(isClickable()), ) } @@ -80,4 +85,4 @@ class LoginActivityTest { performLogin() onView(withText(R.string.gdpr_dialog_title)).check(matches(isDisplayed())) } -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityGeneralTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityGeneralTest.kt index 4859b02..b457f44 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityGeneralTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityGeneralTest.kt @@ -26,11 +26,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith - @RunWith(AndroidJUnit4::class) @LargeTest class SettingsActivityGeneralTest { - @get:Rule val activityRule = ActivityScenarioRule(LoginActivity::class.java) @@ -38,7 +36,7 @@ class SettingsActivityGeneralTest { fun init() { loginAndInitHome() openActionBarOverflowOrOptionsMenu( - ApplicationProvider.getApplicationContext() + ApplicationProvider.getApplicationContext(), ) onView(withText(R.string.title_activity_settings)).perform(click()) onView(withText(R.string.pref_header_general)).perform(click()) @@ -48,68 +46,75 @@ class SettingsActivityGeneralTest { fun testGeneral() { onView(withText(R.string.pref_api_items_number_title)).check(matches(isDisplayed())) onView( - withSettingsCheckboxWidget(R.string.pref_general_infinite_loading_title) + withSettingsCheckboxWidget(R.string.pref_general_infinite_loading_title), ).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withText(R.string.pref_general_category_links)).check(matches(isDisplayed())) onView(withSettingsCheckboxWidget(R.string.pref_article_viewer_title)).check( matches( allOf( - isDisplayed(), isChecked() - ) - ) + isDisplayed(), + isChecked(), + ), + ), ) onView(withSettingsCheckboxWidget(R.string.reader_static_bar_title)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxFrame(R.string.reader_static_bar_title)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) onView(withText(R.string.pref_general_category_displaying)).check(matches(isDisplayed())) onView(withSettingsCheckboxWidget(R.string.pref_switch_card_view_title)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxWidget(R.string.card_height_title)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxFrame(R.string.card_height_title)).check( matches( - not(isEnabled()) - ) + not(isEnabled()), + ), ) onView(withSettingsCheckboxWidget(R.string.switch_unread_count_title)).check( matches( allOf( - isDisplayed(), isChecked() - ) - ) + isDisplayed(), + isChecked(), + ), + ), ) onView(withId(R.id.settings)).perform(swipeUp()) onView(withSettingsCheckboxWidget(R.string.display_all_counts_title)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) } @@ -120,25 +125,25 @@ class SettingsActivityGeneralTest { // Value check onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(replaceText("AVC")) .check(matches(withText(""))) // TODO: should check message error. Not working for api level 30+ onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(replaceText("-1")) .check(matches(withText(""))) // TODO: should check message error. Not working for api level 30+ onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(replaceText("300")) .check(matches(withText(""))) onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(typeTextIntoFocusedView("300")) .check(matches(withText("30"))) onView( - withId(android.R.id.edit) + withId(android.R.id.edit), ).perform(replaceText("10")) .check(matches(withText("10"))) onView(isRoot()).perform(ViewActions.pressBack()) @@ -157,18 +162,18 @@ class SettingsActivityGeneralTest { // article viewer settings onView(withSettingsCheckboxFrame(R.string.reader_static_bar_title)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) onView(withSettingsCheckboxWidget(R.string.pref_article_viewer_title)).perform(click()) onView(withSettingsCheckboxFrame(R.string.reader_static_bar_title)).check( matches( - not(isEnabled()) - ) + not(isEnabled()), + ), ) onView(withSettingsCheckboxFrame(R.string.card_height_title)).check(matches(not(isEnabled()))) onView(withSettingsCheckboxWidget(R.string.pref_switch_card_view_title)).perform(click()) onView(withSettingsCheckboxFrame(R.string.card_height_title)).check(matches(isEnabled())) } -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityOfflineTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityOfflineTest.kt index c2f192c..26df578 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityOfflineTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityOfflineTest.kt @@ -21,11 +21,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith - @RunWith(AndroidJUnit4::class) @LargeTest class SettingsActivityOfflineTest { - @get:Rule val activityRule = ActivityScenarioRule(LoginActivity::class.java) @@ -38,7 +36,7 @@ class SettingsActivityOfflineTest { } loginAndInitHome() openActionBarOverflowOrOptionsMenu( - ApplicationProvider.getApplicationContext() + ApplicationProvider.getApplicationContext(), ) onView(withText(R.string.title_activity_settings)).perform(click()) onView(withText(R.string.pref_header_offline)).perform(click()) @@ -49,58 +47,63 @@ class SettingsActivityOfflineTest { onView(withSettingsCheckboxWidget(R.string.pref_switch_periodic_refresh)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxWidget(R.string.pref_switch_items_caching)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_items_caching)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) onView(withText(R.string.pref_periodic_refresh_minutes_title)).check( matches( - allOf(isNotEnabled(), isDisplayed()) - ) + allOf(isNotEnabled(), isDisplayed()), + ), ) onView(withSettingsCheckboxWidget(R.string.pref_switch_refresh_when_charging)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_refresh_when_charging)).check( matches( - isNotEnabled() - ) + isNotEnabled(), + ), ) onView(withSettingsCheckboxWidget(R.string.pref_switch_notify_new_items)).check( matches( allOf( - isDisplayed(), not(isChecked()) - ) - ) + isDisplayed(), + not(isChecked()), + ), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_notify_new_items)).check( matches( - isNotEnabled() - ) + isNotEnabled(), + ), ) onView(withSettingsCheckboxWidget(R.string.pref_switch_update_sources)).check( matches( allOf( - isDisplayed(), isChecked() - ) - ) + isDisplayed(), + isChecked(), + ), + ), ) } @@ -111,50 +114,50 @@ class SettingsActivityOfflineTest { onView(withText(R.string.pref_switch_items_caching_on)).check(matches(isDisplayed())) onView(withSettingsCheckboxFrame(R.string.pref_switch_items_caching)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) onView(withText(R.string.pref_periodic_refresh_minutes_title)).check( matches( - isNotEnabled() - ) + isNotEnabled(), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_refresh_when_charging)).check( matches( - isNotEnabled() - ) + isNotEnabled(), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_notify_new_items)).check( matches( - isNotEnabled() - ) + isNotEnabled(), + ), ) onView(withText(R.string.pref_switch_periodic_refresh_off)).check( matches( - isDisplayed() - ) + isDisplayed(), + ), ) onView(withSettingsCheckboxWidget(R.string.pref_switch_periodic_refresh)).perform(click()) onView(withText(R.string.pref_switch_periodic_refresh_on)).check( matches( - isDisplayed() - ) + isDisplayed(), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_periodic_refresh_minutes_title)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_refresh_when_charging)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_notify_new_items)).check( matches( - isEnabled() - ) + isEnabled(), + ), ) changeAndCancelSetting("360", "123") { onView(withText(R.string.pref_periodic_refresh_minutes_title)).perform(click()) @@ -166,4 +169,4 @@ class SettingsActivityOfflineTest { onView(withSettingsCheckboxFrame(R.string.pref_switch_notify_new_items)).perform(click()) onView(withSettingsCheckboxWidget(R.string.pref_switch_update_sources)).perform(click()) } -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityReaderTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityReaderTest.kt index 88e1f27..cf4ffb6 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityReaderTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityReaderTest.kt @@ -19,11 +19,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith - @RunWith(AndroidJUnit4::class) @LargeTest class SettingsActivityReaderTest { - @get:Rule val activityRule = ActivityScenarioRule(LoginActivity::class.java) @@ -36,7 +34,7 @@ class SettingsActivityReaderTest { } loginAndInitHome() openActionBarOverflowOrOptionsMenu( - ApplicationProvider.getApplicationContext() + ApplicationProvider.getApplicationContext(), ) onView(withText(R.string.title_activity_settings)).perform(click()) onView(withText(R.string.pref_header_viewer)).perform(click()) @@ -47,11 +45,12 @@ class SettingsActivityReaderTest { onView(withSettingsCheckboxFrame(R.string.pref_switch_actions_pager_scroll)).check( matches( allOf( - isDisplayed(), not( - isChecked() - ) - ) - ) + isDisplayed(), + not( + isChecked(), + ), + ), + ), ) onView(withText(R.string.pref_content_reader_font_size)).check(matches(isDisplayed())) onView(withText(R.string.settings_reader_font)).check(matches(isDisplayed())) @@ -61,14 +60,14 @@ class SettingsActivityReaderTest { fun testReaderActions() { onView(withText(R.string.pref_switch_actions_pager_scroll_off)).check( matches( - isDisplayed() - ) + isDisplayed(), + ), ) onView(withSettingsCheckboxFrame(R.string.pref_switch_actions_pager_scroll)).perform(click()) onView(withText(R.string.pref_switch_actions_pager_scroll_on)).check( matches( - isDisplayed() - ) + isDisplayed(), + ), ) onView(withText(R.string.pref_content_reader_font_size)).perform(click()) @@ -83,4 +82,4 @@ class SettingsActivityReaderTest { onView(withText(R.string.settings_reader_font)).perform(click()) } } -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityTest.kt index 69101c6..3dcc96b 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SettingsActivityTest.kt @@ -20,7 +20,6 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class SettingsActivityTest { - @get:Rule val activityRule = ActivityScenarioRule(LoginActivity::class.java) lateinit var context: Context @@ -35,10 +34,8 @@ class SettingsActivityTest { onView(withText(R.string.title_activity_settings)).perform(click()) } - @Test fun testAllSettings() { - onView(withText(R.string.pref_header_general)).check(matches(isDisplayed())) onView(withText(R.string.pref_header_viewer)).check(matches(isDisplayed())) onView(withText(R.string.pref_header_offline)).check(matches(isDisplayed())) @@ -48,14 +45,13 @@ class SettingsActivityTest { matches( allOf( isDisplayed(), - not(isSelected()) - ) - ) + not(isSelected()), + ), + ), ) onView(withText(R.string.action_about)).check(matches(isDisplayed())) } - @Test fun testThemes() { testPreferencesFromArray(context, R.array.ModeTitles) { @@ -63,7 +59,6 @@ class SettingsActivityTest { } } - @Test fun testExperimentail() { onView(withText(R.string.pref_header_experimental)).perform(click()) @@ -75,13 +70,11 @@ class SettingsActivityTest { } } - @Test fun testBugReports() { onView(withText(R.string.pref_switch_disable_acra)).perform(click()) } - @Test fun testLinks() { onView(withText(R.string.pref_header_links)).perform(click()) @@ -91,10 +84,9 @@ class SettingsActivityTest { onView(withText(R.string.translation)).check(matches(isDisplayed())) } - @Test fun testAbout() { onView(withText(R.string.action_about)).perform(click()) onView(withText("ACRA")).check(matches(isDisplayed())) } -} \ No newline at end of file +} diff --git a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SourcesActivityTest.kt b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SourcesActivityTest.kt index f7e0a57..53cf67d 100644 --- a/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SourcesActivityTest.kt +++ b/androidApp/src/androidTest/kotlin/bou/amine/apps/readerforselfossv2/android/SourcesActivityTest.kt @@ -41,11 +41,10 @@ class SourcesActivityTest { fun addSource() { testAddSourceWithUrl( "https://lorem-rss.herokuapp.com/feed?unit=year&interval=1&length=10", - sourceName + sourceName, ) } - @Test fun addSourceCheckContent() { testAddSourceWithUrl("https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en", sourceName) @@ -54,7 +53,7 @@ class SourcesActivityTest { onView(withText(R.string.menu_home_refresh)).perform(click()) onView(withText(R.string.refresh_dialog_message)).check(matches(isDisplayed())) onView( - withId(android.R.id.button1) + withId(android.R.id.button1), ).perform(click()) Thread.sleep(10000) onView(withId(R.id.swipeRefreshLayout)).perform(swipeDown()) @@ -74,10 +73,9 @@ class SourcesActivityTest { onView(withText(sourceName)).check(doesNotExist()) } - private fun goToSources() { openMenu() onView(withText(R.string.menu_home_sources)) .perform(click()) } -} \ No newline at end of file +} 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 84a85e8..cc61c85 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/HomeActivity.kt @@ -49,7 +49,10 @@ import org.kodein.di.instance import java.security.MessageDigest import java.util.concurrent.TimeUnit -class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware { +class HomeActivity : + AppCompatActivity(), + SearchView.OnQueryTextListener, + DIAware { private var items: ArrayList = ArrayList() private var elementsShown: ItemType = ItemType.UNREAD @@ -171,11 +174,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar getElementsAccordingToTab() } } else { - Toast.makeText( - this@HomeActivity, - "Found null when swiping at positon $position.", - Toast.LENGTH_LONG, - ).show() + Toast + .makeText( + this@HomeActivity, + "Found null when swiping at positon $position.", + Toast.LENGTH_LONG, + ).show() } } } @@ -200,15 +204,18 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar tabNewBadge = TextBadgeItem() .setText("") - .setHideOnSelect(false).hide(false) + .setHideOnSelect(false) + .hide(false) tabArchiveBadge = TextBadgeItem() .setText("") - .setHideOnSelect(false).hide(false) + .setHideOnSelect(false) + .hide(false) tabStarredBadge = TextBadgeItem() .setText("") - .setHideOnSelect(false).hide(false) + .setHideOnSelect(false) + .hide(false) if (appSettingsService.isDisplayUnreadCountEnabled()) { lifecycleScope.launch { @@ -236,14 +243,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar BottomNavigationItem( R.drawable.ic_tab_fiber_new_black_24dp, getString(R.string.tab_new), - ) - .setBadgeItem(tabNewBadge) + ).setBadgeItem(tabNewBadge) val tabArchive = BottomNavigationItem( R.drawable.ic_tab_archive_black_24dp, getString(R.string.tab_read), - ) - .setBadgeItem(tabArchiveBadge) + ).setBadgeItem(tabArchiveBadge) val tabStarred = BottomNavigationItem( R.drawable.ic_tab_favorite_black_24dp, @@ -425,17 +430,17 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar binding.recyclerView.addOnScrollListener(recyclerViewScrollListener) } - private fun getLastVisibleItem(): Int { - return when (val manager = binding.recyclerView.layoutManager) { + private fun getLastVisibleItem(): Int = + when (val manager = binding.recyclerView.layoutManager) { is StaggeredGridLayoutManager -> - manager.findLastCompletelyVisibleItemPositions( - null, - ).last() + manager + .findLastCompletelyVisibleItemPositions( + null, + ).last() is GridLayoutManager -> manager.findLastCompletelyVisibleItemPosition() else -> 0 } - } private fun mayBeEmpty() = if (items.isEmpty()) { @@ -577,7 +582,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar messageRes: Int, doFn: () -> Unit, ) { - AlertDialog.Builder(this@HomeActivity) + AlertDialog + .Builder(this@HomeActivity) .setMessage(messageRes) .setTitle(titleRes) .setPositiveButton(android.R.string.ok) { _, _ -> doFn() } @@ -589,7 +595,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.issue_tracker -> { - baseContext.openUrlInBrowser(AppSettingsService.trackerUrl) + baseContext.openUrlInBrowser(AppSettingsService.BUG_URL) return true } @@ -606,18 +612,19 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar CoroutineScope(Dispatchers.Main).launch { val updatedRemote = repository.updateRemote() if (updatedRemote) { - Toast.makeText( - this@HomeActivity, - R.string.refresh_success_response, - Toast.LENGTH_LONG, - ) - .show() + Toast + .makeText( + this@HomeActivity, + R.string.refresh_success_response, + Toast.LENGTH_LONG, + ).show() } else { - Toast.makeText( - this@HomeActivity, - R.string.refresh_failer_message, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + this@HomeActivity, + R.string.refresh_failer_message, + Toast.LENGTH_SHORT, + ).show() } CountingIdlingResourceSingleton.decrement() } @@ -633,25 +640,26 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar CoroutineScope(Dispatchers.Main).launch { val success = repository.markAllAsRead(items) if (success) { - Toast.makeText( - this@HomeActivity, - R.string.all_posts_read, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + this@HomeActivity, + R.string.all_posts_read, + Toast.LENGTH_SHORT, + ).show() tabNewBadge.removeBadge() getElementsAccordingToTab() } else { - Toast.makeText( - this@HomeActivity, - R.string.all_posts_not_read, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + this@HomeActivity, + R.string.all_posts_not_read, + Toast.LENGTH_SHORT, + ).show() } handleListResult() binding.swipeRefreshLayout.isRefreshing = false CountingIdlingResourceSingleton.decrement() - } } } @@ -661,7 +669,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar R.id.action_disconnect -> { needsConfirmation( R.string.confirm_disconnect_title, - R.string.confirm_disconnect_description + R.string.confirm_disconnect_description, ) { runBlocking { repository.logout() @@ -702,7 +710,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar private fun handleRecurringTask() { if (appSettingsService.isPeriodicRefreshEnabled()) { val myConstraints = - Constraints.Builder() + Constraints + .Builder() .setRequiresBatteryNotLow(true) .setRequiresCharging(appSettingsService.isRefreshWhenChargingOnlyEnabled()) .setRequiresStorageNotLow(true) @@ -711,19 +720,19 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar val backgroundWork = PeriodicWorkRequestBuilder( appSettingsService.getRefreshMinutes(), - TimeUnit.MINUTES - ) - .setConstraints(myConstraints) + TimeUnit.MINUTES, + ).setConstraints(myConstraints) .addTag("selfoss-loading") .build() - WorkManager.getInstance( - baseContext, - ).enqueueUniquePeriodicWork( - "selfoss-loading", - ExistingPeriodicWorkPolicy.KEEP, - backgroundWork - ) + WorkManager + .getInstance( + baseContext, + ).enqueueUniquePeriodicWork( + "selfoss-loading", + ExistingPeriodicWorkPolicy.KEEP, + backgroundWork, + ) } } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ImageActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ImageActivity.kt index 6221b6e..516c8bf 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ImageActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ImageActivity.kt @@ -84,7 +84,9 @@ class ImageActivity : AppCompatActivity() { return super.onOptionsItemSelected(item) } - private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) { + private inner class ScreenSlidePagerAdapter( + fa: FragmentActivity, + ) : FragmentStateAdapter(fa) { override fun getItemCount(): Int = allImages.size override fun createFragment(position: Int): Fragment = ImageFragment.newInstance(allImages[position]) 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 81b0b5a..29f1234 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 @@ -30,7 +30,9 @@ 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 isWithLogin = false @@ -108,7 +110,7 @@ class LoginActivity : AppCompatActivity(), DIAware { repository.updateApiInformation() ACRA.errorReporter.putCustomData( "SELFOSS_API_VERSION", - appSettingsService.getApiVersion().toString() + appSettingsService.getApiVersion().toString(), ) CountingIdlingResourceSingleton.decrement() } @@ -132,9 +134,18 @@ class LoginActivity : AppCompatActivity(), DIAware { binding.passwordView.error = null // Store values at the time of the login attempt. - val url = binding.urlView.text.toString().trim() - val login = binding.loginView.text.toString().trim() - val password = binding.passwordView.text.toString().trim() + val url = + binding.urlView.text + .toString() + .trim() + val login = + binding.loginView.text + .toString() + .trim() + val password = + binding.passwordView.text + .toString() + .trim() failInvalidUrl(url) failLoginDetails(password, login) @@ -151,11 +162,12 @@ class LoginActivity : AppCompatActivity(), DIAware { repository.updateApiInformation() } catch (e: Exception) { if (e.message?.startsWith("No transformation found") == true) { - Toast.makeText( - applicationContext, - R.string.application_selfoss_only, - Toast.LENGTH_LONG, - ).show() + Toast + .makeText( + applicationContext, + R.string.application_selfoss_only, + Toast.LENGTH_LONG, + ).show() preferenceError() showProgress(false) } @@ -270,7 +282,7 @@ class LoginActivity : AppCompatActivity(), DIAware { return when (item.itemId) { R.id.issue_tracker -> { val browserIntent = - Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl)) + Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.BUG_URL)) startActivity(browserIntent) return true } @@ -280,9 +292,9 @@ class LoginActivity : AppCompatActivity(), DIAware { .withAboutIconShown(true) .withAboutVersionShown(true) .withAboutSpecial2("Bug reports") - .withAboutSpecial2Description(AppSettingsService.trackerUrl) + .withAboutSpecial2Description(AppSettingsService.BUG_URL) .withAboutSpecial1("Project Page") - .withAboutSpecial1Description(AppSettingsService.sourceUrl) + .withAboutSpecial1Description(AppSettingsService.SOURCE_URL) .start(this) true } @@ -290,4 +302,4 @@ class LoginActivity : AppCompatActivity(), DIAware { else -> super.onOptionsItemSelected(item) } } -} \ No newline at end of file +} 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 b23b3ba..c5c123d 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/MyApp.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/MyApp.kt @@ -9,11 +9,11 @@ import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner import androidx.multidex.MultiDexApplication -import bou.amine.apps.readerforselfossv2.DI.networkModule import bou.amine.apps.readerforselfossv2.android.testing.TestingHelper 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.di.networkModule import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.service.AppSettingsService import com.github.ln_12.library.ConnectivityStatus @@ -36,21 +36,23 @@ import org.kodein.di.bind import org.kodein.di.instance import org.kodein.di.singleton -class MyApp : MultiDexApplication(), DIAware { +class MyApp : + MultiDexApplication(), + DIAware { override val di by DI.lazy { bind() with singleton { AppSettingsService(ACRA.isACRASenderServiceProcess() || TestingHelper().isUnitTest()) } import(networkModule) bind() with singleton { DriverFactory(applicationContext) } bind() with singleton { ReaderForSelfossDB(driverFactory.createDriver()) } bind() with - singleton { - Repository( - instance(), - instance(), - isConnectionAvailable, - instance(), - ) - } + singleton { + Repository( + instance(), + instance(), + isConnectionAvailable, + instance(), + ) + } bind() with singleton { ConnectivityStatus(applicationContext) } bind() with singleton { AppViewModel(repository = instance()) } } @@ -89,11 +91,12 @@ class MyApp : MultiDexApplication(), DIAware { R.string.network_connectivity_lost } - Toast.makeText( - applicationContext, - toastMessage, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + applicationContext, + toastMessage, + Toast.LENGTH_SHORT, + ).show() } } } @@ -151,13 +154,13 @@ class MyApp : MultiDexApplication(), DIAware { val name = getString(R.string.notification_channel_sync) val importance = NotificationManager.IMPORTANCE_LOW - val mChannel = NotificationChannel(AppSettingsService.syncChannelId, name, importance) + val mChannel = NotificationChannel(AppSettingsService.SYNC_CHANNEL_ID, name, importance) val newItemsChannelname = getString(R.string.new_items_channel_sync) val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT val newItemsChannelmChannel = NotificationChannel( - AppSettingsService.newItemsChannelId, + AppSettingsService.NEW_ITEMS_CHANNEL, newItemsChannelname, newItemsChannelimportance, ) @@ -199,4 +202,4 @@ class MyApp : MultiDexApplication(), DIAware { super.onPause(owner) } } -} \ No newline at end of file +} 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 dd645a5..c5a4bbc 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 @@ -22,7 +22,9 @@ import org.kodein.di.DIAware import org.kodein.di.android.closestDI import org.kodein.di.instance -class ReaderActivity : AppCompatActivity(), DIAware { +class ReaderActivity : + AppCompatActivity(), + DIAware { private var currentItem: Int = 0 private lateinit var toolbarMenu: Menu @@ -99,19 +101,19 @@ class ReaderActivity : AppCompatActivity(), DIAware { oldInstanceState.clear() } - private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : - FragmentStateAdapter(fa) { + private inner class ScreenSlidePagerAdapter( + fa: FragmentActivity, + ) : FragmentStateAdapter(fa) { override fun getItemCount(): Int = allItems.size - override fun createFragment(position: Int): Fragment = - ArticleFragment.newInstance(allItems[position]) + override fun createFragment(position: Int): Fragment = ArticleFragment.newInstance(allItems[position]) } override fun onKeyDown( keyCode: Int, event: KeyEvent?, - ): Boolean { - return when (keyCode) { + ): Boolean = + when (keyCode) { KeyEvent.KEYCODE_VOLUME_DOWN -> { val currentFragment = supportFragmentManager.findFragmentByTag("f" + binding.pager.currentItem) as ArticleFragment @@ -130,7 +132,6 @@ class ReaderActivity : AppCompatActivity(), DIAware { super.onKeyDown(keyCode, event) } } - } private fun alignmentMenu() { val showJustify = appSettingsService.getActiveAllignment() == AppSettingsService.ALIGN_LEFT @@ -229,4 +230,4 @@ class ReaderActivity : AppCompatActivity(), DIAware { startActivity(intent) overridePendingTransition(0, 0) } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt index f322627..70745e3 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/SourcesActivity.kt @@ -18,7 +18,9 @@ import org.kodein.di.DIAware import org.kodein.di.android.closestDI import org.kodein.di.instance -class SourcesActivity : AppCompatActivity(), DIAware { +class SourcesActivity : + AppCompatActivity(), + DIAware { private lateinit var binding: ActivitySourcesBinding override val di by closestDI() @@ -68,11 +70,12 @@ class SourcesActivity : AppCompatActivity(), DIAware { binding.recyclerView.adapter = mAdapter mAdapter.notifyDataSetChanged() } else { - Toast.makeText( - this@SourcesActivity, - R.string.cant_get_sources, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + this@SourcesActivity, + R.string.cant_get_sources, + Toast.LENGTH_SHORT, + ).show() } CountingIdlingResourceSingleton.decrement() } @@ -81,4 +84,4 @@ class SourcesActivity : AppCompatActivity(), DIAware { startActivity(Intent(this@SourcesActivity, UpsertSourceActivity::class.java)) } } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/UpsertSourceActivity.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/UpsertSourceActivity.kt index a6b93d8..98c27e5 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/UpsertSourceActivity.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/UpsertSourceActivity.kt @@ -21,7 +21,9 @@ import org.kodein.di.DIAware import org.kodein.di.android.closestDI import org.kodein.di.instance -class UpsertSourceActivity : AppCompatActivity(), DIAware { +class UpsertSourceActivity : + AppCompatActivity(), + DIAware { private var existingSource: SelfossModel.SourceDetail? = null private var mSpoutsValue: String? = null @@ -105,11 +107,12 @@ class UpsertSourceActivity : AppCompatActivity(), DIAware { } fun handleSpoutFailure(networkIssue: Boolean = false) { - Toast.makeText( - this@UpsertSourceActivity, - if (networkIssue) R.string.cant_get_spouts_no_network else R.string.cant_get_spouts, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + this@UpsertSourceActivity, + if (networkIssue) R.string.cant_get_spouts_no_network else R.string.cant_get_spouts, + Toast.LENGTH_SHORT, + ).show() binding.progress.visibility = View.GONE } @@ -192,11 +195,12 @@ class UpsertSourceActivity : AppCompatActivity(), DIAware { if (successfullyAddedSource) { finish() } else { - Toast.makeText( - this@UpsertSourceActivity, - R.string.cant_create_source, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + this@UpsertSourceActivity, + R.string.cant_create_source, + Toast.LENGTH_SHORT, + ).show() } } } 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 3f2de89..894af9e 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 @@ -49,7 +49,10 @@ class ItemCardAdapter( return ViewHolder(binding) } - private fun handleClickListeners(holderBinding: CardItemBinding, position: Int) { + private fun handleClickListeners( + holderBinding: CardItemBinding, + position: Int, + ) { holderBinding.favButton.setOnClickListener { val item = items[position] if (item.starred) { @@ -96,12 +99,13 @@ class ItemCardAdapter( binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) - binding.sourceTitleAndDate.text = try { - itm.sourceAuthorAndDate() - } catch (e: Exception) { - e.sendSilentlyWithAcraWithName("ItemCardAdapter parse date") - itm.sourceAuthorOnly() - } + binding.sourceTitleAndDate.text = + try { + itm.sourceAuthorAndDate() + } catch (e: Exception) { + e.sendSilentlyWithAcraWithName("ItemCardAdapter parse date") + itm.sourceAuthorOnly() + } if (!appSettingsService.isFullHeightCardsEnabled()) { binding.itemImage.maxHeight = imageMaxHeight @@ -125,5 +129,7 @@ class ItemCardAdapter( } } - inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) -} \ No newline at end of file + inner class ViewHolder( + val binding: CardItemBinding, + ) : RecyclerView.ViewHolder(binding.root) +} 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 f6a48b5..a8e0256 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 @@ -53,12 +53,13 @@ class ItemListAdapter( binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent)) - binding.sourceTitleAndDate.text = try { - itm.sourceAuthorAndDate() - } catch (e: Exception) { - e.sendSilentlyWithAcraWithName("ItemListAdapter parse date") - itm.sourceAuthorOnly() - } + binding.sourceTitleAndDate.text = + try { + itm.sourceAuthorAndDate() + } catch (e: Exception) { + e.sendSilentlyWithAcraWithName("ItemListAdapter parse date") + itm.sourceAuthorOnly() + } if (itm.getThumbnail(repository.baseUrl).isEmpty()) { if (itm.getIcon(repository.baseUrl).isEmpty()) { @@ -72,5 +73,7 @@ class ItemListAdapter( } } - inner class ViewHolder(val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) -} \ No newline at end of file + inner class ViewHolder( + val binding: ListItemBinding, + ) : RecyclerView.ViewHolder(binding.root) +} 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 e3ea18c..79391a6 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 @@ -18,7 +18,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.kodein.di.DIAware -abstract class ItemsAdapter : RecyclerView.Adapter(), DIAware { +abstract class ItemsAdapter : + RecyclerView.Adapter(), + DIAware { abstract val items: ArrayList abstract val repository: Repository abstract val binding: ViewBinding @@ -45,8 +47,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG, - ) - .setAction(R.string.undo_string) { + ).setAction(R.string.undo_string) { unreadItemAtIndex(item, position, false) } @@ -66,8 +67,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte app.findViewById(R.id.coordLayout), R.string.marked_as_unread, Snackbar.LENGTH_LONG, - ) - .setAction(R.string.undo_string) { + ).setAction(R.string.undo_string) { readItemAtIndex(item, position, false) } @@ -77,7 +77,10 @@ abstract class ItemsAdapter : RecyclerView.Adapte s.show() } - protected fun handleLinkOpening(holderBinding: ViewBinding, position: Int) { + protected fun handleLinkOpening( + holderBinding: ViewBinding, + position: Int, + ) { holderBinding.root.setOnClickListener { repository.setReaderItems(items) c.openItemUrl( 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 069e227..1998cab 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 @@ -29,7 +29,8 @@ import org.kodein.di.instance class SourcesListAdapter( private val app: Activity, private val items: ArrayList, -) : RecyclerView.Adapter(), DIAware { +) : RecyclerView.Adapter(), + DIAware { private val c: Context = app.baseContext private lateinit var binding: SourceListItemBinding @@ -61,11 +62,12 @@ class SourcesListAdapter( notifyItemRemoved(position) notifyItemRangeChanged(position, itemCount) } else { - Toast.makeText( - app, - R.string.can_delete_source, - Toast.LENGTH_SHORT, - ).show() + Toast + .makeText( + app, + R.string.can_delete_source, + Toast.LENGTH_SHORT, + ).show() } } } @@ -99,5 +101,7 @@ class SourcesListAdapter( override fun getItemCount(): Int = items.size - inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) + inner class ViewHolder( + val mView: ConstraintLayout, + ) : RecyclerView.ViewHolder(mView) } 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/LoadingWorker.kt similarity index 85% rename from androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/background/background.kt rename to androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/background/LoadingWorker.kt index 8e0bc89..955ee80 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/LoadingWorker.kt @@ -23,11 +23,13 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.kodein.di.DIAware import org.kodein.di.instance -import java.util.* +import java.util.Timer import kotlin.concurrent.schedule -class LoadingWorker(val context: Context, params: WorkerParameters) : - Worker(context, params), +class LoadingWorker( + val context: Context, + params: WorkerParameters, +) : Worker(context, params), DIAware { override val di by lazy { (applicationContext as MyApp).di } private val repository: Repository by instance() @@ -40,12 +42,13 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notification = - NotificationCompat.Builder(applicationContext, AppSettingsService.syncChannelId) + NotificationCompat + .Builder(applicationContext, AppSettingsService.SYNC_CHANNEL_ID) .setContentTitle(context.getString(R.string.loading_notification_title)) .setContentText(context.getString(R.string.loading_notification_text)) .setOngoing(true) .setPriority(PRIORITY_LOW) - .setChannelId(AppSettingsService.syncChannelId) + .setChannelId(AppSettingsService.SYNC_CHANNEL_ID) .setSmallIcon(R.drawable.ic_stat_cloud_download_black_24dp) notificationManager.notify(1, notification.build()) @@ -87,19 +90,18 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : PendingIntent.getActivity(context, 0, intent, pflags) val newItemsNotification = - NotificationCompat.Builder( - applicationContext, - AppSettingsService.newItemsChannelId, - ) - .setContentTitle(context.getString(R.string.new_items_notification_title)) + NotificationCompat + .Builder( + applicationContext, + AppSettingsService.NEW_ITEMS_CHANNEL, + ).setContentTitle(context.getString(R.string.new_items_notification_title)) .setContentText( context.getString( R.string.new_items_notification_text, newSize, ), - ) - .setPriority(PRIORITY_DEFAULT) - .setChannelId(AppSettingsService.newItemsChannelId) + ).setPriority(PRIORITY_DEFAULT) + .setChannelId(AppSettingsService.NEW_ITEMS_CHANNEL) .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 df42e99..d450ed6 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 @@ -66,7 +66,9 @@ import java.util.concurrent.ExecutionException private const val IMAGE_JPG = "image/jpg" -class ArticleFragment : Fragment(), DIAware { +class ArticleFragment : + Fragment(), + DIAware { private var fontSize: Int = 16 private lateinit var item: SelfossModel.Item private lateinit var url: String @@ -115,12 +117,13 @@ class ArticleFragment : Fragment(), DIAware { contentText = item.content contentTitle = item.title.getHtmlDecoded() contentImage = item.getThumbnail(repository.baseUrl) - contentSource = try { - item.sourceAuthorAndDate() - } catch (e: Exception) { - e.sendSilentlyWithAcraWithName("Article Fragment parse date") - item.sourceAuthorOnly() - } + contentSource = + try { + item.sourceAuthorAndDate() + } catch (e: Exception) { + e.sendSilentlyWithAcraWithName("Article Fragment parse date") + item.sourceAuthorOnly() + } allImages = item.getImages() fontSize = appSettingsService.getFontSize() @@ -166,7 +169,8 @@ class ArticleFragment : Fragment(), DIAware { } catch (e: InflateException) { e.sendSilentlyWithAcraWithName("webview not available") try { - AlertDialog.Builder(requireContext()) + AlertDialog + .Builder(requireContext()) .setMessage(requireContext().getString(R.string.webview_dialog_issue_message)) .setTitle(requireContext().getString(R.string.webview_dialog_issue_title)) .setPositiveButton( @@ -174,8 +178,7 @@ class ArticleFragment : Fragment(), DIAware { ) { _, _ -> appSettingsService.disableArticleViewer() requireActivity().finish() - } - .create() + }.create() .show() } catch (e: IllegalStateException) { e.sendSilentlyWithAcraWithName("Context required is null") @@ -234,21 +237,23 @@ class ArticleFragment : Fragment(), DIAware { repository.markAsRead(this@ArticleFragment.item) } this@ArticleFragment.item.unread = false - Toast.makeText( - requireContext(), - R.string.marked_as_read, - Toast.LENGTH_LONG, - ).show() + Toast + .makeText( + requireContext(), + R.string.marked_as_read, + Toast.LENGTH_LONG, + ).show() } else { CoroutineScope(Dispatchers.IO).launch { repository.unmarkAsRead(this@ArticleFragment.item) } this@ArticleFragment.item.unread = true - Toast.makeText( - context, - R.string.marked_as_unread, - Toast.LENGTH_LONG, - ).show() + Toast + .makeText( + context, + R.string.marked_as_unread, + Toast.LENGTH_LONG, + ).show() } } catch (e: IllegalStateException) { e.sendSilentlyWithAcraWithName("Context required is null") @@ -321,8 +326,7 @@ class ArticleFragment : Fragment(), DIAware { .asBitmap() .load( lead_image_url, - ) - .apply(RequestOptions.fitCenterTransform()) + ).apply(RequestOptions.fitCenterTransform()) .into(binding.imageView) } else { binding.imageView.visibility = View.GONE @@ -336,14 +340,16 @@ class ArticleFragment : Fragment(), DIAware { override fun shouldOverrideUrlLoading( view: WebView?, url: String, - ): Boolean { - return if (context != null && url.isUrlValid() && binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { + ): Boolean = + if (context != null && + url.isUrlValid() && + binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE + ) { requireContext().openUrlInBrowser(url) true } else { false } - } @Deprecated("Deprecated in Java") override fun shouldInterceptRequest( @@ -352,12 +358,18 @@ class ArticleFragment : Fragment(), DIAware { ): WebResourceResponse? { val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) if (url.lowercase(Locale.US).contains(".jpg") || - url.lowercase(Locale.US) + url + .lowercase(Locale.US) .contains(".jpeg") ) { try { val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() + Glide + .with(view) + .asBitmap() + .apply(glideOptions) + .load(url) + .submit() .get() return WebResourceResponse( IMAGE_JPG, @@ -370,7 +382,12 @@ class ArticleFragment : Fragment(), DIAware { } else if (url.lowercase(Locale.US).contains(".png")) { try { val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() + Glide + .with(view) + .asBitmap() + .apply(glideOptions) + .load(url) + .submit() .get() return WebResourceResponse( IMAGE_JPG, @@ -383,7 +400,12 @@ class ArticleFragment : Fragment(), DIAware { } else if (url.lowercase(Locale.US).contains(".webp")) { try { val image = - Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() + Glide + .with(view) + .asBitmap() + .apply(glideOptions) + .load(url) + .submit() .get() return WebResourceResponse( IMAGE_JPG, @@ -422,7 +444,6 @@ class ArticleFragment : Fragment(), DIAware { context.theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true) context.theme.resolveAttribute(R.attr.colorSurface, colorSurface, true) - } catch (e: IllegalStateException) { e.sendSilentlyWithAcraWithName("Context issue when setting attributes, but context wasn't null before") } @@ -450,15 +471,13 @@ class ArticleFragment : Fragment(), DIAware { GestureDetector( activity, object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapUp(e: MotionEvent): Boolean { - return performClick() - } + override fun onSingleTapUp(e: MotionEvent): Boolean = performClick() }, ) binding.webcontent.setOnTouchListener { _, event -> gestureDetector.onTouchEvent( - event + event, ) } @@ -597,10 +616,11 @@ class ArticleFragment : Fragment(), DIAware { } fun performClick(): Boolean { - if (allImages != null && ( - binding.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || - binding.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE - ) + if (allImages != null && + ( + binding.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || + binding.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE + ) ) { val position: Int = allImages.indexOf(binding.webcontent.hitTestResult.extra) @@ -612,4 +632,4 @@ class ArticleFragment : Fragment(), DIAware { } return false } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt index 7af823f..307d3ac 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/FilterSheetFragment.kt @@ -33,7 +33,9 @@ import org.kodein.di.DIAware import org.kodein.di.android.x.closestDI import org.kodein.di.instance -class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { +class FilterSheetFragment : + BottomSheetDialogFragment(), + DIAware { private lateinit var binding: FilterFragmentBinding override val di: DI by closestDI() private val repository: Repository by instance() @@ -80,7 +82,8 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { val c = Chip(context) c.ellipsize = TextUtils.TruncateAt.END - Glide.with(context) + Glide + .with(context) .load(source.getIcon(repository.baseUrl)) .into( object : ViewTarget(c) { @@ -190,4 +193,4 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { companion object { const val TAG = "FilterModalBottomSheet" } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt index b9c68e0..3a4e023 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt @@ -14,7 +14,7 @@ class ImageFragment : Fragment() { private lateinit var imageUrl: String private val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) private var _binding: FragmentImageBinding? = null - private val binding get() = _binding + val binding get() = _binding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -31,7 +31,8 @@ class ImageFragment : Fragment() { val view = binding?.root binding!!.photoView.visibility = View.VISIBLE - Glide.with(requireActivity()) + Glide + .with(requireActivity()) .asBitmap() .apply(glideOptions) .load(imageUrl) diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/model/AndroidIModelUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/model/AndroidIModelUtils.kt index 2898e9f..5c5f32e 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/model/AndroidIModelUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/model/AndroidIModelUtils.kt @@ -17,9 +17,12 @@ fun SelfossModel.Item.preloadImages(context: Context): Boolean { try { for (url in imageUrls) { if (URLUtil.isValidUrl(url)) { - Glide.with(context).asBitmap() + Glide + .with(context) + .asBitmap() .apply(glideOptions) - .load(url).submit() + .load(url) + .submit() } } } catch (e: Error) { @@ -40,4 +43,4 @@ fun String.toTextDrawableString(): String { } } return textDrawable.toString() -} \ No newline at end of file +} 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 f0594fe..adce9bb 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 @@ -64,15 +64,14 @@ class SettingsActivity : outState.putCharSequence(TITLE_TAG, title) } - override fun onSupportNavigateUp(): Boolean { - return if (supportFragmentManager.popBackStackImmediate()) { + override fun onSupportNavigateUp(): Boolean = + if (supportFragmentManager.popBackStackImmediate()) { supportActionBar?.title = getText(R.string.title_activity_settings) false } else { super.onBackPressed() true } - } override fun onPreferenceStartFragment( caller: PreferenceFragmentCompat, @@ -81,15 +80,17 @@ class SettingsActivity : // Instantiate the new Fragment val args = pref.extras val fragment = - supportFragmentManager.fragmentFactory.instantiate( - classLoader, - pref.fragment.toString(), - ).apply { - arguments = args - setTargetFragment(caller, 0) - } + supportFragmentManager.fragmentFactory + .instantiate( + classLoader, + pref.fragment.toString(), + ).apply { + arguments = args + setTargetFragment(caller, 0) + } // Replace the existing Fragment with the new Fragment - supportFragmentManager.beginTransaction() + supportFragmentManager + .beginTransaction() .replace(R.id.settings, fragment) .addToBackStack(null) .commit() @@ -108,7 +109,7 @@ class SettingsActivity : preferenceManager.findPreference(CURRENT_THEME)?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> AppCompatDelegate.setDefaultNightMode( - newValue.toString().toInt() + newValue.toString().toInt(), ) // ListPreference Only takes string-arrays ¯\_(ツ)_/¯ true } @@ -144,11 +145,12 @@ class SettingsActivity : val input: Int = (dest.toString() + source.toString()).toInt() if (input in 1..200) return@InputFilter null } catch (nfe: NumberFormatException) { - Toast.makeText( - activity, - R.string.items_number_should_be_number, - Toast.LENGTH_LONG - ).show() + Toast + .makeText( + activity, + R.string.items_number_should_be_number, + Toast.LENGTH_LONG, + ).show() } "" }, @@ -234,19 +236,19 @@ class SettingsActivity : preferenceManager.findPreference("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(AppSettingsService.trackerUrl) + openUrl(AppSettingsService.BUG_URL) true } preferenceManager.findPreference("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(AppSettingsService.sourceUrl) + openUrl(AppSettingsService.SOURCE_URL) false } preferenceManager.findPreference("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrl(AppSettingsService.translationUrl) + openUrl(AppSettingsService.TRANSLATION_URL) false } } @@ -260,4 +262,4 @@ class SettingsActivity : setPreferencesFromResource(R.xml.pref_experimental, rootKey) } } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/CountingIdlingResourceSingleton.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/CountingIdlingResourceSingleton.kt index 089ba63..b134a83 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/CountingIdlingResourceSingleton.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/CountingIdlingResourceSingleton.kt @@ -3,7 +3,6 @@ package bou.amine.apps.readerforselfossv2.android.testing import androidx.test.espresso.idling.CountingIdlingResource object CountingIdlingResourceSingleton { - private const val RESOURCE = "GLOBAL" @JvmField @@ -18,4 +17,4 @@ object CountingIdlingResourceSingleton { countingIdlingResource.decrement() } } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/TestingHelper.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/TestingHelper.kt index 897465c..56abc2a 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/TestingHelper.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/testing/TestingHelper.kt @@ -2,7 +2,6 @@ package bou.amine.apps.readerforselfossv2.android.testing import android.os.Build - class TestingHelper { fun isUnitTest(): Boolean { var device = Build.DEVICE @@ -16,4 +15,4 @@ class TestingHelper { } return device == "robolectric" && product == "robolectric" } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt index f67830d..4bbeaa5 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/AppUtils.kt @@ -16,9 +16,10 @@ fun Context.shareLink( sendIntent.putExtra(Intent.EXTRA_SUBJECT, itemTitle) sendIntent.type = "text/plain" startActivity( - Intent.createChooser( - sendIntent, - getString(R.string.share), - ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), + Intent + .createChooser( + sendIntent, + getString(R.string.share), + ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), ) } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/CircleImageView.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/CircleImageView.kt index 31ff749..c6d227d 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/CircleImageView.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/CircleImageView.kt @@ -59,7 +59,5 @@ class CircleImageView textView.text = text.toTextDrawableString() } - private fun colorFromIdentifier(key: String): Int { - return colorScheme[abs(key.hashCode()) % colorScheme.size] - } + private fun colorFromIdentifier(key: String): Int = colorScheme[abs(key.hashCode()) % colorScheme.size] } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt index ddc4752..5f546ee 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/LinksUtils.kt @@ -18,7 +18,6 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp import okhttp3.HttpUrl.Companion.toHttpUrlOrNull - fun Context.openItemUrl( currentItem: Int, linkDecoded: String, @@ -26,11 +25,12 @@ fun Context.openItemUrl( app: Activity, ) { if (!linkDecoded.isUrlValid()) { - Toast.makeText( - this, - this.getString(R.string.cant_open_invalid_url), - Toast.LENGTH_LONG, - ).show() + Toast + .makeText( + this, + this.getString(R.string.cant_open_invalid_url), + Toast.LENGTH_LONG, + ).show() } else { if (articleViewer) { val intent = Intent(this, ReaderActivity::class.java) @@ -42,8 +42,7 @@ fun Context.openItemUrl( } } -fun String.isUrlValid(): Boolean = - this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches() +fun String.isUrlValid(): Boolean = this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches() fun String.isBaseUrlInvalid(): Boolean { val baseUrl = this.toHttpUrlOrNull() @@ -61,7 +60,6 @@ fun Context.openItemUrlInBrowserAsNewTask(i: SelfossModel.Item) { } fun Context.openUrlInBrowserAsNewTask(url: String) { - val intent = Intent(Intent.ACTION_VIEW) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK intent.data = Uri.parse(url) @@ -80,7 +78,6 @@ fun Context.mayBeStartActivity(intent: Intent) { } catch (e: ActivityNotFoundException) { Toast.makeText(this, getString(R.string.no_browser), Toast.LENGTH_SHORT).show() } - } class LinkOnTouchListener : View.OnTouchListener { @@ -122,4 +119,4 @@ class LinkOnTouchListener : View.OnTouchListener { } return ret } -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/ACRAUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/ACRAUtils.kt index b6e6199..63751a3 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/ACRAUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/ACRAUtils.kt @@ -6,4 +6,4 @@ import org.acra.ktx.sendSilentlyWithAcra fun Throwable.sendSilentlyWithAcraWithName(name: String) { ACRA.errorReporter.putCustomData("error_source", name) this.sendSilentlyWithAcra() -} \ No newline at end of file +} diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/AcraReportingAdministrator.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/AcraReportingAdministrator.kt index 0ac5463..0ece4fb 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/AcraReportingAdministrator.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/utils/acra/AcraReportingAdministrator.kt @@ -8,22 +8,19 @@ import org.acra.config.CoreConfiguration import org.acra.config.ReportingAdministrator import org.acra.data.CrashReportData - @AutoService(ReportingAdministrator::class) class AcraReportingAdministrator : ReportingAdministrator { override fun shouldStartCollecting( context: Context, config: CoreConfiguration, - reportBuilder: ReportBuilder - ): Boolean { - return reportBuilder.exception !is DeadSystemException && (reportBuilder.exception != null && reportBuilder.exception!!::class.simpleName != "CannotDeliverBroadcastException") - } + reportBuilder: ReportBuilder, + ): Boolean = + reportBuilder.exception !is DeadSystemException && + (reportBuilder.exception != null && reportBuilder.exception!!::class.simpleName != "CannotDeliverBroadcastException") override fun shouldSendReport( context: Context, config: CoreConfiguration, - crashReportData: CrashReportData - ): Boolean { - return crashReportData.get("BRAND") != "redroid" - } -} \ No newline at end of file + crashReportData: CrashReportData, + ): Boolean = crashReportData.get("BRAND") != "redroid" +} 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 67b8906..2c083a8 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 @@ -13,7 +13,8 @@ import java.io.InputStream fun Context.bitmapCenterCrop( url: String, iv: ImageView, -) = Glide.with(this) +) = Glide + .with(this) .asBitmap() .load(url) .apply(RequestOptions.centerCropTransform()) @@ -25,7 +26,8 @@ fun Context.circularDrawable( ) { view.textView.text = "" - Glide.with(this) + Glide + .with(this) .load(url) .into(view.imageView) } diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/viewmodel/AppViewModel.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/viewmodel/AppViewModel.kt index 7cc0a81..2b73e01 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/viewmodel/AppViewModel.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/viewmodel/AppViewModel.kt @@ -7,7 +7,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch -class AppViewModel(private val repository: Repository) : ViewModel() { +class AppViewModel( + private val repository: Repository, +) : ViewModel() { private val _networkAvailableProvider = MutableSharedFlow() val networkAvailableProvider = _networkAvailableProvider.asSharedFlow() private var wasConnected = true @@ -19,11 +21,10 @@ class AppViewModel(private val repository: Repository) : ViewModel() { if (isConnected && !wasConnected && repository.connectionMonitored) { _networkAvailableProvider.emit(true) wasConnected = true - } else if (!isConnected && wasConnected && repository.connectionMonitored) - { - _networkAvailableProvider.emit(false) - wasConnected = false - } + } else if (!isConnected && wasConnected && repository.connectionMonitored) { + _networkAvailableProvider.emit(false) + wasConnected = false + } } } } diff --git a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/helpers.kt b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/Helpers.kt similarity index 85% rename from androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/helpers.kt rename to androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/Helpers.kt index 319538f..51ebb26 100644 --- a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/helpers.kt +++ b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/Helpers.kt @@ -11,13 +11,17 @@ fun dialogMessage(): String { return latestDialog.findViewById(android.R.id.message)?.text.toString() } -fun Menu.assertClickable(@IdRes id: Int) { +fun Menu.assertClickable( + @IdRes id: Int, +) { this.assertVisible(id) val item = this.findItem(id) assertTrue(item.isEnabled) } -fun Menu.assertVisible(@IdRes id: Int) { +fun Menu.assertVisible( + @IdRes id: Int, +) { val item = this.findItem(id) assertTrue(item.isVisible) -} \ No newline at end of file +} diff --git a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/LoginActivityTest.kt b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/LoginActivityTest.kt index 2dd513c..5eba600 100644 --- a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/LoginActivityTest.kt +++ b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/LoginActivityTest.kt @@ -11,10 +11,8 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.Robolectric - -@RunWith(RobotElectriqueRunnerclass::class) +@RunWith(RobotElectriqueRunner::class) class LoginActivityTest { - @Test fun login_shouldDisplay() { Robolectric.buildActivity(LoginActivity::class.java).use { controller -> @@ -74,4 +72,4 @@ class LoginActivityTest { assertEquals(expectedIntent.component, actual.component) } }*/ -} \ No newline at end of file +} diff --git a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/RobotElectriqueRunner.kt b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/RobotElectriqueRunner.kt index 315dff2..2f22623 100644 --- a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/RobotElectriqueRunner.kt +++ b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/android/tests/robolectric/RobotElectriqueRunner.kt @@ -3,10 +3,8 @@ package bou.amine.apps.readerforselfossv2.android.tests.robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config -class RobotElectriqueRunnerclass(testClass: Class<*>?) : - RobolectricTestRunner(testClass) { - - override fun buildGlobalConfig(): Config { - return Config.Builder().setSdk(25, 30, 33).build() - } -} \ No newline at end of file +class RobotElectriqueRunner( + testClass: Class<*>?, +) : RobolectricTestRunner(testClass) { + override fun buildGlobalConfig(): Config = Config.Builder().setSdk(25, 30, 33).build() +} diff --git a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/RepositoryTest.kt b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/RepositoryTest.kt index fc78ef4..c5287ed 100644 --- a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/RepositoryTest.kt +++ b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/RepositoryTest.kt @@ -42,14 +42,14 @@ private const val FEED_URL = "https://test.com/feed" private const val TAGS = "Test, New" +private val NUMBER_ARTICLES = 100 +private val NUMBER_UNREAD = 50 +private val NUMBER_STARRED = 20 + class RepositoryTest { private val db = mockk(relaxed = true) private val appSettingsService = mockk() private val api = mockk() - - private val NUMBER_ARTICLES = 100 - private val NUMBER_UNREAD = 50 - private val NUMBER_STARRED = 20 private lateinit var repository: Repository private fun initializeRepository( @@ -75,19 +75,20 @@ class RepositoryTest { every { appSettingsService.isUpdateSourcesEnabled() } returns false coEvery { api.apiInformation() } returns - StatusAndData( - success = true, - data = SelfossModel.ApiInformation( + StatusAndData( + success = true, + data = + SelfossModel.ApiInformation( "2.19-ba1e8e3", "4.0.0", - SelfossModel.ApiConfiguration(false, true) + SelfossModel.ApiConfiguration(false, true), ), - ) + ) coEvery { api.stats() } returns - StatusAndData( - success = true, - data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED), - ) + StatusAndData( + success = true, + data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED), + ) every { db.itemsQueries.deleteItemsWhereSource(any()) } returns Unit every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() @@ -117,7 +118,7 @@ class RepositoryTest { fun get_api_4_date_with_api_1_version_stored() { every { appSettingsService.getApiVersion() } returns 1 coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) every { appSettingsService.updateApiVersion(any()) } returns Unit initializeRepository() @@ -133,14 +134,15 @@ class RepositoryTest { fun get_public_access() { every { appSettingsService.updatePublicAccess(any()) } returns Unit coEvery { api.apiInformation() } returns - StatusAndData( - success = true, - data = SelfossModel.ApiInformation( + StatusAndData( + success = true, + data = + SelfossModel.ApiInformation( "2.19-ba1e8e3", "4.0.0", - SelfossModel.ApiConfiguration(true, true) + SelfossModel.ApiConfiguration(true, true), ), - ) + ) every { appSettingsService.getUserName() } returns "" initializeRepository() @@ -153,14 +155,15 @@ class RepositoryTest { fun get_public_access_username_not_empty() { every { appSettingsService.updatePublicAccess(any()) } returns Unit coEvery { api.apiInformation() } returns - StatusAndData( - success = true, - data = SelfossModel.ApiInformation( + StatusAndData( + success = true, + data = + SelfossModel.ApiInformation( "2.19-ba1e8e3", "4.0.0", - SelfossModel.ApiConfiguration(true, true) + SelfossModel.ApiConfiguration(true, true), ), - ) + ) every { appSettingsService.getUserName() } returns "username" initializeRepository() @@ -173,14 +176,15 @@ class RepositoryTest { fun get_public_access_no_auth() { every { appSettingsService.updatePublicAccess(any()) } returns Unit coEvery { api.apiInformation() } returns - StatusAndData( - success = true, - data = SelfossModel.ApiInformation( + StatusAndData( + success = true, + data = + SelfossModel.ApiInformation( "2.19-ba1e8e3", "4.0.0", - SelfossModel.ApiConfiguration(true, false) + SelfossModel.ApiConfiguration(true, false), ), - ) + ) every { appSettingsService.getUserName() } returns "" initializeRepository() @@ -193,14 +197,15 @@ class RepositoryTest { fun get_public_access_disabled() { every { appSettingsService.updatePublicAccess(any()) } returns Unit coEvery { api.apiInformation() } returns - StatusAndData( - success = true, - data = SelfossModel.ApiInformation( + StatusAndData( + success = true, + data = + SelfossModel.ApiInformation( "2.19-ba1e8e3", "4.0.0", - SelfossModel.ApiConfiguration(false, true) + SelfossModel.ApiConfiguration(false, true), ), - ) + ) every { appSettingsService.getUserName() } returns "" initializeRepository() @@ -216,10 +221,10 @@ class RepositoryTest { val itemParameters = FakeItemParameters() itemParameters.datetime = "2021-04-23 11:45:32" coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData( - success = true, - data = generateTestApiItem(itemParameters), - ) + StatusAndData( + success = true, + data = generateTestApiItem(itemParameters), + ) initializeRepository() runBlocking { @@ -232,7 +237,7 @@ class RepositoryTest { @Test fun get_newer_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) initializeRepository() runBlocking { @@ -247,7 +252,7 @@ class RepositoryTest { @Test fun get_all_newer_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) initializeRepository() repository.displayedItems = ItemType.ALL @@ -263,7 +268,7 @@ class RepositoryTest { @Test fun get_newer_starred_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) initializeRepository() repository.displayedItems = ItemType.STARRED @@ -302,8 +307,8 @@ class RepositoryTest { coEvery { db.itemsQueries.items().executeAsList() } returns generateTestDBItems( itemParameter1, ) + - generateTestDBItems(itemParameter2) + - generateTestDBItems(itemParameter3) + generateTestDBItems(itemParameter2) + + generateTestDBItems(itemParameter3) every { appSettingsService.isItemCachingEnabled() } returns true @@ -330,8 +335,8 @@ class RepositoryTest { coEvery { db.itemsQueries.items().executeAsList() } returns generateTestDBItems( itemParameter1, ) + - generateTestDBItems(itemParameter2) + - generateTestDBItems(itemParameter3) + generateTestDBItems(itemParameter2) + + generateTestDBItems(itemParameter3) every { appSettingsService.isItemCachingEnabled() } returns true @@ -360,7 +365,7 @@ class RepositoryTest { @Test fun get_older_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) initializeRepository() repository.items = ArrayList(generateTestApiItem()) @@ -376,7 +381,7 @@ class RepositoryTest { @Test fun get_all_older_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) initializeRepository() repository.items = ArrayList(generateTestApiItem()) @@ -393,7 +398,7 @@ class RepositoryTest { @Test fun get_older_starred_items() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = true, data = generateTestApiItem()) + StatusAndData(success = true, data = generateTestApiItem()) initializeRepository() repository.displayedItems = ItemType.STARRED @@ -833,7 +838,7 @@ class RepositoryTest { @Test fun create_source() { coEvery { api.createSourceForVersion(any(), any(), any(), any()) } returns - SuccessResponse(true) + SuccessResponse(true) initializeRepository() var response: Boolean @@ -861,7 +866,7 @@ class RepositoryTest { @Test fun create_source_but_response_fails() { coEvery { api.createSourceForVersion(any(), any(), any(), any()) } returns - SuccessResponse(false) + SuccessResponse(false) initializeRepository() var response: Boolean @@ -889,7 +894,7 @@ class RepositoryTest { @Test fun create_source_without_connection() { coEvery { api.createSourceForVersion(any(), any(), any(), any()) } returns - SuccessResponse(true) + SuccessResponse(true) initializeRepository(MutableStateFlow(false)) var response: Boolean @@ -962,10 +967,10 @@ class RepositoryTest { @Test fun update_remote() { coEvery { api.update() } returns - StatusAndData( - success = true, - data = "finished", - ) + StatusAndData( + success = true, + data = "finished", + ) initializeRepository() var response: Boolean @@ -980,10 +985,10 @@ class RepositoryTest { @Test fun update_remote_but_response_fails() { coEvery { api.update() } returns - StatusAndData( - success = false, - data = "unallowed access", - ) + StatusAndData( + success = false, + data = "unallowed access", + ) initializeRepository() var response: Boolean @@ -998,10 +1003,10 @@ class RepositoryTest { @Test fun update_remote_with_unallowed_access() { coEvery { api.update() } returns - StatusAndData( - success = true, - data = "unallowed access", - ) + StatusAndData( + success = true, + data = "unallowed access", + ) initializeRepository() var response: Boolean @@ -1016,10 +1021,10 @@ class RepositoryTest { @Test fun update_remote_without_connection() { coEvery { api.update() } returns - StatusAndData( - success = true, - data = "undocumented...", - ) + StatusAndData( + success = true, + data = "undocumented...", + ) initializeRepository(MutableStateFlow(false)) var response: Boolean @@ -1109,11 +1114,11 @@ class RepositoryTest { any(), ) } returnsMany - listOf( - StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), - StatusAndData(success = true, data = generateTestApiItem(itemParameter2)), - StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), - ) + listOf( + StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), + StatusAndData(success = true, data = generateTestApiItem(itemParameter2)), + StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), + ) initializeRepository() prepareSearch() @@ -1127,7 +1132,7 @@ class RepositoryTest { @Test fun cache_items_but_response_fails() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = false, data = generateTestApiItem()) + StatusAndData(success = false, data = generateTestApiItem()) initializeRepository() prepareSearch() @@ -1141,7 +1146,7 @@ class RepositoryTest { @Test fun cache_items_without_connection() { coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns - StatusAndData(success = false, data = generateTestApiItem()) + StatusAndData(success = false, data = generateTestApiItem()) initializeRepository(MutableStateFlow(false)) prepareSearch() @@ -1168,4 +1173,4 @@ class RepositoryTest { ) repository.searchFilter = "search" } -} \ No newline at end of file +} diff --git a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/TestUtils.kt b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/TestUtils.kt index ca36a2d..e1d83c9 100644 --- a/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/TestUtils.kt +++ b/androidApp/src/test/kotlin/bou/amine/apps/readerforselfossv2/tests/repository/TestUtils.kt @@ -3,8 +3,8 @@ package bou.amine.apps.readerforselfossv2.tests.repository import bou.amine.apps.readerforselfossv2.dao.ITEM import bou.amine.apps.readerforselfossv2.model.SelfossModel -fun generateTestDBItems(item: FakeItemParameters = FakeItemParameters()): List { - return listOf( +fun generateTestDBItems(item: FakeItemParameters = FakeItemParameters()): List = + listOf( ITEM( id = item.id, datetime = item.datetime, @@ -20,10 +20,9 @@ fun generateTestDBItems(item: FakeItemParameters = FakeItemParameters()): List { - return listOf( +fun generateTestApiItem(item: FakeItemParameters = FakeItemParameters()): List = + listOf( SelfossModel.Item( id = item.id.toInt(), datetime = item.datetime, @@ -39,7 +38,6 @@ fun generateTestApiItem(item: FakeItemParameters = FakeItemParameters()): List?, authType: String?, - ) {} + ) { + } override fun checkServerTrusted( chain: Array?, authType: String?, - ) {} + ) { + } override fun getAcceptedIssuers(): Array = arrayOf() } -actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) { +actual fun setupInsecureHttpEngine(config: CIOEngineConfig) { config.https.trustManager = NaiveTrustManager() } 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 e5664fb..eb8a38d 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,8 +1,7 @@ package bou.amine.apps.readerforselfossv2.utils import android.text.format.DateUtils -import io.github.aakira.napier.Napier -import kotlinx.datetime.* +import kotlinx.datetime.Clock actual class DateUtils { actual companion object { diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt index e5100cf..6553890 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ModelConverters.kt @@ -4,19 +4,13 @@ import android.net.Uri import android.text.Html import bou.amine.apps.readerforselfossv2.model.SelfossModel import org.jsoup.Jsoup -import java.util.* +import java.util.Locale -actual fun String.getHtmlDecoded(): String { - return Html.fromHtml(this).toString() -} +actual fun String.getHtmlDecoded(): String = Html.fromHtml(this).toString() -actual fun SelfossModel.Item.getIcon(baseUrl: String): String { - return constructUrl(baseUrl, "favicons", icon) -} +actual fun SelfossModel.Item.getIcon(baseUrl: String): String = constructUrl(baseUrl, "favicons", icon) -actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String { - return constructUrl(baseUrl, "thumbnails", thumbnail) -} +actual fun SelfossModel.Item.getThumbnail(baseUrl: String): String = constructUrl(baseUrl, "thumbnails", thumbnail) actual fun SelfossModel.Item.getImages(): ArrayList { val allImages = ArrayList() @@ -34,16 +28,14 @@ actual fun SelfossModel.Item.getImages(): ArrayList { return allImages } -actual fun SelfossModel.Source.getIcon(baseUrl: String): String { - return constructUrl(baseUrl, "favicons", icon) -} +actual fun SelfossModel.Source.getIcon(baseUrl: String): String = constructUrl(baseUrl, "favicons", icon) actual fun constructUrl( baseUrl: String, path: String, file: String?, -): String { - return if (file == null || file == "null" || file.isEmpty()) { +): String = + if (file == null || file == "null" || file.isEmpty()) { "" } else { val baseUriBuilder = Uri.parse(baseUrl).buildUpon() @@ -51,4 +43,3 @@ actual fun constructUrl( baseUriBuilder.toString() } -} diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/dao/DeviceDatabase.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt similarity index 98% rename from shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/dao/DeviceDatabase.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt index ab41017..bd9338f 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/dao/DeviceDatabase.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt @@ -4,4 +4,4 @@ import app.cash.sqldelight.db.SqlDriver expect class DriverFactory { fun createDriver(): SqlDriver -} \ No newline at end of file +} 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 similarity index 89% rename from shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/DI/modules.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/di/Modules.kt index f099de4..2429dda 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,4 +1,4 @@ -package bou.amine.apps.readerforselfossv2.DI +package bou.amine.apps.readerforselfossv2.di import bou.amine.apps.readerforselfossv2.rest.MercuryApi import bou.amine.apps.readerforselfossv2.rest.SelfossApi diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt index 48578b4..cabe0b3 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt @@ -3,19 +3,20 @@ package bou.amine.apps.readerforselfossv2.model import kotlinx.serialization.Serializable @Serializable -class SuccessResponse(val success: Boolean) { +class SuccessResponse( + val success: Boolean, +) { val isSuccess: Boolean get() = success } -class StatusAndData(val success: Boolean, val data: T? = null) { +class StatusAndData( + val success: Boolean, + val data: T? = null, +) { companion object { - fun succes(d: T): StatusAndData { - return StatusAndData(true, d) - } + fun succes(d: T): StatusAndData = StatusAndData(true, d) - fun error(): StatusAndData { - return StatusAndData(false) - } + fun error(): StatusAndData = StatusAndData(false) } } diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt index 9b2bd99..1cc4d18 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/SelfossModel.kt @@ -141,7 +141,7 @@ class SelfossModel { } if (stringUrl.isEmptyOrNullOrNullString()) { - throw Exception("Link ${link} was translated to ${stringUrl}, but was empty. Handle this.") + throw Exception("Link $link was translated to $stringUrl, but was empty. Handle this.") } return stringUrl @@ -172,12 +172,11 @@ class SelfossModel { // TODO: this seems to be super slow. object TagsListSerializer : KSerializer> { - override fun deserialize(decoder: Decoder): List { - return when (val json = ((decoder as JsonDecoder).decodeJsonElement())) { + override fun deserialize(decoder: Decoder): List = + when (val json = ((decoder as JsonDecoder).decodeJsonElement())) { is JsonArray -> json.toList().map { it.toString().replace("^\"|\"$".toRegex(), "") } else -> json.toString().split(",") } - } override val descriptor: SerialDescriptor get() = PrimitiveSerialDescriptor("tags", PrimitiveKind.STRING) @@ -188,7 +187,7 @@ class SelfossModel { ) { encoder.encodeCollection( PrimitiveSerialDescriptor("tags", PrimitiveKind.STRING), - value.size + value.size, ) { this.toString() } } } @@ -204,10 +203,11 @@ class SelfossModel { } override val descriptor: SerialDescriptor - get() = PrimitiveSerialDescriptor( - "BooleanOrIntForSomeSelfossVersions", - PrimitiveKind.BOOLEAN - ) + get() = + PrimitiveSerialDescriptor( + "BooleanOrIntForSomeSelfossVersions", + PrimitiveKind.BOOLEAN, + ) override fun serialize( encoder: Encoder, @@ -216,4 +216,4 @@ class SelfossModel { TODO("Not yet implemented") } } -} \ 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/Repository.kt similarity index 92% rename from shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt index f84df1f..38fb97d 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryImpl.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/repository/Repository.kt @@ -1,12 +1,21 @@ package bou.amine.apps.readerforselfossv2.repository -import bou.amine.apps.readerforselfossv2.dao.* +import bou.amine.apps.readerforselfossv2.dao.ACTION +import bou.amine.apps.readerforselfossv2.dao.DriverFactory +import bou.amine.apps.readerforselfossv2.dao.ITEM +import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB +import bou.amine.apps.readerforselfossv2.dao.SOURCE +import bou.amine.apps.readerforselfossv2.dao.TAG import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.model.StatusAndData import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.service.AppSettingsService -import bou.amine.apps.readerforselfossv2.utils.* +import bou.amine.apps.readerforselfossv2.utils.ItemType +import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded +import bou.amine.apps.readerforselfossv2.utils.toEntity +import bou.amine.apps.readerforselfossv2.utils.toParsedDate +import bou.amine.apps.readerforselfossv2.utils.toView import io.github.aakira.napier.Napier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -170,8 +179,8 @@ class Repository( } } - suspend fun getSpouts(): Map { - return if (isNetworkAvailable()) { + suspend fun getSpouts(): Map = + if (isNetworkAvailable()) { val spouts = api.spouts() if (spouts.success && spouts.data != null) { spouts.data @@ -181,7 +190,6 @@ class Repository( } else { throw NetworkUnavailableException() } - } suspend fun getSourcesDetailsOrStats(): ArrayList { var sources = ArrayList() @@ -234,14 +242,13 @@ class Repository( return success } - private suspend fun markAsReadById(id: Int): Boolean { - return if (isNetworkAvailable()) { + private suspend fun markAsReadById(id: Int): Boolean = + if (isNetworkAvailable()) { api.markAsRead(id.toString()).isSuccess } else { insertDBAction(id.toString(), read = true) true } - } suspend fun unmarkAsRead(item: SelfossModel.Item): Boolean { val success = unmarkAsReadById(item.id) @@ -252,14 +259,13 @@ class Repository( return success } - private suspend fun unmarkAsReadById(id: Int): Boolean { - return if (isNetworkAvailable()) { + private suspend fun unmarkAsReadById(id: Int): Boolean = + if (isNetworkAvailable()) { api.unmarkAsRead(id.toString()).isSuccess } else { insertDBAction(id.toString(), unread = true) true } - } suspend fun starr(item: SelfossModel.Item): Boolean { val success = starrById(item.id) @@ -270,14 +276,13 @@ class Repository( return success } - private suspend fun starrById(id: Int): Boolean { - return if (isNetworkAvailable()) { + private suspend fun starrById(id: Int): Boolean = + if (isNetworkAvailable()) { api.starr(id.toString()).isSuccess } else { insertDBAction(id.toString(), starred = true) true } - } suspend fun unstarr(item: SelfossModel.Item): Boolean { val success = unstarrById(item.id) @@ -288,14 +293,13 @@ class Repository( return success } - private suspend fun unstarrById(id: Int): Boolean { - return if (isNetworkAvailable()) { + private suspend fun unstarrById(id: Int): Boolean = + if (isNetworkAvailable()) { api.unstarr(id.toString()).isSuccess } else { insertDBAction(id.toString(), starred = true) true } - } suspend fun markAllAsRead(items: ArrayList): Boolean { var success = false @@ -361,12 +365,13 @@ class Repository( ): Boolean { var response = false if (isNetworkAvailable()) { - response = api.createSourceForVersion( - title, - url, - spout, - tags, - ).isSuccess == true + response = api + .createSourceForVersion( + title, + url, + spout, + tags, + ).isSuccess == true } return response @@ -407,13 +412,12 @@ class Repository( return success } - suspend fun updateRemote(): Boolean { - return if (isNetworkAvailable()) { + suspend fun updateRemote(): Boolean = + if (isNetworkAvailable()) { api.update().data.equals("finished") } else { false } - } suspend fun login(): Boolean { var result = false @@ -422,7 +426,7 @@ class Repository( val response = api.login() result = response.isSuccess == true } catch (cause: Throwable) { - Napier.e("login failed", cause, tag = "RepositoryImpl.login") + Napier.e("login failed", cause, tag = "Repository.login") } } return result @@ -436,7 +440,7 @@ class Repository( // a random rss feed, that would throw a NoTransformationFoundException fetchFailed = !api.getItemsWithoutCatch().success } catch (e: Throwable) { - Napier.e("checkIfFetchFails failed", e, tag = "RepositoryImpl.shouldBeSelfossInstance") + Napier.e("checkIfFetchFails failed", e, tag = "Repository.shouldBeSelfossInstance") } } @@ -448,10 +452,10 @@ class Repository( try { val response = api.logout() if (!response.isSuccess) { - Napier.e("Couldn't logout.", tag = "RepositoryImpl.logout") + Napier.e("Couldn't logout.", tag = "Repository.logout") } } catch (cause: Throwable) { - Napier.e("logout failed", cause, tag = "RepositoryImpl.logout") + Napier.e("logout failed", cause, tag = "Repository.logout") } appSettingsService.clearAll() } else { @@ -578,16 +582,19 @@ class Repository( markAsReadById(action.articleid.toInt()), action, ) + action.unread -> doAndReportOnFail( unmarkAsReadById(action.articleid.toInt()), action, ) + action.starred -> doAndReportOnFail( starrById(action.articleid.toInt()), action, ) + action.unstarred -> doAndReportOnFail( unstarrById(action.articleid.toInt()), @@ -618,9 +625,7 @@ class Repository( _readerItems = readerItems } - fun getReaderItems(): ArrayList { - return _readerItems - } + fun getReaderItems(): ArrayList = _readerItems fun migrate(driverFactory: DriverFactory) { ReaderForSelfossDB.Schema.migrate(driverFactory.createDriver(), 0, 1) @@ -634,7 +639,5 @@ class Repository( _selectedSource = null } - fun getSelectedSource(): SelfossModel.SourceDetail? { - return _selectedSource - } + fun getSelectedSource(): SelfossModel.SourceDetail? = _selectedSource } diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/MercuryApi.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/MercuryApi.kt index 5fc678c..35d9eab 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/MercuryApi.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/MercuryApi.kt @@ -17,8 +17,8 @@ import kotlinx.serialization.json.Json class MercuryApi { var client = createHttpClient() - private fun createHttpClient(): HttpClient { - return HttpClient { + private fun createHttpClient(): HttpClient = + HttpClient { install(HttpCache) install(ContentNegotiation) { json( @@ -40,7 +40,6 @@ class MercuryApi { } expectSuccess = false } - } suspend fun query(url: String): StatusAndData = bodyOrFailure( @@ -48,4 +47,4 @@ class MercuryApi { parameter("link", url) }, ) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt index f499cdc..82098b8 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt @@ -3,23 +3,28 @@ package bou.amine.apps.readerforselfossv2.rest import bou.amine.apps.readerforselfossv2.model.StatusAndData import bou.amine.apps.readerforselfossv2.model.SuccessResponse import io.github.aakira.napier.Napier -import io.ktor.client.* -import io.ktor.client.call.* -import io.ktor.client.request.* -import io.ktor.client.request.forms.* -import io.ktor.client.statement.* -import io.ktor.http.* +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.delete +import io.ktor.client.request.forms.submitForm +import io.ktor.client.request.get +import io.ktor.client.request.post +import io.ktor.client.request.url +import io.ktor.client.statement.HttpResponse +import io.ktor.http.HttpStatusCode +import io.ktor.http.Parameters +import io.ktor.http.isSuccess -suspend fun responseOrSuccessIf404(r: HttpResponse?): SuccessResponse { - return if (r != null && r.status === HttpStatusCode.NotFound) { +suspend fun responseOrSuccessIf404(r: HttpResponse?): SuccessResponse = + if (r != null && r.status === HttpStatusCode.NotFound) { SuccessResponse(true) } else { maybeResponse(r) } -} -suspend fun maybeResponse(r: HttpResponse?): SuccessResponse { - return if (r != null && r.status.isSuccess()) { +suspend fun maybeResponse(r: HttpResponse?): SuccessResponse = + if (r != null && r.status.isSuccess()) { r.body() } else { if (r != null) { @@ -27,7 +32,6 @@ suspend fun maybeResponse(r: HttpResponse?): SuccessResponse { } SuccessResponse(false) } -} suspend inline fun bodyOrFailure(r: HttpResponse?): StatusAndData { try { @@ -98,4 +102,4 @@ suspend fun HttpClient.tryToSubmitForm( url(url) block() } - } \ No newline at end of file + } 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 fc7bb82..f4562f3 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 @@ -33,16 +33,18 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.serialization.json.Json -expect fun setupInsecureHTTPEngine(config: CIOEngineConfig) +expect fun setupInsecureHttpEngine(config: CIOEngineConfig) -class SelfossApi(private val appSettingsService: AppSettingsService) { +class SelfossApi( + private val appSettingsService: AppSettingsService, +) { var client = createHttpClient() fun createHttpClient() = HttpClient(CIO) { if (appSettingsService.getSelfSigned()) { engine { - setupInsecureHTTPEngine(this) + setupInsecureHttpEngine(this) } } install(HttpCache) @@ -105,12 +107,14 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { private fun hasLoginInfo() = appSettingsService.getUserName().isNotEmpty() && - appSettingsService.getPassword() - .isNotEmpty() + appSettingsService + .getPassword() + .isNotEmpty() suspend fun login(): SuccessResponse = if (appSettingsService.getUserName().isNotEmpty() && - appSettingsService.getPassword() + appSettingsService + .getPassword() .isNotEmpty() ) { if (shouldHavePostLogin()) { @@ -127,8 +131,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { client.tryToGet(url("/login")) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -150,8 +156,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { client.tryToPost(url("/login")) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -168,8 +176,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }, ) - private fun shouldHaveNewLogout() = - appSettingsService.getApiVersion() >= 5 // We are missing 4.1.0 + private fun shouldHaveNewLogout() = appSettingsService.getApiVersion() >= 5 // We are missing 4.1.0 suspend fun logout(): SuccessResponse = if (shouldHaveNewLogout()) { @@ -181,8 +188,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { private suspend fun maybeLogoutIfAvailable() = responseOrSuccessIf404( client.tryToGet(url("/logout")) { - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -202,8 +211,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { private suspend fun doLogout() = maybeResponse( client.tryToDelete(url("/api/session/current")) { - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -242,8 +253,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("updatedsince", updatedSince) parameter("items", items ?: appSettingsService.getItemsNumber()) parameter("offset", offset) - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -269,8 +282,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { } parameter("type", "all") parameter("items", 1) - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -294,8 +309,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -319,8 +336,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -344,8 +363,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -369,8 +390,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -394,8 +417,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -419,8 +444,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -440,8 +467,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { suspend fun apiInformation(): StatusAndData = bodyOrFailure( client.tryToGet(url("/api/about")) { - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -465,8 +494,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -490,8 +521,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -515,8 +548,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -540,8 +575,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -563,16 +600,18 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { client.tryToSubmitForm( url = url("/mark"), formParameters = - Parameters.build { - if (!shouldHavePostLogin()) { - append("username", appSettingsService.getUserName()) - append("password", appSettingsService.getPassword()) - } - ids.map { append("ids[]", it) } - }, + Parameters.build { + if (!shouldHavePostLogin()) { + append("username", appSettingsService.getUserName()) + append("password", appSettingsService.getPassword()) + } + ids.map { append("ids[]", it) } + }, block = { - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -614,19 +653,21 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { client.tryToSubmitForm( url = url("/source"), formParameters = - Parameters.build { - if (!shouldHavePostLogin()) { - append("username", appSettingsService.getUserName()) - append("password", appSettingsService.getPassword()) - } - append("title", title) - append("url", url) - append("spout", spout) - append(tagsParamName, tags) - }, + Parameters.build { + if (!shouldHavePostLogin()) { + append("username", appSettingsService.getUserName()) + append("password", appSettingsService.getPassword()) + } + append("title", title) + append("url", url) + append("spout", spout) + append(tagsParamName, tags) + }, block = { - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -669,19 +710,21 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { client.tryToSubmitForm( url = url("/source/$id"), formParameters = - Parameters.build { - if (!shouldHavePostLogin()) { - append("username", appSettingsService.getUserName()) - append("password", appSettingsService.getPassword()) - } - append("title", title) - append("url", url) - append("spout", spout) - append(tagsParamName, tags) - }, + Parameters.build { + if (!shouldHavePostLogin()) { + append("username", appSettingsService.getUserName()) + append("password", appSettingsService.getPassword()) + } + append("title", title) + append("url", url) + append("spout", spout) + append(tagsParamName, tags) + }, block = { - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -705,8 +748,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) } - if (appSettingsService.getBasicUserName() - .isNotEmpty() && appSettingsService.getBasicPassword().isNotEmpty() + if (appSettingsService + .getBasicUserName() + .isNotEmpty() && + appSettingsService.getBasicPassword().isNotEmpty() ) { headers { append( @@ -722,4 +767,4 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { } }, ) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ACRASettings.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ACRASettings.kt index 07da94d..cfba825 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ACRASettings.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/ACRASettings.kt @@ -121,4 +121,4 @@ class ACRASettings : Settings { longs.remove(key) strings.remove(key) } -} \ 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 index 46c2475..6713ad1 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt @@ -2,7 +2,9 @@ package bou.amine.apps.readerforselfossv2.service import com.russhwolf.settings.Settings -class AppSettingsService(acraSenderServiceProcess: Boolean = false) { +class AppSettingsService( + acraSenderServiceProcess: Boolean = false, +) { val settings: Settings = if (acraSenderServiceProcess) { ACRASettings() @@ -11,37 +13,37 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } // Api related - private var _apiVersion: Int = -1 - private var _publicAccess: Boolean? = null - private var _selfSigned: Boolean? = null - private var _baseUrl: String = "" - private var _userName: String = "" - private var _basicUserName: String = "" - private var _password: String = "" - private var _basicPassword: String = "" + private var apiVersion: Int = -1 + private var publicAccess: Boolean? = null + private var selfSigned: Boolean? = null + private var baseUrl: String = "" + private var userName: String = "" + private var basicUserName: String = "" + private var password: String = "" + private var basicPassword: String = "" // User settings related - private var _itemsCaching: 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 _notifyNewItems: Boolean? = null - private var _itemsNumber: Int? = null - private var _apiTimeout: Long? = null - private var _refreshMinutes: Long = 360 - private var _markOnScroll: Boolean? = null - private var _activeAlignment: Int? = null + private var itemsCaching: 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 notifyNewItems: Boolean? = null + private var itemsNumber: Int? = null + private var apiTimeout: Long? = null + private var refreshMinutes: Long = 360 + private var markOnScroll: Boolean? = null + private var activeAlignment: Int? = null - private var _fontSize: Int? = null - private var _staticBar: Boolean? = null - private var _font: String = "" - private var _theme: Int? = null + private var fontSize: Int? = null + private var staticBar: Boolean? = null + private var font: String = "" + private var theme: Int? = null init { refreshApiSettings() @@ -49,11 +51,11 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } fun getApiVersion(): Int { - if (_apiVersion == -1) { + if (apiVersion == -1) { refreshApiVersion() - return _apiVersion + return apiVersion } - return _apiVersion + return apiVersion } fun updateApiVersion(apiMajorVersion: Int) { @@ -62,14 +64,14 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } private fun refreshApiVersion() { - _apiVersion = settings.getInt(API_VERSION_MAJOR, -1) + apiVersion = settings.getInt(API_VERSION_MAJOR, -1) } fun getPublicAccess(): Boolean { - if (_publicAccess == null) { + if (publicAccess == null) { refreshPublicAccess() } - return _publicAccess!! + return publicAccess!! } fun updatePublicAccess(publicAccess: Boolean) { @@ -78,14 +80,14 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } private fun refreshPublicAccess() { - _publicAccess = settings.getBoolean(API_PUBLIC_ACCESS, false) + publicAccess = settings.getBoolean(API_PUBLIC_ACCESS, false) } fun getSelfSigned(): Boolean { - if (_selfSigned == null) { + if (selfSigned == null) { refreshSelfSigned() } - return _selfSigned!! + return selfSigned!! } fun updateSelfSigned(selfSigned: Boolean) { @@ -94,53 +96,53 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } private fun refreshSelfSigned() { - _selfSigned = settings.getBoolean(API_SELF_SIGNED, false) + selfSigned = settings.getBoolean(API_SELF_SIGNED, false) } fun getBaseUrl(): String { - if (_baseUrl.isEmpty()) { + if (baseUrl.isEmpty()) { refreshBaseUrl() } - return _baseUrl + return baseUrl } fun getUserName(): String { - if (_userName.isEmpty()) { + if (userName.isEmpty()) { refreshUsername() } - return _userName + return userName } fun getPassword(): String { - if (_password.isEmpty()) { + if (password.isEmpty()) { refreshPassword() } - return _password + return password } fun getBasicUserName(): String { - if (_basicUserName.isEmpty()) { + if (basicUserName.isEmpty()) { refreshBasicUsername() } - return _basicUserName + return basicUserName } fun getBasicPassword(): String { - if (_basicPassword.isEmpty()) { + if (basicPassword.isEmpty()) { refreshBasicPassword() } - return _basicPassword + return basicPassword } fun getItemsNumber(): Int { - if (_itemsNumber == null) { + if (itemsNumber == null) { refreshItemsNumber() } - return _itemsNumber!! + return itemsNumber!! } private fun refreshItemsNumber() { - _itemsNumber = + itemsNumber = try { settings.getString(API_ITEMS_NUMBER, "20").toInt() } catch (e: Exception) { @@ -150,16 +152,16 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } fun getApiTimeout(): Long { - if (_apiTimeout == null) { + if (apiTimeout == null) { refreshApiTimeout() } - return _apiTimeout!! + return apiTimeout!! } private fun secToMs(n: Long) = n * 1000 private fun refreshApiTimeout() { - _apiTimeout = + apiTimeout = secToMs( try { val settingsTimeout = settings.getString(API_TIMEOUT, "60") @@ -177,229 +179,229 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } private fun refreshBaseUrl() { - _baseUrl = settings.getString(BASE_URL, "") + baseUrl = settings.getString(BASE_URL, "") } private fun refreshUsername() { - _userName = settings.getString(LOGIN, "") + userName = settings.getString(LOGIN, "") } private fun refreshPassword() { - _password = settings.getString(PASSWORD, "") + password = settings.getString(PASSWORD, "") } private fun refreshBasicUsername() { - _basicUserName = settings.getString(BASIC_LOGIN, "") + basicUserName = settings.getString(BASIC_LOGIN, "") } private fun refreshBasicPassword() { - _basicPassword = settings.getString(BASIC_PASSWORD, "") + basicPassword = settings.getString(BASIC_PASSWORD, "") } private fun refreshArticleViewerEnabled() { - _articleViewer = settings.getBoolean(PREFER_ARTICLE_VIEWER, true) + articleViewer = settings.getBoolean(PREFER_ARTICLE_VIEWER, true) } fun isArticleViewerEnabled(): Boolean { - if (_articleViewer != null) { + if (articleViewer != null) { refreshArticleViewerEnabled() } - return _articleViewer == true + return articleViewer == true } private fun refreshShouldBeCardViewEnabled() { - _shouldBeCardView = settings.getBoolean(CARD_VIEW_ACTIVE, false) + shouldBeCardView = settings.getBoolean(CARD_VIEW_ACTIVE, false) } fun isCardViewEnabled(): Boolean { - if (_shouldBeCardView != null) { + if (shouldBeCardView != null) { refreshShouldBeCardViewEnabled() } - return _shouldBeCardView == true + return shouldBeCardView == true } private fun refreshDisplayUnreadCountEnabled() { - _displayUnreadCount = settings.getBoolean(DISPLAY_UNREAD_COUNT, true) + displayUnreadCount = settings.getBoolean(DISPLAY_UNREAD_COUNT, true) } fun isDisplayUnreadCountEnabled(): Boolean { - if (_displayUnreadCount != null) { + if (displayUnreadCount != null) { refreshDisplayUnreadCountEnabled() } - return _displayUnreadCount == true + return displayUnreadCount == true } private fun refreshDisplayAllCountEnabled() { - _displayAllCount = settings.getBoolean(DISPLAY_OTHER_COUNT, false) + displayAllCount = settings.getBoolean(DISPLAY_OTHER_COUNT, false) } fun isDisplayAllCountEnabled(): Boolean { - if (_displayAllCount != null) { + if (displayAllCount != null) { refreshDisplayAllCountEnabled() } - return _displayAllCount == true + return displayAllCount == true } private fun refreshFullHeightCardsEnabled() { - _fullHeightCards = settings.getBoolean(FULL_HEIGHT_CARDS, false) + fullHeightCards = settings.getBoolean(FULL_HEIGHT_CARDS, false) } fun isFullHeightCardsEnabled(): Boolean { - if (_fullHeightCards != null) { + if (fullHeightCards != null) { refreshFullHeightCardsEnabled() } - return _fullHeightCards == true + return fullHeightCards == true } private fun refreshUpdateSourcesEnabled() { - _updateSources = settings.getBoolean(UPDATE_SOURCES, true) + updateSources = settings.getBoolean(UPDATE_SOURCES, true) } fun isUpdateSourcesEnabled(): Boolean { - if (_updateSources != null) { + if (updateSources != null) { refreshUpdateSourcesEnabled() } - return _updateSources == true + return updateSources == true } private fun refreshPeriodicRefreshEnabled() { - _periodicRefresh = settings.getBoolean(PERIODIC_REFRESH, false) + periodicRefresh = settings.getBoolean(PERIODIC_REFRESH, false) } fun isPeriodicRefreshEnabled(): Boolean { - if (_periodicRefresh != null) { + if (periodicRefresh != null) { refreshPeriodicRefreshEnabled() } - return _periodicRefresh == true + return periodicRefresh == true } private fun refreshRefreshWhenChargingOnlyEnabled() { - _refreshWhenChargingOnly = settings.getBoolean(REFRESH_WHEN_CHARGING, false) + refreshWhenChargingOnly = settings.getBoolean(REFRESH_WHEN_CHARGING, false) } fun isRefreshWhenChargingOnlyEnabled(): Boolean { - if (_refreshWhenChargingOnly != null) { + if (refreshWhenChargingOnly != null) { refreshRefreshWhenChargingOnlyEnabled() } - return _refreshWhenChargingOnly == true + return refreshWhenChargingOnly == true } private fun refreshRefreshMinutes() { - _refreshMinutes = settings.getString(PERIODIC_REFRESH_MINUTES, "360").toLong() - if (_refreshMinutes <= 15) { - _refreshMinutes = 15 + refreshMinutes = settings.getString(PERIODIC_REFRESH_MINUTES, "360").toLong() + if (refreshMinutes <= 15) { + refreshMinutes = 15 } } fun getRefreshMinutes(): Long { - if (_refreshMinutes != 360L) { + if (refreshMinutes != 360L) { refreshRefreshMinutes() } - return _refreshMinutes + return refreshMinutes } private fun refreshInfiniteLoadingEnabled() { - _infiniteLoading = settings.getBoolean(INFINITE_LOADING, false) + infiniteLoading = settings.getBoolean(INFINITE_LOADING, false) } fun isInfiniteLoadingEnabled(): Boolean { - if (_infiniteLoading != null) { + if (infiniteLoading != null) { refreshInfiniteLoadingEnabled() } - return _infiniteLoading == true + return infiniteLoading == true } private fun refreshItemCachingEnabled() { - _itemsCaching = settings.getBoolean(ITEMS_CACHING, false) + itemsCaching = settings.getBoolean(ITEMS_CACHING, false) } fun isItemCachingEnabled(): Boolean { - if (_itemsCaching != null) { + if (itemsCaching != null) { refreshItemCachingEnabled() } - return _itemsCaching == true + return itemsCaching == true } private fun refreshNotifyNewItemsEnabled() { - _notifyNewItems = settings.getBoolean(NOTIFY_NEW_ITEMS, false) + notifyNewItems = settings.getBoolean(NOTIFY_NEW_ITEMS, false) } fun isNotifyNewItemsEnabled(): Boolean { - if (_notifyNewItems != null) { + if (notifyNewItems != null) { refreshNotifyNewItemsEnabled() } - return _notifyNewItems == true + return notifyNewItems == true } private fun refreshMarkOnScrollEnabled() { - _markOnScroll = settings.getBoolean(MARK_ON_SCROLL, false) + markOnScroll = settings.getBoolean(MARK_ON_SCROLL, false) } fun isMarkOnScrollEnabled(): Boolean { - if (_markOnScroll != null) { + if (markOnScroll != null) { refreshMarkOnScrollEnabled() } - return _markOnScroll == true + return markOnScroll == true } private fun refreshActiveAllignment() { - _activeAlignment = settings.getInt(TEXT_ALIGN, JUSTIFY) + activeAlignment = settings.getInt(TEXT_ALIGN, JUSTIFY) } fun getActiveAllignment(): Int { - if (_activeAlignment != null) { + if (activeAlignment != null) { refreshActiveAllignment() } - return _activeAlignment ?: JUSTIFY + return activeAlignment ?: JUSTIFY } fun changeAllignment(allignment: Int) { settings.putInt(TEXT_ALIGN, allignment) - _activeAlignment = allignment + activeAlignment = allignment } private fun refreshFontSize() { - _fontSize = settings.getString(READER_FONT_SIZE, "16").toInt() + fontSize = settings.getString(READER_FONT_SIZE, "16").toInt() } fun getFontSize(): Int { - if (_fontSize != null) { + if (fontSize != null) { refreshFontSize() } - return _fontSize ?: 16 + return fontSize ?: 16 } private fun refreshStaticBarEnabled() { - _staticBar = settings.getBoolean(READER_STATIC_BAR, false) + staticBar = settings.getBoolean(READER_STATIC_BAR, false) } fun isStaticBarEnabled(): Boolean { - if (_staticBar != null) { + if (staticBar != null) { refreshStaticBarEnabled() } - return _staticBar == true + return staticBar == true } private fun refreshFont() { - _font = settings.getString(READER_FONT, "") + font = settings.getString(READER_FONT, "") } fun getFont(): String { - if (_font.isEmpty()) { + if (font.isEmpty()) { refreshFont() } - return _font + return font } private fun refreshCurrentTheme() { - _theme = settings.getString(CURRENT_THEME, "-1").toInt() + theme = settings.getString(CURRENT_THEME, "-1").toInt() } fun getCurrentTheme(): Int { - if (_theme == null) { + if (theme == null) { refreshCurrentTheme() } - return _theme ?: -1 + return theme ?: -1 } fun refreshApiSettings() { @@ -478,15 +480,15 @@ class AppSettingsService(acraSenderServiceProcess: Boolean = false) { } companion object { - const val translationUrl = "https://crwd.in/readerforselfoss" + const val TRANSLATION_URL = "https://crwd.in/readerforselfoss" - const val sourceUrl = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform" + const val SOURCE_URL = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform" - const val trackerUrl = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" + const val BUG_URL = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" - const val syncChannelId = "sync-channel-id" + const val SYNC_CHANNEL_ID = "sync-channel-id" - const val newItemsChannelId = "new-items-channel-id" + const val NEW_ITEMS_CHANNEL = "new-items-channel-id" const val JUSTIFY = 1 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 7cbcbbd..4b68662 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 @@ -17,7 +17,11 @@ fun String.toParsedDate(): Long { if (this.matches(oldVersionFormat)) { this.replace(" ", "T") } else if (this.matches(newVersionFormat)) { - newVersionFormat.find(this)?.groups?.get(1)?.value ?: throw Exception("Couldn't parse $this") + newVersionFormat + .find(this) + ?.groups + ?.get(1) + ?.value ?: throw Exception("Couldn't parse $this") } else { throw Exception("Unrecognized format for $this") } diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt index 60efc42..9e07b29 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/EntityUtils.kt @@ -82,4 +82,4 @@ fun SelfossModel.Tag.getColorHexCode(): String = "#$char1$char1$char2$char2$char3$char3" } else { this.color - } \ No newline at end of file + } diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ItemType.kt similarity index 76% rename from shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt rename to shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ItemType.kt index e5a0ff4..ef53ba2 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/Enums.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/utils/ItemType.kt @@ -1,6 +1,9 @@ package bou.amine.apps.readerforselfossv2.utils -enum class ItemType(val position: Int, val type: String) { +enum class ItemType( + val position: Int, + val type: String, +) { UNREAD(1, "unread"), ALL(2, "all"), STARRED(3, "starred"), diff --git a/shared/src/commonTest/kotlin/DatesTest.kt b/shared/src/commonTest/kotlin/DatesTest.kt index e074d04..81b199e 100644 --- a/shared/src/commonTest/kotlin/DatesTest.kt +++ b/shared/src/commonTest/kotlin/DatesTest.kt @@ -8,27 +8,29 @@ import kotlin.test.Test import kotlin.test.assertEquals class DatesTest { - private val newVersionDateVariant = "2022-12-24T17:00:08+00" - private val newVersionDate = "2013-04-07T13:43:00+01:00" - private val newVersionDate2 = "2013-04-07T13:43:00-01:00" - private val oldVersionDate = "2013-05-07 13:46:00" - private val oldVersionDateVariant = "2021-03-21 10:32:00.000000" - + private val newVersionDateVariant = "2022-12-24T17:00:08+00" + private val newVersionDate = "2013-04-07T13:43:00+01:00" + private val newVersionDate2 = "2013-04-07T13:43:00-01:00" + private val oldVersionDate = "2013-05-07 13:46:00" + private val oldVersionDateVariant = "2021-03-21 10:32:00.000000" @Test fun new_version_date_should_be_parsed() { val date = newVersionDate.toParsedDate() val expected = - LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.currentSystemDefault()) + LocalDateTime(2013, 4, 7, 13, 43, 0, 0) + .toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() assertEquals(expected, date) } + @Test fun new_version_date2_should_be_parsed() { val date = newVersionDate2.toParsedDate() val expected = - LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.currentSystemDefault()) + LocalDateTime(2013, 4, 7, 13, 43, 0, 0) + .toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() assertEquals(expected, date) @@ -38,7 +40,8 @@ class DatesTest { fun old_version_date_should_be_parsed() { val date = oldVersionDate.toParsedDate() val expected = - LocalDateTime(2013, 5, 7, 13, 46, 0, 0).toInstant(TimeZone.currentSystemDefault()) + LocalDateTime(2013, 5, 7, 13, 46, 0, 0) + .toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() assertEquals(expected, date) @@ -48,7 +51,8 @@ class DatesTest { fun old_version_variant_date_should_be_parsed() { val date = oldVersionDateVariant.toParsedDate() val expected = - LocalDateTime(2021, 3, 21, 10, 32, 0, 0).toInstant(TimeZone.currentSystemDefault()) + LocalDateTime(2021, 3, 21, 10, 32, 0, 0) + .toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() assertEquals(expected, date) @@ -58,7 +62,8 @@ class DatesTest { fun new_version_variant_date_should_be_parsed() { val date = newVersionDateVariant.toParsedDate() val expected = - LocalDateTime(2022, 12, 24, 17, 0, 8, 0).toInstant(TimeZone.currentSystemDefault()) + LocalDateTime(2022, 12, 24, 17, 0, 8, 0) + .toInstant(TimeZone.currentSystemDefault()) .toEpochMilliseconds() assertEquals(expected, date) diff --git a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt index 17e359d..cb47fda 100644 --- a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt +++ b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt @@ -4,7 +4,5 @@ import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver actual class DriverFactory { - actual fun createDriver(): SqlDriver { - return NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db") - } -} \ No newline at end of file + actual fun createDriver(): SqlDriver = NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db") +} diff --git a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/SetupInsecureHttpEngine.kt similarity index 61% rename from shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt rename to shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/SetupInsecureHttpEngine.kt index 0bfd800..e90f3e1 100644 --- a/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt +++ b/shared/src/iosArm64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/SetupInsecureHttpEngine.kt @@ -2,5 +2,5 @@ package bou.amine.apps.readerforselfossv2.rest import io.ktor.client.engine.cio.CIOEngineConfig -actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) { +actual fun setupInsecureHttpEngine(config: CIOEngineConfig) { } 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 6b6cb5b..1b5e402 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 @@ -6,4 +6,4 @@ actual class DateUtils { TODO("Not yet implemented") } } -} \ No newline at end of file +} diff --git a/shared/src/iosSimulatorArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.iosSimulatorArm64.kt b/shared/src/iosSimulatorArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.iosSimulatorArm64.kt index ee78316..903125f 100644 --- a/shared/src/iosSimulatorArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.iosSimulatorArm64.kt +++ b/shared/src/iosSimulatorArm64Main/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.iosSimulatorArm64.kt @@ -6,4 +6,4 @@ actual class DateUtils actual constructor() { TODO("Not yet implemented") } } -} \ No newline at end of file +} diff --git a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt index 17e359d..cb47fda 100644 --- a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt +++ b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/dao/DriverFactory.kt @@ -4,7 +4,5 @@ import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver actual class DriverFactory { - actual fun createDriver(): SqlDriver { - return NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db") - } -} \ No newline at end of file + actual fun createDriver(): SqlDriver = NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db") +} diff --git a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/SetupInsecureHttpEngine.kt similarity index 61% rename from shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt rename to shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/SetupInsecureHttpEngine.kt index 0bfd800..e90f3e1 100644 --- a/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/setupInsecureHTTPEngine.kt +++ b/shared/src/iosX64Main/kotlin/bou/amine/apps/readerforselfossv2/rest/SetupInsecureHttpEngine.kt @@ -2,5 +2,5 @@ package bou.amine.apps.readerforselfossv2.rest import io.ktor.client.engine.cio.CIOEngineConfig -actual fun setupInsecureHTTPEngine(config: CIOEngineConfig) { +actual fun setupInsecureHttpEngine(config: CIOEngineConfig) { } 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 6b6cb5b..1b5e402 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 @@ -6,4 +6,4 @@ actual class DateUtils { TODO("Not yet implemented") } } -} \ No newline at end of file +}