Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve translating posts via Mastodon api #4463

Merged
merged 6 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ class ConversationsFragment :
adapter.peek(position)?.let { conversation ->
viewMedia(
attachmentIndex,
AttachmentViewData.list(conversation.lastStatus.status),
AttachmentViewData.list(conversation.lastStatus),
view
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -80,28 +81,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 -> {
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,17 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), 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(),
Expand All @@ -206,7 +206,7 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
}

Attachment.Type.UNKNOWN -> {
context?.openLink(actionable.attachments[attachmentIndex].url)
context?.openLink(status.attachments[attachmentIndex].url)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ class TimelineFragment :
val status = adapter.peek(position)?.asStatusOrNull() ?: return
super.viewMedia(
attachmentIndex,
AttachmentViewData.list(status.actionable),
AttachmentViewData.list(status),
view
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -36,17 +35,16 @@ data class AttachmentViewData(
companion object {
@JvmStatic
fun list(
status: Status,
status: StatusViewData.Concrete,
alwaysShowSensitiveMedia: Boolean = false
): List<AttachmentViewData> {
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
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
59 changes: 24 additions & 35 deletions app/src/main/res/layout/item_status.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,46 +103,35 @@
app:layout_constraintTop_toTopOf="@id/status_display_name"
tools:text="13:37" />

<Button
android:id="@+id/status_button_untranslate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_show_original"
style="@style/TuskyButton.TextButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/status_translation_status"
app:layout_constraintBottom_toBottomOf="@id/status_translation_status"
android:layout_marginEnd="10dp"
android:visibility="gone"
tools:visibility="visible"
android:minHeight="0dp" />

<TextView
android:id="@+id/status_translation_status"
style="@style/TextSizeSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
style="@style/TextSizeSmall"
tools:text="Translated from Lang by Service"
app:layout_constraintStart_toStartOf="@id/status_display_name"
app:layout_constraintEnd_toStartOf="@id/status_button_untranslate"
app:layout_constraintTop_toBottomOf="@id/status_username"
android:layout_marginEnd="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="10dp"
android:lineSpacingMultiplier="1.1"
android:maxLines="4"
android:visibility="gone"
tools:visibility="visible"
android:minLines="2"
android:lineSpacingMultiplier="1.1"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
app:layout_constraintBottom_toTopOf="@id/status_translation_barrier"
/>
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/status_display_name"
app:layout_constraintTop_toBottomOf="@id/status_username"
tools:text="Translated from Lang by Service"
tools:visibility="visible" />

<androidx.constraintlayout.widget.Barrier
android:id="@+id/status_translation_barrier"
android:layout_width="match_parent"
<Button
android:id="@+id/status_button_untranslate"
style="@style/TuskyButton.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="status_translation_status, status_button_untranslate" />
android:paddingHorizontal="0dp"
android:layout_marginEnd="10dp"
android:minHeight="0dp"
android:text="@string/action_show_original"
android:visibility="gone"
app:layout_constraintStart_toStartOf="@id/status_display_name"
app:layout_constraintTop_toBottomOf="@id/status_translation_status"
tools:visibility="visible" />

<com.keylesspalace.tusky.view.ClickableSpanTextView
android:id="@+id/status_content_warning_description"
Expand All @@ -157,7 +146,7 @@
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/status_display_name"
app:layout_constraintTop_toBottomOf="@id/status_translation_barrier"
app:layout_constraintTop_toBottomOf="@id/status_button_untranslate"
tools:text="content warning which is very long and it doesn't fit"
tools:visibility="visible" />

Expand Down Expand Up @@ -359,13 +348,13 @@
android:layout_marginStart="-14dp"
android:contentDescription="@string/action_reply"
android:importantForAccessibility="no"
tools:ignore="NegativeMargin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/status_inset"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="@id/status_display_name"
app:layout_constraintTop_toBottomOf="@id/status_poll_description"
app:srcCompat="@drawable/ic_reply_24dp" />
app:srcCompat="@drawable/ic_reply_24dp"
tools:ignore="NegativeMargin" />

<TextView
android:id="@+id/status_replies"
Expand Down
52 changes: 21 additions & 31 deletions app/src/main/res/layout/item_status_detailed.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,45 +78,35 @@
app:layout_constraintTop_toBottomOf="@id/status_display_name"
tools:text="\@ConnyDuck\@mastodon.social" />

<Button
android:id="@+id/status_button_untranslate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_show_original"
app:layout_constraintTop_toTopOf="@id/status_translation_status"
app:layout_constraintBottom_toBottomOf="@id/status_translation_status"
style="@style/TuskyButton.TextButton"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="14dp"
android:minHeight="0dp"
android:visibility="gone"
tools:visibility="visible" />

<TextView
android:id="@+id/status_translation_status"
style="@style/TextSizeSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
style="@style/TextSizeSmall"
android:layout_marginStart="14dp"
tools:text="Translated from blah using service"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_avatar"
app:layout_constraintEnd_toStartOf="@id/status_button_untranslate"
android:minLines="2"
android:layout_marginTop="8dp"
android:layout_marginEnd="14dp"
android:lineSpacingMultiplier="1.1"
android:gravity="center_vertical"
android:layout_marginTop="4dp"
android:visibility="gone"
tools:visibility="visible"
android:layout_marginEnd="4dp"/>
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_avatar"
tools:text="Translated from blah using service"
tools:visibility="visible" />

<androidx.constraintlayout.widget.Barrier
android:id="@+id/status_translation_barrier"
android:layout_width="match_parent"
<Button
android:id="@+id/status_button_untranslate"
style="@style/TuskyButton.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="status_translation_status, status_button_untranslate" />

android:layout_marginStart="14dp"
android:layout_marginEnd="14dp"
android:minHeight="0dp"
android:paddingHorizontal="0dp"
android:text="@string/action_show_original"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_translation_status"
tools:visibility="visible" />

<com.keylesspalace.tusky.view.ClickableSpanTextView
android:id="@+id/status_content_warning_description"
Expand All @@ -133,7 +123,7 @@
android:textSize="?attr/status_text_large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_translation_barrier"
app:layout_constraintTop_toBottomOf="@id/status_button_untranslate"
tools:text="CW this is a long long long long long long long long content warning" />

<com.google.android.material.button.MaterialButton
Expand Down
Loading