Add Self view for stories

This commit is contained in:
Matthieu 2023-12-21 14:03:36 +01:00
parent 0290e6f8d5
commit bb3c9afb13
8 changed files with 208 additions and 85 deletions

View File

@ -1,7 +1,6 @@
package org.pixeldroid.app.stories package org.pixeldroid.app.stories
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View.OnClickListener import android.view.View.OnClickListener
@ -26,6 +25,7 @@ import org.pixeldroid.app.databinding.ActivityStoriesBinding
import org.pixeldroid.app.posts.setTextViewFromISO8601 import org.pixeldroid.app.posts.setTextViewFromISO8601
import org.pixeldroid.app.utils.BaseActivity import org.pixeldroid.app.utils.BaseActivity
import org.pixeldroid.app.utils.api.objects.Account import org.pixeldroid.app.utils.api.objects.Account
import org.pixeldroid.app.utils.api.objects.Story
import org.pixeldroid.app.utils.api.objects.StoryCarousel import org.pixeldroid.app.utils.api.objects.StoryCarousel
@ -33,6 +33,7 @@ class StoriesActivity: BaseActivity() {
companion object { companion object {
const val STORY_CAROUSEL = "LaunchStoryCarousel" const val STORY_CAROUSEL = "LaunchStoryCarousel"
const val STORY_CAROUSEL_SELF = "LaunchStoryCarouselSelf"
const val STORY_CAROUSEL_USER_ID = "LaunchStoryUserId" const val STORY_CAROUSEL_USER_ID = "LaunchStoryUserId"
} }
@ -49,14 +50,15 @@ class StoriesActivity: BaseActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val carousel = intent.getSerializableExtra(STORY_CAROUSEL) as StoryCarousel val carousel = intent.getSerializableExtra(STORY_CAROUSEL) as? StoryCarousel
val userId = intent.getStringExtra(STORY_CAROUSEL_USER_ID) val userId = intent.getStringExtra(STORY_CAROUSEL_USER_ID)
val selfCarousel: Array<Story>? = intent.getSerializableExtra(STORY_CAROUSEL_SELF) as? Array<Story>
binding = ActivityStoriesBinding.inflate(layoutInflater) binding = ActivityStoriesBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
val _model: StoriesViewModel by viewModels { val _model: StoriesViewModel by viewModels {
StoriesViewModelFactory(application, carousel, userId) StoriesViewModelFactory(application, carousel, userId, selfCarousel?.asList())
} }
model = _model model = _model

View File

@ -4,21 +4,21 @@ import android.app.Application
import android.os.CountDownTimer import android.os.CountDownTimer
import android.text.Editable import android.text.Editable
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.utils.PixelDroidApplication import org.pixeldroid.app.utils.PixelDroidApplication
import org.pixeldroid.app.utils.api.objects.CarouselUserContainer
import org.pixeldroid.app.utils.api.objects.Story
import org.pixeldroid.app.utils.api.objects.StoryCarousel import org.pixeldroid.app.utils.api.objects.StoryCarousel
import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.di.PixelfedAPIHolder import org.pixeldroid.app.utils.di.PixelfedAPIHolder
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@ -40,20 +40,21 @@ data class StoriesUiState(
class StoriesViewModel( class StoriesViewModel(
application: Application, application: Application,
val carousel: StoryCarousel, val carousel: StoryCarousel?,
userId: String? userId: String?,
val selfCarousel: List<Story>?
) : AndroidViewModel(application) { ) : AndroidViewModel(application) {
@Inject @Inject
lateinit var apiHolder: PixelfedAPIHolder lateinit var apiHolder: PixelfedAPIHolder
@Inject
lateinit var db: AppDatabase
private var currentAccount = carousel.nodes?.firstOrNull { it?.user?.id == userId } private var currentAccount: CarouselUserContainer?
private val _uiState: MutableStateFlow<StoriesUiState> = MutableStateFlow( private val _uiState: MutableStateFlow<StoriesUiState>
newUiStateFromCurrentAccount()
)
val uiState: StateFlow<StoriesUiState> = _uiState val uiState: StateFlow<StoriesUiState>
val count = MutableLiveData<Float>() val count = MutableLiveData<Float>()
@ -61,12 +62,20 @@ class StoriesViewModel(
init { init {
(application as PixelDroidApplication).getAppComponent().inject(this) (application as PixelDroidApplication).getAppComponent().inject(this)
currentAccount =
if (selfCarousel != null) {
db.userDao().getActiveUser()?.let { CarouselUserContainer(it, selfCarousel) }
} else carousel?.nodes?.firstOrNull { it?.user?.id == userId }
_uiState = MutableStateFlow(newUiStateFromCurrentAccount())
uiState = _uiState
startTimerForCurrent() startTimerForCurrent()
} }
private fun setTimer(timerLength: Float) { private fun setTimer(timerLength: Float) {
count.value = timerLength count.value = timerLength
timer = object: CountDownTimer((timerLength * 1000).toLong(), 100){ timer = object: CountDownTimer((timerLength * 1000).toLong(), 50){
override fun onTick(millisUntilFinished: Long) { override fun onTick(millisUntilFinished: Long) {
count.value = millisUntilFinished.toFloat() / 1000 count.value = millisUntilFinished.toFloat() / 1000
@ -98,8 +107,9 @@ class StoriesViewModel(
) )
} }
} else { } else {
if(selfCarousel != null) return
val currentUserId = currentAccount?.user?.id val currentUserId = currentAccount?.user?.id
val currentAccountIndex = carousel.nodes?.indexOfFirst { it?.user?.id == currentUserId } ?: return val currentAccountIndex = carousel?.nodes?.indexOfFirst { it?.user?.id == currentUserId } ?: return
currentAccount = when (index) { currentAccount = when (index) {
uiState.value.imageList.size -> { uiState.value.imageList.size -> {
// Go to next user // Go to next user
@ -209,10 +219,11 @@ class StoriesViewModel(
class StoriesViewModelFactory( class StoriesViewModelFactory(
val application: Application, val application: Application,
val carousel: StoryCarousel, val carousel: StoryCarousel?,
val userId: String? val userId: String?,
val selfCarousel: List<Story>?
) : ViewModelProvider.Factory { ) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
return modelClass.getConstructor(Application::class.java, StoryCarousel::class.java, String::class.java).newInstance(application, carousel, userId) return modelClass.getConstructor(Application::class.java, StoryCarousel::class.java, String::class.java, List::class.java).newInstance(application, carousel, userId, selfCarousel)
} }
} }

View File

@ -2,26 +2,33 @@ package org.pixeldroid.app.stories
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.RenderEffect
import android.graphics.Shader
import android.os.Build
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleCoroutineScope
import androidx.paging.LoadState
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.StoryCarouselAddStoryBinding
import org.pixeldroid.app.databinding.StoryCarouselBinding import org.pixeldroid.app.databinding.StoryCarouselBinding
import org.pixeldroid.app.databinding.StoryCarouselItemBinding import org.pixeldroid.app.databinding.StoryCarouselItemBinding
import org.pixeldroid.app.databinding.StoryCarouselSelfBinding
import org.pixeldroid.app.postCreation.camera.CameraActivity import org.pixeldroid.app.postCreation.camera.CameraActivity
import org.pixeldroid.app.postCreation.camera.CameraFragment import org.pixeldroid.app.postCreation.camera.CameraFragment
import org.pixeldroid.app.utils.api.objects.CarouselUserContainer import org.pixeldroid.app.utils.api.objects.CarouselUserContainer
import org.pixeldroid.app.utils.api.objects.Story
import org.pixeldroid.app.utils.api.objects.StoryCarousel import org.pixeldroid.app.utils.api.objects.StoryCarousel
import org.pixeldroid.app.utils.di.PixelfedAPIHolder import org.pixeldroid.app.utils.di.PixelfedAPIHolder
/** /**
* Adapter to the show the a [RecyclerView] item for a [LoadState] * Adapter that has either 1 or 0 items, to show stories widget or not
*/ */
class StoriesAdapter(val lifecycleScope: LifecycleCoroutineScope, val apiHolder: PixelfedAPIHolder) : RecyclerView.Adapter<StoryCarouselViewHolder>() { class StoriesAdapter(val lifecycleScope: LifecycleCoroutineScope, val apiHolder: PixelfedAPIHolder) : RecyclerView.Adapter<StoryCarouselViewHolder>() {
var carousel: StoryCarousel? = null var carousel: StoryCarousel? = null
@ -74,7 +81,8 @@ class StoriesAdapter(val lifecycleScope: LifecycleCoroutineScope, val apiHolder:
val api = apiHolder.api ?: apiHolder.setToCurrentUser() val api = apiHolder.api ?: apiHolder.setToCurrentUser()
val carousel = api.carousel() val carousel = api.carousel()
if (carousel.nodes?.isEmpty() != true) { // If there are stories from someone else or our stories to show, show them
if (carousel.nodes?.isEmpty() == false || carousel.self?.nodes?.isEmpty() == false) {
// Pass carousel to adapter // Pass carousel to adapter
gotStories(carousel) gotStories(carousel)
} else { } else {
@ -113,8 +121,12 @@ class StoriesListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var storyCarousel: StoryCarousel? = null private var storyCarousel: StoryCarousel? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if(viewType == R.layout.story_carousel_add_story){ return if(viewType == R.layout.story_carousel_self){
val v = StoryCarouselAddStoryBinding.inflate(LayoutInflater.from(parent.context), parent, false) val v = StoryCarouselSelfBinding.inflate(LayoutInflater.from(parent.context), parent, false)
v.myStory.visibility =
if (storyCarousel?.self?.nodes?.isEmpty() == false) View.VISIBLE
else View.GONE
AddViewHolder(v) AddViewHolder(v)
} }
else { else {
@ -124,7 +136,7 @@ class StoriesListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return if(position == 0) R.layout.story_carousel_add_story return if(position == 0) R.layout.story_carousel_self
else R.layout.story_carousel_item else R.layout.story_carousel_item
} }
@ -133,21 +145,15 @@ class StoriesListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val carouselPosition = position - 1 val carouselPosition = position - 1
storyCarousel?.nodes?.get(carouselPosition)?.let { (holder as ViewHolder).bindItem(it) } storyCarousel?.nodes?.get(carouselPosition)?.let { (holder as ViewHolder).bindItem(it) }
holder.itemView.setOnClickListener { holder.itemView.setOnClickListener {
storyCarousel?.let { carousel ->
storyCarousel?.nodes?.get(carouselPosition)?.user?.id?.let { userId -> storyCarousel?.nodes?.get(carouselPosition)?.user?.id?.let { userId ->
val intent = Intent(holder.itemView.context, StoriesActivity::class.java) val intent = Intent(holder.itemView.context, StoriesActivity::class.java)
intent.putExtra(StoriesActivity.STORY_CAROUSEL, carousel) intent.putExtra(StoriesActivity.STORY_CAROUSEL, storyCarousel)
intent.putExtra(StoriesActivity.STORY_CAROUSEL_USER_ID, userId) intent.putExtra(StoriesActivity.STORY_CAROUSEL_USER_ID, userId)
holder.itemView.context.startActivity(intent) holder.itemView.context.startActivity(intent)
} }
} }
}
} else { } else {
holder.itemView.setOnClickListener { storyCarousel?.self?.nodes?.let { (holder as? AddViewHolder)?.bindItem(it.filterNotNull()) }
val intent = Intent(holder.itemView.context, CameraActivity::class.java)
intent.putExtra(CameraFragment.CAMERA_ACTIVITY_STORY, true)
holder.itemView.context.startActivity(intent)
}
} }
} }
@ -162,7 +168,35 @@ class StoriesListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
notifyDataSetChanged() notifyDataSetChanged()
} }
class AddViewHolder(itemBinding: StoryCarouselAddStoryBinding) : RecyclerView.ViewHolder(itemBinding.root) class AddViewHolder(private val itemBinding: StoryCarouselSelfBinding) : RecyclerView.ViewHolder(itemBinding.root) {
fun bindItem(nodes: List<Story>) {
itemBinding.addStory.setOnClickListener {
val intent = Intent(itemView.context, CameraActivity::class.java)
intent.putExtra(CameraFragment.CAMERA_ACTIVITY_STORY, true)
itemView.context.startActivity(intent)
}
itemBinding.myStory.setOnClickListener {
val intent = Intent(itemView.context, StoriesActivity::class.java)
intent.putExtra(StoriesActivity.STORY_CAROUSEL_SELF, nodes.toTypedArray())
itemView.context.startActivity(intent)
}
// Only show image on new Android versions, because the transformations need it and the
// text is not legible without the transformations
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Glide.with(itemBinding.root).load(nodes.firstOrNull()?.src).into(itemBinding.carouselImageView)
val value = 70 * 255 / 100
val darkFilterRenderEffect = PorterDuffColorFilter(Color.argb(value, 0, 0, 0), PorterDuff.Mode.SRC_ATOP)
val blurRenderEffect =
RenderEffect.createBlurEffect(
4f, 4f, Shader.TileMode.MIRROR
)
val combinedEffect = RenderEffect.createColorFilterEffect(darkFilterRenderEffect, blurRenderEffect)
itemBinding.carouselImageView.setRenderEffect(combinedEffect)
}
}
}
class ViewHolder(private val itemBinding: StoryCarouselItemBinding) : class ViewHolder(private val itemBinding: StoryCarouselItemBinding) :
RecyclerView.ViewHolder(itemBinding.root) { RecyclerView.ViewHolder(itemBinding.root) {

View File

@ -1,5 +1,6 @@
package org.pixeldroid.app.utils.api.objects package org.pixeldroid.app.utils.api.objects
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
import java.io.Serializable import java.io.Serializable
import java.time.Instant import java.time.Instant
@ -23,7 +24,13 @@ data class CarouselUser(
data class CarouselUserContainer( data class CarouselUserContainer(
val user: CarouselUser?, val user: CarouselUser?,
val nodes: List<Story?>?, val nodes: List<Story?>?,
): Serializable ): Serializable {
constructor(user: UserDatabaseEntity, nodes: List<Story?>?) : this(
CarouselUser(user.user_id, user.username, null, user.avatar_static,
local = true,
is_author = true
), nodes)
}
data class Story( data class Story(
val id: String?, val id: String?,

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM12,14.5v-9l6,4.5 -6,4.5z"/>
</vector>

View File

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.carousel.MaskableFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/carousel_add_story"
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
tools:context="androidx.recyclerview.widget.RecyclerView"
android:layout_marginEnd="4dp"
android:background="?attr/colorSecondaryContainer"
android:foreground="?attr/selectableItemBackground"
app:shapeAppearance="?attr/shapeAppearanceCornerExtraLarge">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/carousel_image_view"
android:layout_width="match_parent"
android:layout_height="40dp"
android:contentDescription="@string/story_image"
android:scaleType="fitCenter"
android:src="@drawable/collection_add"
app:layout_constraintBottom_toTopOf="@id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorOnSecondaryContainer" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_story"
android:textColor="?attr/colorOnSecondaryContainer"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/carousel_image_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.carousel.MaskableFrameLayout>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.carousel.MaskableFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/carousel_add_story"
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:background="?attr/colorStoryImage"
app:shapeAppearance="?attr/shapeAppearanceCornerExtraLarge"
tools:context="androidx.recyclerview.widget.RecyclerView">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/carousel_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/story_image"
android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/add_story"
android:foreground="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/my_story"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/carousel_add_story_icon"
android:layout_width="match_parent"
android:layout_height="40dp"
android:contentDescription="@string/add_story"
android:scaleType="fitCenter"
android:src="@drawable/collection_add"
app:layout_constraintBottom_toTopOf="@id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorOnStoryImage" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_story"
android:textColor="?attr/colorOnStoryImage"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/carousel_add_story_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/my_story"
android:foreground="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/add_story"
tools:visibility="visible">
<ImageView
android:id="@+id/my_story_icon"
android:layout_width="match_parent"
android:layout_height="40dp"
android:contentDescription="@string/my_story"
android:scaleType="fitCenter"
android:src="@drawable/story_play"
app:layout_constraintBottom_toTopOf="@id/my_story_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorOnStoryImage" />
<TextView
android:id="@+id/my_story_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_story"
android:textColor="?attr/colorOnStoryImage"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/my_story_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.carousel.MaskableFrameLayout>

View File

@ -338,4 +338,12 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="add_story">Add Story</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_could_not_see">Error: could not mark story as seen</string>
<string name="story_pause">Start or pause the stories</string> <string name="story_pause">Start or pause the stories</string>
<string name="my_story">My story</string>
<!-- Type of new publication that is being created (as opposed to a traditional post, if this is chosen it would be a story) -->
<string name="type_story">Story</string>
<!-- Type of new publication that is being created (as opposed to a story, if this is chosen it would be a traditional post) -->
<string name="type_post">Post</string>
<string name="continue_post_creation">Continue</string>
<string name="extraneous_pictures_stories">Pictures after the first were removed but can be restored by switching back to creating a Post</string>
<string name="story_duration">Story Duration</string>
</resources> </resources>