From 4cf734ce9ab4cd38adb7efb5fb090b25c7d2a555 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 15:23:42 +0100 Subject: [PATCH 01/10] avoid IllegalArgumentException --- .../android/fragments/BaseStatusListFragment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index a73d7d7228..7ec3873d41 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -362,8 +362,9 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat private Rect tmpRect=new Rect(); @Override public void getSelectorBounds(View view, Rect outRect){ - boolean hasDescendant = false, hasAncestor = false, isWarning = false; - int lastIndex = -1, firstIndex = -1; + if(list!=view.getParent()) return; + boolean hasDescendant=false, hasAncestor=false, isWarning=false; + int lastIndex=-1, firstIndex=-1; if(((UsableRecyclerView) list).isIncludeMarginsInItemHitbox()){ list.getDecoratedBoundsWithMargins(view, outRect); }else{ From 26391a6f14b1cc4d237406db1f793c5f90d186b0 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 15:37:03 +0100 Subject: [PATCH 02/10] hopefully fix string index out of bounds https://paste.crdroid.net/3FNRe7 --- .../main/java/org/joinmastodon/android/ui/utils/UiUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java index 187b89ac4d..306b767c12 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java @@ -1688,7 +1688,7 @@ private static String extractPronounsFromField(String localizedPronouns, Account if(!field.name.toLowerCase().contains(localizedPronouns) && !field.name.toLowerCase().contains("pronouns")) return null; String text=HtmlParser.text(field.value); - if(field.value.toLowerCase().contains("https://")){ + if(text.toLowerCase().contains("https://")){ for(String pronounUrl : pronounsUrls){ int index=text.indexOf(pronounUrl); int beginPronouns=index+pronounUrl.length(); From a085744038f2f52b9d340d51275d1a4e131f885b Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 15:37:31 +0100 Subject: [PATCH 03/10] fix missing parens on start of pronouns --- .../org/joinmastodon/android/ui/utils/UiUtils.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java index 306b767c12..a33da0105e 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java @@ -1707,13 +1707,14 @@ private static String extractPronounsFromField(String localizedPronouns, Account Matcher matcher=trimPronouns.matcher(text); if(!matcher.find()) return null; String pronouns=matcher.group(1); - // crude fix to allow for pronouns like "it(/she)" - int missingClosingParens=0; + // crude fix to allow for pronouns like "it(/she)" or "(de) sie/ihr" + int missingParens=0; for(char c : pronouns.toCharArray()){ - if(c=='(') missingClosingParens++; - if(c==')') missingClosingParens--; + if(c=='(') missingParens++; + if(c==')') missingParens--; } - pronouns+=")".repeat(Math.max(0, missingClosingParens)); + if(missingParens > 0) pronouns+=")".repeat(missingParens); + else if(missingParens < 0) pronouns="(".repeat(missingParens*-1)+pronouns; // if ends with an un-closed custom emoji if(pronouns.matches("^.*\\s+:[a-zA-Z_]+$")) pronouns+=':'; return pronouns; From d6aeb753fc8aca3da41feee729b3a4f98ae618e6 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 16:13:14 +0100 Subject: [PATCH 04/10] allow exclamation/question marks in pronouns --- .../joinmastodon/android/ui/utils/UiUtilsTest.java | 4 ++++ .../org/joinmastodon/android/ui/utils/UiUtils.java | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/mastodon/src/androidTest/java/org/joinmastodon/android/ui/utils/UiUtilsTest.java b/mastodon/src/androidTest/java/org/joinmastodon/android/ui/utils/UiUtilsTest.java index 4728a48618..d9ea49e146 100644 --- a/mastodon/src/androidTest/java/org/joinmastodon/android/ui/utils/UiUtilsTest.java +++ b/mastodon/src/androidTest/java/org/joinmastodon/android/ui/utils/UiUtilsTest.java @@ -257,5 +257,9 @@ public void extractPronouns() { assertEquals("* (asterisk)", UiUtils.extractPronouns(MastodonApp.context, fakeAccount( makeField("pronouns", "-- * (asterisk) --") )).orElseThrow()); + + assertEquals("they/(she?)", UiUtils.extractPronouns(MastodonApp.context, fakeAccount( + makeField("pronouns", "they/(she?)...") + )).orElseThrow()); } } \ No newline at end of file diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java index a33da0105e..d5f3281ad0 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java @@ -1683,7 +1683,9 @@ public static CharSequence generateFormattedString(String format, CharSequence.. "pronouns.page/" }; - private static final Pattern trimPronouns=Pattern.compile("[^\\w*]*([\\w*].*[\\w*]|[\\w*])\\W*"); + private static final String PRONOUN_CHARS="\\w*¿¡!?"; + private static final Pattern trimPronouns= + Pattern.compile("[^"+PRONOUN_CHARS+"]*(["+PRONOUN_CHARS+"].*["+PRONOUN_CHARS+"]|["+PRONOUN_CHARS+"])\\W*"); private static String extractPronounsFromField(String localizedPronouns, AccountField field) { if(!field.name.toLowerCase().contains(localizedPronouns) && !field.name.toLowerCase().contains("pronouns")) return null; @@ -1707,14 +1709,20 @@ private static String extractPronounsFromField(String localizedPronouns, Account Matcher matcher=trimPronouns.matcher(text); if(!matcher.find()) return null; String pronouns=matcher.group(1); + // crude fix to allow for pronouns like "it(/she)" or "(de) sie/ihr" - int missingParens=0; + int missingParens=0, missingBrackets=0; for(char c : pronouns.toCharArray()){ if(c=='(') missingParens++; - if(c==')') missingParens--; + else if(c=='[') missingBrackets++; + else if(c==')') missingParens--; + else if(c==']') missingBrackets--; } if(missingParens > 0) pronouns+=")".repeat(missingParens); else if(missingParens < 0) pronouns="(".repeat(missingParens*-1)+pronouns; + if(missingBrackets > 0) pronouns+="]".repeat(missingBrackets); + else if(missingBrackets < 0) pronouns="[".repeat(missingBrackets*-1)+pronouns; + // if ends with an un-closed custom emoji if(pronouns.matches("^.*\\s+:[a-zA-Z_]+$")) pronouns+=':'; return pronouns; From 95dd3ff0680d9225d80b817d81a30b5b62b04c09 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 16:13:43 +0100 Subject: [PATCH 05/10] fix translation language name --- .../android/ui/displayitems/TextStatusDisplayItem.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java index 5881c66674..cc22f4fe7a 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java @@ -211,8 +211,9 @@ public void updateTranslation(boolean updateText){ String existingTransLang=existingTrans!=null ? existingTrans.detectedSourceLanguage : null; String lang=existingTransLang!=null ? existingTransLang : item.status.getContentStatus().language; Locale locale=lang!=null ? Locale.forLanguageTag(lang) : null; - translationButton.setText(locale!=null - ? item.parentFragment.getString(R.string.translate_post, locale.getDisplayLanguage()) + String displayLang=locale==null || locale.getDisplayLanguage().isBlank() ? lang : locale.getDisplayLanguage(); + translationButton.setText(displayLang!=null + ? item.parentFragment.getString(R.string.translate_post, displayLang) : item.parentFragment.getString(R.string.sk_translate_post)); translationButton.setClickable(true); translationButton.animate().alpha(1).setDuration(100).start(); From 295cb742875b942e3797b2a83f4cc83131e456c6 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 16:30:46 +0100 Subject: [PATCH 06/10] don't show translate for empty decoding --- .../joinmastodon/android/model/Status.java | 5 ++-- .../android/utils/StatusTextEncoder.java | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Status.java b/mastodon/src/main/java/org/joinmastodon/android/model/Status.java index eb13a43fcd..452ac85368 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Status.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Status.java @@ -4,6 +4,7 @@ import static org.joinmastodon.android.api.MastodonAPIController.gsonWithoutDeserializer; import android.text.TextUtils; +import android.util.Pair; import org.joinmastodon.android.api.ObjectValidationException; import org.joinmastodon.android.api.RequiredField; @@ -223,10 +224,10 @@ public boolean isEligibleForTranslation(AccountSession session){ instanceInfo.v2.configuration.translation.enabled; try { - String bottomText = BOTTOM_TEXT_PATTERN.matcher(getStrippedText()).find() + Pair> decoded=BOTTOM_TEXT_PATTERN.matcher(getStrippedText()).find() ? new StatusTextEncoder(Bottom::decode).decode(getStrippedText(), BOTTOM_TEXT_PATTERN) : null; - if(bottomText==null || bottomText.length()==0 || bottomText.equals("\u0005")) bottomText=null; + String bottomText=decoded==null || decoded.second.stream().allMatch(s->s.trim().isEmpty()) ? null : decoded.first; if(bottomText!=null){ translation=new Translation(); translation.content=bottomText; diff --git a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusTextEncoder.java b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusTextEncoder.java index 12f3d48911..7bf862178c 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusTextEncoder.java +++ b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusTextEncoder.java @@ -1,9 +1,9 @@ package org.joinmastodon.android.utils; -import android.text.TextUtils; - -import org.joinmastodon.android.fragments.ComposeFragment; +import android.util.Pair; +import java.util.ArrayList; +import java.util.List; import java.util.function.Function; import java.util.regex.MatchResult; import java.util.regex.Matcher; @@ -40,19 +40,22 @@ public String encode(String content) { } // 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; + public Pair> decode(String content, Pattern regex) { + Matcher m=regex.matcher(content); + StringBuilder decodedString=new StringBuilder(); + List decodedParts=new ArrayList<>(); + int previousEnd=0; while (m.find()) { - MatchResult res = m.toMatchResult(); + MatchResult res=m.toMatchResult(); // everything before the match - do not decode decodedString.append(content.substring(previousEnd, res.start())); - previousEnd = res.end(); + previousEnd=res.end(); // the match - do decode - decodedString.append(fn.apply(res.group())); + String decoded=fn.apply(res.group()); + decodedParts.add(decoded); + decodedString.append(decoded); } decodedString.append(content.substring(previousEnd)); - return decodedString.toString(); + return Pair.create(decodedString.toString(), decodedParts); } } From 613cd2a1eaeca0d97ad0ba1a77b57d927d60c5c9 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 10 Nov 2023 20:06:18 +0100 Subject: [PATCH 07/10] remove unused playRelease build type --- mastodon/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/mastodon/build.gradle b/mastodon/build.gradle index a48312df95..c848c91fe9 100644 --- a/mastodon/build.gradle +++ b/mastodon/build.gradle @@ -33,7 +33,6 @@ android { applicationIdSuffix '.debug' } githubRelease { initWith release } - playRelease { initWith release } fdroidRelease { initWith release } } compileOptions { From 50d1523210f20bd96c660d828f2ca845bad55e69 Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:10:50 +0100 Subject: [PATCH 08/10] feat: re-add 12 hour option to polls (#917) --- .../android/ui/viewcontrollers/ComposePollViewController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/viewcontrollers/ComposePollViewController.java b/mastodon/src/main/java/org/joinmastodon/android/ui/viewcontrollers/ComposePollViewController.java index aa72ec7240..9c3b64e7f2 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/viewcontrollers/ComposePollViewController.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/viewcontrollers/ComposePollViewController.java @@ -42,6 +42,7 @@ public class ComposePollViewController{ 30*60, 3600, 6*3600, + 12*3600, 24*3600, 3*24*3600, 7*24*3600, From 24794f28aab7b02902ec1d7cd7c38ae6ee9fd1ef Mon Sep 17 00:00:00 2001 From: S1m <31284753+p1gp1g@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:12:27 +0100 Subject: [PATCH 09/10] Fix: registering multi account for UnifiedPush (#907) * Register all account when enabling UnifiedPush * Register new account to UnifiedPush if enabled --- .../api/session/AccountSessionManager.java | 13 +++++++- .../SettingsNotificationsFragment.java | 30 +++++++++++-------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSessionManager.java b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSessionManager.java index 56b411a6ef..cd959a85ae 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSessionManager.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSessionManager.java @@ -1,5 +1,7 @@ package org.joinmastodon.android.api.session; +import static org.unifiedpush.android.connector.UnifiedPush.getDistributor; + import android.app.Activity; import android.app.NotificationManager; import android.content.ComponentName; @@ -34,6 +36,7 @@ import org.joinmastodon.android.model.LegacyFilter; import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Token; +import org.unifiedpush.android.connector.UnifiedPush; import java.io.File; import java.io.FileInputStream; @@ -101,6 +104,7 @@ private AccountSessionManager(){ } public void addAccount(Instance instance, Token token, Account self, Application app, AccountActivationInfo activationInfo){ + Context context = MastodonApp.context; instances.put(instance.uri, instance); AccountSession session=new AccountSession(token, self, app, instance.uri, activationInfo==null, activationInfo); sessions.put(session.getID(), session); @@ -113,7 +117,14 @@ public void addAccount(Instance instance, Token token, Account self, Application MastodonAPIController.runInBackground(()->writeInstanceInfoFile(wrapper, instance.uri)); updateMoreInstanceInfo(instance, instance.uri); - if(PushSubscriptionManager.arePushNotificationsAvailable()){ + if (!UnifiedPush.getDistributor(context).isEmpty()) { + UnifiedPush.registerApp( + context, + session.getID(), + new ArrayList<>(), + context.getPackageName() + ); + } else if(PushSubscriptionManager.arePushNotificationsAvailable()){ session.getPushSubscriptionManager().registerAccountForPush(null); } maybeUpdateShortcuts(); diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsNotificationsFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsNotificationsFragment.java index 2b240629b7..9c6d096320 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsNotificationsFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsNotificationsFragment.java @@ -334,13 +334,15 @@ private void onUnifiedPushClick(){ return; } - UnifiedPush.unregisterApp( - getContext(), - accountID - ); - - //re-register to fcm - AccountSessionManager.getInstance().getAccount(accountID).getPushSubscriptionManager().registerAccountForPush(getPushSubscription()); + for (AccountSession accountSession : AccountSessionManager.getInstance().getLoggedInAccounts()) { + UnifiedPush.unregisterApp( + getContext(), + accountSession.getID() + ); + + //re-register to fcm + accountSession.getPushSubscriptionManager().registerAccountForPush(getPushSubscription()); + } unifiedPushItem.toggle(); rebindItem(unifiedPushItem); } @@ -350,12 +352,14 @@ private void showUnifiedPushRegisterDialog(List distributors){ (dialog, which)->{ String userDistrib = distributors.get(which); UnifiedPush.saveDistributor(getContext(), userDistrib); - UnifiedPush.registerApp( - getContext(), - accountID, - new ArrayList<>(), - getContext().getPackageName() - ); + for (AccountSession accountSession : AccountSessionManager.getInstance().getLoggedInAccounts()){ + UnifiedPush.registerApp( + getContext(), + accountSession.getID(), + new ArrayList<>(), + getContext().getPackageName() + ); + } unifiedPushItem.toggle(); rebindItem(unifiedPushItem); }).setOnCancelListener(d->rebindItem(unifiedPushItem)).show(); From 2818672cdad3685ef549b906e16dfc3291bdf7ba Mon Sep 17 00:00:00 2001 From: S1m <31284753+p1gp1g@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:15:45 +0100 Subject: [PATCH 10/10] Fix NullPointerException when receiving push when killed (#914) --- .../org/joinmastodon/android/api/session/AccountSession.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java index 3f9f1fe26b..5d70e0b236 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java @@ -260,11 +260,13 @@ private boolean statusIsOnOwnProfile(Status s, Account profile){ } private boolean isFilteredType(Status s){ + AccountLocalPreferences localPreferences = getLocalPreferences(); return (!localPreferences.showReplies && s.inReplyToId != null) || (!localPreferences.showBoosts && s.reblog != null); } public void filterStatusContainingObjects(List objects, Function extractor, FilterContext context, Account profile){ + AccountLocalPreferences localPreferences = getLocalPreferences(); if(!localPreferences.serverSideFiltersSupported) for(T obj:objects){ Status s=extractor.apply(obj); if(s!=null && s.filtered!=null){ @@ -307,7 +309,7 @@ public boolean filterStatusContainingObject(T object, Function ex if(isFilteredType(s) && (context == FilterContext.HOME || context == FilterContext.PUBLIC)) return true; // Even with server-side filters, clients are expected to remove statuses that match a filter that hides them - if(localPreferences.serverSideFiltersSupported){ + if(getLocalPreferences().serverSideFiltersSupported){ for(FilterResult filter : s.filtered){ if(filter.filter.isActive() && filter.filter.filterAction==FilterAction.HIDE) return true;