Merge pull request #6166 from networkException/autoplay-animated-images

[Feature] Add the option to autoplay animated images
This commit is contained in:
Benoit Marty 2022-05-30 20:42:19 +02:00 committed by GitHub
commit 5de6771547
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 48 additions and 4 deletions

1
changelog.d/6166.feature Normal file
View file

@ -0,0 +1 @@
Add settings switch to allow autoplaying animated images

View file

@ -56,4 +56,8 @@ class UserPreferencesProvider @Inject constructor(private val vectorPreferences:
fun showLiveSenderInfo(): Boolean { fun showLiveSenderInfo(): Boolean {
return vectorPreferences.showLiveSenderInfo() return vectorPreferences.showLiveSenderInfo()
} }
fun autoplayAnimatedImages(): Boolean {
return vectorPreferences.autoplayAnimatedImages()
}
} }

View file

@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.verification.VerificationState import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.getMsgType
import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
@ -119,6 +120,7 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
isLastFromThisSender = isLastFromThisSender, isLastFromThisSender = isLastFromThisSender,
e2eDecoration = e2eDecoration, e2eDecoration = e2eDecoration,
sendStateDecoration = sendStateDecoration, sendStateDecoration = sendStateDecoration,
messageType = event.root.getMsgType()
) )
} }

View file

@ -67,7 +67,8 @@ class MessageItemAttributesFactory @Inject constructor(
threadSummaryFormatted = displayableEventFormatter.formatThreadSummary(threadDetails?.threadSummaryLatestEvent).toString(), threadSummaryFormatted = displayableEventFormatter.formatThreadSummary(threadDetails?.threadSummaryLatestEvent).toString(),
threadDetails = threadDetails, threadDetails = threadDetails,
reactionsSummaryEvents = reactionsSummaryEvents, reactionsSummaryEvents = reactionsSummaryEvents,
areThreadMessagesEnabled = preferencesProvider.areThreadMessagesEnabled() areThreadMessagesEnabled = preferencesProvider.areThreadMessagesEnabled(),
autoplayAnimatedImages = preferencesProvider.autoplayAnimatedImages()
) )
} }
} }

View file

