diff --git a/app/build.gradle b/app/build.gradle index b29bd11f3..c5c0297bf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,7 +43,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.0' implementation 'org.jsoup:jsoup:1.10.3' implementation 'com.github.stom79:country-picker-android:1.2.0' - implementation 'com.github.stom79:mytransl:1.1' + implementation 'com.github.stom79:mytransl:1.2' safetynetImplementation 'com.google.android.gms:play-services-safetynet:11.6.0' safetynetImplementation 'io.github.kobakei:ratethisapp:1.2.0' } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java index da5d82726..0aec895d7 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java @@ -1581,7 +1581,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc } @Override - public void onRetrieveEmoji(Status status) { + public void onRetrieveEmoji(Status status, boolean fromTranslation) { } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java index 60fd2e84e..b252e29e9 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java @@ -68,8 +68,6 @@ public class Status implements Parcelable { private String in_reply_to_id; private String in_reply_to_account_id; private Status reblog; - private String content; - private String content_translated; private Date created_at; private int reblogs_count; private int favourites_count; @@ -77,7 +75,6 @@ public class Status implements Parcelable { private boolean favourited; private boolean pinned; private boolean sensitive; - private String spoiler_text; private String visibility; private boolean attachmentShown = false; private boolean spoilerShown = false; @@ -90,12 +87,14 @@ public class Status implements Parcelable { private String language; private boolean isTranslated = false; private boolean isEmojiFound = false; + private boolean isEmojiTranslateFound = false; private boolean isClickable = false; private boolean isTranslationShown = false; private boolean isNew = false; private boolean isTakingScreenShot = false; private boolean isVisible = true; private Status status; + private String content, contentCW, contentTranslated; private SpannableString contentSpan, contentSpanCW, contentSpanTranslated; @@ -113,13 +112,13 @@ public class Status implements Parcelable { account = in.readParcelable(Account.class.getClassLoader()); mentions = in.readArrayList(Mention.class.getClassLoader()); content = in.readString(); - content_translated = in.readString(); + contentTranslated = in.readString(); reblogs_count = in.readInt(); favourites_count = in.readInt(); reblogged = in.readByte() != 0; favourited = in.readByte() != 0; sensitive = in.readByte() != 0; - spoiler_text = in.readString(); + contentCW = in.readString(); visibility = in.readString(); language = in.readString(); attachmentShown = in.readByte() != 0; @@ -261,11 +260,11 @@ public class Status implements Parcelable { } public String getSpoiler_text() { - return spoiler_text; + return contentCW; } public void setSpoiler_text(String spoiler_text) { - this.spoiler_text = spoiler_text; + this.contentCW = spoiler_text; } @@ -334,13 +333,13 @@ public class Status implements Parcelable { dest.writeParcelable(account, flags); dest.writeList(mentions); dest.writeString(content); - dest.writeString(content_translated); + dest.writeString(contentTranslated); dest.writeInt(reblogs_count); dest.writeInt(favourites_count); dest.writeByte((byte) (reblogged ? 1 : 0)); dest.writeByte((byte) (favourited ? 1 : 0)); dest.writeByte((byte) (sensitive ? 1 : 0)); - dest.writeString(spoiler_text); + dest.writeString(contentCW); dest.writeString(visibility); dest.writeString(language); dest.writeByte((byte) (attachmentShown ? 1 : 0)); @@ -383,12 +382,12 @@ public class Status implements Parcelable { isTranslationShown = translationShown; } - public String getContent_translated() { - return content_translated; + public String getContentTranslated() { + return contentTranslated; } - public void setContent_translated(String content_translated) { - this.content_translated = content_translated; + public void setContentTranslated(String content_translated) { + this.contentTranslated = content_translated; } public List getReplies() { @@ -465,10 +464,10 @@ public class Status implements Parcelable { SpannableString spannableStringTranslated; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContent_translated(), Html.FROM_HTML_MODE_LEGACY)); + spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated(), Html.FROM_HTML_MODE_LEGACY)); else //noinspection deprecation - spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContent_translated())); + spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated())); status.setContentSpanTranslated(treatment(context, spannableStringTranslated)); } @@ -479,7 +478,6 @@ public class Status implements Parcelable { final SpannableString spannableStringContent; final SpannableString spannableStringCW; - SpannableString spannableStringTranslated = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) @@ -495,19 +493,11 @@ public class Status implements Parcelable { //noinspection deprecation spannableStringCW = new SpannableString(Html.fromHtml(status.getReblog() != null ?status.getReblog().getSpoiler_text():status.getSpoiler_text())); - if( status.getContent_translated() != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContent_translated(), Html.FROM_HTML_MODE_LEGACY)); - else - //noinspection deprecation - spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContent_translated())); - } final List emojis = status.getReblog() != null ? status.getReblog().getEmojis() : status.getEmojis(); if( emojis != null && emojis.size() > 0 ) { final int[] i = {0}; for (final Emojis emoji : emojis) { - final SpannableString finalSpannableStringTranslated = spannableStringTranslated; Glide.with(context) .asBitmap() .load(emoji.getUrl()) @@ -523,9 +513,7 @@ public class Status implements Parcelable { if( i[0] == (emojis.size())) { status.setContentSpan(spannableStringContent); status.setContentSpanCW(spannableStringCW); - if( finalSpannableStringTranslated != null) - status.setContentSpanTranslated(finalSpannableStringTranslated); - listener.onRetrieveEmoji(status); + listener.onRetrieveEmoji(status,false); } return false; } @@ -556,6 +544,63 @@ public class Status implements Parcelable { endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } } + i[0]++; + if( i[0] == (emojis.size())) { + status.setContentSpan(spannableStringContent); + status.setContentSpanCW(spannableStringCW); + listener.onRetrieveEmoji(status, false); + } + } + }); + + } + } + } + + + public void makeEmojisTranslation(final Context context, final OnRetrieveEmojiInterface listener){ + + SpannableString spannableStringTranslated = null; + + + if( status.getContentTranslated() != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated(), Html.FROM_HTML_MODE_LEGACY)); + else + //noinspection deprecation + spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated())); + } + + final List emojis = status.getReblog() != null ? status.getReblog().getEmojis() : status.getEmojis(); + if( emojis != null && emojis.size() > 0 ) { + final int[] i = {0}; + for (final Emojis emoji : emojis) { + final SpannableString finalSpannableStringTranslated = spannableStringTranslated; + Glide.with(context) + .asBitmap() + .load(emoji.getUrl()) + .listener(new RequestListener() { + @Override + public boolean onResourceReady(Bitmap resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + return false; + } + + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + i[0]++; + if( i[0] == (emojis.size())) { + if( finalSpannableStringTranslated != null) + status.setContentSpanTranslated(finalSpannableStringTranslated); + listener.onRetrieveEmoji(status, true); + } + return false; + } + }) + .into(new SimpleTarget() { + @Override + public void onResourceReady(Bitmap resource, Transition transition) { + final String targetedEmoji = ":" + emoji.getShortcode() + ":"; + if (finalSpannableStringTranslated != null && finalSpannableStringTranslated.toString().contains(targetedEmoji)) { //emojis can be used several times so we have to loop for (int startPosition = -1; (startPosition = finalSpannableStringTranslated.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) { @@ -569,11 +614,9 @@ public class Status implements Parcelable { } i[0]++; if( i[0] == (emojis.size())) { - status.setContentSpan(spannableStringContent); - status.setContentSpanCW(spannableStringCW); if( finalSpannableStringTranslated != null) status.setContentSpanTranslated(finalSpannableStringTranslated); - listener.onRetrieveEmoji(status); + listener.onRetrieveEmoji(status, true); } } }); @@ -586,7 +629,7 @@ public class Status implements Parcelable { private SpannableString treatment(final Context context, final SpannableString spannableString){ - List mentions = status.getReblog() != null ? status.getReblog().getMentions() : status.getMentions(); + List mentions = this.status.getReblog() != null ? this.status.getReblog().getMentions() : this.status.getMentions(); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); boolean embedded_browser = sharedpreferences.getBoolean(Helper.SET_EMBEDDED_BROWSER, true); if( embedded_browser){ @@ -702,4 +745,12 @@ public class Status implements Parcelable { public boolean isClickable() { return isClickable; } + + public boolean isEmojiTranslateFound() { + return isEmojiTranslateFound; + } + + public void setEmojiTranslateFound(boolean emojiTranslateFound) { + isEmojiTranslateFound = emojiTranslateFound; + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java index dd8e4a416..6e6624e58 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java @@ -32,7 +32,6 @@ import android.support.v4.content.ContextCompat; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; import android.text.Html; -import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.util.TypedValue; import android.view.LayoutInflater; @@ -906,7 +905,7 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On @Override - public void onRetrieveEmoji(Status status) { + public void onRetrieveEmoji(Status status, boolean fromTranslation) { if( !status.isEmojiFound()) { for (int i = 0; i < notificationsListAdapter.getItemCount(); i++) { if (notificationsListAdapter.getItemAt(i) != null && notificationsListAdapter.getItemAt(i).getStatus() != null && notificationsListAdapter.getItemAt(i).getStatus().getId().equals(status.getId())) { diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java index 970ba655d..16a6c0d8a 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java @@ -388,7 +388,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct holder.new_element.setVisibility(View.GONE); int iconSizePercent = sharedpreferences.getInt(Helper.SET_ICON_SIZE, 130); int textSizePercent = sharedpreferences.getInt(Helper.SET_TEXT_SIZE, 110); - boolean trans_forced = sharedpreferences.getBoolean(Helper.SET_TRANS_FORCED, false); + final boolean trans_forced = sharedpreferences.getBoolean(Helper.SET_TRANS_FORCED, false); holder.status_more.getLayoutParams().height = (int) Helper.convertDpToPixel((20*iconSizePercent/100), context); holder.status_more.getLayoutParams().width = (int) Helper.convertDpToPixel((20*iconSizePercent/100), context); holder.status_privacy.getLayoutParams().height = (int) Helper.convertDpToPixel((20*iconSizePercent/100), context); @@ -464,8 +464,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct if( !status.isEmojiFound()) status.makeEmojis(context, StatusListAdapter.this); - holder.status_content.setText(status.getContentSpan()); - holder.status_spoiler.setText(status.getContentSpanCW()); + holder.status_content.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE); + holder.status_spoiler.setText(status.getContentSpanCW(), TextView.BufferType.SPANNABLE); //Manages translations @@ -476,16 +476,23 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct @Override public void onClick(View v) { if( !status.isTranslated() ){ - myTransL.translate(status.getContent(), myTransL.getLocale(), new Results() { + String statusToTranslate; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + statusToTranslate = Html.fromHtml(status.getReblog() != null ?status.getReblog().getContent():status.getContent(), Html.FROM_HTML_MODE_LEGACY).toString(); + else + //noinspection deprecation + statusToTranslate = Html.fromHtml(status.getReblog() != null ?status.getReblog().getContent():status.getContent()).toString(); + + myTransL.translate(statusToTranslate, myTransL.getLocale(), new Results() { @Override public void onSuccess(Translate translate) { if( translate.getTranslatedContent() != null) { status.setTranslated(true); status.setTranslationShown(true); - status.setContent_translated(translate.getTranslatedContent()); + status.setContentTranslated(translate.getTranslatedContent()); status.makeClickableTranslation(context); - holder.status_content_translated.setMovementMethod(LinkMovementMethod.getInstance()); - statusListAdapter.notifyDataSetChanged(); + status.makeEmojisTranslation(context, StatusListAdapter.this); + notifyStatusChanged(status); }else { Toast.makeText(context, R.string.toast_error_translate, Toast.LENGTH_LONG).show(); } @@ -497,7 +504,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct }); }else { status.setTranslationShown(!status.isTranslationShown()); - statusListAdapter.notifyDataSetChanged(); + notifyStatusChanged(status); } } }); @@ -710,12 +717,14 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/DroidSans-Regular.ttf"); holder.status_content.setTypeface(tf); - + holder.status_content_translated.setTypeface(tf); //Toot was translated and user asked to see it - if( status.isTranslationShown()){ + + if( status.isTranslationShown() && status.getContentSpanTranslated() != null){ + holder.status_content_translated.setText(status.getContentSpanTranslated(), TextView.BufferType.SPANNABLE); + holder.status_content_translated.setMovementMethod(LinkMovementMethod.getInstance()); holder.status_content.setVisibility(View.GONE); holder.status_content_translated_container.setVisibility(View.VISIBLE); - holder.status_content_translated.setTypeface(tf); }else { //Toot is not translated holder.status_content.setVisibility(View.VISIBLE); holder.status_content_translated_container.setVisibility(View.GONE); @@ -1368,17 +1377,39 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct } } + private void notifyStatusChanged(Status status){ + for (int i = 0; i < statusListAdapter.getItemCount(); i++) { + if (statusListAdapter.getItemAt(i) != null && statusListAdapter.getItemAt(i).getId().equals(status.getId())) { + try { + statusListAdapter.notifyItemChanged(i); + } catch (Exception ignored) { + } + } + } + } + @Override - public void onRetrieveEmoji(Status status) { - if( !status.isEmojiFound()) { - for (int i = 0; i < statusListAdapter.getItemCount(); i++) { - if (statusListAdapter.getItemAt(i) != null && statusListAdapter.getItemAt(i).getId().equals(status.getId())) { - if( statusListAdapter.getItemAt(i) != null) { + public void onRetrieveEmoji(Status status, boolean fromTranslation) { + if( !fromTranslation) { + if (!status.isEmojiFound()) { + for (int i = 0; i < statusListAdapter.getItemCount(); i++) { + if (statusListAdapter.getItemAt(i) != null && statusListAdapter.getItemAt(i).getId().equals(status.getId())) { statusListAdapter.getItemAt(i).setEmojiFound(true); try { statusListAdapter.notifyItemChanged(i); - }catch (Exception ignored){} + } catch (Exception ignored) {} + } + } + } + }else { + if (!status.isEmojiTranslateFound()) { + for (int i = 0; i < statusListAdapter.getItemCount(); i++) { + if (statusListAdapter.getItemAt(i) != null && statusListAdapter.getItemAt(i).getId().equals(status.getId())) { + statusListAdapter.getItemAt(i).setEmojiTranslateFound(true); + try { + statusListAdapter.notifyItemChanged(i); + } catch (Exception ignored) {} } } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveEmojiInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveEmojiInterface.java index 93db54d18..43469eb9e 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveEmojiInterface.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveEmojiInterface.java @@ -27,6 +27,6 @@ import fr.gouv.etalab.mastodon.client.Entities.Status; * Interface when retrieving emojis */ public interface OnRetrieveEmojiInterface { - void onRetrieveEmoji(Status status); + void onRetrieveEmoji(Status status, boolean fromTranslation); void onRetrieveSearchEmoji(List emojis); }