Compare commits

..

1 Commits

Author SHA1 Message Date
4fbebf2954 chore: code style fixes for ktlint
Some checks failed
Check PR code / Lint (pull_request) Failing after 2m19s
Check PR code / build (pull_request) Has been skipped
2025-01-11 15:23:02 +01:00
39 changed files with 261 additions and 191 deletions

View File

@ -3,25 +3,34 @@ root = true
[*] [*]
insert_final_newline = true insert_final_newline = true
[{*.kt,*.kts}] [.editorconfig]
insert_final_newline = false
ij_kotlin_line_break_after_multiline_when_entry = false
[*.{kt,kts}] [*.{kt,kts}]
# Disable wildcard imports entirely # Disable wildcard imports entirely
ij_kotlin_name_count_to_use_star_import = 2147483647 ij_kotlin_name_count_to_use_star_import = 2147483647
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
end_of_line = lf end_of_line = lf
ij_kotlin_allow_trailing_comma = true ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true ij_kotlin_allow_trailing_comma_on_call_site = true
ij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^ 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 ij_kotlin_packages_to_use_import_on_demand = unset
indent_size = 4 indent_size = 4
indent_style = space indent_style = space
ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than = unset 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_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 1
ktlint_code_style = ktlint_official 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_body_expression_wrapping = multiline
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 2 ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 2
ktlint_ignore_back_ticked_identifier = false ktlint_ignore_back_ticked_identifier = false
ktlint_property_naming_constant_naming = screaming_snake_case
max_line_length = 140 max_line_length = 140
[**/build]
ktlint = disabled

View File

