More work on stories
This commit is contained in:
parent
888c6328d9
commit
f60889ea14
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue