countUsername = new HashMap<>();
+ for (Mention mention : announcement.mentions) {
+ Integer count = countUsername.get(mention.username);
+ if (count == null) {
+ count = 0;
+ }
+ if (countUsername.containsKey(mention.username)) {
+ countUsername.put(mention.username, count + 1);
+ } else {
+ countUsername.put(mention.username, 1);
+ }
+ }
+ for (Mention mention : announcement.mentions) {
+ Integer count = countUsername.get(mention.username);
+ if (count == null) {
+ count = 0;
+ }
+ if (word.trim().compareToIgnoreCase("@" + mention.username) == 0 && count == 1) {
+ targetedMention = mention;
+ break;
+ }
+ }
+ if (targetedMention != null) {
+ b.putString(Helper.ARG_USER_ID, targetedMention.id);
+ } else {
+ b.putString(Helper.ARG_MENTION, word.trim());
+ }
+ intent.putExtras(b);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ break;
+ case MENTION_LONG:
+ intent = new Intent(context, ProfileActivity.class);
+ b = new Bundle();
+ targetedMention = null;
+ for (Mention mention : announcement.mentions) {
+ if (word.trim().substring(1).compareToIgnoreCase("@" + mention.acct) == 0) {
+ targetedMention = mention;
+ break;
+ }
+ }
+ if (targetedMention != null) {
+ b.putString(Helper.ARG_USER_ID, targetedMention.id);
+ } else {
+ b.putString(Helper.ARG_MENTION, word.trim());
+ }
+ intent.putExtras(b);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ break;
+ }
+ }
+
+ @Override
+ public void updateDrawState(@NonNull TextPaint ds) {
+ super.updateDrawState(ds);
+ ds.setUnderlineText(false);
+ ds.setColor(linkColor);
+ }
+ }, matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+ }
+ }
+ return trimSpannable(new SpannableStringBuilder(content));
+ }
+
/**
* Remove extra carriage returns at the bottom due to tags in toots
*
@@ -586,6 +1007,24 @@ public class SpannableHelper {
return statuses;
}
+
+ public static List convertAnnouncement(Context context, List announcements) {
+ if (announcements != null) {
+ for (Announcement announcement : announcements) {
+ convertAnnouncement(context, announcement);
+ }
+ }
+ return announcements;
+ }
+
+
+ public static Announcement convertAnnouncement(Context context, Announcement announcement) {
+ if (announcement != null) {
+ announcement.span_content = SpannableHelper.convert(context, announcement, announcement.content);
+ }
+ return announcement;
+ }
+
public static Status convertStatus(Context context, Status status) {
if (status != null) {
status.span_content = SpannableHelper.convert(context, status, status.content);
diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/AnnouncementAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/AnnouncementAdapter.java
new file mode 100644
index 00000000..0153460c
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/ui/drawer/AnnouncementAdapter.java
@@ -0,0 +1,221 @@
+package app.fedilab.android.ui.drawer;
+/* Copyright 2022 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+
+import static android.content.Context.INPUT_METHOD_SERVICE;
+import static app.fedilab.android.BaseMainActivity.emojis;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelStoreOwner;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.vanniktech.emoji.EmojiManager;
+import com.vanniktech.emoji.EmojiPopup;
+import com.vanniktech.emoji.one.EmojiOneProvider;
+
+import java.util.List;
+
+import app.fedilab.android.R;
+import app.fedilab.android.activities.MainActivity;
+import app.fedilab.android.client.entities.api.Announcement;
+import app.fedilab.android.client.entities.api.Reaction;
+import app.fedilab.android.databinding.DrawerAnnouncementBinding;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM;
+
+
+public class AnnouncementAdapter extends RecyclerView.Adapter {
+
+ private final List announcements;
+ private Context context;
+ private AnnouncementsVM announcementsVM;
+ private AlertDialog alertDialogEmoji;
+
+ public AnnouncementAdapter(List announcements) {
+ this.announcements = announcements;
+ }
+
+ public int getCount() {
+ return announcements.size();
+ }
+
+ public Announcement getItem(int position) {
+ return announcements.get(position);
+ }
+
+ @NonNull
+ @Override
+ public AnnouncementHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ context = parent.getContext();
+ DrawerAnnouncementBinding itemBinding = DrawerAnnouncementBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
+ return new AnnouncementHolder(itemBinding);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull AnnouncementHolder holder, int position) {
+ Announcement announcement = announcements.get(position);
+ if (announcement.reactions != null && announcement.reactions.size() > 0) {
+ ReactionAdapter reactionAdapter = new ReactionAdapter(announcement.id, announcement.reactions);
+ holder.binding.reactionsView.setAdapter(reactionAdapter);
+ LinearLayoutManager layoutManager
+ = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
+ holder.binding.reactionsView.setLayoutManager(layoutManager);
+ } else {
+ holder.binding.reactionsView.setAdapter(null);
+ }
+ holder.binding.content.setText(announcement.span_content, TextView.BufferType.SPANNABLE);
+ if (announcement.starts_at != null) {
+ String dateIni;
+ String dateEnd;
+ if (announcement.all_day) {
+ dateIni = Helper.shortDateToString(announcement.starts_at);
+ dateEnd = Helper.shortDateToString(announcement.ends_at);
+ } else {
+ dateIni = Helper.longDateToString(announcement.starts_at);
+ dateEnd = Helper.longDateToString(announcement.ends_at);
+ }
+ String text = context.getString(R.string.action_announcement_from_to, dateIni, dateEnd);
+ holder.binding.dates.setText(text);
+ holder.binding.dates.setVisibility(View.VISIBLE);
+ } else {
+ holder.binding.dates.setVisibility(View.GONE);
+ }
+ holder.binding.statusEmoji.setOnClickListener(v -> {
+ EmojiManager.install(new EmojiOneProvider());
+ final EmojiPopup emojiPopup = EmojiPopup.Builder.fromRootView(holder.binding.statusEmoji).setOnEmojiPopupDismissListener(() -> {
+ InputMethodManager imm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(holder.binding.statusEmoji.getWindowToken(), 0);
+ }).setOnEmojiClickListener((emoji, imageView) -> {
+ String emojiStr = imageView.getUnicode();
+ boolean alreadyAdded = false;
+ for (Reaction reaction : announcement.reactions) {
+ if (reaction.name.compareTo(emojiStr) == 0) {
+ alreadyAdded = true;
+ reaction.count = (reaction.count - 1);
+ if (reaction.count == 0) {
+ announcement.reactions.remove(reaction);
+ }
+ notifyItemChanged(position);
+ break;
+ }
+ }
+ if (!alreadyAdded) {
+ Reaction reaction = new Reaction();
+ reaction.me = true;
+ reaction.count = 1;
+ reaction.name = emojiStr;
+ announcement.reactions.add(0, reaction);
+ notifyItemChanged(position);
+ }
+ announcementsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AnnouncementsVM.class);
+ if (alreadyAdded) {
+ announcementsVM.removeReaction(MainActivity.currentInstance, MainActivity.currentToken, announcement.id, emojiStr);
+ } else {
+ announcementsVM.addReaction(MainActivity.currentInstance, MainActivity.currentToken, announcement.id, emojiStr);
+ }
+ })
+ .build(holder.binding.fakeEdittext);
+ emojiPopup.toggle();
+ });
+ holder.binding.statusAddCustomEmoji.setOnClickListener(v -> {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context, Helper.dialogStyle());
+ int paddingPixel = 15;
+ float density = context.getResources().getDisplayMetrics().density;
+ int paddingDp = (int) (paddingPixel * density);
+ builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
+ builder.setTitle(R.string.insert_emoji);
+ if (emojis != null && emojis.size() > 0) {
+ GridView gridView = new GridView(context);
+ gridView.setAdapter(new EmojiAdapter(emojis));
+ gridView.setNumColumns(5);
+ gridView.setOnItemClickListener((parent, view, index, id) -> {
+ String emojiStr = emojis.get(index).shortcode;
+ String url = emojis.get(index).url;
+ String static_url = emojis.get(index).static_url;
+ boolean alreadyAdded = false;
+ for (Reaction reaction : announcement.reactions) {
+ if (reaction.name.compareTo(emojiStr) == 0) {
+ alreadyAdded = true;
+ reaction.count = (reaction.count - 1);
+ if (reaction.count == 0) {
+ announcement.reactions.remove(reaction);
+ }
+ notifyItemChanged(position);
+ break;
+ }
+ }
+ if (!alreadyAdded) {
+ Reaction reaction = new Reaction();
+ reaction.me = true;
+ reaction.count = 1;
+ reaction.name = emojiStr;
+ reaction.url = url;
+ reaction.static_url = static_url;
+ announcement.reactions.add(0, reaction);
+ notifyItemChanged(position);
+ }
+ announcementsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AnnouncementsVM.class);
+ if (alreadyAdded) {
+ announcementsVM.removeReaction(MainActivity.currentInstance, MainActivity.currentToken, announcement.id, emojiStr);
+ } else {
+ announcementsVM.addReaction(MainActivity.currentInstance, MainActivity.currentToken, announcement.id, emojiStr);
+ }
+ alertDialogEmoji.dismiss();
+ });
+ gridView.setPadding(paddingDp, paddingDp, paddingDp, paddingDp);
+ builder.setView(gridView);
+ } else {
+ TextView textView = new TextView(context);
+ textView.setText(context.getString(R.string.no_emoji));
+ textView.setPadding(paddingDp, paddingDp, paddingDp, paddingDp);
+ builder.setView(textView);
+ }
+ alertDialogEmoji = builder.show();
+ });
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return announcements.size();
+ }
+
+
+ static class AnnouncementHolder extends RecyclerView.ViewHolder {
+ DrawerAnnouncementBinding binding;
+
+ AnnouncementHolder(DrawerAnnouncementBinding itemView) {
+ super(itemView.getRoot());
+ binding = itemView;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java
index 34390d98..c1b93872 100644
--- a/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java
+++ b/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java
@@ -15,6 +15,7 @@ package app.fedilab.android.ui.drawer;
* see . */
+import static app.fedilab.android.BaseMainActivity.emojis;
import static app.fedilab.android.BaseMainActivity.instanceInfo;
import static app.fedilab.android.activities.ComposeActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
@@ -124,7 +125,6 @@ public class ComposeAdapter extends RecyclerView.Adapter emojis;
private int statusCount;
private Context context;
private AlertDialog alertDialogEmoji;
@@ -1226,12 +1226,7 @@ public class ComposeAdapter extends RecyclerView.Adapter. */
+
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelStoreOwner;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+import app.fedilab.android.R;
+import app.fedilab.android.activities.MainActivity;
+import app.fedilab.android.client.entities.api.Reaction;
+import app.fedilab.android.databinding.DrawerReactionBinding;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM;
+
+
+/**
+ * Created by Thomas on 10/03/2020.
+ * Adapter for reactions on messages
+ */
+public class ReactionAdapter extends RecyclerView.Adapter {
+
+ private final List reactions;
+ private final String announcementId;
+ private Context context;
+
+ ReactionAdapter(String announcementId, List reactions) {
+ this.reactions = reactions;
+ this.announcementId = announcementId;
+ }
+
+ @NonNull
+ @Override
+ public ReactionHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
+ context = parent.getContext();
+ DrawerReactionBinding itemBinding = DrawerReactionBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
+ return new ReactionHolder(itemBinding);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ReactionHolder holder, int position) {
+ final Reaction reaction = reactions.get(position);
+
+ holder.binding.reactionCount.setText(String.valueOf(reaction.count));
+ if (reaction.me) {
+ holder.binding.reactionContainer.setBackgroundResource(R.drawable.reaction_voted);
+ } else {
+ holder.binding.reactionContainer.setBackgroundResource(R.drawable.reaction_border);
+ }
+ if (reaction.url != null) {
+ holder.binding.reactionName.setVisibility(View.GONE);
+ holder.binding.reactionEmoji.setVisibility(View.VISIBLE);
+ holder.binding.reactionEmoji.setContentDescription(reaction.name);
+ Helper.loadImage(holder.binding.reactionEmoji, reaction.url);
+ } else {
+ holder.binding.reactionName.setText(reaction.name);
+ holder.binding.reactionName.setVisibility(View.VISIBLE);
+ holder.binding.reactionEmoji.setVisibility(View.GONE);
+ }
+ AnnouncementsVM announcementsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AnnouncementsVM.class);
+ holder.binding.reactionContainer.setOnClickListener(v -> {
+ if (reaction.me) {
+ announcementsVM.removeReaction(MainActivity.currentInstance, MainActivity.currentToken, announcementId, reaction.name);
+ reaction.me = false;
+ } else {
+ announcementsVM.addReaction(MainActivity.currentInstance, MainActivity.currentToken, announcementId, reaction.name);
+ reaction.me = true;
+ }
+ notifyItemChanged(position);
+ });
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return reactions.size();
+ }
+
+
+ static class ReactionHolder extends RecyclerView.ViewHolder {
+ DrawerReactionBinding binding;
+
+ ReactionHolder(DrawerReactionBinding itemView) {
+ super(itemView.getRoot());
+ binding = itemView;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAnnouncement.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAnnouncement.java
new file mode 100644
index 00000000..695a9d4d
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAnnouncement.java
@@ -0,0 +1,121 @@
+package app.fedilab.android.ui.fragment.timeline;
+/* Copyright 2022 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import java.util.List;
+
+import app.fedilab.android.BaseMainActivity;
+import app.fedilab.android.R;
+import app.fedilab.android.client.entities.api.Announcement;
+import app.fedilab.android.databinding.FragmentPaginationBinding;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.helper.ThemeHelper;
+import app.fedilab.android.ui.drawer.AnnouncementAdapter;
+import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM;
+
+
+public class FragmentMastodonAnnouncement extends Fragment {
+
+
+ private FragmentPaginationBinding binding;
+ private AnnouncementsVM announcementsVM;
+ private AnnouncementAdapter announcementAdapter;
+
+
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ ViewGroup container, Bundle savedInstanceState) {
+
+ binding = FragmentPaginationBinding.inflate(inflater, container, false);
+ View root = binding.getRoot();
+ binding.getRoot().setBackgroundColor(ThemeHelper.getBackgroundColor(requireActivity()));
+ int c1 = getResources().getColor(R.color.cyanea_accent_reference);
+ binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.cyanea_primary_reference));
+ binding.swipeContainer.setColorSchemeColors(
+ c1, c1, c1
+ );
+ announcementsVM = new ViewModelProvider(FragmentMastodonAnnouncement.this).get(AnnouncementsVM.class);
+ binding.loader.setVisibility(View.VISIBLE);
+ binding.recyclerView.setVisibility(View.GONE);
+ announcementsVM.getAnnouncements(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null)
+ .observe(getViewLifecycleOwner(), this::initializeAnnouncementView);
+ return root;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ NotificationManager notificationManager = (NotificationManager) requireActivity().getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.cancel(Helper.NOTIFICATION_USER_NOTIF);
+ }
+
+ /**
+ * Intialize the view for announcements
+ *
+ * @param announcements List of {@link Announcement}
+ */
+ private void initializeAnnouncementView(List announcements) {
+
+ binding.loader.setVisibility(View.GONE);
+ binding.swipeContainer.setRefreshing(false);
+ if (announcements == null || announcements.size() == 0) {
+ binding.noActionText.setText(R.string.no_announcements);
+ binding.noAction.setVisibility(View.VISIBLE);
+ binding.recyclerView.setVisibility(View.GONE);
+ return;
+ } else {
+ binding.noAction.setVisibility(View.GONE);
+ binding.recyclerView.setVisibility(View.VISIBLE);
+ }
+
+
+ announcementAdapter = new AnnouncementAdapter(announcements);
+ LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity());
+ binding.recyclerView.setLayoutManager(mLayoutManager);
+ binding.recyclerView.setAdapter(announcementAdapter);
+
+
+ binding.swipeContainer.setOnRefreshListener(() -> {
+ binding.swipeContainer.setRefreshing(true);
+ announcementsVM.getAnnouncements(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null)
+ .observe(getViewLifecycleOwner(), this::initializeAnnouncementView);
+ });
+
+ }
+
+ public void scrollToTop() {
+ binding.recyclerView.scrollToPosition(0);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ binding.recyclerView.setAdapter(null);
+ announcementAdapter = null;
+ binding = null;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java
index da36a04b..4421f04d 100644
--- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java
+++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java
@@ -58,6 +58,7 @@ import app.fedilab.android.helper.SpannableHelper;
import app.fedilab.android.helper.ThemeHelper;
import app.fedilab.android.ui.drawer.StatusAdapter;
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
+import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM;
import app.fedilab.android.viewmodel.mastodon.SearchVM;
import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
@@ -70,6 +71,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
private FragmentPaginationBinding binding;
private TimelinesVM timelinesVM;
private AccountsVM accountsVM;
+ private AnnouncementsVM announcementsVM;
private boolean flagLoading;
private List statuses;
private String search, searchCache;
@@ -237,6 +239,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
timelinesVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, TimelinesVM.class);
accountsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AccountsVM.class);
+ announcementsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AnnouncementsVM.class);
binding.loader.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AnnouncementsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AnnouncementsVM.java
index c9ce5251..5b916e26 100644
--- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AnnouncementsVM.java
+++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AnnouncementsVM.java
@@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
import app.fedilab.android.client.endpoints.MastodonAnnouncementsService;
import app.fedilab.android.client.entities.api.Announcement;
import app.fedilab.android.helper.Helper;
+import app.fedilab.android.helper.SpannableHelper;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Response;
@@ -67,7 +68,7 @@ public class AnnouncementsVM extends AndroidViewModel {
* @param withDismissed If true, response will include announcements dismissed by the user. Defaults to false.
* @return {@link LiveData} containing a {@link List} of {@link Announcement}s
*/
- public LiveData> getAnnouncements(@NonNull String instance, String token, boolean withDismissed) {
+ public LiveData> getAnnouncements(@NonNull String instance, String token, Boolean withDismissed) {
MastodonAnnouncementsService mastodonAnnouncementsService = init(instance);
announcementListMutableLiveData = new MutableLiveData<>();
new Thread(() -> {
@@ -78,6 +79,7 @@ public class AnnouncementsVM extends AndroidViewModel {
Response> getAnnouncementsResponse = getAnnouncementsCall.execute();
if (getAnnouncementsResponse.isSuccessful()) {
announcementList = getAnnouncementsResponse.body();
+ SpannableHelper.convertAnnouncement(getApplication(), announcementList);
}
} catch (Exception e) {
e.printStackTrace();
diff --git a/app/src/main/res/drawable/ic_baseline_add_reaction_24.xml b/app/src/main/res/drawable/ic_baseline_add_reaction_24.xml
new file mode 100644
index 00000000..5872363d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_add_reaction_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_emoji_emotions_24.xml b/app/src/main/res/drawable/ic_baseline_emoji_emotions_24.xml
new file mode 100644
index 00000000..9300ca33
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_emoji_emotions_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_message_24.xml b/app/src/main/res/drawable/ic_baseline_message_24.xml
index c9a3e3da..762268ce 100644
--- a/app/src/main/res/drawable/ic_baseline_message_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_message_24.xml
@@ -2,7 +2,7 @@
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
- android:tint="?attr/colorControlNormal"
+ android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
+
+
+
+
diff --git a/app/src/main/res/drawable/reaction_voted.xml b/app/src/main/res/drawable/reaction_voted.xml
new file mode 100644
index 00000000..267b5815
--- /dev/null
+++ b/app/src/main/res/drawable/reaction_voted.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_announcement.xml b/app/src/main/res/layout/activity_announcement.xml
new file mode 100644
index 00000000..92dbf9d7
--- /dev/null
+++ b/app/src/main/res/layout/activity_announcement.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_announcement.xml b/app/src/main/res/layout/drawer_announcement.xml
new file mode 100644
index 00000000..7f82092b
--- /dev/null
+++ b/app/src/main/res/layout/drawer_announcement.xml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_reaction.xml b/app/src/main/res/layout/drawer_reaction.xml
new file mode 100644
index 00000000..84ada755
--- /dev/null
+++ b/app/src/main/res/layout/drawer_reaction.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
index 87296e93..b7e788b4 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -28,6 +28,13 @@
android:id="@+id/nav_list"
android:icon="@drawable/ic_baseline_view_list_24"
android:title="@string/action_lists" />
+
+
+
- Are you want to exit without saving image ?