Merge remote-tracking branch 'megalodon_main/main'
# Conflicts: # mastodon/build.gradle # mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java # mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FileStatusDisplayItem.java # mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java # mastodon/src/main/res/menu/profile.xml # metadata/cy/full_description.txt
This commit is contained in:
@@ -54,7 +54,6 @@ public class GlobalUserPreferences{
|
||||
public static boolean collapseLongPosts;
|
||||
public static boolean spectatorMode;
|
||||
public static boolean autoHideFab;
|
||||
public static boolean compactReblogReplyLine;
|
||||
public static boolean allowRemoteLoading;
|
||||
public static boolean forwardReportDefault;
|
||||
public static AutoRevealMode autoRevealEqualSpoilers;
|
||||
@@ -130,7 +129,6 @@ public class GlobalUserPreferences{
|
||||
collapseLongPosts=prefs.getBoolean("collapseLongPosts", true);
|
||||
spectatorMode=prefs.getBoolean("spectatorMode", false);
|
||||
autoHideFab=prefs.getBoolean("autoHideFab", true);
|
||||
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
|
||||
allowRemoteLoading=prefs.getBoolean("allowRemoteLoading", true);
|
||||
autoRevealEqualSpoilers=AutoRevealMode.valueOf(prefs.getString("autoRevealEqualSpoilers", AutoRevealMode.THREADS.name()));
|
||||
forwardReportDefault=prefs.getBoolean("forwardReportDefault", true);
|
||||
@@ -208,7 +206,6 @@ public class GlobalUserPreferences{
|
||||
.putBoolean("collapseLongPosts", collapseLongPosts)
|
||||
.putBoolean("spectatorMode", spectatorMode)
|
||||
.putBoolean("autoHideFab", autoHideFab)
|
||||
.putBoolean("compactReblogReplyLine", compactReblogReplyLine)
|
||||
.putBoolean("allowRemoteLoading", allowRemoteLoading)
|
||||
.putString("autoRevealEqualSpoilers", autoRevealEqualSpoilers.name())
|
||||
.putBoolean("forwardReportDefault", forwardReportDefault)
|
||||
|
||||
@@ -8,7 +8,10 @@ import org.joinmastodon.android.api.requests.statuses.SetStatusBookmarked;
|
||||
import org.joinmastodon.android.api.requests.statuses.SetStatusFavorited;
|
||||
import org.joinmastodon.android.api.requests.statuses.SetStatusMuted;
|
||||
import org.joinmastodon.android.api.requests.statuses.SetStatusReblogged;
|
||||
import org.joinmastodon.android.events.ReblogDeletedEvent;
|
||||
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||
import org.joinmastodon.android.events.StatusCreatedEvent;
|
||||
import org.joinmastodon.android.events.StatusDeletedEvent;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.model.StatusPrivacy;
|
||||
|
||||
@@ -50,7 +53,7 @@ public class StatusInteractionController{
|
||||
runningFavoriteRequests.remove(status.id);
|
||||
result.favouritesCount = Math.max(0, status.favouritesCount + (favorited ? 1 : -1));
|
||||
cb.accept(result);
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,13 +62,13 @@ public class StatusInteractionController{
|
||||
error.showToast(MastodonApp.context);
|
||||
status.favourited=!favorited;
|
||||
cb.accept(status);
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
runningFavoriteRequests.put(status.id, req);
|
||||
status.favourited=favorited;
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
}
|
||||
|
||||
public void setReblogged(Status status, boolean reblogged, StatusPrivacy visibility, Consumer<Status> cb){
|
||||
@@ -80,11 +83,15 @@ public class StatusInteractionController{
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Status reblog){
|
||||
Status result = reblog.getContentStatus();
|
||||
Status result=reblog.getContentStatus();
|
||||
runningReblogRequests.remove(status.id);
|
||||
result.reblogsCount = Math.max(0, status.reblogsCount + (reblogged ? 1 : -1));
|
||||
cb.accept(result);
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
|
||||
if(updateCounters){
|
||||
E.post(new StatusCountersUpdatedEvent(result));
|
||||
if(reblogged) E.post(new StatusCreatedEvent(reblog, accountID));
|
||||
else E.post(new ReblogDeletedEvent(status.id, accountID));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,13 +100,13 @@ public class StatusInteractionController{
|
||||
error.showToast(MastodonApp.context);
|
||||
status.reblogged=!reblogged;
|
||||
cb.accept(status);
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
runningReblogRequests.put(status.id, req);
|
||||
status.reblogged=reblogged;
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
}
|
||||
|
||||
public void setBookmarked(Status status, boolean bookmarked){
|
||||
@@ -120,7 +127,7 @@ public class StatusInteractionController{
|
||||
public void onSuccess(Status result){
|
||||
runningBookmarkRequests.remove(status.id);
|
||||
cb.accept(result);
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,12 +136,12 @@ public class StatusInteractionController{
|
||||
error.showToast(MastodonApp.context);
|
||||
status.bookmarked=!bookmarked;
|
||||
cb.accept(status);
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
runningBookmarkRequests.put(status.id, req);
|
||||
status.bookmarked=bookmarked;
|
||||
if (updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
if(updateCounters) E.post(new StatusCountersUpdatedEvent(status));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.joinmastodon.android.events;
|
||||
|
||||
public class ReblogDeletedEvent{
|
||||
public final String statusID;
|
||||
public final String accountID;
|
||||
|
||||
public ReblogDeletedEvent(String statusID, String accountID){
|
||||
this.statusID=statusID;
|
||||
this.accountID=accountID;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.joinmastodon.android.events;
|
||||
|
||||
import org.joinmastodon.android.model.ScheduledStatus;
|
||||
|
||||
public class ScheduledStatusDeletedEvent{
|
||||
public final String id;
|
||||
public final String accountID;
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.text.TextWatcher;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -124,11 +123,11 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -166,7 +165,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
|
||||
public LinearLayout mainLayout;
|
||||
private SizeListenerLinearLayout contentView;
|
||||
private TextView selfName, selfUsername, selfExtraText, extraText, pronouns;
|
||||
private TextView selfName, selfUsername, selfExtraText, extraText;
|
||||
private ImageView selfAvatar;
|
||||
private Account self;
|
||||
private String instanceDomain;
|
||||
@@ -686,7 +685,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
});
|
||||
View originalPost=view.findViewById(R.id.original_post);
|
||||
extraText=view.findViewById(R.id.extra_text);
|
||||
pronouns=view.findViewById(R.id.pronouns);
|
||||
originalPost.setVisibility(View.VISIBLE);
|
||||
originalPost.setOnClickListener(v->{
|
||||
Bundle args=new Bundle();
|
||||
@@ -863,6 +861,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
|
||||
inflater.inflate(editingStatus==null ? R.menu.compose : R.menu.compose_edit, menu);
|
||||
@@ -911,7 +910,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
languageButton = wrap.findViewById(R.id.language_btn);
|
||||
languageButton.setOnClickListener(v->showLanguageAlert());
|
||||
languageButton.setOnLongClickListener(v->{
|
||||
languageButton.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
if(!getLocalPrefs().bottomEncoding){
|
||||
getLocalPrefs().bottomEncoding=true;
|
||||
getLocalPrefs().save();
|
||||
@@ -919,22 +917,27 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
return false;
|
||||
});
|
||||
|
||||
if(GlobalUserPreferences.relocatePublishButton){
|
||||
publishButtonRelocated.setOnClickListener(v -> {
|
||||
if(GlobalUserPreferences.altTextReminders && editingStatus==null)
|
||||
checkAltTextsAndPublish();
|
||||
else
|
||||
publish();
|
||||
});
|
||||
} else {
|
||||
publishButton.setOnClickListener(v -> {
|
||||
if(GlobalUserPreferences.altTextReminders && editingStatus==null)
|
||||
checkAltTextsAndPublish();
|
||||
else
|
||||
publish();
|
||||
});
|
||||
}
|
||||
publishButton.setOnClickListener(v->{
|
||||
Consumer<Boolean> draftCheckComplete=(isDraft)->{
|
||||
if(GlobalUserPreferences.altTextReminders && !isDraft) checkAltTextsAndPublish();
|
||||
else publish();
|
||||
};
|
||||
|
||||
boolean isAlreadyDraft=scheduledAt!=null && scheduledAt.isAfter(DRAFTS_AFTER_INSTANT);
|
||||
if(editingStatus!=null && scheduledAt!=null && isAlreadyDraft) {
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.sk_save_draft)
|
||||
.setMessage(R.string.sk_save_draft_message)
|
||||
.setPositiveButton(R.string.save, (d, w)->draftCheckComplete.accept(isAlreadyDraft))
|
||||
.setNegativeButton(R.string.publish, (d, w)->{
|
||||
updateScheduledAt(null);
|
||||
draftCheckComplete.accept(false);
|
||||
})
|
||||
.show();
|
||||
}else{
|
||||
draftCheckComplete.accept(isAlreadyDraft);
|
||||
}
|
||||
});
|
||||
draftsBtn.setOnClickListener(v-> draftOptionsPopup.show());
|
||||
draftsBtn.setOnTouchListener(draftOptionsPopup.getDragToOpenListener());
|
||||
updateScheduledAt(scheduledAt != null ? scheduledAt : scheduledStatus != null ? scheduledStatus.scheduledAt : null);
|
||||
@@ -945,8 +948,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
? languageResolver.fromOrFallback(prefs.postingDefaultLanguage)
|
||||
: languageResolver.getDefault());
|
||||
|
||||
if (isInstancePixelfed()) spoilerBtn.setVisibility(View.GONE);
|
||||
if (isInstancePixelfed() || (editingStatus != null && scheduledStatus == null)) {
|
||||
if(isInstancePixelfed()) spoilerBtn.setVisibility(View.GONE);
|
||||
if(isInstancePixelfed() || (editingStatus!=null && !redraftStatus)) {
|
||||
// editing an already published post
|
||||
draftsBtn.setVisibility(View.GONE);
|
||||
}
|
||||
@@ -1077,7 +1080,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
|
||||
@Override
|
||||
protected int getNavigationIconDrawableResource(){
|
||||
return R.drawable.ic_baseline_close_24;
|
||||
return R.drawable.ic_fluent_dismiss_24_regular;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1146,31 +1149,23 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
overlayParams.token=mainEditText.getWindowToken();
|
||||
wm.addView(sendingOverlay, overlayParams);
|
||||
|
||||
if(GlobalUserPreferences.relocatePublishButton){
|
||||
publishButtonRelocated.setEnabled(false);
|
||||
} else {
|
||||
publishButton.setEnabled(false);
|
||||
}
|
||||
|
||||
(GlobalUserPreferences.relocatePublishButton ? publishButtonRelocated : publishButton).setEnabled(false);
|
||||
V.setVisibilityAnimated(sendProgress, View.VISIBLE);
|
||||
|
||||
mediaViewController.saveAltTextsBeforePublishing(this::actuallyPublish, this::handlePublishError);
|
||||
}
|
||||
|
||||
private void actuallyPublish(){
|
||||
actuallyPublish(false);
|
||||
}
|
||||
private void actuallyPublish(boolean force){
|
||||
String text=mainEditText.getText().toString();
|
||||
CreateStatus.Request req=new CreateStatus.Request();
|
||||
if ("bottom".equals(postLang.encoding)) {
|
||||
text = new StatusTextEncoder(Bottom::encode).encode(text);
|
||||
req.spoilerText = "bottom-encoded emoji spam";
|
||||
if("bottom".equals(postLang.encoding)){
|
||||
text=new StatusTextEncoder(Bottom::encode).encode(text);
|
||||
req.spoilerText="bottom-encoded emoji spam";
|
||||
}
|
||||
if (localOnly &&
|
||||
if(localOnly &&
|
||||
AccountSessionManager.get(accountID).getLocalPreferences().glitchInstance &&
|
||||
!GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()) {
|
||||
text += " " + GLITCH_LOCAL_ONLY_SUFFIX;
|
||||
!GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()){
|
||||
text+=" "+GLITCH_LOCAL_ONLY_SUFFIX;
|
||||
}
|
||||
req.status=text;
|
||||
req.localOnly=localOnly;
|
||||
@@ -1184,19 +1179,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
req.mediaAttributes=mediaViewController.getAttachmentAttributes();
|
||||
}
|
||||
}
|
||||
// ask whether to publish now when editing an existing draft
|
||||
if (!force && editingStatus != null && scheduledAt != null && scheduledAt.isAfter(DRAFTS_AFTER_INSTANT)) {
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.sk_save_draft)
|
||||
.setMessage(R.string.sk_save_draft_message)
|
||||
.setPositiveButton(R.string.save, (d, w) -> actuallyPublish(true))
|
||||
.setNegativeButton(R.string.publish, (d, w) -> {
|
||||
updateScheduledAt(null);
|
||||
actuallyPublish();
|
||||
})
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
if(replyTo!=null || (editingStatus != null && editingStatus.inReplyToId!=null)){
|
||||
req.inReplyToId=editingStatus!=null ? editingStatus.inReplyToId : replyTo.id;
|
||||
}
|
||||
@@ -1303,13 +1285,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
wm.removeView(sendingOverlay);
|
||||
sendingOverlay=null;
|
||||
V.setVisibilityAnimated(sendProgress, View.GONE);
|
||||
|
||||
if(GlobalUserPreferences.relocatePublishButton) {
|
||||
publishButtonRelocated.setEnabled(true);
|
||||
} else {
|
||||
publishButton.setEnabled(true);
|
||||
}
|
||||
|
||||
(GlobalUserPreferences.relocatePublishButton ? publishButtonRelocated : publishButton).setEnabled(true);
|
||||
if(error instanceof MastodonErrorResponse me){
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.post_failed)
|
||||
@@ -1397,20 +1373,20 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
}
|
||||
|
||||
private void confirmDiscardDraftAndFinish(){
|
||||
boolean attachmentsPending = mediaViewController.areAnyAttachmentsNotDone();
|
||||
if (attachmentsPending) new M3AlertDialogBuilder(getActivity())
|
||||
boolean attachmentsPending=mediaViewController.areAnyAttachmentsNotDone();
|
||||
if(attachmentsPending) new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.sk_unfinished_attachments)
|
||||
.setMessage(R.string.sk_unfinished_attachments_message)
|
||||
.setPositiveButton(R.string.edit, (d, w) -> {})
|
||||
.setNegativeButton(R.string.discard, (d, w) -> Nav.finish(this))
|
||||
.setPositiveButton(R.string.ok, (d, w)->{})
|
||||
.setNegativeButton(R.string.discard, (d, w)->Nav.finish(this))
|
||||
.show();
|
||||
else new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(editingStatus != null ? R.string.sk_confirm_save_changes : R.string.sk_confirm_save_draft)
|
||||
.setPositiveButton(R.string.save, (d, w) -> {
|
||||
updateScheduledAt(scheduledAt == null ? getDraftInstant() : scheduledAt);
|
||||
.setTitle(editingStatus!=null ? R.string.sk_confirm_save_changes : R.string.sk_confirm_save_draft)
|
||||
.setPositiveButton(R.string.save, (d, w)->{
|
||||
updateScheduledAt(scheduledAt==null ? getDraftInstant() : scheduledAt);
|
||||
publish();
|
||||
})
|
||||
.setNegativeButton(R.string.discard, (d, w) -> Nav.finish(this))
|
||||
.setNegativeButton(R.string.discard, (d, w)->Nav.finish(this))
|
||||
.show();
|
||||
}
|
||||
|
||||
@@ -1615,8 +1591,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
}
|
||||
|
||||
private void updateHeaders() {
|
||||
UiUtils.setExtraTextInfo(getContext(), selfExtraText, null, false, false, localOnly || statusVisibility==StatusPrivacy.LOCAL, null);
|
||||
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, pronouns, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
|
||||
UiUtils.setExtraTextInfo(getContext(), selfExtraText, false, false, localOnly || statusVisibility==StatusPrivacy.LOCAL, null);
|
||||
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
|
||||
}
|
||||
|
||||
private void buildVisibilityPopup(View v){
|
||||
|
||||
@@ -271,7 +271,7 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
|
||||
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
relationship=relationships.get(item.account.id);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
|
||||
|
||||
if(relationship==null || !relationship.followedBy){
|
||||
actionWrap.setVisibility(View.GONE);
|
||||
|
||||
@@ -404,9 +404,8 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||
addListsToOverflowMenu();
|
||||
addHashtagsToOverflowMenu();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !UiUtils.isEMUI()) {
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P && !UiUtils.isEMUI())
|
||||
m.setGroupDividerEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -293,7 +293,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
|
||||
continue;
|
||||
Status contentStatus=ntf.status.getContentStatus();
|
||||
if(contentStatus.poll!=null && contentStatus.poll.id.equals(ev.poll.id)){
|
||||
updatePoll(ntf.id, ntf.status, ev.poll);
|
||||
updatePoll(ntf.id, contentStatus, ev.poll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,20 +846,21 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
boolean hasMultipleAccounts = AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
|
||||
MenuItem openWithAccounts = menu.findItem(R.id.open_with_account);
|
||||
openWithAccounts.setVisible(hasMultipleAccounts);
|
||||
SubMenu accountsMenu = openWithAccounts.getSubMenu();
|
||||
if (hasMultipleAccounts) {
|
||||
SubMenu accountsMenu=openWithAccounts.getSubMenu();
|
||||
if(hasMultipleAccounts){
|
||||
accountsMenu.clear();
|
||||
UiUtils.populateAccountsMenu(accountID, accountsMenu, s-> UiUtils.openURL(
|
||||
getActivity(), s.getID(), account.url, false
|
||||
));
|
||||
}
|
||||
menu.findItem(R.id.share).setTitle(R.string.share_user);
|
||||
|
||||
if(isOwnProfile) {
|
||||
if (isInstancePixelfed()) menu.findItem(R.id.scheduled).setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
MenuItem mute = menu.findItem(R.id.mute);
|
||||
menu.findItem(R.id.manage_user_lists).setTitle(getString(R.string.sk_lists_with_user, account.getShortUsername()));
|
||||
MenuItem mute=menu.findItem(R.id.mute);
|
||||
mute.setTitle(getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getShortUsername()));
|
||||
mute.setIcon(relationship.muting ? R.drawable.ic_fluent_speaker_2_24_regular : R.drawable.ic_fluent_speaker_off_24_regular);
|
||||
UiUtils.insetPopupMenuIcon(getContext(), mute);
|
||||
@@ -867,19 +868,22 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
menu.findItem(R.id.report).setTitle(getString(R.string.report_user, account.getShortUsername()));
|
||||
menu.findItem(R.id.manage_user_lists).setVisible(relationship.following);
|
||||
menu.findItem(R.id.soft_block).setVisible(relationship.followedBy && !relationship.following);
|
||||
MenuItem hideBoosts=menu.findItem(R.id.hide_boosts);
|
||||
if (relationship.following) {
|
||||
MenuItem hideBoosts = menu.findItem(R.id.hide_boosts);
|
||||
hideBoosts.setTitle(getString(relationship.showingReblogs ? R.string.hide_boosts_from_user : R.string.show_boosts_from_user, account.getShortUsername()));
|
||||
hideBoosts.setIcon(relationship.showingReblogs ? R.drawable.ic_fluent_arrow_repeat_all_off_24_regular : R.drawable.ic_fluent_arrow_repeat_all_24_regular);
|
||||
UiUtils.insetPopupMenuIcon(getContext(), hideBoosts);
|
||||
menu.findItem(R.id.manage_user_lists).setTitle(getString(R.string.sk_lists_with_user, account.getShortUsername()));
|
||||
hideBoosts.setVisible(true);
|
||||
} else {
|
||||
menu.findItem(R.id.hide_boosts).setVisible(false);
|
||||
hideBoosts.setVisible(false);
|
||||
}
|
||||
MenuItem blockDomain=menu.findItem(R.id.block_domain);
|
||||
if(!account.isLocal()){
|
||||
blockDomain.setTitle(getString(relationship.domainBlocking ? R.string.unblock_domain : R.string.block_domain, account.getDomain()));
|
||||
blockDomain.setVisible(true);
|
||||
}else{
|
||||
blockDomain.setVisible(false);
|
||||
}
|
||||
if(!account.isLocal())
|
||||
menu.findItem(R.id.block_domain).setTitle(getString(relationship.domainBlocking ? R.string.unblock_domain : R.string.block_domain, account.getDomain()));
|
||||
else
|
||||
menu.findItem(R.id.block_domain).setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -891,11 +895,11 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
intent.putExtra(Intent.EXTRA_TEXT, account.url);
|
||||
startActivity(Intent.createChooser(intent, item.getTitle()));
|
||||
}else if(id==R.id.mute){
|
||||
confirmToggleMuted();
|
||||
UiUtils.confirmToggleMuteUser(getActivity(), accountID, account, relationship.muting, this::updateRelationship);
|
||||
}else if(id==R.id.block){
|
||||
confirmToggleBlocked();
|
||||
UiUtils.confirmToggleBlockUser(getActivity(), accountID, account, relationship.blocking, this::updateRelationship);
|
||||
}else if(id==R.id.soft_block){
|
||||
confirmSoftBlockUser();
|
||||
UiUtils.confirmSoftBlockUser(getActivity(), accountID, account, this::updateRelationship);
|
||||
}else if(id==R.id.report){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
@@ -1197,7 +1201,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
updateMetadataHeight();
|
||||
|
||||
Toolbar toolbar=getToolbar();
|
||||
Drawable close=getToolbarContext().getDrawable(R.drawable.ic_baseline_close_24).mutate();
|
||||
Drawable close=getToolbarContext().getDrawable(R.drawable.ic_fluent_dismiss_24_regular).mutate();
|
||||
close.setTint(UiUtils.getThemeColor(getToolbarContext(), R.attr.colorM3OnSurfaceVariant));
|
||||
toolbar.setNavigationIcon(close);
|
||||
toolbar.setNavigationContentDescription(R.string.discard);
|
||||
@@ -1303,18 +1307,6 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
private void confirmToggleMuted(){
|
||||
UiUtils.confirmToggleMuteUser(getActivity(), accountID, account, relationship.muting, this::updateRelationship);
|
||||
}
|
||||
|
||||
private void confirmToggleBlocked(){
|
||||
UiUtils.confirmToggleBlockUser(getActivity(), accountID, account, relationship.blocking, this::updateRelationship);
|
||||
}
|
||||
|
||||
private void confirmSoftBlockUser(){
|
||||
UiUtils.confirmSoftBlockUser(getActivity(), accountID, account, this::updateRelationship);
|
||||
}
|
||||
|
||||
private void updateRelationship(Relationship r){
|
||||
relationship=r;
|
||||
updateRelationship();
|
||||
|
||||
@@ -120,6 +120,15 @@ public class ScheduledStatusListFragment extends BaseStatusListFragment<Schedule
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShown(){
|
||||
super.onShown();
|
||||
// because, for some reason, when navigating back from compose fragment,
|
||||
// match_parent would otherwise be incorrect (leaving a gap for the keyboard
|
||||
// where there is none)
|
||||
list.post(list::requestLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
currentRequest=new GetScheduledStatuses(offset==0 ? null : nextMaxID, count)
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.StatusMuteChangedEvent;
|
||||
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
|
||||
import org.joinmastodon.android.events.PollUpdatedEvent;
|
||||
import org.joinmastodon.android.events.ReblogDeletedEvent;
|
||||
import org.joinmastodon.android.events.RemoveAccountPostsEvent;
|
||||
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||
import org.joinmastodon.android.events.StatusCreatedEvent;
|
||||
@@ -31,6 +32,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -159,12 +161,12 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
|
||||
}
|
||||
}
|
||||
|
||||
protected Status getContentStatusByID(String id){
|
||||
public Status getContentStatusByID(String id){
|
||||
Status s=getStatusByID(id);
|
||||
return s==null ? null : s.getContentStatus();
|
||||
}
|
||||
|
||||
protected Status getStatusByID(String id){
|
||||
public Status getStatusByID(String id){
|
||||
for(Status s:data){
|
||||
if(s.id.equals(id)){
|
||||
return s;
|
||||
@@ -191,43 +193,58 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeStatus(Status status){
|
||||
data.remove(status);
|
||||
preloadedData.remove(status);
|
||||
int index=-1, ancestorFirstIndex = -1, ancestorLastIndex = -1;
|
||||
for(int i=0;i<displayItems.size();i++){
|
||||
StatusDisplayItem item = displayItems.get(i);
|
||||
if(status.id.equals(item.parentID)){
|
||||
index=i;
|
||||
break;
|
||||
}
|
||||
if (item.parentID.equals(status.inReplyToId)) {
|
||||
if (ancestorFirstIndex == -1) ancestorFirstIndex = i;
|
||||
ancestorLastIndex = i;
|
||||
private void iterateRemoveStatus(List<Status> l, String id){
|
||||
Iterator<Status> it=l.iterator();
|
||||
while(it.hasNext()){
|
||||
if(it.next().getContentStatus().id.equals(id)){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeStatusDisplayItems(Status status, int index, int ancestorFirstIndex, int ancestorLastIndex, boolean deleteContent){
|
||||
// did we find an ancestor that is also the status' neighbor?
|
||||
if (ancestorFirstIndex >= 0 && ancestorLastIndex == index - 1) {
|
||||
for (int i = ancestorFirstIndex; i <= ancestorLastIndex; i++) {
|
||||
StatusDisplayItem item = displayItems.get(i);
|
||||
if(ancestorFirstIndex>=0 && ancestorLastIndex==index-1){
|
||||
for(int i=ancestorFirstIndex; i<=ancestorLastIndex; i++){
|
||||
StatusDisplayItem item=displayItems.get(i);
|
||||
String id=deleteContent ? item.getContentID() : item.parentID;
|
||||
// update ancestor to have no descendant anymore
|
||||
if (item.parentID.equals(status.inReplyToId)) item.hasDescendantNeighbor = false;
|
||||
if(id.equals(status.inReplyToId)) item.hasDescendantNeighbor=false;
|
||||
}
|
||||
adapter.notifyItemRangeChanged(ancestorFirstIndex, ancestorLastIndex - ancestorFirstIndex + 1);
|
||||
adapter.notifyItemRangeChanged(ancestorFirstIndex, ancestorLastIndex-ancestorFirstIndex+1);
|
||||
}
|
||||
|
||||
if(index==-1)
|
||||
return;
|
||||
if(index==-1) return;
|
||||
int lastIndex;
|
||||
for(lastIndex=index;lastIndex<displayItems.size();lastIndex++){
|
||||
if(!displayItems.get(lastIndex).parentID.equals(status.id))
|
||||
break;
|
||||
StatusDisplayItem item=displayItems.get(lastIndex);
|
||||
String id=deleteContent ? item.getContentID() : item.parentID;
|
||||
if(!id.equals(status.id)) break;
|
||||
}
|
||||
displayItems.subList(index, lastIndex).clear();
|
||||
adapter.notifyItemRangeRemoved(index, lastIndex-index);
|
||||
}
|
||||
|
||||
protected void removeStatus(Status status){
|
||||
boolean deleteContent=status==status.getContentStatus();
|
||||
int ancestorFirstIndex=-1, ancestorLastIndex=-1;
|
||||
for(int i=0;i<displayItems.size();i++){
|
||||
StatusDisplayItem item=displayItems.get(i);
|
||||
String id=deleteContent ? item.getContentID() : item.parentID;
|
||||
if(id.equals(status.id)){
|
||||
removeStatusDisplayItems(status, i, ancestorFirstIndex, ancestorLastIndex, deleteContent);
|
||||
ancestorFirstIndex=ancestorLastIndex=-1;
|
||||
continue;
|
||||
}
|
||||
if(id.equals(status.inReplyToId)){
|
||||
if(ancestorFirstIndex==-1) ancestorFirstIndex=i;
|
||||
ancestorLastIndex=i;
|
||||
}
|
||||
}
|
||||
iterateRemoveStatus(data, status.id);
|
||||
iterateRemoveStatus(preloadedData, status.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
@@ -316,6 +333,18 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
|
||||
removeStatus(status);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onReblogDeleted(ReblogDeletedEvent ev){
|
||||
if(!ev.accountID.equals(accountID))
|
||||
return;
|
||||
for(Status item : data){
|
||||
if(item.getContentStatus().id.equals(ev.statusID) && item.reblog!=null){
|
||||
removeStatus(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusCreated(StatusCreatedEvent ev){
|
||||
if(!ev.accountID.equals(accountID))
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
@@ -65,6 +66,8 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
accountID=getArguments().getString("account");
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -258,7 +261,7 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
|
||||
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
relationship=relationships.get(item.account.id);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
|
||||
|
||||
if(relationship==null){
|
||||
actionWrap.setVisibility(View.GONE);
|
||||
|
||||
@@ -2,8 +2,8 @@ package org.joinmastodon.android.fragments.discover;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
@@ -15,14 +15,12 @@ import org.joinmastodon.android.fragments.IsOnTop;
|
||||
import org.joinmastodon.android.fragments.ScrollableToTop;
|
||||
import org.joinmastodon.android.model.Card;
|
||||
import org.joinmastodon.android.model.viewmodel.CardViewModel;
|
||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
|
||||
import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -33,11 +31,9 @@ import me.grishka.appkit.api.SimpleCallback;
|
||||
import me.grishka.appkit.fragments.BaseRecyclerFragment;
|
||||
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.ListImageLoaderAdapter;
|
||||
import me.grishka.appkit.imageloader.ListImageLoaderWrapper;
|
||||
import me.grishka.appkit.imageloader.RecyclerViewDelegate;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
@@ -61,6 +57,8 @@ public class DiscoverNewsFragment extends BaseRecyclerFragment<CardViewModel> im
|
||||
super.onCreate(savedInstanceState);
|
||||
accountID=getArguments().getString("account");
|
||||
bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_LINKS, accountID);
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.joinmastodon.android.fragments.discover;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -10,8 +11,6 @@ import org.joinmastodon.android.api.requests.trends.GetTrendingHashtags;
|
||||
import org.joinmastodon.android.fragments.IsOnTop;
|
||||
import org.joinmastodon.android.fragments.ScrollableToTop;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||
import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.ui.views.HashtagChartView;
|
||||
|
||||
@@ -35,6 +34,8 @@ public class TrendingHashtagsFragment extends BaseRecyclerFragment<Hashtag> impl
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
accountID=getArguments().getString("account");
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -83,9 +83,10 @@ public class CustomWelcomeFragment extends InstanceCatalogFragment {
|
||||
|
||||
@Override
|
||||
protected void updateFilteredList(){
|
||||
boolean addFakeInstance = currentSearchQuery.length()>0 && currentSearchQuery.matches("^\\S+\\.[^\\.]+$");
|
||||
String query=getCurrentSearchQuery();
|
||||
boolean addFakeInstance=query.length()>0 && query.matches("^\\S+\\.[^\\.]+$");
|
||||
if(addFakeInstance){
|
||||
fakeInstance.domain=fakeInstance.normalizedDomain=currentSearchQuery;
|
||||
fakeInstance.domain=fakeInstance.normalizedDomain=query;
|
||||
fakeInstance.description=getString(R.string.loading_instance);
|
||||
if(filteredData.size()>0 && filteredData.get(0)==fakeInstance){
|
||||
if(list.findViewHolderForAdapterPosition(1) instanceof InstanceViewHolder ivh){
|
||||
@@ -99,12 +100,12 @@ public class CustomWelcomeFragment extends InstanceCatalogFragment {
|
||||
}
|
||||
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
||||
filteredData.clear();
|
||||
if(currentSearchQuery.length()>0){
|
||||
if(query.length()>0){
|
||||
boolean foundExactMatch=false;
|
||||
for(CatalogInstance inst:data){
|
||||
if(inst.normalizedDomain.contains(currentSearchQuery)){
|
||||
if(inst.normalizedDomain.contains(query)){
|
||||
filteredData.add(inst);
|
||||
if(inst.normalizedDomain.equals(currentSearchQuery))
|
||||
if(inst.normalizedDomain.equals(query))
|
||||
foundExactMatch=true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ abstract class InstanceCatalogFragment extends MastodonRecyclerFragment<CatalogI
|
||||
currentSearchQuery=searchEdit.getText().toString().toLowerCase().trim();
|
||||
updateFilteredList();
|
||||
searchEdit.removeCallbacks(searchDebouncer);
|
||||
Instance instance=instancesCache.get(normalizeInstanceDomain(currentSearchQuery));
|
||||
Instance instance=instancesCache.get(normalizeInstanceDomain(getCurrentSearchQuery()));
|
||||
if(instance==null){
|
||||
showProgressDialog();
|
||||
loadInstanceInfo(currentSearchQuery, false);
|
||||
loadInstanceInfo(getCurrentSearchQuery(), false);
|
||||
}else{
|
||||
proceedWithAuthOrSignup(instance);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ abstract class InstanceCatalogFragment extends MastodonRecyclerFragment<CatalogI
|
||||
protected void onSearchChangedDebounced(){
|
||||
currentSearchQuery=searchEdit.getText().toString().toLowerCase().trim();
|
||||
updateFilteredList();
|
||||
loadInstanceInfo(currentSearchQuery, false);
|
||||
loadInstanceInfo(getCurrentSearchQuery(), false);
|
||||
}
|
||||
|
||||
protected List<CatalogInstance> sortInstances(List<CatalogInstance> result){
|
||||
@@ -126,9 +126,16 @@ abstract class InstanceCatalogFragment extends MastodonRecyclerFragment<CatalogI
|
||||
instanceProgressDialog.show();
|
||||
}
|
||||
|
||||
protected String getCurrentSearchQuery(){
|
||||
String[] parts=currentSearchQuery.split("@");
|
||||
return parts.length>0 ? parts[parts.length-1] : "";
|
||||
}
|
||||
|
||||
protected String normalizeInstanceDomain(String _domain){
|
||||
if(TextUtils.isEmpty(_domain))
|
||||
return null;
|
||||
String[] parts=_domain.split("@");
|
||||
_domain=parts[parts.length - 1];
|
||||
if(_domain.contains(":")){
|
||||
try{
|
||||
_domain=Uri.parse(_domain).getAuthority();
|
||||
@@ -198,7 +205,7 @@ abstract class InstanceCatalogFragment extends MastodonRecyclerFragment<CatalogI
|
||||
instanceProgressDialog=null;
|
||||
proceedWithAuthOrSignup(result);
|
||||
}
|
||||
if(Objects.equals(domain, currentSearchQuery) || Objects.equals(currentSearchQuery, redirects.get(domain)) || Objects.equals(currentSearchQuery, redirectsInverse.get(domain))){
|
||||
if(Objects.equals(domain, getCurrentSearchQuery()) || Objects.equals(getCurrentSearchQuery(), redirects.get(domain)) || Objects.equals(getCurrentSearchQuery(), redirectsInverse.get(domain))){
|
||||
boolean found=false;
|
||||
for(CatalogInstance ci:filteredData){
|
||||
if(ci.domain.equals(domain) && ci!=fakeInstance){
|
||||
|
||||
@@ -227,7 +227,7 @@ public class ReportDoneFragment extends MastodonToolbarFragment{
|
||||
|
||||
@Override
|
||||
protected int getNavigationIconDrawableResource(){
|
||||
return R.drawable.ic_baseline_close_24;
|
||||
return R.drawable.ic_fluent_dismiss_24_regular;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.joinmastodon.android.api.requests.instance.GetInstance;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -15,9 +13,6 @@ import java.time.LocalDate;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
|
||||
/**
|
||||
* Represents a user of Mastodon and their associated profile.
|
||||
*/
|
||||
@@ -163,26 +158,27 @@ public class Account extends BaseModel implements Searchable{
|
||||
if(fields!=null){
|
||||
for(AccountField f:fields)
|
||||
f.postprocess();
|
||||
} else {
|
||||
fields = Collections.emptyList();
|
||||
}else{
|
||||
fields=Collections.emptyList();
|
||||
}
|
||||
if(emojis!=null){
|
||||
for(Emoji e:emojis)
|
||||
e.postprocess();
|
||||
} else {
|
||||
emojis = Collections.emptyList();
|
||||
}else{
|
||||
emojis=Collections.emptyList();
|
||||
}
|
||||
if(moved!=null)
|
||||
moved.postprocess();
|
||||
if(fqn == null) fqn = getFullyQualifiedName();
|
||||
if(id == null) id = "";
|
||||
if(username == null) username = "";
|
||||
if(fqn==null) fqn=getFullyQualifiedName();
|
||||
if(id==null) id="";
|
||||
if(username==null) username="";
|
||||
if(TextUtils.isEmpty(displayName))
|
||||
displayName = !TextUtils.isEmpty(username) ? username : "";
|
||||
if(acct == null) acct = "";
|
||||
if(url == null) url = "";
|
||||
if(note == null) note = "";
|
||||
if(avatar == null) avatar = "";
|
||||
displayName=!TextUtils.isEmpty(username) ? username : "";
|
||||
if(acct==null) acct="";
|
||||
if(url==null) url="";
|
||||
if(note==null) note="";
|
||||
if(avatar==null) avatar="";
|
||||
if(displayName!=null) displayName='\u2068'+displayName+'\u2069';
|
||||
}
|
||||
|
||||
public boolean isLocal(){
|
||||
|
||||
@@ -52,7 +52,7 @@ public class Announcement extends BaseModel implements DisplayItemsParent {
|
||||
|
||||
public Status toStatus() {
|
||||
Status s=Status.ofFake(id, content, publishedAt);
|
||||
s.createdAt=startsAt != null ? startsAt : publishedAt;
|
||||
s.createdAt=startsAt != null ? startsAt : publishedAt;
|
||||
s.reactions=reactions;
|
||||
if(updatedAt != null) s.editedAt=updatedAt;
|
||||
return s;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class SearchViewHelper{
|
||||
searchLayout.addView(searchEdit, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
|
||||
|
||||
clearSearchButton=new ImageButton(context);
|
||||
clearSearchButton.setImageResource(R.drawable.ic_baseline_close_24);
|
||||
clearSearchButton.setImageResource(R.drawable.ic_fluent_dismiss_24_regular);
|
||||
clearSearchButton.setContentDescription(context.getString(R.string.clear));
|
||||
clearSearchButton.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(context, R.attr.colorM3OnSurfaceVariant)));
|
||||
clearSearchButton.setBackground(UiUtils.getThemeDrawable(toolbarContext, android.R.attr.actionBarItemBackground));
|
||||
|
||||
@@ -149,7 +149,7 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
|
||||
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
relationship=item.parentFragment.getRelationship(item.account.id);
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null,true, false, false, item.account);
|
||||
|
||||
if(item.notification.type==Notification.Type.FOLLOW_REQUEST && (relationship==null || !relationship.followedBy)){
|
||||
actionWrap.setVisibility(View.GONE);
|
||||
|
||||
@@ -1,80 +1,52 @@
|
||||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.Image;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Card;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.SingleImagePhotoViewerListener;
|
||||
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class FileStatusDisplayItem extends StatusDisplayItem{
|
||||
private final Status status;
|
||||
private final Attachment attachment;
|
||||
|
||||
public FileStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Attachment attachment, Status status){
|
||||
public FileStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Attachment attachment) {
|
||||
super(parentID, parentFragment);
|
||||
this.status=status;
|
||||
this.attachment=attachment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(){
|
||||
public Type getType() {
|
||||
return Type.FILE;
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<FileStatusDisplayItem>{
|
||||
public static class Holder extends StatusDisplayItem.Holder<FileStatusDisplayItem> {
|
||||
private final TextView title, domain;
|
||||
private final ImageView icon;
|
||||
private final Context context;
|
||||
|
||||
public Holder(Context context, ViewGroup parent){
|
||||
public Holder(Context context, ViewGroup parent) {
|
||||
super(context, R.layout.display_item_file, parent);
|
||||
title=findViewById(R.id.title);
|
||||
domain=findViewById(R.id.domain);
|
||||
icon=findViewById(R.id.imageView);
|
||||
this.context=context;
|
||||
|
||||
findViewById(R.id.inner).setOnClickListener(this::onClick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(FileStatusDisplayItem item) {
|
||||
Uri url = Uri.parse(getUrl());
|
||||
|
||||
title.setText(item.attachment.description != null
|
||||
? item.attachment.description
|
||||
: url.getLastPathSegment());
|
||||
|
||||
title.setEllipsize(item.attachment.description != null ? TextUtils.TruncateAt.END : TextUtils.TruncateAt.MIDDLE);
|
||||
domain.setText(url.getHost());
|
||||
|
||||
icon.setImageDrawable(context.getDrawable(R.drawable.ic_fluent_attach_24_regular));
|
||||
title.setText(item.attachment.description != null
|
||||
? item.attachment.description
|
||||
: url.getLastPathSegment());
|
||||
title.setEllipsize(item.attachment.description != null ? TextUtils.TruncateAt.END : TextUtils.TruncateAt.MIDDLE);
|
||||
domain.setText(url.getHost());
|
||||
}
|
||||
|
||||
private void onClick(View v) {
|
||||
UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), getUrl());
|
||||
UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), getUrl());
|
||||
}
|
||||
|
||||
private String getUrl() {
|
||||
|
||||
@@ -18,7 +18,7 @@ import me.grishka.appkit.utils.V;
|
||||
|
||||
public class GapStatusDisplayItem extends StatusDisplayItem{
|
||||
public boolean loading;
|
||||
private Status status;
|
||||
private final Status status;
|
||||
|
||||
public GapStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status){
|
||||
super(parentID, parentFragment);
|
||||
|
||||
@@ -139,7 +139,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView name, time, username, extraText, pronouns;
|
||||
private final TextView name, time, username, extraText;
|
||||
private final View collapseBtn, timeUsernameSeparator;
|
||||
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator, markAsRead, collapseBtnIcon, botIcon;
|
||||
private final PopupMenu optionsMenu;
|
||||
@@ -166,7 +166,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
collapseBtn=findViewById(R.id.collapse_btn);
|
||||
collapseBtnIcon=findViewById(R.id.collapse_btn_icon);
|
||||
extraText=findViewById(R.id.extra_text);
|
||||
pronouns=findViewById(R.id.pronouns);
|
||||
avatar.setOnClickListener(this::onAvaClick);
|
||||
avatar.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||
avatar.setClipToOutline(true);
|
||||
@@ -211,7 +210,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
}else if(item.scheduledStatus!=null){
|
||||
args.putString("sourceText", item.status.text);
|
||||
args.putString("sourceSpoiler", item.status.spoilerText);
|
||||
args.putBoolean("redraftStatus", true);
|
||||
args.putParcelable("scheduledStatus", Parcels.wrap(item.scheduledStatus));
|
||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||
}else{
|
||||
@@ -221,14 +219,14 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
public void onSuccess(GetStatusSourceText.Response result){
|
||||
args.putString("sourceText", result.text);
|
||||
args.putString("sourceSpoiler", result.spoilerText);
|
||||
if (result.contentType != null) {
|
||||
if(result.contentType!=null){
|
||||
args.putString("sourceContentType", result.contentType.name());
|
||||
}
|
||||
if (redraft) {
|
||||
if(redraft){
|
||||
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{
|
||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||
}, true);
|
||||
} else {
|
||||
}else{
|
||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||
}
|
||||
}
|
||||
@@ -245,7 +243,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
if (item.scheduledStatus != null) {
|
||||
UiUtils.confirmDeleteScheduledPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.scheduledStatus, ()->{});
|
||||
} else {
|
||||
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{});
|
||||
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{}, false);
|
||||
}
|
||||
}else if(id==R.id.pin || id==R.id.unpin) {
|
||||
UiUtils.confirmPinPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, !item.status.pinned, s->{});
|
||||
@@ -337,7 +335,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
if(TextUtils.isEmpty(item.extraText)){
|
||||
if (item.status != null) {
|
||||
boolean displayPronouns=item.parentFragment instanceof ThreadFragment ? GlobalUserPreferences.displayPronounsInThreads : GlobalUserPreferences.displayPronounsInTimelines;
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, pronouns, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
|
||||
}
|
||||
}else{
|
||||
extraText.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -10,10 +10,8 @@ import android.text.SpannableStringBuilder;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
@@ -40,7 +38,7 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
private StatusPrivacy visibility;
|
||||
@DrawableRes
|
||||
private int iconEnd;
|
||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper(), fullTextEmojiHelper;
|
||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||
private View.OnClickListener handleClick;
|
||||
public boolean needBottomPadding;
|
||||
ReblogOrReplyLineStatusDisplayItem extra;
|
||||
@@ -58,21 +56,13 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
HtmlParser.parseCustomEmoji(ssb, emojis);
|
||||
this.text=ssb;
|
||||
emojiHelper.setText(ssb);
|
||||
this.fullText=fullText;
|
||||
this.icon=icon;
|
||||
this.status=status;
|
||||
this.handleClick=handleClick;
|
||||
TypedValue outValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
|
||||
updateVisibility(visibility);
|
||||
|
||||
if (fullText != null) {
|
||||
fullTextEmojiHelper = new CustomEmojiHelper();
|
||||
SpannableStringBuilder fullTextSsb = new SpannableStringBuilder(fullText);
|
||||
HtmlParser.parseCustomEmoji(fullTextSsb, emojis);
|
||||
this.fullText=fullTextSsb;
|
||||
fullTextEmojiHelper.setText(fullTextSsb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateVisibility(StatusPrivacy visibility) {
|
||||
@@ -92,34 +82,27 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
@Override
|
||||
public int getImageCount(){
|
||||
return emojiHelper.getImageCount();
|
||||
return emojiHelper.getImageCount() + (extra!=null ? extra.emojiHelper.getImageCount() : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
return emojiHelper.getImageRequest(index);
|
||||
CustomEmojiHelper helper=index<emojiHelper.getImageCount() ? emojiHelper : extra.emojiHelper;
|
||||
return helper.getImageRequest(index%emojiHelper.getImageCount());
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<ReblogOrReplyLineStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView text, extraText;
|
||||
private final View separator;
|
||||
private final ViewGroup parent;
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_reblog_or_reply_line, parent);
|
||||
this.parent = parent;
|
||||
text=findViewById(R.id.text);
|
||||
extraText=findViewById(R.id.extra_text);
|
||||
separator=findViewById(R.id.separator);
|
||||
if (GlobalUserPreferences.compactReblogReplyLine) {
|
||||
parent.addOnLayoutChangeListener((v, l, t, right, b, ol, ot, oldRight, ob) -> {
|
||||
if (right != oldRight) layoutLine();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void bindLine(ReblogOrReplyLineStatusDisplayItem item, TextView text) {
|
||||
if (item.fullText != null) text.setContentDescription(item.fullText);
|
||||
text.setText(item.text);
|
||||
text.setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, item.iconEnd, 0);
|
||||
text.setOnClickListener(item.handleClick);
|
||||
@@ -133,7 +116,10 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
case LOCAL -> R.string.sk_local_only;
|
||||
default -> 0;
|
||||
} : 0;
|
||||
if (visibilityText != 0) text.setContentDescription(item.text + " (" + ctx.getString(visibilityText) + ")");
|
||||
String visibilityDescription=visibilityText!=0 ? " (" + ctx.getString(visibilityText) + ")" : null;
|
||||
text.setContentDescription(item.fullText==null && visibilityDescription==null ? null :
|
||||
(item.fullText!=null ? item.fullText : item.text)
|
||||
+ (visibilityDescription!=null ? visibilityDescription : ""));
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N)
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(text);
|
||||
text.setCompoundDrawableTintList(text.getTextColors());
|
||||
@@ -146,31 +132,14 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
extraText.setVisibility(item.extra == null ? View.GONE : View.VISIBLE);
|
||||
separator.setVisibility(item.extra == null ? View.GONE : View.VISIBLE);
|
||||
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), item.needBottomPadding ? V.dp(16) : 0);
|
||||
layoutLine();
|
||||
}
|
||||
|
||||
private void layoutLine() {
|
||||
// layout line only if above header, compact and has extra
|
||||
if (!GlobalUserPreferences.compactReblogReplyLine || item.extra == null) return;
|
||||
itemView.measure(
|
||||
View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY),
|
||||
View.MeasureSpec.UNSPECIFIED);
|
||||
boolean isVertical = ((LinearLayout) itemView).getOrientation() == LinearLayout.VERTICAL;
|
||||
extraText.setPaddingRelative(extraText.getPaddingStart(), item.extra != null && isVertical ? 0 : V.dp(16), extraText.getPaddingEnd(), extraText.getPaddingBottom());
|
||||
separator.setVisibility(item.extra != null && !isVertical ? View.VISIBLE : View.GONE);
|
||||
((LinearLayout) itemView).removeView(extraText);
|
||||
if (isVertical) ((LinearLayout) itemView).addView(extraText);
|
||||
else ((LinearLayout) itemView).addView(extraText, 0);
|
||||
text.setText(isVertical ? item.fullText : item.text);
|
||||
if (item.extra != null) {
|
||||
extraText.setText(isVertical ? item.extra.fullText : item.extra.text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable image){
|
||||
item.emojiHelper.setImageDrawable(index, image);
|
||||
CustomEmojiHelper helper=index<item.emojiHelper.getImageCount() ? item.emojiHelper : item.extra.emojiHelper;
|
||||
helper.setImageDrawable(index%item.emojiHelper.getImageCount(), image);
|
||||
text.invalidate();
|
||||
extraText.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,8 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountLocalPreferences;
|
||||
@@ -22,6 +24,7 @@ import org.joinmastodon.android.fragments.HashtagTimelineFragment;
|
||||
import org.joinmastodon.android.fragments.HomeTabFragment;
|
||||
import org.joinmastodon.android.fragments.ListTimelineFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.StatusListFragment;
|
||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
@@ -58,10 +61,10 @@ public abstract class StatusDisplayItem{
|
||||
public boolean inset;
|
||||
public int index;
|
||||
public boolean
|
||||
hasDescendantNeighbor = false,
|
||||
hasAncestoringNeighbor = false,
|
||||
isMainStatus = true,
|
||||
isDirectDescendant = false;
|
||||
hasDescendantNeighbor=false,
|
||||
hasAncestoringNeighbor=false,
|
||||
isMainStatus=true,
|
||||
isDirectDescendant=false;
|
||||
|
||||
public static final int FLAG_INSET=1;
|
||||
public static final int FLAG_NO_FOOTER=1 << 1;
|
||||
@@ -89,6 +92,16 @@ public abstract class StatusDisplayItem{
|
||||
this.parentFragment=parentFragment;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getContentID(){
|
||||
if(parentFragment instanceof StatusListFragment slf){
|
||||
Status s=slf.getContentStatusByID(parentID);
|
||||
return s!=null ? s.id : parentID;
|
||||
}else{
|
||||
return parentID;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Type getType();
|
||||
|
||||
public int getImageCount(){
|
||||
@@ -131,7 +144,7 @@ public abstract class StatusDisplayItem{
|
||||
String parentID = parent.getID();
|
||||
String text = threadReply ? fragment.getString(R.string.sk_show_thread)
|
||||
: account == null ? fragment.getString(R.string.sk_in_reply)
|
||||
: GlobalUserPreferences.compactReblogReplyLine && status.reblog != null ? account.displayName
|
||||
: status.reblog != null ? account.displayName
|
||||
: fragment.getString(R.string.in_reply_to, account.displayName);
|
||||
String fullText = threadReply ? fragment.getString(R.string.sk_show_thread)
|
||||
: account == null ? fragment.getString(R.string.sk_in_reply)
|
||||
@@ -169,7 +182,7 @@ public abstract class StatusDisplayItem{
|
||||
statusForContent.rebloggedBy = status.account;
|
||||
|
||||
String fullText = fragment.getString(R.string.user_boosted, status.account.displayName);
|
||||
String text = GlobalUserPreferences.compactReblogReplyLine && replyLine != null ? status.account.displayName : fullText;
|
||||
String text = replyLine != null ? status.account.displayName : fullText;
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, text, status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20sp_filled, isOwnPost ? status.visibility : null, i->{
|
||||
args.putParcelable("profileAccount", Parcels.wrap(status.account));
|
||||
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
|
||||
@@ -197,7 +210,7 @@ public abstract class StatusDisplayItem{
|
||||
.map(ReblogOrReplyLineStatusDisplayItem.class::cast)
|
||||
.findFirst();
|
||||
|
||||
if (primaryLine.isPresent() && GlobalUserPreferences.compactReblogReplyLine) {
|
||||
if (primaryLine.isPresent()) {
|
||||
primaryLine.get().extra = replyLine;
|
||||
} else {
|
||||
items.add(replyLine);
|
||||
|
||||
@@ -210,6 +210,7 @@ public class HtmlParser{
|
||||
}
|
||||
|
||||
public static void parseCustomEmoji(SpannableStringBuilder ssb, List<Emoji> emojis){
|
||||
if(emojis==null) return;
|
||||
Map<String, Emoji> emojiByCode =
|
||||
emojis.stream()
|
||||
.collect(
|
||||
|
||||
@@ -68,6 +68,7 @@ import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.CacheController;
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.api.MastodonErrorResponse;
|
||||
import org.joinmastodon.android.api.StatusInteractionController;
|
||||
@@ -634,23 +635,25 @@ public class UiUtils {
|
||||
.show();
|
||||
}
|
||||
|
||||
public static void confirmDeletePost(Activity activity, String accountID, Status status, Consumer<Status> resultCallback) {
|
||||
confirmDeletePost(activity, accountID, status, resultCallback, false);
|
||||
}
|
||||
|
||||
public static void confirmDeletePost(Activity activity, String accountID, Status status, Consumer<Status> resultCallback, boolean forRedraft) {
|
||||
Status s=status.getContentStatus();
|
||||
showConfirmationAlert(activity,
|
||||
forRedraft ? R.string.sk_confirm_delete_and_redraft_title : R.string.confirm_delete_title,
|
||||
forRedraft ? R.string.sk_confirm_delete_and_redraft : R.string.confirm_delete,
|
||||
forRedraft ? R.string.sk_delete_and_redraft : R.string.delete,
|
||||
forRedraft ? R.drawable.ic_fluent_arrow_clockwise_28_regular : R.drawable.ic_fluent_delete_28_regular,
|
||||
() -> new DeleteStatus(status.id)
|
||||
() -> new DeleteStatus(s.id)
|
||||
.setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Status result) {
|
||||
resultCallback.accept(result);
|
||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().deleteStatus(status.id);
|
||||
E.post(new StatusDeletedEvent(status.id, accountID));
|
||||
CacheController cache=AccountSessionManager.get(accountID).getCacheController();
|
||||
cache.deleteStatus(s.id);
|
||||
E.post(new StatusDeletedEvent(s.id, accountID));
|
||||
if(status!=s){
|
||||
cache.deleteStatus(status.id);
|
||||
E.post(new StatusDeletedEvent(status.id, accountID));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -852,32 +855,35 @@ public class UiUtils {
|
||||
() -> follow(activity, accountID, account, false, progressCallback, resultCallback),
|
||||
() -> progressCallback.accept(false));
|
||||
} else {
|
||||
follow(activity, accountID, account, false, progressCallback, resultCallback);
|
||||
Runnable action=()->{
|
||||
progressCallback.accept(true);
|
||||
new SetAccountFollowed(account.id, !relationship.following && !relationship.requested, true)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Relationship result){
|
||||
resultCallback.accept(result);
|
||||
progressCallback.accept(false);
|
||||
if(!result.following && !result.requested){
|
||||
E.post(new RemoveAccountPostsEvent(accountID, account.id, true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
error.showToast(activity);
|
||||
progressCallback.accept(false);
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
};
|
||||
if(relationship.following && GlobalUserPreferences.confirmUnfollow){
|
||||
showConfirmationAlert(activity, null, activity.getString(R.string.unfollow_confirmation, account.getDisplayUsername()), activity.getString(R.string.unfollow), R.drawable.ic_fluent_person_delete_24_regular, action);
|
||||
}else{
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void follow(Activity activity, String accountID, Account account, boolean followed, Consumer<Boolean> progressCallback, Consumer<Relationship> resultCallback) {
|
||||
progressCallback.accept(true);
|
||||
new SetAccountFollowed(account.id, followed, true, false)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Relationship result){
|
||||
resultCallback.accept(result);
|
||||
progressCallback.accept(false);
|
||||
if(!result.following && !result.requested){
|
||||
E.post(new RemoveAccountPostsEvent(accountID, account.id, true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
error.showToast(activity);
|
||||
progressCallback.accept(false);
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
|
||||
public static void handleFollowRequest(Activity activity, Account account, String accountID, @Nullable String notificationID, boolean accepted, Relationship relationship, Consumer<Relationship> resultCallback) {
|
||||
if (accepted) {
|
||||
@@ -1161,23 +1167,21 @@ public class UiUtils {
|
||||
return back;
|
||||
}
|
||||
|
||||
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, @Nullable TextView pronouns, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
|
||||
List<String> extraParts = extraText!=null && (localOnly || mentionedOnly) ? new ArrayList<>() : null;
|
||||
Optional<String> p=pronouns==null || !displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
|
||||
if(p.isPresent()) {
|
||||
HtmlParser.setTextWithCustomEmoji(pronouns, p.get(), account.emojis);
|
||||
pronouns.setVisibility(View.VISIBLE);
|
||||
}else if(pronouns!=null){
|
||||
pronouns.setVisibility(View.GONE);
|
||||
}
|
||||
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
|
||||
List<String> extraParts=new ArrayList<>();
|
||||
Optional<String> p=!displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
|
||||
|
||||
if(localOnly)
|
||||
extraParts.add(ctx.getString(R.string.sk_inline_local_only));
|
||||
if(mentionedOnly)
|
||||
extraParts.add(ctx.getString(R.string.sk_inline_direct));
|
||||
if(extraText!=null && extraParts!=null && !extraParts.isEmpty()) {
|
||||
String sepp = ctx.getString(R.string.sk_separator);
|
||||
String text = String.join(" " + sepp + " ", extraParts);
|
||||
if(account == null) extraText.setText(text);
|
||||
if(p.isPresent() && extraParts.isEmpty())
|
||||
extraParts.add(p.get());
|
||||
|
||||
if(extraText!=null && !extraParts.isEmpty()) {
|
||||
String sepp=ctx.getString(R.string.sk_separator);
|
||||
String text=String.join(" " + sepp + " ", extraParts);
|
||||
if(account==null) extraText.setText(text);
|
||||
else HtmlParser.setTextWithCustomEmoji(extraText, text, account.emojis);
|
||||
extraText.setVisibility(View.VISIBLE);
|
||||
return true;
|
||||
@@ -1753,14 +1757,17 @@ public class UiUtils {
|
||||
|
||||
Matcher matcher=trimPronouns.matcher(text);
|
||||
if(!matcher.find()) return null;
|
||||
String matched=matcher.group(1);
|
||||
String pronouns=matcher.group(1);
|
||||
// crude fix to allow for pronouns like "it(/she)"
|
||||
int missingClosingParens=0;
|
||||
for(char c : matched.toCharArray()){
|
||||
for(char c : pronouns.toCharArray()){
|
||||
if(c=='(') missingClosingParens++;
|
||||
if(c==')') missingClosingParens--;
|
||||
}
|
||||
return matched+")".repeat(Math.max(0, missingClosingParens));
|
||||
pronouns+=")".repeat(Math.max(0, missingClosingParens));
|
||||
// if ends with an un-closed custom emoji
|
||||
if(pronouns.matches("^.*\\s+:[a-zA-Z_]+$")) pronouns+=':';
|
||||
return pronouns;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/9475589/how-to-get-string-from-different-locales-in-android
|
||||
@@ -1772,7 +1779,7 @@ public class UiUtils {
|
||||
}
|
||||
|
||||
public static Optional<String> extractPronouns(Context context, @Nullable Account account) {
|
||||
if (account == null) return Optional.empty();
|
||||
if (account==null || account.fields==null) return Optional.empty();
|
||||
String localizedPronouns=context.getString(R.string.sk_pronouns_label).toLowerCase();
|
||||
|
||||
// higher = worse. the lowest number wins. also i'm sorry for writing this
|
||||
|
||||
@@ -4,11 +4,12 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@@ -19,6 +20,7 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
@@ -27,8 +29,8 @@ import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.R;
|
||||
@@ -51,11 +53,8 @@ import org.parceler.Parcel;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
@@ -204,6 +203,15 @@ public class ComposeMediaViewController{
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButton(ImageButton btn, @DrawableRes int drawableId, @StringRes int labelId){
|
||||
btn.setImageResource(drawableId);
|
||||
String label=fragment.getContext().getString(labelId);
|
||||
btn.setContentDescription(label);
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||
btn.setTooltipText(label);
|
||||
}
|
||||
}
|
||||
|
||||
private View createMediaAttachmentView(DraftMediaAttachment draft){
|
||||
View thumb=fragment.getActivity().getLayoutInflater().inflate(R.layout.compose_media_thumb, attachmentsView, false);
|
||||
ImageView img=thumb.findViewById(R.id.thumb);
|
||||
@@ -231,12 +239,11 @@ public class ComposeMediaViewController{
|
||||
draft.removeButton.setOnClickListener(this::onRemoveMediaAttachmentClick);
|
||||
draft.editButton.setTag(draft);
|
||||
|
||||
thumb.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||
thumb.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
||||
thumb.setClipToOutline(true);
|
||||
img.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||
img.setClipToOutline(true);
|
||||
|
||||
thumb.setBackgroundColor(UiUtils.getThemeColor(fragment.getActivity(), R.attr.colorM3Surface));
|
||||
thumb.setOnLongClickListener(v->{
|
||||
if(!v.hasTransientState() && attachments.size()>1){
|
||||
attachmentsView.startDragging(v);
|
||||
@@ -266,11 +273,11 @@ public class ComposeMediaViewController{
|
||||
draft.subtitleView.setText(subtitleRes);
|
||||
}
|
||||
draft.titleView.setText(fragment.getString(R.string.attachment_x_percent_uploaded, 0));
|
||||
draft.removeButton.setImageResource(R.drawable.ic_baseline_close_24);
|
||||
updateButton(draft.removeButton, R.drawable.ic_fluent_dismiss_24_regular, R.string.delete);
|
||||
|
||||
if(draft.state==AttachmentUploadState.ERROR){
|
||||
draft.titleView.setText(R.string.upload_failed);
|
||||
draft.editButton.setImageResource(R.drawable.ic_fluent_arrow_counterclockwise_24_regular);
|
||||
updateButton(draft.removeButton, R.drawable.ic_fluent_arrow_counterclockwise_24_regular, R.string.retry);
|
||||
draft.editButton.setOnClickListener(this::onRetryOrCancelMediaUploadClick);
|
||||
draft.progressBar.setVisibility(View.GONE);
|
||||
draft.setUseErrorColors(true);
|
||||
@@ -280,7 +287,7 @@ public class ComposeMediaViewController{
|
||||
draft.editButton.setOnClickListener(this::onEditMediaDescriptionClick);
|
||||
}else{
|
||||
draft.editButton.setVisibility(View.GONE);
|
||||
draft.removeButton.setImageResource(R.drawable.ic_baseline_close_24);
|
||||
updateButton(draft.removeButton, R.drawable.ic_fluent_dismiss_24_regular, R.string.delete);
|
||||
if(draft.state==AttachmentUploadState.PROCESSING){
|
||||
draft.titleView.setText(R.string.upload_processing);
|
||||
}else{
|
||||
@@ -374,7 +381,7 @@ public class ComposeMediaViewController{
|
||||
// attachment.retryButton.setContentDescription(fragment.getString(R.string.retry_upload));
|
||||
|
||||
V.setVisibilityAnimated(attachment.editButton, View.VISIBLE);
|
||||
attachment.editButton.setImageResource(R.drawable.ic_fluent_arrow_counterclockwise_24_regular);
|
||||
updateButton(attachment.editButton, R.drawable.ic_fluent_arrow_counterclockwise_24_regular, R.string.retry);
|
||||
attachment.editButton.setOnClickListener(ComposeMediaViewController.this::onRetryOrCancelMediaUploadClick);
|
||||
attachment.setUseErrorColors(true);
|
||||
V.setVisibilityAnimated(attachment.progressBar, View.GONE);
|
||||
@@ -478,8 +485,8 @@ public class ComposeMediaViewController{
|
||||
throw new IllegalStateException("Unexpected state "+attachment.state);
|
||||
attachment.uploadRequest=null;
|
||||
attachment.state=AttachmentUploadState.DONE;
|
||||
attachment.editButton.setImageResource(R.drawable.ic_fluent_edit_24_regular);
|
||||
attachment.removeButton.setImageResource(R.drawable.ic_fluent_delete_24_regular);
|
||||
updateButton(attachment.editButton, R.drawable.ic_fluent_edit_24_regular, R.string.sk_edit_alt_text);
|
||||
updateButton(attachment.removeButton, R.drawable.ic_fluent_dismiss_24_regular, R.string.delete);
|
||||
attachment.editButton.setOnClickListener(this::onEditMediaDescriptionClick);
|
||||
V.setVisibilityAnimated(attachment.progressBar, View.GONE);
|
||||
V.setVisibilityAnimated(attachment.editButton, View.VISIBLE);
|
||||
@@ -708,18 +715,21 @@ public class ComposeMediaViewController{
|
||||
if(errorTransitionAnimator!=null)
|
||||
errorTransitionAnimator.cancel();
|
||||
AnimatorSet set=new AnimatorSet();
|
||||
int color1, color2, color3;
|
||||
int defaultBg=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3Surface);
|
||||
int errorBg=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3ErrorContainer);
|
||||
int color2, color3;
|
||||
if(use){
|
||||
color1=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3ErrorContainer);
|
||||
color2=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3Error);
|
||||
color3=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3OnErrorContainer);
|
||||
}else{
|
||||
color1=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3Surface);
|
||||
color2=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3OnSurface);
|
||||
color3=UiUtils.getThemeColor(view.getContext(), R.attr.colorM3OnSurfaceVariant);
|
||||
}
|
||||
GradientDrawable bg=(GradientDrawable) view.getBackground().mutate();
|
||||
ValueAnimator bgAnim=ValueAnimator.ofArgb(use ? defaultBg : errorBg, use ? errorBg : defaultBg);
|
||||
bgAnim.addUpdateListener(anim->bg.setColor((Integer) anim.getAnimatedValue()));
|
||||
set.playTogether(
|
||||
ObjectAnimator.ofArgb(view, "backgroundColor", ((ColorDrawable)view.getBackground()).getColor(), color1),
|
||||
bgAnim,
|
||||
ObjectAnimator.ofArgb(titleView, "textColor", titleView.getCurrentTextColor(), color2),
|
||||
ObjectAnimator.ofArgb(subtitleView, "textColor", subtitleView.getCurrentTextColor(), color3),
|
||||
ObjectAnimator.ofArgb(removeButton.getDrawable(), "tint", subtitleView.getCurrentTextColor(), color3)
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.app.Fragment;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.TypefaceSpan;
|
||||
@@ -25,6 +26,7 @@ import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.ListsFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.report.ReportReasonChoiceFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
@@ -98,6 +100,9 @@ public class AccountViewHolder extends BindableViewHolder<AccountViewModel> impl
|
||||
contextMenu=new PopupMenu(fragment.getActivity(), menuAnchor);
|
||||
contextMenu.inflate(R.menu.profile);
|
||||
contextMenu.setOnMenuItemClickListener(this::onContextMenuItemSelected);
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P && !UiUtils.isEMUI())
|
||||
contextMenu.getMenu().setGroupDividerEnabled(true);
|
||||
UiUtils.enablePopupMenuIcons(fragment.getContext(), contextMenu);
|
||||
|
||||
setStyle(AccessoryType.BUTTON, false);
|
||||
}
|
||||
@@ -212,14 +217,20 @@ public class AccountViewHolder extends BindableViewHolder<AccountViewModel> impl
|
||||
Menu menu=contextMenu.getMenu();
|
||||
Account account=item.account;
|
||||
|
||||
menu.findItem(R.id.share).setTitle(fragment.getString(R.string.share_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.manage_user_lists).setTitle(fragment.getString(R.string.sk_lists_with_user, account.getShortUsername()));
|
||||
menu.findItem(R.id.mute).setTitle(fragment.getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.block).setTitle(fragment.getString(relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.report).setTitle(fragment.getString(R.string.report_user, account.getDisplayUsername()));
|
||||
MenuItem mute=menu.findItem(R.id.mute);
|
||||
mute.setTitle(fragment.getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getShortUsername()));
|
||||
mute.setIcon(relationship.muting ? R.drawable.ic_fluent_speaker_0_24_regular : R.drawable.ic_fluent_speaker_off_24_regular);
|
||||
UiUtils.insetPopupMenuIcon(fragment.getContext(), mute);
|
||||
menu.findItem(R.id.block).setTitle(fragment.getString(relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getShortUsername()));
|
||||
menu.findItem(R.id.report).setTitle(fragment.getString(R.string.report_user, account.getShortUsername()));
|
||||
menu.findItem(R.id.manage_user_lists).setVisible(relationship.following);
|
||||
menu.findItem(R.id.soft_block).setVisible(relationship.followedBy && !relationship.following);
|
||||
MenuItem hideBoosts=menu.findItem(R.id.hide_boosts);
|
||||
if(relationship.following){
|
||||
hideBoosts.setTitle(fragment.getString(relationship.showingReblogs ? R.string.hide_boosts_from_user : R.string.show_boosts_from_user, account.getDisplayUsername()));
|
||||
hideBoosts.setTitle(fragment.getString(relationship.showingReblogs ? R.string.hide_boosts_from_user : R.string.show_boosts_from_user, account.getShortUsername()));
|
||||
hideBoosts.setIcon(relationship.showingReblogs ? R.drawable.ic_fluent_arrow_repeat_all_off_24_regular : R.drawable.ic_fluent_arrow_repeat_all_24_regular);
|
||||
UiUtils.insetPopupMenuIcon(fragment.getContext(), hideBoosts);
|
||||
hideBoosts.setVisible(true);
|
||||
}else{
|
||||
hideBoosts.setVisible(false);
|
||||
@@ -274,6 +285,8 @@ public class AccountViewHolder extends BindableViewHolder<AccountViewModel> impl
|
||||
UiUtils.confirmToggleMuteUser(fragment.getActivity(), accountID, account, relationship.muting, this::updateRelationship);
|
||||
}else if(id==R.id.block){
|
||||
UiUtils.confirmToggleBlockUser(fragment.getActivity(), accountID, account, relationship.blocking, this::updateRelationship);
|
||||
}else if(id==R.id.soft_block){
|
||||
UiUtils.confirmSoftBlockUser(fragment.getActivity(), accountID, account, this::updateRelationship);
|
||||
}else if(id==R.id.report){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
@@ -303,6 +316,12 @@ public class AccountViewHolder extends BindableViewHolder<AccountViewModel> impl
|
||||
})
|
||||
.wrapProgress(fragment.getActivity(), R.string.loading, false)
|
||||
.exec(accountID);
|
||||
}else if(id==R.id.manage_user_lists){
|
||||
final Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putString("profileAccount", account.id);
|
||||
args.putString("profileDisplayUsername", account.getDisplayUsername());
|
||||
Nav.go(fragment.getActivity(), ListsFragment.class, args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,10 +36,12 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
|
||||
LayoutParams lp=(LayoutParams) v.getLayoutParams();
|
||||
remainingWidth-=v.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
|
||||
}
|
||||
View first=getChildAt(0);
|
||||
if(first instanceof TextView){
|
||||
// guaranteeing at least 64dp of width for the display name
|
||||
((TextView) first).setMaxWidth(Math.max(remainingWidth, V.dp(64)));
|
||||
if(getChildAt(0) instanceof TextView first){
|
||||
// guaranteeing at least 64sp of width for the display name
|
||||
first.setMaxWidth(Math.max(remainingWidth, V.sp(64)));
|
||||
}
|
||||
if(getChildAt(1) instanceof TextView second){
|
||||
second.setMaxWidth(Math.max(remainingWidth, V.sp(120)));
|
||||
}
|
||||
}else{
|
||||
View first=getChildAt(0);
|
||||
|
||||
Reference in New Issue
Block a user