implement story creation

This commit is contained in:
Matthieu 2023-06-19 23:06:09 +02:00
parent ae54b83ec7
commit db3da57b7b
17 changed files with 160 additions and 8443 deletions

View File

@ -1,6 +1,7 @@
package org.pixeldroid.app.postCreation
import android.os.*
import androidx.core.view.WindowCompat
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import org.pixeldroid.app.R

View File

@ -33,6 +33,7 @@ import kotlinx.coroutines.launch
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.FragmentPostCreationBinding
import org.pixeldroid.app.postCreation.camera.CameraActivity
import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.postCreation.carousel.CarouselItem
import org.pixeldroid.app.utils.BaseFragment
import org.pixeldroid.app.utils.db.entities.InstanceDatabaseEntity
@ -83,11 +84,16 @@ class PostCreationFragment : BaseFragment() {
requireActivity().intent.clipData!!,
instance,
requireActivity().intent.getStringExtra(PostCreationActivity.PICTURE_DESCRIPTION),
requireActivity().intent.getBooleanExtra(PostCreationActivity.POST_NSFW, false)
requireActivity().intent.getBooleanExtra(PostCreationActivity.POST_NSFW, false),
requireActivity().intent.getBooleanExtra(CameraFragment.CAMERA_ACTIVITY_STORY, false),
)
}
model = _model
if(model.storyCreation){
binding.carousel.showCaption = false
}
model.getPhotoData().observe(viewLifecycleOwner) { newPhotoData ->
// update UI
binding.carousel.addData(

View File

@ -22,6 +22,7 @@ import androidx.preference.PreferenceManager
import com.jarsilio.android.scrambler.exceptions.UnsupportedFileFormatException
import com.jarsilio.android.scrambler.stripMetadata
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.flow.MutableStateFlow
@ -107,7 +108,8 @@ class PostCreationViewModel(
clipdata: ClipData? = null,
val instance: InstanceDatabaseEntity? = null,
existingDescription: String? = null,
existingNSFW: Boolean = false
existingNSFW: Boolean = false,
val storyCreation: Boolean = false,
) : AndroidViewModel(application) {
private val photoData: MutableLiveData<MutableList<PhotoData>> by lazy {
MutableLiveData<MutableList<PhotoData>>().also {
@ -444,7 +446,11 @@ class PostCreationViewModel(
apiHolder.setToCurrentUser(it)
} ?: apiHolder.api ?: apiHolder.setToCurrentUser()
val inter = api.mediaUpload(description, requestBody.parts[0])
val inter: Observable<Attachment> =
//TODO specify story duration
//TODO validate that image is correct (?) aspect ratio
if (storyCreation) api.storyUpload(requestBody.parts[0])
else api.mediaUpload(description, requestBody.parts[0])
apiHolder.api = null
postSub = inter
@ -453,7 +459,11 @@ class PostCreationViewModel(
.subscribe(
{ attachment: Attachment ->
data.progress = 0
data.uploadId = attachment.id!!
data.uploadId = if(storyCreation){
attachment.media_id!!
} else {
attachment.id!!
}
},
{ e: Throwable ->
_uiState.update { currentUiState ->
@ -509,11 +519,19 @@ class PostCreationViewModel(
apiHolder.setToCurrentUser(it)
} ?: apiHolder.api ?: apiHolder.setToCurrentUser()
api.postStatus(
statusText = description,
media_ids = getPhotoData().value!!.mapNotNull { it.uploadId }.toList(),
sensitive = nsfw
)
if(storyCreation){
api.storyPublish(
media_id = getPhotoData().value!!.firstNotNullOf { it.uploadId },
can_react = "1", can_reply = "1",
duration = 10
)
} else{
api.postStatus(
statusText = description,
media_ids = getPhotoData().value!!.mapNotNull { it.uploadId }.toList(),
sensitive = nsfw
)
}
Toast.makeText(getApplication(), getApplication<PixelDroidApplication>().getString(R.string.upload_post_success),
Toast.LENGTH_SHORT).show()
val intent = Intent(getApplication(), MainActivity::class.java)
@ -555,8 +573,8 @@ class PostCreationViewModel(
}
}
class PostCreationViewModelFactory(val application: Application, val clipdata: ClipData, val instance: InstanceDatabaseEntity, val existingDescription: String?, val existingNSFW: Boolean) : ViewModelProvider.Factory {
class PostCreationViewModelFactory(val application: Application, val clipdata: ClipData, val instance: InstanceDatabaseEntity, val existingDescription: String?, val existingNSFW: Boolean, val storyCreation: Boolean) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return modelClass.getConstructor(Application::class.java, ClipData::class.java, InstanceDatabaseEntity::class.java, String::class.java, Boolean::class.java).newInstance(application, clipdata, instance, existingDescription, existingNSFW)
return modelClass.getConstructor(Application::class.java, ClipData::class.java, InstanceDatabaseEntity::class.java, String::class.java, Boolean::class.java, Boolean::class.java).newInstance(application, clipdata, instance, existingDescription, existingNSFW, storyCreation)
}
}

View File

@ -20,6 +20,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.launch
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.FragmentPostSubmissionBinding
import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.utils.BaseFragment
import org.pixeldroid.app.utils.db.entities.InstanceDatabaseEntity
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
@ -68,7 +69,8 @@ class PostSubmissionFragment : BaseFragment() {
requireActivity().intent.clipData!!,
instance,
requireActivity().intent.getStringExtra(PostCreationActivity.PICTURE_DESCRIPTION),
requireActivity().intent.getBooleanExtra(PostCreationActivity.POST_NSFW, false)
requireActivity().intent.getBooleanExtra(PostCreationActivity.POST_NSFW, false),
requireActivity().intent.getBooleanExtra(CameraFragment.CAMERA_ACTIVITY_STORY, false)
)
}
model = _model
@ -77,6 +79,14 @@ class PostSubmissionFragment : BaseFragment() {
binding.nsfwSwitch.isChecked = model.uiState.value.nsfw
binding.newPostDescriptionInputField.setText(model.uiState.value.newPostDescriptionText)
if(model.storyCreation){
binding.nsfwSwitch.visibility = View.GONE
binding.postTextInputLayout.visibility = View.GONE
binding.privateTitle.visibility = View.GONE
binding.postPreview.visibility = View.GONE
//TODO show story specific stuff here
}
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
model.uiState.collect { uiState ->

View File

@ -5,6 +5,8 @@ import android.os.Bundle
import android.view.MenuItem
import org.pixeldroid.app.MainActivity
import org.pixeldroid.app.R
import org.pixeldroid.app.postCreation.camera.CameraFragment.Companion.CAMERA_ACTIVITY
import org.pixeldroid.app.postCreation.camera.CameraFragment.Companion.CAMERA_ACTIVITY_STORY
import org.pixeldroid.app.utils.BaseThemedWithBarActivity
@ -13,12 +15,17 @@ class CameraActivity : BaseThemedWithBarActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setTitle(R.string.add_photo)
val cameraFragment = CameraFragment()
val story: Boolean = intent.getBooleanExtra(CAMERA_ACTIVITY_STORY, false)
if(story) supportActionBar?.setTitle(R.string.add_story)
else supportActionBar?.setTitle(R.string.add_photo)
val arguments = Bundle()
arguments.putBoolean("CameraActivity", true)
arguments.putBoolean(CAMERA_ACTIVITY, true)
arguments.putBoolean(CAMERA_ACTIVITY_STORY, story)
cameraFragment.arguments = arguments
supportFragmentManager.beginTransaction()

View File

@ -70,6 +70,7 @@ class CameraFragment : BaseFragment() {
private var camera: Camera? = null
private var inActivity by Delegates.notNull<Boolean>()
private var addToStory by Delegates.notNull<Boolean>()
private var filePermissionDialogLaunched: Boolean = false
@ -89,7 +90,8 @@ class CameraFragment : BaseFragment() {
savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
inActivity = arguments?.getBoolean("CameraActivity") ?: false
inActivity = arguments?.getBoolean(CAMERA_ACTIVITY) ?: false
addToStory = arguments?.getBoolean(CAMERA_ACTIVITY_STORY) ?: false
binding = FragmentCameraBinding.inflate(layoutInflater)
@ -464,15 +466,20 @@ class CameraFragment : BaseFragment() {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
if(inActivity){
if(inActivity && !addToStory){
requireActivity().setResult(Activity.RESULT_OK, intent)
requireActivity().finish()
} else {
if(addToStory){
intent.putExtra(CAMERA_ACTIVITY_STORY, addToStory)
}
startActivity(intent)
}
}
companion object {
const val CAMERA_ACTIVITY = "CameraActivity"
const val CAMERA_ACTIVITY_STORY = "CameraActivityStory"
private const val TAG = "CameraFragment"
private const val RATIO_4_3_VALUE = 4.0 / 3.0

View File

@ -40,7 +40,6 @@ class ImageCarousel(
)
private lateinit var recyclerView: RecyclerView
private lateinit var tvCaption: TextView
private var snapHelper: SnapHelper = PagerSnapHelper()
var indicator: CircleIndicator2? = null
@ -103,11 +102,12 @@ class ImageCarousel(
* ****************************************************************
*/
//FIXME this is modified a bunch of times all over the place, so it can't be set to false and stay there
var showCaption = false
set(value) {
field = value
tvCaption.visibility = if (showCaption) View.VISIBLE else View.GONE
binding.tvCaption.visibility = if (showCaption) View.VISIBLE else View.GONE
}
@Dimension(unit = Dimension.PX)
@ -115,7 +115,7 @@ class ImageCarousel(
set(value) {
field = value
tvCaption.setTextSize(TypedValue.COMPLEX_UNIT_PX, captionTextSize.toFloat())
binding.tvCaption.setTextSize(TypedValue.COMPLEX_UNIT_PX, captionTextSize.toFloat())
}
var showIndicator = false
@ -245,14 +245,14 @@ class ImageCarousel(
showNavigationButtons = showNavigationButtons
binding.editMediaDescriptionLayout.visibility = if(editingMediaDescription) VISIBLE else INVISIBLE
tvCaption.visibility = if(editingMediaDescription) INVISIBLE else VISIBLE
showCaption = !editingMediaDescription
} else {
recyclerView.layoutManager = GridLayoutManager(context, 3)
binding.btnNext.visibility = GONE
binding.btnPrevious.visibility = GONE
binding.editMediaDescriptionLayout.visibility = INVISIBLE
tvCaption.visibility = INVISIBLE
showCaption = false
}
showIndicator = value
@ -279,7 +279,7 @@ class ImageCarousel(
updateDescriptionCallback?.invoke(currentPosition, description)
}
binding.editMediaDescriptionLayout.visibility = if(value) VISIBLE else INVISIBLE
tvCaption.visibility = if(value) INVISIBLE else VISIBLE
showCaption = !value
}
@ -289,10 +289,10 @@ class ImageCarousel(
set(value) {
if(!value.isNullOrEmpty()) {
field = value
tvCaption.text = value
binding.tvCaption.text = value
} else {
field = null
tvCaption.text = context.getText(R.string.no_media_description)
binding.tvCaption.text = context.getText(R.string.no_media_description)
}
}
@ -317,12 +317,11 @@ class ImageCarousel(
binding = ImageCarouselBinding.inflate(LayoutInflater.from(context),this, true)
recyclerView = binding.recyclerView
tvCaption = binding.tvCaption
recyclerView.setHasFixedSize(true)
// For marquee effect
tvCaption.isSelected = true
binding.tvCaption.isSelected = true
}
@ -441,7 +440,7 @@ class ImageCarousel(
caption.apply {
if(layoutCarousel){
binding.editMediaDescriptionLayout.visibility = INVISIBLE
tvCaption.visibility = VISIBLE
showCaption = true
}
currentDescription = this
}
@ -472,7 +471,7 @@ class ImageCarousel(
}
})
tvCaption.setOnClickListener {
binding.tvCaption.setOnClickListener {
editingMediaDescription = true
}

View File

@ -7,6 +7,7 @@ import android.view.MotionEvent
import android.view.View.OnClickListener
import android.view.View.OnTouchListener
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.Lifecycle
@ -41,6 +42,9 @@ class StoriesActivity: BaseThemedWithoutBarActivity() {
private lateinit var model: StoriesViewModel
override fun onCreate(savedInstanceState: Bundle?) {
//force night mode always
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
super.onCreate(savedInstanceState)
val carousel = intent.getSerializableExtra(STORY_CAROUSEL) as StoryCarousel
@ -213,8 +217,6 @@ class StoriesActivity: BaseThemedWithoutBarActivity() {
binding.viewLeft.setOnTouchListener(onTouchListener)
binding.viewRight.setOnTouchListener(onTouchListener)
//TODO implement hold to pause
binding.viewRight.setOnClickListener {
model.goToNext()
}

View File

@ -4,11 +4,14 @@ import android.app.Application
import android.os.CountDownTimer
import android.text.Editable
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
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.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
@ -119,7 +122,20 @@ class StoriesViewModel(
startTimerForCurrent()
}
fun goToNext() = goTo(uiState.value.currentImage + 1)
fun goToNext() {
viewModelScope.launch {
try {
val api = apiHolder.api ?: apiHolder.setToCurrentUser()
currentStoryId()?.let { api.storySeen(it) }
} catch (exception: Exception){
_uiState.update { currentUiState ->
currentUiState.copy(errorMessage = R.string.story_could_not_see)
}
}
}
goTo(uiState.value.currentImage + 1)
}
fun goToPrevious() = goTo(uiState.value.currentImage - 1)
@ -148,8 +164,7 @@ class StoriesViewModel(
viewModelScope.launch {
try {
val api = apiHolder.api ?: apiHolder.setToCurrentUser()
val id = currentAccount?.nodes?.getOrNull(uiState.value.currentImage)?.id
id?.let { api.storyComment(it, text.toString()) }
currentStoryId()?.let { api.storyComment(it, text.toString()) }
_uiState.update { currentUiState ->
currentUiState.copy(snackBar = R.string.sent_reply_story)
@ -163,6 +178,8 @@ class StoriesViewModel(
}
}
private fun currentStoryId(): String? = currentAccount?.nodes?.getOrNull(uiState.value.currentImage)?.id
fun replyChanged(text: String) {
_uiState.update { currentUiState ->
currentUiState.copy(reply = text)

View File

@ -13,6 +13,8 @@ import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.StoryCarouselAddStoryBinding
import org.pixeldroid.app.databinding.StoryCarouselBinding
import org.pixeldroid.app.databinding.StoryCarouselItemBinding
import org.pixeldroid.app.postCreation.camera.CameraActivity
import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.postCreation.carousel.dpToPx
import org.pixeldroid.app.utils.api.objects.CarouselUserContainer
import org.pixeldroid.app.utils.api.objects.StoryCarousel
@ -103,7 +105,9 @@ class StoriesListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
}
} else {
holder.itemView.setOnClickListener {
//TODO support for adding a story
val intent = Intent(holder.itemView.context, CameraActivity::class.java)
intent.putExtra(CameraFragment.CAMERA_ACTIVITY_STORY, true)
holder.itemView.context.startActivity(intent)
}
}
}

View File

@ -236,12 +236,11 @@ interface PixelfedAPI {
)
@GET("/api/v1.1/stories/carousel")
suspend fun carousel(
): StoryCarousel
suspend fun carousel(): StoryCarousel
@POST("/api/v1.1/stories/seen")
suspend fun storySeen(
@Query("id") id: String //TODO figure out if this is the id of post or of user?
@Query("id") id: String
)
@POST("/api/v1.1/stories/comment")
@ -250,6 +249,24 @@ interface PixelfedAPI {
@Query("caption") caption: String
)
@Multipart
@POST("/api/v1.1/stories/add")
fun storyUpload(
@Part file: MultipartBody.Part,
@Part duration: MultipartBody.Part? = null,
): Observable<Attachment>
@POST("/api/v1.1/stories/publish")
suspend fun storyPublish(
@Query("media_id") media_id: String,
//From 0 to 30
//TODO figure out what this duration means
@Query("duration") duration: Int = 10,
//FIXME this should be able to take a boolean or at least "true"/"false" but only "0"/"1" works. Same issue as sensitive boolean in postStatus
@Query("can_reply") can_reply: String,
@Query("can_react") can_react: String,
)
@POST("/api/v1.1/stories/self-expire/{id}")
suspend fun deleteCarousel(
@Path("id") storyId: String

View File

@ -18,6 +18,12 @@ data class Attachment(
//Deprecated attributes
val text_url: String? = null, //URL
//Pixelfed's Story upload response... TODO make the server return a regular Attachment?
val msg: String?,
val media_id: String?,
val media_url: String?,
val media_type: String?,
) : Serializable {
enum class AttachmentType: Serializable {
unknown, image, gifv, video, audio

View File

@ -3,8 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="@color/black"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/black">
<com.google.android.material.card.MaterialCardView
android:id="@+id/storyErrorCard"
@ -22,8 +22,8 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="48dp"
android:layout_marginEnd="8dp">
android:layout_marginEnd="8dp"
android:minHeight="48dp">
<ImageView
android:id="@+id/storyErrorIcon"
@ -65,39 +65,39 @@
<ImageButton
android:id="@+id/pause"
android:layout_marginEnd="12dp"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_margin="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/play_video"
android:contentDescription="@string/story_pause"
android:src="@drawable/play_pause"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthorProfilePicture"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/storyAuthorProfilePicture"
app:layout_constraintTop_toTopOf="@+id/carouselProgress"
tools:visibility="visible" />
<ProgressBar
android:id="@+id/progressBarStory"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:progress="0"
tools:progress="56"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
tools:progress="56" />
<ImageView
android:id="@+id/storyAuthorProfilePicture"
android:layout_margin="12dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="12dp"
android:contentDescription="@string/profile_picture"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBarStory"
tools:srcCompat="@tools:sample/avatars"
android:contentDescription="@string/profile_picture" />
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/storyAuthor"
@ -105,7 +105,6 @@
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthorProfilePicture"
app:layout_constraintStart_toEndOf="@+id/storyAuthorProfilePicture"
app:layout_constraintTop_toTopOf="@+id/storyAuthorProfilePicture"
tools:text="username" />
@ -115,20 +114,20 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthorProfilePicture"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthor"
app:layout_constraintStart_toEndOf="@+id/storyAuthor"
app:layout_constraintTop_toTopOf="@+id/storyAuthorProfilePicture"
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:endIconContentDescription="TODO"
app:endIconDrawable="@drawable/ic_send_blue"
app:endIconContentDescription="TODO">
app:endIconMode="custom"
app:layout_constraintBottom_toBottomOf="parent"
tools:hint="Reply to PixelDroid">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
@ -141,18 +140,18 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
app:layout_constraintBottom_toBottomOf="@+id/pause"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthor"
app:layout_constraintEnd_toStartOf="@+id/pause"
app:layout_constraintTop_toTopOf="@+id/pause"
app:layout_constraintTop_toTopOf="@+id/storyAge"
tools:text="2/3" />
<View
android:id="@+id/viewRight"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/storyReplyField"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/viewMiddle"
app:layout_constraintBottom_toTopOf="@id/storyReplyField"
app:layout_constraintTop_toBottomOf="@+id/storyAuthorProfilePicture" />
@ -160,9 +159,9 @@
android:id="@+id/viewMiddle"
android:layout_width="80dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/storyReplyField"
app:layout_constraintEnd_toStartOf="@id/viewRight"
app:layout_constraintStart_toEndOf="@id/viewLeft"
app:layout_constraintBottom_toTopOf="@id/storyReplyField"
app:layout_constraintTop_toBottomOf="@+id/storyAuthorProfilePicture" />
@ -170,11 +169,10 @@
android:id="@+id/viewLeft"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/viewMiddle"
app:layout_constraintBottom_toTopOf="@id/storyReplyField"
app:layout_constraintEnd_toStartOf="@id/viewMiddle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/storyAuthorProfilePicture" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -11,7 +11,7 @@
android:id="@+id/carousel"
android:layout_width="match_parent"
android:layout_height="0dp"
app:showCaption="true"
app:showCaption="false"
app:layout_constraintBottom_toTopOf="@+id/buttonConstraints"
app:layout_constraintTop_toTopOf="parent"/>

View File

@ -337,4 +337,6 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="error_fetch_story">Something went wrong fetching the carousel</string>
<string name="sent_reply_story">Sent reply</string>
<string name="add_story">Add Story</string>
<string name="story_could_not_see">Error: could not mark story as seen</string>
<string name="story_pause">Start or pause the stories</string>
</resources>

View File

@ -23,6 +23,7 @@
<style name="AppTheme.PopupOverlay" parent="Theme.Material3.Light" />
<style name="AppTheme.ActionBar.Transparent" parent="Theme.Material3.Dark">
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">always</item>
<item name="colorPrimary">@android:color/transparent</item>
<item name="colorPrimaryDark">@android:color/transparent</item>
<item name="colorPrimaryVariant">@android:color/transparent</item>

File diff suppressed because it is too large Load Diff