enable liking and boosting statuses

This commit is contained in:
Konrad Pozniak 2020-06-14 09:13:19 +02:00
parent 4984a68750
commit f568a2fc81
11 changed files with 126 additions and 42 deletions

View File

@ -71,7 +71,7 @@ class TimelineFragment : DaggerFragment(R.layout.fragment_timeline), TimeLineAct
} }
override fun onBoost(post: StatusEntity) { override fun onBoost(post: StatusEntity) {
TODO("Not yet implemented") viewModel.onBoost(post)
} }
override fun onReply(status: StatusEntity) { override fun onReply(status: StatusEntity) {

View File

@ -67,6 +67,8 @@ class TimelineListAdapter(
true true
} }
holder.binding.postBoostButton.isChecked = status.reblogged
holder.binding.postBoostButton.setEventListener { button, buttonState -> holder.binding.postBoostButton.setEventListener { button, buttonState ->
listener.onBoost(status) listener.onBoost(status)
true true

View File

@ -9,7 +9,10 @@ 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
@ -19,7 +22,7 @@ import javax.inject.Inject
class TimelineViewModel @Inject constructor( class TimelineViewModel @Inject constructor(
private val accountManager: AccountManager, private val accountManager: AccountManager,
private val db: AppDatabase, private val db: AppDatabase,
fediverseApi: FediverseApi private val fediverseApi: FediverseApi
) : ViewModel() { ) : ViewModel() {
@OptIn(FlowPreview::class) @OptIn(FlowPreview::class)
@ -36,13 +39,46 @@ class TimelineViewModel @Inject constructor(
fun onFavorite(status: StatusEntity) { fun onFavorite(status: StatusEntity) {
viewModelScope.launch { viewModelScope.launch {
// repository.onFavorite(status, accountManager.activeAccount()?.id!!) val alreadyFavourited = status.favourited
if (alreadyFavourited) {
fediverseApi.unfavouriteStatus(status.actionableId)
} else {
fediverseApi.favouriteStatus(status.actionableId)
}.updateStatusInDb()
}
}
fun onBoost(status: StatusEntity) {
viewModelScope.launch {
val alreadyBoosted = status.reblogged
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(!status.mediaVisible, status.id, accountManager.activeAccount()?.id!!) 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

@ -12,7 +12,7 @@ import at.connyduck.pixelcat.db.entitity.StatusEntity
interface TimelineDao { interface TimelineDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertOrReplace(status: StatusEntity): Long suspend fun insertOrReplace(status: StatusEntity)
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertOrReplace(statuses: List<StatusEntity>) suspend fun insertOrReplace(statuses: List<StatusEntity>)

View File

@ -15,6 +15,7 @@ import java.util.Date
data class StatusEntity( data class StatusEntity(
val accountId: Long, val accountId: Long,
val id: String, val id: String,
val actionableId: String,
val url: String?, // not present if it's reblog val url: String?, // not present if it's reblog
@Embedded(prefix = "a_") val account: TimelineAccountEntity, @Embedded(prefix = "a_") val account: TimelineAccountEntity,
val content: String, val content: String,
@ -27,7 +28,6 @@ data class StatusEntity(
val spoilerText: String, val spoilerText: String,
val visibility: Status.Visibility, val visibility: Status.Visibility,
val attachments: List<Attachment>, val attachments: List<Attachment>,
val mediaPosition: Int, val mediaPosition: Int,
val mediaVisible: Boolean val mediaVisible: Boolean
) )
@ -35,6 +35,7 @@ data class StatusEntity(
fun Status.toEntity(accountId: Long, mediaPosition: Int = 0, mediaVisible: Boolean = !this.sensitive) = StatusEntity( fun Status.toEntity(accountId: Long, mediaPosition: Int = 0, mediaVisible: Boolean = !this.sensitive) = StatusEntity(
accountId = accountId, accountId = accountId,
id = id, id = id,
actionableId = actionableStatus.id,
url = actionableStatus.url, url = actionableStatus.url,
account = actionableStatus.account.toEntity(accountId), account = actionableStatus.account.toEntity(accountId),
content = actionableStatus.content, content = actionableStatus.content,

View File

@ -154,4 +154,14 @@ interface FediverseApi {
suspend fun unfavouriteStatus( suspend fun unfavouriteStatus(
@Path("id") statusId: String @Path("id") statusId: String
): NetworkResponse<Status> ): NetworkResponse<Status>
@POST("api/v1/statuses/{id}/reblog")
suspend fun reblogStatus(
@Path("id") statusId: String
): NetworkResponse<Status>
@POST("api/v1/statuses/{id}/unreblog")
suspend fun unreblogStatus(
@Path("id") statusId: String
): NetworkResponse<Status>
} }

View File

@ -7,7 +7,7 @@
android:pathData="M20.84,4.61a5.5,5.5 0,0 0,-7.78 0L12,5.67l-1.06,-1.06a5.5,5.5 0,0 0,-7.78 7.78l1.06,1.06L12,21.23l7.78,-7.78 1.06,-1.06a5.5,5.5 0,0 0,0 -7.78z" android:pathData="M20.84,4.61a5.5,5.5 0,0 0,-7.78 0L12,5.67l-1.06,-1.06a5.5,5.5 0,0 0,-7.78 7.78l1.06,1.06L12,21.23l7.78,-7.78 1.06,-1.06a5.5,5.5 0,0 0,0 -7.78z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="2" android:strokeWidth="2"
android:fillColor="#f00" android:fillColor="@color/pixelcat_gradient_warm_middle"
android:strokeColor="#f00" android:strokeColor="@color/pixelcat_gradient_warm_middle"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View File

@ -1,34 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:fillColor="#00000000" android:fillColor="#00000000"
android:pathData="M17,1l4,4l-4,4" android:pathData="M17,1l4,4l-4,4"
android:strokeWidth="2" android:strokeWidth="2"
android:strokeColor="?android:attr/textColorTertiary" android:strokeColor="?android:attr/textColorTertiary"
android:strokeLineCap="round" android:strokeLineCap="round"
android:strokeLineJoin="round" /> android:strokeLineJoin="round" />
<path <path
android:fillColor="#00000000" android:fillColor="#00000000"
android:pathData="M3,11V9a4,4 0,0 1,4 -4h14" android:pathData="M3,11V9a4,4 0,0 1,4 -4h14"
android:strokeWidth="2" android:strokeWidth="2"
android:strokeColor="?android:attr/textColorTertiary" android:strokeColor="?android:attr/textColorTertiary"
android:strokeLineCap="round" android:strokeLineCap="round"
android:strokeLineJoin="round" /> android:strokeLineJoin="round" />
<path <path
android:fillColor="#00000000" android:fillColor="#00000000"
android:pathData="M7,23l-4,-4l4,-4" android:pathData="M7,23l-4,-4l4,-4"
android:strokeWidth="2" android:strokeWidth="2"
android:strokeColor="?android:attr/textColorTertiary" android:strokeColor="?android:attr/textColorTertiary"
android:strokeLineCap="round" android:strokeLineCap="round"
android:strokeLineJoin="round" /> android:strokeLineJoin="round" />
<path <path
android:fillColor="#00000000" android:fillColor="#00000000"
android:pathData="M21,13v2a4,4 0,0 1,-4 4H3" android:pathData="M21,13v2a4,4 0,0 1,-4 4H3"
android:strokeWidth="2" android:strokeWidth="2"
android:strokeColor="?android:attr/textColorTertiary" android:strokeColor="?android:attr/textColorTertiary"
android:strokeLineCap="round" android:strokeLineCap="round"
android:strokeLineJoin="round" /> android:strokeLineJoin="round" />
</vector> </vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"
android:pathData="M17,1l4,4l-4,4"
android:strokeWidth="2"
android:strokeColor="@color/pixelcat_gradient_cold_middle"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M3,11V9a4,4 0,0 1,4 -4h14"
android:strokeWidth="2"
android:strokeColor="@color/pixelcat_gradient_cold_middle"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M7,23l-4,-4l4,-4"
android:strokeWidth="2"
android:strokeColor="@color/pixelcat_gradient_cold_middle"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M21,13v2a4,4 0,0 1,-4 4H3"
android:strokeWidth="2"
android:strokeColor="@color/pixelcat_gradient_cold_middle"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector>

View File

@ -5,6 +5,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipChildren="false"
android:paddingBottom="8dp"> android:paddingBottom="8dp">
<ImageView <ImageView
@ -60,8 +61,8 @@
android:layout_height="0dp" android:layout_height="0dp"
android:background="#ccc" android:background="#ccc"
android:gravity="center" android:gravity="center"
android:textStyle="bold"
android:text="@string/sensitive_media" android:text="@string/sensitive_media"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/postImages" app:layout_constraintBottom_toBottomOf="@id/postImages"
app:layout_constraintTop_toTopOf="@id/postImages" /> app:layout_constraintTop_toTopOf="@id/postImages" />
@ -90,7 +91,7 @@
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
app:layout_constraintStart_toEndOf="@id/postLikeButton" app:layout_constraintStart_toEndOf="@id/postLikeButton"
app:layout_constraintTop_toBottomOf="@id/postImages" app:layout_constraintTop_toBottomOf="@id/postImages"
sparkbutton:activeImage="@drawable/ic_repeat" sparkbutton:activeImage="@drawable/ic_repeat_active"
sparkbutton:iconSize="24dp" sparkbutton:iconSize="24dp"
sparkbutton:inactiveImage="@drawable/ic_repeat" sparkbutton:inactiveImage="@drawable/ic_repeat"
sparkbutton:primaryColor="@color/boost_button_primary" sparkbutton:primaryColor="@color/boost_button_primary"

View File

@ -14,10 +14,10 @@
<color name="divider_color">#e0e0e0</color> <color name="divider_color">#e0e0e0</color>
<color name="heart_button_primary">#f00</color> <color name="heart_button_primary">@color/pixelcat_gradient_warm_end</color>
<color name="heart_button_secondary">#f90</color> <color name="heart_button_secondary">@color/pixelcat_gradient_warm_start</color>
<color name="boost_button_primary">#1A2980</color> <color name="boost_button_primary">@color/pixelcat_gradient_cold_end</color>
<color name="boost_button_secondary">#207da7</color> <color name="boost_button_secondary">@color/pixelcat_gradient_cold_start</color>
</resources> </resources>