Merge pull request #734 from FineFindus/feat/translate-media-upstream
Allow translation of attachments, spoilers and polls
This commit is contained in:
@@ -357,7 +357,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
|
||||
int prevSize=pollItems.size();
|
||||
pollItems.clear();
|
||||
StatusDisplayItem.buildPollItems(itemID, this, poll, pollItems);
|
||||
StatusDisplayItem.buildPollItems(itemID, this, poll, status, pollItems);
|
||||
if(prevSize!=pollItems.size()){
|
||||
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
|
||||
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());
|
||||
@@ -586,11 +586,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
return;
|
||||
status.translation=result;
|
||||
status.translationState=Status.TranslationState.SHOWN;
|
||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||
if(text!=null){
|
||||
text.updateTranslation(true);
|
||||
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
||||
}
|
||||
updateTranslation(itemID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -598,10 +594,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
if(getActivity()==null)
|
||||
return;
|
||||
status.translationState=Status.TranslationState.HIDDEN;
|
||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||
if(text!=null){
|
||||
text.updateTranslation(true);
|
||||
}
|
||||
updateTranslation(itemID);
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.translation_failed)
|
||||
@@ -613,11 +606,31 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
}
|
||||
}
|
||||
}
|
||||
updateTranslation(itemID);
|
||||
}
|
||||
|
||||
private void updateTranslation(String itemID) {
|
||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||
if(text!=null){
|
||||
text.updateTranslation(true);
|
||||
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
||||
}
|
||||
|
||||
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
||||
if(spoiler!=null){
|
||||
spoiler.rebind();
|
||||
}
|
||||
|
||||
MediaGridStatusDisplayItem.Holder media=findHolderOfType(itemID, MediaGridStatusDisplayItem.Holder.class);
|
||||
if (media!=null) {
|
||||
media.rebind();
|
||||
}
|
||||
|
||||
for(int i=0;i<list.getChildCount();i++){
|
||||
if(list.getChildViewHolder(list.getChildAt(i)) instanceof PollOptionStatusDisplayItem.Holder item){
|
||||
item.rebind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void rebuildAllDisplayItems(){
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import org.joinmastodon.android.api.AllFieldsAreRequired;
|
||||
|
||||
@AllFieldsAreRequired
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
|
||||
public class Translation extends BaseModel{
|
||||
@RequiredField
|
||||
public String content;
|
||||
@RequiredField
|
||||
public String detectedSourceLanguage;
|
||||
@RequiredField
|
||||
public String provider;
|
||||
public String spoilerText;
|
||||
public MediaAttachment[] mediaAttachments;
|
||||
public PollTranslation poll;
|
||||
|
||||
public static class MediaAttachment {
|
||||
public String id;
|
||||
public String description;
|
||||
}
|
||||
|
||||
public static class PollTranslation {
|
||||
public String id;
|
||||
public PollOption[] options;
|
||||
}
|
||||
|
||||
public static class PollOption {
|
||||
public String title;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -21,6 +22,8 @@ import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.model.Translation;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
||||
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
||||
@@ -31,7 +34,12 @@ import org.joinmastodon.android.ui.views.MediaGridLayout;
|
||||
import org.joinmastodon.android.utils.TypedObjectPool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
@@ -45,6 +53,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||
private final PhotoLayoutHelper.TiledLayoutResult tiledLayout;
|
||||
private final TypedObjectPool<GridItemType, MediaAttachmentViewController> viewPool;
|
||||
private final List<Attachment> attachments;
|
||||
private final Map<String, Pair<String, String>> translatedAttachments = new HashMap<>();
|
||||
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
|
||||
public final Status status;
|
||||
public boolean sensitiveRevealed;
|
||||
@@ -181,6 +190,25 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||
c.altButton.setAlpha(1f);
|
||||
}
|
||||
controllers.add(c);
|
||||
|
||||
if (item.status.translation != null){
|
||||
if(item.status.translationState==Status.TranslationState.SHOWN){
|
||||
if(!item.translatedAttachments.containsKey(att.id)){
|
||||
Optional<Translation.MediaAttachment> translatedAttachment=Arrays.stream(item.status.translation.mediaAttachments).filter(mediaAttachment->mediaAttachment.id.equals(att.id)).findFirst();
|
||||
translatedAttachment.ifPresent(mediaAttachment->{
|
||||
item.translatedAttachments.put(mediaAttachment.id, new Pair<>(att.description, mediaAttachment.description));
|
||||
att.description=mediaAttachment.description;
|
||||
});
|
||||
}else{
|
||||
//SAFETY: must be non-null, as we check if the map contains the attachment before
|
||||
att.description=Objects.requireNonNull(item.translatedAttachments.get(att.id)).second;
|
||||
}
|
||||
}else{
|
||||
if (item.translatedAttachments.containsKey(att.id)) {
|
||||
att.description=Objects.requireNonNull(item.translatedAttachments.get(att.id)).first;
|
||||
}
|
||||
}
|
||||
}
|
||||
c.bind(att, item.status);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.widget.TextView;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Poll;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
@@ -22,6 +23,7 @@ import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
|
||||
public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||
private CharSequence text;
|
||||
private CharSequence translatedText;
|
||||
public final Poll.Option option;
|
||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||
private boolean showResults;
|
||||
@@ -29,12 +31,15 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||
private boolean isMostVoted;
|
||||
private final int optionIndex;
|
||||
public final Poll poll;
|
||||
public final Status status;
|
||||
|
||||
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment){
|
||||
|
||||
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment, Status status){
|
||||
super(parentID, parentFragment);
|
||||
this.optionIndex=optionIndex;
|
||||
option=poll.options.get(optionIndex);
|
||||
this.poll=poll;
|
||||
this.status=status;
|
||||
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
||||
emojiHelper.setText(text);
|
||||
showResults=poll.isExpired() || poll.voted;
|
||||
@@ -83,7 +88,14 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
@Override
|
||||
public void onBind(PollOptionStatusDisplayItem item){
|
||||
text.setText(item.text);
|
||||
if (item.status.translation != null && item.status.translationState == Status.TranslationState.SHOWN) {
|
||||
if(item.translatedText==null){
|
||||
item.translatedText=item.status.translation.poll.options[item.optionIndex].title;
|
||||
}
|
||||
text.setText(item.translatedText);
|
||||
} else {
|
||||
text.setText(item.text);
|
||||
}
|
||||
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
||||
itemView.setClickable(!item.showResults);
|
||||
if(item.showResults){
|
||||
|
||||
@@ -26,6 +26,7 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
|
||||
public final Status status;
|
||||
public final ArrayList<StatusDisplayItem> contentItems=new ArrayList<>();
|
||||
private final CharSequence parsedTitle;
|
||||
private CharSequence translatedTitle;
|
||||
private final CustomEmojiHelper emojiHelper;
|
||||
private final Type type;
|
||||
|
||||
@@ -85,7 +86,14 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
@Override
|
||||
public void onBind(SpoilerStatusDisplayItem item){
|
||||
title.setText(item.parsedTitle);
|
||||
if(item.status.translationState==Status.TranslationState.SHOWN){
|
||||
if(item.translatedTitle==null){
|
||||
item.translatedTitle=item.status.translation.spoilerText;
|
||||
}
|
||||
title.setText(item.translatedTitle);
|
||||
}else{
|
||||
title.setText(item.parsedTitle);
|
||||
}
|
||||
action.setText(item.status.spoilerRevealed ? R.string.spoiler_hide : R.string.spoiler_show);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ public abstract class StatusDisplayItem{
|
||||
}
|
||||
}
|
||||
if(statusForContent.poll!=null){
|
||||
buildPollItems(parentID, fragment, statusForContent.poll, contentItems);
|
||||
buildPollItems(parentID, fragment, statusForContent.poll, status, contentItems);
|
||||
}
|
||||
if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty() && TextUtils.isEmpty(statusForContent.spoilerText)){
|
||||
contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
|
||||
@@ -192,10 +192,10 @@ public abstract class StatusDisplayItem{
|
||||
return items;
|
||||
}
|
||||
|
||||
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
|
||||
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, Status status, List<StatusDisplayItem> items){
|
||||
int i=0;
|
||||
for(Poll.Option opt:poll.options){
|
||||
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment));
|
||||
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment, status));
|
||||
i++;
|
||||
}
|
||||
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll));
|
||||
|
||||
Reference in New Issue
Block a user