Compare commits
5 Commits
d862bfba4f
...
6d610ed61a
Author | SHA1 | Date | |
---|---|---|---|
6d610ed61a | |||
792950be7c | |||
|
af8969ce4a | ||
|
27c55e59a1 | ||
|
94a0747947 |
@ -188,7 +188,7 @@ dependencies {
|
|||||||
implementation("com.github.ln-12:multiplatform-connectivity-status:1.3.0")
|
implementation("com.github.ln-12:multiplatform-connectivity-status:1.3.0")
|
||||||
|
|
||||||
// SQLDELIGHT
|
// SQLDELIGHT
|
||||||
implementation("com.squareup.sqldelight:android-driver:1.5.3")
|
implementation("com.squareup.sqldelight:android-driver:1.5.4")
|
||||||
|
|
||||||
//test
|
//test
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
|
@ -63,13 +63,6 @@ class SourcesActivity : AppCompatActivity(), DIAware {
|
|||||||
)
|
)
|
||||||
binding.recyclerView.adapter = mAdapter
|
binding.recyclerView.adapter = mAdapter
|
||||||
mAdapter.notifyDataSetChanged()
|
mAdapter.notifyDataSetChanged()
|
||||||
if (items.isEmpty()) {
|
|
||||||
Toast.makeText(
|
|
||||||
this@SourcesActivity,
|
|
||||||
R.string.nothing_here,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this@SourcesActivity,
|
this@SourcesActivity,
|
||||||
|
@ -10,9 +10,12 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
||||||
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.*
|
import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.shareLink
|
||||||
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
|
||||||
@ -59,7 +62,7 @@ class ItemCardAdapter(
|
|||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||||
|
|
||||||
if (!appSettingsService.isFullHeightCardsEnabled()) {
|
if (!appSettingsService.isFullHeightCardsEnabled()) {
|
||||||
binding.itemImage.maxHeight = imageMaxHeight
|
binding.itemImage.maxHeight = imageMaxHeight
|
||||||
|
@ -51,7 +51,7 @@ class ItemListAdapter(
|
|||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||||
|
|
||||||
if (itm.getThumbnail(repository.baseUrl).isEmpty()) {
|
if (itm.getThumbnail(repository.baseUrl).isEmpty()) {
|
||||||
|
|
||||||
|
@ -61,9 +61,13 @@ class SourcesListAdapter(
|
|||||||
binding.sourceTitle.text = itm.title.getHtmlDecoded()
|
binding.sourceTitle.text = itm.title.getHtmlDecoded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getItemId(position: Int) = position.toLong()
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int) = position
|
||||||
|
|
||||||
override fun getItemCount(): Int = items.size
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
inner class ViewHolder(internal val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
inner class ViewHolder(private val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handleClickListeners()
|
handleClickListeners()
|
||||||
@ -74,13 +78,13 @@ class SourcesListAdapter(
|
|||||||
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
|
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
|
||||||
|
|
||||||
deleteBtn.setOnClickListener {
|
deleteBtn.setOnClickListener {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[bindingAdapterPosition]
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val successfullyDeletedSource = repository.deleteSource(id)
|
val successfullyDeletedSource = repository.deleteSource(id)
|
||||||
if (successfullyDeletedSource) {
|
if (successfullyDeletedSource) {
|
||||||
items.removeAt(adapterPosition)
|
items.removeAt(bindingAdapterPosition)
|
||||||
notifyItemRemoved(adapterPosition)
|
notifyItemRemoved(bindingAdapterPosition)
|
||||||
notifyItemRangeChanged(adapterPosition, itemCount)
|
notifyItemRangeChanged(bindingAdapterPosition, itemCount)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
app,
|
app,
|
||||||
|
@ -101,7 +101,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
contentText = item.content
|
contentText = item.content
|
||||||
contentTitle = item.title.getHtmlDecoded()
|
contentTitle = item.title.getHtmlDecoded()
|
||||||
contentImage = item.getThumbnail(repository.baseUrl)
|
contentImage = item.getThumbnail(repository.baseUrl)
|
||||||
contentSource = item.sourceAndDateText(repository.dateUtils)
|
contentSource = item.sourceAndDateText()
|
||||||
allImages = item.getImages()
|
allImages = item.getImages()
|
||||||
|
|
||||||
fontSize = appSettingsService.getFontSize()
|
fontSize = appSettingsService.getFontSize()
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.repository
|
package bou.amine.apps.readerforselfossv2.repository
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
|
||||||
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
||||||
import io.mockk.mockk
|
|
||||||
import junit.framework.TestCase.assertEquals
|
import junit.framework.TestCase.assertEquals
|
||||||
import kotlinx.datetime.LocalDateTime
|
import kotlinx.datetime.LocalDateTime
|
||||||
import kotlinx.datetime.TimeZone
|
import kotlinx.datetime.TimeZone
|
||||||
@ -10,14 +8,13 @@ import kotlinx.datetime.toInstant
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class DatesTest {
|
class DatesTest {
|
||||||
private val dateUtils: DateUtils = DateUtils()
|
|
||||||
|
|
||||||
private val v3Date = "2013-04-07T13:43:00+01:00"
|
private val v3Date = "2013-04-07T13:43:00+01:00"
|
||||||
private val v4Date = "2013-04-07 13:43:00"
|
private val v4Date = "2013-04-07 13:43:00"
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun v3_date_should_be_parsed() {
|
fun v3_date_should_be_parsed() {
|
||||||
val date = dateUtils.parseDate(v3Date)
|
val date = DateUtils.parseDate(v3Date)
|
||||||
val expected = LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.of("UTC+1")) .toEpochMilliseconds()
|
val expected = LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.of("UTC+1")) .toEpochMilliseconds()
|
||||||
|
|
||||||
assertEquals(date, expected)
|
assertEquals(date, expected)
|
||||||
@ -25,7 +22,7 @@ class DatesTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun v4_date_should_be_parsed() {
|
fun v4_date_should_be_parsed() {
|
||||||
val date = dateUtils.parseDate(v4Date)
|
val date = DateUtils.parseDate(v4Date)
|
||||||
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()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
// SqlDelight
|
// SqlDelight
|
||||||
classpath("com.squareup.sqldelight:gradle-plugin:1.5.3")
|
classpath("com.squareup.sqldelight:gradle-plugin:1.5.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
object SqlDelight {
|
object SqlDelight {
|
||||||
const val runtime = "com.squareup.sqldelight:runtime:1.5.3"
|
const val runtime = "com.squareup.sqldelight:runtime:1.5.4"
|
||||||
const val android = "com.squareup.sqldelight:android-driver:1.5.3"
|
const val android = "com.squareup.sqldelight:android-driver:1.5.4"
|
||||||
const val native = "com.squareup.sqldelight:native-driver:1.5.3"
|
const val native = "com.squareup.sqldelight:native-driver:1.5.4"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,24 +5,25 @@ import kotlinx.datetime.*
|
|||||||
|
|
||||||
|
|
||||||
actual class DateUtils {
|
actual class DateUtils {
|
||||||
|
actual companion object {
|
||||||
|
actual fun parseDate(dateString: String): Long {
|
||||||
|
return try {
|
||||||
|
Instant.parse(dateString).toEpochMilliseconds()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LocalDateTime.parse(dateString.replace(" ", "T")).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual fun parseRelativeDate(dateString: String): String {
|
||||||
return try {
|
|
||||||
Instant.parse(dateString).toEpochMilliseconds()
|
val date = parseDate(dateString)
|
||||||
} catch (e: Exception) {
|
|
||||||
LocalDateTime.parse(dateString.replace(" ", "T")).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
return " " + DateUtils.getRelativeTimeSpanString(
|
||||||
|
date,
|
||||||
|
Clock.System.now().toEpochMilliseconds(),
|
||||||
|
DateUtils.MINUTE_IN_MILLIS,
|
||||||
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun parseRelativeDate(dateString: String): String {
|
|
||||||
|
|
||||||
val date = parseDate(dateString)
|
|
||||||
|
|
||||||
return " " + DateUtils.getRelativeTimeSpanString(
|
|
||||||
date,
|
|
||||||
Clock.System.now().toEpochMilliseconds(),
|
|
||||||
DateUtils.MINUTE_IN_MILLIS,
|
|
||||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -108,8 +108,8 @@ class SelfossModel {
|
|||||||
return stringUrl
|
return stringUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sourceAndDateText(dateUtils: DateUtils): String =
|
fun sourceAndDateText(): String =
|
||||||
this.sourcetitle.getHtmlDecoded() + dateUtils.parseRelativeDate(this.datetime)
|
this.sourcetitle.getHtmlDecoded() + DateUtils.parseRelativeDate(this.datetime)
|
||||||
|
|
||||||
fun toggleStar(): Item {
|
fun toggleStar(): Item {
|
||||||
this.starred = !this.starred
|
this.starred = !this.starred
|
||||||
|
@ -18,7 +18,6 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
var connectionMonitored = false
|
var connectionMonitored = false
|
||||||
|
|
||||||
var baseUrl = appSettingsService.getBaseUrl()
|
var baseUrl = appSettingsService.getBaseUrl()
|
||||||
var dateUtils: DateUtils = DateUtils()
|
|
||||||
|
|
||||||
var displayedItems = ItemType.UNREAD
|
var displayedItems = ItemType.UNREAD
|
||||||
|
|
||||||
@ -74,7 +73,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
if (fetchedItems.success && fetchedItems.data != null) {
|
if (fetchedItems.success && fetchedItems.data != null) {
|
||||||
items = ArrayList(fetchedItems.data!!)
|
items = ArrayList(fetchedItems.data!!)
|
||||||
if (fromDB) {
|
if (fromDB) {
|
||||||
items.sortByDescending { dateUtils.parseDate(it.datetime) }
|
items.sortByDescending { DateUtils.parseDate(it.datetime) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.service
|
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
|
||||||
|
|
||||||
class SearchService(val dateUtils: DateUtils) {
|
|
||||||
var displayedItems: String = "unread"
|
|
||||||
set(value) {
|
|
||||||
field = when (value) {
|
|
||||||
"all" -> "all"
|
|
||||||
"unread" -> "unread"
|
|
||||||
"read" -> "read"
|
|
||||||
"starred" -> "starred"
|
|
||||||
else -> "all"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var position = 0
|
|
||||||
var searchFilter: String? = null
|
|
||||||
var sourceIDFilter: Long? = null
|
|
||||||
var sourceFilter: String? = null
|
|
||||||
var tagFilter: String? = null
|
|
||||||
var itemsCaching = false
|
|
||||||
|
|
||||||
var badgeUnread = -1
|
|
||||||
var badgeAll = -1
|
|
||||||
var badgeStarred = -1
|
|
||||||
}
|
|
@ -1,14 +1,9 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
|
||||||
|
|
||||||
|
|
||||||
fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long =
|
|
||||||
dateUtils.parseDate(this.datetime)
|
|
||||||
|
|
||||||
expect class DateUtils() {
|
expect class DateUtils() {
|
||||||
fun parseDate(dateString: String): Long
|
companion object {
|
||||||
|
fun parseDate(dateString: String): Long
|
||||||
|
|
||||||
fun parseRelativeDate(dateString: String): String
|
fun parseRelativeDate(dateString: String): String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
actual class DateUtils {
|
||||||
|
actual companion object {
|
||||||
|
actual fun parseDate(dateString: String): Long {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
|
actual fun parseRelativeDate(dateString: String): String {
|
||||||
actual fun parseDate(dateString: String): Long {
|
TODO("Not yet implemented")
|
||||||
TODO("Not yet implemented")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun parseRelativeDate(dateString: String): String {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -2,13 +2,15 @@ package bou.amine.apps.readerforselfossv2.utils
|
|||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
|
||||||
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
|
actual class DateUtils {
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual companion object {
|
||||||
TODO("Not yet implemented")
|
actual fun parseDate(dateString: String): Long {
|
||||||
}
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
actual fun parseRelativeDate(dateString: String): String {
|
actual fun parseRelativeDate(dateString: String): String {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user