@ -104,12 +104,14 @@ fun testAddSourceWithUrl(
onView(withId(R.id.fab)) onView(withId(R.id.fab))
.perform(click()) .perform(click())
onView(withId(R.id.nameInput)) onView(withId(R.id.nameInput))
.perform(click()).perform(typeTextIntoFocusedView(sourceName)) .perform(click())
.perform(typeTextIntoFocusedView(sourceName))
onView(withId(R.id.sourceUri)) onView(withId(R.id.sourceUri))
.perform(click()) .perform(click())
.perform(typeTextIntoFocusedView(url)) .perform(typeTextIntoFocusedView(url))
onView(withId(R.id.tags)) onView(withId(R.id.tags))
.perform(click()).perform(typeTextIntoFocusedView("tag1,tag2,tag3")) .perform(click())
.perform(typeTextIntoFocusedView("tag1,tag2,tag3"))
onView(withId(R.id.spoutsSpinner)) onView(withId(R.id.spoutsSpinner))
.perform(click()) .perform(click())
onData(hasToString("RSS Feed")).perform(click()) onData(hasToString("RSS Feed")).perform(click())

View File

@ -49,9 +49,7 @@ fun withError(
} }
} }
fun isPopupWindow(): Matcher<Root> { fun isPopupWindow(): Matcher<Root> = isPlatformPopup()
return isPlatformPopup()
}
fun withDrawable( fun withDrawable(
@DrawableRes id: Int, @DrawableRes id: Int,
@ -73,8 +71,8 @@ fun withDrawable(
fun hasBottombarItemText( fun hasBottombarItemText(
@StringRes id: Int, @StringRes id: Int,
): Matcher<View>? { ): Matcher<View>? =
return allOf( allOf(
withResourceName("fixed_bottom_navigation_icon"), withResourceName("fixed_bottom_navigation_icon"),
withParent( withParent(
allOf( allOf(
@ -83,23 +81,21 @@ fun hasBottombarItemText(
), ),
), ),
) )
}
fun withSettingsCheckboxWidget( fun withSettingsCheckboxWidget(
@StringRes id: Int, @StringRes id: Int,
): Matcher<View>? { ): Matcher<View>? =
return allOf( allOf(
withId(android.R.id.switch_widget), withId(android.R.id.switch_widget),
withParent( withParent(
withSettingsCheckboxFrame(id), withSettingsCheckboxFrame(id),
), ),
) )
}
fun withSettingsCheckboxFrame( fun withSettingsCheckboxFrame(
@StringRes id: Int, @StringRes id: Int,
): Matcher<View>? { ): Matcher<View>? =
return allOf( allOf(
withId(android.R.id.widget_frame), withId(android.R.id.widget_frame),
hasSibling( hasSibling(
allOf( allOf(
@ -110,7 +106,6 @@ fun withSettingsCheckboxFrame(
), ),
), ),
) )
}
fun openMenu() { fun openMenu() {
openActionBarOverflowOrOptionsMenu( openActionBarOverflowOrOptionsMenu(

View File

@ -36,25 +36,31 @@ class LoginActivityTest {
@Before @Before
fun registerIdlingResource() { fun registerIdlingResource() {
IdlingRegistry.getInstance() IdlingRegistry
.getInstance()
.register(CountingIdlingResourceSingleton.countingIdlingResource) .register(CountingIdlingResourceSingleton.countingIdlingResource)
} }
@After @After
fun unregisterIdlingResource() { fun unregisterIdlingResource() {
IdlingRegistry.getInstance() IdlingRegistry
.getInstance()
.unregister(CountingIdlingResourceSingleton.countingIdlingResource) .unregister(CountingIdlingResourceSingleton.countingIdlingResource)
} }
@Test @Test
fun viewIsInitialized() { fun viewIsInitialized() {
onView(withId(R.id.urlView)).check(matches(isDisplayed())) 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( .check(
matches(isClickable()), matches(isClickable()),
) )
onView(withId(R.id.withLogin)).check(matches(isDisplayed())) onView(withId(R.id.withLogin))
.check(matches(isNotChecked())).check( .check(matches(isDisplayed()))
.check(matches(isNotChecked()))
.check(
matches(isClickable()), matches(isClickable()),
) )
} }

View File

@ -35,7 +35,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.openUrlInBrowser
import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.Enums.ItemType import bou.amine.apps.readerforselfossv2.utils.ItemType
import com.ashokvarma.bottomnavigation.BottomNavigationBar import com.ashokvarma.bottomnavigation.BottomNavigationBar
import com.ashokvarma.bottomnavigation.BottomNavigationItem import com.ashokvarma.bottomnavigation.BottomNavigationItem
import com.ashokvarma.bottomnavigation.TextBadgeItem import com.ashokvarma.bottomnavigation.TextBadgeItem
@ -595,7 +595,7 @@ class HomeActivity :
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.issue_tracker -> { R.id.issue_tracker -> {
baseContext.openUrlInBrowser(AppSettingsService.TRACKER_URL) baseContext.openUrlInBrowser(AppSettingsService.BUG_URL)
return true return true
} }

View File

@ -84,7 +84,9 @@ class ImageActivity : AppCompatActivity() {
return super.onOptionsItemSelected(item) 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 getItemCount(): Int = allImages.size
override fun createFragment(position: Int): Fragment = ImageFragment.newInstance(allImages[position]) override fun createFragment(position: Int): Fragment = ImageFragment.newInstance(allImages[position])

View File

@ -134,9 +134,18 @@ class LoginActivity :
binding.passwordView.error = null binding.passwordView.error = null
// Store values at the time of the login attempt. // Store values at the time of the login attempt.
val url = binding.urlView.text.toString().trim() val url =
val login = binding.loginView.text.toString().trim() binding.urlView.text
val password = binding.passwordView.text.toString().trim() .toString()
.trim()
val login =
binding.loginView.text
.toString()
.trim()
val password =
binding.passwordView.text
.toString()
.trim()
failInvalidUrl(url) failInvalidUrl(url)
failLoginDetails(password, login) failLoginDetails(password, login)
@ -273,7 +282,7 @@ class LoginActivity :
return when (item.itemId) { return when (item.itemId) {
R.id.issue_tracker -> { R.id.issue_tracker -> {
val browserIntent = val browserIntent =
Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.TRACKER_URL)) Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.BUG_URL))
startActivity(browserIntent) startActivity(browserIntent)
return true return true
} }
@ -283,7 +292,7 @@ class LoginActivity :
.withAboutIconShown(true) .withAboutIconShown(true)
.withAboutVersionShown(true) .withAboutVersionShown(true)
.withAboutSpecial2("Bug reports") .withAboutSpecial2("Bug reports")
.withAboutSpecial2Description(AppSettingsService.TRACKER_URL) .withAboutSpecial2Description(AppSettingsService.BUG_URL)
.withAboutSpecial1("Project Page") .withAboutSpecial1("Project Page")
.withAboutSpecial1Description(AppSettingsService.SOURCE_URL) .withAboutSpecial1Description(AppSettingsService.SOURCE_URL)
.start(this) .start(this)

View File

@ -160,7 +160,7 @@ class MyApp :
val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT
val newItemsChannelmChannel = val newItemsChannelmChannel =
NotificationChannel( NotificationChannel(
AppSettingsService.NEW_ITEMS_CHANNEL_ID, AppSettingsService.NEW_ITEMS_CHANNEL,
newItemsChannelname, newItemsChannelname,
newItemsChannelimportance, newItemsChannelimportance,
) )

View File

@ -22,7 +22,9 @@ import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
class ReaderActivity : AppCompatActivity(), DIAware { class ReaderActivity :
AppCompatActivity(),
DIAware {
private var currentItem: Int = 0 private var currentItem: Int = 0
private lateinit var toolbarMenu: Menu private lateinit var toolbarMenu: Menu
@ -99,8 +101,9 @@ class ReaderActivity : AppCompatActivity(), DIAware {
oldInstanceState.clear() oldInstanceState.clear()
} }
private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : private inner class ScreenSlidePagerAdapter(
FragmentStateAdapter(fa) { fa: FragmentActivity,
) : FragmentStateAdapter(fa) {
override fun getItemCount(): Int = allItems.size 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])
@ -109,8 +112,8 @@ class ReaderActivity : AppCompatActivity(), DIAware {
override fun onKeyDown( override fun onKeyDown(
keyCode: Int, keyCode: Int,
event: KeyEvent?, event: KeyEvent?,
): Boolean { ): Boolean =
return when (keyCode) { when (keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> { KeyEvent.KEYCODE_VOLUME_DOWN -> {
val currentFragment = val currentFragment =
supportFragmentManager.findFragmentByTag("f" + binding.pager.currentItem) as ArticleFragment supportFragmentManager.findFragmentByTag("f" + binding.pager.currentItem) as ArticleFragment
@ -129,7 +132,6 @@ class ReaderActivity : AppCompatActivity(), DIAware {
super.onKeyDown(keyCode, event) super.onKeyDown(keyCode, event)
} }
} }
}
private fun alignmentMenu() { private fun alignmentMenu() {
val showJustify = appSettingsService.getActiveAllignment() == AppSettingsService.ALIGN_LEFT val showJustify = appSettingsService.getActiveAllignment() == AppSettingsService.ALIGN_LEFT

View File

@ -18,7 +18,9 @@ import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
class SourcesActivity : AppCompatActivity(), DIAware { class SourcesActivity :
AppCompatActivity(),
DIAware {
private lateinit var binding: ActivitySourcesBinding private lateinit var binding: ActivitySourcesBinding
override val di by closestDI() override val di by closestDI()
@ -68,7 +70,8 @@ class SourcesActivity : AppCompatActivity(), DIAware {
binding.recyclerView.adapter = mAdapter binding.recyclerView.adapter = mAdapter
mAdapter.notifyDataSetChanged() mAdapter.notifyDataSetChanged()
} else { } else {
Toast.makeText( Toast
.makeText(
this@SourcesActivity, this@SourcesActivity,
R.string.cant_get_sources, R.string.cant_get_sources,
Toast.LENGTH_SHORT, Toast.LENGTH_SHORT,

View File

@ -21,7 +21,9 @@ import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
class UpsertSourceActivity : AppCompatActivity(), DIAware { class UpsertSourceActivity :
AppCompatActivity(),
DIAware {
private var existingSource: SelfossModel.SourceDetail? = null private var existingSource: SelfossModel.SourceDetail? = null
private var mSpoutsValue: String? = null private var mSpoutsValue: String? = null
@ -105,7 +107,8 @@ class UpsertSourceActivity : AppCompatActivity(), DIAware {
} }
fun handleSpoutFailure(networkIssue: Boolean = false) { fun handleSpoutFailure(networkIssue: Boolean = false) {
Toast.makeText( Toast
.makeText(
this@UpsertSourceActivity, this@UpsertSourceActivity,
if (networkIssue) R.string.cant_get_spouts_no_network else R.string.cant_get_spouts, if (networkIssue) R.string.cant_get_spouts_no_network else R.string.cant_get_spouts,
Toast.LENGTH_SHORT, Toast.LENGTH_SHORT,
@ -192,7 +195,8 @@ class UpsertSourceActivity : AppCompatActivity(), DIAware {
if (successfullyAddedSource) { if (successfullyAddedSource) {
finish() finish()
} else { } else {
Toast.makeText( Toast
.makeText(
this@UpsertSourceActivity, this@UpsertSourceActivity,
R.string.cant_create_source, R.string.cant_create_source,
Toast.LENGTH_SHORT, Toast.LENGTH_SHORT,

View File

@ -129,5 +129,7 @@ class ItemCardAdapter(
} }
} }
inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) inner class ViewHolder(
val binding: CardItemBinding,
) : RecyclerView.ViewHolder(binding.root)
} }

View File

@ -73,5 +73,7 @@ class ItemListAdapter(
} }
} }
inner class ViewHolder(val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) inner class ViewHolder(
val binding: ListItemBinding,
) : RecyclerView.ViewHolder(binding.root)
} }

View File

@ -11,7 +11,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl
import bou.amine.apps.readerforselfossv2.model.SelfossModel import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.Enums.ItemType import bou.amine.apps.readerforselfossv2.utils.ItemType
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View File

@ -29,7 +29,8 @@ import org.kodein.di.instance
class SourcesListAdapter( class SourcesListAdapter(
private val app: Activity, private val app: Activity,
private val items: ArrayList<SelfossModel.SourceDetail>, private val items: ArrayList<SelfossModel.SourceDetail>,
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>(), DIAware { ) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>(),
DIAware {
private val c: Context = app.baseContext private val c: Context = app.baseContext
private lateinit var binding: SourceListItemBinding private lateinit var binding: SourceListItemBinding
@ -61,7 +62,8 @@ class SourcesListAdapter(
notifyItemRemoved(position) notifyItemRemoved(position)
notifyItemRangeChanged(position, itemCount) notifyItemRangeChanged(position, itemCount)
} else { } else {
Toast.makeText( Toast
.makeText(
app, app,
R.string.can_delete_source, R.string.can_delete_source,
Toast.LENGTH_SHORT, Toast.LENGTH_SHORT,
@ -99,5 +101,7 @@ class SourcesListAdapter(
override fun getItemCount(): Int = items.size override fun getItemCount(): Int = items.size
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) inner class ViewHolder(
val mView: ConstraintLayout,
) : RecyclerView.ViewHolder(mView)
} }

View File

@ -93,7 +93,7 @@ class LoadingWorker(
NotificationCompat NotificationCompat
.Builder( .Builder(
applicationContext, applicationContext,
AppSettingsService.NEW_ITEMS_CHANNEL_ID, AppSettingsService.NEW_ITEMS_CHANNEL,
).setContentTitle(context.getString(R.string.new_items_notification_title)) ).setContentTitle(context.getString(R.string.new_items_notification_title))
.setContentText( .setContentText(
context.getString( context.getString(
@ -101,7 +101,7 @@ class LoadingWorker(
newSize, newSize,
), ),
).setPriority(PRIORITY_DEFAULT) ).setPriority(PRIORITY_DEFAULT)
.setChannelId(AppSettingsService.NEW_ITEMS_CHANNEL_ID) .setChannelId(AppSettingsService.NEW_ITEMS_CHANNEL)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setAutoCancel(true) .setAutoCancel(true)
.setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp) .setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp)

View File

@ -66,7 +66,9 @@ import java.util.concurrent.ExecutionException
private const val IMAGE_JPG = "image/jpg" private const val IMAGE_JPG = "image/jpg"
class ArticleFragment : Fragment(), DIAware { class ArticleFragment :
Fragment(),
DIAware {
private var fontSize: Int = 16 private var fontSize: Int = 16
private lateinit var item: SelfossModel.Item private lateinit var item: SelfossModel.Item
private lateinit var url: String private lateinit var url: String
@ -167,7 +169,8 @@ class ArticleFragment : Fragment(), DIAware {
} catch (e: InflateException) { } catch (e: InflateException) {
e.sendSilentlyWithAcraWithName("webview not available") e.sendSilentlyWithAcraWithName("webview not available")
try { try {
AlertDialog.Builder(requireContext()) AlertDialog
.Builder(requireContext())
.setMessage(requireContext().getString(R.string.webview_dialog_issue_message)) .setMessage(requireContext().getString(R.string.webview_dialog_issue_message))
.setTitle(requireContext().getString(R.string.webview_dialog_issue_title)) .setTitle(requireContext().getString(R.string.webview_dialog_issue_title))
.setPositiveButton( .setPositiveButton(
@ -175,8 +178,7 @@ class ArticleFragment : Fragment(), DIAware {
) { _, _ -> ) { _, _ ->
appSettingsService.disableArticleViewer() appSettingsService.disableArticleViewer()
requireActivity().finish() requireActivity().finish()
} }.create()
.create()
.show() .show()
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
e.sendSilentlyWithAcraWithName("Context required is null") e.sendSilentlyWithAcraWithName("Context required is null")
@ -235,7 +237,8 @@ class ArticleFragment : Fragment(), DIAware {
repository.markAsRead(this@ArticleFragment.item) repository.markAsRead(this@ArticleFragment.item)
} }
this@ArticleFragment.item.unread = false this@ArticleFragment.item.unread = false
Toast.makeText( Toast
.makeText(
requireContext(), requireContext(),
R.string.marked_as_read, R.string.marked_as_read,
Toast.LENGTH_LONG, Toast.LENGTH_LONG,
@ -245,7 +248,8 @@ class ArticleFragment : Fragment(), DIAware {
repository.unmarkAsRead(this@ArticleFragment.item) repository.unmarkAsRead(this@ArticleFragment.item)
} }
this@ArticleFragment.item.unread = true this@ArticleFragment.item.unread = true
Toast.makeText( Toast
.makeText(
context, context,
R.string.marked_as_unread, R.string.marked_as_unread,
Toast.LENGTH_LONG, Toast.LENGTH_LONG,
@ -322,8 +326,7 @@ class ArticleFragment : Fragment(), DIAware {
.asBitmap() .asBitmap()
.load( .load(
lead_image_url, lead_image_url,
) ).apply(RequestOptions.fitCenterTransform())
.apply(RequestOptions.fitCenterTransform())
.into(binding.imageView) .into(binding.imageView)
} else { } else {
binding.imageView.visibility = View.GONE binding.imageView.visibility = View.GONE
@ -337,8 +340,8 @@ class ArticleFragment : Fragment(), DIAware {
override fun shouldOverrideUrlLoading( override fun shouldOverrideUrlLoading(
view: WebView?, view: WebView?,
url: String, url: String,
): Boolean { ): Boolean =
return if (context != null && if (context != null &&
url.isUrlValid() && url.isUrlValid() &&
binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) { ) {
@ -347,7 +350,6 @@ class ArticleFragment : Fragment(), DIAware {
} else { } else {
false false
} }
}
@Deprecated("Deprecated in Java") @Deprecated("Deprecated in Java")
override fun shouldInterceptRequest( override fun shouldInterceptRequest(
@ -356,12 +358,18 @@ class ArticleFragment : Fragment(), DIAware {
): WebResourceResponse? { ): WebResourceResponse? {
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
if (url.lowercase(Locale.US).contains(".jpg") || if (url.lowercase(Locale.US).contains(".jpg") ||
url.lowercase(Locale.US) url
.lowercase(Locale.US)
.contains(".jpeg") .contains(".jpeg")
) { ) {
try { try {
val image = val image =
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() Glide
.with(view)
.asBitmap()
.apply(glideOptions)
.load(url)
.submit()
.get() .get()
return WebResourceResponse( return WebResourceResponse(
IMAGE_JPG, IMAGE_JPG,
@ -374,7 +382,12 @@ class ArticleFragment : Fragment(), DIAware {
} else if (url.lowercase(Locale.US).contains(".png")) { } else if (url.lowercase(Locale.US).contains(".png")) {
try { try {
val image = val image =
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() Glide
.with(view)
.asBitmap()
.apply(glideOptions)
.load(url)
.submit()
.get() .get()
return WebResourceResponse( return WebResourceResponse(
IMAGE_JPG, IMAGE_JPG,
@ -387,7 +400,12 @@ class ArticleFragment : Fragment(), DIAware {
} else if (url.lowercase(Locale.US).contains(".webp")) { } else if (url.lowercase(Locale.US).contains(".webp")) {
try { try {
val image = val image =
Glide.with(view).asBitmap().apply(glideOptions).load(url).submit() Glide
.with(view)
.asBitmap()
.apply(glideOptions)
.load(url)
.submit()
.get() .get()
return WebResourceResponse( return WebResourceResponse(
IMAGE_JPG, IMAGE_JPG,
@ -453,9 +471,7 @@ class ArticleFragment : Fragment(), DIAware {
GestureDetector( GestureDetector(
activity, activity,
object : GestureDetector.SimpleOnGestureListener() { object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean { override fun onSingleTapUp(e: MotionEvent): Boolean = performClick()
return performClick()
}
}, },
) )
@ -600,7 +616,8 @@ class ArticleFragment : Fragment(), DIAware {
} }
fun performClick(): Boolean { fun performClick(): Boolean {
if (allImages != null && ( if (allImages != null &&
(
binding.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || binding.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
binding.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE binding.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) )

View File

@ -33,7 +33,9 @@ import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI import org.kodein.di.android.x.closestDI
import org.kodein.di.instance import org.kodein.di.instance
class FilterSheetFragment : BottomSheetDialogFragment(), DIAware { class FilterSheetFragment :
BottomSheetDialogFragment(),
DIAware {
private lateinit var binding: FilterFragmentBinding private lateinit var binding: FilterFragmentBinding
override val di: DI by closestDI() override val di: DI by closestDI()
private val repository: Repository by instance() private val repository: Repository by instance()
@ -80,7 +82,8 @@ class FilterSheetFragment : BottomSheetDialogFragment(), DIAware {
val c = Chip(context) val c = Chip(context)
c.ellipsize = TextUtils.TruncateAt.END c.ellipsize = TextUtils.TruncateAt.END
Glide.with(context) Glide
.with(context)
.load(source.getIcon(repository.baseUrl)) .load(source.getIcon(repository.baseUrl))
.into( .into(
object : ViewTarget<Chip?, Drawable?>(c) { object : ViewTarget<Chip?, Drawable?>(c) {

View File

@ -14,7 +14,7 @@ class ImageFragment : Fragment() {
private lateinit var imageUrl: String private lateinit var imageUrl: String
private val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) private val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
private var _binding: FragmentImageBinding? = null private var _binding: FragmentImageBinding? = null
private val binding get() = _binding val binding get() = _binding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -31,7 +31,8 @@ class ImageFragment : Fragment() {
val view = binding?.root val view = binding?.root
binding!!.photoView.visibility = View.VISIBLE binding!!.photoView.visibility = View.VISIBLE
Glide.with(requireActivity()) Glide
.with(requireActivity())
.asBitmap() .asBitmap()
.apply(glideOptions) .apply(glideOptions)
.load(imageUrl) .load(imageUrl)

View File

@ -17,9 +17,12 @@ fun SelfossModel.Item.preloadImages(context: Context): Boolean {
try { try {
for (url in imageUrls) { for (url in imageUrls) {
if (URLUtil.isValidUrl(url)) { if (URLUtil.isValidUrl(url)) {
Glide.with(context).asBitmap() Glide
.with(context)
.asBitmap()
.apply(glideOptions) .apply(glideOptions)
.load(url).submit() .load(url)
.submit()
} }
} }
} catch (e: Error) { } catch (e: Error) {

View File

@ -236,7 +236,7 @@ class SettingsActivity :
preferenceManager.findPreference<Preference>("trackerLink")?.onPreferenceClickListener = preferenceManager.findPreference<Preference>("trackerLink")?.onPreferenceClickListener =
Preference.OnPreferenceClickListener { Preference.OnPreferenceClickListener {
openUrl(AppSettingsService.TRACKER_URL) openUrl(AppSettingsService.BUG_URL)
true true
} }

View File

@ -16,7 +16,8 @@ fun Context.shareLink(
sendIntent.putExtra(Intent.EXTRA_SUBJECT, itemTitle) sendIntent.putExtra(Intent.EXTRA_SUBJECT, itemTitle)
sendIntent.type = "text/plain" sendIntent.type = "text/plain"
startActivity( startActivity(
Intent.createChooser( Intent
.createChooser(
sendIntent, sendIntent,
getString(R.string.share), getString(R.string.share),
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),

View File

@ -59,7 +59,5 @@ class CircleImageView
textView.text = text.toTextDrawableString() textView.text = text.toTextDrawableString()
} }
private fun colorFromIdentifier(key: String): Int { private fun colorFromIdentifier(key: String): Int = colorScheme[abs(key.hashCode()) % colorScheme.size]
return colorScheme[abs(key.hashCode()) % colorScheme.size]
}
} }

View File

@ -25,7 +25,8 @@ fun Context.openItemUrl(
app: Activity, app: Activity,
) { ) {
if (!linkDecoded.isUrlValid()) { if (!linkDecoded.isUrlValid()) {
Toast.makeText( Toast
.makeText(
this, this,
this.getString(R.string.cant_open_invalid_url), this.getString(R.string.cant_open_invalid_url),
Toast.LENGTH_LONG, Toast.LENGTH_LONG,

View File

@ -13,7 +13,8 @@ import java.io.InputStream
fun Context.bitmapCenterCrop( fun Context.bitmapCenterCrop(
url: String, url: String,
iv: ImageView, iv: ImageView,
) = Glide.with(this) ) = Glide
.with(this)
.asBitmap() .asBitmap()
.load(url) .load(url)
.apply(RequestOptions.centerCropTransform()) .apply(RequestOptions.centerCropTransform())
@ -25,7 +26,8 @@ fun Context.circularDrawable(
) { ) {
view.textView.text = "" view.textView.text = ""
Glide.with(this) Glide
.with(this)
.load(url) .load(url)
.into(view.imageView) .into(view.imageView)
} }

View File

@ -7,7 +7,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class AppViewModel(private val repository: Repository) : ViewModel() { class AppViewModel(
private val repository: Repository,
) : ViewModel() {
private val _networkAvailableProvider = MutableSharedFlow<Boolean>() private val _networkAvailableProvider = MutableSharedFlow<Boolean>()
val networkAvailableProvider = _networkAvailableProvider.asSharedFlow() val networkAvailableProvider = _networkAvailableProvider.asSharedFlow()
private var wasConnected = true private var wasConnected = true

View File

@ -42,15 +42,14 @@ private const val FEED_URL = "https://test.com/feed"
private const val TAGS = "Test, New" private const val TAGS = "Test, New"
private const val NUMBER_ARTICLES = 100 private val NUMBER_ARTICLES = 100
private const val NUMBER_UNREAD = 50 private val NUMBER_UNREAD = 50
private const val NUMBER_STARRED = 20 private val NUMBER_STARRED = 20
class RepositoryTest { class RepositoryTest {
private val db = mockk<ReaderForSelfossDB>(relaxed = true) private val db = mockk<ReaderForSelfossDB>(relaxed = true)
private val appSettingsService = mockk<AppSettingsService>() private val appSettingsService = mockk<AppSettingsService>()
private val api = mockk<SelfossApi>() private val api = mockk<SelfossApi>()
private lateinit var repository: Repository private lateinit var repository: Repository
private fun initializeRepository( private fun initializeRepository(

View File

@ -44,7 +44,7 @@ class FakeItemParameters {
var datetime = "2022-09-09T03:32:01-04:00" var datetime = "2022-09-09T03:32:01-04:00"
val title = "Etica della ricerca sotto i riflettori." val title = "Etica della ricerca sotto i riflettori."
val content = val content =
"<p><strong>Luigi Campanella, già Presidente SCI</strong></p>\n<p>Letica della scienza è di certo ambito di cui continuiamo</p>" "<p><strong>Luigi Campanella, già Presidente SCI</strong></p>\n<p>Letica della scienza è di certo ambito di cui continuiamo a scoprire nuovi aspetti e risvolti.</p>\n<p>Lultimo è quello delle intelligenze artificiali capaci di creare opere complesse basate su immagini e parole memorizzate con il rischio di fake news e di contenuti disturbanti.</p>\n<p>Per evitare che ciò accada si sta procedendo filtrando secondo criteri di autocensura i dati da cui lintelligenza artificiale parte.</p>\n<p>Comincia ad intravedersi un futuro prossimo di competizione fra autori umani ed artificiali nel quale sarà importante, quando i loro prodotti saranno indistinguibili, dichiararne lorigine.</p>\n<p>Come si comprende, si conferma che gli aspetti etici dellinnovazione e della ricerca si diversificato sempre di più.</p>\n<p>La biologia molecolare e la genetica già in passato hanno posto allattenzione comune aspetti di etica della scienza che hanno indotto a nuove riflessioni circa i limiti delle ricerche.</p>\n<p>Largomento, sempre attuale, torna sulle prime pagine a seguito della pubblicazione di una ricerca della Università di Cambridge che ha sviluppato una struttura cellulare di un topo con un cuore che batte regolarmente.</p>\n<img src=\"https://ilblogdellasci.files.wordpress.com/2022/09/image002-1.png?w=481\" alt=\"\" width=\"697\" height=\"430\" /><img src=\"https://ilblogdellasci.files.wordpress.com/2022/09/image003-1.png?w=906\" alt=\"\" /><p>Magdalena Zernicka-Goetz</p>\n<img src=\"https://ilblogdellasci.files.wordpress.com/2022/09/image004.jpg?w=474\" alt=\"\" width=\"622\" height=\"465\" /><p>Gianluca Amadei</p>\n<p>Del gruppo fa parte anche uno scienziato italiano Gianluca Amadei,che dinnanzi alle obiezioni di natura etica sulla realizzazione della vita artificiale si è affrettato a sostenere che non è creare nuove vite il fine primario della ricerca, ma quello di salvare quelle esistenti, di dare contributi essenziali alla medicina citando il caso del fallimento tuttora non interpretato di alcune gravidanze e di superare la sperimentazione animale, così contribuendo positivamente alla soluzione di un altro dilemma etico.</p>\n<p>Lembrione sintetico ha ovviamente come primo traguardo il contributo ai trapianti oggi drammaticamente carenti nellofferta rispetto alla domanda, con attese fino a 4 anni per i trapianti di cuore ed a 2 anni per quelli di fegato. Il lavoro dovrebbe adesso continuare presso lAteneo di Padova per creare nuovi organi e nuovi farmaci.</p>"
var unread = true var unread = true
var starred = true var starred = true
val thumbnail = null val thumbnail = null

View File

@ -4,12 +4,13 @@ import android.content.Context
import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver
actual class DriverFactory(private val context: Context) { actual class DriverFactory(
actual fun createDriver(): SqlDriver { private val context: Context,
return AndroidSqliteDriver( ) {
actual fun createDriver(): SqlDriver =
AndroidSqliteDriver(
ReaderForSelfossDB.Schema, ReaderForSelfossDB.Schema,
context, context,
"ReaderForSelfossV2-android.db", "ReaderForSelfossV2-android.db",
) )
}
} }

View File

@ -7,7 +7,7 @@ class MercuryModel {
class ParsedContent( class ParsedContent(
val title: String? = null, val title: String? = null,
val content: String? = null, val content: String? = null,
val lead_image_url: String? = null, val lead_image_url: String? = null, // NOSONAR
val url: String? = null, val url: String? = null,
val error: Boolean? = null, val error: Boolean? = null,
val message: String? = null, val message: String? = null,

View File

@ -11,7 +11,7 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.model.StatusAndData import bou.amine.apps.readerforselfossv2.model.StatusAndData
import bou.amine.apps.readerforselfossv2.rest.SelfossApi import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.Enums.ItemType import bou.amine.apps.readerforselfossv2.utils.ItemType
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
import bou.amine.apps.readerforselfossv2.utils.toEntity import bou.amine.apps.readerforselfossv2.utils.toEntity
import bou.amine.apps.readerforselfossv2.utils.toParsedDate import bou.amine.apps.readerforselfossv2.utils.toParsedDate
@ -36,26 +36,26 @@ class Repository(
var displayedItems = ItemType.UNREAD var displayedItems = ItemType.UNREAD
private var tagFilterFlow = MutableStateFlow<SelfossModel.Tag?>(null) private var _tagFilter = MutableStateFlow<SelfossModel.Tag?>(null)
var tagFilter = tagFilterFlow.asStateFlow() var tagFilter = _tagFilter.asStateFlow()
private var sourceFilterFlow = MutableStateFlow<SelfossModel.Source?>(null) private var _sourceFilter = MutableStateFlow<SelfossModel.Source?>(null)
var sourceFilter = sourceFilterFlow.asStateFlow() var sourceFilter = _sourceFilter.asStateFlow()
var searchFilter: String? = null var searchFilter: String? = null
var offlineOverride = false var offlineOverride = false
private val badgeUnreadFlow = MutableStateFlow(0) private val _badgeUnread = MutableStateFlow(0)
val badgeUnread = badgeUnreadFlow.asStateFlow() val badgeUnread = _badgeUnread.asStateFlow()
private val badgeAllFlow = MutableStateFlow(0) private val _badgeAll = MutableStateFlow(0)
val badgeAll = badgeAllFlow.asStateFlow() val badgeAll = _badgeAll.asStateFlow()
private val badgeStarredFlow = MutableStateFlow(0) private val _badgeStarred = MutableStateFlow(0)
val badgeStarred = badgeStarredFlow.asStateFlow() val badgeStarred = _badgeStarred.asStateFlow()
private var fetchedTags = false private var fetchedTags = false
private var fetchedSources = false private var fetchedSources = false
private var readerItems = ArrayList<SelfossModel.Item>() private var _readerItems = ArrayList<SelfossModel.Item>()
private var selectedSource: SelfossModel.SourceDetail? = null private var _selectedSource: SelfossModel.SourceDetail? = null
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> { suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error() var fetchedItems: StatusAndData<List<SelfossModel.Item>> = StatusAndData.error()
@ -144,17 +144,17 @@ class Repository(
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val response = api.stats() val response = api.stats()
if (response.success && response.data != null) { if (response.success && response.data != null) {
badgeUnreadFlow.value = response.data.unread ?: 0 _badgeUnread.value = response.data.unread ?: 0
badgeAllFlow.value = response.data.total _badgeAll.value = response.data.total
badgeStarredFlow.value = response.data.starred ?: 0 _badgeStarred.value = response.data.starred ?: 0
success = true success = true
} }
} else if (appSettingsService.isItemCachingEnabled()) { } else if (appSettingsService.isItemCachingEnabled()) {
// TODO: do this differently, because it's not efficient // TODO: do this differently, because it's not efficient
val dbItems = getDBItems() val dbItems = getDBItems()
badgeUnreadFlow.value = dbItems.filter { item -> item.unread }.size _badgeUnread.value = dbItems.filter { item -> item.unread }.size
badgeStarredFlow.value = dbItems.filter { item -> item.starred }.size _badgeStarred.value = dbItems.filter { item -> item.starred }.size
badgeAllFlow.value = dbItems.size _badgeAll.value = dbItems.size
success = true success = true
} }
return success return success
@ -316,7 +316,7 @@ class Repository(
private fun markAsReadLocally(item: SelfossModel.Item) { private fun markAsReadLocally(item: SelfossModel.Item) {
if (item.unread) { if (item.unread) {
item.unread = false item.unread = false
badgeUnreadFlow.value -= 1 _badgeUnread.value -= 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -327,7 +327,7 @@ class Repository(
private fun unmarkAsReadLocally(item: SelfossModel.Item) { private fun unmarkAsReadLocally(item: SelfossModel.Item) {
if (!item.unread) { if (!item.unread) {
item.unread = true item.unread = true
badgeUnreadFlow.value += 1 _badgeUnread.value += 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -338,7 +338,7 @@ class Repository(
private fun starrLocally(item: SelfossModel.Item) { private fun starrLocally(item: SelfossModel.Item) {
if (!item.starred) { if (!item.starred) {
item.starred = true item.starred = true
badgeStarredFlow.value += 1 _badgeStarred.value += 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -349,7 +349,7 @@ class Repository(
private fun unstarrLocally(item: SelfossModel.Item) { private fun unstarrLocally(item: SelfossModel.Item) {
if (item.starred) { if (item.starred) {
item.starred = false item.starred = false
badgeStarredFlow.value -= 1 _badgeStarred.value -= 1
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -614,30 +614,30 @@ class Repository(
} }
fun setTagFilter(tag: SelfossModel.Tag?) { fun setTagFilter(tag: SelfossModel.Tag?) {
tagFilterFlow.value = tag _tagFilter.value = tag
} }
fun setSourceFilter(source: SelfossModel.Source?) { fun setSourceFilter(source: SelfossModel.Source?) {
sourceFilterFlow.value = source _sourceFilter.value = source
} }
fun setReaderItems(readerItems: ArrayList<SelfossModel.Item>) { fun setReaderItems(readerItems: ArrayList<SelfossModel.Item>) {
this.readerItems = readerItems _readerItems = readerItems
} }
fun getReaderItems(): ArrayList<SelfossModel.Item> = readerItems fun getReaderItems(): ArrayList<SelfossModel.Item> = _readerItems
fun migrate(driverFactory: DriverFactory) { fun migrate(driverFactory: DriverFactory) {
ReaderForSelfossDB.Schema.migrate(driverFactory.createDriver(), 0, 1) ReaderForSelfossDB.Schema.migrate(driverFactory.createDriver(), 0, 1)
} }
fun setSelectedSource(source: SelfossModel.SourceDetail) { fun setSelectedSource(source: SelfossModel.SourceDetail) {
selectedSource = source _selectedSource = source
} }
fun unsetSelectedSource() { fun unsetSelectedSource() {
selectedSource = null _selectedSource = null
} }
fun getSelectedSource(): SelfossModel.SourceDetail? = selectedSource fun getSelectedSource(): SelfossModel.SourceDetail? = _selectedSource
} }

View File

@ -17,8 +17,8 @@ import kotlinx.serialization.json.Json
class MercuryApi { class MercuryApi {
var client = createHttpClient() var client = createHttpClient()
private fun createHttpClient(): HttpClient { private fun createHttpClient(): HttpClient =
return HttpClient { HttpClient {
install(HttpCache) install(HttpCache)
install(ContentNegotiation) { install(ContentNegotiation) {
json( json(
@ -40,7 +40,6 @@ class MercuryApi {
} }
expectSuccess = false expectSuccess = false
} }
}
suspend fun query(url: String): StatusAndData<MercuryModel.ParsedContent> = suspend fun query(url: String): StatusAndData<MercuryModel.ParsedContent> =
bodyOrFailure( bodyOrFailure(

View File

@ -484,11 +484,11 @@ class AppSettingsService(
const val SOURCE_URL = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform" const val SOURCE_URL = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform"
const val TRACKER_URL = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform/issues" const val BUG_URL = "https://gitea.amine-bouabdallaoui.fr/Louvorg/ReaderForSelfoss-multiplatform/issues"
const val SYNC_CHANNEL_ID = "sync-channel-id" const val SYNC_CHANNEL_ID = "sync-channel-id"
const val NEW_ITEMS_CHANNEL_ID = "new-items-channel-id" const val NEW_ITEMS_CHANNEL = "new-items-channel-id"
const val JUSTIFY = 1 const val JUSTIFY = 1

View File

@ -17,7 +17,11 @@ fun String.toParsedDate(): Long {
if (this.matches(oldVersionFormat)) { if (this.matches(oldVersionFormat)) {
this.replace(" ", "T") this.replace(" ", "T")
} else if (this.matches(newVersionFormat)) { } 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 { } else {
throw Exception("Unrecognized format for $this") throw Exception("Unrecognized format for $this")
} }

View File

@ -1,17 +0,0 @@
package bou.amine.apps.readerforselfossv2.utils
object Enums {
enum class ItemType(
val position: Int,
val type: String,
) {
UNREAD(1, "unread"),
ALL(2, "all"),
STARRED(3, "starred"),
;
companion object {
fun fromInt(value: Int) = values().first { it.position == value }
}
}
}

View File

@ -0,0 +1,15 @@
package bou.amine.apps.readerforselfossv2.utils
enum class ItemType(
val position: Int,
val type: String,
) {
UNREAD(1, "unread"),
ALL(2, "all"),
STARRED(3, "starred"),
;
companion object {
fun fromInt(value: Int) = values().first { it.position == value }
}
}

View File

@ -18,7 +18,8 @@ class DatesTest {
fun new_version_date_should_be_parsed() { fun new_version_date_should_be_parsed() {
val date = newVersionDate.toParsedDate() val date = newVersionDate.toParsedDate()
val expected = 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() .toEpochMilliseconds()
assertEquals(expected, date) assertEquals(expected, date)
@ -28,7 +29,8 @@ class DatesTest {
fun new_version_date2_should_be_parsed() { fun new_version_date2_should_be_parsed() {
val date = newVersionDate2.toParsedDate() val date = newVersionDate2.toParsedDate()
val expected = 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() .toEpochMilliseconds()
assertEquals(expected, date) assertEquals(expected, date)
@ -38,7 +40,8 @@ class DatesTest {
fun old_version_date_should_be_parsed() { fun old_version_date_should_be_parsed() {
val date = oldVersionDate.toParsedDate() val date = oldVersionDate.toParsedDate()
val expected = 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() .toEpochMilliseconds()
assertEquals(expected, date) assertEquals(expected, date)
@ -48,7 +51,8 @@ class DatesTest {
fun old_version_variant_date_should_be_parsed() { fun old_version_variant_date_should_be_parsed() {
val date = oldVersionDateVariant.toParsedDate() val date = oldVersionDateVariant.toParsedDate()
val expected = 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() .toEpochMilliseconds()
assertEquals(expected, date) assertEquals(expected, date)
@ -58,7 +62,8 @@ class DatesTest {
fun new_version_variant_date_should_be_parsed() { fun new_version_variant_date_should_be_parsed() {
val date = newVersionDateVariant.toParsedDate() val date = newVersionDateVariant.toParsedDate()
val expected = 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() .toEpochMilliseconds()
assertEquals(expected, date) assertEquals(expected, date)

View File

@ -4,7 +4,5 @@ import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.native.NativeSqliteDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver
actual class DriverFactory { actual class DriverFactory {
actual fun createDriver(): SqlDriver { actual fun createDriver(): SqlDriver = NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db")
return NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db")
}
} }

View File

@ -4,7 +4,5 @@ import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.native.NativeSqliteDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver
actual class DriverFactory { actual class DriverFactory {
actual fun createDriver(): SqlDriver { actual fun createDriver(): SqlDriver = NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db")
return NativeSqliteDriver(ReaderForSelfossDB.Schema, "ReaderForSelfossV2-IOS.db")
}
} }