More debugging. Source adding is still broken. Needs DB integration.

This commit is contained in:
aminecmi 2022-05-21 22:05:11 +02:00
parent 6e38e8753c
commit 4c69e72499
18 changed files with 247 additions and 327 deletions

View File

@ -133,7 +133,7 @@ class AddSourceActivity : AppCompatActivity() {
}
CoroutineScope(Dispatchers.IO).launch {
CoroutineScope(Dispatchers.Main).launch {
var items = api!!.spouts()
if (items != null) {
@ -192,7 +192,7 @@ class AddSourceActivity : AppCompatActivity() {
Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show()
}
else -> {
CoroutineScope(Dispatchers.IO).launch {
CoroutineScope(Dispatchers.Main).launch {
val response: SelfossModel.SuccessResponse? = api.createSourceForVersion(
title,
url,

View File

@ -235,7 +235,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
lastFetchDone = false
handleDrawerItems()
CoroutineScope(Dispatchers.Main).launch {
service.refreshFocusedItems(itemsNumber, applicationContext.isNetworkAvailable())
getElementsAccordingToTab()
binding.swipeRefreshLayout.isRefreshing = false
}
@ -276,7 +275,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
reloadBadgeContent()
val tagHashes = i.tags.split(",").map { it.longHash() }
val tagHashes = i.tags.map { it.longHash() }
tagsBadge = tagsBadge.map {
if (tagHashes.contains(it.key)) {
(it.key to (it.value - 1))
@ -868,9 +867,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
override fun onTabUnselected(position: Int) = Unit
override fun onTabReselected(position: Int) {
val layoutManager = binding.recyclerView.adapter
when (layoutManager) {
when (val layoutManager = binding.recyclerView.adapter) {
is StaggeredGridLayoutManager ->
if (layoutManager.findFirstCompletelyVisibleItemPositions(null)[0] == 0) {
getElementsAccordingToTab()
@ -902,10 +900,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private fun fetchOnEmptyList() {
binding.recyclerView.doOnNextLayout {
// Todo:
// if (SharedItems.focusedItems.size - 1 == getLastVisibleItem()) {
// getElementsAccordingToTab(true)
// }
// TODO: do if last element (or is empty ?)
getElementsAccordingToTab(true)
}
}
@ -927,8 +923,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}
private fun getLastVisibleItem() : Int {
val manager = binding.recyclerView.layoutManager
return when (manager) {
return when (val manager = binding.recyclerView.layoutManager) {
is StaggeredGridLayoutManager -> manager.findLastCompletelyVisibleItemPositions(
null
).last()
@ -945,8 +940,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}
private fun getElementsAccordingToTab(
appendResults: Boolean = false,
offsetOverride: Int? = null
appendResults: Boolean = false
) {
fun doGetAccordingToTab() {
when (elementsShown) {
@ -957,12 +951,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}
}
// Todo:
// offset = if (appendResults) {
// SharedItems.focusedItems.size - 1
// } else {
// 0
// }
offset = if (appendResults && items.size > 0) {
items.size - 1
} else {
0
}
firstVisible = if (appendResults) firstVisible else 0
doGetAccordingToTab()
@ -970,41 +963,42 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private fun getUnRead(appendResults: Boolean = false) {
CoroutineScope(Dispatchers.Main).launch {
// Todo:
// if (appendResults || !SharedItems.fetchedUnread) {
// binding.swipeRefreshLayout.isRefreshing = true
// service.getUnreadItems(itemsNumber, offset, applicationContext.isNetworkAvailable())
// binding.swipeRefreshLayout.isRefreshing = false
// }
// Todo: SharedItems.getUnRead()
// Todo: items = SharedItems.focusedItems
binding.swipeRefreshLayout.isRefreshing = true
val apiItems = service.getUnreadItems(itemsNumber, offset, applicationContext.isNetworkAvailable())
if (appendResults) {
apiItems?.let { items.addAll(it) }
} else {
items = apiItems.orEmpty() as ArrayList<SelfossModel.Item>
}
binding.swipeRefreshLayout.isRefreshing = false
handleListResult()
}
}
private fun getRead(appendResults: Boolean = false) {
CoroutineScope(Dispatchers.Main).launch {
// Todo:
// if (appendResults || !SharedItems.fetchedAll) {
// binding.swipeRefreshLayout.isRefreshing = true
// service.getReadItems(itemsNumber, offset, applicationContext.isNetworkAvailable())
// binding.swipeRefreshLayout.isRefreshing = false
// }
// SharedItems.getAll()
// items = SharedItems.focusedItems
binding.swipeRefreshLayout.isRefreshing = true
val apiItems = service.getReadItems(itemsNumber, offset, applicationContext.isNetworkAvailable())
if (appendResults) {
apiItems?.let { items.addAll(it) }
} else {
items = apiItems.orEmpty() as ArrayList<SelfossModel.Item>
}
binding.swipeRefreshLayout.isRefreshing = false
handleListResult()
}
}
private fun getStarred(appendResults: Boolean = false) {
CoroutineScope(Dispatchers.Main).launch {
if (appendResults || !searchService.fetchedStarred) {
binding.swipeRefreshLayout.isRefreshing = true
service.getStarredItems(itemsNumber, offset, applicationContext.isNetworkAvailable())
binding.swipeRefreshLayout.isRefreshing = false
binding.swipeRefreshLayout.isRefreshing = true
val apiItems = service.getStarredItems(itemsNumber, offset, applicationContext.isNetworkAvailable())
if (appendResults) {
apiItems?.let { items.addAll(it) }
} else {
items = apiItems.orEmpty() as ArrayList<SelfossModel.Item>
}
// Todo: SharedItems.getStarred()
// Todo: items = SharedItems.focusedItems
binding.swipeRefreshLayout.isRefreshing = false
handleListResult()
}
}
@ -1069,7 +1063,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
}
binding.recyclerView.adapter = recyclerAdapter
} else {
(recyclerAdapter as ItemsAdapter<*>).updateAllItems()
(recyclerAdapter as ItemsAdapter<*>).updateAllItems(items)
}
reloadBadges()
@ -1186,7 +1180,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
if (this@HomeActivity.isNetworkAvailable(null, offlineShortcut)) {
CoroutineScope(Dispatchers.Main).launch {
val success = service.readAll(applicationContext.isNetworkAvailable())
val success = service.readAll(items.map { it.id.toString() }, applicationContext.isNetworkAvailable())
if (success) {
Toast.makeText(
this@HomeActivity,

View File

@ -130,7 +130,8 @@ class ReaderActivity : AppCompatActivity() {
private fun readItem(item: SelfossModel.Item) {
if (markOnScroll) {
CoroutineScope(Dispatchers.IO).launch {
// Todo: SharedItems.readItem(applicationContext, api, db, item)
api.markAsRead(item.id.toString())
// TODO: update item in DB
}
}
}
@ -177,7 +178,7 @@ class ReaderActivity : AppCompatActivity() {
inflater.inflate(R.menu.reader_menu, menu)
toolbarMenu = menu
if (allItems.isNotEmpty() && allItems[currentItem].starred == 1) {
if (allItems.isNotEmpty() && allItems[currentItem].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
@ -194,7 +195,7 @@ class ReaderActivity : AppCompatActivity() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (allItems[position].starred == 1) {
if (allItems[position].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
@ -225,26 +226,16 @@ class ReaderActivity : AppCompatActivity() {
return true
}
R.id.star -> {
if (allItems[binding.pager.currentItem].starred == 1) {
if (allItems[binding.pager.currentItem].starred) {
CoroutineScope(Dispatchers.IO).launch {
// Todo:
// SharedItems.unstarItem(
// this@ReaderActivity,
// api,
// db,
// allItems[binding.pager.currentItem]
// )
api.unstarr(allItems[binding.pager.currentItem].id.toString())
// TODO: update in DB
}
afterUnsave()
} else {
CoroutineScope(Dispatchers.IO).launch {
// Todo:
// SharedItems.starItem(
// this@ReaderActivity,
// api,
// db,
// allItems[binding.pager.currentItem]
// )
api.starr(allItems[binding.pager.currentItem].id.toString())
// TODO: update in DB
}
afterSave()
}

View File

@ -80,7 +80,7 @@ class SourcesActivity : AppCompatActivity() {
binding.recyclerView.layoutManager = mLayoutManager
if (this@SourcesActivity.isNetworkAvailable(binding.recyclerView)) {
CoroutineScope(Dispatchers.IO).launch {
CoroutineScope(Dispatchers.Main).launch {
val response = api.sources()
if (response != null) {
items = response

View File

@ -59,7 +59,7 @@ class ItemCardAdapter(
with(holder) {
val itm = items[position]
binding.favButton.isSelected = itm.starred == 1
binding.favButton.isSelected = itm.starred
binding.title.text = itm.getTitleDecoded()
binding.title.setOnTouchListener(LinkOnTouchListener())
@ -112,17 +112,19 @@ class ItemCardAdapter(
binding.favButton.setOnClickListener {
val item = items[bindingAdapterPosition]
if (c.isNetworkAvailable()) {
if (item.starred == 1) {
if (item.starred) {
CoroutineScope(Dispatchers.IO).launch {
// Todo: SharedItems.unstarItem(c, api, db, item)
api.unstarr(item.id.toString())
// TODO: save to db
}
item.starred = 0
item.starred = false
binding.favButton.isSelected = false
} else {
CoroutineScope(Dispatchers.IO).launch {
// Todo: SharedItems.starItem(c, api, db, item)
api.starr(item.id.toString())
// TODO: save to db
}
item.starred = 1
item.starred = true
binding.favButton.isSelected = true
}
}

View File

@ -29,10 +29,10 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
abstract val searchService: SearchService
abstract val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
fun updateAllItems() {
items = ArrayList() // TODO: SharedItems.focusedItems
fun updateAllItems(items: ArrayList<SelfossModel.Item>) {
this.items = items
notifyDataSetChanged()
updateItems(items)
updateItems(this.items)
}
private fun unmarkSnackbar(i: SelfossModel.Item, position: Int) {
@ -44,14 +44,8 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
)
.setAction(R.string.undo_string) {
CoroutineScope(Dispatchers.IO).launch {
// Todo: SharedItems.unreadItem(app, api, db, i)
unreadItemAtIndex(position, false)
}
// Todo:
// if (SharedItems.displayedItems == "unread") {
// addItemAtIndex(i, position)
// } else {
// notifyItemChanged(position)
// }
}
val view = s.view
@ -68,17 +62,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
Snackbar.LENGTH_LONG
)
.setAction(R.string.undo_string) {
CoroutineScope(Dispatchers.IO).launch {
// Todo: SharedItems.readItem(app, api, db, items[position])
}
// Todo: items = SharedItems.focusedItems
// Todo:
// if (SharedItems.displayedItems == "unread") {
// notifyItemRemoved(position)
// updateItems(items)
// } else {
// notifyItemChanged(position)
// }
readItemAtIndex(position)
}
val view = s.view
@ -88,18 +72,19 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
}
fun handleItemAtIndex(position: Int) {
// Todo:
// if (SharedItems.unreadItemStatusAtIndex(position)) {
// readItemAtIndex(position)
// } else {
// unreadItemAtIndex(position)
// }
if (items[position].unread) {
readItemAtIndex(position)
} else {
unreadItemAtIndex(position)
}
}
private fun readItemAtIndex(position: Int) {
private fun readItemAtIndex(position: Int, showSnackbar: Boolean = true) {
val i = items[position]
CoroutineScope(Dispatchers.IO).launch {
// Todo: SharedItems.readItem(app, api, db, i)
api.markAsRead(i.id.toString())
// TODO: update db
}
// Todo:
// if (SharedItems.displayedItems == "unread") {
@ -109,15 +94,22 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
// } else {
// notifyItemChanged(position)
// }
unmarkSnackbar(i, position)
if (showSnackbar) {
unmarkSnackbar(i, position)
}
}
private fun unreadItemAtIndex(position: Int) {
private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) {
CoroutineScope(Dispatchers.IO).launch {
api.unmarkAsRead(items[position].id.toString())
// Todo: SharedItems.unreadItem(app, api, db, items[position])
// TODO: update db
}
notifyItemChanged(position)
markSnackbar(position)
if (showSnackbar) {
markSnackbar(position)
}
}
fun addItemAtIndex(item: SelfossModel.Item, position: Int) {

View File

@ -28,7 +28,6 @@ import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAvailabl
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.rest.SelfossModel
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
import bou.amine.apps.readerforselfossv2.service.SearchService
import bou.amine.apps.readerforselfossv2.service.SelfossService
import bou.amine.apps.readerforselfossv2.utils.DateUtils
@ -109,21 +108,33 @@ override fun doWork(): Result {
}
}
service.getAndStoreAllItems(context.isNetworkAvailable())
// TODO: SharedItems.updateDatabase(db, dateUtils)
storeItems(notifyNewItems, notificationManager)
if (context.isNetworkAvailable()) {
launch {
try {
val newItems = service.allNewItems()
handleNewItemsNotification(newItems, notifyNewItems, notificationManager)
val readItems = service.allReadItems()
val starredItems = service.allStarredItems()
// TODO: save all to DB
} catch (e: Throwable) {}
}
}
}
}
}
return Result.success()
}
private fun storeItems(notifyNewItems: Boolean, notificationManager: NotificationManager) {
private fun handleNewItemsNotification(
newItems: List<SelfossModel.Item>?,
notifyNewItems: Boolean,
notificationManager: NotificationManager
) {
CoroutineScope(Dispatchers.IO).launch {
val apiItems = emptyList<SelfossModel.Item>() // TODO: SharedItems.items
val apiItems = newItems.orEmpty()
val newSize = apiItems.filter { it.unread == 1 }.size
val newSize = apiItems.filter { it.unread }.size
if (notifyNewItems && newSize > 0) {
val intent = Intent(context, MainActivity::class.java).apply {

View File

@ -111,7 +111,9 @@ class ArticleFragment : Fragment() {
service = SelfossService(SelfossApi(apiDetailsService), dbService, SearchService(DateUtils(apiDetailsService)))
item = requireArguments().getParcelable(ARG_ITEMS)!!
val pi: ParecelableItem = requireArguments().getParcelable(ARG_ITEMS)!!
item = pi.toModel()
db = Room.databaseBuilder(
requireContext(),
@ -187,17 +189,12 @@ class ArticleFragment : Fragment() {
R.id.share_action -> requireActivity().shareLink(url, contentTitle)
R.id.open_action -> requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item)
R.id.unread_action -> if (context != null) {
if (this@ArticleFragment.item.unread == 1) {
if (this@ArticleFragment.item.unread) {
CoroutineScope(Dispatchers.IO).launch {
// TODO:
// dbService.readItem(
// context!!,
// api,
// db,
// this@ArticleFragment.item
// )
api.markAsRead(this@ArticleFragment.item.id.toString())
// TODO: Update in DB
}
this@ArticleFragment.item.unread = 0
this@ArticleFragment.item.unread = false
Toast.makeText(
context,
R.string.marked_as_read,
@ -205,15 +202,10 @@ class ArticleFragment : Fragment() {
).show()
} else {
CoroutineScope(Dispatchers.IO).launch {
// TODO
// .unreadItem(
// context!!,
// api,
// db,
// this@ArticleFragment.item
// )
api.unmarkAsRead(this@ArticleFragment.item.id.toString())
// TODO: Update in DB
}
this@ArticleFragment.item.unread = 1
this@ArticleFragment.item.unread = true
Toast.makeText(
context,
R.string.marked_as_unread,

View File

@ -1,7 +1,9 @@
package bou.amine.apps.readerforselfossv2.android.model
import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import androidx.annotation.RequiresApi
import bou.amine.apps.readerforselfossv2.rest.SelfossModel
import com.google.gson.annotations.SerializedName
@ -17,15 +19,29 @@ fun SelfossModel.Item.toParcelable() : ParecelableItem =
this.icon,
this.link,
this.sourcetitle,
this.tags
this.tags.joinToString(",")
)
fun ParecelableItem.toModel() : SelfossModel.Item =
SelfossModel.Item(
this.id,
this.datetime,
this.title,
this.content,
this.unread,
this.starred,
this.thumbnail,
this.icon,
this.link,
this.sourcetitle,
this.tags.split(",")
)
data class ParecelableItem(
@SerializedName("id") val id: String,
@SerializedName("id") val id: Int,
@SerializedName("datetime") val datetime: String,
@SerializedName("title") val title: String,
@SerializedName("content") val content: String,
@SerializedName("unread") var unread: Int,
@SerializedName("starred") var starred: Int,
@SerializedName("unread") var unread: Boolean,
@SerializedName("starred") var starred: Boolean,
@SerializedName("thumbnail") val thumbnail: String?,
@SerializedName("icon") val icon: String?,
@SerializedName("link") val link: String,
@ -42,12 +58,12 @@ data class ParecelableItem(
}
constructor(source: Parcel) : this(
id = source.readString().orEmpty(),
id = source.readInt(),
datetime = source.readString().orEmpty(),
title = source.readString().orEmpty(),
content = source.readString().orEmpty(),
unread = source.readInt(),
starred = source.readInt(),
unread = source.readByte().toInt() != 0,
starred = source.readByte().toInt() != 0,
thumbnail = source.readString(),
icon = source.readString(),
link = source.readString().orEmpty(),
@ -58,12 +74,12 @@ data class ParecelableItem(
override fun describeContents() = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(id)
dest.writeInt(id)
dest.writeString(datetime)
dest.writeString(title)
dest.writeString(content)
dest.writeInt(unread)
dest.writeInt(starred)
dest.writeByte(if (unread) 1 else 0)
dest.writeByte(if (starred) 1 else 0)
dest.writeString(thumbnail)
dest.writeString(icon)
dest.writeString(link)

View File

@ -23,11 +23,11 @@ class AndroidDeviceDatabaseService(db: AndroidDeviceDatabase, searchService: Sea
}
override fun appendNewItems(newItems: List<SelfossModel.Item>) {
var tmpItems = items
if (tmpItems != newItems) {
tmpItems = tmpItems.filter { item -> newItems.find { it.id == item.id } == null } as ArrayList<SelfossModel.Item>
tmpItems.addAll(newItems)
items = tmpItems
var oldItems = items
if (oldItems != newItems) {
oldItems = oldItems.filter { item -> newItems.find { it.id == item.id } == null } as ArrayList<SelfossModel.Item>
oldItems.addAll(newItems)
items = oldItems
sortItems()
getFocusedItems()

View File

@ -8,40 +8,41 @@ import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
class AndroidApiDetailsService(c: Context) : ApiDetailsService {
val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(c)
private var apiVersion: Int = -1
private var baseUrl: String = ""
private var userName: String = ""
private var password: String = ""
private var _apiVersion: Int = -1
private var _baseUrl: String = ""
private var _userName: String = ""
private var _password: String = ""
override fun logApiCalls(message: String) {
Log.d("LogApiCalls", message)
}
override fun getApiVersion(): Int {
if (apiVersion != -1) {
apiVersion = settings.getInt("apiVersion", -1)!!
if (_apiVersion == -1) {
_apiVersion = settings.getInt("apiVersionMajor", -1)!!
return settings.getInt("apiVersionMajor", -1)!!
}
return apiVersion
return _apiVersion
}
override fun getBaseUrl(): String {
if (baseUrl.isEmpty()) {
baseUrl = settings.getString("url", "")!!
if (_baseUrl.isEmpty()) {
_baseUrl = settings.getString("url", "")!!
}
return baseUrl
return _baseUrl
}
override fun getUserName(): String {
if (userName.isEmpty()) {
userName = settings.getString("login", "")!!
if (_userName.isEmpty()) {
_userName = settings.getString("login", "")!!
}
return userName
return _userName
}
override fun getPassword(): String {
if (password.isEmpty()) {
password = settings.getString("password", "")!!
if (_password.isEmpty()) {
_password = settings.getString("password", "")!!
}
return password
return _password
}
}

View File

@ -24,15 +24,6 @@ fun SelfossModel.Item.sourceAndDateText(dateUtils: DateUtils): String {
}
fun SelfossModel.Item.toggleStar(): SelfossModel.Item {
this.starred = if (this.starred == 0) 1 else 0
this.starred = !this.starred
return this
}
fun List<SelfossModel.Item>.flattenTags(): List<SelfossModel.Item> =
this.flatMap {
val item = it
val tags: List<String> = it.tags.split(",")
tags.map { t ->
item.copy(tags = t.trim())
}
}

View File

@ -16,7 +16,7 @@ fun TagEntity.toView(): SelfossModel.Tag =
fun SourceEntity.toView(): SelfossModel.Source =
SelfossModel.Source(
this.id,
this.id.toInt(),
this.title,
this.tags.split(","),
this.spout,
@ -26,7 +26,7 @@ fun SourceEntity.toView(): SelfossModel.Source =
fun SelfossModel.Source.toEntity(): SourceEntity =
SourceEntity(
this.id,
this.id.toString(),
this.getTitleDecoded(),
this.tags.joinToString(","),
this.spout,
@ -43,30 +43,30 @@ fun SelfossModel.Tag.toEntity(): TagEntity =
fun AndroidItemEntity.toView(): SelfossModel.Item =
SelfossModel.Item(
this.id,
this.id.toInt(),
this.datetime,
this.title,
this.content,
if (this.unread) 1 else 0,
if (this.starred) 1 else 0,
this.unread,
this.starred,
this.thumbnail,
this.icon,
this.link,
this.sourcetitle,
this.tags
this.tags.split(",")
)
fun SelfossModel.Item.toEntity(): AndroidItemEntity =
AndroidItemEntity(
this.id,
this.id.toString(),
this.datetime,
this.getTitleDecoded(),
this.content,
this.unread == 1,
this.starred == 1,
this.unread,
this.starred,
this.thumbnail,
this.icon,
this.link,
this.getSourceTitle(),
this.tags
this.tags.joinToString(",")
)

View File

@ -7,6 +7,7 @@ import io.ktor.client.engine.*
import io.ktor.client.engine.ProxyBuilder.http
import io.ktor.client.plugins.auth.*
import io.ktor.client.plugins.auth.providers.*
import io.ktor.client.plugins.cache.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
@ -19,6 +20,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
private val client = HttpClient() {
install(ContentNegotiation) {
install(HttpCache)
json(Json {
prettyPrint = true
isLenient = true
@ -100,7 +102,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
}.body()
suspend fun spouts(): Map<String, SelfossModel.Spout>? =
client.get(url("/a/spouts")) {
client.get(url("/sources/spouts")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
}.body()
@ -115,55 +117,38 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
client.get(url("/api/about")).body()
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/mark/$id"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
},
encodeInQuery = true
).body()
client.post(url("/mark/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
}.body()
suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/unmark/$id"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
},
encodeInQuery = true
).body()
client.post(url("/unmark/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
}.body()
suspend fun starr(id: String): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/starr/$id"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
},
encodeInQuery = true
).body()
client.post(url("/starr/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
}.body()
suspend fun unstarr(id: String): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/unstarr/$id"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
},
encodeInQuery = true
).body()
client.post(url("/unstarr/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
}.body()
suspend fun markAllAsRead(ids: List<String>): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/mark"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
append("ids[]", ids.joinToString(","))
},
encodeInQuery = true
).body()
url = url("/mark"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
ids.map { append("ids[]", it) }
}
).body()
suspend fun createSourceForVersion(
title: String,
@ -186,19 +171,15 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
tags: String,
filter: String
): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/source"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
append("title", title)
append("url", url)
append("spout", spout)
append("tags", tags)
append("filter", filter)
},
encodeInQuery = true
).body()
client.post(url("/source")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("title", title)
parameter("url", url)
parameter("spout", spout)
parameter("tags", tags)
parameter("filter", filter)
}.body()
private suspend fun createSource2(
title: String,
@ -207,21 +188,17 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
tags: String,
filter: String
): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/source"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
append("title", title)
append("url", url)
append("spout", spout)
append("tags[]", tags)
append("filter", filter)
},
encodeInQuery = true
).body()
client.post(url("/source")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("title", title)
parameter("url", url)
parameter("spout", spout)
parameter("tags[]", tags)
parameter("filter", filter)
}.body()
suspend fun deleteSource(id: String): SelfossModel.SuccessResponse? =
suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? =
client.delete(url("/source/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())

View File

@ -52,7 +52,7 @@ class SelfossModel {
@Serializable
data class Source(
val id: String,
val id: Int,
val title: String,
val tags: List<String>,
val spout: String,
@ -62,16 +62,16 @@ class SelfossModel {
@Serializable
data class Item(
val id: String,
val id: Int,
val datetime: String,
val title: String,
val content: String,
var unread: Int,
var starred: Int,
var unread: Boolean,
var starred: Boolean,
val thumbnail: String?,
val icon: String?,
val link: String,
val sourcetitle: String,
val tags: String
val tags: List<String>
)
}

View File

@ -27,8 +27,8 @@ abstract class DeviceDataBaseService<ItemEntity>(val db: DeviceDatabase<ItemEnti
// This filtered items from items val. Do not use
fun getFocusedItems() {}
fun computeBadges() {
searchService.badgeUnread = items.filter { item -> item.unread == 1 }.size
searchService.badgeStarred = items.filter { item -> item.starred == 1 }.size
searchService.badgeUnread = items.filter { item -> item.unread }.size
searchService.badgeStarred = items.filter { item -> item.starred }.size
searchService.badgeAll = items.size
}
}

View File

@ -21,10 +21,6 @@ class SearchService(val dateUtils: DateUtils) {
var tagFilter: String? = null
var itemsCaching = false
var fetchedUnread = false
var fetchedAll = false
var fetchedStarred = false
var badgeUnread = -1
var badgeAll = -1
var badgeStarred = -1

View File

@ -7,90 +7,48 @@ import kotlinx.coroutines.*
class SelfossService<ItemEntity>(val api: SelfossApi, private val dbService: DeviceDataBaseService<ItemEntity>, private val searchService: SearchService) {
suspend fun getAndStoreAllItems(isNetworkAvailable: Boolean) = withContext(
suspend fun getReadItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean): List<SelfossModel.Item>? = withContext(
Dispatchers.Default) {
if (isNetworkAvailable) {
launch {
try {
enqueueArticles(allNewItems(), true)
} catch (e: Throwable) {}
}
launch {
try {
enqueueArticles(allReadItems(), false)
} catch (e: Throwable) {}
}
launch {
try {
enqueueArticles(allStarredItems(), false)
} catch (e: Throwable) {}
}
val apiItems = readItems( itemsNumber, offset)
// SAVE OR UPDATE IN DB
return@withContext apiItems
} else {
launch { dbService.updateDatabase() }
// GET FROM DB
return@withContext emptyList()
}
}
suspend fun refreshFocusedItems(itemsNumber: Int, isNetworkAvailable: Boolean) = withContext(
suspend fun getUnreadItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean): List<SelfossModel.Item>? = withContext(
Dispatchers.Default) {
if (isNetworkAvailable) {
val response = when (searchService.displayedItems) {
"read" -> readItems(itemsNumber, 0)
"unread" -> newItems(itemsNumber, 0)
"starred" -> starredItems(itemsNumber, 0)
else -> readItems(itemsNumber, 0)
}
if (response != null) {
// TODO:
// dbService.refreshFocusedItems(response.body() as ArrayList<SelfossModel.Item>)
dbService.updateDatabase()
}
val apiItems = newItems(itemsNumber, offset)
// SAVE OR UPDATE IN DB
return@withContext apiItems
} else {
// GET FROM DB
return@withContext emptyList()
}
}
suspend fun getReadItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean) = withContext(
suspend fun getStarredItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean): List<SelfossModel.Item>? = withContext(
Dispatchers.Default) {
if (isNetworkAvailable) {
try {
enqueueArticles(readItems( itemsNumber, offset), false)
searchService.fetchedAll = true
dbService.updateDatabase()
} catch (e: Throwable) {}
val apiItems = starredItems(itemsNumber, offset)
// SAVE OR UPDATE IN DB
return@withContext apiItems
} else {
// GET FROM DB
return@withContext emptyList()
}
}
suspend fun getUnreadItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean) = withContext(
Dispatchers.Default) {
if (isNetworkAvailable) {
try {
if (!searchService.fetchedUnread) {
dbService.clearDBItems()
}
enqueueArticles(newItems(itemsNumber, offset), false)
searchService.fetchedUnread = true
} catch (e: Throwable) {}
}
dbService.updateDatabase()
}
suspend fun getStarredItems(itemsNumber: Int, offset: Int, isNetworkAvailable: Boolean) = withContext(
Dispatchers.Default) {
if (isNetworkAvailable) {
try {
enqueueArticles(starredItems(itemsNumber, offset), false)
searchService.fetchedStarred = true
dbService.updateDatabase()
} catch (e: Throwable) {
}
}
}
suspend fun readAll(isNetworkAvailable: Boolean): Boolean {
suspend fun readAll(ids: List<String>, isNetworkAvailable: Boolean): Boolean {
// Add ids params
var success = false
if (isNetworkAvailable) {
// Do api call to read all
} else {
// Do db call to read all
success = api.markAllAsRead(ids)?.isSuccess == true
// SAVE OR UPDATE IN DB
}
// refresh view
return success
@ -100,7 +58,6 @@ class SelfossService<ItemEntity>(val api: SelfossApi, private val dbService: Dev
if (isNetworkAvailable) {
try {
val response = api.stats()
if (response != null) {
searchService.badgeUnread = response.unread
searchService.badgeAll = response.total
@ -123,13 +80,13 @@ class SelfossService<ItemEntity>(val api: SelfossApi, private val dbService: Dev
}
}
private suspend fun allNewItems(): List<SelfossModel.Item>? =
suspend fun allNewItems(): List<SelfossModel.Item>? =
readItems(200, 0)
private suspend fun allReadItems(): List<SelfossModel.Item>? =
suspend fun allReadItems(): List<SelfossModel.Item>? =
newItems(200, 0)
private suspend fun allStarredItems(): List<SelfossModel.Item>? =
suspend fun allStarredItems(): List<SelfossModel.Item>? =
starredItems(200, 0)
private suspend fun readItems(