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(",")
)