From 9dccd06a06bb31530da8f434c96dd466ebf0b9ce Mon Sep 17 00:00:00 2001 From: Levi Bard Date: Thu, 16 Jan 2020 19:05:52 +0100 Subject: [PATCH] Add support for uploading audio attachments (#1630) * Add support for audio attachments. Partially addresses #1337 * Register Tusky as a target for audio sharing * Use icon with textColorTertiary for audio preview --- app/src/main/AndroidManifest.xml | 7 +++++++ .../tusky/components/compose/ComposeActivity.kt | 13 ++++++++----- .../tusky/components/compose/ComposeViewModel.kt | 3 ++- .../components/compose/MediaPreviewAdapter.kt | 15 ++++++++++----- .../tusky/components/compose/MediaUploader.kt | 8 ++++++++ .../res/drawable/ic_music_box_preview_24dp.xml | 8 ++++++++ app/src/main/res/values/strings.xml | 1 + 7 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 app/src/main/res/drawable/ic_music_box_preview_24dp.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0f77db166..3535d9f59 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -89,6 +89,13 @@ + + + + + + + () if (intent.action != null) { when (intent.action) { @@ -323,7 +323,7 @@ class ComposeActivity : BaseActivity(), combineOptionalLiveData(viewModel.media, viewModel.poll) { media, poll -> val active = poll == null && media!!.size != 4 - && media.firstOrNull()?.type != QueuedMedia.Type.VIDEO + && (media.isEmpty() || media.first().type == QueuedMedia.Type.IMAGE) enableButton(composeAddMediaButton, active, active) enablePollButton(media.isNullOrEmpty()) }.subscribe() @@ -813,7 +813,7 @@ class ComposeActivity : BaseActivity(), val intent = Intent(Intent.ACTION_GET_CONTENT) intent.addCategory(Intent.CATEGORY_OPENABLE) - val mimeTypes = arrayOf("image/*", "video/*") + val mimeTypes = arrayOf("image/*", "video/*", "audio/*") intent.type = "*/*" intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes) startActivityForResult(intent, MEDIA_PICK_RESULT) @@ -856,6 +856,9 @@ class ComposeActivity : BaseActivity(), is VideoSizeException -> { R.string.error_video_upload_size } + is AudioSizeException -> { + R.string.error_audio_upload_size + } is VideoOrImageException -> { R.string.error_media_upload_image_or_video } @@ -980,7 +983,7 @@ class ComposeActivity : BaseActivity(), val description: String? = null ) { enum class Type { - IMAGE, VIDEO; + IMAGE, VIDEO, AUDIO; } } @@ -1036,7 +1039,7 @@ class ComposeActivity : BaseActivity(), @JvmStatic fun canHandleMimeType(mimeType: String?): Boolean { - return mimeType != null && (mimeType.startsWith("image/") || mimeType.startsWith("video/") || mimeType == "text/plain") + return mimeType != null && (mimeType.startsWith("image/") || mimeType.startsWith("video/") || mimeType.startsWith("audio/") || mimeType == "text/plain") } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt index 159738538..0e71596fc 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt @@ -127,7 +127,7 @@ class ComposeViewModel mediaUploader.prepareMedia(uri) .map { (type, uri, size) -> val mediaItems = media.value!! - if (type == QueuedMedia.Type.VIDEO + if (type != QueuedMedia.Type.IMAGE && mediaItems.isNotEmpty() && mediaItems[0].type == QueuedMedia.Type.IMAGE) { throw VideoOrImageException() @@ -388,6 +388,7 @@ class ComposeViewModel val mediaType = when (a.type) { Attachment.Type.VIDEO, Attachment.Type.GIFV -> QueuedMedia.Type.VIDEO Attachment.Type.UNKNOWN, Attachment.Type.IMAGE -> QueuedMedia.Type.IMAGE + Attachment.Type.AUDIO -> QueuedMedia.Type.AUDIO else -> QueuedMedia.Type.IMAGE } addUploadedMedia(a.id, mediaType, a.url.toUri(), a.description) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt index babb0a391..093e860fb 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaPreviewAdapter.kt @@ -69,11 +69,16 @@ class MediaPreviewAdapter( val item = differ.currentList[position] holder.progressImageView.setChecked(!item.description.isNullOrEmpty()) holder.progressImageView.setProgress(item.uploadPercent) - Glide.with(holder.itemView.context) - .load(item.uri) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .dontAnimate() - .into(holder.progressImageView) + if (item.type == ComposeActivity.QueuedMedia.Type.AUDIO) { + // TODO: Fancy waveform display? + holder.progressImageView.setImageResource(R.drawable.ic_music_box_preview_24dp) + } else { + Glide.with(holder.itemView.context) + .load(item.uri) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .dontAnimate() + .into(holder.progressImageView) + } } private val differ = AsyncListDiffer(this, object : DiffUtil.ItemCallback() { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt index af41f4bbd..73fa6d11f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt @@ -63,6 +63,7 @@ interface MediaUploader { fun uploadMedia(media: QueuedMedia): Observable } +class AudioSizeException : Exception() class VideoSizeException : Exception() class MediaTypeException : Exception() class CouldNotOpenFileException : Exception() @@ -128,6 +129,12 @@ class MediaUploaderImpl( "image" -> { PreparedMedia(QueuedMedia.Type.IMAGE, uri, mediaSize) } + "audio" -> { + if (mediaSize > STATUS_AUDIO_SIZE_LIMIT) { + throw AudioSizeException() + } + PreparedMedia(QueuedMedia.Type.AUDIO, uri, mediaSize) + } else -> { throw MediaTypeException() } @@ -196,6 +203,7 @@ class MediaUploaderImpl( private companion object { private const val TAG = "MediaUploaderImpl" private const val STATUS_VIDEO_SIZE_LIMIT = 41943040 // 40MiB + private const val STATUS_AUDIO_SIZE_LIMIT = 41943040 // 40MiB private const val STATUS_IMAGE_SIZE_LIMIT = 8388608 // 8MiB private const val STATUS_IMAGE_PIXEL_SIZE_LIMIT = 16777216 // 4096^2 Pixels diff --git a/app/src/main/res/drawable/ic_music_box_preview_24dp.xml b/app/src/main/res/drawable/ic_music_box_preview_24dp.xml new file mode 100644 index 000000000..67901791a --- /dev/null +++ b/app/src/main/res/drawable/ic_music_box_preview_24dp.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 21bd1e3ea..7311b17b5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ The status is too long! The file must be less than 8MB. Video files must be less than 40MB. + Audio files must be less than 40MB. That type of file cannot be uploaded. That file could not be opened. Permission to read media is required.