From 3cdcffe03d97ee33c1a23e03dda3bd3003e0b122 Mon Sep 17 00:00:00 2001 From: sk Date: Mon, 9 Jan 2023 13:16:03 -0300 Subject: [PATCH] implement announcements closes #127 --- .../announcements/DismissAnnouncement.java | 10 ++ .../announcements/GetAnnouncements.java | 15 +++ .../fragments/AnnouncementsFragment.java | 107 ++++++++++++++++++ .../fragments/HomeTimelineFragment.java | 31 ++++- .../onboarding/CustomLoginFragment.java | 21 ++-- .../android/model/Announcement.java | 63 +++++++++++ .../displayitems/HeaderStatusDisplayItem.java | 69 ++++++++++- .../drawable/ic_announcements_24_badged.xml | 10 ++ .../ic_fluent_checkmark_20_filled.xml | 3 + .../ic_fluent_circle_small_20_filled.xml | 3 + .../ic_fluent_megaphone_24_regular.xml | 3 + .../ic_fluent_more_vertical_20_filled.xml | 3 + .../main/res/layout/display_item_header.xml | 17 ++- .../main/res/layout/header_welcome_custom.xml | 3 +- mastodon/src/main/res/menu/home.xml | 5 + mastodon/src/main/res/values/strings_sk.xml | 3 + 16 files changed, 344 insertions(+), 22 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/DismissAnnouncement.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/GetAnnouncements.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/fragments/AnnouncementsFragment.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/model/Announcement.java create mode 100644 mastodon/src/main/res/drawable/ic_announcements_24_badged.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_checkmark_20_filled.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_circle_small_20_filled.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_megaphone_24_regular.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_more_vertical_20_filled.xml diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/DismissAnnouncement.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/DismissAnnouncement.java new file mode 100644 index 000000000..3227a2cd5 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/DismissAnnouncement.java @@ -0,0 +1,10 @@ +package org.joinmastodon.android.api.requests.announcements; + +import org.joinmastodon.android.api.MastodonAPIRequest; + +public class DismissAnnouncement extends MastodonAPIRequest{ + public DismissAnnouncement(String id){ + super(HttpMethod.POST, "/announcements/" + id + "/dismiss", Object.class); + setRequestBody(new Object()); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/GetAnnouncements.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/GetAnnouncements.java new file mode 100644 index 000000000..4bedba6d6 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/announcements/GetAnnouncements.java @@ -0,0 +1,15 @@ +package org.joinmastodon.android.api.requests.announcements; + +import com.google.gson.reflect.TypeToken; + +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.Announcement; + +import java.util.List; + +public class GetAnnouncements extends MastodonAPIRequest> { + public GetAnnouncements(boolean withDismissed) { + super(MastodonAPIRequest.HttpMethod.GET, "/announcements", new TypeToken<>(){}); + addQueryParameter("with_dismissed", withDismissed ? "true" : "false"); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AnnouncementsFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AnnouncementsFragment.java new file mode 100644 index 000000000..eb03ddd78 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AnnouncementsFragment.java @@ -0,0 +1,107 @@ +package org.joinmastodon.android.fragments; + +import android.app.Activity; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageButton; + +import com.squareup.otto.Subscribe; + +import org.joinmastodon.android.E; +import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.announcements.GetAnnouncements; +import org.joinmastodon.android.api.requests.statuses.CreateStatus; +import org.joinmastodon.android.api.requests.statuses.GetScheduledStatuses; +import org.joinmastodon.android.api.session.AccountSession; +import org.joinmastodon.android.api.session.AccountSessionManager; +import org.joinmastodon.android.events.ScheduledStatusCreatedEvent; +import org.joinmastodon.android.events.ScheduledStatusDeletedEvent; +import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.Announcement; +import org.joinmastodon.android.model.HeaderPaginationList; +import org.joinmastodon.android.model.Instance; +import org.joinmastodon.android.model.ScheduledStatus; +import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem; +import org.joinmastodon.android.ui.displayitems.StatusDisplayItem; +import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem; +import org.joinmastodon.android.ui.text.HtmlParser; +import org.joinmastodon.android.ui.utils.UiUtils; +import org.parceler.Parcels; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import me.grishka.appkit.Nav; +import me.grishka.appkit.api.PaginatedList; +import me.grishka.appkit.api.SimpleCallback; + +public class AnnouncementsFragment extends BaseStatusListFragment { + private Instance instance; + private AccountSession session; + private List unreadIDs = null; + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + setTitle(R.string.sk_announcements); + session = AccountSessionManager.getInstance().getAccount(accountID); + instance = AccountSessionManager.getInstance().getInstanceInfo(session.domain); + loadData(); + } + + @Override + protected List buildDisplayItems(Announcement a) { + if(TextUtils.isEmpty(a.content)) return List.of(); + Account instanceUser = new Account(); + instanceUser.id = instanceUser.acct = instanceUser.username = session.domain; + instanceUser.displayName = instance.title; + instanceUser.url = "https://"+session.domain+"/about"; + instanceUser.avatar = instanceUser.avatarStatic = instance.thumbnail; + instanceUser.emojis = List.of(); + Status fakeStatus = a.toStatus(); + return List.of( + HeaderStatusDisplayItem.fromAnnouncement(a, fakeStatus, instanceUser, this, accountID, this::onMarkAsRead), + new TextStatusDisplayItem(a.id, HtmlParser.parse(a.content, a.emojis, a.mentions, a.tags, accountID), this, fakeStatus) + ); + } + + public void onMarkAsRead(String id) { + if (unreadIDs == null) return; + unreadIDs.remove(id); + if (unreadIDs.size() == 0) setResult(true, null); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + protected void addAccountToKnown(Announcement s) {} + + @Override + public void onItemClick(String id) { + } + + @Override + protected void onDataLoaded(List d, boolean more) { + unreadIDs = d.stream().filter(a -> !a.read).map(a -> a.id).collect(Collectors.toList()); + super.onDataLoaded(d, more); + } + + @Override + protected void doLoadData(int offset, int count){ + currentRequest=new GetAnnouncements(true) + .setCallback(new SimpleCallback<>(this){ + @Override + public void onSuccess(List result){ + onDataLoaded(result, false); + } + }) + .exec(accountID); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java index 69993d5eb..0d18115ed 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java @@ -29,10 +29,12 @@ import com.squareup.otto.Subscribe; import org.joinmastodon.android.E; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.announcements.GetAnnouncements; import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.events.SelfUpdateStateChangedEvent; import org.joinmastodon.android.events.StatusCreatedEvent; +import org.joinmastodon.android.model.Announcement; import org.joinmastodon.android.model.CacheablePaginatedResponse; import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Status; @@ -56,11 +58,14 @@ import me.grishka.appkit.utils.CubicBezierInterpolator; import me.grishka.appkit.utils.V; public class HomeTimelineFragment extends StatusListFragment{ + private static final int ANNOUNCEMENTS_RESULT = 654; + private ImageButton fab; private ImageView toolbarLogo; private Button toolbarShowNewPostsBtn; private boolean newPostsBtnShown; private AnimatorSet currentNewPostsAnim; + private MenuItem announcements; private String maxID; @@ -126,16 +131,40 @@ public class HomeTimelineFragment extends StatusListFragment{ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ inflater.inflate(R.menu.home, menu); + announcements = menu.findItem(R.id.announcements); + + new GetAnnouncements(false).setCallback(new Callback<>() { + @Override + public void onSuccess(List result) { + boolean hasUnread = result.stream().anyMatch(a -> !a.read); + announcements.setIcon(hasUnread ? R.drawable.ic_announcements_24_badged : R.drawable.ic_fluent_megaphone_24_regular); + } + + @Override + public void onError(ErrorResponse error) { + error.showToast(getActivity()); + } + }).exec(accountID); } @Override public boolean onOptionsItemSelected(MenuItem item){ Bundle args=new Bundle(); args.putString("account", accountID); - Nav.go(getActivity(), SettingsFragment.class, args); + if (item.getItemId() == R.id.settings) Nav.go(getActivity(), SettingsFragment.class, args); + if (item.getItemId() == R.id.announcements) { + Nav.goForResult(getActivity(), AnnouncementsFragment.class, args, ANNOUNCEMENTS_RESULT, this); + } return true; } + @Override + public void onFragmentResult(int reqCode, boolean noMoreUnread, Bundle result){ + if (reqCode == ANNOUNCEMENTS_RESULT && noMoreUnread) { + announcements.setIcon(R.drawable.ic_fluent_megaphone_24_regular); + } + } + @Override public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/CustomLoginFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/CustomLoginFragment.java index 1b249f0ef..32f721c3a 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/CustomLoginFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/CustomLoginFragment.java @@ -36,10 +36,10 @@ import me.grishka.appkit.utils.SingleViewRecyclerAdapter; import me.grishka.appkit.utils.V; import me.grishka.appkit.views.UsableRecyclerView; -public class CustomLoginFragment extends InstanceCatalogFragment { +public class CustomWelcomeFragment extends InstanceCatalogFragment { private View headerView; - public CustomLoginFragment() { + public CustomWelcomeFragment() { super(R.layout.fragment_welcome_custom, 1); } @@ -55,9 +55,9 @@ public class CustomLoginFragment extends InstanceCatalogFragment { dataLoaded(); } -// @Override + @Override protected void onUpdateToolbar(){ -// super.onUpdateToolbar(); + super.onUpdateToolbar(); if (!canGoBack()) { ImageView toolbarLogo=new ImageView(getActivity()); @@ -137,9 +137,11 @@ public class CustomLoginFragment extends InstanceCatalogFragment { headerView.findViewById(R.id.more).setVisibility(View.GONE); headerView.findViewById(R.id.visibility).setVisibility(View.GONE); - ((TextView) headerView.findViewById(R.id.username)).setText("@moshidon"); + headerView.findViewById(R.id.separator).setVisibility(View.GONE); + headerView.findViewById(R.id.timestamp).setVisibility(View.GONE); + headerView.findViewById(R.id.unread_indicator).setVisibility(View.GONE); + ((TextView) headerView.findViewById(R.id.username)).setText(R.string.sk_app_username); ((TextView) headerView.findViewById(R.id.name)).setText(R.string.sk_app_name); - ((TextView) headerView.findViewById(R.id.timestamp)).setText(R.string.time_now); ((ImageView) headerView.findViewById(R.id.avatar)).setImageDrawable(getActivity().getDrawable(R.mipmap.ic_launcher)); ((FragmentStackActivity) getActivity()).invalidateSystemBarColors(this); @@ -168,7 +170,7 @@ public class CustomLoginFragment extends InstanceCatalogFragment { return mergeAdapter; } - private class InstancesAdapter extends UsableRecyclerView.Adapter{ + private class InstancesAdapter extends UsableRecyclerView.Adapter { public InstancesAdapter(){ super(imgLoader); } @@ -204,11 +206,6 @@ public class CustomLoginFragment extends InstanceCatalogFragment { public InstanceViewHolder(){ super(getActivity(), R.layout.item_instance_custom, list); - -// itemView.setPadding(V.dp(16), V.dp(16), V.dp(16), V.dp(16)); -// TypedValue value = new TypedValue(); -// getActivity().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true); -// itemView.setBackground(getActivity().getTheme().getDrawable(R.drawable.bg_search_field)); title=findViewById(R.id.title); description=findViewById(R.id.description); userCount=findViewById(R.id.user_count); diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Announcement.java b/mastodon/src/main/java/org/joinmastodon/android/model/Announcement.java new file mode 100644 index 000000000..4282da920 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Announcement.java @@ -0,0 +1,63 @@ +package org.joinmastodon.android.model; + +import org.joinmastodon.android.api.RequiredField; +import org.parceler.Parcel; + +import java.time.Instant; +import java.util.List; + +@Parcel +public class Announcement extends BaseModel implements DisplayItemsParent { + @RequiredField + public String id; + @RequiredField + public String content; + public Instant startsAt; + public Instant endsAt; + public boolean published; + public boolean allDay; + public Instant publishedAt; + public Instant updatedAt; + public boolean read; + public List emojis; + public List mentions; + public List tags; + + @Override + public String toString() { + return "Announcement{" + + "id='" + id + '\'' + + ", content='" + content + '\'' + + ", startsAt=" + startsAt + + ", endsAt=" + endsAt + + ", published=" + published + + ", allDay=" + allDay + + ", publishedAt=" + publishedAt + + ", updatedAt=" + updatedAt + + ", read=" + read + + ", emojis=" + emojis + + ", mentions=" + mentions + + ", tags=" + tags + + '}'; + } + + public Status toStatus() { + Status s = new Status(); + s.id = id; + s.mediaAttachments = List.of(); + s.createdAt = startsAt != null ? startsAt : publishedAt; + if (updatedAt != null) s.editedAt = updatedAt; + s.content = s.text = content; + s.spoilerText = ""; + s.visibility = StatusPrivacy.PUBLIC; + s.mentions = List.of(); + s.tags = List.of(); + s.emojis = List.of(); + return s; + } + + @Override + public String getID() { + return id; + } +} 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 a0b080d97..ecf7af152 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 @@ -24,6 +24,7 @@ import android.widget.Toast; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; +import org.joinmastodon.android.api.requests.announcements.DismissAnnouncement; import org.joinmastodon.android.api.requests.statuses.CreateStatus; import org.joinmastodon.android.api.requests.statuses.GetStatusSourceText; import org.joinmastodon.android.api.session.AccountSession; @@ -35,6 +36,7 @@ import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ThreadFragment; import org.joinmastodon.android.fragments.report.ReportReasonChoiceFragment; import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.Announcement; import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Relationship; @@ -52,6 +54,7 @@ import java.time.format.FormatStyle; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.function.Consumer; import me.grishka.appkit.Nav; import me.grishka.appkit.api.APIRequest; @@ -75,6 +78,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ private String extraText; private Notification notification; private ScheduledStatus scheduledStatus; + private Announcement announcement; + private Consumer consumeReadAnnouncement; public HeaderStatusDisplayItem(String parentID, Account user, Instant createdAt, BaseStatusListFragment parentFragment, String accountID, Status status, String extraText, Notification notification, ScheduledStatus scheduledStatus){ super(parentID, parentFragment); @@ -103,6 +108,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ this.extraText=extraText; } + public static HeaderStatusDisplayItem fromAnnouncement(Announcement a, Status fakeStatus, Account instanceUser, BaseStatusListFragment parentFragment, String accountID, Consumer consumeReadID) { + HeaderStatusDisplayItem item = new HeaderStatusDisplayItem(a.id, instanceUser, a.startsAt, parentFragment, accountID, fakeStatus, null, null, null); + item.announcement = a; + item.consumeReadAnnouncement = consumeReadID; + return item; + } + @Override public Type getType(){ return Type.HEADER; @@ -122,8 +134,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ } public static class Holder extends StatusDisplayItem.Holder implements ImageLoaderViewHolder{ - private final TextView name, username, timestamp, extraText; - private final ImageView avatar, more, visibility, deleteNotification; + private final TextView name, username, timestamp, extraText, separator; + private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator; private final PopupMenu optionsMenu; private Relationship relationship; private APIRequest currentRelationshipRequest; @@ -139,11 +151,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ super(activity, R.layout.display_item_header, parent); name=findViewById(R.id.name); username=findViewById(R.id.username); + separator=findViewById(R.id.separator); timestamp=findViewById(R.id.timestamp); avatar=findViewById(R.id.avatar); more=findViewById(R.id.more); visibility=findViewById(R.id.visibility); deleteNotification=findViewById(R.id.delete_notification); + unreadIndicator=findViewById(R.id.unread_indicator); extraText=findViewById(R.id.extra_text); avatar.setOnClickListener(this::onAvaClick); avatar.setOutlineProvider(roundCornersOutline); @@ -268,6 +282,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ public void onBind(HeaderStatusDisplayItem item){ name.setText(item.parsedName); username.setText('@'+item.user.acct); + separator.setVisibility(View.VISIBLE); + username.setCompoundDrawablesWithIntrinsicBounds(item.user.bot ? R.drawable.ic_fluent_bot_24_filled : 0, 0, 0, 0); @@ -278,10 +294,14 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault()); timestamp.setText(item.scheduledStatus.scheduledAt.atZone(ZoneId.systemDefault()).format(formatter)); } - else if(item.status==null || item.status.editedAt==null) + else if ((item.status==null || item.status.editedAt==null) && item.createdAt != null) timestamp.setText(UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt)); - else + else if (item.status != null && item.status.editedAt != null) timestamp.setText(item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt))); + else { + separator.setVisibility(View.GONE); + timestamp.setText(""); + } visibility.setVisibility(item.hasVisibilityToggle && !item.inset ? View.VISIBLE : View.GONE); deleteNotification.setVisibility(GlobalUserPreferences.enableDeleteNotifications && item.notification!=null && !item.inset ? View.VISIBLE : View.GONE); if(item.hasVisibilityToggle){ @@ -305,6 +325,42 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ currentRelationshipRequest.cancel(); } relationship=null; + + String desc; + if (item.announcement != null) { + if (unreadIndicator.getVisibility() == View.GONE) { + more.setAlpha(0f); + unreadIndicator.setAlpha(0f); + unreadIndicator.setVisibility(View.VISIBLE); + } + float alpha = item.announcement.read ? 0 : 1; + more.setImageResource(R.drawable.ic_fluent_checkmark_20_filled); + desc = item.parentFragment.getString(R.string.sk_mark_as_read); + more.animate().alpha(alpha); + unreadIndicator.animate().alpha(alpha); + more.setOnClickListener(v -> { + new DismissAnnouncement(item.announcement.id).setCallback(new Callback<>() { + @Override + public void onSuccess(Object o) { + item.consumeReadAnnouncement.accept(item.announcement.id); + item.announcement.read = true; + rebind(); + } + + @Override + public void onError(ErrorResponse error) { + error.showToast(item.parentFragment.getActivity()); + } + }).exec(item.accountID); + }); + } else { + more.setImageResource(R.drawable.ic_fluent_more_vertical_20_filled); + desc = item.parentFragment.getString(R.string.more_options); + more.setOnClickListener(this::onMoreClick); + } + + more.setContentDescription(desc); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) more.setTooltipText(desc); } @Override @@ -325,6 +381,10 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ } private void onAvaClick(View v){ + if (item.announcement != null) { + UiUtils.openURL(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.user.url); + return; + } Bundle args=new Bundle(); args.putString("account", item.accountID); args.putParcelable("profileAccount", Parcels.wrap(item.user)); @@ -356,6 +416,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ } private void updateOptionsMenu(){ + if (item.announcement != null) return; boolean hasMultipleAccounts = AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1; Menu menu=optionsMenu.getMenu(); diff --git a/mastodon/src/main/res/drawable/ic_announcements_24_badged.xml b/mastodon/src/main/res/drawable/ic_announcements_24_badged.xml new file mode 100644 index 000000000..e5b51e160 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_announcements_24_badged.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/mastodon/src/main/res/drawable/ic_fluent_checkmark_20_filled.xml b/mastodon/src/main/res/drawable/ic_fluent_checkmark_20_filled.xml new file mode 100644 index 000000000..101bc9a61 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_checkmark_20_filled.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_circle_small_20_filled.xml b/mastodon/src/main/res/drawable/ic_fluent_circle_small_20_filled.xml new file mode 100644 index 000000000..19ceb0169 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_circle_small_20_filled.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_megaphone_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_megaphone_24_regular.xml new file mode 100644 index 000000000..e6e4f6664 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_megaphone_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_more_vertical_20_filled.xml b/mastodon/src/main/res/drawable/ic_fluent_more_vertical_20_filled.xml new file mode 100644 index 000000000..8f7f1d2c1 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_more_vertical_20_filled.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/layout/display_item_header.xml b/mastodon/src/main/res/layout/display_item_header.xml index f7cf78c45..5c307d82e 100644 --- a/mastodon/src/main/res/layout/display_item_header.xml +++ b/mastodon/src/main/res/layout/display_item_header.xml @@ -18,7 +18,7 @@ android:background="?android:selectableItemBackgroundBorderless" android:contentDescription="@string/more_options" android:scaleType="center" - android:src="@drawable/ic_post_more" + android:src="@drawable/ic_fluent_more_vertical_20_filled" android:tint="?android:textColorSecondary" /> + + @@ -94,7 +105,7 @@ android:layout_height="wrap_content" android:layout_below="@id/name_wrap" android:layout_marginEnd="8dp" - android:layout_toStartOf="@id/visibility" + android:layout_toStartOf="@id/unread_indicator" android:layout_toEndOf="@id/avatar" android:layoutDirection="locale" android:minHeight="20sp" diff --git a/mastodon/src/main/res/layout/header_welcome_custom.xml b/mastodon/src/main/res/layout/header_welcome_custom.xml index a1ae29f82..ed6bda666 100644 --- a/mastodon/src/main/res/layout/header_welcome_custom.xml +++ b/mastodon/src/main/res/layout/header_welcome_custom.xml @@ -14,8 +14,7 @@ android:layout_height="wrap_content" android:layout_marginHorizontal="16dp" android:layout_marginVertical="12dp" - android:text="@string/sk_welcome_title" - /> + android:text="@string/sk_welcome_title" /> + Clear recently used emoji Disable "Relocate publish button" to allow customization Keep only latest notification + Announcements + Mark as read Add new poll option Compose Error publishing + \ No newline at end of file