WIP
This commit is contained in:
parent
727007d94f
commit
571b893fcd
@ -1,9 +1,8 @@
|
|||||||
package com.isolaatti.images.common.data.remote
|
package com.isolaatti.images.common.data.remote
|
||||||
|
|
||||||
|
|
||||||
data class ImageDto(
|
data class ImageDto(
|
||||||
val id: String,
|
val id: String,
|
||||||
val userId: Int,
|
val userId: Int,
|
||||||
val squadId: String?,
|
val squadId: String?
|
||||||
val username: String,
|
|
||||||
val idOnFirebase: String
|
|
||||||
)
|
)
|
||||||
@ -34,7 +34,7 @@ class ImagesRepositoryImpl @Inject constructor(private val imagesApi: ImagesApi,
|
|||||||
val response = imagesApi.getImagesOfUser(userId, lastId).awaitResponse()
|
val response = imagesApi.getImagesOfUser(userId, lastId).awaitResponse()
|
||||||
if(response.isSuccessful) {
|
if(response.isSuccessful) {
|
||||||
val imagesDto = response.body()
|
val imagesDto = response.body()
|
||||||
val images = imagesDto?.data?.map { Image.fromDto(it) }
|
val images = imagesDto?.data?.map { Image(it.id) }
|
||||||
|
|
||||||
emit(Resource.Success(images))
|
emit(Resource.Success(images))
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ class ImagesRepositoryImpl @Inject constructor(private val imagesApi: ImagesApi,
|
|||||||
emit(Resource.Error(Resource.Error.ErrorType.ServerError))
|
emit(Resource.Error(Resource.Error.ErrorType.ServerError))
|
||||||
return@flow
|
return@flow
|
||||||
}
|
}
|
||||||
val image = Image.fromDto(imageDto)
|
val image = Image(imageDto.id)
|
||||||
emit(Resource.Success(image))
|
emit(Resource.Success(image))
|
||||||
} else {
|
} else {
|
||||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.isolaatti.images.common.domain.entity
|
package com.isolaatti.images.common.domain.entity
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
import com.isolaatti.common.Deletable
|
import com.isolaatti.common.Deletable
|
||||||
import com.isolaatti.images.common.data.remote.ImageDto
|
import com.isolaatti.images.common.data.remote.ImageDto
|
||||||
import com.isolaatti.markdown.Generators
|
import com.isolaatti.markdown.Generators
|
||||||
@ -7,19 +9,16 @@ import com.isolaatti.utils.UrlGen
|
|||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class Image(
|
data class Image(
|
||||||
val id: String,
|
val id: String
|
||||||
val userId: Int,
|
): Deletable(), Parcelable {
|
||||||
val username: String
|
|
||||||
): Deletable(), Serializable {
|
|
||||||
val imageUrl: String get() = UrlGen.imageUrl(id)
|
val imageUrl: String get() = UrlGen.imageUrl(id)
|
||||||
val smallImageUrl : String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_SMALL)
|
val smallImageUrl : String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_SMALL)
|
||||||
val reducedImageUrl: String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_REDUCED)
|
val reducedImageUrl: String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_REDUCED)
|
||||||
|
|
||||||
val markdown: String get() = Generators.generateImage(imageUrl)
|
val markdown: String get() = Generators.generateImage(imageUrl)
|
||||||
|
|
||||||
companion object {
|
constructor(parcel: Parcel) : this(parcel.readString()!!)
|
||||||
fun fromDto(imageDto: ImageDto) = Image(imageDto.id, imageDto.userId, imageDto.username)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@ -28,16 +27,30 @@ data class Image(
|
|||||||
other as Image
|
other as Image
|
||||||
|
|
||||||
if (id != other.id) return false
|
if (id != other.id) return false
|
||||||
if (userId != other.userId) return false
|
|
||||||
if (username != other.username) return false
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = id.hashCode()
|
var result = id.hashCode()
|
||||||
result = 31 * result + userId
|
|
||||||
result = 31 * result + username.hashCode()
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeString(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<Image> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): Image {
|
||||||
|
return Image(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<Image?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ class PictureViewerImageWrapperFragment : Fragment() {
|
|||||||
fun getInstance(image: Image): PictureViewerImageWrapperFragment {
|
fun getInstance(image: Image): PictureViewerImageWrapperFragment {
|
||||||
val fragment = PictureViewerImageWrapperFragment()
|
val fragment = PictureViewerImageWrapperFragment()
|
||||||
fragment.arguments = Bundle().apply {
|
fragment.arguments = Bundle().apply {
|
||||||
putSerializable(ARGUMENT_IMAGE, image)
|
putParcelable(ARGUMENT_IMAGE, image)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fragment
|
return fragment
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class PictureViewerMainFragment : Fragment() {
|
|||||||
private val onPageChangeCallback = object: ViewPager2.OnPageChangeCallback() {
|
private val onPageChangeCallback = object: ViewPager2.OnPageChangeCallback() {
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
super.onPageSelected(position)
|
super.onPageSelected(position)
|
||||||
binding.imageAuthor.text = images[position].username
|
//binding.imageAuthor.text = images[position].username
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class PictureViewerMainFragment : Fragment() {
|
|||||||
binding.viewpager.adapter = adapter
|
binding.viewpager.adapter = adapter
|
||||||
binding.viewpager.setCurrentItem(position, false)
|
binding.viewpager.setCurrentItem(position, false)
|
||||||
binding.viewpager.registerOnPageChangeCallback(onPageChangeCallback)
|
binding.viewpager.registerOnPageChangeCallback(onPageChangeCallback)
|
||||||
binding.imageAuthor.text = images[position].username
|
//binding.imageAuthor.text = images[position].username
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
package com.isolaatti.posting.posts.data.remote
|
package com.isolaatti.posting.posts.data.remote
|
||||||
|
|
||||||
import android.os.Parcel
|
|
||||||
import android.os.Parcelable
|
|
||||||
import com.isolaatti.audio.common.data.AudioDto
|
import com.isolaatti.audio.common.data.AudioDto
|
||||||
import java.io.Serializable
|
import com.isolaatti.images.common.data.remote.ImageDto
|
||||||
|
|
||||||
data class FeedDto(
|
data class FeedDto(
|
||||||
val data: MutableList<PostDto>,
|
val data: MutableList<PostDto>,
|
||||||
@ -18,6 +16,7 @@ data class FeedDto(
|
|||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
data class PostDto(
|
data class PostDto(
|
||||||
val post: Post,
|
val post: Post,
|
||||||
var numberOfLikes: Int,
|
var numberOfLikes: Int,
|
||||||
@ -26,17 +25,9 @@ data class FeedDto(
|
|||||||
val squadName: String?,
|
val squadName: String?,
|
||||||
var liked: Boolean,
|
var liked: Boolean,
|
||||||
var audio: AudioDto?
|
var audio: AudioDto?
|
||||||
): Parcelable {
|
){
|
||||||
|
|
||||||
constructor(parcel: Parcel) : this(
|
val list: MutableList<ImageDto> = mutableListOf()
|
||||||
parcel.readParcelable(Post::class.java.classLoader)!!,
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readString()!!,
|
|
||||||
parcel.readString(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readParcelable(AudioDto::class.java.classLoader)
|
|
||||||
)
|
|
||||||
|
|
||||||
data class Post(
|
data class Post(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
@ -47,70 +38,9 @@ data class FeedDto(
|
|||||||
var audioId: String?,
|
var audioId: String?,
|
||||||
val squadId: String?,
|
val squadId: String?,
|
||||||
val linkedDiscussionId: Long,
|
val linkedDiscussionId: Long,
|
||||||
val linkedCommentId: Long
|
val linkedCommentId: Long,
|
||||||
) : Parcelable {
|
var images: List<ImageDto>
|
||||||
constructor(parcel: Parcel) : this(
|
)
|
||||||
parcel.readLong(),
|
|
||||||
parcel.readString() ?: "",
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readString() ?: "",
|
|
||||||
parcel.readString(),
|
|
||||||
parcel.readString(),
|
|
||||||
parcel.readLong(),
|
|
||||||
parcel.readLong()
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
|
||||||
parcel.writeLong(id)
|
|
||||||
parcel.writeString(textContent)
|
|
||||||
parcel.writeInt(userId)
|
|
||||||
parcel.writeInt(privacy)
|
|
||||||
parcel.writeString(date)
|
|
||||||
parcel.writeString(audioId)
|
|
||||||
parcel.writeString(squadId)
|
|
||||||
parcel.writeLong(linkedDiscussionId)
|
|
||||||
parcel.writeLong(linkedCommentId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object CREATOR : Parcelable.Creator<Post> {
|
|
||||||
override fun createFromParcel(parcel: Parcel): Post {
|
|
||||||
return Post(parcel)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newArray(size: Int): Array<Post?> {
|
|
||||||
return arrayOfNulls(size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
|
||||||
parcel.writeParcelable(post, flags)
|
|
||||||
parcel.writeInt(numberOfLikes)
|
|
||||||
parcel.writeInt(numberOfComments)
|
|
||||||
parcel.writeString(userName)
|
|
||||||
parcel.writeString(squadName)
|
|
||||||
parcel.writeByte(if (liked) 1 else 0)
|
|
||||||
parcel.writeSerializable(audio)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object CREATOR : Parcelable.Creator<PostDto> {
|
|
||||||
override fun createFromParcel(parcel: Parcel): PostDto {
|
|
||||||
return PostDto(parcel)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newArray(size: Int): Array<PostDto?> {
|
|
||||||
return arrayOfNulls(size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,10 +7,8 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.isolaatti.images.common.data.remote.DeleteImagesDto
|
|
||||||
import com.isolaatti.images.common.data.remote.ImageDto
|
import com.isolaatti.images.common.data.remote.ImageDto
|
||||||
import com.isolaatti.images.common.data.remote.ImagesApi
|
import com.isolaatti.images.common.data.remote.ImagesApi
|
||||||
import com.isolaatti.images.common.domain.entity.Image
|
|
||||||
import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
||||||
import com.isolaatti.posting.posts.data.remote.DeletePostDto
|
import com.isolaatti.posting.posts.data.remote.DeletePostDto
|
||||||
import com.isolaatti.posting.posts.data.remote.EditPostDto
|
import com.isolaatti.posting.posts.data.remote.EditPostDto
|
||||||
@ -20,6 +18,7 @@ import com.isolaatti.posting.posts.data.remote.FeedsApi
|
|||||||
import com.isolaatti.posting.posts.data.remote.PostApi
|
import com.isolaatti.posting.posts.data.remote.PostApi
|
||||||
import com.isolaatti.posting.posts.data.remote.PostDeletedDto
|
import com.isolaatti.posting.posts.data.remote.PostDeletedDto
|
||||||
import com.isolaatti.posting.posts.data.remote.VersionDto
|
import com.isolaatti.posting.posts.data.remote.VersionDto
|
||||||
|
import com.isolaatti.posting.posts.domain.PostingSteps
|
||||||
import com.isolaatti.posting.posts.domain.PostsRepository
|
import com.isolaatti.posting.posts.domain.PostsRepository
|
||||||
import com.isolaatti.posting.posts.domain.entity.Post
|
import com.isolaatti.posting.posts.domain.entity.Post
|
||||||
import com.isolaatti.profile.domain.entity.ProfileListItem
|
import com.isolaatti.profile.domain.entity.ProfileListItem
|
||||||
@ -82,7 +81,7 @@ class PostsRepositoryImpl @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun makePost(createPostDto: CreatePostDto, images: List<Uri>): Flow<Resource<FeedDto.PostDto>> = flow {
|
override fun makePost(createPostDto: CreatePostDto, images: List<Uri>): Flow<Resource<PostingSteps>> = flow {
|
||||||
emit(Resource.Loading())
|
emit(Resource.Loading())
|
||||||
try {
|
try {
|
||||||
val hasImages = images.isNotEmpty()
|
val hasImages = images.isNotEmpty()
|
||||||
@ -103,6 +102,7 @@ class PostsRepositoryImpl @Inject constructor(
|
|||||||
emit(Resource.Error())
|
emit(Resource.Error())
|
||||||
return@flow
|
return@flow
|
||||||
}
|
}
|
||||||
|
emit(Resource.Success(PostingSteps.UploadingPhotos))
|
||||||
images.forEach { imageUri ->
|
images.forEach { imageUri ->
|
||||||
var imageInputStream: InputStream? = null
|
var imageInputStream: InputStream? = null
|
||||||
try {
|
try {
|
||||||
@ -146,20 +146,19 @@ class PostsRepositoryImpl @Inject constructor(
|
|||||||
postApi.deletePost(DeletePostDto(postId)).awaitResponse()
|
postApi.deletePost(DeletePostDto(postId)).awaitResponse()
|
||||||
emit(Resource.Error(Resource.Error.ErrorType.ServerError, "Some images were not processed correctly"))
|
emit(Resource.Error(Resource.Error.ErrorType.ServerError, "Some images were not processed correctly"))
|
||||||
} else {
|
} else {
|
||||||
postApi.setIsDraft(postId, false)
|
val setIsDraftCall = postApi.setIsDraft(postId, false).awaitResponse()
|
||||||
val response = postApi.getPost(postId).awaitResponse()
|
|
||||||
|
|
||||||
if(response.isSuccessful) {
|
if(setIsDraftCall.isSuccessful) {
|
||||||
emit(Resource.Success(response.body()))
|
emit(Resource.Success(PostingSteps.Finished))
|
||||||
} else {
|
} else {
|
||||||
val msg = "Post posted but could not retrieve updated post data from server"
|
val code = setIsDraftCall.code()
|
||||||
Log.e(LOG_TAG, msg)
|
Log.e(LOG_TAG, "Could not set as \"not draft\"")
|
||||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code()), msg))
|
emit(Resource.Error(Resource.Error.mapErrorCode(code), "Could not set as \"not draft\""))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit(Resource.Success(result.body()))
|
emit(Resource.Success(PostingSteps.Finished))
|
||||||
return@flow
|
return@flow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
package com.isolaatti.posting.posts.domain
|
||||||
|
|
||||||
|
enum class PostingSteps {
|
||||||
|
PostContent, UploadingPhotos, Finished, Unspecified
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@ interface PostsRepository {
|
|||||||
|
|
||||||
fun getProfilePosts(userId: Int, lastId: Long, olderFirst: Boolean, filter: FeedFilterDto?): Flow<Resource<MutableList<Post>>>
|
fun getProfilePosts(userId: Int, lastId: Long, olderFirst: Boolean, filter: FeedFilterDto?): Flow<Resource<MutableList<Post>>>
|
||||||
|
|
||||||
fun makePost(createPostDto: CreatePostDto, images: List<Uri>): Flow<Resource<FeedDto.PostDto>>
|
fun makePost(createPostDto: CreatePostDto, images: List<Uri>): Flow<Resource<PostingSteps>>
|
||||||
fun editPost(editPostDto: EditPostDto): Flow<Resource<FeedDto.PostDto>>
|
fun editPost(editPostDto: EditPostDto): Flow<Resource<FeedDto.PostDto>>
|
||||||
fun deletePost(postId: Long): Flow<Resource<PostDeletedDto>>
|
fun deletePost(postId: Long): Flow<Resource<PostDeletedDto>>
|
||||||
fun loadPost(postId: Long): Flow<Resource<Post>>
|
fun loadPost(postId: Long): Flow<Resource<Post>>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import android.os.Parcelable
|
|||||||
import com.isolaatti.audio.common.domain.Audio
|
import com.isolaatti.audio.common.domain.Audio
|
||||||
import com.isolaatti.common.Ownable
|
import com.isolaatti.common.Ownable
|
||||||
import com.isolaatti.common.hashtagRegex
|
import com.isolaatti.common.hashtagRegex
|
||||||
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||||
|
|
||||||
data class Post(
|
data class Post(
|
||||||
@ -20,7 +21,8 @@ data class Post(
|
|||||||
val userName: String,
|
val userName: String,
|
||||||
val squadName: String?,
|
val squadName: String?,
|
||||||
var liked: Boolean,
|
var liked: Boolean,
|
||||||
val audio: Audio? = null
|
val audio: Audio? = null,
|
||||||
|
val images: List<Image>
|
||||||
) : Ownable, Parcelable {
|
) : Ownable, Parcelable {
|
||||||
constructor(parcel: Parcel) : this(
|
constructor(parcel: Parcel) : this(
|
||||||
parcel.readLong(),
|
parcel.readLong(),
|
||||||
@ -35,7 +37,8 @@ data class Post(
|
|||||||
parcel.readString()!!,
|
parcel.readString()!!,
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readByte() != 0.toByte(),
|
parcel.readByte() != 0.toByte(),
|
||||||
parcel.readSerializable() as? Audio
|
parcel.readSerializable() as? Audio,
|
||||||
|
parcel.readParcelableArray(Image::class.java.classLoader)?.toList() as? List<Image> ?: emptyList()
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +58,8 @@ data class Post(
|
|||||||
userName = it.userName,
|
userName = it.userName,
|
||||||
squadName = it.squadName,
|
squadName = it.squadName,
|
||||||
liked = it.liked,
|
liked = it.liked,
|
||||||
audio = it.audio?.let { audioDto -> Audio.fromDto(audioDto) }
|
audio = it.audio?.let { audioDto -> Audio.fromDto(audioDto) },
|
||||||
|
images = it.post.images.map { imageDto -> Image(imageDto.id) }
|
||||||
)
|
)
|
||||||
}.toMutableList()
|
}.toMutableList()
|
||||||
}
|
}
|
||||||
@ -73,7 +77,8 @@ data class Post(
|
|||||||
numberOfLikes = postDto.numberOfLikes,
|
numberOfLikes = postDto.numberOfLikes,
|
||||||
userName = postDto.userName,
|
userName = postDto.userName,
|
||||||
squadName = postDto.squadName,
|
squadName = postDto.squadName,
|
||||||
liked = postDto.liked
|
liked = postDto.liked,
|
||||||
|
images = postDto.post.images.map { imageDto -> Image(imageDto.id) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +108,7 @@ data class Post(
|
|||||||
parcel.writeString(squadName)
|
parcel.writeString(squadName)
|
||||||
parcel.writeByte(if (liked) 1 else 0)
|
parcel.writeByte(if (liked) 1 else 0)
|
||||||
parcel.writeSerializable(audio)
|
parcel.writeSerializable(audio)
|
||||||
|
parcel.writeParcelableArray(images.toTypedArray(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
override fun describeContents(): Int {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package com.isolaatti.posting.posts.domain.use_case
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
||||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
import com.isolaatti.posting.posts.domain.PostingSteps
|
||||||
import com.isolaatti.posting.posts.domain.PostsRepository
|
import com.isolaatti.posting.posts.domain.PostsRepository
|
||||||
import com.isolaatti.utils.Resource
|
import com.isolaatti.utils.Resource
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@ -15,7 +15,7 @@ class MakePost @Inject constructor(private val postsRepository: PostsRepository)
|
|||||||
images: List<Uri>,
|
images: List<Uri>,
|
||||||
audioId: String?,
|
audioId: String?,
|
||||||
squadId: String?
|
squadId: String?
|
||||||
): Flow<Resource<FeedDto.PostDto>> {
|
): Flow<Resource<PostingSteps>> {
|
||||||
return postsRepository.makePost(CreatePostDto(privacy, content, audioId, squadId), images)
|
return postsRepository.makePost(CreatePostDto(privacy, content, audioId, squadId), images)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
|||||||
import com.isolaatti.posting.posts.data.remote.EditPostDto
|
import com.isolaatti.posting.posts.data.remote.EditPostDto
|
||||||
import com.isolaatti.posting.posts.data.remote.EditPostDto.Companion.PRIVACY_ISOLAATTI
|
import com.isolaatti.posting.posts.data.remote.EditPostDto.Companion.PRIVACY_ISOLAATTI
|
||||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||||
|
import com.isolaatti.posting.posts.domain.PostingSteps
|
||||||
import com.isolaatti.posting.posts.domain.entity.Post
|
import com.isolaatti.posting.posts.domain.entity.Post
|
||||||
import com.isolaatti.posting.posts.domain.use_case.EditPost
|
import com.isolaatti.posting.posts.domain.use_case.EditPost
|
||||||
import com.isolaatti.posting.posts.domain.use_case.LoadSinglePost
|
import com.isolaatti.posting.posts.domain.use_case.LoadSinglePost
|
||||||
@ -39,7 +40,6 @@ class CreatePostViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val validation: MutableLiveData<Boolean> = MutableLiveData(false)
|
val validation: MutableLiveData<Boolean> = MutableLiveData(false)
|
||||||
val posted: MutableLiveData<Post?> = MutableLiveData()
|
|
||||||
val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData()
|
val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData()
|
||||||
val sendingPost: MutableLiveData<Boolean> = MutableLiveData(false)
|
val sendingPost: MutableLiveData<Boolean> = MutableLiveData(false)
|
||||||
val postToEdit: MutableLiveData<EditPostDto> = MutableLiveData()
|
val postToEdit: MutableLiveData<EditPostDto> = MutableLiveData()
|
||||||
@ -49,6 +49,9 @@ class CreatePostViewModel @Inject constructor(
|
|||||||
private val _photos: MutableStateFlow<List<Uri>> = MutableStateFlow(emptyList())
|
private val _photos: MutableStateFlow<List<Uri>> = MutableStateFlow(emptyList())
|
||||||
val photos: StateFlow<List<Uri>> get() = _photos
|
val photos: StateFlow<List<Uri>> get() = _photos
|
||||||
|
|
||||||
|
private val _postingStep = MutableStateFlow(PostingSteps.Unspecified)
|
||||||
|
val postingStep: StateFlow<PostingSteps> get() = _postingStep
|
||||||
|
|
||||||
val audioAttachment: MutableLiveData<Playable?> = MutableLiveData()
|
val audioAttachment: MutableLiveData<Playable?> = MutableLiveData()
|
||||||
|
|
||||||
private var audioDraft: Long? = null
|
private var audioDraft: Long? = null
|
||||||
@ -71,8 +74,12 @@ class CreatePostViewModel @Inject constructor(
|
|||||||
).onEach {
|
).onEach {
|
||||||
when(it) {
|
when(it) {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
|
if(it.data == PostingSteps.Finished) {
|
||||||
sendingPost.postValue(false)
|
sendingPost.postValue(false)
|
||||||
posted.postValue(Post.fromPostDto(it.data!!))
|
}
|
||||||
|
|
||||||
|
_postingStep.value = it.data!!
|
||||||
|
|
||||||
}
|
}
|
||||||
is Resource.Error -> {
|
is Resource.Error -> {
|
||||||
sendingPost.postValue(false)
|
sendingPost.postValue(false)
|
||||||
@ -103,7 +110,6 @@ class CreatePostViewModel @Inject constructor(
|
|||||||
when(it) {
|
when(it) {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
sendingPost.postValue(false)
|
sendingPost.postValue(false)
|
||||||
posted.postValue(Post.fromPostDto(it.data!!))
|
|
||||||
}
|
}
|
||||||
is Resource.Error -> {
|
is Resource.Error -> {
|
||||||
sendingPost.postValue(false)
|
sendingPost.postValue(false)
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.isolaatti.posting.posts.presentation
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||||
|
import coil.load
|
||||||
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
|
|
||||||
|
class PostImagesViewPagerAdapter(private val images: List<Image>) :
|
||||||
|
RecyclerView.Adapter<PostImagesViewPagerAdapter.PostImagesViewPagerAdapterItemViewHolder>() {
|
||||||
|
class PostImagesViewPagerAdapterItemViewHolder(val imageView: ImageView) : ViewHolder(imageView)
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): PostImagesViewPagerAdapterItemViewHolder {
|
||||||
|
return PostImagesViewPagerAdapterItemViewHolder(
|
||||||
|
imageView = ImageView(parent.context).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = images.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: PostImagesViewPagerAdapterItemViewHolder, position: Int) {
|
||||||
|
val image = images[position]
|
||||||
|
|
||||||
|
holder.imageView.load(image.reducedImageUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ import android.widget.ImageView
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.core.text.set
|
import androidx.core.text.set
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||||
import coil.load
|
import coil.load
|
||||||
@ -162,6 +163,14 @@ class PostsRecyclerViewAdapter (
|
|||||||
itemBinding.audio.root.visibility = View.GONE
|
itemBinding.audio.root.visibility = View.GONE
|
||||||
itemBinding.audio.playButton.setOnClickListener(null)
|
itemBinding.audio.playButton.setOnClickListener(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(post.images.isNotEmpty()) {
|
||||||
|
itemBinding.photosViewPager.isVisible = true
|
||||||
|
itemBinding.photosViewPager.adapter = PostImagesViewPagerAdapter(post.images)
|
||||||
|
} else {
|
||||||
|
itemBinding.photosViewPager.isVisible = false
|
||||||
|
itemBinding.photosViewPager.adapter = null
|
||||||
|
}
|
||||||
itemBinding.shareButton.setOnClickListener {
|
itemBinding.shareButton.setOnClickListener {
|
||||||
callback.onShare(post.id)
|
callback.onShare(post.id)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,14 +13,18 @@ import androidx.compose.foundation.gestures.ScrollableState
|
|||||||
import androidx.compose.foundation.gestures.rememberScrollableState
|
import androidx.compose.foundation.gestures.rememberScrollableState
|
||||||
import androidx.compose.foundation.gestures.scrollable
|
import androidx.compose.foundation.gestures.scrollable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Close
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.BasicAlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@ -29,7 +33,9 @@ import androidx.compose.material3.OutlinedTextFieldDefaults
|
|||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@ -40,6 +46,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.isolaatti.MyApplication
|
import com.isolaatti.MyApplication
|
||||||
@ -48,8 +55,10 @@ import com.isolaatti.audio.common.components.AudioRecorder
|
|||||||
import com.isolaatti.common.IsolaattiBaseActivity
|
import com.isolaatti.common.IsolaattiBaseActivity
|
||||||
import com.isolaatti.common.IsolaattiTheme
|
import com.isolaatti.common.IsolaattiTheme
|
||||||
import com.isolaatti.posting.posts.components.PostAttachments
|
import com.isolaatti.posting.posts.components.PostAttachments
|
||||||
|
import com.isolaatti.posting.posts.domain.PostingSteps
|
||||||
import com.isolaatti.posting.posts.presentation.CreatePostViewModel
|
import com.isolaatti.posting.posts.presentation.CreatePostViewModel
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
|
||||||
@ -146,6 +155,33 @@ class CreatePostActivity : IsolaattiBaseActivity() {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
|
val posting by viewModel.sendingPost.observeAsState()
|
||||||
|
|
||||||
|
if(posting == true) {
|
||||||
|
val postingStep by viewModel.postingStep.collectAsState()
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {},
|
||||||
|
text = {
|
||||||
|
Row {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
Text(
|
||||||
|
when(postingStep) {
|
||||||
|
PostingSteps.PostContent -> getString(R.string.posting)
|
||||||
|
PostingSteps.UploadingPhotos -> getString(R.string.uploading_photos)
|
||||||
|
PostingSteps.Finished -> ""
|
||||||
|
PostingSteps.Unspecified -> ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = null,
|
||||||
|
title = {
|
||||||
|
Text(getString(R.string.posting))
|
||||||
|
},
|
||||||
|
confirmButton = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
Column(modifier = Modifier.padding(it).verticalScroll(scrollState)) {
|
Column(modifier = Modifier.padding(it).verticalScroll(scrollState)) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = text,
|
value = text,
|
||||||
|
|||||||
@ -182,10 +182,7 @@ class ProfileMainFragment : Fragment() {
|
|||||||
val profilePictureUrl = profile?.profilePictureUrl
|
val profilePictureUrl = profile?.profilePictureUrl
|
||||||
if(profilePictureUrl != null) {
|
if(profilePictureUrl != null) {
|
||||||
PictureViewerActivity.startActivityWithImages(requireContext(), arrayOf(
|
PictureViewerActivity.startActivityWithImages(requireContext(), arrayOf(
|
||||||
Image(
|
Image(profile.profileImageId ?: "")
|
||||||
profile.profileImageId ?: "",
|
|
||||||
profile.userId,
|
|
||||||
profile.uniqueUsername)
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,15 +15,20 @@
|
|||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
>
|
>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="4dp">
|
android:padding="4dp">
|
||||||
|
|
||||||
<RelativeLayout android:layout_width="match_parent"
|
<RelativeLayout
|
||||||
|
android:id="@+id/post_header_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/avatar_picture"
|
android:id="@+id/avatar_picture"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
@ -65,7 +70,17 @@
|
|||||||
layout="@layout/audio_attachment"
|
layout="@layout/audio_attachment"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/post_header_container"/>
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/photos_view_pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/audio"
|
||||||
|
app:layout_constraintDimensionRatio="H,1:1"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/post_content"
|
android:id="@+id/post_content"
|
||||||
@ -76,13 +91,15 @@
|
|||||||
android:linksClickable="true"
|
android:linksClickable="true"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
tools:text="Hola"
|
tools:text="Hola"
|
||||||
android:fontFamily="sans-serif"/>
|
android:fontFamily="sans-serif"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/photos_view_pager"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:gravity="start">
|
android:gravity="start"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/post_content">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/like_button"
|
android:id="@+id/like_button"
|
||||||
@ -110,7 +127,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/baseline_info_24" />
|
app:icon="@drawable/baseline_info_24" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@ -218,6 +218,8 @@
|
|||||||
<string name="ascending_by_creation_date">older-newer</string>
|
<string name="ascending_by_creation_date">older-newer</string>
|
||||||
<string name="descending_by_creation_date">newer-older</string>
|
<string name="descending_by_creation_date">newer-older</string>
|
||||||
<string name="invalid_arg">Invalid value passed</string>
|
<string name="invalid_arg">Invalid value passed</string>
|
||||||
|
<string name="posting">Posting</string>
|
||||||
|
<string name="uploading_photos">Uploading photos</string>
|
||||||
<string-array name="report_reasons">
|
<string-array name="report_reasons">
|
||||||
<item>Spam</item>
|
<item>Spam</item>
|
||||||
<item>Explicit content</item>
|
<item>Explicit content</item>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user