enable liking and boosting statuses
This commit is contained in:
parent
4984a68750
commit
f568a2fc81
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue