More work on stories

This commit is contained in:
Matthieu 2023-05-09 22:48:06 +02:00
parent 888c6328d9
commit f60889ea14
5 changed files with 149 additions and 8 deletions

View File

@ -4,6 +4,8 @@ import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
@ -13,7 +15,9 @@ import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.launch
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ActivityStoriesBinding
import org.pixeldroid.app.posts.setTextViewFromISO8601
import org.pixeldroid.app.utils.BaseThemedWithoutBarActivity
@ -43,6 +47,23 @@ class StoriesActivity: BaseThemedWithoutBarActivity() {
uiState.age?.let { setTextViewFromISO8601(it, binding.storyAge, false) }
if (uiState.errorMessage != null) {
binding.storyErrorText.text = uiState.errorMessage
binding.storyErrorCard.isVisible = true
} else binding.storyErrorCard.isVisible = false
if (uiState.snackBar != null) {
Snackbar.make(
binding.root, uiState.snackBar,
Snackbar.LENGTH_SHORT
).setAnchorView(binding.storyReplyField).show()
model.shownSnackbar()
}
if (uiState.username != null) {
binding.storyReplyField.hint = getString(R.string.replyToStory).format(uiState.username)
} else binding.storyReplyField.hint = null
uiState.profilePicture?.let {
Glide.with(binding.storyAuthorProfilePicture)
.load(it)
@ -79,6 +100,22 @@ class StoriesActivity: BaseThemedWithoutBarActivity() {
}
}
}
binding.storyReplyField.editText?.doAfterTextChanged {
it?.let { text ->
val string = text.toString()
if(string != model.uiState.value.reply) model.replyChanged(string)
}
}
binding.storyReplyField.setEndIconOnClickListener {
binding.storyReplyField.editText?.text?.let { text ->
model.sendReply(text)
}
}
binding.storyErrorCard.setOnClickListener{
model.dismissError()
}
model.count.observe(this) { state ->
// Render state in UI
@ -96,11 +133,7 @@ class StoriesActivity: BaseThemedWithoutBarActivity() {
binding.pause.setOnClickListener {
//Set the button's appearance
it.isSelected = !it.isSelected
if (it.isSelected) {
//Handle selected state change
} else {
//Handle de-select state change
}
model.pause()
}
binding.storyImage.setOnClickListener {

View File

@ -2,16 +2,19 @@ package org.pixeldroid.app.stories
import android.app.Application
import android.os.CountDownTimer
import android.text.Editable
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.pixeldroid.app.R
import org.pixeldroid.app.utils.PixelDroidApplication
import org.pixeldroid.app.utils.api.objects.StoryCarousel
import org.pixeldroid.app.utils.di.PixelfedAPIHolder
@ -27,6 +30,8 @@ data class StoriesUiState(
val durationList: List<Int> = emptyList(),
val paused: Boolean = false,
val errorMessage: String? = null,
val snackBar: String? = null,
val reply: String = ""
)
class StoriesViewModel(
@ -134,6 +139,44 @@ class StoriesViewModel(
currentUiState.copy(paused = !currentUiState.paused)
}
}
fun sendReply(text: Editable) {
viewModelScope.launch {
try {
val api = apiHolder.api ?: apiHolder.setToCurrentUser()
//TODO don't just take the first here, choose from activity input somehow?
val id = carousel?.nodes?.firstOrNull()?.nodes?.getOrNull(uiState.value.currentImage)?.id
id?.let { api.storyComment(it, text.toString()) }
_uiState.update { currentUiState ->
currentUiState.copy(snackBar = "Sent reply")
}
} catch (exception: Exception){
_uiState.update { currentUiState ->
currentUiState.copy(errorMessage = "Something went wrong sending reply")
}
}
}
}
fun replyChanged(text: String) {
_uiState.update { currentUiState ->
currentUiState.copy(reply = text)
}
}
fun dismissError() {
_uiState.update { currentUiState ->
currentUiState.copy(errorMessage = null)
}
}
fun shownSnackbar() {
_uiState.update { currentUiState ->
currentUiState.copy(snackBar = null)
}
}
}
class StoriesViewModelFactory(val application: Application) : ViewModelProvider.Factory {

View File

@ -236,10 +236,16 @@ interface PixelfedAPI {
): StoryCarousel
@POST("/api/v1.1/stories/seen")
suspend fun carouselSeen(
suspend fun storySeen(
@Query("id") id: String //TODO figure out if this is the id of post or of user?
)
@POST("/api/v1.1/stories/comment")
suspend fun storyComment(
@Query("sid") sid: String,
@Query("caption") caption: String
)
@POST("/api/v1.1/stories/self-expire/{id}")
suspend fun deleteCarousel(
@Path("id") storyId: String

View File

@ -6,16 +6,59 @@
android:background="@color/black"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:id="@+id/storyErrorCard"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:visibility="invisible"
app:cardBackgroundColor="?attr/colorSecondaryContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/storyAuthorProfilePicture"
tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="48dp"
android:layout_marginEnd="8dp">
<ImageView
android:id="@+id/storyErrorIcon"
android:layout_width="50dp"
android:layout_height="match_parent"
android:importantForAccessibility="no"
android:src="@drawable/error"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorOnSecondaryContainer" />
<TextView
android:id="@+id/storyErrorText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@id/storyErrorIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/storyErrorIcon"
app:layout_constraintTop_toTopOf="@id/storyErrorIcon"
tools:text="Something is wrong with stories" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<ImageView
android:id="@+id/storyImage"
android:layout_width="match_parent"
android:layout_height="0dp"
android:contentDescription="@string/story_image"
tools:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBarStory"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBarStory"
tools:srcCompat="@tools:sample/backgrounds/scenic[10]" />
<ImageButton
@ -72,8 +115,23 @@
app:layout_constraintBottom_toBottomOf="@+id/storyAuthorProfilePicture"
app:layout_constraintStart_toEndOf="@+id/storyAuthor"
app:layout_constraintTop_toTopOf="@+id/storyAuthorProfilePicture"
app:layout_constraintVertical_bias="0.517"
tools:text="48m" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/storyReplyField"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:hint="Reply to PixelDroid"
app:endIconMode="custom"
app:endIconDrawable="@drawable/ic_send_blue"
app:endIconContentDescription="TODO">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -331,4 +331,5 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="switch_accounts">Switch accounts</string>
<string name="summary_always_show_nsfw">NSFW/CW posts will not be blurred, and will be shown by default.</string>
<string name="story_image">Story image</string>
<string name="replyToStory">Reply to %1$s</string>
</resources>