add like/boost functionality

This commit is contained in:
Conny Duck 2020-06-29 22:25:09 +02:00
parent 98d654876e
commit 8d3fd8eeff
7 changed files with 107 additions and 56 deletions

View File

@ -80,19 +80,14 @@ class TimelineFragment : DaggerFragment(R.layout.fragment_timeline), TimeLineAct
binding.timelineSwipeRefresh.isRefreshing = false binding.timelineSwipeRefresh.isRefreshing = false
} }
// viewModel.posts.observe(viewLifecycleOwner, Observer { t -> adapter.submitList(t) })
} }
companion object { override fun onFavorite(status: StatusEntity) {
fun newInstance() = TimelineFragment() viewModel.onFavorite(status)
} }
override fun onFavorite(post: StatusEntity) { override fun onBoost(status: StatusEntity) {
viewModel.onFavorite(post) viewModel.onBoost(status)
}
override fun onBoost(post: StatusEntity) {
viewModel.onBoost(post)
} }
override fun onReply(status: StatusEntity) { override fun onReply(status: StatusEntity) {
@ -106,4 +101,8 @@ class TimelineFragment : DaggerFragment(R.layout.fragment_timeline), TimeLineAct
override fun onDetailsOpened(status: StatusEntity) { override fun onDetailsOpened(status: StatusEntity) {
startActivity(DetailActivity.newIntent(requireContext(), status.actionableId)) startActivity(DetailActivity.newIntent(requireContext(), status.actionableId))
} }
companion object {
fun newInstance() = TimelineFragment()
}
} }

View File

@ -35,8 +35,8 @@ import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
interface TimeLineActionListener { interface TimeLineActionListener {
fun onFavorite(post: StatusEntity) fun onFavorite(status: StatusEntity)
fun onBoost(post: StatusEntity) fun onBoost(status: StatusEntity)
fun onReply(status: StatusEntity) fun onReply(status: StatusEntity)
fun onMediaVisibilityChanged(status: StatusEntity) fun onMediaVisibilityChanged(status: StatusEntity)
fun onDetailsOpened(status: StatusEntity) fun onDetailsOpened(status: StatusEntity)

View File

@ -0,0 +1,61 @@
package at.connyduck.pixelcat.components.timeline
import at.connyduck.pixelcat.db.AccountManager
import at.connyduck.pixelcat.db.AppDatabase
import at.connyduck.pixelcat.db.entitity.StatusEntity
import at.connyduck.pixelcat.db.entitity.toEntity
import at.connyduck.pixelcat.model.Status
import at.connyduck.pixelcat.network.FediverseApi
import at.connyduck.pixelcat.network.calladapter.NetworkResponse
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TimelineUseCases @Inject constructor(
val api: FediverseApi,
val db: AppDatabase,
val accountManager: AccountManager
) {
suspend fun onFavorite(status: StatusEntity) {
val alreadyFavourited = status.favourited
if (alreadyFavourited) {
api.unfavouriteStatus(status.actionableId)
} else {
api.favouriteStatus(status.actionableId)
}.updateStatusInDb()
}
suspend fun onBoost(status: StatusEntity) {
val alreadyBoosted = status.reblogged
if (alreadyBoosted) {
api.unreblogStatus(status.actionableId)
} else {
api.reblogStatus(status.actionableId)
}.updateStatusInDb()
}
suspend fun onMediaVisibilityChanged(status: StatusEntity) {
db.statusDao().changeMediaVisibility(
!status.mediaVisible,
status.id,
accountManager.activeAccount()?.id!!
)
}
private suspend fun NetworkResponse<Status>.updateStatusInDb() {
fold<Any?>(
{ updatedStatus ->
val accountId = accountManager.activeAccount()?.id!!
val updatedStatusEntity = updatedStatus.toEntity(accountId)
db.statusDao().insertOrReplace(updatedStatusEntity)
},
{
// Todo
}
)
}
}

View File

@ -28,10 +28,7 @@ import androidx.paging.cachedIn
import at.connyduck.pixelcat.db.AccountManager import at.connyduck.pixelcat.db.AccountManager
import at.connyduck.pixelcat.db.AppDatabase import at.connyduck.pixelcat.db.AppDatabase
import at.connyduck.pixelcat.db.entitity.StatusEntity import at.connyduck.pixelcat.db.entitity.StatusEntity
import at.connyduck.pixelcat.db.entitity.toEntity
import at.connyduck.pixelcat.model.Status
import at.connyduck.pixelcat.network.FediverseApi import at.connyduck.pixelcat.network.FediverseApi
import at.connyduck.pixelcat.network.calladapter.NetworkResponse
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.flatMapConcat import kotlinx.coroutines.flow.flatMapConcat
@ -39,9 +36,10 @@ import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class TimelineViewModel @Inject constructor( class TimelineViewModel @Inject constructor(
private val accountManager: AccountManager, accountManager: AccountManager,
private val db: AppDatabase, private val db: AppDatabase,
private val fediverseApi: FediverseApi private val fediverseApi: FediverseApi,
private val useCases: TimelineUseCases
) : ViewModel() { ) : ViewModel() {
@OptIn(FlowPreview::class) @OptIn(FlowPreview::class)
@ -58,46 +56,20 @@ class TimelineViewModel @Inject constructor(
fun onFavorite(status: StatusEntity) { fun onFavorite(status: StatusEntity) {
viewModelScope.launch { viewModelScope.launch {
val alreadyFavourited = status.favourited useCases.onFavorite(status)
if (alreadyFavourited) {
fediverseApi.unfavouriteStatus(status.actionableId)
} else {
fediverseApi.favouriteStatus(status.actionableId)
}.updateStatusInDb()
} }
} }
fun onBoost(status: StatusEntity) { fun onBoost(status: StatusEntity) {
viewModelScope.launch { viewModelScope.launch {
val alreadyBoosted = status.reblogged useCases.onBoost(status)
if (alreadyBoosted) {
fediverseApi.unreblogStatus(status.actionableId)
} else {
fediverseApi.reblogStatus(status.actionableId)
}.updateStatusInDb()
} }
} }
fun onMediaVisibilityChanged(status: StatusEntity) { fun onMediaVisibilityChanged(status: StatusEntity) {
viewModelScope.launch { viewModelScope.launch {
db.statusDao().changeMediaVisibility( useCases.onMediaVisibilityChanged(status)
!status.mediaVisible,
status.id,
accountManager.activeAccount()?.id!!
)
} }
} }
private suspend fun NetworkResponse<Status>.updateStatusInDb() {
fold<Any?>(
{ updatedStatus ->
val accountId = accountManager.activeAccount()?.id!!
val updatedStatusEntity = updatedStatus.toEntity(accountId)
db.statusDao().insertOrReplace(updatedStatusEntity)
},
{
// Todo
}
)
}
} }

View File

@ -80,12 +80,12 @@ class DetailActivity: BaseActivity(), TimeLineActionListener {
} }
override fun onFavorite(post: StatusEntity) { override fun onFavorite(status: StatusEntity) {
TODO("Not yet implemented") viewModel.onFavorite(status)
} }
override fun onBoost(post: StatusEntity) { override fun onBoost(status: StatusEntity) {
TODO("Not yet implemented") viewModel.onBoost(status)
} }
override fun onReply(status: StatusEntity) { override fun onReply(status: StatusEntity) {
@ -93,7 +93,7 @@ class DetailActivity: BaseActivity(), TimeLineActionListener {
} }
override fun onMediaVisibilityChanged(status: StatusEntity) { override fun onMediaVisibilityChanged(status: StatusEntity) {
TODO("Not yet implemented") viewModel.onMediaVisibilityChanged(status)
} }
override fun onDetailsOpened(status: StatusEntity) { override fun onDetailsOpened(status: StatusEntity) {

View File

@ -22,6 +22,7 @@ package at.connyduck.pixelcat.components.timeline.detail
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import at.connyduck.pixelcat.components.timeline.TimelineUseCases
import at.connyduck.pixelcat.components.util.Loading import at.connyduck.pixelcat.components.util.Loading
import at.connyduck.pixelcat.components.util.Success import at.connyduck.pixelcat.components.util.Success
import at.connyduck.pixelcat.components.util.UiState import at.connyduck.pixelcat.components.util.UiState
@ -35,9 +36,10 @@ import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class DetailViewModel @Inject constructor( class DetailViewModel @Inject constructor(
val api: FediverseApi, private val api: FediverseApi,
val db: AppDatabase, private val db: AppDatabase,
val accountManager: AccountManager private val accountManager: AccountManager,
private val useCases: TimelineUseCases
) : ViewModel() { ) : ViewModel() {
val currentStatus = MutableLiveData<UiState<StatusEntity>>() val currentStatus = MutableLiveData<UiState<StatusEntity>>()
@ -75,7 +77,6 @@ class DetailViewModel @Inject constructor(
} }
} }
private suspend fun loadStatus() { private suspend fun loadStatus() {
api.status(statusId).fold({ api.status(statusId).fold({
val statusEntity = it.toEntity(accountManager.activeAccount()?.id!!) val statusEntity = it.toEntity(accountManager.activeAccount()?.id!!)
@ -96,4 +97,22 @@ class DetailViewModel @Inject constructor(
}) })
} }
fun onFavorite(status: StatusEntity) {
viewModelScope.launch {
useCases.onFavorite(status)
}
}
fun onBoost(status: StatusEntity) {
viewModelScope.launch {
useCases.onBoost(status)
}
}
fun onMediaVisibilityChanged(status: StatusEntity) {
viewModelScope.launch {
useCases.onMediaVisibilityChanged(status)
}
}
} }

View File

@ -3,6 +3,6 @@ package at.connyduck.pixelcat.components.util
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
class BindingHolder<T: ViewBinding>( class BindingHolder<T : ViewBinding>(
val binding: T val binding: T
): RecyclerView.ViewHolder(binding.root) ) : RecyclerView.ViewHolder(binding.root)