@ -188,6 +188,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
val threadSummaryFormatted: String? = null, val threadSummaryFormatted: String? = null,
val threadDetails: ThreadDetails? = null, val threadDetails: ThreadDetails? = null,
val areThreadMessagesEnabled: Boolean = false, val areThreadMessagesEnabled: Boolean = false,
val autoplayAnimatedImages: Boolean = false,
override val reactionsSummaryEvents: ReactionsSummaryEvents? = null, override val reactionsSummaryEvents: ReactionsSummaryEvents? = null,
) : AbsBaseMessageItem.Attributes { ) : AbsBaseMessageItem.Attributes {

View file

@ -34,6 +34,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStat
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import org.matrix.android.sdk.api.session.room.model.message.MessageType
@EpoxyModelClass(layout = R.layout.item_timeline_event_base) @EpoxyModelClass(layout = R.layout.item_timeline_event_base)
abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Holder>() { abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Holder>() {
@ -80,7 +81,17 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
ViewCompat.setTransitionName(holder.imageView, "imagePreview_${id()}") ViewCompat.setTransitionName(holder.imageView, "imagePreview_${id()}")
holder.mediaContentView.onClick(attributes.itemClickListener) holder.mediaContentView.onClick(attributes.itemClickListener)
holder.mediaContentView.setOnLongClickListener(attributes.itemLongClickListener) holder.mediaContentView.setOnLongClickListener(attributes.itemLongClickListener)
holder.playContentView.visibility = if (playable) View.VISIBLE else View.GONE
val isImageMessage = attributes.informationData.messageType == MessageType.MSGTYPE_IMAGE
val autoplayAnimatedImages = attributes.autoplayAnimatedImages
holder.playContentView.visibility = if (playable && isImageMessage && autoplayAnimatedImages) {
View.GONE
} else if (playable) {
View.VISIBLE
} else {
View.GONE
}
} }
override fun unbind(holder: Holder) { override fun unbind(holder: Holder) {

View file

@ -43,6 +43,7 @@ data class MessageInformationData(
val sendStateDecoration: SendStateDecoration = SendStateDecoration.NONE, val sendStateDecoration: SendStateDecoration = SendStateDecoration.NONE,
val isFirstFromThisSender: Boolean = false, val isFirstFromThisSender: Boolean = false,
val isLastFromThisSender: Boolean = false, val isLastFromThisSender: Boolean = false,
val messageType: String? = null
) : Parcelable { ) : Parcelable {
val matrixItem: MatrixItem val matrixItem: MatrixItem

View file

@ -41,6 +41,7 @@ import im.vector.app.core.glide.GlideRequest
import im.vector.app.core.glide.GlideRequests import im.vector.app.core.glide.GlideRequests
import im.vector.app.core.ui.model.Size import im.vector.app.core.ui.model.Size
import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.settings.VectorPreferences
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.content.ContentUrlResolver
@ -67,7 +68,8 @@ private const val URL_PREVIEW_IMAGE_MIN_FULL_HEIGHT_PX = 315
class ImageContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper, class ImageContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper,
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionHolder: ActiveSessionHolder,
private val dimensionConverter: DimensionConverter) { private val dimensionConverter: DimensionConverter,
private val vectorPreferences: VectorPreferences) {
@Parcelize @Parcelize
data class Data( data class Data(
@ -133,7 +135,10 @@ class ImageContentRenderer @Inject constructor(private val localFilesHelper: Loc
imageView.contentDescription = data.filename imageView.contentDescription = data.filename
createGlideRequest(data, mode, imageView, size) createGlideRequest(data, mode, imageView, size)
.dontAnimate() .let {
if (vectorPreferences.autoplayAnimatedImages()) it
else it.dontAnimate()
}
.transform(cornerTransformation) .transform(cornerTransformation)
// .thumbnail(0.3f) // .thumbnail(0.3f)
.into(imageView) .into(imageView)

View file

@ -105,6 +105,7 @@ class VectorPreferences @Inject constructor(
private const val SETTINGS_SHOW_EMOJI_KEYBOARD = "SETTINGS_SHOW_EMOJI_KEYBOARD" private const val SETTINGS_SHOW_EMOJI_KEYBOARD = "SETTINGS_SHOW_EMOJI_KEYBOARD"
private const val SETTINGS_LABS_ENABLE_LATEX_MATHS = "SETTINGS_LABS_ENABLE_LATEX_MATHS" private const val SETTINGS_LABS_ENABLE_LATEX_MATHS = "SETTINGS_LABS_ENABLE_LATEX_MATHS"
const val SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE = "SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE" const val SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE = "SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE"
const val SETTINGS_AUTOPLAY_ANIMATED_IMAGES = "SETTINGS_AUTOPLAY_ANIMATED_IMAGES"
// Room directory // Room directory
private const val SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS = "SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS" private const val SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS = "SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS"
@ -773,6 +774,15 @@ class VectorPreferences @Inject constructor(
return defaultPrefs.getBoolean(SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY, false) return defaultPrefs.getBoolean(SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY, false)
} }
/**
* Tells if animated image attachments should automatically play their animation in the timeline.
*
* @return true if animated image attachments should automatically play their animation in the timeline
*/
fun autoplayAnimatedImages(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_AUTOPLAY_ANIMATED_IMAGES, false)
}
/** /**
* Tells if the typing notifications should be sent. * Tells if the typing notifications should be sent.
* *

View file

@ -973,6 +973,8 @@
<string name="settings_show_read_receipts_summary">Click on the read receipts for a detailed list.</string> <string name="settings_show_read_receipts_summary">Click on the read receipts for a detailed list.</string>
<string name="settings_chat_effects_title">Show chat effects</string> <string name="settings_chat_effects_title">Show chat effects</string>
<string name="settings_chat_effects_description">Use /confetti command or send a message containing ❄️ or 🎉</string> <string name="settings_chat_effects_description">Use /confetti command or send a message containing ❄️ or 🎉</string>
<string name="settings_autoplay_animated_images_title">Autoplay animated images</string>
<string name="settings_autoplay_animated_images_summary">Play animated images in the timeline as soon as they are visible</string>
<string name="settings_show_join_leave_messages">Show join and leave events</string> <string name="settings_show_join_leave_messages">Show join and leave events</string>
<string name="settings_show_join_leave_messages_summary">Invites, removes, and bans are unaffected.</string> <string name="settings_show_join_leave_messages_summary">Invites, removes, and bans are unaffected.</string>
<string name="settings_show_avatar_display_name_changes_messages">Show account events</string> <string name="settings_show_avatar_display_name_changes_messages">Show account events</string>

View file

@ -140,6 +140,12 @@
android:summary="@string/settings_chat_effects_description" android:summary="@string/settings_chat_effects_description"
android:title="@string/settings_chat_effects_title" /> android:title="@string/settings_chat_effects_title" />
<im.vector.app.core.preference.VectorSwitchPreference
android:defaultValue="false"
android:key="SETTINGS_AUTOPLAY_ANIMATED_IMAGES"
android:summary="@string/settings_autoplay_animated_images_summary"
android:title="@string/settings_autoplay_animated_images_title" />
<im.vector.app.core.preference.VectorSwitchPreference <im.vector.app.core.preference.VectorSwitchPreference
android:key="SETTINGS_VIBRATE_ON_MENTION_KEY" android:key="SETTINGS_VIBRATE_ON_MENTION_KEY"
android:title="@string/settings_vibrate_on_mention" android:title="@string/settings_vibrate_on_mention"