From 344863b5d41c3228034ff5a322c337cd0ba00efc Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Thu, 5 Sep 2019 21:07:01 +0200 Subject: [PATCH] Add audio support for timelines (#1466) * Add minimal audio support for timelines * fix attachment description formatting --- .../tusky/adapter/StatusBaseViewHolder.java | 35 +++++++++++++++---- .../conversation/ConversationViewHolder.java | 2 +- .../keylesspalace/tusky/entity/Attachment.kt | 6 +++- .../tusky/fragment/SFragment.java | 3 +- .../tusky/fragment/ViewMediaFragment.kt | 3 +- .../main/res/drawable/ic_music_box_24dp.xml | 8 +++++ 6 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 app/src/main/res/drawable/ic_music_box_24dp.xml diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index 159ab96f..99841318 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -334,8 +334,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { favouriteButton.setChecked(favourited); } - private void loadImage(MediaPreviewImageView imageView, String previewUrl, String description, - MetaData meta) { + private void loadImage(MediaPreviewImageView imageView, String previewUrl, MetaData meta) { if (TextUtils.isEmpty(previewUrl)) { Glide.with(imageView) .load(mediaPreviewUnloadedId) @@ -385,7 +384,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } if (!sensitive || showingContent) { - loadImage(imageView, previewUrl, description, attachments.get(i).getMeta()); + loadImage(imageView, previewUrl, attachments.get(i).getMeta()); } else { imageView.setImageResource(mediaPreviewUnloadedId); } @@ -458,6 +457,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { case GIFV: case VIDEO: return R.drawable.ic_videocam_24dp; + case AUDIO: + return R.drawable.ic_music_box_24dp; } } @@ -505,11 +506,14 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } private static CharSequence getAttachmentDescription(Context context, Attachment attachment) { + String duration = ""; + if(attachment.getMeta().getDuration() != null && attachment.getMeta().getDuration() > 0) { + duration = formatDuration(attachment.getMeta().getDuration()) + " "; + } if (TextUtils.isEmpty(attachment.getDescription())) { - return context - .getString(R.string.description_status_media_no_description_placeholder); + return duration + context.getString(R.string.description_status_media_no_description_placeholder); } else { - return attachment.getDescription(); + return duration + attachment.getDescription(); } } @@ -605,7 +609,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { setFavourited(status.isFavourited()); List attachments = status.getAttachments(); boolean sensitive = status.isSensitive(); - if (mediaPreviewEnabled) { + if (mediaPreviewEnabled && !hasAudioAttachment(attachments)) { setMediaPreviews(attachments, sensitive, listener, status.isShowingContent()); if (attachments.size() == 0) { @@ -651,6 +655,15 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } } + protected static boolean hasAudioAttachment(List attachments) { + for(Attachment attachment: attachments) { + if (attachment.getType() == Attachment.Type.AUDIO) { + return true; + } + } + return false; + } + private void setDescriptionForStatus(@NonNull StatusViewData.Concrete status) { Context context = itemView.getContext(); @@ -848,4 +861,12 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { return pollDescription.getContext().getString(R.string.poll_info_format, votesText, pollDurationInfo); } + private static String formatDuration(double durationInSeconds) { + int seconds = (int) Math.round(durationInSeconds) % 60; + int minutes = (int) durationInSeconds % 3600 / 60; + int hours = (int) durationInSeconds / 3600; + + return String.format("%d:%02d:%02d", hours, minutes, seconds); + } + } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java index 6cb69382..db2dc2cc 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java @@ -85,7 +85,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder { setFavourited(status.getFavourited()); List attachments = status.getAttachments(); boolean sensitive = status.getSensitive(); - if(mediaPreviewEnabled) { + if(mediaPreviewEnabled && !hasAudioAttachment(attachments)) { setMediaPreviews(attachments, sensitive, listener, status.getShowingHiddenContent()); if (attachments.size() == 0) { diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt index 785b7c56..dc3732bc 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt @@ -42,6 +42,8 @@ data class Attachment( GIFV, @SerializedName("video") VIDEO, + @SerializedName("audio") + AUDIO, @SerializedName("unknown") UNKNOWN } @@ -53,6 +55,7 @@ data class Attachment( "\"image\"" -> Type.IMAGE "\"gifv\"" -> Type.GIFV "\"video\"" -> Type.VIDEO + "\"audio\"" -> Type.AUDIO else -> Type.UNKNOWN } } @@ -63,7 +66,8 @@ data class Attachment( */ @Parcelize data class MetaData ( - val focus: Focus? + val focus: Focus?, + val duration: Float? ) : Parcelable /** diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java index 1f2f99f8..9dd5706d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java @@ -310,7 +310,8 @@ public abstract class SFragment extends BaseFragment implements Injectable { switch (type) { case GIFV: case VIDEO: - case IMAGE: { + case IMAGE: + case AUDIO: { final List attachments = AttachmentViewData.list(actionable); final Intent intent = ViewMediaActivity.newIntent(getContext(), attachments, urlIndex); diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt index fcc8ddae..540469fa 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt @@ -51,7 +51,8 @@ abstract class ViewMediaFragment : BaseFragment(), SharedElementTransitionListen val fragment = when (attachment.type) { Attachment.Type.IMAGE -> ViewImageFragment() Attachment.Type.VIDEO, - Attachment.Type.GIFV -> ViewVideoFragment() + Attachment.Type.GIFV, + Attachment.Type.AUDIO -> ViewVideoFragment() else -> ViewImageFragment() // it probably won't show anything, but its better than crashing } fragment.arguments = arguments diff --git a/app/src/main/res/drawable/ic_music_box_24dp.xml b/app/src/main/res/drawable/ic_music_box_24dp.xml new file mode 100644 index 00000000..c0243d93 --- /dev/null +++ b/app/src/main/res/drawable/ic_music_box_24dp.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file