parent
c757b1ffea
commit
29ad08f2ea
|
@ -70,6 +70,7 @@ dependencies {
|
||||||
implementation 'com.squareup:otto:1.3.8'
|
implementation 'com.squareup:otto:1.3.8'
|
||||||
implementation 'de.psdev:async-otto:1.0.3'
|
implementation 'de.psdev:async-otto:1.0.3'
|
||||||
implementation 'org.parceler:parceler-api:1.1.12'
|
implementation 'org.parceler:parceler-api:1.1.12'
|
||||||
|
implementation 'com.github.bottom-software-foundation:bottom-java:2.1.0'
|
||||||
annotationProcessor 'org.parceler:parceler:1.1.12'
|
annotationProcessor 'org.parceler:parceler:1.1.12'
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class GlobalUserPreferences{
|
||||||
public static boolean showAltIndicator;
|
public static boolean showAltIndicator;
|
||||||
public static boolean showNoAltIndicator;
|
public static boolean showNoAltIndicator;
|
||||||
public static boolean enablePreReleases;
|
public static boolean enablePreReleases;
|
||||||
|
public static boolean bottomEncoding;
|
||||||
public static String publishButtonText;
|
public static String publishButtonText;
|
||||||
public static ThemePreference theme;
|
public static ThemePreference theme;
|
||||||
public static ColorPreference color;
|
public static ColorPreference color;
|
||||||
|
@ -83,6 +84,7 @@ public class GlobalUserPreferences{
|
||||||
showAltIndicator=prefs.getBoolean("showAltIndicator", true);
|
showAltIndicator=prefs.getBoolean("showAltIndicator", true);
|
||||||
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
|
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
|
||||||
enablePreReleases=prefs.getBoolean("enablePreReleases", false);
|
enablePreReleases=prefs.getBoolean("enablePreReleases", false);
|
||||||
|
bottomEncoding=prefs.getBoolean("bottomEncoding", false);
|
||||||
publishButtonText=prefs.getString("publishButtonText", "");
|
publishButtonText=prefs.getString("publishButtonText", "");
|
||||||
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
|
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
|
||||||
recentLanguages=fromJson(prefs.getString("recentLanguages", null), recentLanguagesType, new HashMap<>());
|
recentLanguages=fromJson(prefs.getString("recentLanguages", null), recentLanguagesType, new HashMap<>());
|
||||||
|
@ -121,6 +123,7 @@ public class GlobalUserPreferences{
|
||||||
.putBoolean("showNoAltIndicator", showNoAltIndicator)
|
.putBoolean("showNoAltIndicator", showNoAltIndicator)
|
||||||
.putBoolean("enablePreReleases", enablePreReleases)
|
.putBoolean("enablePreReleases", enablePreReleases)
|
||||||
.putString("publishButtonText", publishButtonText)
|
.putString("publishButtonText", publishButtonText)
|
||||||
|
.putBoolean("bottomEncoding", bottomEncoding)
|
||||||
.putInt("theme", theme.ordinal())
|
.putInt("theme", theme.ordinal())
|
||||||
.putString("color", color.name())
|
.putString("color", color.name())
|
||||||
.putString("recentLanguages", gson.toJson(recentLanguages))
|
.putString("recentLanguages", gson.toJson(recentLanguages))
|
||||||
|
|
|
@ -154,6 +154,7 @@ public class MainActivity extends FragmentStackActivity{
|
||||||
);
|
);
|
||||||
Bundle currentArgs = currentFragment.getArguments();
|
Bundle currentArgs = currentFragment.getArguments();
|
||||||
if (this.fragmentContainers.size() == 1
|
if (this.fragmentContainers.size() == 1
|
||||||
|
&& currentArgs != null
|
||||||
&& currentArgs.getBoolean("_can_go_back", false)
|
&& currentArgs.getBoolean("_can_go_back", false)
|
||||||
&& currentArgs.containsKey("account")) {
|
&& currentArgs.containsKey("account")) {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
|
@ -42,6 +42,7 @@ import android.text.TextWatcher;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
@ -66,6 +67,7 @@ import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.github.bottomSoftwareFoundation.bottom.Bottom;
|
||||||
import com.twitter.twittertext.TwitterTextEmojiRegex;
|
import com.twitter.twittertext.TwitterTextEmojiRegex;
|
||||||
|
|
||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
|
@ -115,6 +117,7 @@ import org.joinmastodon.android.ui.views.LinkedTextView;
|
||||||
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
|
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
|
||||||
import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
|
import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
|
||||||
import org.joinmastodon.android.utils.MastodonLanguage;
|
import org.joinmastodon.android.utils.MastodonLanguage;
|
||||||
|
import org.joinmastodon.android.utils.StringEncoder;
|
||||||
import org.parceler.Parcel;
|
import org.parceler.Parcel;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
@ -155,11 +158,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
private static final Pattern GLITCH_LOCAL_ONLY_PATTERN = Pattern.compile("[\\s\\S]*" + GLITCH_LOCAL_ONLY_SUFFIX + "[\uFE00-\uFE0F]*");
|
private static final Pattern GLITCH_LOCAL_ONLY_PATTERN = Pattern.compile("[\\s\\S]*" + GLITCH_LOCAL_ONLY_SUFFIX + "[\uFE00-\uFE0F]*");
|
||||||
private static final String TAG="ComposeFragment";
|
private static final String TAG="ComposeFragment";
|
||||||
|
|
||||||
private static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
|
public static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
// from https://github.com/mastodon/mastodon-ios/blob/main/Mastodon/Helper/MastodonRegex.swift
|
// from https://github.com/mastodon/mastodon-ios/blob/main/Mastodon/Helper/MastodonRegex.swift
|
||||||
private static final Pattern AUTO_COMPLETE_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+)|:([a-zA-Z0-9_]+))");
|
public static final Pattern AUTO_COMPLETE_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+)|:([a-zA-Z0-9_]+))");
|
||||||
private static final Pattern HIGHLIGHT_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))");
|
public static final Pattern HIGHLIGHT_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))");
|
||||||
|
|
||||||
@SuppressLint("NewApi") // this class actually exists on 6.0
|
@SuppressLint("NewApi") // this class actually exists on 6.0
|
||||||
private final BreakIterator breakIterator=BreakIterator.getCharacterInstance();
|
private final BreakIterator breakIterator=BreakIterator.getCharacterInstance();
|
||||||
|
@ -229,7 +232,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
private boolean ignoreSelectionChanges=false;
|
private boolean ignoreSelectionChanges=false;
|
||||||
private Runnable updateUploadEtaRunnable;
|
private Runnable updateUploadEtaRunnable;
|
||||||
|
|
||||||
private String language;
|
private String language, encoding;
|
||||||
private MastodonLanguage.LanguageResolver languageResolver;
|
private MastodonLanguage.LanguageResolver languageResolver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -835,9 +838,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLanguage(MastodonLanguage loc) {
|
private void updateLanguage(MastodonLanguage loc) {
|
||||||
language = loc.getLanguage();
|
updateLanguage(loc.getLanguage(), loc.getLanguageName(), loc.getDefaultName());
|
||||||
languageButton.setText(loc.getLanguageName());
|
}
|
||||||
languageButton.setContentDescription(getActivity().getString(R.string.sk_post_language, loc.getDefaultName()));
|
|
||||||
|
private void updateLanguage(String languageTag, String languageName, String defaultName) {
|
||||||
|
language = languageTag;
|
||||||
|
languageButton.setText(languageName);
|
||||||
|
languageButton.setContentDescription(getActivity().getString(R.string.sk_post_language, defaultName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@ -854,9 +861,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
|
|
||||||
Menu languageMenu = languagePopup.getMenu();
|
Menu languageMenu = languagePopup.getMenu();
|
||||||
for (String recentLanguage : Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)) {
|
for (String recentLanguage : Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)) {
|
||||||
|
if (recentLanguage.equals("bottom")) {
|
||||||
|
addBottomLanguage(languageMenu);
|
||||||
|
} else {
|
||||||
MastodonLanguage l = languageResolver.from(recentLanguage);
|
MastodonLanguage l = languageResolver.from(recentLanguage);
|
||||||
languageMenu.add(0, allLanguages.indexOf(l), Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
|
languageMenu.add(0, allLanguages.indexOf(l), Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SubMenu allLanguagesMenu = languageMenu.addSubMenu(R.string.sk_available_languages);
|
SubMenu allLanguagesMenu = languageMenu.addSubMenu(R.string.sk_available_languages);
|
||||||
for (int i = 0; i < allLanguages.size(); i++) {
|
for (int i = 0; i < allLanguages.size(); i++) {
|
||||||
|
@ -864,13 +875,35 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
allLanguagesMenu.add(0, i, Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
|
allLanguagesMenu.add(0, i, Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GlobalUserPreferences.bottomEncoding) addBottomLanguage(allLanguagesMenu);
|
||||||
|
|
||||||
|
btn.setOnLongClickListener(v->{
|
||||||
|
btn.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||||
|
if (!GlobalUserPreferences.bottomEncoding) {
|
||||||
|
GlobalUserPreferences.bottomEncoding = true;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
addBottomLanguage(allLanguagesMenu);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
languagePopup.setOnMenuItemClickListener(i->{
|
languagePopup.setOnMenuItemClickListener(i->{
|
||||||
if (i.hasSubMenu()) return false;
|
if (i.hasSubMenu()) return false;
|
||||||
|
if (i.getItemId() == allLanguages.size()) {
|
||||||
|
updateLanguage(language, "\uD83E\uDD7A\uD83D\uDC49\uD83D\uDC48", "bottom");
|
||||||
|
encoding = "bottom";
|
||||||
|
} else {
|
||||||
updateLanguage(allLanguages.get(i.getItemId()));
|
updateLanguage(allLanguages.get(i.getItemId()));
|
||||||
|
encoding = null;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addBottomLanguage(Menu menu) {
|
||||||
|
menu.add(0, allLanguages.size(), Menu.NONE, "bottom (\uD83E\uDD7A\uD83D\uDC49\uD83D\uDC48)");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item){
|
public boolean onOptionsItemSelected(MenuItem item){
|
||||||
return true;
|
return true;
|
||||||
|
@ -995,6 +1028,10 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
private void publish(boolean force){
|
private void publish(boolean force){
|
||||||
String text=mainEditText.getText().toString();
|
String text=mainEditText.getText().toString();
|
||||||
CreateStatus.Request req=new CreateStatus.Request();
|
CreateStatus.Request req=new CreateStatus.Request();
|
||||||
|
if ("bottom".equals(encoding)) {
|
||||||
|
text = new StringEncoder(Bottom::encode).encode(text);
|
||||||
|
req.spoilerText = "bottom-encoded emoji spam";
|
||||||
|
}
|
||||||
if (localOnly &&
|
if (localOnly &&
|
||||||
GlobalUserPreferences.accountsInGlitchMode.contains(accountID) &&
|
GlobalUserPreferences.accountsInGlitchMode.contains(accountID) &&
|
||||||
!GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()) {
|
!GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()) {
|
||||||
|
@ -1135,7 +1172,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||||
if (replyTo == null) {
|
if (replyTo == null) {
|
||||||
List<String> newRecentLanguages = new ArrayList<>(Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages));
|
List<String> newRecentLanguages = new ArrayList<>(Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages));
|
||||||
newRecentLanguages.remove(language);
|
newRecentLanguages.remove(language);
|
||||||
|
newRecentLanguages.remove(encoding);
|
||||||
newRecentLanguages.add(0, language);
|
newRecentLanguages.add(0, language);
|
||||||
|
newRecentLanguages.add(0, encoding);
|
||||||
recentLanguages.put(accountID, newRecentLanguages.stream().limit(4).collect(Collectors.toList()));
|
recentLanguages.put(accountID, newRecentLanguages.stream().limit(4).collect(Collectors.toList()));
|
||||||
GlobalUserPreferences.save();
|
GlobalUserPreferences.save();
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,7 +375,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void updateList(List<T> addItems, Map<Integer, T> items) {
|
private <T> void updateList(List<T> addItems, Map<Integer, T> items) {
|
||||||
if (addItems.size() == 0) return;
|
if (addItems.size() == 0 || getActivity() == null) return;
|
||||||
for (int i = 0; i < addItems.size(); i++) items.put(View.generateViewId(), addItems.get(i));
|
for (int i = 0; i < addItems.size(); i++) items.put(View.generateViewId(), addItems.get(i));
|
||||||
updateOverflowMenu();
|
updateOverflowMenu();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,16 @@ package org.joinmastodon.android.ui.displayitems;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.graphics.drawable.Animatable;
|
import android.graphics.drawable.Animatable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.github.bottomSoftwareFoundation.bottom.Bottom;
|
||||||
|
import com.github.bottomSoftwareFoundation.bottom.TranslationError;
|
||||||
|
|
||||||
import org.joinmastodon.android.GlobalUserPreferences;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
|
@ -20,13 +22,15 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Instance;
|
import org.joinmastodon.android.model.Instance;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
|
|
||||||
import org.joinmastodon.android.model.StatusPrivacy;
|
import org.joinmastodon.android.model.StatusPrivacy;
|
||||||
import org.joinmastodon.android.model.TranslatedStatus;
|
import org.joinmastodon.android.model.TranslatedStatus;
|
||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.joinmastodon.android.ui.views.LinkedTextView;
|
import org.joinmastodon.android.ui.views.LinkedTextView;
|
||||||
|
import org.joinmastodon.android.utils.StringEncoder;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
@ -46,6 +50,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||||
public boolean translated = false;
|
public boolean translated = false;
|
||||||
public TranslatedStatus translation = null;
|
public TranslatedStatus translation = null;
|
||||||
private AccountSession session;
|
private AccountSession session;
|
||||||
|
public static final Pattern BOTTOM_TEXT_PATTERN = Pattern.compile("(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️)(?:\uD83D\uDC49\uD83D\uDC48(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️))*\uD83D\uDC49\uD83D\uDC48");
|
||||||
|
|
||||||
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){
|
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){
|
||||||
super(parentID, parentFragment);
|
super(parentID, parentFragment);
|
||||||
|
@ -145,17 +150,31 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||||
instanceInfo.v2 != null && instanceInfo.v2.configuration.translation != null &&
|
instanceInfo.v2 != null && instanceInfo.v2.configuration.translation != null &&
|
||||||
instanceInfo.v2.configuration.translation.enabled;
|
instanceInfo.v2.configuration.translation.enabled;
|
||||||
|
|
||||||
translateWrap.setVisibility(
|
boolean isBottomText = BOTTOM_TEXT_PATTERN.matcher(item.status.getStrippedText()).find();
|
||||||
(!GlobalUserPreferences.translateButtonOpenedOnly || item.textSelectable) &&
|
translateWrap.setVisibility((isBottomText || (
|
||||||
translateEnabled &&
|
translateEnabled &&
|
||||||
!item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) &&
|
!item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) &&
|
||||||
item.status.language != null &&
|
item.status.language != null &&
|
||||||
(item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage))
|
(item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage))))
|
||||||
? View.VISIBLE : View.GONE);
|
&& (!GlobalUserPreferences.translateButtonOpenedOnly || item.textSelectable)
|
||||||
|
? View.VISIBLE : View.GONE
|
||||||
|
);
|
||||||
translateButton.setText(item.translated ? R.string.sk_translate_show_original : R.string.sk_translate_post);
|
translateButton.setText(item.translated ? R.string.sk_translate_show_original : R.string.sk_translate_post);
|
||||||
translateInfo.setText(item.translated ? itemView.getResources().getString(R.string.sk_translated_using, item.translation.provider) : "");
|
translateInfo.setText(item.translated ? itemView.getResources().getString(R.string.sk_translated_using, isBottomText ? "bottom-java" : item.translation.provider) : "");
|
||||||
translateButton.setOnClickListener(v->{
|
translateButton.setOnClickListener(v->{
|
||||||
if (item.translation == null) {
|
if (item.translation == null) {
|
||||||
|
if (isBottomText) {
|
||||||
|
try {
|
||||||
|
item.translation = new TranslatedStatus();
|
||||||
|
item.translation.content = new StringEncoder(Bottom::decode).decode(item.status.getStrippedText(), BOTTOM_TEXT_PATTERN);
|
||||||
|
item.translated = true;
|
||||||
|
} catch (TranslationError err) {
|
||||||
|
item.translation = null;
|
||||||
|
Toast.makeText(itemView.getContext(), err.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
rebind();
|
||||||
|
return;
|
||||||
|
}
|
||||||
translateProgress.setVisibility(View.VISIBLE);
|
translateProgress.setVisibility(View.VISIBLE);
|
||||||
translateButton.setClickable(false);
|
translateButton.setClickable(false);
|
||||||
translateButton.animate().alpha(0.5f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start();
|
translateButton.animate().alpha(0.5f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start();
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.content.res.Resources;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.model.Instance;
|
import org.joinmastodon.android.model.Instance;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.joinmastodon.android.utils;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.fragments.ComposeFragment;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.regex.MatchResult;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
// not a good class
|
||||||
|
public class StringEncoder {
|
||||||
|
private final Function<String, String> fn;
|
||||||
|
|
||||||
|
public StringEncoder(Function<String, String> fn) {
|
||||||
|
this.fn = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prettiest method award winner 2023 [citation needed]
|
||||||
|
public String encode(String content) {
|
||||||
|
StringBuilder encodedString = new StringBuilder();
|
||||||
|
// matches mentions and hashtags
|
||||||
|
Matcher m = ComposeFragment.HIGHLIGHT_PATTERN.matcher(content);
|
||||||
|
int previousEnd = 0;
|
||||||
|
while (m.find()) {
|
||||||
|
MatchResult res = m.toMatchResult();
|
||||||
|
// everything before the match - do encode
|
||||||
|
encodedString.append(fn.apply(content.substring(previousEnd, res.start())));
|
||||||
|
previousEnd = res.end();
|
||||||
|
// the match - do not encode
|
||||||
|
encodedString.append(res.group());
|
||||||
|
}
|
||||||
|
// everything after the last match - do encode
|
||||||
|
encodedString.append(fn.apply(content.substring(previousEnd)));
|
||||||
|
return encodedString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// prettiest almost-exact replica of a pretty function
|
||||||
|
public String decode(String content, Pattern regex) {
|
||||||
|
Matcher m = regex.matcher(content);
|
||||||
|
StringBuilder decodedString = new StringBuilder();
|
||||||
|
int previousEnd = 0;
|
||||||
|
while (m.find()) {
|
||||||
|
MatchResult res = m.toMatchResult();
|
||||||
|
// everything before the match - do not decode
|
||||||
|
decodedString.append(content.substring(previousEnd, res.start()));
|
||||||
|
previousEnd = res.end();
|
||||||
|
// the match - do decode
|
||||||
|
decodedString.append(fn.apply(res.group()));
|
||||||
|
}
|
||||||
|
decodedString.append(content.substring(previousEnd));
|
||||||
|
return decodedString.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ dependencyResolutionManagement {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Megalodon"
|
rootProject.name = "Megalodon"
|
||||||
|
|
Loading…
Reference in New Issue