From 32dea865022d5be4ec98f779f474ae44ac9a26c8 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Sun, 26 May 2024 08:06:51 +0200 Subject: [PATCH] Improve translating posts via Mastodon api (#4463) This does 4 things: - Alt text is now translated when opening media of translated posts. Previously only the long-press alt text was translated. - The translate button is now hidden on non-public posts. The Mastodon api returns 403 there. - Translated posts will only be collapsible when the original was collapsible as well. It is just weird when an "show more" button suddenly appears because the post got longer by translating it. - The translation status and the untranslate button are now shown below each other instead of next to each other. Looks way better on smaller display or long texts. Before / After --- .../media/AccountMediaRemoteMediator.kt | 10 +++- .../conversation/ConversationsFragment.kt | 2 +- .../notifications/NotificationsFragment.kt | 2 +- .../report/adapter/AdapterHandler.kt | 3 +- .../report/adapter/StatusViewHolder.kt | 2 +- .../fragments/ReportStatusesFragment.kt | 39 ++++++------ .../fragments/SearchStatusesFragment.kt | 10 ++-- .../components/timeline/TimelineFragment.kt | 2 +- .../viewthread/ViewThreadFragment.kt | 2 +- .../keylesspalace/tusky/fragment/SFragment.kt | 5 +- .../tusky/viewdata/AttachmentViewData.kt | 14 ++--- .../tusky/viewdata/StatusViewData.kt | 4 +- app/src/main/res/layout/item_status.xml | 59 ++++++++----------- .../main/res/layout/item_status_detailed.xml | 52 +++++++--------- 14 files changed, 97 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/media/AccountMediaRemoteMediator.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/media/AccountMediaRemoteMediator.kt index f20f6ae73..dd8dae73c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/media/AccountMediaRemoteMediator.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/media/AccountMediaRemoteMediator.kt @@ -59,7 +59,15 @@ class AccountMediaRemoteMediator( } val attachments = statuses.flatMap { status -> - AttachmentViewData.list(status, activeAccount.alwaysShowSensitiveMedia) + status.attachments.map { attachment -> + AttachmentViewData( + attachment = attachment, + statusId = status.id, + statusUrl = status.url.orEmpty(), + sensitive = status.sensitive, + isRevealed = activeAccount.alwaysShowSensitiveMedia || !status.sensitive + ) + } } if (loadType == LoadType.REFRESH) { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt index 1cf0dea5b..3d15093f7 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt @@ -319,7 +319,7 @@ class ConversationsFragment : adapter.peek(position)?.let { conversation -> viewMedia( attachmentIndex, - AttachmentViewData.list(conversation.lastStatus.status), + AttachmentViewData.list(conversation.lastStatus), view ) } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt index 6bd076805..f9f01c49e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt @@ -397,7 +397,7 @@ class NotificationsFragment : } override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) { - val status = adapter.peek(position)?.asStatusOrNull()?.status ?: return + val status = adapter.peek(position)?.asStatusOrNull() ?: return super.viewMedia(attachmentIndex, AttachmentViewData.list(status), view) } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/AdapterHandler.kt b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/AdapterHandler.kt index fd150f91a..64e38db33 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/AdapterHandler.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/AdapterHandler.kt @@ -18,9 +18,10 @@ package com.keylesspalace.tusky.components.report.adapter import android.view.View import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.interfaces.LinkListener +import com.keylesspalace.tusky.viewdata.StatusViewData interface AdapterHandler : LinkListener { - fun showMedia(v: View?, status: Status?, idx: Int) + fun showMedia(v: View?, status: StatusViewData.Concrete, idx: Int) fun setStatusChecked(status: Status, isChecked: Boolean) fun isStatusChecked(id: String): Boolean } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt index f8db53107..239407523 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt @@ -59,7 +59,7 @@ class StatusViewHolder( private val previewListener = object : StatusViewHelper.MediaPreviewListener { override fun onViewMedia(v: View?, idx: Int) { viewdata()?.let { viewdata -> - adapterHandler.showMedia(v, viewdata.status, idx) + adapterHandler.showMedia(v, viewdata, idx) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt index bebd198de..ed3139c66 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt @@ -53,6 +53,7 @@ import com.keylesspalace.tusky.util.StatusDisplayOptions import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.viewdata.AttachmentViewData +import com.keylesspalace.tusky.viewdata.StatusViewData import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.utils.colorInt @@ -83,28 +84,26 @@ class ReportStatusesFragment : private var snackbarErrorRetry: Snackbar? = null - override fun showMedia(v: View?, status: Status?, idx: Int) { - status?.actionableStatus?.let { actionable -> - when (actionable.attachments[idx].type) { - Attachment.Type.GIFV, Attachment.Type.VIDEO, Attachment.Type.IMAGE, Attachment.Type.AUDIO -> { - val attachments = AttachmentViewData.list(actionable) - val intent = ViewMediaActivity.newIntent(context, attachments, idx) - if (v != null) { - val url = actionable.attachments[idx].url - ViewCompat.setTransitionName(v, url) - val options = ActivityOptionsCompat.makeSceneTransitionAnimation( - requireActivity(), - v, - url - ) - startActivity(intent, options.toBundle()) - } else { - startActivity(intent) - } - } - Attachment.Type.UNKNOWN -> { + override fun showMedia(v: View?, status: StatusViewData.Concrete, idx: Int) { + when (status.attachments[idx].type) { + Attachment.Type.GIFV, Attachment.Type.VIDEO, Attachment.Type.IMAGE, Attachment.Type.AUDIO -> { + val attachments = AttachmentViewData.list(status) + val intent = ViewMediaActivity.newIntent(context, attachments, idx) + if (v != null) { + val url = status.attachments[idx].url + ViewCompat.setTransitionName(v, url) + val options = ActivityOptionsCompat.makeSceneTransitionAnimation( + requireActivity(), + v, + url + ) + startActivity(intent, options.toBundle()) + } else { + startActivity(intent) } } + Attachment.Type.UNKNOWN -> { + } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt index 031daa1e9..d13e05457 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt @@ -182,17 +182,17 @@ class SearchStatusesFragment : SearchFragment(), Status } override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) { - searchAdapter.peek(position)?.status?.actionableStatus?.let { actionable -> - when (actionable.attachments[attachmentIndex].type) { + searchAdapter.peek(position)?.let { status -> + when (status.attachments[attachmentIndex].type) { Attachment.Type.GIFV, Attachment.Type.VIDEO, Attachment.Type.IMAGE, Attachment.Type.AUDIO -> { - val attachments = AttachmentViewData.list(actionable) + val attachments = AttachmentViewData.list(status) val intent = ViewMediaActivity.newIntent( context, attachments, attachmentIndex ) if (view != null) { - val url = actionable.attachments[attachmentIndex].url + val url = status.attachments[attachmentIndex].url ViewCompat.setTransitionName(view, url) val options = ActivityOptionsCompat.makeSceneTransitionAnimation( requireActivity(), @@ -206,7 +206,7 @@ class SearchStatusesFragment : SearchFragment(), Status } Attachment.Type.UNKNOWN -> { - context?.openLink(actionable.attachments[attachmentIndex].url) + context?.openLink(status.attachments[attachmentIndex].url) } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt index 6325a9e60..135cb0635 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt @@ -534,7 +534,7 @@ class TimelineFragment : val status = adapter.peek(position)?.asStatusOrNull() ?: return super.viewMedia( attachmentIndex, - AttachmentViewData.list(status.actionable), + AttachmentViewData.list(status), view ) } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt index 9726b7c1f..359438b10 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt @@ -381,7 +381,7 @@ class ViewThreadFragment : } override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) { - val status = adapter.currentList[position].status + val status = adapter.currentList[position] super.viewMedia( attachmentIndex, list(status, alwaysShowSensitiveMedia), diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.kt index a5e7b39ca..e9e147fa0 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.kt @@ -249,11 +249,12 @@ abstract class SFragment : Fragment() { ) } - // translation not there for your own posts + // translation not there for your own posts, posts already in your language or non-public posts menu.findItem(R.id.status_translate)?.let { translateItem -> translateItem.isVisible = onMoreTranslate != null && !status.language.equals(Locale.getDefault().language, ignoreCase = true) && - instanceInfoRepository.cachedInstanceInfoOrFallback.translationEnabled == true + instanceInfoRepository.cachedInstanceInfoOrFallback.translationEnabled == true && + (status.visibility == Status.Visibility.PUBLIC || status.visibility == Status.Visibility.UNLISTED) translateItem.setTitle(if (translation != null) R.string.action_show_original else R.string.action_translate) } diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt b/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt index 2626cfeef..1881c52ea 100644 --- a/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt +++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt @@ -17,7 +17,6 @@ package com.keylesspalace.tusky.viewdata import android.os.Parcelable import com.keylesspalace.tusky.entity.Attachment -import com.keylesspalace.tusky.entity.Status import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @@ -36,17 +35,16 @@ data class AttachmentViewData( companion object { @JvmStatic fun list( - status: Status, + status: StatusViewData.Concrete, alwaysShowSensitiveMedia: Boolean = false ): List { - val actionable = status.actionableStatus - return actionable.attachments.map { attachment -> + return status.attachments.map { attachment -> AttachmentViewData( attachment = attachment, - statusId = actionable.id, - statusUrl = actionable.url!!, - sensitive = actionable.sensitive, - isRevealed = alwaysShowSensitiveMedia || !actionable.sensitive + statusId = status.actionableId, + statusUrl = status.actionable.url!!, + sensitive = status.actionable.sensitive, + isRevealed = alwaysShowSensitiveMedia || !status.actionable.sensitive ) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt b/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt index 7647773eb..485467909 100644 --- a/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt +++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt @@ -82,10 +82,12 @@ sealed class StatusViewData { /** * Specifies whether the content of this post is long enough to be automatically * collapsed or if it should show all content regardless. + * Translated posts only show the button if the original post had it as well. * * @return Whether the post is collapsible or never collapsed. */ - val isCollapsible: Boolean = shouldTrimStatus(this.content) + val isCollapsible: Boolean = shouldTrimStatus(this.content) && + (translation == null || shouldTrimStatus(actionable.content.parseAsMastodonHtml())) val actionable: Status get() = status.actionableStatus diff --git a/app/src/main/res/layout/item_status.xml b/app/src/main/res/layout/item_status.xml index c022c2dba..ec066927d 100644 --- a/app/src/main/res/layout/item_status.xml +++ b/app/src/main/res/layout/item_status.xml @@ -103,46 +103,35 @@ app:layout_constraintTop_toTopOf="@id/status_display_name" tools:text="13:37" /> -