Rudimentary video support in PostCreationActivity

This commit is contained in:
Matthieu 2022-02-16 13:01:32 +01:00
parent 63362a031b
commit 03f83790f2
12 changed files with 117 additions and 47 deletions

View File

@ -50,11 +50,12 @@ import kotlin.math.ceil
private const val TAG = "Post Creation Activity" private const val TAG = "Post Creation Activity"
data class PhotoData( data class PhotoData(
var imageUri: Uri, var imageUri: Uri,
var size: Long, var size: Long,
var uploadId: String? = null, var uploadId: String? = null,
var progress: Int? = null, var progress: Int? = null,
var imageDescription: String? = null, var imageDescription: String? = null,
var video: Boolean,
) )
class PostCreationActivity : BaseActivity() { class PostCreationActivity : BaseActivity() {
@ -85,7 +86,7 @@ class PostCreationActivity : BaseActivity() {
intent.clipData?.let { addPossibleImages(it) } intent.clipData?.let { addPossibleImages(it) }
val carousel: ImageCarousel = binding.carousel val carousel: ImageCarousel = binding.carousel
carousel.addData(photoData.map { CarouselItem(it.imageUri) }) carousel.addData(photoData.map { CarouselItem(it.imageUri, video = it.video) })
carousel.layoutCarouselCallback = { carousel.layoutCarouselCallback = {
if(it){ if(it){
// Became a carousel // Became a carousel
@ -138,7 +139,7 @@ class PostCreationActivity : BaseActivity() {
binding.removePhotoButton.setOnClickListener { binding.removePhotoButton.setOnClickListener {
carousel.currentPosition.takeIf { it != -1 }?.let { currentPosition -> carousel.currentPosition.takeIf { it != -1 }?.let { currentPosition ->
photoData.removeAt(currentPosition) photoData.removeAt(currentPosition)
carousel.addData(photoData.map { CarouselItem(it.imageUri, it.imageDescription) }) carousel.addData(photoData.map { CarouselItem(it.imageUri, it.imageDescription, it.video) })
binding.addPhotoButton.isEnabled = true binding.addPhotoButton.isEnabled = true
} }
} }
@ -164,17 +165,17 @@ class PostCreationActivity : BaseActivity() {
} }
for (i in 0 until count) { for (i in 0 until count) {
clipData.getItemAt(i).uri.let { clipData.getItemAt(i).uri.let {
val size = it.getSizeAndValidate() val sizeAndVideoPair: Pair<Long, Boolean> = it.getSizeAndVideoValidate()
photoData.add(PhotoData(imageUri = it, size = size)) photoData.add(PhotoData(imageUri = it, size = sizeAndVideoPair.first, video = sizeAndVideoPair.second))
} }
} }
} }
/** /**
* Returns the size of the file of the Uri, and opens a dialog in case it is too big or in case * Returns the size of the file of the Uri, and whether it is a video,
* the file is unsupported. * and opens a dialog in case it is too big or in case the file is unsupported.
*/ */
private fun Uri.getSizeAndValidate(): Long { private fun Uri.getSizeAndVideoValidate(): Pair<Long, Boolean> {
val size: Long = val size: Long =
if (toString().startsWith("content")) { if (toString().startsWith("content")) {
contentResolver.query(this, null, null, null, null) contentResolver.query(this, null, null, null, null)
@ -209,7 +210,7 @@ class PostCreationActivity : BaseActivity() {
setNegativeButton(android.R.string.ok) { _, _ -> } setNegativeButton(android.R.string.ok) { _, _ -> }
}.show() }.show()
} }
return size return Pair(size, isVideo)
} }
private val addPhotoResultContract = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> private val addPhotoResultContract = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
@ -217,7 +218,7 @@ class PostCreationActivity : BaseActivity() {
result.data?.clipData?.let { result.data?.clipData?.let {
addPossibleImages(it) addPossibleImages(it)
} }
binding.carousel.addData(photoData.map { CarouselItem(it.imageUri, it.imageDescription) }) binding.carousel.addData(photoData.map { CarouselItem(it.imageUri, it.imageDescription, it.video) })
} else if (result.resultCode != Activity.RESULT_CANCELED) { } else if (result.resultCode != Activity.RESULT_CANCELED) {
Toast.makeText(applicationContext, "Error while adding images", Toast.LENGTH_SHORT).show() Toast.makeText(applicationContext, "Error while adding images", Toast.LENGTH_SHORT).show()
} }
@ -309,8 +310,8 @@ class PostCreationActivity : BaseActivity() {
*/ */
private fun upload() { private fun upload() {
enableButton(false) enableButton(false)
binding.uploadProgressBar.visibility = View.VISIBLE binding.uploadProgressBar.visibility = VISIBLE
binding.uploadCompletedTextview.visibility = View.INVISIBLE binding.uploadCompletedTextview.visibility = INVISIBLE
binding.removePhotoButton.isEnabled = false binding.removePhotoButton.isEnabled = false
binding.editPhotoButton.isEnabled = false binding.editPhotoButton.isEnabled = false
binding.addPhotoButton.isEnabled = false binding.addPhotoButton.isEnabled = false
@ -432,21 +433,30 @@ class PostCreationActivity : BaseActivity() {
val position: Int = result.data!!.getIntExtra(PhotoEditActivity.PICTURE_POSITION, 0) val position: Int = result.data!!.getIntExtra(PhotoEditActivity.PICTURE_POSITION, 0)
photoData.getOrNull(position)?.apply { photoData.getOrNull(position)?.apply {
imageUri = result.data!!.getStringExtra(PhotoEditActivity.PICTURE_URI)!!.toUri() imageUri = result.data!!.getStringExtra(PhotoEditActivity.PICTURE_URI)!!.toUri()
size = imageUri.getSizeAndValidate() val (imageSize, imageVideo) = imageUri.getSizeAndVideoValidate()
size = imageSize
video = imageVideo
progress = null progress = null
uploadId = null uploadId = null
} ?: Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show() } ?: Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show()
binding.carousel.addData(photoData.map { CarouselItem(it.imageUri, it.imageDescription) }) binding.carousel.addData(photoData.map { CarouselItem(it.imageUri, it.imageDescription, it.video) })
} else if(result?.resultCode != Activity.RESULT_CANCELED){ } else if(result?.resultCode != Activity.RESULT_CANCELED){
Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show() Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show()
} }
} }
private fun edit(position: Int) { private fun edit(position: Int) {
val intent = Intent(this, PhotoEditActivity::class.java) if(photoData[position].video){
.putExtra(PhotoEditActivity.PICTURE_URI, photoData[position].imageUri) AlertDialog.Builder(this).apply {
.putExtra(PhotoEditActivity.PICTURE_POSITION, position) setMessage(R.string.video_edit_not_yet_supported)
editResultContract.launch(intent) setNegativeButton(android.R.string.ok) { _, _ -> }
}.show()
} else {
val intent = Intent(this, PhotoEditActivity::class.java)
.putExtra(PhotoEditActivity.PICTURE_URI, photoData[position].imageUri)
.putExtra(PhotoEditActivity.PICTURE_POSITION, position)
editResultContract.launch(intent)
}
} }
} }

View File

@ -2,10 +2,11 @@ package org.pixeldroid.app.postCreation
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.FrameLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
internal class SquareLayout(context: Context, attrs: AttributeSet) : internal class SquareLayout(context: Context, attrs: AttributeSet) :
RelativeLayout(context, attrs) { FrameLayout(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec) super.onMeasure(widthMeasureSpec, widthMeasureSpec)

View File

@ -3,13 +3,17 @@ package org.pixeldroid.app.postCreation.carousel
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.ImageView import android.widget.ImageView
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.posts.MediaViewerActivity
class CarouselAdapter( class CarouselAdapter(
@ -26,6 +30,8 @@ class CarouselAdapter(
class MyViewHolder(itemView: View, imageViewId: Int) : RecyclerView.ViewHolder(itemView) { class MyViewHolder(itemView: View, imageViewId: Int) : RecyclerView.ViewHolder(itemView) {
var img: ImageView = itemView.findViewById(imageViewId) var img: ImageView = itemView.findViewById(imageViewId)
// Null if not relevant
val videoIndicator: ImageButton? = itemView.findViewById(R.id.videoIndicator)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
@ -60,10 +66,21 @@ class CarouselAdapter(
} }
override fun onBindViewHolder(holder: MyViewHolder, position: Int) { override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
if(carousel) { if (carousel) {
holder.img.scaleType = imageScaleType holder.img.scaleType = imageScaleType
holder.videoIndicator?.setOnClickListener{
with(dataList[position]) {
MediaViewerActivity.openActivity(
holder.itemView.context,
imageUrl.toString(),
caption
)
}
}
} }
holder.videoIndicator?.visibility = if (dataList[position].video) VISIBLE else GONE
dataList.elementAtOrNull(position)?.let { dataList.elementAtOrNull(position)?.let {
Glide.with(holder.itemView.context) Glide.with(holder.itemView.context)
.load(it.imageUrl) .load(it.imageUrl)
@ -83,7 +100,6 @@ class CarouselAdapter(
true true
} }
} }
} }

View File

@ -4,7 +4,6 @@ import android.net.Uri
data class CarouselItem constructor( data class CarouselItem constructor(
val imageUrl: Uri, val imageUrl: Uri,
val caption: String? = null val caption: String? = null,
) { val video: Boolean
constructor(imageUrl: Uri) : this(imageUrl, null) )
}

View File

@ -49,7 +49,7 @@ class ImageCarousel(
var indicator: CircleIndicator2? = null var indicator: CircleIndicator2? = null
set(newIndicator) { set(newIndicator) {
indicator?.apply { indicator?.apply {
// if we remove it form the view, then the caption textView constraint won't work. // if we remove it from the view, then the caption textView constraint won't work.
this.visibility = View.GONE this.visibility = View.GONE
isBuiltInIndicator = false isBuiltInIndicator = false

View File

@ -1,5 +1,7 @@
package org.pixeldroid.app.posts package org.pixeldroid.app.posts
import android.content.Context
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.media2.common.MediaMetadata import androidx.media2.common.MediaMetadata
@ -15,6 +17,13 @@ class MediaViewerActivity : BaseActivity() {
companion object { companion object {
const val VIDEO_URL_TAG = "video_url_mediavieweractivity" const val VIDEO_URL_TAG = "video_url_mediavieweractivity"
const val VIDEO_DESCRIPTION_TAG = "video_description_mediavieweractivity" const val VIDEO_DESCRIPTION_TAG = "video_description_mediavieweractivity"
fun openActivity(context: Context, url: String?, description: String?){
val intent = Intent(context, MediaViewerActivity::class.java)
intent.putExtra(VIDEO_URL_TAG, url)
intent.putExtra(VIDEO_DESCRIPTION_TAG, description)
context.startActivity(intent)
}
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -39,6 +39,7 @@ import com.karumi.dexter.listener.single.BasePermissionListener
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.posts.MediaViewerActivity.Companion.VIDEO_DESCRIPTION_TAG import org.pixeldroid.app.posts.MediaViewerActivity.Companion.VIDEO_DESCRIPTION_TAG
import org.pixeldroid.app.posts.MediaViewerActivity.Companion.VIDEO_URL_TAG import org.pixeldroid.app.posts.MediaViewerActivity.Companion.VIDEO_URL_TAG
import org.pixeldroid.app.posts.MediaViewerActivity.Companion.openActivity
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -620,14 +621,12 @@ private class AlbumViewPagerAdapter(private val media_attachments: List<Attachme
holder.videoPlayButton.visibility = if(video) View.VISIBLE else View.GONE holder.videoPlayButton.visibility = if(video) View.VISIBLE else View.GONE
if(video){ if(video){
fun openActivity(){ holder.videoPlayButton.setOnClickListener {
val intent = Intent(holder.binding.root.context, MediaViewerActivity::class.java) openActivity(holder.binding.root.context, url, description)
intent.putExtra(VIDEO_URL_TAG, url) }
intent.putExtra(VIDEO_DESCRIPTION_TAG, description) holder.image.setOnClickListener {
holder.binding.root.context.startActivity(intent) openActivity(holder.binding.root.context, url, description)
} }
holder.videoPlayButton.setOnClickListener {openActivity()}
holder.image.setOnClickListener {openActivity()}
} }
val description = description val description = description

View File

@ -73,6 +73,7 @@ fun bitmapFromUri(contentResolver: ContentResolver, uri: Uri?): Bitmap =
) )
{ decoder, _, _ -> decoder.isMutableRequired = true } { decoder, _, _ -> decoder.isMutableRequired = true }
} else { } else {
@Suppress("DEPRECATION")
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri) val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)
modifyOrientation(bitmap!!, contentResolver, uri!!) modifyOrientation(bitmap!!, contentResolver, uri!!)
} }

View File

@ -10,6 +10,7 @@
android:id="@+id/addPhotoSquare" android:id="@+id/addPhotoSquare"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_gravity="center"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:background="@drawable/add_photo_button" android:background="@drawable/add_photo_button"

View File

@ -1,15 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.pixeldroid.app.postCreation.SquareLayout xmlns:android="http://schemas.android.com/apk/res/android" <org.pixeldroid.app.postCreation.SquareLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:foreground="?selectableItemBackground"
android:clickable="true" android:clickable="true"
android:focusable="true"> android:focusable="true"
android:foreground="?selectableItemBackground">
<ImageView <ImageView
android:id="@+id/galleryImage" android:id="@+id/galleryImage"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/post_image"
android:padding="8dp" android:padding="8dp"
android:scaleType="centerCrop" android:scaleType="centerCrop" />
android:contentDescription="@string/post_image" />
<ImageButton
android:id="@+id/videoIndicator"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="top"
android:layout_margin="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/play_video"
android:src="@drawable/play_circle_filled"
android:visibility="gone"
tools:visibility="visible" />
</org.pixeldroid.app.postCreation.SquareLayout> </org.pixeldroid.app.postCreation.SquareLayout>

View File

@ -1,9 +1,28 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/img"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:scaleType="centerInside"
tools:ignore="ContentDescription"
tools:src="@tools:sample/backgrounds/scenic" /> <ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
tools:ignore="ContentDescription" />
<ImageButton
android:id="@+id/videoIndicator"
android:visibility="gone"
android:background="?attr/selectableItemBackgroundBorderless"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="@drawable/play_circle_filled"
android:contentDescription="@string/play_video" />
</FrameLayout>

View File

@ -261,4 +261,5 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="no_camera_permission">Camera permission not granted, grant the permission in settings if you want to let PixelDroid use the camera</string> <string name="no_camera_permission">Camera permission not granted, grant the permission in settings if you want to let PixelDroid use the camera</string>
<string name="no_storage_permission">Storage permission not granted, grant the permission in settings if you want to let PixelDroid show the thumbnail</string> <string name="no_storage_permission">Storage permission not granted, grant the permission in settings if you want to let PixelDroid show the thumbnail</string>
<string name="play_video">Play video</string> <string name="play_video">Play video</string>
<string name="video_edit_not_yet_supported">Video editing is not yet supported</string>
</resources> </resources>