From 71c80dd381fd0eadfb7efa7e834e9795905184b8 Mon Sep 17 00:00:00 2001 From: sk Date: Tue, 27 Dec 2022 20:53:06 -0300 Subject: [PATCH] I want to fucking die --- .../fragments/NotificationsFragment.java | 21 +++- .../android/fragments/ProfileFragment.java | 12 +- .../displayitems/FooterStatusDisplayItem.java | 93 ++++++++++++-- .../displayitems/HeaderStatusDisplayItem.java | 10 +- .../android/ui/utils/UiUtils.java | 118 ++++++++++++------ .../ic_fluent_arrow_clockwise_24_regular.xml | 3 + .../ic_fluent_arrow_clockwise_28_regular.xml | 3 + .../ic_fluent_arrow_reply_28_regular.xml | 3 + .../ic_fluent_bookmark_28_regular.xml | 3 + .../drawable/ic_fluent_globe_24_regular.xml | 3 + ...c_fluent_mail_inbox_dismiss_28_regular.xml | 3 + .../drawable/ic_fluent_person_28_regular.xml | 3 + .../ic_fluent_person_delete_24_regular.xml | 3 + ...ic_fluent_person_prohibited_24_regular.xml | 3 + ...ic_fluent_person_prohibited_28_regular.xml | 3 + .../res/drawable/ic_fluent_pin_24_regular.xml | 3 + .../res/drawable/ic_fluent_pin_28_regular.xml | 3 + .../drawable/ic_fluent_pin_off_24_regular.xml | 3 + .../drawable/ic_fluent_pin_off_28_regular.xml | 3 + .../drawable/ic_fluent_shield_28_regular.xml | 3 + ...ic_fluent_shield_prohibited_24_regular.xml | 3 + .../ic_fluent_speaker_2_24_regular.xml | 3 + .../ic_fluent_speaker_2_28_regular.xml | 3 + .../ic_fluent_speaker_mute_24_regular.xml | 3 + .../ic_fluent_speaker_mute_28_regular.xml | 3 + .../drawable/ic_fluent_star_28_regular.xml | 3 + .../drawable/ic_fluent_warning_24_regular.xml | 3 + .../main/res/drawable/ic_follow_selector.xml | 8 ++ mastodon/src/main/res/menu/post.xml | 29 +++-- mastodon/src/main/res/menu/profile.xml | 16 +-- 30 files changed, 291 insertions(+), 82 deletions(-) create mode 100644 mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_arrow_reply_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_bookmark_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_globe_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_mail_inbox_dismiss_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_person_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_person_delete_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_person_prohibited_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_person_prohibited_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_pin_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_pin_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_pin_off_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_pin_off_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_shield_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_shield_prohibited_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_speaker_2_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_speaker_2_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_speaker_mute_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_speaker_mute_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_star_28_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_warning_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_follow_selector.xml diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java index 0bfc93cad..264a27622 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java @@ -74,15 +74,26 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ inflater.inflate(R.menu.notifications, menu); + menu.findItem(R.id.clear_notifications).setVisible(GlobalUserPreferences.enableDeleteNotifications); + UiUtils.enableOptionsMenuIcons(getActivity(), menu, R.id.follow_requests); } @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() != R.id.follow_requests) return false; - Bundle args=new Bundle(); - args.putString("account", accountID); - Nav.go(getActivity(), FollowRequestsListFragment.class, args); - return true; + if (item.getItemId() == R.id.follow_requests) { + Bundle args=new Bundle(); + args.putString("account", accountID); + Nav.go(getActivity(), FollowRequestsListFragment.class, args); + return true; + } else if (item.getItemId() == R.id.clear_notifications) { + UiUtils.confirmDeleteNotification(getActivity(), accountID, null, ()->{ + for (int i = 0; i < tabViews.length; i++) { + getFragmentForPage(i).reload(); + } + }); + return true; + } + return false; } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java index f585494cd..713140adb 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -553,16 +553,24 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList if(relationship==null && !isOwnProfile) return; inflater.inflate(isOwnProfile ? R.menu.profile_own : R.menu.profile, menu); + UiUtils.enableOptionsMenuIcons(getActivity(), menu, R.id.bookmarks, R.id.followed_hashtags); menu.findItem(R.id.share).setTitle(getString(R.string.share_user, account.getDisplayUsername())); if(isOwnProfile) return; - menu.findItem(R.id.mute).setTitle(getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername())); + MenuItem mute = menu.findItem(R.id.mute); + mute.setTitle(getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername())); + mute.setIcon(relationship.muting ? R.drawable.ic_fluent_speaker_2_24_regular : R.drawable.ic_fluent_speaker_mute_24_regular); + UiUtils.insetPopupMenuIcon(getContext(), mute); + menu.findItem(R.id.block).setTitle(getString(relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getDisplayUsername())); menu.findItem(R.id.report).setTitle(getString(R.string.report_user, account.getDisplayUsername())); MenuItem manageUserLists=menu.findItem(R.id.manage_user_lists); if(relationship.following) { - menu.findItem(R.id.hide_boosts).setTitle(getString(relationship.showingReblogs ? R.string.hide_boosts_from_user : R.string.show_boosts_from_user, account.getDisplayUsername())); + 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.getDisplayUsername())); + 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); manageUserLists.setTitle(getString(R.string.sk_lists_with_user, account.getDisplayUsername())); manageUserLists.setVisible(true); }else { diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java index da92f4499..f9ab6364e 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java @@ -60,7 +60,14 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ private static final Animation opacityOut, opacityIn; private View touchingView = null; - private final Runnable longClickRunnable = () -> { if (touchingView != null) touchingView.performLongClick(); }; + private boolean longClickPerformed = false; + private final Runnable longClickRunnable = () -> { + longClickPerformed = touchingView != null && touchingView.performLongClick(); + if (longClickPerformed && touchingView != null) { + touchingView.startAnimation(opacityIn); + touchingView.animate().scaleX(1).scaleY(1).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start(); + } + }; private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){ @Override @@ -72,12 +79,12 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ }; static { - opacityOut = new AlphaAnimation(1, 0.7f); - opacityOut.setDuration(200); + opacityOut = new AlphaAnimation(1, 0.55f); + opacityOut.setDuration(300); opacityOut.setInterpolator(CubicBezierInterpolator.DEFAULT); opacityOut.setFillAfter(true); - opacityIn = new AlphaAnimation(0.7f, 1); - opacityIn.setDuration(300); + opacityIn = new AlphaAnimation(0.55f, 1); + opacityIn.setDuration(500); opacityIn.setInterpolator(CubicBezierInterpolator.DEFAULT); } @@ -101,6 +108,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ View bookmark=findViewById(R.id.bookmark_btn); reply.setOnTouchListener(this::onButtonTouch); reply.setOnClickListener(this::onReplyClick); + reply.setOnLongClickListener(this::onReplyLongClick); reply.setAccessibilityDelegate(buttonAccessibilityDelegate); boost.setOnTouchListener(this::onButtonTouch); boost.setOnClickListener(this::onBoostClick); @@ -108,9 +116,11 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ boost.setAccessibilityDelegate(buttonAccessibilityDelegate); favorite.setOnTouchListener(this::onButtonTouch); favorite.setOnClickListener(this::onFavoriteClick); + favorite.setOnLongClickListener(this::onFavoriteLongClick); favorite.setAccessibilityDelegate(buttonAccessibilityDelegate); bookmark.setOnTouchListener(this::onButtonTouch); bookmark.setOnClickListener(this::onBookmarkClick); + bookmark.setOnLongClickListener(this::onBookmarkLongClick); bookmark.setAccessibilityDelegate(buttonAccessibilityDelegate); share.setOnTouchListener(this::onButtonTouch); share.setOnClickListener(this::onShareClick); @@ -144,15 +154,15 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ boolean disabled = !v.isEnabled() || (v instanceof FrameLayout parentFrame && parentFrame.getChildCount() > 0 && !parentFrame.getChildAt(0).isEnabled()); int action = event.getAction(); - long eventDuration = event.getEventTime() - event.getDownTime(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { touchingView = null; v.removeCallbacks(longClickRunnable); - v.animate().scaleX(1).scaleY(1).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start(); + if (!longClickPerformed) v.animate().scaleX(1).scaleY(1).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start(); if (disabled) return true; - if (action == MotionEvent.ACTION_UP && eventDuration <= ViewConfiguration.getLongPressTimeout()) v.performClick(); - else v.startAnimation(opacityIn); + if (action == MotionEvent.ACTION_UP && !longClickPerformed) v.performClick(); + else if (!longClickPerformed) v.startAnimation(opacityIn); } else if (action == MotionEvent.ACTION_DOWN) { + longClickPerformed = false; touchingView = v; // 20dp to center in middle of icon, because: (icon width = 24dp) / 2 + (paddingStart = 8dp) v.setPivotX(V.dp(20)); @@ -172,6 +182,20 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args); } + private boolean onReplyLongClick(View v) { + if (AccountSessionManager.getInstance().getLoggedInAccounts().size() < 2) return false; + UiUtils.pickAccount(v.getContext(), item.accountID, R.string.sk_reply_as, R.drawable.ic_fluent_arrow_reply_28_regular, session -> { + Bundle args=new Bundle(); + String accountID = session.getID(); + args.putString("account", accountID); + UiUtils.lookupStatus(v.getContext(), item.status, accountID, item.accountID, status -> { + args.putParcelable("replyTo", Parcels.wrap(status)); + Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args); + }); + }, null); + return true; + } + private void onBoostClick(View v){ boost.setSelected(!item.status.reblogged); AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setReblogged(item.status, !item.status.reblogged, null, r->boostConsumer(v, r)); @@ -198,6 +222,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ View separator = menu.findViewById(R.id.separator); TextView reblogHeader = menu.findViewById(R.id.reblog_header); TextView undoReblog = menu.findViewById(R.id.delete_reblog); + TextView reblogAs = menu.findViewById(R.id.reblog_as); TextView itemPublic = menu.findViewById(R.id.vis_public); TextView itemUnlisted = menu.findViewById(R.id.vis_unlisted); TextView itemFollowers = menu.findViewById(R.id.vis_followers); @@ -205,6 +230,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ undoReblog.setVisibility(item.status.reblogged ? View.VISIBLE : View.GONE); separator.setVisibility(item.status.reblogged ? View.GONE : View.VISIBLE); reblogHeader.setVisibility(item.status.reblogged ? View.GONE : View.VISIBLE); + reblogAs.setVisibility(AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1 ? View.VISIBLE : View.GONE); itemPublic.setVisibility(item.status.reblogged || item.status.visibility.isLessVisibleThan(StatusPrivacy.PUBLIC) ? View.GONE : View.VISIBLE); itemUnlisted.setVisibility(item.status.reblogged || item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) ? View.GONE : View.VISIBLE); @@ -215,10 +241,10 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ Drawable unlistedDrawable = ctx.getDrawable(R.drawable.ic_fluent_people_community_24_regular); Drawable followersDrawable = ctx.getDrawable(R.drawable.ic_fluent_people_checkmark_24_regular); - StatusPrivacy defaultVisibility = session.preferences.postingDefaultVisibility; + StatusPrivacy defaultVisibility = session.preferences != null ? session.preferences.postingDefaultVisibility : null; // e.g. post visibility is unlisted, but default is public // in this case, we want to display the check mark on the most visible visibility - if (item.status.visibility.isLessVisibleThan(defaultVisibility)) { + if (defaultVisibility != null && item.status.visibility.isLessVisibleThan(defaultVisibility)) { for (StatusPrivacy vis : StatusPrivacy.values()) { if (vis.equals(item.status.visibility)) { defaultVisibility = vis; @@ -234,6 +260,19 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ itemPublic.setOnClickListener(c->doReblog.accept(StatusPrivacy.PUBLIC)); itemUnlisted.setOnClickListener(c->doReblog.accept(StatusPrivacy.UNLISTED)); itemFollowers.setOnClickListener(c->doReblog.accept(StatusPrivacy.PRIVATE)); + reblogAs.setOnClickListener(c->{ + dialog.dismiss(); + UiUtils.pickInteractAs(v.getContext(), + item.accountID, item.status, + s -> s.reblogged, + (ic, status, consumer) -> ic.setReblogged(status, true, null, consumer), + R.string.sk_reblog_as, + R.string.sk_reblogged_as, + R.string.sk_already_reblogged, + // TODO: replace once available: https://raw.githubusercontent.com/microsoft/fluentui-system-icons/main/android/library/src/main/res/drawable/ic_fluent_arrow_repeat_all_28_regular.xml + R.drawable.ic_fluent_arrow_repeat_all_24_regular + ); + }); menu.findViewById(R.id.quote).setOnClickListener(c->{ dialog.dismiss(); @@ -257,13 +296,41 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ }); } + private boolean onFavoriteLongClick(View v) { + if (AccountSessionManager.getInstance().getLoggedInAccounts().size() < 2) return false; + UiUtils.pickInteractAs(v.getContext(), + item.accountID, item.status, + s -> s.favourited, + (ic, status, consumer) -> ic.setFavorited(status, true, consumer), + R.string.sk_favorite_as, + R.string.sk_favorited_as, + R.string.sk_already_favorited, + R.drawable.ic_fluent_star_28_regular + ); + return true; + } + private void onBookmarkClick(View v){ - bookmark.setSelected(item.status.bookmarked); + bookmark.setSelected(!item.status.bookmarked); AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setBookmarked(item.status, !item.status.bookmarked, r->{ v.startAnimation(opacityIn); }); } + private boolean onBookmarkLongClick(View v) { + if (AccountSessionManager.getInstance().getLoggedInAccounts().size() < 2) return false; + UiUtils.pickInteractAs(v.getContext(), + item.accountID, item.status, + s -> s.bookmarked, + (ic, status, consumer) -> ic.setBookmarked(status, true, consumer), + R.string.sk_bookmark_as, + R.string.sk_bookmarked_as, + R.string.sk_already_bookmarked, + R.drawable.ic_fluent_bookmark_28_regular + ); + return true; + } + private void onShareClick(View v){ v.startAnimation(opacityIn); Intent intent=new Intent(Intent.ACTION_SEND); @@ -273,7 +340,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ } private boolean onShareLongClick(View v){ - UiUtils.copyText(v.getContext(), item.status.url); + UiUtils.copyText(v, item.status.url); return true; } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java index 4a9645fd0..66c421a1f 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java @@ -222,6 +222,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ } return true; }); + UiUtils.enablePopupMenuIcons(activity, optionsMenu); } private void openWithAccount() { @@ -323,6 +324,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ menu.findItem(R.id.open_in_browser).setVisible(item.status!=null); MenuItem blockDomain=menu.findItem(R.id.block_domain); MenuItem mute=menu.findItem(R.id.mute); + MenuItem hideBoosts=menu.findItem(R.id.hide_boosts); MenuItem block=menu.findItem(R.id.block); MenuItem report=menu.findItem(R.id.report); MenuItem follow=menu.findItem(R.id.follow); @@ -338,6 +340,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ */ if(isOwnPost){ mute.setVisible(false); + hideBoosts.setVisible(false); block.setVisible(false); report.setVisible(false); follow.setVisible(false); @@ -348,6 +351,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ report.setVisible(true); follow.setVisible(relationship==null || relationship.following || (!relationship.blocking && !relationship.blockedBy && !relationship.domainBlocking && !relationship.muting)); mute.setTitle(item.parentFragment.getString(relationship!=null && relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername())); + mute.setIcon(relationship!=null && relationship.muting ? R.drawable.ic_fluent_speaker_2_24_regular : R.drawable.ic_fluent_speaker_mute_24_regular); + UiUtils.insetPopupMenuIcon(item.parentFragment.getContext(), mute); block.setTitle(item.parentFragment.getString(relationship!=null && relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getDisplayUsername())); report.setTitle(item.parentFragment.getString(R.string.report_user, account.getDisplayUsername())); // disabled in megalodon. domain blocks from a post clutters the context menu and looks out of place @@ -357,7 +362,10 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ // }else{ blockDomain.setVisible(false); // } - follow.setTitle(item.parentFragment.getString(relationship!=null && relationship.following ? R.string.unfollow_user : R.string.follow_user, account.getDisplayUsername())); + boolean following = relationship!=null && relationship.following; + follow.setTitle(item.parentFragment.getString(following ? R.string.unfollow_user : R.string.follow_user, account.getDisplayUsername())); + follow.setIcon(following ? R.drawable.ic_fluent_person_delete_24_regular : R.drawable.ic_fluent_person_add_24_regular); + UiUtils.insetPopupMenuIcon(item.parentFragment.getContext(), follow); } } } 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 907618da3..fe28da756 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 @@ -105,6 +105,7 @@ import java.util.stream.Collectors; import androidx.annotation.AttrRes; import androidx.annotation.DrawableRes; +import androidx.annotation.IdRes; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.browser.customtabs.CustomTabsIntent; @@ -348,22 +349,29 @@ public class UiUtils{ } public static void showConfirmationAlert(Context context, @StringRes int title, @StringRes int message, @StringRes int confirmButton, Runnable onConfirmed){ - showConfirmationAlert(context, context.getString(title), context.getString(message), context.getString(confirmButton), onConfirmed); + showConfirmationAlert(context, title, message, confirmButton, 0, onConfirmed); } - public static void showConfirmationAlert(Context context, CharSequence title, CharSequence message, CharSequence confirmButton, Runnable onConfirmed){ + public static void showConfirmationAlert(Context context, @StringRes int title, @StringRes int message, @StringRes int confirmButton, @DrawableRes int icon, Runnable onConfirmed){ + showConfirmationAlert(context, context.getString(title), context.getString(message), context.getString(confirmButton), icon, onConfirmed); + } + + public static void showConfirmationAlert(Context context, CharSequence title, CharSequence message, CharSequence confirmButton, int icon, Runnable onConfirmed){ new M3AlertDialogBuilder(context) .setTitle(title) .setMessage(message) .setPositiveButton(confirmButton, (dlg, i)->onConfirmed.run()) .setNegativeButton(R.string.cancel, null) + .setIcon(icon) .show(); } public static void confirmToggleBlockUser(Activity activity, String accountID, Account account, boolean currentlyBlocked, Consumer resultCallback){ showConfirmationAlert(activity, activity.getString(currentlyBlocked ? R.string.confirm_unblock_title : R.string.confirm_block_title), activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.displayName), - activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block), ()->{ + activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block), + currentlyBlocked ? R.drawable.ic_fluent_person_28_regular : R.drawable.ic_fluent_person_prohibited_28_regular, + ()->{ new SetAccountBlocked(account.id, !currentlyBlocked) .setCallback(new Callback<>(){ @Override @@ -387,7 +395,9 @@ public class UiUtils{ public static void confirmToggleBlockDomain(Activity activity, String accountID, String domain, boolean currentlyBlocked, Runnable resultCallback){ showConfirmationAlert(activity, activity.getString(currentlyBlocked ? R.string.confirm_unblock_domain_title : R.string.confirm_block_domain_title), activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, domain), - activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block), ()->{ + activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block), + R.drawable.ic_fluent_shield_28_regular, + ()->{ new SetDomainBlocked(domain, !currentlyBlocked) .setCallback(new Callback<>(){ @Override @@ -408,7 +418,9 @@ public class UiUtils{ public static void confirmToggleMuteUser(Activity activity, String accountID, Account account, boolean currentlyMuted, Consumer resultCallback){ showConfirmationAlert(activity, activity.getString(currentlyMuted ? R.string.confirm_unmute_title : R.string.confirm_mute_title), activity.getString(currentlyMuted ? R.string.confirm_unmute : R.string.confirm_mute, account.displayName), - activity.getString(currentlyMuted ? R.string.do_unmute : R.string.do_mute), ()->{ + activity.getString(currentlyMuted ? R.string.do_unmute : R.string.do_mute), + currentlyMuted ? R.drawable.ic_fluent_speaker_2_28_regular : R.drawable.ic_fluent_speaker_mute_28_regular, + ()->{ new SetAccountMuted(account.id, !currentlyMuted) .setCallback(new Callback<>(){ @Override @@ -433,24 +445,28 @@ public class UiUtils{ } public static void confirmDeletePost(Activity activity, String accountID, Status status, Consumer resultCallback, boolean forRedraft){ - 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, ()->{ - new DeleteStatus(status.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)); - } + 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) + .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)); + } - @Override - public void onError(ErrorResponse error){ - error.showToast(activity); - } - }) - .wrapProgress(activity, R.string.deleting, false) - .exec(accountID); - }); + @Override + public void onError(ErrorResponse error){ + error.showToast(activity); + } + }) + .wrapProgress(activity, R.string.deleting, false) + .exec(accountID) + ); } public static void confirmPinPost(Activity activity, String accountID, Status status, boolean pinned, Consumer resultCallback){ @@ -458,6 +474,7 @@ public class UiUtils{ pinned ? R.string.sk_confirm_pin_post_title : R.string.sk_confirm_unpin_post_title, pinned ? R.string.sk_confirm_pin_post : R.string.sk_confirm_unpin_post, pinned ? R.string.sk_pin_post : R.string.sk_unpin_post, + pinned ? R.drawable.ic_fluent_pin_off_28_regular : R.drawable.ic_fluent_pin_28_regular, ()->{ new SetStatusPinned(status.id, pinned) .setCallback(new Callback<>() { @@ -485,7 +502,8 @@ public class UiUtils{ notification == null ? R.string.sk_clear_all_notifications : R.string.sk_delete_notification, notification == null ? R.string.sk_clear_all_notifications_confirm : R.string.sk_delete_notification_confirm, notification == null ? R.string.sk_clear_all_notifications_confirm_action : R.string.sk_delete_notification_confirm_action, - ()-> new DismissNotification(notification != null ? notification.id : null).setCallback(new Callback<>() { + notification == null ? R.drawable.ic_fluent_mail_inbox_dismiss_28_regular : R.drawable.ic_fluent_delete_28_regular, + () -> new DismissNotification(notification != null ? notification.id : null).setCallback(new Callback<>() { @Override public void onSuccess(Object o) { callback.run(); @@ -666,6 +684,42 @@ public class UiUtils{ return bitmap; } + public static void insetPopupMenuIcon(Context context, MenuItem item) { + ColorStateList iconTint=ColorStateList.valueOf(UiUtils.getThemeColor(context, android.R.attr.textColorSecondary)); + insetPopupMenuIcon(item, iconTint); + } + public static void insetPopupMenuIcon(MenuItem item, ColorStateList iconTint) { + Drawable icon=item.getIcon().mutate(); + if(Build.VERSION.SDK_INT>=26) item.setIconTintList(iconTint); + else icon.setTintList(iconTint); + icon=new InsetDrawable(icon, V.dp(8), 0, V.dp(8), 0); + item.setIcon(icon); + SpannableStringBuilder ssb=new SpannableStringBuilder(item.getTitle()); + item.setTitle(ssb); + } + + public static void enableOptionsMenuIcons(Context context, Menu menu, @IdRes int... asAction) { + if(menu.getClass().getSimpleName().equals("MenuBuilder")){ + try { + Method m = menu.getClass().getDeclaredMethod( + "setOptionalIconsVisible", Boolean.TYPE); + m.setAccessible(true); + m.invoke(menu, true); + enableMenuIcons(context, menu, asAction); + } + catch(Exception ignored){} + } + } + + public static void enableMenuIcons(Context context, Menu m, @IdRes int... exclude) { + ColorStateList iconTint=ColorStateList.valueOf(UiUtils.getThemeColor(context, android.R.attr.textColorSecondary)); + for(int i=0;i id == item.getItemId())) continue; + insetPopupMenuIcon(item, iconTint); + } + } + public static void enablePopupMenuIcons(Context context, PopupMenu menu){ Menu m=menu.getMenu(); if(Build.VERSION.SDK_INT>=29){ @@ -677,23 +731,7 @@ public class UiUtils{ setOptionalIconsVisible.invoke(m, true); }catch(Exception ignore){} } - ColorStateList iconTint=ColorStateList.valueOf(UiUtils.getThemeColor(context, android.R.attr.textColorSecondary)); - for(int i=0;i=26){ - item.setIconTintList(iconTint); - }else{ - icon.setTintList(iconTint); - } - icon=new InsetDrawable(icon, V.dp(8), 0, 0, 0); - item.setIcon(icon); - SpannableStringBuilder ssb=new SpannableStringBuilder(item.getTitle()); - ssb.insert(0, " "); - ssb.setSpan(new SpacerSpan(V.dp(24), 1), 0, 1, 0); - ssb.append(" ", new SpacerSpan(V.dp(8), 1), 0); - item.setTitle(ssb); - } + enableMenuIcons(context, m); } public static void setUserPreferredTheme(Context context){ diff --git a/mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_24_regular.xml new file mode 100644 index 000000000..d130d2b90 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_28_regular.xml new file mode 100644 index 000000000..c693e299d --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_arrow_clockwise_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_arrow_reply_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_arrow_reply_28_regular.xml new file mode 100644 index 000000000..7e17362da --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_arrow_reply_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_bookmark_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_bookmark_28_regular.xml new file mode 100644 index 000000000..964afe7b1 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_bookmark_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_globe_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_globe_24_regular.xml new file mode 100644 index 000000000..580825c79 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_globe_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_mail_inbox_dismiss_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_mail_inbox_dismiss_28_regular.xml new file mode 100644 index 000000000..2ea945f3d --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_mail_inbox_dismiss_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_person_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_person_28_regular.xml new file mode 100644 index 000000000..ab35ad3fd --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_person_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_person_delete_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_person_delete_24_regular.xml new file mode 100644 index 000000000..106276c58 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_person_delete_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_person_prohibited_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_person_prohibited_24_regular.xml new file mode 100644 index 000000000..dece645aa --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_person_prohibited_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_person_prohibited_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_person_prohibited_28_regular.xml new file mode 100644 index 000000000..7de6abefc --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_person_prohibited_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_pin_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_pin_24_regular.xml new file mode 100644 index 000000000..0dff766bc --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_pin_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_pin_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_pin_28_regular.xml new file mode 100644 index 000000000..cc5a4f204 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_pin_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_pin_off_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_pin_off_24_regular.xml new file mode 100644 index 000000000..cb69ef23b --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_pin_off_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_pin_off_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_pin_off_28_regular.xml new file mode 100644 index 000000000..523fa6031 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_pin_off_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_shield_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_shield_28_regular.xml new file mode 100644 index 000000000..30bf53796 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_shield_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_shield_prohibited_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_shield_prohibited_24_regular.xml new file mode 100644 index 000000000..a6d013610 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_shield_prohibited_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_speaker_2_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_speaker_2_24_regular.xml new file mode 100644 index 000000000..8ba6f262d --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_speaker_2_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_speaker_2_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_speaker_2_28_regular.xml new file mode 100644 index 000000000..486228e0e --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_speaker_2_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_speaker_mute_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_speaker_mute_24_regular.xml new file mode 100644 index 000000000..8cd5f52dc --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_speaker_mute_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_speaker_mute_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_speaker_mute_28_regular.xml new file mode 100644 index 000000000..b45d213d3 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_speaker_mute_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_star_28_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_star_28_regular.xml new file mode 100644 index 000000000..27e31d2bf --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_star_28_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_warning_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_warning_24_regular.xml new file mode 100644 index 000000000..fbb3813ca --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_warning_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_follow_selector.xml b/mastodon/src/main/res/drawable/ic_follow_selector.xml new file mode 100644 index 000000000..8cd4d4e92 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_follow_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/mastodon/src/main/res/menu/post.xml b/mastodon/src/main/res/menu/post.xml index 9b876f64c..b0de637d0 100644 --- a/mastodon/src/main/res/menu/post.xml +++ b/mastodon/src/main/res/menu/post.xml @@ -1,16 +1,19 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mastodon/src/main/res/menu/profile.xml b/mastodon/src/main/res/menu/profile.xml index 097d1b40a..1f2a99a2d 100644 --- a/mastodon/src/main/res/menu/profile.xml +++ b/mastodon/src/main/res/menu/profile.xml @@ -1,11 +1,11 @@ - - - - - - - - + + + + + + + + \ No newline at end of file